コード例 #1
0
ファイル: psd.py プロジェクト: parsonsh/neuropy
def plot_psd(datas, cs=None, ylims=None, titlestr=''):
    f = figure(figsize=figsize)
    for data, c in zip(datas, cs):
        data = filter.notch(data)[
            0]  # remove 60 Hz mains noise, as for SI calc
        # convert data from uV to mV. I think P is in mV^2?:
        P, freqs = mpl.mlab.psd(data / 1e3,
                                NFFT=NFFT,
                                Fs=SAMPFREQ,
                                noverlap=NOVERLAP)
        # keep only freqs between F0 and F1:
        f0, f1 = F0, F1  # need to set different local names, since they're not read-only
        if f0 == None:
            f0 = freqs[0]
        if f1 == None:
            f1 = freqs[-1]
        lo, hi = freqs.searchsorted([f0, f1])
        P, freqs = P[lo:hi], freqs[lo:hi]
        # check for and replace zero power values (ostensibly due to gaps in recording)
        # before attempting to convert to dB:
        zis = np.where(
            P == 0.0)  # row and column indices where P has zero power
        if len(zis[0]) > 0:  # at least one hit
            P[zis] = np.finfo(
                np.float64).max  # temporarily replace zeros with max float
            minnzval = P.min()  # get minimum nonzero value
            P[zis] = minnzval  # replace with min nonzero values
        P = 10. * np.log10(P)  # convert power to dB wrt 1 mV^2?
        # for better visualization, clip power values to within (P0, P1) dB
        if P0 != None:
            P[P < P0] = P0
        if P1 != None:
            P[P > P1] = P1
        plot(freqs, P, c=c, ls='-', marker=None)
    # demarcate SI power ratio frequency bands with horizontal lines:
    hlines(y=-50,
           xmin=LFPPRLOBAND[0],
           xmax=LFPPRLOBAND[1],
           colors='e',
           linestyles='-',
           lw=5)
    hlines(y=-30,
           xmin=LFPPRHIBAND[0],
           xmax=LFPPRHIBAND[1],
           colors='e',
           linestyles='-',
           lw=5)
    axis('tight')
    xscale(XSCALE)
    ylim(ylims)
    xlabel("frequency (Hz)")
    ylabel("power (dB)")
    gcfm().window.setWindowTitle(titlestr + ' ' + XSCALE)
    f.tight_layout(pad=0.3)  # crop figure to contents
コード例 #2
0
ファイル: lfp.py プロジェクト: neuropy/neuropy
    def notch(self, chanis=None, freq=60, bw=0.25, gpass=0.01, gstop=30, ftype='ellip'):
        """Filter out frequencies centered on freq (Hz), of bandwidth +/- bw (Hz) on
        data row indices chanis, in-place.

        ftype: 'ellip', 'butter', 'cheby1', 'cheby2', 'bessel'
        """
        data = self.get_data()
        if chanis == None:
            chanis = np.arange(len(data))
        data = data[chanis]
        data, b, a = filter.notch(data, self.sampfreq, freq, bw, gpass, gstop, ftype)
        self.data[chanis] = data
        return b, a
コード例 #3
0
    def notch(self,
              chanis=None,
              freq=60,
              bw=0.25,
              gpass=0.01,
              gstop=30,
              ftype='ellip'):
        """Filter out frequencies centered on freq (Hz), of bandwidth +/- bw (Hz) on
        data row indices chanis, in-place.

        ftype: 'ellip', 'butter', 'cheby1', 'cheby2', 'bessel'
        """
        data = self.get_data()
        if chanis == None:
            chanis = np.arange(len(data))
        data = data[chanis]
        data, b, a = filter.notch(data, self.sampfreq, freq, bw, gpass, gstop,
                                  ftype)
        self.data[chanis] = data
        return b, a
コード例 #4
0
ファイル: psd.py プロジェクト: catubc/neuron
def plot_psd(data, titlestr):
    data = filter.notch(data)[0] # remove 60 Hz mains noise, as for SI calc
    # convert data from uV to mV. I think P is in mV^2?:
    P, freqs = mpl.mlab.psd(data/1e3, NFFT=NFFT, Fs=SAMPFREQ, noverlap=NOVERLAP)
    # keep only freqs between F0 and F1:
    f0, f1 = F0, F1 # need to set different local names, since they're not read-only
    if f0 == None:
        f0 = freqs[0]
    if f1 == None:
        f1 = freqs[-1]
    lo, hi = freqs.searchsorted([f0, f1])
    P, freqs = P[lo:hi], freqs[lo:hi]
    # check for and replace zero power values (ostensibly due to gaps in recording)
    # before attempting to convert to dB:
    zis = np.where(P == 0.0) # row and column indices where P has zero power
    if len(zis[0]) > 0: # at least one hit
        P[zis] = np.finfo(np.float64).max # temporarily replace zeros with max float
        minnzval = P.min() # get minimum nonzero value
        P[zis] = minnzval # replace with min nonzero values
    P = 10. * np.log10(P) # convert power to dB wrt 1 mV^2?
    # for better visualization, clip power values to within (P0, P1) dB
    if P0 != None:
        P[P < P0] = P0
    if P1 != None:
        P[P > P1] = P1
    f = pl.figure(figsize=figsize)
    a = f.add_subplot(111)
    a.plot(freqs, P, 'k-')
    # add SI frequency band limits:
    a.axvline(x=LFPSILOWBAND[0], c='r', ls='--')
    a.axvline(x=LFPSILOWBAND[1], c='r', ls='--')
    a.axvline(x=LFPSIHIGHBAND[0], c='b', ls='--')
    a.axvline(x=LFPSIHIGHBAND[1], c='b', ls='--')
    a.axis('tight')
    a.set_xscale(XSCALE)
    a.set_ylim(ymin=P[-1]) # use last power value to set ymin
    a.set_xlabel("frequency (Hz)")
    a.set_ylabel("power (dB)")
    gcfm().window.setWindowTitle(titlestr+' '+XSCALE)
    f.tight_layout(pad=0.3) # crop figure to contents
コード例 #5
0
def plot_psd(datas, cs=None, ylims=None, titlestr=''):
    f = figure(figsize=figsize)
    for data, c in zip(datas, cs):
        data = filter.notch(data)[0] # remove 60 Hz mains noise, as for SI calc
        # convert data from uV to mV. I think P is in mV^2?:
        P, freqs = mpl.mlab.psd(data/1e3, NFFT=NFFT, Fs=SAMPFREQ, noverlap=NOVERLAP)
        # keep only freqs between F0 and F1:
        f0, f1 = F0, F1 # need to set different local names, since they're not read-only
        if f0 == None:
            f0 = freqs[0]
        if f1 == None:
            f1 = freqs[-1]
        lo, hi = freqs.searchsorted([f0, f1])
        P, freqs = P[lo:hi], freqs[lo:hi]
        # check for and replace zero power values (ostensibly due to gaps in recording)
        # before attempting to convert to dB:
        zis = np.where(P == 0.0) # row and column indices where P has zero power
        if len(zis[0]) > 0: # at least one hit
            P[zis] = np.finfo(np.float64).max # temporarily replace zeros with max float
            minnzval = P.min() # get minimum nonzero value
            P[zis] = minnzval # replace with min nonzero values
        P = 10. * np.log10(P) # convert power to dB wrt 1 mV^2?
        # for better visualization, clip power values to within (P0, P1) dB
        if P0 != None:
            P[P < P0] = P0
        if P1 != None:
            P[P > P1] = P1
        plot(freqs, P, c=c, ls='-', marker=None)
    # demarcate SI frequency bands with horizontal lines:
    hlines(y=-50, xmin=LFPSILOWBAND[0], xmax=LFPSILOWBAND[1], colors='e',
           linestyles='-', lw=5)
    hlines(y=-30, xmin=LFPSIHIGHBAND[0], xmax=LFPSIHIGHBAND[1], colors='e',
           linestyles='-', lw=5)
    axis('tight')
    xscale(XSCALE)
    ylim(ylims)
    xlabel("frequency (Hz)")
    ylabel("power (dB)")
    gcfm().window.setWindowTitle(titlestr+' '+XSCALE)
    f.tight_layout(pad=0.3) # crop figure to contents
コード例 #6
0
ファイル: lfp.py プロジェクト: neuropy/neuropy
    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
コード例 #7
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