Esempio n. 1
0
def plotClicked(plt, pts):
    pt = pts[0]
    #(id, fn, time) = pt.data
    
    #[['SourceFile', 'ProtocolSequenceDir', 'fitTime']]
    #fh = db.getDir('ProtocolSequence', id)[fn]
    fh = pt.data()['SourceFile']
    id = pt.data()['ProtocolSequenceDir']
    time = pt.data()['fitTime']
    
    data = fh.read()['Channel':'primary']
    data = fn.besselFilter(data, 8e3)
    p = pw2.plot(data, clear=True)
    pos = time / data.xvals('Time')[-1]
    arrow = pg.CurveArrow(p, pos=pos)
    xr = pw2.viewRect().left(), pw2.viewRect().right()
    if time < xr[0] or time > xr[1]:
        w = xr[1]-xr[0]
        pw2.setXRange(time-w/5., time+4*w/5., padding=0)
    
    fitLen = pt.data()['fitDecayTau']*pt.data()['fitLengthOverDecay']
    x = np.linspace(time, time+fitLen, fitLen * 50e3)
    v = [pt.data()['fitAmplitude'], pt.data()['fitTime'], pt.data()['fitRiseTau'], pt.data()['fitDecayTau']]
    y = fn.pspFunc(v, x, risePower=2.0) + data[np.argwhere(data.xvals('Time')>time)[0]-1]
    pw2.plot(x, y, pen='b')
Esempio n. 2
0
def processEventFits(events, startEvent, stopEvent, opts):
    ## This function does all the processing work for EventFitter.
    dt = opts['dt']
    origTau = opts['tau']
    multiFit = opts['multiFit']
    waveform = opts['waveform']
    tvals = opts['tvals']
    
    nFields = len(events.dtype.fields)
    
    dtype = [(n, events[n].dtype) for n in events.dtype.names]
    output = np.empty(len(events), dtype=dtype + [
        ('fitAmplitude', float), 
        ('fitTime', float),
        ('fitRiseTau', float), 
        ('fitDecayTau', float), 
        ('fitTimeToPeak', float),
        ('fitError', float),
        ('fitFractionalError', float),
        ('fitLengthOverDecay', float),
    ])
    
    offset = 0 ## not all input events will produce output events; offset keeps track of the difference.

    outputState = {
        'guesses': [],
        'eventData': [], 
        'indexes': [], 
        'xVals': [],
        'yVals': []
    }
    
    for i in range(startEvent, stopEvent):
        start = events[i]['time']
        #sliceLen = 50e-3
        sliceLen = dt*300. ## Ca2+ events are much longer than 50ms
        if i+1 < len(events):
            nextStart = events[i+1]['time']
            sliceLen = min(sliceLen, nextStart-start)
                
        guessLen = events[i]['len']*dt
        tau = origTau
        if tau is not None:
            guessLen += tau*2.
        #print i, guessLen, tau, events[i]['len']*dt

        #sliceLen = 50e-3
        sliceLen = guessLen
        if i+1 < len(events):  ## cut slice back if there is another event coming up
            nextStart = events[i+1]['time']
            sliceLen = min(sliceLen, nextStart-start)
        
        
        ## Figure out from where to pull waveform data that will be fitted
        startIndex = np.argwhere(tvals>=start)[0][0]
        stopIndex = startIndex + int(sliceLen/dt)
        eventData = waveform[startIndex:stopIndex]
        times = tvals[startIndex:stopIndex]
        #print i, startIndex, stopIndex, dt
        if len(times) < 4:  ## PSP fit requires at least 4 points; skip this one
            offset += 1
            continue
        
        ## reconvolve this chunk of the signal if it was previously deconvolved
        if tau is not None:
            eventData = functions.expReconvolve(eventData, tau=tau, dt=dt)
        #print i, len(eventData)
        ## Make guesses as to the shape of the event
        mx = eventData.max()
        mn = eventData.min()
        if mx > -mn:
            peakVal = mx
        else:
            peakVal = mn
        guessAmp = peakVal * 2  ## fit converges more reliably if we start too large
        guessRise = guessLen/4.
        guessDecay = guessLen/2.
        guessStart = times[0]
        
        zc = functions.zeroCrossingEvents(eventData - (peakVal/3.))
        ## eliminate events going the wrong direction
        if len(zc) > 0:
            if guessAmp > 0:
                zc = zc[zc['peak']>0]
            else:
                zc = zc[zc['peak']<0]
        #print zc    
        ## measure properties for the largest event within 10ms of start
        zc = zc[zc['index'] < 10e-3/dt]
        if len(zc) > 0:
            if guessAmp > 0:
                zcInd = np.argmax(zc['sum']) ## the largest event in this clip
            else:
                zcInd = np.argmin(zc['sum']) ## the largest event in this clip
            zcEv = zc[zcInd]
            #guessLen = dt*zc[zcInd]['len']
            guessRise = .1e-3 #dt*zcEv['len'] * 0.2
            guessDecay = dt*zcEv['len'] * 0.8 
            guessStart = times[0] + dt*zcEv['index'] - guessRise*3.
            
            ## cull down the data set if possible
            cullLen = zcEv['index'] + zcEv['len']*3
            if len(eventData) > cullLen:
                eventData = eventData[:cullLen]
                times = times[:cullLen]
                
            
        ## fitting to exponential rise * decay
        ## parameters are [amplitude, x-offset, rise tau, fall tau]
        guess = [guessAmp, guessStart, guessRise, guessDecay]
        #guess = [amp, times[0], guessLen/4., guessLen/2.]  ## careful! 
        bounds = [
            sorted((guessAmp * 0.1, guessAmp)),
            sorted((guessStart-min(guessRise, 0.01), guessStart+guessRise*2)), 
            sorted((dt*0.5, guessDecay)),
            sorted((dt*0.5, guessDecay * 50.))
        ]
        yVals = eventData.view(np.ndarray)
        
        fit = functions.fitPsp(times, yVals, guess=guess, bounds=bounds, multiFit=multiFit)
        
        computed = functions.pspFunc(fit, times)
        peakTime = functions.pspMaxTime(fit[2], fit[3])
        diff = (yVals - computed)
        err = (diff**2).sum()
        fracError = diff.std() / computed.std()
        lengthOverDecay = (times[-1] - fit[1]) / fit[3]  # ratio of (length of data that was fit : decay constant)
        output[i-offset] = tuple(events[i]) + tuple(fit) + (peakTime, err, fracError, lengthOverDecay)
        #output['fitTime'] += output['time']
            
        #print fit
        #self.events.append(eventData)
        
        outputState['guesses'].append(guess)
        outputState['eventData'].append(eventData)
        outputState['indexes'].append(i)
        outputState['xVals'].append(times)
        outputState['yVals'].append(computed)
        

    if offset > 0:
        output = output[:-offset]
        
    outputState['output'] = output
        
    return outputState
Esempio n. 3
0
 def process(self, waveform, events, display=True):
     self.deletedFits = []
     for item in self.plotItems:
         try:
             item.sigClicked.disconnect(self.fitClicked)
         except:
             pass
     self.plotItems = []
     
     tau = waveform.infoCopy(-1).get('expDeconvolveTau', None)
     dt = waveform.xvals(0)[1] - waveform.xvals(0)[0]
     opts = {
         'dt': dt, 'tau': tau, 'multiFit': self.ctrls['multiFit'].isChecked(),
         'waveform': waveform.view(np.ndarray),
         'tvals': waveform.xvals('Time'),
     }
     
     
     #if not self.ctrls['parallel'].isChecked():
     output = processEventFits(events, startEvent=0, stopEvent=len(events), opts=opts)
     guesses = output['guesses']
     eventData = output['eventData']
     indexes = output['indexes']
     xVals = output['xVals']
     yVals = output['yVals']
     output = output['output']
     #else:
         #print "parallel:", self.pool, self.poolSize
         #results = []
         #nProcesses = self.ctrls['nProcesses'].value()
         #evPerProcess = int(len(events) / nProcesses)
         #start = 0
         #for i in range(nProcesses):
             #stop = start + evPerProcess
             #if stop > len(events):
                 #stop = len(events)
             #args = (events, start, stop, opts)
             #results.append(self.pool.apply_async(processEventFits, args))
             #print "started process", start, stop
             #start = stop
         #data = []
         #guesses = []
         #eventData = []
         #indexes = []
         #xVals = []
         #yVals = []
         #for res in results:  ## reconstruct results here
             #print "getting result", res
             #output = res.get(10)
             #data.append(output['output'])
             #guesses.extend(output['guesses'])
             #eventData.extend(output['eventData'])
             #indexes.extend(output['indexes'])
             #xVals.extend(output['xVals'])
             #yVals.extend(output['yVals'])
         #output = np.concatenate(data)
         
     for i in range(len(indexes)):            
         if display and self['plot'].isConnected():
             if self.ctrls['plotFits'].isChecked():
                 item = pg.PlotDataItem(x=xVals[i], y=yVals[i], pen=(0, 0, 255), clickable=True)
                 item.setZValue(100)
                 self.plotItems.append(item)
                 item.eventIndex = indexes[i]
                 item.sigClicked.connect(self.fitClicked)
                 item.deleted = False
             if self.ctrls['plotGuess'].isChecked():
                 item2 = pg.PlotDataItem(x=xVals[i], y=functions.pspFunc(guesses[i], xVals[i]), pen=(255, 0, 0))
                 item2.setZValue(100)
                 self.plotItems.append(item2)
             if self.ctrls['plotEvents'].isChecked():
                 item2 = pg.PlotDataItem(x=xVals[i], y=eventData[i], pen=(0, 255, 0))
                 item2.setZValue(100)
                 self.plotItems.append(item2)
             #plot = self.plot.connections().keys()[0].node().getPlot()
             #plot.addItem(item)
         
     self.outputData = output
     return {'output': output, 'plot': self.plotItems}
Esempio n. 4
0
File: Scan.py Progetto: ablot/acq4
 def displayData(self, fh, plot, pen, evTime=None, eventFilter=None):
     """
     Display data for a single site in a plot--ephys trace, detected events
     Returns all items added to the plot.
     """
     pen = pg.mkPen(pen)
     
     items = []
     if isinstance(fh, basestring):
         fh = self.source()[fh]
     if fh.isDir():
         fh = self.dataModel.getClampFile(fh)
         
     ## plot all data, incl. events
     data = fh.read()['primary']
     data = fn.besselFilter(data, 4e3)
     pc = plot.plot(data, pen=pen, clear=False)
     items.append(pc)
     
     ## mark location of event if an event index was given
     if evTime is not None:
         #pos = float(index)/len(data)
         pos = evTime / data.xvals('Time')[-1]
         #print evTime, data.xvals('Time')[-1], pos
         #print index
         arrow = pg.CurveArrow(pc, pos=pos)
         plot.addItem(arrow)
         items.append(arrow)
         
     events = self.getEvents(fh)['events']
     
     if eventFilter is not None:
         events = eventFilter(events)
     
     ## draw ticks over all detected events
     if len(events) > 0:
         if 'fitTime' in events.dtype.names:
             times = events['fitTime']
             ticks = pg.VTickGroup(times, [0.9, 1.0], pen=pen)
             plot.addItem(ticks)
             items.append(ticks)
             #self.mapTicks.append(ticks)
             
         ## draw event fits
         evPen = pg.mkPen(pen)
         c = evPen.color()
         c.setAlpha(c.alpha()/2)
         evPen.setColor(c)
         for ev in events:
             time = ev['fitTime']
             try:
                 fitLen = ev['fitDecayTau']*ev['fitLengthOverDecay']
             except IndexError:
                 fitLen = ev['fitDecayTau']*4.
             x = np.linspace(time, time+fitLen, fitLen * 50e3)
             v = [ev['fitAmplitude'], ev['fitTime'], ev['fitRiseTau'], ev['fitDecayTau']]
             y = fn.pspFunc(v, x, risePower=2.0) + data[np.argwhere(data.xvals('Time')>time)[0]-1]
             evc = plot.plot(x, y, pen=evPen)
             evc.setZValue(pc.zValue()-100)
             
     return items