deconvolution.py 技術ドキュメント

プログラムの動作

deconvolution.py は、測定データに畳み込まれた応答関数(主にガウス関数)を逆畳み込みすることによって、元のスペクトル形状を復元するためのPythonプログラムです。主に光電子分光(PES)などのスペクトルデータ解析を想定しています。

主な機能:

  • 多様な逆畳み込みアルゴリズムのサポート:

    • Jacobi法: 繰り返し計算による逆畳み込み。収束性や安定性を制御するためのダンピング係数や平滑化機能を持つ。

    • Gauss-Seidel法: Jacobi法と同様の繰り返し計算だが、更新された値を即座に利用することで収束が速い可能性がある。

    • FFT (高速フーリエ変換) 法: 周波数領域での除算による効率的な逆畳み込み。

    • SciPyの deconvolve 関数: Pythonの科学計算ライブラリSciPyに実装されている逆畳み込み機能を利用。

  • 畳み込みシミュレーション: numpy.convolve を使用して、元のデータにフィルター関数を畳み込むことで、逆畳み込みの効果を確認できる。

  • ガウス関数フィルターの生成: 半値幅(Wa)と有効範囲(Grange)を指定してガウス応答関数を生成する。

  • データの前処理:

    • 平滑化: 移動平均または多項式フィット(Savitzky-Golayフィルターに類似)によるノイズ低減。

    • データ拡張: FFTやSciPyの deconvolve で発生しがちな端点効果を抑制するため、データの両端をゼロや線形補間で拡張する。

  • 結果の可視化: matplotlib を用いて、元のデータ、畳み込み後のデータ、逆畳み込み後のデータをリアルタイムまたは最終的にグラフ表示する。

  • CSV形式での入出力: 測定データの読み込みと結果の保存にCSV形式を使用する。

解決する課題:

測定データ(特に分光データ)は、測定装置の分解能や自然幅によって、本来のシャープなピークがブロードニング(広がり)を起こして観測されます。このプログラムは、ブロードニングを引き起こす応答関数(フィルター関数)が既知である場合に、観測データからその応答関数の影響を取り除き、より高分解能な元のスペクトル形状を推定することを目的としています。これにより、ピーク位置の精密な決定や、隠れた構造の検出が可能になります。

原理

このプログラムでは、いくつかの異なる逆畳み込みアルゴリズムが実装されています。基本的な畳み込みの概念から始め、各アルゴリズムの原理を説明します。

1. 畳み込みの基本

観測されるデータ \(I_{\text{conv}}(x)\) は、本来のデータ \(I_{\text{raw}}(x)\) と装置の応答関数(またはフィルター関数)\(H(x)\) の畳み込みとして表されます。

\[I_{\text{conv}}(x) = (I_{\text{raw}} * H)(x) = \int_{-\infty}^{\infty} I_{\text{raw}}(x') H(x - x') dx'\]

離散データの場合、これは以下のように近似されます。

\[I_{\text{conv},i} = \sum_j I_{\text{raw},j} H_{i-j}\]

逆畳み込みは、この \(I_{\text{conv},i}\)\(H_{i-j}\) から \(I_{\text{raw},j}\) を推定する問題です。

2. ガウス関数フィルター

応答関数 \(H(x)\) として、このプログラムではガウス関数が使用されます。半値幅 Wa のガウス関数 \(G(x, x_0, W_a)\) は以下のように定義されます。

まず、プログラムでは半値幅 \(W_a\) を用いて正規化定数 \(A\) とスケール因子 \(a\) を計算します。 \(A = \frac{1}{W_a} \sqrt{\frac{\ln 2}{\pi}}\) \(a = \frac{W_a}{\sqrt{\ln 2}}\)

これらを用いて、ガウス関数は次の形式で計算されます。 $\(G(x, x_0, W_a) = A \cdot \exp\left(-\left(\frac{x - x_0}{a}\right)^2\right)\)$

ここで、\(x_0\) はピーク中心、\(W_a\) は半値幅です。プログラム内では、フィルター関数の中心 \(x_0\) は0として扱われ、\(H_{ij}\)\((j-i) \cdot \text{xstep}\) におけるガウス関数として定義されます。

3. Jacobi法とGauss-Seidel法による繰り返し逆畳み込み

これらの方法は、上記の離散畳み込み方程式を \(I_{\text{raw}}\) について解くための繰り返しアルゴリズムです。プログラムでは、南茂夫 編著「科学計測のための波形データ処理」の繰り返し法をベースに、以下の更新式を用いています。

観測データ \(y_{\text{raw},i}\) と、現在の推定値 \(y_{\text{old},j}\) が与えられたとき、次の推定値 \(y_{\text{new},i}\) は以下のように計算されます。

まず、現在の推定値 \(y_{\text{old}}\) を用いて、畳み込み後の期待値 \(Hx_i\) を計算します。プログラムの Hij 関数は \(H_{j-i}\) に対応します。 $\(Hx_i = \sum_j H_{j-i} y_{\text{old},j}\)$

また、フィルター関数の総和 \(Sg_i\) を計算します。 $\(Sg_i = \sum_j H_{j-i}\)$

そして、中心要素 \(h = H_{0}\) を用いて、新しい推定値 \(y_{\text{new},i}\) を導出します。dump はダンピング係数です。

\[y_{\text{new},i} = y_{\text{old},i} + \text{dump} \cdot \frac{1}{H_{0}} \left( y_{\text{raw},i} - \frac{Hx_i}{Sg_i} \right)\]
  • Jacobi法 (deconvolute_jacobi): 新しい推定値 \(y_{\text{new},i}\) の計算に、常に一つ前の反復の推定値 \(y_{\text{old},j}\) を用います。つまり、ある反復内の全ての \(i\) について \(y_{\text{new},i}\) を計算し終えてから、その結果を次の反復の \(y_{\text{old},j}\) に更新します。

  • Gauss-Seidel法 (deconvolute_gauss_seidel): Jacobi法と異なり、新しい推定値 \(y_{\text{new},i}\) の計算において、既に同じ反復内で更新された \(y_j\) (\(j < i\)) を直ちに利用します。これにより、一般にJacobi法よりも収束が速いとされています。

    Gauss-Seidel法では、\(Hx_i\) の計算が以下のように変わります。 $\(Hx_i = \sum_{j < i} H_{j-i} y_{j} + \sum_{j \ge i} H_{j-i} y_{\text{old},j}\)\( ここで、\)y_{j}\( は現在の反復で既に計算された新しい値、\)y_{\text{old},j}$ は前の反復の値です。

これらの繰り返し法では、各反復後に平滑化処理(ノイズ抑制)やゼロ補正(負の値の除去)が適用されることがあります。

4. FFTによる逆畳み込み (deconvolute_fft)

畳み込み定理によれば、空間領域での畳み込みは、フーリエ変換された周波数領域での乗算に相当します。

\[\mathcal{F}\{I_{\text{raw}} * H\} = \mathcal{F}\{I_{\text{raw}}\} \cdot \mathcal{F}\{H\}\]
\[\hat{I}_{\text{conv}}(\nu) = \hat{I}_{\text{raw}}(\nu) \cdot \hat{H}(\nu)\]

したがって、逆畳み込みは周波数領域での除算によって行えます。

\[\hat{I}_{\text{raw}}(\nu) = \frac{\hat{I}_{\text{conv}}(\nu)}{\hat{H}(\nu)}\]

元のデータをFFTし、応答関数をFFTし、周波数領域で除算を行った後、逆フーリエ変換(IFFT)することで \(I_{\text{raw}}(x)\) を得ます。この方法では、データの長さが2のべき乗である必要があり、ゼロパディングによるデータ拡張が行われます。また、\(\hat{H}(\nu)\) が0に近い値をとる場合、除算が不安定になるため、ノイズの影響を受けやすいという欠点があります。

5. SciPyの scipy.signal.deconvolve (deconvolute_deconvolve)

SciPyライブラリの deconvolve 関数は、観測データと応答関数が与えられたときに、応答関数がどのようなデータに畳み込まれたかを推定します。これは最小二乗法などの数値的手法に基づいて実装されています。

6. データの前処理

  • 平滑化 (Smoothing): SmoothingBySimpleAverage は単純移動平均を、SmoothingByPolynomialFit はSavitzky-Golayフィルターに類似した多項式フィットに基づく重み付き移動平均を適用してノイズを低減します。

  • データ拡張 (Extend Smooth): FFTや scipy.signal.deconvolve を使用する際に、データの両端で発生する不連続性や端点効果を抑えるために、データの先頭にゼロや線形補間されたデータを追加します。

必要な非標準ライブラリとインストール方法

このプログラムは、以下の非標準ライブラリに依存しています。

  • NumPy: 数値計算を効率的に行うためのライブラリ。配列操作、フーリエ変換などに使用されます。

  • SciPy: 科学技術計算のためのライブラリ。信号処理モジュール(scipy.signal.deconvolve)を使用します。

  • Matplotlib: グラフ描画のためのライブラリ。結果の可視化に使用されます。

これらのライブラリは、Pythonのパッケージインストーラー pip を使用してインストールできます。

pip install numpy scipy matplotlib

必要な入力ファイル

プログラムは、CSV形式またはタブ区切り(.TXT 拡張子)のテキストファイルを読み込みます。

  • ファイル名: コマンドライン引数で指定します。デフォルトは pes.csv です。

  • ファイル形式:

    • CSV (.csv): カンマ (,) 区切り。

    • TXT (.txt): タブ (\t) 区切り。

  • データ構造:

    • 1行目はヘッダー行として扱われます(例: Energy,Intensity)。

    • 2行目以降はデータ行であり、各行は少なくとも2つの数値カラムを持つ必要があります。

    • 最初のカラムがX軸データ(例: エネルギー)、2番目のカラムがY軸データ(例: 強度)として扱われます。

    • .TXT ファイルの場合、X軸データは読み込み時に符号が反転されます(PESデータにおける結合エネルギーの慣例に対応)。

  • データ範囲: コマンドライン引数 xminxmax で指定された範囲内のデータのみが読み込まれ、処理されます。

例 (pes.csv):

Energy,Intensity
-5.0,10.2
-4.9,11.5
-4.8,13.1
...
1.9,8.7
2.0,9.0

生成される出力ファイル

プログラムは、処理された逆畳み込み結果を新しいCSVファイルとして保存します。

  • ファイル名: 入力ファイル名に基づいて自動的に生成されます。

    • 入力ファイルが input.csv の場合、出力ファイルは input-deconvoluted.csv となります。

    • 入力ファイルが data.txt の場合、出力ファイルは data-deconvoluted.csv となります。

  • ファイル内容: 出力CSVファイルには以下の3つのカラムが含まれます。

    1. x: 処理後のX軸データ(エネルギーなど)。

    2. y(input): 逆畳み込み処理の入力として使用されたY軸データ。前処理(平滑化、データ拡張、畳み込みなど)が適用された後のデータです。

    3. y(deconvoluted): 逆畳み込み処理によって得られたY軸データ。

例 (input-deconvoluted.csv):

x,y(input),y(deconvoluted)
-4.5,10.0,9.5
-4.4,10.5,11.0
-4.3,11.2,13.2
...

コマンドラインでの使用例 (Usage)

deconvolution.py は、実行モードによって必要な引数が異なります。

1. 畳み込み (convolve) または FFT (fft) モードの場合:

python deconvolution.py file mode convmode smoothmode xmin xmax Wa Grange kzero klin
  • file: 入力データファイル名 (例: pes.csv)

  • mode: 実行モード (convolve または fft)

  • convmode: convolve または fft モードでの畳み込みの挙動 ('', full, same)

    • '' (空): デフォルトの full と同等(NumPyのデフォルト)

    • full: 出力は \((N+M-1)\) の長さになり、全ての畳み込み結果を含む。

    • same: 出力は入力と同じ長さ \(N\) になるようにクリッピングされる。

  • smoothmode: 前処理の平滑化およびデータ拡張の方法。none, convolve, extend, average+ で結合した文字列。

    • none: 何も適用しない。

    • convolve: 畳み込みによる平滑化(別途フィルターが適用されるわけではない。データ拡張の前に convolve 関数を通すことを意味する)

    • extend: データ端をゼロまたは線形補間で拡張。

    • average: 移動平均による平滑化。

    • 例: convolve+extend, average+extend

  • xmin: 解析範囲のX軸最小値 (float)

  • xmax: 解析範囲のX軸最大値 (float)

  • Wa: ガウスフィルターの半値幅 (float, eV)

  • Grange: ガウスフィルターを考慮する Wa の倍率 (float)

  • kzero: データ拡張時に先頭に追加するゼロデータの幅を nw の倍数で指定 (nw はガウスフィルター半分の幅) (float)

  • klin: データ拡張時に線形補間する幅を nw の倍数で指定 (float)

2. Jacobi法 (jacobi) または Gauss-Seidel法 (gs) モードの場合:

python deconvolution.py file mode xmin xmax Wa dump nmaxiter eps nsmooth zeroc
  • file: 入力データファイル名 (例: pes.csv)

  • mode: 実行モード (gs または jacobi)

    • gs: Gauss-Seidel法

    • jacobi: Jacobi法

  • xmin: 解析範囲のX軸最小値 (float)

  • xmax: 解析範囲のX軸最大値 (float)

  • Wa: ガウスフィルターの半値幅 (float, eV)

  • dump: ダンピング係数 (float)。収束を制御する。

  • nmaxiter: 最大反復回数 (int)。

  • eps: 収束判定に使用する相対誤差の閾値 (float)。

  • nsmooth: 各反復後に適用する平滑化の窓幅 (int)。

  • zeroc: ゼロ補正 (0: 無効, 1: 有効)。負の値を0にクリップする。

コマンドラインでの具体的な使用例

例1: Gauss-Seidel法による逆畳み込み

pes.csv という入力ファイルに対して、Gauss-Seidel法を用いて逆畳み込みを実行します。

python deconvolution.py pes.csv gs -6.0 2.0 0.12 1.0 300 1.0e-4 5 0
  • pes.csv: 入力データファイル。

  • gs: Gauss-Seidel法で実行。

  • -6.0: 解析範囲のX軸最小値。

  • 2.0: 解析範囲のX軸最大値。

  • 0.12: ガウスフィルターの半値幅を \(0.12\) eV に設定。

  • 1.0: ダンピング係数を \(1.0\) に設定。

  • 300: 最大反復回数を \(300\) 回に設定。

  • 1.0e-4: 収束判定の相対誤差を \(1.0 \times 10^{-4}\) に設定。

  • 5: 各反復後に窓幅 \(5\) のSavitzky-Golayフィルターで平滑化。

  • 0: 負の値のゼロ補正を無効化。

実行結果の説明:

プログラムはまず、入力データの概要、フィルターパラメータ、Gauss-Seidel法の反復条件を表示します。 その後、matplotlib を用いたグラフウィンドウが開き、リアルタイムで逆畳み込みの反復計算の進捗が表示されます。上段のグラフには、元の生データと現在の逆畳み込み結果が重ねて表示され、下段にはガウスフィルターの形状が表示されます。 各反復ステップごとに、誤差と収束状況がコンソールに表示されます。 収束条件を満たすか、最大反復回数に達すると計算が終了し、最終的なグラフが表示された後、結果が pes-deconvoluted.csv というファイルに保存されます。このCSVファイルには、X軸データ、逆畳み込みへの入力データ、および最終的な逆畳み込み結果が含まれます。

例2: FFT法による逆畳み込みとデータ拡張・平滑化

pes.csv という入力ファイルに対して、FFT法を用いて逆畳み込みを実行し、前処理としてデータ拡張と移動平均による平滑化を適用します。

python deconvolution.py pes.csv fft full average+extend -4.5 2.0 0.12 2.0 5 5
  • pes.csv: 入力データファイル。

  • fft: FFT法で実行。

  • full: numpy.convolve のモードを full に設定(FFTでは内部的にデータ長が調整されるため、ここでの full は主に前処理の convolve 関数に影響)。

  • average+extend: 前処理として、移動平均 (average) とデータ拡張 (extend) を適用。

  • -4.5: 解析範囲のX軸最小値。

  • 2.0: 解析範囲のX軸最大値。

  • 0.12: ガウスフィルターの半値幅を \(0.12\) eV に設定。

  • 2.0: ガウスフィルターを半値幅の \(2.0\) 倍の範囲で考慮。

  • 5: データ拡張時に先頭に nw*5 個のゼロを追加。

  • 5: データ拡張時に nw*5 個の線形補間を適用。

実行結果の説明:

プログラムは、入力データの概要、フィルターパラメータ、FFT法固有のデータ長変更(2のべき乗への調整)、およびデータ拡張の詳細を表示します。 前処理として、入力データに対して移動平均による平滑化と、FFT処理での端点効果を軽減するためのデータ拡張が行われます。 その後、拡張・平滑化されたデータとガウスフィルター波形に対してFFTベースの逆畳み込みが実行されます。 計算終了後、matplotlib のグラフウィンドウに3つのプロットが表示されます。上段には入力として使用された(畳み込まれた)データと逆畳み込み結果、中段には元の生データと畳み込み入力データ、下段にはFFT処理に用いられたフィルター波形が表示されます。 最後に、結果は pes-deconvoluted.csv というファイルに保存されます。