2

Pythonでは、2つの配列を正規化してから、それらが重なっている領域の平均を取り、新しい複合配列を作成しようとしています。

これを行うには、次のことを行う必要があると思います。

  1. 重複する領域を見つけ、
  2. オーバーラップしたy値を補間し、
  3. 繰り返して、最適な正規化定数を見つけてから、
  4. ピースを貼り合わせて、新しい曲線を作成します

いくつかのセミランダムな値を使用すると、次のようになります。

ここに画像の説明を入力してください

このコードは、y値がそれほど離れていない小さなデータセットには最適ですが、Y1とY2の間に桁違いの値があるとPythonがクラッシュします(明らかに反復が原因です)。コードは次のとおりです。

X1o = [x for x in X1 if x > X2[0]]
X2o = [x for x in X2 if x < X1[-1]]
Y1o = [y for y in Y1[(len(Y1)-len(X1o)):]]
Y2o = [y for y in Y2[:len(X2o)]]
Y2o = list(interp(X1o,X2o,Y2o))

c = abs(min(Y1o)-max(Y2o))
Y2test = [y2+c for y2 in Y2o]
Y2s = []
d = 0.01*min(Y2test)
while min(Y2test) < max(Y1o):
  Y2test = [y+d for y in Y2test]
  Y2s.append(Y2test)
  plot(X1o,Y2test,c='k',alpha=0.5)

idx = min(map(lambda i: (u.squaredError(Y1o, i), i, Y2s.index(i)), Y2s))[-1]         
Yavg = [(y1+y2)/2 for y1,y2 in zip(Y1o,Y2s[idx])]
diff = Y2s[idx][0]-Y2o[0]

X = [x for x in X1 if x < X2[0]] + X1o + [x for x in X2 if x > X1[-1]]
Y = [y for x,y in zip(X1,Y1) if x < X2[0]] + Yavg + [y+diff for x,y in zip(X2,Y2) if x > X1[-1]]

私は本当にこれを、数千のデータポイントとy値の間に最大20桁の広がりを持つ恒星スペクトルで行う必要があります。

任意の提案をいただければ幸いです!

4

1 に答える 1

1

あなたのコードは、numpyとより少ないpythonリストを使用することで大きな恩恵を受けるでしょう。これは非効率的で、特にあなたの行Y2s.append(Y2test)です。サイクルが長すぎるとwhile、非常に長いリストに追加するだけで、時間がかかり非効率になります。

そうは言っても、コードのボトルネックは最小化です。あなたは現在、Pythonリストを使ってブルートフォース攻撃を行っています。scipy.optimize関数の1つを使用することで大きなメリットが得られます。

これが私がすることのいくつかの広い提案です:

  1. 両方のスペクトルのx座標の極値を見つけ、両方を共通のx値のグリッドに内挿します。
  2. scipy.optimize.fminのフレーバーを使用して最小化を行い、最適な正規化を計算します。
  3. 正規化されたスペクトルの一部を共通のグリッドに内挿します

fminを使用したサンプルコード(テストされていません)は次のとおりです。

import numpy as np
import scipy.optimize as opt

# y1 = interpolated values for one of the spectra
# y2 = interpolated values for the other spectra, normalise this one 

def errfunc(p, a1, a2):
    return np.sum(a1 - a2 * p)

p0 = 1.  # initial guess
norm_factor = opt.fmin(errfunc, p0, args=(y1, y2))

そして、これはあなたに最適なものを与えるはずですnorm_factor

于 2012-12-12T22:00:34.773 に答える