def test_get_spectra_unknown_method(): """ Test that providing an unknown method to get_spectra rasies a ValueError """ tseries = np.array([[1, 2, 3], [4, 5, 6]]) with pytest.raises(ValueError) as e_info: tsa.get_spectra(tseries, method=dict(this_method='foo'))
def spectrum(self): """ The spectra of each of the channels and cross-spectra between different channles in the input TimeSeries object """ f, spectrum = tsa.get_spectra(self.input.data, method=self.method) return spectrum
def test_get_spectra(): """ Testing spectral estimation """ methods = (None, {"this_method": 'welch', "NFFT": 256, "Fs": 2 * np.pi}, {"this_method": 'welch', "NFFT": 1024, "Fs": 2 * np.pi}) for method in methods: avg_pwr1 = [] avg_pwr2 = [] est_pwr1 = [] est_pwr2 = [] arsig1, _, _ = utils.ar_generator(N=2 ** 16) # It needs to be that long for # the answers to converge arsig2, _, _ = utils.ar_generator(N=2 ** 16) avg_pwr1.append((arsig1 ** 2).mean()) avg_pwr2.append((arsig2 ** 2).mean()) tseries = np.vstack([arsig1,arsig2]) f, c = tsa.get_spectra(tseries,method=method) # \sum_{\omega} psd d\omega: est_pwr1.append(np.sum(c[0, 0]) * (f[1] - f[0])) est_pwr2.append(np.sum(c[1, 1]) * (f[1] - f[0])) # Get it right within the order of magnitude: npt.assert_array_almost_equal(est_pwr1, avg_pwr1, decimal=-1) npt.assert_array_almost_equal(est_pwr2, avg_pwr2, decimal=-1)
def test_get_spectra(): """Testing get_spectra""" t = np.linspace(0,16*np.pi,2**14) x = np.sin(t) + np.sin(2*t) + np.sin(3*t) + 0.1 *np.random.rand(t.shape[-1]) x = np.reshape(x,(2,x.shape[-1]/2)) N = x.shape[-1] #Make sure you get back the expected shape for different spectra: NFFT = 64 f_mlab=tsa.get_spectra(x,method={'this_method':'mlab','NFFT':NFFT}) f_periodogram=tsa.get_spectra(x,method={'this_method':'periodogram_csd'}) f_multi_taper=tsa.get_spectra(x,method={'this_method':'multi_taper_csd'}) npt.assert_equal(f_mlab[0].shape[0],NFFT/2+1) npt.assert_equal(f_periodogram[0].shape[0],N/2+1) npt.assert_equal(f_multi_taper[0].shape[0],N/2+1)
def test_cached_coherence(): """Testing the cached coherence functions """ NFFT = 64 # This is the default behavior n_freqs = NFFT // 2 + 1 ij = [(0, 1), (1, 0)] ts = np.loadtxt(os.path.join(test_dir_path, 'tseries12.txt')) freqs, cache = tsa.cache_fft(ts, ij) # Are the frequencies the right ones? npt.assert_equal(freqs, utils.get_freqs(2 * np.pi, NFFT)) # Check that the fft of the first window is what we expect: hann = mlab.window_hanning(np.ones(NFFT)) w_ts = ts[0][:NFFT] * hann w_ft = fftpack.fft(w_ts)[0:n_freqs] # This is the result of the function: first_window_fft = cache['FFT_slices'][0][0] npt.assert_equal(w_ft, first_window_fft) coh_cached = tsa.cache_to_coherency(cache, ij)[0, 1] f, c = tsa.coherency(ts) coh_direct = c[0, 1] npt.assert_almost_equal(coh_direct, coh_cached) # Only welch PSD works and an error is thrown otherwise. This tests that # the error is thrown: with pytest.raises(ValueError) as e_info: tsa.cache_fft(ts, ij, method=methods[2]) # Take the method in which the window is defined on input: freqs, cache1 = tsa.cache_fft(ts, ij, method=methods[3]) # And compare it to the method in which it isn't: freqs, cache2 = tsa.cache_fft(ts, ij, method=methods[4]) npt.assert_equal(cache1, cache2) # Do the same, while setting scale_by_freq to False: freqs, cache1 = tsa.cache_fft(ts, ij, method=methods[3], scale_by_freq=False) freqs, cache2 = tsa.cache_fft(ts, ij, method=methods[4], scale_by_freq=False) npt.assert_equal(cache1, cache2) # Test cache_to_psd: psd1 = tsa.cache_to_psd(cache, ij)[0] # Against the standard get_spectra: f, c = tsa.get_spectra(ts) psd2 = c[0][0] npt.assert_almost_equal(psd1, psd2) # Test that prefer_speed_over_memory doesn't change anything: freqs, cache1 = tsa.cache_fft(ts, ij) freqs, cache2 = tsa.cache_fft(ts, ij, prefer_speed_over_memory=True) psd1 = tsa.cache_to_psd(cache1, ij)[0] psd2 = tsa.cache_to_psd(cache2, ij)[0] npt.assert_almost_equal(psd1, psd2)
def frequencies(self): """The spectrum and cross-spectra, computed using mlab csd """ self.mlab_method = self.method self.mlab_method['this_method'] = 'mlab' self.mlab_method['Fs'] = self.sampling_rate f,spectrum_mlab = tsa.get_spectra(self.data,method=self.mlab_method) return f
def frequencies(self): """ The central frequencies in the bands """ #XXX Use NFFT in the method in order to calculate these, without having #to calculate the spectrum: f, spectrum = tsa.get_spectra(self.input.data, method=self.method) return f
def spectrum_multi_taper(self): """The spectrum and cross-spectra, computed using multi-tapered csd """ self.multi_taper_method = np.copy(self.method) self.multi_taper_method['this_method'] = 'multi_taper_csd' self.multi_taper_method['Fs'] = self.sampling_rate f,spectrum_multi_taper = tsa.get_spectra(self.data, method=self.multi_taper_method) return spectrum_multi_taper
def spectrum_multi_taper(self): """The spectrum and cross-spectra, computed using multi-tapered csd """ data = self.input.data sampling_rate = self.input.sampling_rate self.multi_taper_method = self.method self.multi_taper_method['this_method'] = 'multi_taper_csd' self.multi_taper_method['Fs'] = sampling_rate f,spectrum_multi_taper = tsa.get_spectra(data, method=self.multi_taper_method) return f,spectrum_multi_taper
def output(self): """The standard output for this analyzer is the spectrum and cross-spectra, computed using mlab csd""" data = self.input.data sampling_rate = self.input.sampling_rate self.mlab_method = self.method self.mlab_method['this_method'] = 'mlab' self.mlab_method['Fs'] = sampling_rate f,spectrum_mlab = tsa.get_spectra(data,method=self.mlab_method) return f,spectrum_mlab
def test_get_spectra(): """Testing get_spectra""" t = np.linspace(0,16*np.pi,2**10) x = np.sin(t) + np.sin(2*t) + np.sin(3*t) + 0.1 *np.random.rand(t.shape[-1]) #First test for 1-d data: NFFT = 64 N = x.shape[-1] f_welch=tsa.get_spectra(x,method={'this_method':'welch','NFFT':NFFT}) f_periodogram=tsa.get_spectra(x,method={'this_method':'periodogram_csd'}) f_multi_taper=tsa.get_spectra(x,method={'this_method':'multi_taper_csd'}) npt.assert_equal(f_welch[0].shape,(NFFT/2+1,)) npt.assert_equal(f_periodogram[0].shape,(N/2+1,)) npt.assert_equal(f_multi_taper[0].shape,(N/2+1,)) #Test for multi-channel data x = np.reshape(x,(2,x.shape[-1]/2)) N = x.shape[-1] #Make sure you get back the expected shape for different spectra: NFFT = 64 f_welch=tsa.get_spectra(x,method={'this_method':'welch','NFFT':NFFT}) f_periodogram=tsa.get_spectra(x,method={'this_method':'periodogram_csd'}) f_multi_taper=tsa.get_spectra(x,method={'this_method':'multi_taper_csd'}) npt.assert_equal(f_welch[0].shape[0],NFFT/2+1) npt.assert_equal(f_periodogram[0].shape[0],N/2+1) npt.assert_equal(f_multi_taper[0].shape[0],N/2+1)
def test_get_spectra(): """Testing get_spectra""" t = np.linspace(0, 16 * np.pi, 2**10) x = (np.sin(t) + np.sin(2 * t) + np.sin(3 * t) + 0.1 * np.random.rand(t.shape[-1])) #First test for 1-d data: NFFT = 64 N = x.shape[-1] f_welch = tsa.get_spectra(x, method={'this_method': 'welch', 'NFFT': NFFT}) f_periodogram = tsa.get_spectra(x, method={'this_method': 'periodogram_csd'}) f_multi_taper = tsa.get_spectra(x, method={'this_method': 'multi_taper_csd'}) npt.assert_equal(f_welch[0].shape, (NFFT // 2 + 1, )) npt.assert_equal(f_periodogram[0].shape, (N // 2 + 1, )) npt.assert_equal(f_multi_taper[0].shape, (N // 2 + 1, )) #Test for multi-channel data x = np.reshape(x, (2, x.shape[-1] // 2)) N = x.shape[-1] #Make sure you get back the expected shape for different spectra: NFFT = 64 f_welch = tsa.get_spectra(x, method={'this_method': 'welch', 'NFFT': NFFT}) f_periodogram = tsa.get_spectra(x, method={'this_method': 'periodogram_csd'}) f_multi_taper = tsa.get_spectra(x, method={'this_method': 'multi_taper_csd'}) npt.assert_equal(f_welch[0].shape[0], NFFT / 2 + 1) npt.assert_equal(f_periodogram[0].shape[0], N / 2 + 1) npt.assert_equal(f_multi_taper[0].shape[0], N / 2 + 1)
def output(self): """ The standard output for this analyzer is a tuple f,s, where: f is the frequency bands associated with the discrete spectral components and s is the PSD calculated using :func:`mlab.psd`. """ data = self.input.data sampling_rate = self.input.sampling_rate self.mlab_method = self.method self.mlab_method['this_method'] = 'mlab' self.mlab_method['Fs'] = sampling_rate f,spectrum_mlab = tsa.get_spectra(data,method=self.mlab_method) return f,spectrum_mlab
def test_get_spectra_complex(): """ Testing spectral estimation """ methods = (None, { "this_method": 'welch', "NFFT": 256, "Fs": 2 * np.pi }, { "this_method": 'welch', "NFFT": 1024, "Fs": 2 * np.pi }) for method in methods: avg_pwr1 = [] avg_pwr2 = [] est_pwr1 = [] est_pwr2 = [] # Make complex signals: r, _, _ = utils.ar_generator(N=2**16) # It needs to be that long for # the answers to converge c, _, _ = utils.ar_generator(N=2**16) arsig1 = r + c * scipy.sqrt(-1) r, _, _ = utils.ar_generator(N=2**16) c, _, _ = utils.ar_generator(N=2**16) arsig2 = r + c * scipy.sqrt(-1) avg_pwr1.append((arsig1 * arsig1.conjugate()).mean()) avg_pwr2.append((arsig2 * arsig2.conjugate()).mean()) tseries = np.vstack([arsig1, arsig2]) f, c = tsa.get_spectra(tseries, method=method) # \sum_{\omega} psd d\omega: est_pwr1.append(np.sum(c[0, 0]) * (f[1] - f[0])) est_pwr2.append(np.sum(c[1, 1]) * (f[1] - f[0])) # Get it right within the order of magnitude: npt.assert_array_almost_equal(est_pwr1, avg_pwr1, decimal=-1) npt.assert_array_almost_equal(est_pwr2, avg_pwr2, decimal=-1)
def cpsd(self): """ This outputs both the PSD and the CSD calculated using :func:`algorithms.get_spectra`. Returns ------- (f,s): tuple f: Frequency bands over which the psd/csd are calculated and s: the n by n by len(f) matrix of PSD (on the main diagonal) and CSD (off diagonal) """ self.welch_method = self.method self.welch_method["this_method"] = "welch" self.welch_method["Fs"] = self.input.sampling_rate f, spectrum_welch = tsa.get_spectra(self.input.data, method=self.welch_method) return f, spectrum_welch
def spectrum_multi_taper(self): """ The spectrum and cross-spectra, computed using :func:`multi_taper_csd' XXX This method needs to be improved to include a clever way of figuring out how many tapers to generate and a way to extract the estimate of error based on the tapers. """ data = self.input.data sampling_rate = self.input.sampling_rate self.multi_taper_method = self.method self.multi_taper_method['this_method'] = 'multi_taper_csd' self.multi_taper_method['Fs'] = sampling_rate f,spectrum_multi_taper = tsa.get_spectra(data, method=self.multi_taper_method) return f,spectrum_multi_taper
def cpsd(self): """ This outputs both the PSD and the CSD calculated using :func:`algorithms.get_spectra`. Returns ------- (f,s): tuple f: Frequency bands over which the psd/csd are calculated and s: the n by n by len(f) matrix of PSD (on the main diagonal) and CSD (off diagonal) """ self.welch_method = self.method self.welch_method['this_method'] = 'welch' self.welch_method['Fs'] = self.input.sampling_rate f, spectrum_welch = tsa.get_spectra(self.input.data, method=self.welch_method) return f, spectrum_welch
fig03 = plot_spectral_estimate(freqs, psd, (d_psd,), elabels=("Periodogram",)) """ .. image:: fig/multi_taper_spectral_estimation_03.png Next, we use Welch's periodogram, by applying :func:`tsa.get_spectra`. Note that we explicitely provide the function with a 'method' dict, which specifies the method used in order to calculate the PSD, but the default method is 'welch'. """ welch_freqs, welch_psd = tsa.get_spectra(ar_seq, method=dict(this_method='welch',NFFT=N)) welch_freqs *= (np.pi/welch_freqs.max()) welch_psd = welch_psd.squeeze() dB(welch_psd, welch_psd) fig04 = plot_spectral_estimate(freqs, psd, (welch_psd,), elabels=("Welch",)) """ .. image:: fig/multi_taper_spectral_estimation_04.png Next, we use the multi-taper estimation method. We estimate the spectrum: """
def frequencies(self): f,spectrum = tsa.get_spectra(self.input.data,method=self.method) return f
def spectrum(self): f,spectrum = tsa.get_spectra(self.input.data,method=self.method) return spectrum
fig03 = plot_spectral_estimate(freqs, psd, (d_psd, ), elabels=("Periodogram", )) """ .. image:: fig/multi_taper_spectral_estimation_03.png Next, we use Welch's periodogram, by applying :func:`tsa.get_spectra`. Note that we explicitly provide the function with a 'method' dict, which specifies the method used in order to calculate the PSD, but the default method is 'welch'. """ welch_freqs, welch_psd = tsa.get_spectra(ar_seq, method=dict(this_method='welch', NFFT=N)) welch_freqs *= (np.pi / welch_freqs.max()) welch_psd = welch_psd.squeeze() dB(welch_psd, welch_psd) fig04 = plot_spectral_estimate(freqs, psd, (welch_psd, ), elabels=("Welch", )) """ .. image:: fig/multi_taper_spectral_estimation_04.png Next, we use the multitaper estimation method. We estimate the spectrum: """ f, psd_mt, nu = tsa.multi_taper_psd(ar_seq, adaptive=False, jackknife=False)