@@ -1103,6 +1103,7 @@ def set_time_constraints(self, channels,
11031103
11041104 def set_csd (self , channels , csd ,
11051105 coupling = 'AC' ,
1106+ ignored_frequency_peaks = None ,
11061107 calc_icov = True ):
11071108 """
11081109 Add csd, calculate inverse (optional)
@@ -1117,7 +1118,20 @@ def set_csd(self, channels, csd,
11171118
11181119 csd : ndarray
11191120 csd [nchan, nchan, nsamples]
1121+
1122+ coupling : str, optional [default='AC']
1123+ String that determines if the zero frequency bin of the inverted csd
1124+ should be ignored when calculating
1125+ the optimum amplitude. If set to 'AC', then the zero
1126+ frequency bin is ignored. If set to anything else, then the
1127+ zero frequency bin is kept.
11201128
1129+ ignored_frequency_peaks : float or list of float [default=None]
1130+ frequencies that are ignored in optimal filter
1131+ calculation. The nearest bin (both positive/negative frequencies) from
1132+ given frequency is selected and CSD frequency set to infinity.
1133+
1134+
11211135 Returns
11221136 -------
11231137 None
@@ -1145,6 +1159,9 @@ def set_csd(self, channels, csd,
11451159 f'(# samples={ self ._nbins } ) must have same '
11461160 f'number of samples!' )
11471161
1162+ # frequency vectror
1163+ self ._fft_freqs = fftfreq (nbins , self ._fs )
1164+
11481165 # add to dictionary
11491166 self ._csd [channel_name ] = csd
11501167
@@ -1155,10 +1172,12 @@ def set_csd(self, channels, csd,
11551172 # calculate icov
11561173 if calc_icov :
11571174 self .calc_icovf (channel_name ,
1158- coupling = coupling )
1159-
1160-
1161- def set_psd (self , channel , psd , coupling = 'AC' ):
1175+ coupling = coupling ,
1176+ ignored_frequency_peaks = ignored_frequency_peaks )
1177+
1178+
1179+ def set_psd (self , channel , psd , coupling = 'AC' ,
1180+ ignored_frequency_peaks = None ):
11621181 """
11631182 Add psd for specified channel
11641183 If psd already exist, it is overwritten
@@ -1179,6 +1198,12 @@ def set_psd(self, channel, psd, coupling='AC'):
11791198 frequency bin is ignored. If set to anything else, then the
11801199 zero frequency bin is kept.
11811200
1201+ ignored_frequency_peaks : float or list of float [default=None]
1202+ frequencies that are ignored in optimal filter
1203+ calculation. The nearest bin (both positive/negative frequencies) from
1204+ given frequency is selected and CSD frequency set to infinity.
1205+
1206+
11821207 Returns
11831208 -------
11841209 None
@@ -1201,16 +1226,23 @@ def set_psd(self, channel, psd, coupling='AC'):
12011226 f'psd/template with same tag must have same '
12021227 f'number of samples!' )
12031228
1229+
1230+ # frequency vectror
1231+ self ._fft_freqs = fftfreq (nbins , self ._fs )
1232+
12041233 # add to dictionary
12051234 csd = psd
12061235 if psd .ndim == 1 :
12071236 csd = psd [np .newaxis , np .newaxis , :] # now shape is (1, 1, nfreq)
12081237
1209- self .set_csd (channel , csd , coupling = coupling )
1238+ self .set_csd (channel , csd , coupling = coupling ,
1239+ ignored_frequency_peaks = ignored_frequency_peaks )
12101240
12111241
12121242
1213- def calc_icovf (self , channels , coupling = 'AC' ):
1243+ def calc_icovf (self , channels ,
1244+ coupling = 'AC' ,
1245+ ignored_frequency_peaks = None ):
12141246 """
12151247 A function that inverts the csd or covariance noise matrix between channels.
12161248
@@ -1228,7 +1260,13 @@ def calc_icovf(self, channels, coupling='AC'):
12281260 frequency bin is ignored. If set to anything else, then the
12291261 zero frequency bin is kept.
12301262
1231-
1263+ ignored_frequency_peaks : float or list of float [default=None]
1264+ frequencies that are ignored in optimal filter
1265+ calculation. The nearest bin (both positive/negative frequencies) from
1266+ given frequency is selected and CSD frequency set to infinity.
1267+
1268+
1269+
12321270 Returns
12331271 -------
12341272
@@ -1248,11 +1286,32 @@ def calc_icovf(self, channels, coupling='AC'):
12481286
12491287 if coupling == 'AC' :
12501288 temp_icovf [:,:,0 ] = 0.0
1289+
1290+ if ignored_frequency_peaks is not None :
1291+
1292+ if not isinstance (ignored_frequency_peaks , list ):
1293+ ignored_frequency_peaks = [ignored_frequency_peaks ]
1294+
1295+ for freq in ignored_frequency_peaks :
1296+
1297+ # make sure frequency positive
1298+ freq = np .abs (freq )
1299+
1300+ # positive frequency
1301+ idx_pos = int (np .argmin (np .abs (self ._fft_freqs - freq )))
1302+ mask = np .zeros_like (self ._fft_freqs , dtype = bool )
1303+ mask [idx_pos ] = True
1304+
1305+ # negative frequency
1306+ idx_neg = int (np .argmin (np .abs (self ._fft_freqs + freq )))
1307+ mask [idx_neg ] = True
1308+
1309+ # modify
1310+ temp_icovf [..., mask ] = 0.0
1311+
12511312
12521313 self ._icovf [channel_name ] = temp_icovf
12531314
1254-
1255-
12561315
12571316 def clear_signal (self ):
12581317 """
@@ -1401,8 +1460,10 @@ def calc_phi(self, channels, template_tag=None,
14011460
14021461 # get noise data (inverte covariance matrix)
14031462 if self .icovf (channel_name ) is None :
1404- self .calc_icovf (channel_name )
1405- icovf = self .icovf (channel_name )
1463+ raise ValueError (f'ERROR: Inverted CSD has not been calculated '
1464+ f'for channel { channel_name } !' )
1465+
1466+ icovf = copy .deepcopy (self .icovf (channel_name ))
14061467
14071468
14081469 # get list of tags
0 commit comments