共分散行列(それらのパワースペクトル密度(PSD)およびクロスパワースペクトル密度(CSD))を考えると、一連の定常色付き時系列の生成に問題があります。
2つの時系列と与えられると、ような多くの広く利用可能なルーチンを使用して、パワースペクトル密度(PSD)およびクロススペクトル密度(CSD)を推定できることを知っていますMatlabなどの関数psd()
とcsd()
関数。PSDとCSDは共分散行列を構成します
逆にしたい場合はどうなりますか? 共分散行列が与えられた場合、と実現をどのように生成しますか?
背景理論を含めるか、これを行う既存のツールを指摘してください(Pythonのすべてが素晴らしいでしょう)。
私の試み
以下は、私が試したものと、私が気づいた問題の説明です。少し長い間読んでおり、誤用された用語が含まれている場合は申し訳ありません。間違っていることが指摘できる場合、それは非常に役立ちます。しかし、私の質問は上記の太字のものです。
- PSDとCSDは、時系列のフーリエ変換の積の期待値(またはアンサンブル平均)として記述できます。したがって、共分散行列は次のように記述できます
ここで、
- 共分散行列はエルミート行列であり、ゼロまたは正の実固有値を持ちます。だから、に分解することができる
どこは、非ゼロ要素がの固有値の平方根である対角行列です。は、その列が正規直交固有ベクトルである行列です。は単位行列です。
- 単位行列は次のように書かれている
ここで、およびは、平均値と単位分散がゼロの無相関の複素周波数系列です。
- 2.で3.を使用し、1と比較します。時系列のフーリエ変換は次のとおりです
- 時系列は、逆高速フーリエ変換などのルーチンを使用して取得できます。
これを行うためにPythonでルーチンを作成しました。
def get_noise_freq_domain_CovarMatrix( comatrix , df , inittime , parityN , seed='none' , N_previous_draws=0 ) :
"""
returns the noise time-series given their covariance matrix
INPUT:
comatrix --- covariance matrix, Nts x Nts x Nf numpy array
( Nts = number of time-series. Nf number of positive and non-Nyquist frequencies )
df --- frequency resolution
inittime --- initial time of the noise time-series
parityN --- is the length of the time-series 'Odd' or 'Even'
seed --- seed for the random number generator
N_previous_draws --- number of random number draws to discard first
OUPUT:
t --- time [s]
n --- noise time-series, Nts x N numpy array
"""
if len( comatrix.shape ) != 3 :
raise InputError , 'Input Covariance matrices must be a 3-D numpy array!'
if comatrix.shape[0] != comatrix.shape[1] :
raise InputError , 'Covariance matrix must be square at each frequency!'
Nts , Nf = comatrix.shape[0] , comatrix.shape[2]
if parityN == 'Odd' :
N = 2 * Nf + 1
elif parityN == 'Even' :
N = 2 * ( Nf + 1 )
else :
raise InputError , "parityN must be either 'Odd' or 'Even'!"
stime = 1 / ( N*df )
t = inittime + stime * np.arange( N )
if seed == 'none' :
print 'Not setting the seed for np.random.standard_normal()'
pass
elif seed == 'random' :
np.random.seed( None )
else :
np.random.seed( int( seed ) )
print N_previous_draws
np.random.standard_normal( N_previous_draws ) ;
zs = np.array( [ ( np.random.standard_normal((Nf,)) + 1j * np.random.standard_normal((Nf,)) ) / np.sqrt(2)
for i in range( Nts ) ] )
ntilde_p = np.zeros( ( Nts , Nf ) , dtype=complex )
for k in range( Nf ) :
C = comatrix[ :,:,k ]
if not np.allclose( C , np.conj( np.transpose( C ) ) ) :
print "Covariance matrix NOT Hermitian! Unphysical."
w , V = sp_linalg.eigh( C )
for m in range( w.shape[0] ) :
w[m] = np.real( w[m] )
if np.abs(w[m]) / np.max(w) < 1e-10 :
w[m] = 0
if w[m] < 0 :
print 'Negative eigenvalue! Simulating unpysical signal...'
ntilde_p[ :,k ] = np.conj( np.sqrt( N / (2*stime) ) * np.dot( V , np.dot( np.sqrt( np.diag( w ) ) , zs[ :,k ] ) ) )
zerofill = np.zeros( ( Nts , 1 ) )
if N % 2 == 0 :
ntilde = np.concatenate( ( zerofill , ntilde_p , zerofill , np.conj(np.fliplr(ntilde_p)) ) , axis = 1 )
else :
ntilde = np.concatenate( ( zerofill , ntilde_p , np.conj(np.fliplr(ntilde_p)) ) , axis = 1 )
n = np.real( sp.ifft( ntilde , axis = 1 ) )
return t , n
このルーチンをPSDとCSDに適用しました。これらの分析表現は、使用している検出器のモデリングから取得されています。重要なことは、すべての周波数で、共分散行列を構成することです(少なくとも、これらのif
ステートメントはすべてルーチンで渡されます)。共分散行列は3x3です。3つの時系列は約9000回生成されており、これらのすべての実現にわたって平均された推定PSDおよびCSDは、分析的なものとともに以下にプロットされます。全体的な形状は一致しますが、CSDの特定の周波数で顕著なノイズの特徴があります(図2)。PSDのピーク付近を拡大した後(図3)、PSDが実際に過小評価されていることに気付きました、CSDのノイズの多い特徴は、PSDのピークとほぼ同じ周波数で発生します。これは偶然ではなく、何らかの形でPSDからCSDに電力が漏れているとは思いません。このように多くのデータを実現することで、曲線が互いに重なり合うことを期待していました。