collect_resitest8300 プログラム仕様

Hall測定装置のCSVファイルから、多層モデル解析に使いやすい primary データをExcelに追記するプログラム。

collect_resitest8300.py 技術ドキュメント

このプログラムは、Resitest 8300型などのHall測定結果CSVファイルから、 比抵抗、Hall係数、キャリア濃度、移動度などのデータを抽出し、 整形された「primary」データとしてExcelシートに追記します。 また、処理したファイルに関する情報も別のシートに記録します。

想定している入力:
  • 8310型などの Hall 測定結果CSV

  • cp932 / Shift_JIS 系の日本語CSV

  • 1ファイル中に複数温度・複数測定No.のブロックが入っている形式

基本方針:
  • 第一引数: 出力先 Excel ファイル

  • 第二引数以降: CSVファイルまたはワイルドカード

  • Excel が存在しなければ新規作成

  • Excel が存在すれば単純追記

  • 重複チェック・置換はしない

  • Hall係数は carrier type が N/P と判定できる場合のみ符号付きに変換

  • シートHall係数の再計算値は出力しない

  • 装置CSV中の平均値・最小・最大から半幅誤差と相対誤差を出力

使い方:

python collect_hall_primary.py Hall_summary.xlsx "*.CSV"

例:

python collect_hall_primary.py Hall_summary.xlsx "D:data*.CSV" python collect_hall_primary.py Hall_summary.xlsx ".CSV" "subdir*.csv" python collect_hall_primary.py Hall_summary.xlsx "**.CSV" --recursive python collect_hall_primary.py Hall_summary.xlsx "*.CSV" --dry-run

必要ライブラリ:

pip install openpyxl

electrical.collect_resitest8300.add_param_stats(d: Dict[str, Any], base: str, unit_suffix: str, avg: float | None, vmin: float | None, vmax: float | None, *, signed: bool = False, sign: int | None = None) None[ソース]

平均・最小・最大から半幅誤差と相対誤差を計算し辞書に追加する。

詳細説明:

測定値の平均値 (avg)、最小値 (vmin)、最大値 (vmax) を基に、 半幅誤差 (err) と相対誤差 (err_percent) を計算し、 これらを指定されたベース名と単位サフィックスを用いて辞書 d に追加します。

Hall係数 (signed=True) の場合、装置出力が絶対値で出ていると仮定し、 sign 引数 (N型:-1, P型:+1) に応じて符号を付与します。 N型の場合、min/maxは数直線上で min=-max_abs, max=-min_abs として保存されます。 符号変換が必要な場合、signNone でない場合に適用されます。

パラメータ:
  • d -- 結果を追加する辞書。

  • base -- パラメータのベース名 (例: "hall_coeff")。

  • unit_suffix -- 単位のサフィックス (例: "cm3_C")。

  • avg -- パラメータの平均値。

  • vmin -- パラメータの最小値。

  • vmax -- パラメータの最大値。

  • signed -- Hall係数などのように符号付きで扱うべきかどうかのフラグ。

  • sign -- signed が True の場合に適用する符号 (1 または -1)。

戻り値:

None

electrical.collect_resitest8300.append_records(ws: Any, headers: List[str], records: List[Dict[str, Any]]) None[ソース]

指定されたレコードをExcelシートに追記する。

詳細説明:

各レコード (辞書) を、指定された headers の順序に従って Excelシート ws の新しい行として追加します。 safe_excel_value 関数を使用して、Excelに安全な値のみが書き込まれるようにします。

パラメータ:
  • ws -- データを追記するopenpyxlのWorksheetオブジェクト。

  • headers -- シートのヘッダー列名のリスト。この順序でレコードが書き込まれる。

  • records -- 追記するレコードのリスト。各レコードは辞書形式。

戻り値:

None

electrical.collect_resitest8300.append_to_excel(excel_path: Path, primary_records: List[Dict[str, Any]], file_records: List[Dict[str, Any]], *, primary_sheet: str = 'primary', files_sheet: str = 'files', write_files_sheet: bool = True) None[ソース]

Excelファイルに測定結果とファイル履歴を追記する。

詳細説明:

指定されたExcelファイル excel_path に、 primary_recordsprimary_sheet に、 file_recordsfiles_sheet に追記します。 Excelファイルが存在しない場合は新規作成され、 存在する場合は既存のデータに追記されます。 各シートは ensure_sheet_with_headers でヘッダーが適切に管理され、 style_sheet で書式が設定されます。

パラメータ:
  • excel_path -- 出力先となるExcelファイルのパス。

  • primary_records -- primaryシートに追記する測定レコードのリスト。

  • file_records -- filesシートに追記するファイル履歴レコードのリスト。

  • primary_sheet -- primaryデータを書き込むシート名。デフォルトは "primary"。

  • files_sheet -- ファイル履歴を書き込むシート名。デフォルトは "files"。

  • write_files_sheet -- filesシートを作成・追記するかどうかのフラグ。

戻り値:

None

electrical.collect_resitest8300.build_records_from_csv(path: Path, encoding: str = 'cp932') Tuple[List[Dict[str, Any]], Dict[str, Any]][ソース]

1つのCSVファイルからExcel出力用レコードを作成する。

詳細説明:

指定されたCSVファイル全体を読み込み、ファイル冒頭のグローバル情報と、 各測定ブロック(比抵抗、Hall)の情報を抽出して、 Excelの「primary」シートと「files」シートに書き込むための レコードのリストを生成します。 同一の measurement_no を持つ比抵抗データとHallデータは結合されます。 インポート日時、シートコンダクタンス、品質フラグなども計算・追加されます。 ファイル全体で発生した警告は global_info に集約されます。

パラメータ:
  • path -- 解析対象のCSVファイルのパス。

  • encoding -- CSVファイルの文字エンコーディング。デフォルトは "cp932"。

戻り値:

(primaryデータのレコードリスト, ファイル全体のグローバル情報を含む辞書) のタプル。

electrical.collect_resitest8300.clean_cell(s: Any) str[ソース]

CSVセルのNUL文字と前後空白を除去する。

詳細説明:

CSVファイルによっては、内部にNUL文字 (x00) が含まれていることがあり、 これを削除することで文字列処理の問題を回避します。 また、前後の空白も strip() メソッドで除去します。 入力が None の場合は空文字列を返します。

パラメータ:

s -- CSVセルから読み取られた値。

戻り値:

クリーンアップされた文字列。

electrical.collect_resitest8300.detect_carrier_sign(carrier_type_raw: str) Tuple[int | None, str][ソース]

キャリアタイプからHall係数の符号を決定する。

詳細説明:

入力されたキャリアタイプ文字列を解析し、Hall係数の符号を決定します。 - "N" を含む場合は N型と判断し、符号 -1 を返します。 - "P" を含む場合は P型と判断し、符号 +1 を返します。 - 上記以外の場合は符号を決定できないため None を返します。 また、キャリアタイプの状態を示す文字列 ("N", "P", "unknown") も返します。

パラメータ:

carrier_type_raw -- CSVから読み取られたキャリアタイプ文字列。

戻り値:

Hall係数の符号 (1, -1, または None) と、キャリアタイプの状態を示す文字列のタプル。

electrical.collect_resitest8300.ensure_sheet_with_headers(wb: Any, sheet_name: str, columns: List[str]) Tuple[Any, List[str]][ソース]

Excelシートを用意し、既存ヘッダに不足列を追加する。

詳細説明:

指定されたワークブック wb 内に sheet_name のシートが存在しない場合は新規作成します。 シートが存在する場合、または新規作成された場合、最初の行をヘッダー行として扱います。 指定された columns のリストに存在するが、既存ヘッダーにはない列がある場合、 その列をヘッダーの最後に追加します。 これにより、新しいデータに新しい列が含まれていても、Excelシートのヘッダーが適切に更新されます。

パラメータ:
  • wb -- openpyxlのWorkbookオブジェクト。

  • sheet_name -- 操作対象のシート名。

  • columns -- シートに含めるべき列名のリスト(出力カラム順の定義)。

戻り値:

(操作対象のWorksheetオブジェクト, 更新後のヘッダー列名のリスト) のタプル。

electrical.collect_resitest8300.estimate_hall_measured_current(block_rows: List[List[str]]) Dict[str, float | None][ソース]

Hall測定結果ブロック内の端子間テーブルから実測電流の代表値を推定する。

詳細説明:

Hall測定結果ブロック内の「端子間ホール起電圧」のテーブルより前の行で、 「電流 [A], 電圧 [V], ... 電流 [A], 電圧 [V], ...」のような形式で 記録されている実測電流値を抽出します。 抽出された電流値の絶対値の平均、最小値、最大値を計算して返します。 電流値として妥当な範囲 (絶対値が 1.0 A 未満) のみを採用し、 誤って温度や磁場などを拾わないようにします。

パラメータ:

block_rows -- Hall測定結果ブロック内の行データ。

戻り値:

推定された実測電流の平均値、最小値、最大値を含む辞書。

electrical.collect_resitest8300.expand_input_patterns(patterns: Sequence[str], recursive: bool = False) List[Path][ソース]

WindowsでもPython側でワイルドカード展開する。

詳細説明:

コマンドライン引数で渡されたファイルパスのパターン(ワイルドカードを含む) を展開し、実際に存在するファイルパスのリストを返します。 Windows環境ではシェルがワイルドカードを展開しないため、 glob.glob を使用してPython側で展開を行います。 recursive フラグが True の場合、** を使用した再帰的な検索を有効にします。 重複するファイルは set を使用して排除されます。

パラメータ:
  • patterns -- ワイルドカードを含む可能性のあるファイルパスのリスト。

  • recursive -- ** を使用した再帰検索を有効にするかどうかのフラグ。

戻り値:

展開された、存在するファイルパスの Path オブジェクトのリスト。

electrical.collect_resitest8300.first_nonempty(row: Sequence[str]) str[ソース]

行の最初の空でないセルを返す。

詳細説明:

指定された行 (文字列のシーケンス) を先頭から順に走査し、 最初に見つかった空でない文字列を返します。 行が空であるか、すべてのセルが空文字列である場合は空文字列を返します。

パラメータ:

row -- 文字列のシーケンス(CSVの1行に相当)。

戻り値:

行の最初の空でないセル、または空文字列。

electrical.collect_resitest8300.import_openpyxl()[ソース]

openpyxlライブラリをインポートする。

詳細説明:

openpyxlとその主要なクラス、関数をインポートします。 openpyxlがインストールされていない場合はエラーメッセージを表示し、 SystemExit を発生させてプログラムを終了します。

戻り値:

openpyxlモジュールとその主要なクラス、関数のタプル。

例外:

SystemExit -- openpyxlがインストールされていない場合。

electrical.collect_resitest8300.main(argv: Sequence[str] | None = None) int[ソース]

プログラムのメインエントリポイント。

詳細説明:

コマンドライン引数を解析し、指定されたCSVファイルを読み込み、 測定データを抽出してExcelファイルに書き込む一連の処理を実行します。 入力ファイルが見つからない場合や、解析できるデータがない場合は エラーメッセージを出力し、適切な終了コードを返します。 --dry-run オプションが指定された場合は、Excelへの書き込みは行わず、 解析結果の概要を表示します。

パラメータ:

argv -- コマンドライン引数のリスト (テスト目的などでNone以外の値を渡す)。デフォルトはsys.argv[1:]。

戻り値:

成功時は 0、エラー時は 1 を返す。

electrical.collect_resitest8300.make_file_record(path: Path, global_info: Dict[str, Any], num_measurements: int) Dict[str, Any][ソース]

1つのCSVファイルに関する履歴レコードを作成する。

詳細説明:

指定されたファイルパス path と、そのファイルから抽出された グローバル情報 global_info を基に、ファイル履歴シート (files_sheet) に書き込むためのレコードを作成します。 ファイルサイズ、最終更新時刻、解析時に検出された警告なども含まれます。

パラメータ:
  • path -- 処理対象のCSVファイルのパス。

  • global_info -- CSVファイルから抽出されたグローバル情報を含む辞書。

  • num_measurements -- そのファイルから抽出された測定レコードの数。

戻り値:

ファイル履歴レコードを含む辞書。

electrical.collect_resitest8300.make_quality_flag(record: Dict[str, Any]) str[ソース]

Hallデータの簡易品質フラグを作成する。

詳細説明:

これは最終判断ではなく、Excelで目視確認するための目印です。 以下の基準でフラグを決定します。 - ホールノイズまたは方向依存性が50%以上: "bad" - parser_warning に "missing" が含まれる場合: "warning" - parser_warning に "unknown" が含まれる場合: "warning" - ホールノイズまたは方向依存性が10%以上: "warning" - ホールノイズと方向依存性の両方が値がない場合: "warning" - それ以外の場合: "good"

パラメータ:

record -- 1つの測定レコードを含む辞書。

戻り値:

簡易品質フラグ ("good", "warning", "bad")。

electrical.collect_resitest8300.norm(s: Any) str[ソース]

全角英数字や半角カナを比較しやすい形に正規化する。

詳細説明:

unicodedata.normalize("NFKC", ...) を使用して、 互換等価性を持つ文字を正規化し、前後の空白を除去します。 これにより、例えば「ABC」や「アイウ」のような文字が 「ABC」や「アイウ」に変換され、比較やパースが容易になります。

パラメータ:

s -- 正規化する任意の入力値。

戻り値:

正規化された文字列。

electrical.collect_resitest8300.normalized_param_label(label: str) str[ソース]

パラメータラベルを正規化する。

詳細説明:

入力されたパラメータラベルを norm 関数で正規化し、さらに空白を除去します。 これにより、CSV内の様々な表記揺れに対応し、ラベルの一貫した比較を可能にします。

パラメータ:

label -- 正規化するパラメータラベル文字列。

戻り値:

正規化・空白除去されたパラメータラベル文字列。

electrical.collect_resitest8300.parse_args(argv: Sequence[str] | None = None) Namespace[ソース]

コマンドライン引数を解析する。

詳細説明:

プログラムの実行時に渡されるコマンドライン引数を解析し、 設定値を含む argparse.Namespace オブジェクトを返します。 出力Excelファイル、入力CSVファイル、エンコーディング、再帰検索、 ドライランモード、シート名、verboseモードなどのオプションを定義しています。

パラメータ:

argv -- コマンドライン引数のリスト (テスト目的などでNone以外の値を渡す)。デフォルトはsys.argv[1:]。

戻り値:

解析された引数を含む argparse.Namespace オブジェクト。

electrical.collect_resitest8300.parse_common_block_items(block_rows: List[List[str]]) Dict[str, Any][ソース]

比抵抗・Hallの各ブロック冒頭に共通する情報を読む。

詳細説明:

比抵抗測定結果ブロックやホール測定結果ブロックの冒頭に共通して現れる、 測定No、測定温度、測定開始/終了時刻、設定電流などの情報を抽出します。 これらの情報は、各測定レコードの基本情報として使用されます。

パラメータ:

block_rows -- 特定の測定ブロック内の行データ。

戻り値:

抽出された共通情報を含む辞書。

electrical.collect_resitest8300.parse_float(s: Any) float | None[ソース]

セル文字列から最初の数値を取り出す。

詳細説明:

装置CSVでは * 1.23E+4, # -3.0E-2 のような警告記号付き数値が 出力されることがあります。この関数は、単純な float() 変換ではなく、 正規表現 FLOAT_RE を用いて文字列中の最初の数値部分を抽出し、 それを浮動小数点数として解析します。 また、カンマ(,)や全角ハイフン()も除去してパースを試みます。

パラメータ:

s -- 数値を含む可能性のある文字列または任意のオブジェクト。

戻り値:

抽出された浮動小数点数、または数値が見つからない場合は None。

electrical.collect_resitest8300.parse_global_info(header_rows: List[List[str]]) Dict[str, Any][ソース]

ファイル冒頭の共通情報を読む。

詳細説明:

CSVファイルのヘッダー部分から、試料名、測定年月日、測定者、コメント、 試料厚みなどのグローバルな情報を抽出します。 試料厚みについては、値と単位をパースし、センチメートルへの換算も行います。 抽出された情報は辞書として返されます。

パラメータ:

header_rows -- ファイル冒頭のヘッダー行のリスト。

戻り値:

抽出されたグローバル情報を含む辞書。

electrical.collect_resitest8300.parse_hall_result(block_rows: List[List[str]]) Dict[str, Any][ソース]

<<<AC磁場ホール測定結果>>> ブロックを解析する。

詳細説明:

Hall測定結果ブロックから、磁場、ホール起電圧、位相、ノイズ、ドリフト率、 方向依存性、キャリアタイプ、Hall係数、キャリア濃度、移動度などの 測定結果を抽出します。 共通情報 (parse_common_block_items から得られるもの) も取り込み、 適切なキー名で辞書に格納します。 キャリアタイプに基づいてHall係数の符号を決定し、必要に応じて符号付きに変換します。 パラメータの平均値、最小値、最大値からは半幅誤差と相対誤差も計算されます。 解析中に検出された警告は parser_warning に格納されます。

パラメータ:

block_rows -- Hall測定結果ブロック内の行データ。

戻り値:

抽出されたHall測定結果を含む辞書。

electrical.collect_resitest8300.parse_rho_result(block_rows: List[List[str]]) Dict[str, Any][ソース]

<<<比抵抗測定結果>>> ブロックを解析する。

詳細説明:

比抵抗測定結果ブロックから、F値、比抵抗値、シート抵抗値、ノイズ などの測定結果を抽出します。 共通情報 (parse_common_block_items から得られるもの) も取り込み、 適切なキー名で辞書に格納します。

パラメータ:

block_rows -- 比抵抗測定結果ブロック内の行データ。

戻り値:

抽出された比抵抗測定結果を含む辞書。

electrical.collect_resitest8300.parse_unit(s: Any) str[ソース]

[ mm ] のような単位表記を mm に整形する。

詳細説明:

入力された単位文字列から、角括弧 [] や全角の [] を除去し、 さらにマイクロ記号 μµum に統一して、 単位を比較しやすい標準的な形式に整形します。

パラメータ:

s -- 単位を表す文字列。

戻り値:

整形された単位文字列。

electrical.collect_resitest8300.print_dry_run_summary(records: List[Dict[str, Any]]) None[ソース]

ドライラン実行時の解析結果の概要を表示する。

詳細説明:

--dry-run オプションが指定された際に、Excelに書き込む代わりに 解析された測定レコードの主要な情報を標準出力に表形式で表示します。 これにより、実際の書き込み前にデータの内容を確認できます。

パラメータ:

records -- 解析された測定レコードのリスト。

戻り値:

None

electrical.collect_resitest8300.read_csv_rows(path: Path, encoding: str = 'cp932') List[List[str]][ソース]

CSVを読み込み、セル配列として返す。

詳細説明:

指定されたパスのCSVファイルを、指定されたエンコーディングで読み込みます。 読み込み中に発生するデコードエラーは replace モードで処理され、 NUL文字 (x00) は除去されます。 各セルは clean_cell 関数で整形され、文字列のリストのリストとして返されます。

パラメータ:
  • path -- 読み込むCSVファイルのパス。

  • encoding -- CSVファイルの文字エンコーディング。デフォルトは "cp932"。

戻り値:

CSVの内容を表す文字列のリストのリスト。

electrical.collect_resitest8300.row_label(row: Sequence[str]) str[ソース]

行のラベル(最初のセル)を正規化して返す。

詳細説明:

CSVの行の最初のセルをラベルとみなし、norm 関数で正規化します。 これにより、ラベルの比較やキーとしての使用が容易になります。 行が空の場合は空文字列を返します。

パラメータ:

row -- 文字列のシーケンス(CSVの1行に相当)。

戻り値:

正規化された行ラベル、または空文字列。

electrical.collect_resitest8300.safe_excel_value(v: Any) Any[ソース]

openpyxlに渡せる値に整える。

詳細説明:

Excelのセルに書き込む値として不適切な値(NoneNaNInfinity)を None に変換します。 openpyxlライブラリは NaNInfinity を直接書き込むとエラーになるため、 これらの値を安全に処理するためにこの関数を使用します。

パラメータ:

v -- Excelセルに書き込む可能性のある値。

戻り値:

openpyxlに安全に渡せる値。不適切な場合は None。

electrical.collect_resitest8300.split_blocks(rows: List[List[str]]) Tuple[List[List[str]], List[Tuple[str, List[List[str]]]]][ソース]

CSVの行データを <<<...>>> ブロックに分割する。

詳細説明:

Hall測定装置のCSVファイルは、ファイル冒頭の共通情報と、 <<<比抵抗測定結果>>><<<AC磁場ホール測定結果>>> のような ブロックで構成されています。この関数は、これらのブロックマーカーを 識別し、CSVデータをヘッダー行とタイトル付きのブロックに分割します。 最初の <<<...>>> が現れるまでの行はヘッダー行として扱われます。

パラメータ:

rows -- CSVファイルから読み込まれたすべての行データ。

戻り値:

ヘッダー行のリストと、(ブロックタイトル, ブロック内の行データ) のタプルのリスト。

electrical.collect_resitest8300.style_sheet(ws: Any) None[ソース]

Excelシートのスタイルを設定する。

詳細説明:

シートのヘッダー行に背景色、太字フォント、中央揃えを適用し、 A2セルでのウィンドウ固定とオートフィルターを設定します。 また、列幅をヘッダーの内容や特定のキーに基づいて自動調整します。 数値を含む列には、データの種類に応じて適切な数値書式(指数表記、整数、小数点以下3桁) を適用します。

パラメータ:

ws -- スタイルを設定するopenpyxlのWorksheetオブジェクト。

戻り値:

None

electrical.collect_resitest8300.thickness_to_cm(value: float | None, unit: str) float | None[ソース]

厚さを cm に換算する。未知単位なら None。

詳細説明:

入力された厚さの値と単位から、その厚さをセンチメートル (cm) に換算します。 以下の単位に対応しています。 - cm: 1.0 - mm: 1.0e-1 - um (μm): 1.0e-4 - nm: 1.0e-7 - m: 100.0 - A, Å, ang, angstrom: 1.0e-8 対応していない単位が指定された場合、または value が None の場合は None を返します。

パラメータ:
  • value -- 厚さの数値。

  • unit -- 厚さの単位を表す文字列。

戻り値:

cm に換算された厚さ、または換算できない場合は None。