def autoregressiveSpectrogram(data, window=2.0, overlap=1.0, frequency_resolution=0.5, fs=100, order=50): configuration = {"Window": window, "Overlap": overlap} window = int(window * fs) overlap = int(overlap * fs) NFFT = int(fs / frequency_resolution) epochs = getIndices(len(data), window, overlap) frequency = np.array( pyule(np.array(1), order, NFFT=NFFT, sampling=fs).frequencies()) spectrum = np.ndarray((len(frequency), len(epochs))) for index in range(len(epochs)): p = pyule(data[epochs[index]:epochs[index] + window], order, NFFT=NFFT, sampling=fs) spectrum[:, index] = p.psd time = (epochs + window) / fs return dict({ "Time": time, "Frequency": frequency, "Power": spectrum, "logPower": 10 * np.log10(spectrum), "Config": configuration })
def create_all_psd(): f = pylab.linspace(0, 1, 4096) pylab.figure(figsize=(12,8)) # MA model p = spectrum.pma(xx, 64,128); p(); p.plot() """ #ARMA 15 order a, b, rho = spectrum.arma_estimate(data, 15,15, 30) psd = spectrum.arma2psd(A=a,B=b, rho=rho) newpsd = tools.cshift(psd, len(psd)//2) # switch positive and negative freq pylab.plot(f, 10 * pylab.log10(newpsd/max(newpsd)), label='ARMA 15,15') """ # YULE WALKER p = spectrum.pyule(xx, 7 , NFFT=4096, scale_by_freq=False); p.plot() # equivalent to # plot([x for x in p.frequencies()] , 10*log10(p.psd)); grid(True) #burg method p = spectrum.pburg(xx, 7, scale_by_freq=False); p.plot() #pcovar p = spectrum.pcovar(xx, 7, scale_by_freq=False); p.plot() #pmodcovar p = spectrum.pmodcovar(xx, 7, scale_by_freq=False); p.plot() # correlogram p = spectrum.pcorrelogram(xx, lag=60, NFFT=512, scale_by_freq=False); p.plot() # minvar p = spectrum.pminvar(xx, 7, NFFT=256, scale_by_freq=False); p.plot() # pmusic p = spectrum.pmusic(xx, 10,4, scale_by_freq=False); p.plot() # pmusic p = spectrum.pev(xx, 10, 4, scale_by_freq=False); p.plot() # periodogram p = spectrum.Periodogram(xx, scale_by_freq=False); p.plot() # legend( ["MA 32", "pyule 7", "pburg 7", "pcovar", "pmodcovar", "correlogram", "minvar", "pmusic", "pev", "periodgram"]) pylab.ylim([-80,80])
def apply_(self, d): S = self.noise_filter.apply_(d).data[:, -self.noise_filter.nsamples:, :] nchannels, nsamples, ntrials = S.shape data = np.zeros((self.nfrequencies, d.ninstances)) for trial in range(ntrials): P = np.zeros((self.nharmonics, nchannels, self.nfrequencies)) for freq in range(self.nfrequencies): for ch in range(nchannels): for harm in range(self.nharmonics): P[harm,ch,freq] = np.linalg.norm(S[ch,:,trial].dot(self.data[...,harm,freq])) P = P**2 tildeS = S[...,trial].dot(self.noise_filter.SSVEPRemovalMatrix) Pxx = np.zeros((np.ceil((nsamples+1)/2.0), nchannels)) nPxxRows = Pxx.shape[0] for ch in range(nchannels): p = spectrum.pyule(tildeS[ch,:], self.ar_order, NFFT=nsamples) p() Pxx[:,ch] = p.psd sigma = np.zeros((self.nharmonics, nchannels, self.nfrequencies)) div = self.sample_rate / float(nsamples) for f, freq in enumerate(self.frequencies): for ch in range(nchannels): for h, harm in enumerate(self.harmonics): ind = round(freq * harm / div) sigma[h,ch,f] = np.mean(Pxx[max(0,ind-1):min(ind+2, nPxxRows-1),ch]) SNRs = np.reshape(P / sigma, (self.nharmonics*nchannels, self.nfrequencies)) nSNRs = SNRs.shape[0] if self.weights is None: self.weights = np.ones(nSNRs) / float(nSNRs) else: if len(self.weights) > nSNRs: self.weights = self.weights[:nSNRs] elif len(self.weights) < nSNRs: raise ValueError('inconsistent weight vector size') data[:,trial] = self.weights.dot(SNRs) feat_lab = ['%d Hz' % f for f in self.frequencies] return DataSet(data=data, feat_lab=feat_lab, default=d)
def create_all_psd(): f = pylab.linspace(0, 1, 4096) pylab.figure(figsize=(12, 8)) # MA model p = spectrum.pma(xx, 64, 128) p() p.plot() """ #ARMA 15 order a, b, rho = spectrum.arma_estimate(data, 15,15, 30) psd = spectrum.arma2psd(A=a,B=b, rho=rho) newpsd = tools.cshift(psd, len(psd)//2) # switch positive and negative freq pylab.plot(f, 10 * pylab.log10(newpsd/max(newpsd)), label='ARMA 15,15') """ # YULE WALKER p = spectrum.pyule(xx, 7, NFFT=4096, scale_by_freq=False) p.plot() # equivalent to # plot([x for x in p.frequencies()] , 10*log10(p.psd)); grid(True) #burg method p = spectrum.pburg(xx, 7, scale_by_freq=False) p.plot() #pcovar p = spectrum.pcovar(xx, 7, scale_by_freq=False) p.plot() #pmodcovar p = spectrum.pmodcovar(xx, 7, scale_by_freq=False) p.plot() # correlogram p = spectrum.pcorrelogram(xx, lag=60, NFFT=512, scale_by_freq=False) p.plot() # minvar p = spectrum.pminvar(xx, 7, NFFT=256, scale_by_freq=False) p.plot() # pmusic p = spectrum.pmusic(xx, 10, 4, scale_by_freq=False) p.plot() # pmusic p = spectrum.pev(xx, 10, 4, scale_by_freq=False) p.plot() # periodogram p = spectrum.Periodogram(xx, scale_by_freq=False) p.plot() # legend([ "MA 32", "pyule 7", "pburg 7", "pcovar", "pmodcovar", "correlogram", "minvar", "pmusic", "pev", "periodgram" ]) pylab.ylim([-80, 80])
def ar_psd(nni=None, rpeaks=None, fbands=None, nfft=2**12, order=16, show=True, show_param=True, legend=True, mode='normal'): """Computes a Power Spectral Density (PSD) estimation from the NNI series using the Autoregressive method and computes all frequency domain parameters from this PSD according to the specified frequency bands. References: [Electrophysiology1996], [Kuusela2014], [Kallas2012], [Boardman2002] (additionally recommended: [Miranda2012]) Docs: https://pyhrv.readthedocs.io/en/latest/_pages/api/frequency.html#autoregressive-method-ar-psd Parameters ---------- rpeaks : array R-peak locations in [ms] or [s] nni : array NN-Intervals in [ms] or [s] fbands : dict, optional Dictionary with frequency bands (2-element tuples or list) Value format: (lower_freq_band_boundary, upper_freq_band_boundary) Keys: 'ulf' Ultra low frequency (default: none) optional 'vlf' Very low frequency (default: (0.003Hz, 0.04Hz)) 'lf' Low frequency (default: (0.04Hz - 0.15Hz)) 'hf' High frequency (default: (0.15Hz - 0.4Hz))´ nfft : int, optional Number of points computed for the entire AR result (default: 2**12) order : int, optional Autoregressive model order (default: 16) show : bool, optional If true, show PSD plot (default: True) show_param : bool, optional If true, list all computed PSD parameters next to the plot (default: True) legend : bool, optional If true, add a legend with frequency bands to the plot (default: True) Returns ------- results : biosppy.utils.ReturnTuple object All results of the Autoregressive PSD estimation (see list and keys below) Returned Parameters & Keys -------------------------- .. Peak frequencies of all frequency bands in [Hz] (key: 'ar_peak') .. Absolute powers of all frequency bands in [ms^2][(key: 'ar_abs') .. Relative powers of all frequency bands [%] (key: 'ar_rel') .. Logarithmic powers of all frequency bands [-] (key: 'ar_log') .. Normalized powers of all frequency bands [-] (key: 'ar_norms') .. LF/HF ratio [-] (key: 'ar_ratio') .. Total power over all frequency bands in [ms^2] (key: 'ar_total') .. Interpolation method (key: 'ar_interpolation') .. Resampling frequency (key: 'ar_resampling_frequency') .. AR model order (key: 'ar_order') .. Number of PSD samples (key: 'ar_nfft') Notes ----- .. The returned BioSPPy ReturnTuple object contains all frequency band parameters in parameter specific tuples of length 4 when using the ULF frequency band or of length 3 when NOT using the ULF frequency band. The structures of those tuples are shown in this example below (lomb_results = ReturnTuple object returned by this function): Using ULF, VLF, LF and HF frequency bands: lomb['ar_peak'] = (ulf_peak, vlf_peak, lf_peak, hf_peak) Using VLF, LF and HF frequency bands: lomb['ar_peak'] = (vlf_peak, lf_peak, hf_peak) .. If 'show_param' is true, the parameters (incl. frequency band limits) will be listed next to the graph and no legend with frequency band limits will be added to the plot graph itself, i.e. the effect of 'show_param' will be used over the 'legend' effect. .. Only one type of input data is required. .. If both 'nni' and 'rpeaks' are provided, 'rpeaks' will be chosen over the 'nni' and the 'nni' data will be computed from the 'rpeaks'. .. NN and R-peak series provided in [s] format will be converted to [ms] format. """ # Check input nn = tools.check_input(nni, rpeaks) # Verify or set default frequency bands fbands = _check_freq_bands(fbands) # Resampling (with 4Hz) and interpolate # Because RRi are unevenly spaced we must interpolate it for accurate PSD estimation. fs = 4 t = np.cumsum(nn) t -= t[0] f_interpol = sp.interpolate.interp1d(t, nn, 'cubic') t_interpol = np.arange(t[0], t[-1], 1000./fs) nn_interpol = f_interpol(t_interpol) # Compute autoregressive PSD ar = spectrum.pyule(data=nn_interpol, order=order, NFFT=nfft, sampling=fs, scale_by_freq=False) ar() # Get frequencies and powers frequencies = np.asarray(ar.frequencies()) psd = np.asarray(ar.psd) powers = np.asarray(10 * np.log10(psd) * 10**3) # * 10**3 to compensate with ms^2 to s^2 conversion # in the upcoming steps # Define metadata meta = utils.ReturnTuple((nfft, order, fs, 'cubic'), ('ar_nfft', 'ar_order', 'ar_resampling_frequency', 'ar_interpolation')) if mode not in ['normal', 'dev', 'devplot']: warnings.warn("Unknown mode '%s'. Will proceed with 'normal' mode." % mode, stacklevel=2) mode = 'normal' # Normal Mode: # Returns frequency parameters, PSD plot figure and no frequency & power series/arrays if mode == 'normal': # Compute frequency parameters params, freq_i = _compute_parameters('ar', frequencies, powers, fbands) # Plot PSD figure = _plot_psd('ar', frequencies, powers, freq_i, params, show, show_param, legend) figure = utils.ReturnTuple((figure, ), ('ar_plot', )) # Complete output return tools.join_tuples(params, figure) # Dev Mode: # Returns frequency parameters and frequency & power series/array; does not create a plot figure nor plot the data elif mode == 'dev': # Compute frequency parameters params, _ = _compute_parameters('ar', frequencies, powers, fbands) # Output return tools.join_tuples(params, meta), frequencies, (powers / 10 ** 6) # Devplot Mode: # Returns frequency parameters, PSD plot figure, and frequency & power series/arrays elif mode == 'devplot': # Compute frequency parameters params, freq_i = _compute_parameters('ar', frequencies, powers, fbands) # Plot PSD figure = _plot_psd('ar', frequencies, powers, freq_i, params, show, show_param, legend) figure = utils.ReturnTuple((figure, ), ('ar_plot', )) # Complete output return tools.join_tuples(params, figure, meta), frequencies, (powers / 10 ** 6)
def ar_psd(self, nni=None, rpeaks=None, fbands=None, nfft=2**12, order=16, show=True, show_param=True, legend=True, mode='normal'): # Check input nn = tools.check_input(nni, rpeaks) # Verify or set default frequency bands fbands = self._check_freq_bands(fbands) # Resampling (with 4Hz) and interpolate # Because RRi are unevenly spaced we must interpolate it for accurate PSD estimation. fs = 4 t = np.cumsum(nn) t -= t[0] f_interpol = sp.interpolate.interp1d(t, nn, 'cubic') t_interpol = np.arange(t[0], t[-1], 1000. / fs) nn_interpol = f_interpol(t_interpol) # Compute autoregressive PSD ar = spectrum.pyule(data=nn_interpol, order=order, NFFT=nfft, sampling=fs, scale_by_freq=False) ar() # Get frequencies and powers frequencies = np.asarray(ar.frequencies()) psd = np.asarray(ar.psd) powers = np.asarray( 10 * np.log10(psd) * 10**3) # * 10**3 to compensate with ms^2 to s^2 conversion # in the upcoming steps # Define metadata meta = utils.ReturnTuple( (nfft, order, fs, 'cubic'), ('ar_nfft', 'ar_order', 'ar_resampling_frequency', 'ar_interpolation')) if mode not in ['normal', 'dev', 'devplot']: warnings.warn( "Unknown mode '%s'. Will proceed with 'normal' mode." % mode, stacklevel=2) mode = 'normal' # Normal Mode: # Returns frequency parameters, PSD plot figure and no frequency & power series/arrays if mode == 'normal': # Compute frequency parameters params, freq_i = self._compute_parameters('ar', frequencies, powers, fbands) # Plot PSD figure = self._plot_psd('ar', frequencies, powers, freq_i, params, show, show_param, legend) figure = utils.ReturnTuple((figure, ), ('ar_plot', )) # Complete output return tools.join_tuples(params, figure) # Dev Mode: # Returns frequency parameters and frequency & power series/array; does not create a plot figure nor plot the data elif mode == 'dev': # Compute frequency parameters params, _ = self._compute_parameters('ar', frequencies, powers, fbands) # Output return tools.join_tuples(params, meta), frequencies, (powers / 10**6) # Devplot Mode: # Returns frequency parameters, PSD plot figure, and frequency & power series/arrays elif mode == 'devplot': # Compute frequency parameters params, freq_i = self._compute_parameters('ar', frequencies, powers, fbands) # Plot PSD figure = self._plot_psd('ar', frequencies, powers, freq_i, params, show, show_param, legend) figure = utils.ReturnTuple((figure, ), ('ar_plot', )) # Complete output return tools.join_tuples(params, figure, meta), frequencies, (powers / 10**6)
pyule ======================= """ ########################################################### # Context # ---------- ############################################## # Example # -------- # # In the following example, we use pyule to analyse 1000 noisy signals. # We plot them in gray and the average in red. # from spectrum import pyule from scipy.signal import lfilter from pylab import plot, mean, log10, randn from numpy import array allpsds = [] a = array([1, -2.2137, 2.9403, -2.1697, 0.9606]) for this in range(1000): x = lfilter([1], a, randn(1, 256)) p = pyule(x[0], 4, scale_by_freq=False, NFFT=256) p.plot(color='gray', alpha=0.1) allpsds.append(p.psd) plot(p.frequencies(), 10 * log10(mean(allpsds, axis=0)), "red")
""" ########################################################### # Context # ---------- ############################################## # Example # -------- # # In the following example, we use pyule to analyse 1000 noisy signals. # We plot them in gray and the average in red. # from spectrum import pyule from scipy.signal import lfilter from pylab import plot, mean, log10, randn from numpy import array allpsds = [] a = array([1,-2.2137,2.9403,-2.1697,0.9606]) for this in range(1000): x = lfilter([1], a, randn(1,256)) p = pyule(x[0],4, scale_by_freq=False, NFFT=256) p.plot(color='gray', alpha=0.1) allpsds.append(p.psd) plot(p.frequencies(), 10*log10(mean(allpsds, axis=0)), "red")
def ar_psd(nni=None, rpeaks=None, fbands=None, nfft=2**10, detrend=True, order=16, fs=4, show=True, show_param=True, legend=True, mode='normal'): """ Parameters ---------- rpeaks : array R-peak locations in [ms] or [s] nni : array NN-Intervals in [ms] or [s] fbands : dict, optional Dictionary with frequency bands (2-element tuples or list) Value format: (lower_freq_band_boundary, upper_freq_band_boundary) Keys: 'ulf' Ultra low frequency (default: none) optional 'vlf' Very low frequency (default: (0.003Hz, 0.04Hz)) 'lf' Low frequency (default: (0.04Hz - 0.15Hz)) 'hf' High frequency (default: (0.15Hz - 0.4Hz))´ nfft : int, optional Number of points computed for the entire AR result (default: 2**12) order : int, optional Autoregressive model order (default: 16) show : bool, optional If true, show PSD plot (default: True) show_param : bool, optional If true, list all computed PSD parameters next to the plot (default: True) legend : bool, optional If true, add a legend with frequency bands to the plot (default: True) Returns ------- results : biosppy.utils.ReturnTuple object All results of the Autoregressive PSD estimation (see list and keys below) Returned Parameters & Keys -------------------------- .. Peak frequencies of all frequency bands in [Hz] (key: 'ar_peak') .. Absolute powers of all frequency bands in [ms^2][(key: 'ar_abs') .. Relative powers of all frequency bands [%] (key: 'ar_rel') .. Logarithmic powers of all frequency bands [-] (key: 'ar_log') .. Normalized powers of all frequency bands [-] (key: 'ar_norms') .. LF/HF ratio [-] (key: 'ar_ratio') .. Total power over all frequency bands in [ms^2] (key: 'ar_total') .. Interpolation method (key: 'ar_interpolation') .. Resampling frequency (key: 'ar_resampling_frequency') .. AR model order (key: 'ar_order') .. Number of PSD samples (key: 'ar_nfft') """ # Check input nn = tools.check_input(nni, rpeaks) # Verify or set default frequency bands fbands = fd._check_freq_bands(fbands) # 外れ値をスプライン補間 #nni = _artefact_correction(nni,threshold=0.25) # 4Hzでリサンプリング nn_interpol = detrending.resample_to_4Hz(nni, fs) # 平滑化 if detrend: nn_interpol = detrending.detrend(nn_interpol, Lambda=500) # deternd means nn_interpol = nn_interpol - np.mean(nn_interpol) # Compute autoregressive PSD ar = spectrum.pyule(data=nn_interpol, order=order, NFFT=nfft, sampling=fs, scale_by_freq=False) # Get frequencies and powers frequencies = np.asarray(ar.frequencies()) powers = np.asarray(ar.psd) # Compute frequency parameters params, freq_i = fd._compute_parameters('ar', frequencies, powers, fbands) # Plot PSD #figure = fd._plot_psd('ar', frequencies, powers, freq_i, params, show, show_param, legend) #figure = biosppy.utils.ReturnTuple((figure, ), ('ar_plot', )) # Complete output #return tools.join_tuples(params, figure) return params