Ejemplo n.º 1
0
 def std(self, t0=None, t1=None, chani=-1, width=None, tres=None, fmt='k-', title=True,
         figsize=(20, 3.5)):
     """Plot standard deviation of LFP signal from t0 to t1 on chani, using bins of width
     and tres"""
     uns = get_ipython().user_ns
     self.get_data()
     data = self.data[chani]
     ts = self.get_tssec()
     if t0 == None:
         t0 = ts[0]
     if t1 == None:
         t1 = ts[-1]
     if width == None:
         width = uns['LFPSIWIDTH'] # sec
     if tres == None:
         tres = uns['LFPSITRES'] # sec
     tranges = split_tranges([(t0, t1)], width, tres)
     stds = []
     for trange in tranges:
         ti0, ti1 = ts.searchsorted(trange)
         stds.append(data[ti0:ti1].std())
     stds = np.hstack(stds)
     f = pl.figure(figsize=figsize)
     a = f.add_subplot(111)
     a.plot(tranges[:, 0], stds, fmt)
     a.autoscale(enable=True, tight=True)
     a.set_xlim(xmin=0) # ADC clock starts at t=0
     a.set_xlabel('time (s)')
     a.set_ylabel('LFP $\sigma$ ($\mu$V)')
     titlestr = lastcmd()
     gcfm().window.setWindowTitle(titlestr)
     if title:
         a.set_title(titlestr)
     f.tight_layout(pad=0.3)
     self.f = f
     return stds
Ejemplo n.º 2
0
                 title=title, reclabel=False, figsize=lfpfigsize)
    titlestr = ename + '_c%d' % (chani+1) # 1-based chan ID
    gcfm().window.setWindowTitle(titlestr)


# plot runspeed as a color map:
width, tres = 10, 0.5 # s
minspeed = 1 # cm/s, otherwise considered at rest
runfname = '/home/mspacek/dev/blab/natmov/results/PVCre_0113/s01/PVCre_0113_s01_e11_runspeed.mat'
runmat = loadmat(runfname)
ename = os.path.splitext(os.path.basename(runfname))[0]
tspeed = runmat['tspeed'][0] # s
speed = runmat['speed'][0] # cm/s
t0 = lfp.t0 / 1e6 # sec, tspeed seems to start from 0, lfp starts a few ms later
t1 = lfp.t1 / 1e6
tranges = core.split_tranges([(t0, t1)], width, tres)
tiranges = tspeed.searchsorted(tranges)
nbins = len(tiranges)
tbinspeed = tranges[:, 0]
binspeed = np.zeros(nbins)
for bini, (t0i, t1i) in enumerate(tiranges):
    binspeed[bini] = speed[t0i:t1i].mean()

#figure()
#plot(tbinspeed, binspeed, '-')
binspeed.shape = -1, 1 # column vector
# turn it into a binary rest/run signal:
binspeed[binspeed < minspeed] = 0 # at rest
binspeed[binspeed >= minspeed] = 1 # running
#binspeed /= binspeed.max() # normalize to range [0, 1]
figure(figsize=(1, 10))
Ejemplo n.º 3
0
 for trange in track.tranges:
     if trange[1] - trange[0] >= width: # trange is sufficiently wide
         if trtrange:
             if trange[0] < trtrange[1]*3600*1e6: # trange starts within trtrange
                 rectranges.append(trange)
         else:
             rectranges.append(trange)
 rectranges = np.array(rectranges)
 nids = np.sort(list(track.alln))
 nn = len(nids)
 figure(figsize=figsize)
 axes(axisbg=bg) # set background color
 # plot rates for each rectrange separately, so lines aren't drawn across time gaps:
 for rectrange in rectranges: # one per recording
     recrates = [] # one row per neuron for this recording
     tranges = split_tranges([rectrange], width, tres) # possibly overlapping bins, in us
     midtranges = tranges.mean(axis=1) / 1e6 / 3600 # midpoints of tranges, in hours
     #nmuspikes = np.zeros(len(tranges), dtype=np.int64) # count multiunit spikes per bin
     for nidi, nid in enumerate(nids): # nid order is (or should be) also depth order
         n = track.alln[nid]
         spikeis = n.spikes.searchsorted(tranges) # slice indices into spikes
         nspikes = spikeis[:, 1] - spikeis[:, 0] # number of spikes in each trange
         #nmuspikes += nspikes # accumulate
         rate = nspikes / (width / 1e6) # spike rate per bin, in Hz
         rate[rate == 0.0] = np.nan # replace 0s with nans so they're ignored by plot()
         if cmap:
             cmapi = nidi / nn # from 0 to just under 1, cmaps wrap at 1
             c = cmap(cmapmax*cmapi)
         else:
             c = CCDICT[nidi] # use nidi to maximize colour alternation
         plot(midtranges, rate, '-', lw=lw, c=c, alpha=alpha)
Ejemplo n.º 4
0
    def si(self, kind=None, chani=-1, width=None, tres=None,
           lfpwidth=None, lfptres=None, loband=None, hiband=None, plot=True,
           showstates='auto', statelinepos=[0.2], lw=4, alpha=1, relative2t0=False,
           lim2stim=False, showxlabel=True, showylabel=True, showtitle=True, title=None,
           reclabel=True, swapaxes=False, figsize=None):
        """Calculate an LFP synchrony index, using potentially overlapping windows of width
        and tres, in sec, from the LFP spectrogram, itself composed of bins of lfpwidth and
        lfptres. relative2t0 controls whether to plot relative to t0, or relative to start of
        ADC clock. lim2stim limits the time range only to when a stimulus was presented, i.e.
        to the outermost times of non-NULL din.

        Note that for power ratio methods (kind: L/(L+H) or L/H),
        width and tres are not used, only lfpwidth and lfptres. Options for kind are:

        'L/(L+H)': fraction of power in low band vs total power (Saleem2010)

        'L/H': low to highband power ratio (Li, Poo, Dan 2009)

        'cv': coefficient of variation (std / mean) of all power

        'ncv': normalized CV: (std - mean) / (std + mean)

        'nstdmed': normalized stdmed: (std - med) / (std + med)

        'n2stdmean': normalized 2stdmean: (2*std - mean) / (2*std + mean)

        'n3stdmean': normalized 3stdmean: (3*std - mean) / (3*std + mean)

        """
        uns = get_ipython().user_ns
        if kind == None:
            kind = uns['LFPSIKIND']
        if kind in ['L/(L+H)', 'L/H', 'nLH']: # it's a power ratio measure
            pr = True
        else:
            pr = False

        data = self.get_data()
        ts = self.get_tssec() # full set of timestamps, in sec
        t0, t1 = ts[0], ts[-1]
        if lim2stim:
            t0, t1 = self.apply_lim2stim(t0, t1)
        dt = t1 - t0
        if figsize == None:
            # convert from recording duration time to width in inches, 0.87 accommodates
            # padding around the SI plot:
            figwidth = (dt / 1000) * 5 + 0.87
            figheight = 2.5 # inches
            figsize = figwidth, figheight

        t0i, t1i = ts.searchsorted((t0, t1))
        x = data[chani, t0i:t1i] / 1e3 # slice data, convert from uV to mV
        x = filter.notch(x)[0] # remove 60 Hz mains noise
        try:
            rr = self.r.e0.I['REFRESHRATE']
        except AttributeError: # probably a recording with no experiment
            rr = 200 # assume 200 Hz refresh rate
        if rr <= 100: # CRT was at low vertical refresh rate
            print('filtering out %d Hz from LFP in %s' % (intround(rr), self.r.name))
            x = filter.notch(x, freq=rr)[0] # remove CRT interference

        if width == None:
            width = uns['LFPSIWIDTH'] # sec
        if tres == None:
            tres = uns['LFPSITRES'] # sec
        if lfpwidth == None:
            lfpwidth = uns['LFPPRWIDTH'] if pr else uns['LFPSPECGRAMWIDTH'] # sec
        if lfptres == None:
            lfptres = uns['LFPPRTRES'] if pr else uns['LFPSPECGRAMTRES'] # sec
        if loband == None:
            loband = uns['LFPPRLOBAND']
        f0, f1 = loband
        if hiband == None:
            hiband = uns['LFPPRHIBAND']
        f2, f3 = hiband

        assert lfptres <= lfpwidth
        NFFT = intround(lfpwidth * self.sampfreq)
        noverlap = intround(NFFT - lfptres * self.sampfreq)
        #print('len(x), NFFT, noverlap: %d, %d, %d' % (len(x), NFFT, noverlap))
        # t is midpoints of timebins in sec from start of data. P is in mV^2?:
        P, freqs, Pt = mpl.mlab.specgram(x, NFFT=NFFT, Fs=self.sampfreq, noverlap=noverlap)
        # don't convert power to dB, just washes out the signal in the ratio:
        #P = 10. * np.log10(P)
        if not relative2t0:
            Pt += t0 # convert t to time from start of ADC clock:
        nfreqs = len(freqs)

        # keep only freqs between f0 and f1, and f2 and f3:
        f0i, f1i, f2i, f3i = freqs.searchsorted([f0, f1, f2, f3])
        lP = P[f0i:f1i] # nsubfreqs x nt
        hP = P[f2i:f3i] # nsubfreqs x nt
        lP = lP.sum(axis=0) # nt
        hP = hP.sum(axis=0) # nt

        if pr:
            t = Pt
            ylabel = 'SI (%s)' % kind
        else:
            # potentially overlapping bin time ranges:
            trange = Pt[0], Pt[-1]
            tranges = split_tranges([trange], width, tres) # in sec
            ntranges = len(tranges)
            tis = Pt.searchsorted(tranges) # ntranges x 2 array
            # number of timepoints to use for each trange, almost all will be the same width:
            binnt = intround((tis[:, 1] - tis[:, 0]).mean())
            binhP = np.zeros((ntranges, binnt)) # init appropriate array
            for trangei, t0i in enumerate(tis[:, 0]):
                binhP[trangei] = hP[t0i:t0i+binnt]
            # get midpoint of each trange:
            t = tranges.mean(axis=1)

        #old_settings = np.seterr(all='ignore') # suppress div by 0 errors
        # plot power signal to be analyzed
        #self.si_plot(hP, Pt, t0=0, t1=t[-1], ylim=None, ylabel='highband power',
        #             title=lastcmd()+' highband power', text=self.r.name)

        # set some plotting defaults:
        hlines = []
        if pr:
            ylim = 0, 1
            yticks = 0, 0.2, 0.4, 0.6, 0.8, 1
        else:
            ylim = -1, 1
            yticks = -1, 0, 1
            hlines = [0]

        # calculate some metric of each column, i.e. each bin:
        if kind == 'L/(L+H)':
            si = lP/(lP + hP)
        elif kind == 'L/H':
            si = lP/hP
        elif kind == 'nLH':
            t = Pt
            si = (lP - hP) / (lP + hP)
            ylabel = 'LFP (L - H) / (L + H)'
        elif kind == 'cv':
            si = binhP.std(axis=1) / binhP.mean(axis=1)
            ylim = 0, 2
            ytiks = 0, 1, 2
            ylabel = 'LFP power CV'
        elif kind == 'ncv':
            s = binhP.std(axis=1)
            mean = binhP.mean(axis=1)
            si = (s - mean) / (s + mean)
            ylabel = 'LFP power (std - mean) / (std + mean)'
            #pl.plot(t, s)
            #pl.plot(t, mean)
        elif kind == 'n2stdmean':
            s2 = 2 * binhP.std(axis=1)
            mean = binhP.mean(axis=1)
            si = (s2 - mean) / (s2 + mean)
            ylabel = 'LFP power (2*std - mean) / (2*std + mean)'
            hlines = [-0.1, 0, 0.1] # demarcate desynched and synched thresholds
            #pl.plot(t, s2)
            #pl.plot(t, mean)
        elif kind == 'n3stdmean':
            s3 = 3 * binhP.std(axis=1)
            mean = binhP.mean(axis=1)
            si = (s3 - mean) / (s3 + mean)
            ylabel = 'LFP power (3*std - mean) / (3*std + mean)'
            hlines = [-0.1, 0, 0.1] # demarcate desynched and synched thresholds
            #pl.plot(t, s3)
            #pl.plot(t, mean)
        elif kind == 'n4stdmean':
            s4 = 4 * binhP.std(axis=1)
            mean = binhP.mean(axis=1)
            si = (s4 - mean) / (s4 + mean)
            ylabel = 'LFP power (4*std - mean) / (4*std + mean)'
            #pl.plot(t, s4)
            #pl.plot(t, mean)
        elif kind == 'nstdmed':
            s = binhP.std(axis=1)
            med = np.median(binhP, axis=1)
            si = (s - med) / (s + med)
            ylabel = 'LFP power (std - med) / (std + med)'
            hlines = [-0.1, 0, 0.1] # demarcate desynched and synched thresholds
            #pl.plot(t, s)
            #pl.plot(t, med)
        elif kind == 'n2stdmed':
            s2 = 2 * binhP.std(axis=1)
            med = np.median(binhP, axis=1)
            si = (s2 - med) / (s2 + med)
            ylabel = 'LFP power (2*std - med) / (2*std + med)'
            hlines = [-0.1, 0, 0.1] # demarcate desynched and synched thresholds
            #pl.plot(t, s2)
            #pl.plot(t, med)
        elif kind == 'n3stdmed':
            s3 = 3 * binhP.std(axis=1)
            med = np.median(binhP, axis=1)
            si = (s3 - med) / (s3 + med)
            ylabel = 'LFP power (3*std - med) / (3*std + med)'
            hlines = [-0.1, 0, 0.1] # demarcate desynched and synched thresholds
            #pl.plot(t, s3)
            #pl.plot(t, med)
        elif kind == 'nstdmin':
            s = binhP.std(axis=1)
            min = binhP.min(axis=1)
            si = (s - min) / (s + min)
            ylabel = 'LFP power (std - min) / (std + min)'
            #pl.plot(t, s)
            #pl.plot(t, min)
        elif kind == 'nmadmean':
            mean = binhP.mean(axis=1)
            mad = (np.abs(binhP - mean[:, None])).mean(axis=1)
            si = (mad - mean) / (mad + mean)
            ylabel = 'MUA (MAD - mean) / (MAD + mean)'
            #pl.plot(t, mad)
            #pl.plot(t, mean)
        elif kind == 'nmadmed':
            med = np.median(binhP, axis=1)
            mad = (np.abs(binhP - med[:, None])).mean(axis=1)
            si = (mad - med) / (mad + med)
            ylabel = 'MUA (MAD - median) / (MAD + median)'
            #pl.plot(t, mad)
            #pl.plot(t, med)
        elif kind == 'nvarmin':
            v = binhP.var(axis=1)
            min = binhP.min(axis=1)
            si = (v - min) / (v + min)
            ylabel = 'LFP power (std - min) / (std + min)'
            #pl.plot(t, v)
            #pl.plot(t, min)
        elif kind == 'nptpmean':
            ptp = binhP.ptp(axis=1)
            mean = binhP.mean(axis=1)
            si = (ptp - mean) / (ptp + mean)
            ylabel = 'MUA (ptp - mean) / (ptp + mean)'
            #pl.plot(t, ptp)
            #pl.plot(t, mean)
        elif kind == 'nptpmed':
            ptp = binhP.ptp(axis=1)
            med = np.median(binhP, axis=1)
            si = (ptp - med) / (ptp + med)
            ylabel = 'MUA (ptp - med) / (ptp + med)'
            #pl.plot(t, ptp)
            #pl.plot(t, med)
        elif kind == 'nptpmin':
            ptp = binhP.ptp(axis=1)
            min = binhP.min(axis=1)
            si = (ptp - min) / (ptp + min)
            ylabel = 'MUA (ptp - min) / (ptp + min)'
            #pl.plot(t, ptp)
            #pl.plot(t, min)
        elif kind == 'nmaxmin':
            max = binhP.max(axis=1)
            min = binhP.min(axis=1)
            si = (max - min) / (max + min)
            ylabel = 'MUA (max - min) / (max + min)'
            #pl.plot(t, max)
            #pl.plot(t, min)
        else:
            raise ValueError('unknown kind %r' % kind)
        if plot:
            # calculate xlim, always start from 0, add half a bin width to xmax:
            if pr:
                xlim = (0, t[-1]+lfpwidth/2)
            else:
                xlim = (0, t[-1]+width/2)
            self.si_plot(si, t, t0=t0, t1=t1, xlim=xlim, ylim=ylim, yticks=yticks,
                         ylabel=ylabel, showxlabel=showxlabel, showylabel=showylabel,
                         showtitle=showtitle, title=title,
                         reclabel=reclabel, hlines=hlines,
                         showstates=showstates, statelinepos=statelinepos, lw=lw,
                         alpha=alpha, swapaxes=swapaxes, figsize=figsize)
        #np.seterr(**old_settings) # restore old settings
        return si, t # t are midpoints of bins, offset depends on relative2t0