def _filter_array(self, arr): """ Filter and smooth the 1 or 2 d <arr>ay. """ if len(arr.shape) > 2: raise ValueError("<arr> must be 1 or 2d.") # Then use nitime to # high pass filte using FIR # (~1/128 s, same cutoff as SPM8's default) # FIR did well in: # # Comparison of Filtering Methods for fMRI Datasets # F. Kruggela, D.Y. von Cramona, X. Descombesa # NeuroImage 10 (5), 1999, 530 - 543. filtered = np.ones_like(arr) try: # Try 2d first... for col in range(arr.shape[1]): tsi = nitime.TimeSeries(arr[:, col], 1, self.TR) fsi = nitime.analysis.FilterAnalyzer(tsi, ub=None, lb=0.008) filtered[..., col] = fsi.fir.data except IndexError: # Fall back to 1d tsi = nitime.TimeSeries(arr, 1, self.TR) fsi = nitime.analysis.FilterAnalyzer(tsi, ub=None, lb=0.008) filtered = fsi.fir.data return filtered
def mean_fir(self, window_size=30): """ Estimate and return the average (for all condtions in trials) finite impulse-response model using self.bold and self.trials. <window_size> is the expected length of the haemodynamic response in TRs. """ bold = self.bold.copy() if bold == None: raise ValueError( 'No bold signal is defined. Try create_bold()?') # Convert trials to tr trials_in_tr = roi.timing.dtime(self.trials, self.durations, None, 0) # Truncate bold or trials_in_tr if needed try: bold = bold[0:trials_in_tr.shape[0]] trials_in_tr = trials_in_tr[0:bold.shape[0]] except IndexError: pass # Convert self.bold (an array) to a nitime TimeSeries # instance ts_bold = nt.TimeSeries(bold, sampling_interval=self.TR) # And another one for the events (the different stimuli): ts_trials = nt.TimeSeries(trials_in_tr, sampling_interval=self.TR) # Create a nitime Analyzer instance. eva = nt.analysis.EventRelatedAnalyzer(ts_bold, ts_trials, window_size) # Now do the find the event-relared averaged by FIR: # For details see the nitime module and, # # M.A. Burock and A.M.Dale (2000). Estimation and Detection of # Event-Related fMRI Signals with Temporally Correlated Noise: A # Statistically Efficient and Unbiased Approach. Human Brain # Mapping, 11:249-260 hrf = eva.FIR.data if hrf.ndim == 2: hrf = hrf.mean(0) ## hrf if the mean of all ## conditions in trials hrf = hrf/hrf.max() ## Norm it return hrf
def _evoked_1d(data, events, n_bins, tr, calc_method, correct_baseline): events_ts = nit.TimeSeries(events, sampling_interval=tr) data_ts = nit.TimeSeries(data, sampling_interval=tr) analyzer = nit.analysis.EventRelatedAnalyzer(data_ts, events_ts, n_bins) evoked_data = getattr(analyzer, calc_method) evoked_data = np.asarray(evoked_data).T.astype(float) if evoked_data.ndim == 1: evoked_data = np.array([evoked_data]) if correct_baseline: evoked_data = evoked_data - evoked_data[:, 0, None] return evoked_data
def test_line_broadening(): # Complex time series: arr = np.random.rand(10,10,10,1024) * np.exp(1j * np.pi) ts = nts.TimeSeries(data=arr, sampling_rate=5000.) lbr = 1000. new_ts = ut.line_broadening(ts, lbr) npt.assert_equal(new_ts.shape, ts.shape)
def calc_spectra(self, lbr, cutoff, sampling_rate=5000, min_ppm=-0.7, max_ppm=4.3): # Once we've done that, we only care about the water-suppressed data self.f, self.spec = ana.get_spectra(nt.TimeSeries( self.timeseries, sampling_rate=sampling_rate), line_broadening=lbr, filt_method=dict(lb=cutoff, filt_order=256)) # The first echo (off-resonance) is in the first output self.echo1 = self.spec[:, 0] # The on-resonance is in the second: self.echo2 = self.spec[:, 1] f_ppm = ut.freq_to_ppm(self.f) idx0 = np.argmin(np.abs(f_ppm - min_ppm)) idx1 = np.argmin(np.abs(f_ppm - max_ppm)) idx = slice(idx1, idx0) # Convert from Hz to ppm and extract the part you are interested in. self.f_ppm = f_ppm[idx] # Pack it into a dict: m_e1 = np.mean(self.echo1[:, idx], 0) m_e2 = np.mean(self.echo2[:, idx], 0) self.diff = m_e2 - m_e1 return dict(echo1=m_e1, echo2=m_e2, diff=self.diff), f_ppm
def smooth(X, tr=1.5, ub=0.10, lb=0.001): """Smooth columns in X. Parameters: ----------- X - a 2d array with features in cols tr - the repetition time or sampling (in seconds) ub - upper bound of the band pass (Hz/2*tr) lb - lower bound of the band pass (Hz/2*tr) Note: ---- Smoothing is a linear detrend followed by a bandpass filter from 0.0625-0.15 Hz """ # Linear detrend Xf = signal.detrend(X, axis=0, type='linear', bp=0) # Band pass ts = nt.TimeSeries(Xf.transpose(), sampling_interval=tr) Xf = nt.analysis.FilterAnalyzer(ts, ub=ub, lb=lb).fir.data ## ub and lb selected after some experimentation ## with the simiulated accumulator data ## ub=0.10, lb=0.001).fir.data Xf = Xf.transpose() ## TimeSeries assumes last axis is time, and we need ## the first axis to be time. return Xf
def test_get_spectra(): """ Test the function that does the spectral analysis """ data = np.transpose(nib.load(file_name).get_data(), [1,2,3,4,5,0]).squeeze() w_data, w_supp_data = ana.coil_combine(data) # XXX Just basic smoke-testing for now: f_nonw, nonw_sig1 = ana.get_spectra(nt.TimeSeries(w_supp_data, sampling_rate=5000)) f_nonw, nonw_sig2 = ana.get_spectra(nt.TimeSeries(w_supp_data, sampling_rate=5000), line_broadening=5) f_nonw, nonw_sig3 = ana.get_spectra(nt.TimeSeries(w_supp_data, sampling_rate=5000), line_broadening=5, zerofill=1000)
def nitime_solution(animal, day, cutoff=True): # TODO: add support for custom freq bands import h5py import nitime import numpy as np import nitime.analysis as nta from utils_loading import encode_to_filename from nitime.viz import drawmatrix_channels import matplotlib.pyplot as plt folder = "/Volumes/DATA_01/NL/layerproject/processed/" hf = h5py.File(encode_to_filename(folder, animal, day), 'r') dff = np.array(hf['dff']) NEUR = 'ens' # Critical neuron pair vs general neuron gc if NEUR == 'ens': rois = dff[hf['ens_neur']] elif NEUR == 'neur': rois = dff[hf['nerden']] else: rois = dff[NEUR] rois_ts = nitime.TimeSeries(rois, sampling_interval=1 / hf.attrs['fr']) G = nta.GrangerAnalyzer(rois_ts) if cutoff: sel = np.where(G.frequencies < hf.attrs['fr'])[0] caus_xy = G.causality_xy[:, :, sel] caus_yx = G.causality_yx[:, :, sel] caus_sim = G.simultaneous_causality[:, :, sel] else: caus_xy = G.causality_xy caus_yx = G.causality_yx caus_sim = G.simultaneous_causality g1 = np.mean(caus_xy, -1) g2 = np.mean(caus_yx, -1) g3 = np.mean(caus_sim, -1) g4 = g1-g2 fig03 = drawmatrix_channels(g1, ['E11', 'E12', 'E21', 'E22'], size=[10., 10.], color_anchor = 0) plt.colorbar()
def get_spectra(data, filt_method=dict(lb=0.1, filt_order=256), spect_method=dict(NFFT=1024, n_overlap=1023, BW=2), phase_zero=None, line_broadening=None, zerofill=None): """ Derive the spectra from MRS data Parameters ---------- data : nitime TimeSeries class instance or array Time-series object with data of shape (echos, transients, time-points), containing the FID data. If an array is provided, we will assume that a sampling rate of 5000.0 Hz was used filt_method : dict Details for the filtering method. A FIR zero phase-delay method is used with parameters set according to these parameters spect_method : dict Details for the spectral analysis. Per default, we use line_broadening : float Linewidth for apodization (in Hz). zerofill : int Number of bins to zero fill with. Returns ------- f : the center frequency of the frequencies represented in the spectra spectrum_water, spectrum_water_suppressed: The first spectrum is for the data with water not suppressed and the second spectrum is for the water-suppressed data. Notes ----- This function performs the following operations: 1. Filtering. 2. Apodizing/windowing. Optionally, this is done with line-broadening (see page 92 of Keeler2005_. 3. Spectral analysis. .. [Keeler2005] Keeler, J (2005). Understanding NMR spectroscopy, second edition. Wiley (West Sussex, UK). """ if not isinstance(data, nt.TimeSeries): data = nt.TimeSeries(data, sampling_rate=5000.0) if filt_method is not None: filtered = nta.FilterAnalyzer(data, **filt_method).fir else: filtered = data if line_broadening is not None: lbr_time = line_broadening * np.pi # Conversion from Hz to # time-constant, see Keeler page 94 else: lbr_time = 0 apodized = ut.line_broadening(filtered, lbr_time) if zerofill is not None: new_apodized = np.concatenate( [apodized.data, np.zeros(apodized.shape[:-1] + (zerofill, ))], -1) apodized = nt.TimeSeries(new_apodized, sampling_rate=apodized.sampling_rate) S = nta.SpectralAnalyzer(apodized, method=dict(NFFT=spect_method['NFFT'], n_overlap=spect_method['n_overlap']), BW=spect_method['BW']) f, c = S.spectrum_fourier return f, c
plt import matplotlib.pyplot as plt A = np.vstack((a1, a2)) plt.plot(A.T); plt.legend(['a', 'b']) plt.show() import h5py import nitime import numpy as np import nitime.analysis as nta from utils_loading import encode_to_filename from nitime.viz import drawmatrix_channels rois = A rois_ts = nitime.TimeSeries(rois, sampling_interval=1 / 5) G = nta.GrangerAnalyzer(rois_ts, order=1) if cutoff: sel = np.where(G.frequencies < hf.attrs['fr'])[0] caus_xy = G.causality_xy[:, :, sel] caus_yx = G.causality_yx[:, :, sel] else: caus_xy = G.causality_xy caus_yx = G.causality_yx cutoff = False G = nta.GrangerAnalyzer(rois_ts, order=1) if cutoff: sel = np.where(G.frequencies < hf.attrs['fr'])[0] caus_xy = G.causality_xy[:, :, sel] caus_yx = G.causality_yx[:, :, sel] else:
#calculate frequency lower bound f_lb = 1.0 / (data['ATTface1'].shape[2] * TR) for cond in conds: #initialize shape of object, but only for first subject if s == 0: corr_all[cond] = np.zeros( (len(subjects), num_runs, len(rois), len(rois))) * np.nan coh_all[cond] = np.zeros( (len(subjects), num_runs, len(rois), len(rois))) * np.nan #plt.figure(); plt.suptitle(cond) for nr in range(num_runs): #initialize a time series object T = nt.TimeSeries(data[cond][:, nr, :], sampling_interval=TR) T.metadata['roi'] = rois #initialize a correlation analyzer Corr = nta.CorrelationAnalyzer(T) corr_all[cond][s, nr] = Corr.corrcoef #initialize a coherence analyzer Coh = nta.CoherenceAnalyzer(T) Coh.method['NFFT'] = NFFT freq_ind = np.where( (Coh.frequencies > f_lb) * (Coh.frequencies < f_ub))[0] coh_all[cond][s, nr] = np.mean(Coh.coherence[:, :, freq_ind], -1) #avg over frequencies #For debugging, lets look at some of the spectra