def coherence(y, x, source=None, *args, **kwargs): if source is None: return cohere(y, x, *args, **kwargs) else: cx, fx = cohere(x, source, *args, **kwargs) cy, _ = cohere(y, source, *args, **kwargs) coh = np.min([cx, cy], axis=0) return coh, fx
def _execute(self, x): # Lazy computation of NFFT and noverlap if not hasattr(self, "NFFT"): # Compute NFFT to obtain the desired frequency resolution # (if possible) # self.NFFT has to be even self.NFFT = int(round(0.5 * x.sampling_frequency / \ self.frequency_resolution) * 2) self.noverlap = 0 # For each pair of channels, we compute the STFT features = [] feature_names = [] for i, channel_name1 in enumerate(x.channel_names): for j, channel_name2 in enumerate(x.channel_names[i + 1:]): (Cxy, freqs) = mlab.cohere(x[:, i], x[:, i + 1 + j], Fs=x.sampling_frequency, NFFT=self.NFFT, noverlap=self.noverlap) # TODO: This would be more efficient without the explicit loop for index1, freq in enumerate(freqs): if not (self.min_frequency <= freq <= self.max_frequency): continue # Append as feature features.append(Cxy[index1]) feature_names.append("Coherence_%s_%s_%.2fHz" % (channel_name1, channel_name2, freq)) feature_vector = \ FeatureVector(numpy.atleast_2d(features).astype(numpy.float64), feature_names) return feature_vector
def _execute(self, x): # Lazy computation of NFFT and noverlap if not hasattr(self, "NFFT"): # Compute NFFT to obtain the desired frequency resolution # (if possible) # self.NFFT has to be even self.NFFT = int(round(0.5 * x.sampling_frequency / \ self.frequency_resolution) * 2) self.noverlap = 0 # For each pair of channels, we compute the STFT features = [] feature_names = [] for i, channel_name1 in enumerate(x.channel_names): for j, channel_name2 in enumerate(x.channel_names[i + 1:]): (Cxy, freqs) = mlab.cohere(x[:, i], x[:, i + 1 + j], Fs = x.sampling_frequency, NFFT = self.NFFT, noverlap = self.noverlap) # TODO: This would be more efficient without the explicit loop for index1, freq in enumerate(freqs): if not (self.min_frequency <= freq <= self.max_frequency): continue # Append as feature features.append(Cxy[index1]) feature_names.append("Coherence_%s_%s_%.2fHz" % (channel_name1, channel_name2, freq)) feature_vector = \ FeatureVector(numpy.atleast_2d(features).astype(numpy.float64), feature_names) return feature_vector
def cohere_transfere_MI (convolved_train, wNoise, nFFT, FS): """ Function computes coherence, mutual information from coherence, transfer function and cross-power-spectra density and power spectra density. Function computes the same for whole signal and only for the steady state portion (_short) :param metas: meta data :param convolved_train: convolved spike train :param wNoise: white noise :param nFFT: FFT :param FS: sample rate :return coh: computed coherence :return coh_short: :return freq: :return MI: :return MI_short: :return P_csd: :return P_csd_short: :return P_psd: :return P_csd_short: """ # conversions w. clipping first 2 seconds wNoiseShort = wNoise[2*FS:] conv_train_short = convolved_train[2*FS:] # compute coherence coh, freq = mlab.cohere(wNoise-np.mean(wNoise), convolved_train-np.mean(convolved_train), NFFT=nFFT, Fs=FS) coh_short, _ = mlab.cohere(wNoiseShort-np.mean(wNoiseShort), conv_train_short-np.mean(conv_train_short), NFFT=nFFT, Fs=FS) # calculate the mutual information MI = (-np.log(1-coh))/np.log(2) MI_short = (-np.log(1-coh_short))/np.log(2) # compute csd P_csd, _ = mlab.csd(wNoise, convolved_train, NFFT=nFFT, Fs=FS) P_csd_short, _ = mlab.csd(wNoiseShort, conv_train_short, NFFT=nFFT, Fs=FS) if np.any(np.absolute(P_csd_short) < 0): print("negative CSD") # compute psd P_psd,_ = mlab.psd(wNoise,NFFT=nFFT, Fs=FS) P_psd_short,_ = mlab.psd(wNoiseShort,NFFT=nFFT, Fs=FS) # compute the transfer function H = np.absolute(P_csd)/P_psd H_short = np.absolute(P_csd_short)/P_psd_short return freq, coh, coh_short, H, H_short, MI, MI_short, P_csd, P_csd_short, P_psd, P_psd_short
def octaveBandCoherence(degrAudioBands, refAudioBands, hz, fftRes=0.122): """ Calculate coherence between clean and degraded octave band audio Input ----- * degrAudioBands : array-like Degraded octave band audio * refAudioBands : array-like Reference (clean) octave band audio * hz : float or int Audio sample rate. Must be common between clean and dirty audio * fftRes : float or int Desired FFT frequency resolution Output ------ * coherences : ndarray Coherence values * fftfreqs : ndarray Frequencies for FFT points """ # FFT window size for PSD calculation: 32768 for ~0.06 Hz res at 2 kHz # Beware that 'cohere' isn't as forgiving as 'psd' with FFT lengths # larger than half the length of the signal psdWindow = fftWindowSize(fftRes, hz) print "Calculating degraded and reference audio coherence", print "(FFT length:", psdWindow, "samples)" for i, band in enumerate(degrAudioBands): with catch_warnings(): # catch and ignore spurious warnings simplefilter('ignore') # due to some irrelevant divide by 0's coherence, freqs = cohere(band, refAudioBands[i], NFFT=psdWindow, Fs=hz) # stack-up octave band spectras try: coherences = vstack((coherences, coherence)) fftfreqs = vstack((fftfreqs, freqs)) except: coherences = coherence fftfreqs = freqs return coherences, fftfreqs
def octaveBandCoherence(degrAudioBands, refAudioBands, hz, fftRes=0.122): """ Calculate coherence between clean and degraded octave band audio Input ----- * degrAudioBands : array-like Degraded octave band audio * refAudioBands : array-like Reference (clean) octave band audio * hz : float or int Audio sample rate. Must be common between clean and dirty audio * fftRes : float or int Desired FFT frequency resolution Output ------ * coherences : ndarray Coherence values * fftfreqs : ndarray Frequencies for FFT points """ # FFT window size for PSD calculation: 32768 for ~0.06 Hz res at 2 kHz # Beware that 'cohere' isn't as forgiving as 'psd' with FFT lengths # larger than half the length of the signal psdWindow = fftWindowSize(fftRes, hz) print "Calculating degraded and reference audio coherence", print "(FFT length:",psdWindow,"samples)" for i,band in enumerate(degrAudioBands): with catch_warnings(): # catch and ignore spurious warnings simplefilter('ignore') # due to some irrelevant divide by 0's coherence, freqs = cohere(band, refAudioBands[i], NFFT=psdWindow, Fs=hz) # stack-up octave band spectras try: coherences = vstack((coherences, coherence)) fftfreqs = vstack((fftfreqs, freqs)) except: coherences = coherence fftfreqs = freqs return coherences, fftfreqs
def espec2(x,y,nfft,fs): """ # ================================================================================== # # # Calcula o espectro cruzado entre duas series reais # # Dados de entrada: x = serie real 1 (potencia de 2) # y = serie real 2 (potencia de 2) # nfft - Numero de pontos utilizado para o calculo da FFT # fs - frequencia de amostragem # # Dados de saida: [aa2] - col 0: vetor de frequencia # col 1: amplitude do espectro cruzado # col 2: co-espectro # col 3: quad-espectro # col 4: espectro de fase # col 5: espectro de coerencia # col 6: intervalo de confianca inferior do espectro cruzado # col 7: intervalo de confianca superior do espectro cruzado # col 8: intervalo de confianca da coerencia # # Infos: detrend - mean # window - hanning # noverlap - 50% # # ================================================================================== # """ #cross-spectral density - welch method (complex valued) sp = mlab.csd(x,y,NFFT=nfft,Fs=fs,detrend=mlab.detrend_mean,window=mlab.window_hanning,noverlap=nfft/2) f = sp[1][1:] sp2 = sp[0][1:] #co e quad espectro (real e imag) - verificar com parente co = np.real(sp2) qd = np.imag(sp2) #phase (angle function) ph = np.angle(sp2,deg=True) #ecoherence between x and y (0-1) coer = mlab.cohere(x,y,NFFT=nfft,Fs=fs,detrend=mlab.detrend_mean,window=mlab.window_hanning,noverlap=nfft/2) coer = coer[0][1:] #intervalo de confianca para a amplitude do espectro cruzado - 95% ici = sp2 * 14 /26.12 ics = sp2 * 14 /5.63 #intervalo de confianca para coerencia icc = np.zeros(len(sp2)) icc[:] = 1 - (0.05 ** (1 / (14 / 2.0 - 1))) aa2 = np.array([f,sp2,co,qd,ph,coer,ici,ics,icc]).T return aa2
def crossCalib(monitor_trace, response_trace, **kwargs): m_trace=monitor_trace.copy() r_trace=response_trace.copy() if 'demean' in kwargs and kwargs['demean']: m_trace.detrend('demean') r_trace.detrend('demean') if 'taper' in kwargs and kwargs['taper']: m_trace.taper(0.05) r_trace.taper(0.05) #Paramètres des PSD if 'nfft' in kwargs: n_fft=kwargs['nfft'] else: n_fft=1024 if 'npad' in kwargs: n_pad=kwargs['npad'] else: n_pad=n_fft*4 if 'noverlap' in kwargs: n_overlap=kwargs['noverlap'] else: n_overlap=int(n_fft*0.90) #paz par défaut: chaine générique if 'paz' in kwargs: paz=kwargs['paz'] else: paz=dict() paz['zeros']=np.array([]) paz['poles']=np.array([]) paz['gain']=1 paz['seismometer_gain']=1 paz['datalogger_gain']=1 paz['sensitivity']=paz['seismometer_gain']*paz['datalogger_gain']*paz['gain'] fs=m_trace.stats.sampling_rate (P00,f)=mlab.psd(m_trace.data,Fs=fs,NFFT=n_fft,noverlap=n_overlap,pad_to=n_pad,detrend=mlab.detrend_mean,window=mlab.window_hanning) (P01,f)=mlab.csd(m_trace.data,r_trace.data,Fs=fs,NFFT=n_fft,noverlap=n_overlap,pad_to=n_pad,detrend=mlab.detrend_mean,window=mlab.window_hanning) (C,f)=mlab.cohere(m_trace.data,r_trace.data,Fs=fs,NFFT=n_fft,noverlap=n_overlap,pad_to=n_pad,detrend=mlab.detrend_mean,window=mlab.window_hanning) (b,a)=sp.zpk2tf(paz['zeros'],paz['poles'],paz['sensitivity']) (_w,H0)=sp.freqs(b,a,f*2*np.pi) H1=P01*H0/P00 H1=H1[1:] C=C[1:] f=f[1:] return (H1,C,f)
def cohere1(theta): theta_r = math.radians(theta) rotated = (self.data[0].data) * math.cos(theta_r) + ( self.data[1].data) * math.sin(theta_r) coh, fre = mlab.cohere(referenceStream.data[0].data, rotated, NFFT=NFFT, noverlap=noverlap, Fs=Fs) return (coh - 1).sum()
def test_cohere(): N = 1024 np.random.seed(19680801) x = np.random.randn(N) # phase offset y = np.roll(x, 20) # high-freq roll-off y = np.convolve(y, np.ones(20) / 20., mode='same') cohsq, f = mlab.cohere(x, y, NFFT=256, Fs=2, noverlap=128) assert_allclose(np.mean(cohsq), 0.837, atol=1.e-3) assert np.isreal(np.mean(cohsq))
def espec2(x, y, nfft, fs): """ Calcula o espectro cruzado entre duas series reais Dados de entrada: x = serie real 1 (potencia de 2) y = serie real 2 (potencia de 2) nfft - Numero de pontos utilizado para o calculo da FFT fs - frequencia de amostragem Dados de saida: [aa2] - col 0: vetor de frequencia col 1: amplitude do espectro cruzado col 2: co-espectro col 3: quad-espectro col 4: espectro de fase col 5: espectro de coerencia col 6: intervalo de confianca inferior do espectro cruzado col 7: intervalo de confianca superior do espectro cruzado col 8: intervalo de confianca da coerencia Infos: detrend - mean window - hanning noverlap - 50% """ #cross-spectral density - welch method (complex valued) s, f = mlab.csd(x, y, NFFT=nfft, Fs=fs, detrend=mlab.detrend_mean, window=mlab.window_hanning, noverlap=nfft/2) # graus de liberdade dof = len(x) / nfft * 2 #co e quad espectro (real e imag) - verificar com parente co = np.real(s) qd = np.imag(s) #phase (angle function) ph = np.angle(s, deg=True) #ecoherence between x and y (0-1) coer = mlab.cohere(x, y, NFFT=nfft, Fs=fs, detrend=mlab.detrend_mean, window=mlab.window_hanning, noverlap=nfft/2)[0] # coer = coer[0][1:] #intervalo de confianca para a amplitude do espectro cruzado - 95% ici = s * dof /26.12 ics = s * dof /5.63 #intervalo de confianca para coerencia icc = np.zeros(len(s)) icc[:] = 1 - (0.05 ** (1 / (14 / 2.0 - 1))) # matriz de saida aa = np.array([f, s ,co, qd, ph, coer, ici, ics, icc]).T return aa
def cohere1(theta): print "\ncohere1()..." theta_r = math.radians(theta) rotated = (self.data[0].data)*math.cos(theta_r) + (self.data[1].data)*math.sin(theta_r) coh,fre = mlab.cohere(referenceStream.data[0].data, rotated, NFFT=NFFT, noverlap=noverlap, Fs=Fs) print "theta_r = " + str(theta_r) print "rotated data len = " + str(len(rotated)) print "coherence freq len = " + str(len(fre)) print "coherence data len = " + str(len(coh)) cohsum = (coh - 1).sum() print "coherence sum = (coh - 1).sum() = " + str(cohsum) return cohsum
def calculate_impedance_from_pressure(signals, sr, nwind=1024, ref_sensor_num=0): """ calculates the uncorrected impedance (this is to be compared to a theoretical or known impedance in order to calculate calibration factors) """ slave_sensor_nums = signals.shape[1] slave_sensor_nums.discard(ref_sensor_num) l = self.duct.get_total_length() sensor_gains = [] sensor_coh = [] duct = self.load_model for sno in slave_sensor_nums: # calculate measured transfer functions tz, ff = tfe(x=signals[:, self.ref_sensor_num], y=signals[:, sno], Fs=sr, NFFT=nwind) cz, ff = cohere(x=signals[:, self.ref_sensor_num], y=signals[:, sno], Fs=sr, NFFT=nwind) # calculate theoretical transfer functions calmx_inv = [] z0th = [] for f in ff: cmx1 = duct.transfer_mx_at_freq( f, from_pos=l - self.sensor_positions[self.ref_sensor_num], to_pos=l) cmx2 = duct.transfer_mx_at_freq(f, from_pos=l - self.sensor_positions[sno], to_pos=l) calmx_inv.append(np.array([cmx1[0, :], cmx2[0, :]])) z0th.append(duct.get_input_impedance_at_freq(f, from_pos=l)) calmx_inv = np.array(calmx_inv)
def evaluate(self): """ Coherence function. Matplotlib.mlab implementation. """ cls_attr_name = self.__class__.__name__ + ".time_series" self.time_series.trait["data"].log_debug(owner=cls_attr_name) data_shape = self.time_series.data.shape #(frequency, nodes, nodes, state-variables, modes) result_shape = (self.nfft / 2 + 1, data_shape[2], data_shape[2], data_shape[1], data_shape[3]) LOG.info("result shape will be: %s" % str(result_shape)) result = numpy.zeros(result_shape) #TODO: For region level, 4s, 2000Hz, this takes ~2min... (which is stupidly slow) #One inter-node coherence, across frequencies for each state-var & mode. for mode in range(data_shape[3]): for var in range(data_shape[1]): data = self.time_series.data[:, var, :, mode] data = data - data.mean(axis=0)[numpy.newaxis, :] #TODO: Work out a way around the 4 level loop, #TODO: coherence isn't directional, so, get rid of redundancy... for n1 in range(data_shape[2]): for n2 in range(data_shape[2]): cxy, freq = mlab.cohere( data[:, n1], data[:, n2], NFFT=self.nfft, Fs=self.time_series.sample_rate, detrend=detrend_linear, window=mlab.window_none) result[:, n1, n2, var, mode] = cxy util.log_debug_array(LOG, result, "result") util.log_debug_array(LOG, freq, "freq") coherence = spectral.CoherenceSpectrum(source=self.time_series, nfft=self.nfft, array_data=result, frequency=freq, use_storage=False) return coherence
def coherence_mlab(data, sample_rate, nfft=256): _, nsvar, nnode, nmode = data.shape # (frequency, nodes, nodes, state-variables, modes) coh_shape = nfft/2 + 1, nnode, nnode, nsvar, nmode coh = numpy.zeros(coh_shape) for mode in range(nmode): for var in range(nsvar): data = data[:, var, :, mode].copy() data -= data.mean(axis=0)[numpy.newaxis, :] for n1 in range(nnode): for n2 in range(nnode): cxy, freq = mlab.cohere(data[:, n1], data[:, n2], NFFT=nfft, Fs=sample_rate, detrend=detrend_linear, window=mlab.window_none) coh[:, n1, n2, var, mode] = cxy return coh, freq
def calculate(self, NFFT=2**16, thresh=0.95): self.pxx1, self.freq = mlab.psd(self.corrected_timeseries1.real, NFFT=NFFT, Fs=self.timeseries_sample_rate) self.pii1, self.freq = mlab.psd(self.corrected_timeseries1.imag, NFFT=NFFT, Fs=self.timeseries_sample_rate) self.pxx2, self.freq = mlab.psd(self.corrected_timeseries2.real, NFFT=NFFT, Fs=self.timeseries_sample_rate) self.pii2, self.freq = mlab.psd(self.corrected_timeseries2.imag, NFFT=NFFT, Fs=self.timeseries_sample_rate) self.coherence, self.coh_freq = mlab.cohere( self.corrected_timeseries1.real, self.corrected_timeseries2.real, NFFT=NFFT, Fs=self.timeseries_sample_rate) #print self.coherence.mean() self.effective_dof = self.coherence.mean() * len( self.corrected_timeseries1) / (NFFT / 2.) self.effective_dof = 0.25 * (len(self.corrected_timeseries1) / (NFFT / 2.)) self.gamma95 = 1 - (1 - thresh)**(1. / (self.effective_dof - 1.)) self.mask95 = self.coherence > self.gamma95 self.csd, self.csd_freq = mlab.csd(self.corrected_timeseries1.real, self.corrected_timeseries2.real, NFFT=NFFT, Fs=self.timeseries_sample_rate) self.angle = np.angle(self.csd) self.lpts1 = filters.low_pass_fir( self.corrected_timeseries1.real, cutoff=100.0, nyquist_freq=self.timeseries_sample_rate) self.lpts2 = filters.low_pass_fir( self.corrected_timeseries2.real, cutoff=100.0, nyquist_freq=self.timeseries_sample_rate)
def evaluate(self): """ Coherence function. Matplotlib.mlab implementation. """ cls_attr_name = self.__class__.__name__+".time_series" self.time_series.trait["data"].log_debug(owner = cls_attr_name) data_shape = self.time_series.data.shape #(frequency, nodes, nodes, state-variables, modes) result_shape = (self.nfft/2 + 1, data_shape[2], data_shape[2], data_shape[1], data_shape[3]) LOG.info("result shape will be: %s" % str(result_shape)) result = numpy.zeros(result_shape) #TODO: For region level, 4s, 2000Hz, this takes ~2min... (which is stupidly slow) #One inter-node coherence, across frequencies for each state-var & mode. for mode in range(data_shape[3]): for var in range(data_shape[1]): data = self.time_series.data[:, var, :, mode] data = data - data.mean(axis=0)[numpy.newaxis, :] #TODO: Work out a way around the 4 level loop, #TODO: coherence isn't directional, so, get rid of redundancy... for n1 in range(data_shape[2]): for n2 in range(data_shape[2]): cxy, freq = mlab.cohere(data[:, n1], data[:, n2], NFFT = self.nfft, Fs = self.time_series.sample_rate, detrend = detrend_linear, window = mlab.window_none) result[:, n1, n2, var, mode] = cxy util.log_debug_array(LOG, result, "result") util.log_debug_array(LOG, freq, "freq") coherence = spectral.CoherenceSpectrum(source = self.time_series, nfft = self.nfft, array_data = result, frequency = freq, use_storage = False) return coherence
def calc_spectra(x, y, sr, nfft = None): # expects two 1d arrays as signals and a number for the sampling rate # (optional) parameters for FFT # returns PSD(x,x), PSD(y,y), PSD(x,y), PSD(y,x) and frequency if nfft is None: nfft = 2 ** 11 params = {'NFFT': nfft, 'noverlap': nfft / 2} if not isinstance(params, dict): print('ERROR: params in calc_spectra() is not a dictionary.') x = x - mean(x) y = y - mean(y) Pxx, _ = ml.psd(x, Fs=sr, **params) Pyy, _ = ml.psd(y, Fs=sr, **params) Pxy, _ = ml.csd(x, y, Fs=sr, **params) Pyx, _ = ml.csd(y, x, Fs=sr, **params) ml_coherence, f = ml.cohere(x, y, Fs=sr, **params) return Pxx, Pyy, Pxy, Pyx, ml_coherence, f
def calculate(self,NFFT=2**16,thresh=0.95): self.pxx1,self.freq = mlab.psd(self.corrected_timeseries1.real,NFFT=NFFT,Fs=self.timeseries_sample_rate) self.pii1,self.freq = mlab.psd(self.corrected_timeseries1.imag,NFFT=NFFT,Fs=self.timeseries_sample_rate) self.pxx2,self.freq = mlab.psd(self.corrected_timeseries2.real,NFFT=NFFT,Fs=self.timeseries_sample_rate) self.pii2,self.freq = mlab.psd(self.corrected_timeseries2.imag,NFFT=NFFT,Fs=self.timeseries_sample_rate) self.coherence,self.coh_freq = mlab.cohere(self.corrected_timeseries1.real,self.corrected_timeseries2.real, NFFT=NFFT,Fs=self.timeseries_sample_rate) #print self.coherence.mean() self.effective_dof = self.coherence.mean()*len(self.corrected_timeseries1)/(NFFT/2.) self.effective_dof = 0.25*(len(self.corrected_timeseries1)/(NFFT/2.)) self.gamma95 = 1-(1-thresh)**(1./(self.effective_dof-1.)) self.mask95 = self.coherence > self.gamma95 self.csd,self.csd_freq = mlab.csd(self.corrected_timeseries1.real,self.corrected_timeseries2.real, NFFT=NFFT,Fs=self.timeseries_sample_rate) self.angle = np.angle(self.csd) self.lpts1 = filters.low_pass_fir(self.corrected_timeseries1.real,cutoff=100.0,nyquist_freq=self.timeseries_sample_rate) self.lpts2 = filters.low_pass_fir(self.corrected_timeseries2.real,cutoff=100.0, nyquist_freq=self.timeseries_sample_rate)
def correlate(z,y,mode='p'): # p for pearson, c for pcc and s for spectral coherence l=len(y) if len(z)!=len(y): print 'Error' return if mode=='p': a=num.correlate(dNorm(z),dNorm(y),'valid') return a/len(y) elif mode=='c' : za=scipy.signal.hilbert(z) ya=scipy.signal.hilbert(y) phi1=[cx.phase(x) for x in za] phi2=[cx.phase(x) for x in ya] a=0 for i in range(l): a=a+(abs(cx.exp(1j*phi1[i])+cx.exp(1j*phi2[i]))-\ abs(cx.exp(1j*phi1[i])-cx.exp(1j*phi2[i])))/2 return a/len(y) elif mode=='s': sc,f=cohere(z,y) return sc,f return
def cohere1(theta): theta_r = math.radians(theta) rotated = (self.data[0].data)*math.cos(theta_r) + (self.data[1].data)*math.sin(theta_r) coh,fre = mlab.cohere(referenceStream.data[0].data, rotated, NFFT=NFFT, noverlap=noverlap, Fs=Fs) return (coh - 1).sum()
f = aa1[:,1] sp = aa1[:,0] ## =================================================== ## # Espectro cruzado #espectro cruzado (amplitude do espec cruzado?) aa2 = mlab.csd(eta1,dspx1,NFFT=256,Fs=1.28,detrend=mlab.detrend_mean,window=mlab.window_hanning,noverlap=128) aa2 = np.array(aa2).T #calcula o modulo do espectro aa2[:,0] = abs(aa2[:,0]) #espectro de coerencia aa3 = mlab.cohere(eta1,dspx1,NFFT=256,Fs=1.28,detrend=mlab.detrend_mean,window=mlab.window_hanning,noverlap=128) aa3 = np.array(aa3).T ## Figuras #autoespectro pl.figure() pl.plot(aa[:,0],aa[:,1]) pl.plot(f,sp) pl.legend(['hp','py']) pl.title('espectro de elevacao') #amplitude do espectro cruzado pl.figure() pl.plot(aa[:,0],aa[:,3])
def pyCOH(xin,yin,fs,nfft): coh,freq=mlab.cohere(xin,yin,NFFT=nfft,Fs=fs) return coh,freq
def coherence(self, other, fftlength=None, overlap=None, window=None, **kwargs): """Calculate the frequency-coherence between this `TimeSeries` and another. Parameters ---------- other : `TimeSeries` `TimeSeries` signal to calculate coherence with fftlength : `float`, optional, default: `TimeSeries.duration` number of seconds in single FFT, defaults to a single FFT overlap : `float`, optional, default: `None` number of seconds of overlap between FFTs, defaults to no overlap window : `timeseries.window.Window`, optional, default: `HanningWindow` window function to apply to timeseries prior to FFT, default HanningWindow of the relevant size **kwargs any other keyword arguments accepted by :func:`matplotlib.mlab.cohere` except ``NFFT``, ``window``, and ``noverlap`` which are superceded by the above keyword arguments Returns ------- coherence : :class:`~gwpy.spectrum.core.Spectrum` the coherence `Spectrum` of this `TimeSeries` with the other Notes ----- If `self` and `other` have difference :attr:`TimeSeries.sample_rate` values, the higher sampled `TimeSeries` will be down-sampled to match the lower. See Also -------- :func:`matplotlib.mlab.cohere` for details of the coherence calculator """ from matplotlib import mlab from ..spectrum import Spectrum # check sampling rates if self.sample_rate.to('Hertz') != other.sample_rate.to('Hertz'): sampling = min(self.sample_rate.value, other.sample_rate.value) # resample higher rate series if self.sample_rate.value == sampling: other = other.resample(sampling) self_ = self else: self_ = self.resample(sampling) else: sampling = self.sample_rate.value self_ = self # check fft lengths if overlap is None: overlap = 0 else: overlap = int((overlap * self_.sample_rate).decompose().value) if fftlength is None: fftlength = int(self_.size/2. + overlap/2.) else: fftlength = int((fftlength * self_.sample_rate).decompose().value) if window is not None: kwargs['window'] = window coh, f = mlab.cohere(self_.value, other.value, NFFT=fftlength, Fs=sampling, noverlap=overlap, **kwargs) out = coh.view(Spectrum) out.xindex = f out.epoch = self.epoch out.name = 'Coherence between %s and %s' % (self.name, other.name) out.unit = 'coherence' return out
def transferogram(source, target, rate=1, start_time=0., delta_time=1., sample_duration=.5, window_duration=.125, window_hop=None): ''' tfe, freqs, times, coherence = transferogram(...) Calculates a time-varying transfer function from source (x) to target (y) at intervals delta_time. Parameters: * source: source signal (reuqired) * target: target signal (required) * rate: sampling rate * start_time: starting time for tfe calculations * delta_time: distance between calculations * sample_duration: length of signals used in tfe estimates (longer than window_duration, used in averaging) * window_duration: inidvidual window length in tfe estimates * window_hop: hop between windows (defaults to window_duration/2) Returns: * tfe: transfer functions (complex matrix NxM) * freqs: frequencies corresponding to tfe estimates (array size N) * times: times corresponding to tfe estimates (array size M) * coherence: coherence matrix MxN ''' # convert time to samples sample_start = int(start_time*rate) sample_delta = int(delta_time*rate) sample_len = int(sample_duration*rate) if target is None: n_target = len(source) else: n_target = len(target) n_samples = min(len(source), n_target) sample_end = n_samples - sample_start - sample_len # windowing parameters nsamp_window = nextpow2(window_duration*rate) if window_hop: nsamp_window_hop = nextpow2(window_hop*rate) else: nsamp_window_hop = nsamp_window/2 noverlap = nsamp_window - nsamp_window_hop resp = [] coherence = [] times = [] if target is None: for ii in np.arange(sample_start, sample_end, sample_delta): block_resp, freq = psd(source[ii:ii+sample_len], NFFT=nsamp_window, noverlap=noverlap, Fs=rate) block_coh = [] times.append((ii+sample_len/2)/float(rate)) resp.append(block_resp) coherence.append(block_coh) else: for ii in np.arange(sample_start, sample_end, sample_delta): block_resp, freq = tfe(target[ii:ii+sample_len], source[ii:ii+sample_len], NFFT=nsamp_window, noverlap=noverlap, Fs=rate) block_coh, _ = cohere(target[ii:ii+sample_len], source[ii:ii+sample_len], NFFT=nsamp_window, noverlap=noverlap, Fs=rate) times.append((ii+sample_len/2)/float(rate)) resp.append(block_resp) coherence.append(block_coh) return np.array(resp).T, freq, np.array(times), np.array(coherence).T
sfreq, duration = 1000., 1000 times = np.arange(0, duration, 1 / sfreq) amp , amp2 , nse_amp = 1., 1., 0.5 nfft = 512 nse1 = np.random.rand(times.size) * nse_amp nse2 = np.random.rand(times.size) * nse_amp x = amp * np.sin(2 * np.pi * 200 * times) + nse1 y = amp * np.sin(2 * np.pi * 200 * times + np.pi/5) + nse2 shift = 100 # integer assert shift < sfreq * duration, 'Choose a smaller shift.' #y = amp2 * np.roll(x, shift) + nse2 # coherence using mlab function cohxy, freqs = mlab.cohere(x, y, Fs=sfreq, NFFT=nfft) n_freqs = nfft/2 + 1 def compute_mean_psd_csd(x, y, n_epochs, nfft, sfreq): '''Computes mean of PSD and CSD for signals.''' x2 = np.array_split(x, n_epochs) y2 = np.array_split(y, n_epochs) Rxy = np.zeros((n_epochs, n_freqs), dtype=np.complex) Rxx = np.zeros((n_epochs, n_freqs), dtype=np.complex) Ryy = np.zeros((n_epochs, n_freqs), dtype=np.complex) for i in range(n_epochs): Rxy[i], freqs = mlab.csd(x2[i], y2[i], NFFT=nfft, Fs=sfreq) Rxx[i], _ = mlab.psd(x2[i], NFFT=nfft, Fs=sfreq)
def cohere(plot, *args, **kwargs): """PlotFactory Wrapper of function cohere : Plot the coherence between *x* and *y*. contrarly to matplolib.cohere, cohere return a new imgplot-like instance ready to plot result of the cohere. Different Parameters than matplotlib: data1 : first data set (can be aliased to 'x' for instance) data2 : second data set (can be aliased to 'y' for instance) So by default compute corelation of x over y direction ("y"/"x") : in wich axis the coherence is ploted, default is "y" Altered Parameters (if direction=="y") : x : alias('freqs') y : alias('cohere') freqs : frequences cohere : computed coherence ymin, ymax : set to 0, alias('cohere') (for vlines plot) data1, data2 : copy of the inputs if direction == "x" swap x's and y's the matplotlib doc is copied below Remember that this return a xyplot instance the output of spectrograph are in "cohere", "freqs" -> cohere, freqs = obj.getargs("cohere", "freqs") ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ """ plot.update(kwargs.pop(KWS,{}), **kwargs) (data1, data2, NFFT, Fs, Fc, detrend, window, noverlap, pad_to, sides, scale_by_freq)= plot.parseargs(args, "data1", "data2", "NFFT", "Fs", "Fc", "detrend", "window", "noverlap", "pad_to", "sides", "scale_by_freq", NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none, window=mlab.window_hanning, noverlap=0, pad_to=None, sides='default', scale_by_freq=None ) # index_direction, data_direction di, dd = plot._get_direction() cxy, freqs = mlab.cohere(x=data1, y=data2, NFFT=NFFT, Fs=Fs, detrend=detrend, window=window, noverlap=noverlap, scale_by_freq=scale_by_freq) freqs += Fc plot.update({di:alias('freqs'), dd:alias('cohere'), dd+"min":0, dd+"max":alias('cohere')}, min=0, max=0, lines=alias('freqs'), cohere=cxy, freqs=freqs, data1=data1, data2=data2) plot.locals.setdefault(di+"label", 'Frequency') plot.locals.setdefault(dd+"label", 'Coherence') plot.goifgo()
def coherence(self, other, fftlength=None, fftstride=None, window=None, **kwargs): """Calculate the frequency-coherence between this `TimeSeries` and another. Parameters ---------- other : `TimeSeries` `TimeSeries` signal to calculate coherence with fftlength : `float`, optional, default: `TimeSeries.duration` number of seconds in single FFT, defaults to a single FFT fftstride : `int`, optiona, default: fftlength number of seconds between FFTs, defaults to no overlap window : `timeseries.window.Window`, optional, default: `HanningWindow` window function to apply to timeseries prior to FFT, default HanningWindow of the relevant size **kwargs any other keyword arguments accepted by :func:`matplotlib.mlab.cohere` except ``NFFT``, ``window``, and ``noverlap`` which are superceded by the above keyword arguments Returns ------- coherence : :class:`~gwpy.spectrum.core.Spectrum` the coherence `Spectrum` of this `TimeSeries` with the other Notes ----- If `self` and `other` have difference :attr:`TimeSeries.sample_rate` values, the higher sampled `TimeSeries` will be down-sampled to match the lower. See Also -------- :func:`matplotlib.mlab.cohere` for details of the coherence calculator """ from ..spectrum import Spectrum # check sampling rates if self.sample_rate.to('Hertz') != other.sample_rate.to('Hertz'): sampling = min(self.sample_rate.value, other.sample_rate.value) # resample higher rate series if self.sample_rate.value == sampling: other = other.resample(sampling) self_ = self else: self_ = self.resample(sampling) else: sampling = self.sample_rate.value self_ = self # check fft lengths if fftlength is None: fftlength = self_.duration.value if fftstride is None: fftstride = fftlength fftlength = int(numpy.float64(fftlength) * self_.sample_rate.value) fftstride = int(numpy.float64(fftstride) * self_.sample_rate.value) if window is None: window = HanningWindow(fftlength) coh,f = mlab.cohere(self_.data, other.data, NFFT=fftlength, Fs=sampling, window=window, noverlap=fftlength-fftstride, **kwargs) f0 = f[0] df = f[1]-f[0] out = coh.view(Spectrum) out.f0 = f[0] out.df = (f[1] - f[0]) out.epoch = self.epoch out.name = 'Coherence between %s and %s' % (self.name, other.name) return out
def transferogram(source, target, rate=1, start_time=0., delta_time=1., sample_duration=.5, window_duration=.125, window_hop=None): ''' tfe, freqs, times, coherence = transferogram(...) Calculates a time-varying transfer function from source (x) to target (y) at intervals delta_time. Parameters: * source: source signal (reuqired) * target: target signal (required) * rate: sampling rate * start_time: starting time for tfe calculations * delta_time: distance between calculations * sample_duration: length of signals used in tfe estimates (longer than window_duration, used in averaging) * window_duration: inidvidual window length in tfe estimates * window_hop: hop between windows (defaults to window_duration/2) Returns: * tfe: transfer functions (complex matrix NxM) * freqs: frequencies corresponding to tfe estimates (array size N) * times: times corresponding to tfe estimates (array size M) * coherence: coherence matrix MxN ''' # convert time to samples sample_start = int(start_time * rate) sample_delta = int(delta_time * rate) sample_len = int(sample_duration * rate) if target is None: n_target = len(source) else: n_target = len(target) n_samples = min(len(source), n_target) sample_end = n_samples - sample_start - sample_len # windowing parameters nsamp_window = nextpow2(window_duration * rate) if window_hop: nsamp_window_hop = nextpow2(window_hop * rate) else: nsamp_window_hop = nsamp_window / 2 noverlap = nsamp_window - nsamp_window_hop resp = [] coherence = [] times = [] if target is None: for ii in np.arange(sample_start, sample_end, sample_delta): block_resp, freq = psd(source[ii:ii + sample_len], NFFT=nsamp_window, noverlap=noverlap, Fs=rate) block_coh = [] times.append((ii + sample_len / 2) / float(rate)) resp.append(block_resp) coherence.append(block_coh) else: for ii in np.arange(sample_start, sample_end, sample_delta): block_resp, freq = tfe(target[ii:ii + sample_len], source[ii:ii + sample_len], NFFT=nsamp_window, noverlap=noverlap, Fs=rate) block_coh, _ = cohere(target[ii:ii + sample_len], source[ii:ii + sample_len], NFFT=nsamp_window, noverlap=noverlap, Fs=rate) times.append((ii + sample_len / 2) / float(rate)) resp.append(block_resp) coherence.append(block_coh) return np.array(resp).T, freq, np.array(times), np.array(coherence).T
channelEnd = channelEnd[0:dataSize] print('数据点数%d\n相关分析的点数:%d' % (dataSize, cohereNFFTSize)) titleText = FILE_NAME.split('.')[0:-1] if CHANNEL_NUM < 0: #通道数如果小于0,就进行全局分析 fig = plt.figure() ax = fig.gca(projection='3d') maxCxyIndexs = [] maxCxy = [] maxFre = [] for i in range(1, colCount - 1): channelN = pressuresData.getColumnData(i)[0:dataSize] print('读取通道%d' % (i)) cxy, f = mlab.cohere(channelN, channelEnd, NFFT=cohereNFFTSize, Fs=fs, detrend='mean') ax.plot(f, np.ones(len(f)) * i, cxy) #绘制3d的相关系数 maxCxyIndexs.append(np.argmax(cxy)) maxCxy.append(cxy[maxCxyIndexs[-1]]) maxFre.append(f[maxCxyIndexs[-1]]) #标记最大 if MARK_MAX: ax.plot(maxFre, range(1, colCount - 1), maxCxy, 'o') if SHOW_AXIS_TEXT: ax.set_xlabel('frequency(Hz)') ax.set_ylabel('channel nums') ax.set_zlabel('coherence') plt.subplots_adjust(hspace=0.31) #水平间距 plt.title(titleText)
def espec2(x, y, nfft, fs): """ # ================================================================================== # # # Calcula o espectro cruzado entre duas series reais # # Dados de entrada: x = serie real 1 (potencia de 2) # y = serie real 2 (potencia de 2) # nfft - Numero de pontos utilizado para o calculo da FFT # fs - frequencia de amostragem # # Dados de saida: [aa2] - col 0: vetor de frequencia # col 1: amplitude do espectro cruzado # col 2: co-espectro # col 3: quad-espectro # col 4: espectro de fase # col 5: espectro de coerencia # col 6: intervalo de confianca inferior do espectro cruzado # col 7: intervalo de confianca superior do espectro cruzado # col 8: intervalo de confianca da coerencia # # Infos: detrend - mean # window - hanning # noverlap - 50% # # ================================================================================== # """ #cross-spectral density - welch method (complex valued) sp = mlab.csd(x, y, NFFT=nfft, Fs=fs, detrend=mlab.detrend_mean, window=mlab.window_hanning, noverlap=nfft / 2) f = sp[1][1:] sp2 = sp[0][1:] #co e quad espectro (real e imag) - verificar com parente co = np.real(sp2) qd = np.imag(sp2) #phase (angle function) ph = np.angle(sp2, deg=True) #ecoherence between x and y (0-1) coer = mlab.cohere(x, y, NFFT=nfft, Fs=fs, detrend=mlab.detrend_mean, window=mlab.window_hanning, noverlap=nfft / 2) coer = coer[0][1:] #intervalo de confianca para a amplitude do espectro cruzado - 95% ici = sp2 * 14 / 26.12 ics = sp2 * 14 / 5.63 #intervalo de confianca para coerencia icc = np.zeros(len(sp2)) icc[:] = 1 - (0.05**(1 / (14 / 2.0 - 1))) aa2 = np.array([f, sp2, co, qd, ph, coer, ici, ics, icc]).T return aa2
def PlotTransferFunction(cmd_array, val_array, labels, sample_rate, axes=None, settling_time=0.0, shutdown_time=0.0, nfft=128, detrend='mean', do_unwrap=False, min_coherence=0.0): """Compute and plot transfer functions between two arrays of time series. Args: cmd_array: Array of command (input) values. May be multi-dimensional. val_array: Array of measured (output) values. Same dimensions as cmd_array. labels: Array of strings to use as legend labels. sample_rate: Sample rate in Hz. axes: Array of three axes for plotting, or None to create axes. settling_time: Duration of start of timeseries to ignore. shutdown_time: Duration of end of timeseries to ignore. nfft: Number of points at which to compute the Fourier transform. detrend: Detrend method: 'none', 'mean', or 'linear'. do_unwrap: Boolean specifying whether phase should be unwrapped. min_coherence: Minimum coherence required to include data points in plots. Returns: Array of axes containing resulting plots. Vector of frequencies at which transfer function was computed. Transfer function data. Coherence data. """ assert cmd_array.shape == val_array.shape assert cmd_array.shape[1] == len(labels) assert sample_rate > 0.0 if axes is None: axes = MakeAxes() # Common keyword arguments to Welch's method functions. psd_kwargs = { 'Fs': sample_rate, 'NFFT': nfft, 'detrend': { 'none': mlab.detrend_none, 'mean': mlab.detrend_mean, 'linear': mlab.detrend_linear }[detrend], 'window': mlab.window_hanning } for i in range(cmd_array.shape[1]): settling_samples = np.round(sample_rate * settling_time) shutdown_samples = np.round(sample_rate * shutdown_time) assert settling_samples + shutdown_samples < val_array.shape[0] selected = slice(settling_samples if settling_samples > 0 else None, -shutdown_samples if shutdown_samples > 0 else None) val = np.array(val_array[selected, i]) cmd = np.array(cmd_array[selected, i]) txy, f = EstimateTransferFunction(cmd, val, **psd_kwargs) coh, _ = mlab.cohere(cmd, val, **psd_kwargs) AddTransferFunctionToPlot(axes, f, txy, coh, '-', labels[i], do_unwrap=do_unwrap, min_coherence=min_coherence) return axes, f, txy, coh
sfreq, duration = 1000., 1000 times = np.arange(0, duration, 1 / sfreq) amp, amp2, nse_amp = 1., 1., 0.5 nfft = 512 nse1 = np.random.rand(times.size) * nse_amp nse2 = np.random.rand(times.size) * nse_amp x = amp * np.sin(2 * np.pi * 200 * times) + nse1 y = amp * np.sin(2 * np.pi * 200 * times + np.pi / 5) + nse2 shift = 100 # integer assert shift < sfreq * duration, 'Choose a smaller shift.' #y = amp2 * np.roll(x, shift) + nse2 # coherence using mlab function cohxy, freqs = mlab.cohere(x, y, Fs=sfreq, NFFT=nfft) n_freqs = int(nfft / 2 + 1) def compute_mean_psd_csd(x, y, n_epochs, nfft, sfreq): '''Computes mean of PSD and CSD for signals.''' x2 = np.array_split(x, n_epochs) y2 = np.array_split(y, n_epochs) Rxy = np.zeros((n_epochs, n_freqs), dtype=np.complex) Rxx = np.zeros((n_epochs, n_freqs), dtype=np.complex) Ryy = np.zeros((n_epochs, n_freqs), dtype=np.complex) for i in range(n_epochs): Rxy[i], freqs = mlab.csd(x2[i], y2[i], NFFT=nfft, Fs=sfreq)
def calc(cls, st, window_length=1000): """ Calculate coherences between channels of a data stream TO REMOVE PART COHERENT WITH ANOTHER CHANNEL, WILL HAVE TO DO WELCH MYSELF (MUST APPLY REMOVAL AT THE LEVEL OF EACH FFT) :type st: :class:`~obspy.core.stream.Stream` :param tr: Stream to be processed :type window_length: `numeric` :param window_length: minimum FFT window length in seconds :returns: list of dictionaries containing freqs, data, units, name """ cohers = [] for i in range(len(st) - 1): for j in range(i + 1, len(st)): # print(i,j) tr_i = st[i] tr_j = st[j] tr_i.data = tr_i.data.astype(np.float64) tr_j.data = tr_j.data.astype(np.float64) # Verify that channels are compatible (same sampling rate, # length and starttime) tmp = 'Channels {:d} and {:d}'.format(i, j) if tr_i.stats.sampling_rate != tr_j.stats.sampling_rate: warnings.warn(tmp + 'have different samp rates') cohers.append([]) continue sampling_rate = tr_i.stats.sampling_rate if len(tr_i.data) != len(tr_j.data): warnings.warn(tmp + 'have different lengths') cohers.append([]) continue data_samples = len(tr_i.data) if abs(tr_i.stats.starttime - tr_j.stats.starttime) >\ 1 / sampling_rate: warnings.warn('tmp + ' + 'are offset by > one sample') cohers.append([]) continue starttime = tr_i.stats.starttime # Calculate Coherence nfft = 2**(m.ceil(m.log2(window_length * sampling_rate))) nlap = int(0.75 * nfft) if spect_library == 'mlab': # MLAB GIVES STRANGE ANSWER Cxy, _freq = mlab.cohere(tr_i.data, tr_j.data, nfft, sampling_rate, detrend=mlab.detrend_linear, window=_fft_taper, noverlap=nlap, sides='onesided', scale_by_freq=False) # SCIPY GIVES SIMILAR ANSWER TO MATLAB elif spect_library == 'scipy': _freq, Cxy = ssig.coherence( tr_i.data, tr_j.data, sampling_rate, # window=_fft_taper, nperseg=nfft, detrend="linear", noverlap=nlap) else: warnings.warn( 'Unknown spectra library: "{}"'.format(spect_library)) return False nW = 1 + np.floor((data_samples - nfft) / nlap) csl = np.sqrt(2. / nW) # coherency 95% significance level # Make dictionary, leaving out first freq/Cxy entry (offset) cohers.append(Coherence(Cxy[1:], (i, j))) return cls(_freq[1:], cohers, nW, csl, starttime, starttime + data_samples / sampling_rate, [s.stats for s in st])
def coherence(t, data1, data2): dt = (t[1] - t[0]) cxy, f = cohere(data1, data2, 256, Fs=1. / dt) return cxy, f
dataSize = 8192 if 8192 < len(channelEnd) else len(channelEnd)#数据长度 cohereNFFTSize = 512 if int(dataSize/20)>512 else int(dataSize/20)#相关分析进行频谱的阶段长度 channelEnd = channelEnd[0:dataSize] print('数据点数%d\n相关分析的点数:%d'%(dataSize,cohereNFFTSize)) titleText = FILE_NAME.split('.')[0:-1] if CHANNEL_NUM<0:#通道数如果小于0,就进行全局分析 fig = plt.figure() ax = fig.gca(projection='3d') maxCxyIndexs = [] maxCxy = [] maxFre = [] for i in range(1,colCount-1): channelN = pressuresData.getColumnData(i)[0:dataSize] print('读取通道%d'%(i)) cxy,f = mlab.cohere(channelN,channelEnd,NFFT = cohereNFFTSize,Fs = fs,detrend='mean') ax.plot(f,np.ones(len(f))*i,cxy)#绘制3d的相关系数 maxCxyIndexs.append( np.argmax(cxy) ) maxCxy.append(cxy[maxCxyIndexs[-1]]) maxFre.append(f[maxCxyIndexs[-1]]) #标记最大 if MARK_MAX: ax.plot(maxFre,range(1,colCount-1),maxCxy,'o') if SHOW_AXIS_TEXT: ax.set_xlabel('frequency(Hz)') ax.set_ylabel('channel nums') ax.set_zlabel('coherence') plt.subplots_adjust(hspace=0.31)#水平间距 plt.title(titleText) else:#对特定通道进行分析 channelN = pressuresData.getColumnData(CHANNEL_NUM)[0:dataSize]
y = t[2, :] # subtract mean x = x - np.mean(x) y = y - np.mean(y) # set spectrogram parameters nfft = 2**14 params = {'NFFT': nfft, 'noverlap': nfft / 2} # calc spectra Pxx, _ = ml.psd(x, Fs=sr, **params) Pyy, _ = ml.psd(y, Fs=sr, **params) Pxy, _ = ml.csd(x, y, Fs=sr, **params) Pyx, _ = ml.csd(y, x, Fs=sr, **params) Cxy, f = ml.cohere(x, y, Fs=sr, **params) Pxxs.append(np.absolute(Pxx)) Pyys.append(np.absolute(Pyy)) Pxys.append(np.absolute(Pxy)) Pyxs.append(np.absolute(Pyx)) Cxys.append(np.absolute(Cxy)) freqs = f # calculate mean Pxx = np.mean(Pxxs, axis=0) Pyy = np.mean(Pyys, axis=0) Pxy = np.mean(Pxys, axis=0) Pyx = np.mean(Pyxs, axis=0) Cxy_or = np.mean(Cxys, axis=0)