def process(self, data, display=True): params = ['Amp1', 'Amp2', 'Time', 'Rise', 'Decay', 'Decay2'] guess = tuple([self.ctrls['guess' + name].value() for name in params]) bounds = [(self.ctrls['min' + name].value(), self.ctrls['max' + name].value()) for name in params] rp = self.ctrls['risePower'].value() minTime = self.ctrls['minTime'].value() times = data.xvals('Time') fullTimes = times data = data.view(np.ndarray) startInd = np.argwhere(times>=minTime)[0] times = times[startInd:] data = data[startInd:] ## Ignore specified guess amplitude; make a better guess. mx = data.max() mn = data.min() if abs(mn) > abs(mx): amp = mn else: amp = mx params[0] = amp params[1] = amp fit = functions.fitDoublePsp(x=times, y=data, guess=guess, bounds=bounds, risePower=rp) if self.ctrls['computeWaveform'].isChecked(): fitData = functions.doublePspFunc(fit, fullTimes, rp) else: fitData = None return {'fitParams': fit, 'fitYData': fitData, 'fitXData': fullTimes}
def process(self, data, display=True): rp = self.ctrls['risePower'].value() stimTime = self.ctrls['stimulusTime'].value() times = data.xvals('Time') dt = times[1] - times[0] data1 = data.view(np.ndarray) if stimTime > times[-1]: raise Exception("stimulusTime is larger than length of input data.") stimInd = np.argwhere(times>=stimTime)[0][0] # 1. make sure offset is removed offset = np.median(data1[:stimInd]) data2 = data1 - offset # 2. check for zero-crossing events within 4ms after stimulus cross = functions.zeroCrossingEvents(data2[stimInd:]) maxInd = 4e-3 / dt minLength = self.ctrls['minDirectDuration'].value() / dt gotEvent = None for start, length, sum, peak in cross: if start > maxInd: break if length < minLength: continue if gotEvent is None or length > gotEvent[1]: gotEvent = (start+stimInd, length) #if len(cross) == 0: ## must be a single large event #gotEvent = (0, len(data2)-stimInd) fitParams = dict( directFitAmp1=0., directFitAmp2=0., directFitTime=0., directFitRise=0., directFitDecay1=0., directFitDecay2=0., directFitPeakTime=0., directFitPeak=0., directFitSubtracted=False, directFitValid=False, ) # 3. if there is no large event near stimulus, return original data if gotEvent is None: if display: self.plotItem.clear() return {'output': data, 'fitParams': fitParams, 'plot': self.plotItem} #print "============" #print stimInd #print gotEvent #print cross[:20] # 4. guess amplitude, tau from detected event evStart = gotEvent[0] evEnd = evStart + gotEvent[1] evRgn = data2[evStart:evEnd] #pg.plot(evRgn) mx = evRgn.max() mn = evRgn.min() ampGuess = mx if abs(mx) > abs(mn) else mn tauGuess = gotEvent[1] * dt if ampGuess < 0: ampBound = [None, 0] else: ampBound = [0, None] # 5. fit guess = [ampGuess*2, ampGuess*2, stimTime, 1e-3, tauGuess*0.5, tauGuess*2] bounds = [ ampBound, ampBound, [stimTime, stimTime+4e-3], [1e-4, 100e-3], [1e-3, 1], [5e-3, 10], ] #print guess #print bounds endInd = evStart + gotEvent[1] * 10 fitYData = data2[stimInd:endInd] fitXData = times[stimInd:endInd] fit = functions.fitDoublePsp(x=fitXData, y=fitYData, guess=guess, bounds=bounds, risePower=rp) # 6. subtract fit from original data (offset included), return y = functions.doublePspFunc(fit, times, rp) if display: self.plotItem.setData(x=fitXData, y=y[stimInd:endInd], pen=self.ctrls['plotColor'].color()) ## prepare list of fit params for output (xMax, yMax) = functions.doublePspMax(fit) xMax -= fit[2] ## really interested in time-to-peak, not the exact peak time. fitParams = dict( directFitAmp1=fit[0], directFitAmp2=fit[1], directFitTime=fit[2], directFitRise=fit[3], directFitDecay1=fit[4], directFitDecay2=fit[5], directFitPeakTime=xMax, directFitPeak=yMax, directFitSubtracted=None, directFitValid=True, ) if self.ctrls['subtractDirect'].isChecked(): out = metaarray.MetaArray(data-y, info=data.infoCopy()) fitParams['directFitSubtracted'] = True else: out = data fitParams['directFitSubtracted'] = False return {'fitParams': fitParams, 'output': out, 'plot': self.plotItem}