def test_fgrid(): Fs = 100 nfft = 256 f, idx = libtfr.fgrid(Fs, nfft) assert_equal(f.size, idx.size) assert_equal(f[-1], Fs / 2) f, idx = libtfr.fgrid(Fs, nfft, (10, 40)) assert_true(f[0] >= 10) assert_true(f[-1] <= 40)
def load_sound_stims(files, root="", windowtime=0.016, ovl=0.0016, f_min=500, f_max=8000, gammatone=False, dsample=10, sres=15, compress=0): stims = [] durations = [] for f in files: Fs, wave = read(root + f) duration = int(1000 * len(wave) / Fs) durations.append(duration) if gammatone: Pxx = gg.gtgram(wave, Fs, windowtime, ovl, sres, f_min) Pxx = np.log10(Pxx) else: w = np.hanning(int(windowtime * Fs)) Pxx = libtfr.stft(wave, w, int(w.size * .1)) freqs, ind = libtfr.fgrid(Fs, w.size, [f_min, f_max]) Pxx = Pxx[ind, :] Pxx = np.log10(Pxx + compress) Pxx = resample(Pxx, sres) Pxx = resample(Pxx, duration / dsample, axis=1) stims.append(Pxx) return stims, durations
def specgram(x, NFFT=256, shift=128, Fs=1.0, drange=60, ax=None, cmap=mplt.cm.gray_r, **kwargs): from numpy import hanning from libtfr import stft, fgrid, tgrid, dynamic_range w = hanning(NFFT) S = stft(x, w, shift) F,ind = fgrid(Fs,NFFT,(0,Fs/2)) T = tgrid(x.size, Fs, shift) S = nx.log10(dynamic_range(S, drange)) if ax is None: ax = mplt.gca() ax.imshow(S, extent = (T[0],T[-1],F[0]-0.01,F[-1]), cmap=cmap, **kwargs) return S
def load_stimulus(path, window, step, f_min=0.5, f_max=8.0, f_count=30, compress=1, gammatone=False, **kwargs): """Load sound stimulus and calculate spectrotemporal representation. Parameters: path: location of wave file window: duration of window (in ms) step: window step (in ms) f_min: minimum frequency (in kHz) f_max: maximum frequency (in kHz) f_count: number of frequency bins gammatone: if True, use gammatone filterbank Returns spectrogram, duration (ms) """ import ewave fp = ewave.open(path, "r") Fs = fp.sampling_rate / 1000. osc = ewave.rescale(fp.read(), 'h') if gammatone: import gammatone.gtgram as gg Pxx = gg.gtgram(osc, Fs * 1000, window / 1000, step / 1000, f_count, f_min * 1000) else: import libtfr # nfft based on desired number of channels btw f_min and f_max nfft = int(f_count / (f_max - f_min) * Fs) npoints = int(Fs * window) if nfft < npoints: raise ValueError( "window size {} ({} points) too large for desired freq resolution {}. " "Decrease to {} ms or increase f_count.".format( window, f_count, npoints, nfft / Fs)) nstep = int(Fs * step) taper = np.hanning(npoints) mfft = libtfr.mfft_precalc(nfft, taper) Pxx = mfft.mtspec(osc, nstep) freqs, ind = libtfr.fgrid(Fs, nfft, [f_min, f_max]) Pxx = Pxx[ind, :] if compress is not None: Pxx = np.log10(Pxx + compress) - np.log10(compress) return Pxx, Pxx.shape[1] * step
def mtfft(tl, **kwargs): """ Multitaper fourier transform from point process times [J,Nsp,f] = mtfftpt(tl, **kwargs) Input: tl ragged array of event times Optional keyword arguments: NW time-bandwidth parameter for DPSS tapers (default 3) k number of DPSS tapers to use (default nw*2-1) time_range the range of times to analyze (default is to use range of tl) Fs the frequency resolution (default 1) fpass frequency band to be used in the calculation in the form (fmin, fmax). Default (0, Fs/2) nfft number of frequency bins for transform Output: J complex spectrum with dimensions (freq x chan x tapers) Nsp total spike count in each trial, with dimension (chan,) f frequency grid, with dimension (freq,) Note on units: if the units of the data are T, the corresponding frequency units are in 1/T (sec -> Hz; msec -> kHz) """ from libtfr import fgrid, dpss from numpy import arange, sqrt import toelis NW = kwargs.get('NW', 3) K = kwargs.get('k', NW*2-1) Fs = kwargs.get('Fs', 1) fpass = kwargs.get('fpass', (0, Fs/2.)) dt = 1./Fs try: mintime, maxtime = kwargs['time_range'] t = arange(mintime, maxtime, dt) except KeyError: mintime, maxtime = toelis.range(tl) # pad around spike times to avoid edge effects t = arange(mintime-dt, maxtime+2*dt, dt) N = len(t) nfft = kwargs.get('nfft', N) f,findx = fgrid(Fs, nfft, fpass) tapers = dpss(N, NW, K)[0].T * sqrt(Fs) J, Nsp = _mtfft(tl, tapers, nfft, t, f, findx) return J, Nsp, f
def mtfft(tl, **kwargs): """ Multitaper fourier transform from point process times [J,Nsp,f] = mtfftpt(tl, **kwargs) Input: tl ragged array of event times Optional keyword arguments: NW time-bandwidth parameter for DPSS tapers (default 3) k number of DPSS tapers to use (default nw*2-1) time_range the range of times to analyze (default is to use range of tl) Fs the frequency resolution (default 1) fpass frequency band to be used in the calculation in the form (fmin, fmax). Default (0, Fs/2) nfft number of frequency bins for transform Output: J complex spectrum with dimensions (freq x chan x tapers) Nsp total spike count in each trial, with dimension (chan,) f frequency grid, with dimension (freq,) Note on units: if the units of the data are T, the corresponding frequency units are in 1/T (sec -> Hz; msec -> kHz) """ from libtfr import fgrid, dpss from numpy import arange, sqrt import toelis NW = kwargs.get('NW', 3) K = kwargs.get('k', NW * 2 - 1) Fs = kwargs.get('Fs', 1) fpass = kwargs.get('fpass', (0, Fs / 2.)) dt = 1. / Fs try: mintime, maxtime = kwargs['time_range'] t = arange(mintime, maxtime, dt) except KeyError: mintime, maxtime = toelis.range(tl) # pad around spike times to avoid edge effects t = arange(mintime - dt, maxtime + 2 * dt, dt) N = len(t) nfft = kwargs.get('nfft', N) f, findx = fgrid(Fs, nfft, fpass) tapers = dpss(N, NW, K)[0].T * sqrt(Fs) J, Nsp = _mtfft(tl, tapers, nfft, t, f, findx) return J, Nsp, f
def load_signal(self, locator, dtype='d'): """ Loads the signal and computes the spectrogram. dtype: the data type to store the output in. Use single-precision floats if needed to reduce storage requirements. """ from ewave import wavfile from libtfr import fgrid, dynamic_range from chirp.common.signal import spectrogram from chirp.common.geom import elementlist, masker from numpy import linspace, log10 fp = wavfile(locator) signal = fp.read() Fs = fp.sampling_rate speccr = spectrogram(**self.options) # adjust window size to get correct number of frequency bands df = 1. * (self.options['freq_range'][1] - self.options['freq_range'][0]) / self.options['nfreq'] nfft = int(Fs / df) spec, extent = speccr.linspect(signal, Fs / 1000, nfft=nfft) F, ind = fgrid(Fs, nfft, self.options['freq_range']) # in Hz spec = spec[ind, :] T = linspace(extent[0], extent[1], spec.shape[1]) # in ms # first convert the spectrogram to its final scale if self.options['powscale'].startswith('log'): # TODO calculate dynamic range of the signal for non 16 bit PCM? spec = log10(dynamic_range(spec, 96)) # recenter spectrogram if self.options['subtract_mean']: spec -= spec.mean() if self.options['mask'] != 'none': eblfile = os.path.splitext(locator)[0] + elementlist.default_extension if os.path.exists(eblfile): mask = elementlist.read(eblfile) spec = masker(boxmask=self.options['mask'] == 'box').cut(spec, mask, T, F / 1000.) return spec.astype(dtype)
def specgram(signal, sampling_rate, nfft=256, shift=128, compress=1): """ Calculate a spectrogram of signal. Parameters: signal - the input signal (needs to be a 1D array) nfft - the window size, in points shift - how much to shift the window in each frame, in points sampling_rate - the number of samples per second in the signal compress - how much to compress the spectrogram. Effectively sets the floor of the spectrogram at log10(compress) Returns: the spectrogram, the frequency grid, and the time grid """ from numpy import log10 import libtfr # generate a transform object D = libtfr.mfft_dpss(nfft, 3, 5, nfft) # calculate the power spectrogram P = D.mtspec(signal, shift) freq, find = libtfr.fgrid(sampling_rate, nfft) bins = libtfr.tgrid(P, sampling_rate, shift) return (log10(P + compress) - log10(compress), freq, bins)
def mtstft(tl, window, step, **kwargs): """ Multitaper short time fourier transform from point process times [J,Nsp,f,t] = mtstft(tl, window, step**kwargs) Input: tl ragged array of event times window duration of short time analysis window step step size between windows Optional keyword arguments: NW time-bandwidth parameter for DPSS tapers (default 3) k number of DPSS tapers to use (default nw*2-1) time_range the range of times to analyze (default is to use range of tl) Fs the frequency resolution (default 1) fpass frequency band to be used in the calculation in the form (fmin, fmax). Default (0, Fs/2) nfft number of frequency bins for transform Output: J complex spectrum with dimensions (freq x time x tapers x chan) Nsp total spike count in each trial, with dimension (time, chan) f frequency grid, with dimension (freq,) t time grid, with dimension (time,) Note on units: if the units of the data are T, the corresponding frequency units are in 1/T (sec -> Hz; msec -> kHz) """ from libtfr import fgrid, dpss from numpy import arange, sqrt, zeros import toelis NW = kwargs.get('NW', 3) K = kwargs.get('k', NW*2-1) Fs = kwargs.get('Fs', 1) dt = 1./ Fs fpass = kwargs.get('fpass', (0, Fs/2.)) C = len(tl) twin = arange(0, window, dt) N = len(twin) nfft = kwargs.get('nfft', N) f,findx = fgrid(Fs, nfft, fpass) tapers = dpss(N, NW, K)[0].T * sqrt(Fs) try: mintime, maxtime = kwargs['time_range'] except KeyError: mintime, maxtime = toelis.range(tl) # pad around spikes mintime -= dt maxtime += 2*dt tgrid = arange(mintime, maxtime, step) J = zeros((f.size, tgrid.size, K, C), dtype='D') Nsp = zeros((tgrid.size, C), dtype='i') for i, offset in enumerate(tgrid): j,n = _mtfft(tl, tapers, nfft, twin + offset, f, findx) J[:,i,:,:] = j Nsp[i,:] = n return J, Nsp, f, tgrid
def mtstft(tl, window, step, **kwargs): """ Multitaper short time fourier transform from point process times [J,Nsp,f,t] = mtstft(tl, window, step**kwargs) Input: tl ragged array of event times window duration of short time analysis window step step size between windows Optional keyword arguments: NW time-bandwidth parameter for DPSS tapers (default 3) k number of DPSS tapers to use (default nw*2-1) time_range the range of times to analyze (default is to use range of tl) Fs the frequency resolution (default 1) fpass frequency band to be used in the calculation in the form (fmin, fmax). Default (0, Fs/2) nfft number of frequency bins for transform Output: J complex spectrum with dimensions (freq x time x tapers x chan) Nsp total spike count in each trial, with dimension (time, chan) f frequency grid, with dimension (freq,) t time grid, with dimension (time,) Note on units: if the units of the data are T, the corresponding frequency units are in 1/T (sec -> Hz; msec -> kHz) """ from libtfr import fgrid, dpss from numpy import arange, sqrt, zeros import toelis NW = kwargs.get('NW', 3) K = int(kwargs.get('k', NW * 2 - 1)) Fs = kwargs.get('Fs', 1) dt = 1. / Fs fpass = kwargs.get('fpass', (0, Fs / 2.)) C = len(tl) twin = arange(0, window, dt) N = len(twin) nfft = kwargs.get('nfft', N) f, findx = fgrid(Fs, nfft, fpass) tapers = dpss(N, NW, K)[0].T * sqrt(Fs) try: mintime, maxtime = kwargs['time_range'] except KeyError: mintime, maxtime = toelis.range(tl) # pad around spikes mintime -= dt maxtime += 2 * dt tgrid = arange(mintime, maxtime, step) J = zeros((f.size, tgrid.size, K, C), dtype='D') Nsp = zeros((tgrid.size, C), dtype='i') for i, offset in enumerate(tgrid): j, n = _mtfft(tl, tapers, nfft, twin + offset, f, findx) J[:, i, :, :] = j Nsp[i, :] = n return J, Nsp, f, tgrid