def outputPower(self, forceUpdate=False): """ Return the output power of the laser in Watts. The power returned does not account for the effects of pockels cell, shutter, etc. This information is determined in one of a few ways: 1. The laser directly reports its power output (function needs to be reimplemented in subclass) 2. A photodiode receves a small fraction of the beam and reports an estimated power 3. The output power is specified in the config file Use checkPowerValidity(power) to determine whether this level is within the expected range. Subsequent calls to outputPower() may return a cached value (the maximum age of this value is determined by the powerUpdateInterval config parameter). Use forceUpdate=True to ignore any cached values. """ now = ptime.time() needUpdate = (forceUpdate is True or self.params['currentPower'] is None or self._lastPowerMeasureTime is None or now - self._lastPowerMeasureTime > self.params['powerUpdateInterval']) if needUpdate: self.params['currentPower'] = self._measurePower() self._lastPowerMeasureTime = ptime.time() return self.params['currentPower']
def call(self, fn, *args, **kargs): t = ptime.time() ret = LIB('functions', fn)(*args, **kargs) t2 = ptime.time() if t2-t > 4.0: print backtrace() print "function took %f sec:" % (t2-t), fn, args, kargs return ret
def run(self): """Main loop for patch thread. This is where protocols are executed and data collected.""" try: with MutexLocker(self.lock) as l: self.stopThread = False clamp = self.manager.getDevice(self.clampName) daqName = clamp.listChannels().values()[0]['device'] ## Just guess the DAQ by checking one of the clamp's channels clampName = self.clampName self.paramsUpdated = True l.unlock() lastTime = None while True: ## copy in parameters from GUI updateCommand = False l.relock() if self.paramsUpdated: with self.ui.paramLock: params = self.ui.params.copy() self.paramsUpdated = False updateCommand = True l.unlock() ## run protocol and analysis try: self.runOnce(params, l, clamp, daqName, clampName) except: printExc("Error running/analyzing patch protocol") lastTime = ptime.time()-params['recordTime'] ## This is not a proper 'cycle time', but instead enforces a minimum interval between cycles (but this can be very important for performance) ## sleep until it is time for the next run c = 0 stop = False while True: ## check for stop button every 100ms if c % 10 == 0: l.relock() if self.stopThread: l.unlock() stop = True break l.unlock() now = ptime.time() if now >= (lastTime+params['cycleTime']): break time.sleep(10e-3) ## Wake up every 10ms c += 1 if stop: break except: printExc("Error in patch acquisition thread, exiting.")
def contReadTest(): print ":::::::::::::::::: Continuous Read Test :::::::::::::::::::::" task = n.createTask() task.CreateAIVoltageChan("/Dev1/ai0", "", n.Val_RSE, -10., 10., n.Val_Volts, None) task.CfgSampClkTiming(None, 10000.0, n.Val_Rising, n.Val_ContSamps, 4000) task.start() t = ptime.time() for i in range(0, 10): data, size = task.read(1000) print "Cont read %d - %d samples, %fsec" % (i, size, ptime.time() - t) t = ptime.time() task.stop()
def run(self): """Main loop for patch thread. This is where protocols are executed and data collected.""" try: with self.lock: self.stopThread = False clamp = self.manager.getDevice(self.clampName) daqName = clamp.listChannels().values()[0][ 'device'] ## Just guess the DAQ by checking one of the clamp's channels clampName = self.clampName self.paramsUpdated = True lastTime = None while True: ## copy in parameters from GUI updateCommand = False with self.lock: if self.paramsUpdated: with self.ui.paramLock: params = self.ui.params.copy() self.paramsUpdated = False updateCommand = True ## run protocol and analysis try: self.runOnce(params, clamp, daqName, clampName) except: printExc("Error running/analyzing patch protocol") lastTime = ptime.time() - params[ 'recordTime'] ## This is not a proper 'cycle time', but instead enforces a minimum interval between cycles (but this can be very important for performance) ## sleep until it is time for the next run c = 0 stop = False while True: ## check for stop button every 100ms if c % 10 == 0: with self.lock: if self.stopThread: stop = True break now = ptime.time() if now >= (lastTime + params['cycleTime']): break time.sleep(10e-3) ## Wake up every 10ms c += 1 if stop: break except: printExc("Error in patch acquisition thread, exiting.")
def mark(self, msg=None): if self.disabled: return if msg is None: msg = str(self.markCount) self.markCount += 1 t1 = ptime.time() msg2 = " "+self.msg+" "+msg+" "+"%gms" % ((t1-self.t1)*1000) if self.delayed: self.msgs.append(msg2) else: print msg2 self.t1 = ptime.time() ## don't measure time it took to print
def start(self): self.writeTaskData() ## Only writes if needed. self.result = None ## TODO: Reserve all hardware needed before starting tasks keys = list(self.tasks.keys()) ## move clock task key to the end if self.clockSource in keys: #print " Starting %s last" % str(tt) keys.remove(self.clockSource) keys.append(self.clockSource) for k in keys[:-1]: #print "starting task", k self.tasks[k].start() #self.startTime = time.clock() self.startTime = ptime.time() #print "start time:", self.startTime self.tasks[keys[-1]].start() #print "starting clock task:", keys[-1] # for k in keys: # if not self.tasks[k].isRunning(): # print "Warning: task %s didn't start" % str(k) if self.triggerChannel is not None: ## Set up callback to record time when trigger starts pass
def handleFrame(self, frame): ## Request each device handles its own data ## Note that this is only used to display results; data storage is handled by Manager and the individual devices. #print "got frame", frame prof = Profiler('TaskRunner.handleFrame', disabled=True) for d in frame['result']: try: if d != 'protocol': self.docks[d].widget().handleResult( frame['result'][d], frame['params']) prof.mark('finished %s' % d) except: printExc("Error while handling result from device '%s'" % d) self.sigNewFrame.emit(frame) prof.mark('emit newFrame') ## If this is a single-mode task and looping is turned on, schedule the next run if self.loopEnabled: ct = self.protoStateGroup.state()['loopCycleTime'] t = max(0, ct - (ptime.time() - self.lastProtoTime)) Qt.QTimer.singleShot(int(t * 1000.), self.loop) prof.finish() # good time to collect garbage gc.collect()
def newFrames(self): """Return a list of all frames acquired since the last call to newFrames.""" with self.camLock: nFrames = self.mmc.getRemainingImageCount() if nFrames == 0: return [] now = ptime.time() if self.lastFrameTime is None: self.lastFrameTime = now dt = (now - self.lastFrameTime) / nFrames frames = [] with self.camLock: for i in range(nFrames): frame = {} frame['time'] = self.lastFrameTime + (dt * (i + 1)) frame['id'] = self.frameId frame['data'] = self.mmc.popNextImage().T frames.append(frame) self.frameId += 1 self.lastFrame = frame self.lastFrameTime = now return frames
def start(self): self.writeTaskData() ## Only writes if needed. self.result = None ## TODO: Reserve all hardware needed before starting tasks keys = self.tasks.keys() ## move clock task key to the end if self.clockSource in keys: #print " Starting %s last" % str(tt) keys.remove(self.clockSource) keys.append(self.clockSource) for k in keys[:-1]: #print "starting task", k self.tasks[k].start() #self.startTime = time.clock() self.startTime = ptime.time() #print "start time:", self.startTime self.tasks[keys[-1]].start() #print "starting clock task:", keys[-1] # for k in keys: # if not self.tasks[k].isRunning(): # print "Warning: task %s didn't start" % str(k) if self.triggerChannel is not None: ## Set up callback to record time when trigger starts pass
def generateTask(self, dh, params=None, progressDlg=None): #prof = Profiler("Generate Task: %s" % str(params)) ## Never put {} in the function signature if params is None: params = {} prot = {'protocol': self.protoStateGroup.state()} # Disable timeouts for these tasks because we don't know how long to wait # for external triggers. TODO: use the default timeout, but also allow devices # in the task to modify the default. prot['protocol']['timeout'] = None #prof.mark('protocol state') store = (dh is not None) prot['protocol']['storeData'] = store if store: if params != {}: name = '_'.join(map(lambda i: '%03d'%i, params.values())) #print "mkdir", name info = params.copy() info['dirType'] = 'Protocol' dh1 = dh.mkdir(name, info=info) #prof.mark('create storage dir') else: dh1 = dh prot['protocol']['storageDir'] = dh1 #prof.mark('selected storage dir.') prot['protocol']['name'] = self.currentTask.fileName for d in self.currentTask.devices: if self.currentTask.deviceEnabled(d): ## select out just the parameters needed for this device p = dict([(i[1], params[i]) for i in params.keys() if i[0] == d]) ## Ask the device to generate its task command if d not in self.docks: raise HelpfulException("The device '%s' currently has no dock loaded." % d, reasons=[ "This device name does not exist in the system's configuration", "There was an error when creating the device at program startup", ], tags={}, importance=8, docSections=['userGuide/modules/TaskRunner/loadingNonexistentDevices'] ) prot[d] = self.docks[d].widget().generateTask(p) #prof.mark("get task from %s" % d) #print prot['protocol']['storageDir'].name() if progressDlg is not None: progressDlg.setValue(progressDlg.value()+1) ## only do UI updates every 1 sec. now = ptime.time() if now - self.lastQtProcessTime > 1.0: self.lastQtProcessTime = now QtGui.QApplication.processEvents() if progressDlg.wasCanceled(): raise Exception("Target sequence computation canceled by user.") #prof.mark('done') return prot
def callBack1(self, *args): #print "Callback1: args:", args if args[3] == lib.qcCallbackExposeDone: now = ptime.time() self.frameTimes[args[1]] = now #print "Exposure done. Time: %f, Duration: %f" % return if args[2] != 0: for x in lib('enums', 'QCam_Err'): if lib('enums', 'QCam_Err')[x] == args[2]: raise QCamFunctionError(args[2], "There was an error during QueueFrame/Callback. Error code = %s" %(x)) #self.mutex.lock() with self.mutex: #print "Mutex locked from qcam.callBack1()" #print "set last index", args[1] self.lastImages.append({'id':self.counter, 'data':self.arrays[args[1]].copy(), 'time': self.frameTimes[args[1]], 'exposeDoneTime':self.frameTimes[args[1]]}) self.counter += 1 if self.stopSignal == False: #self.mutex.unlock() #size = self.getImageSize() #if len(self.arrays[self.i]) != size/2: #self.frames[self.i],self.arrays[self.i] = self.mkFrame() #### Need to check that frame is the right size given settings, and if not, make a new frame. self.call(lib.QueueFrame, self.handle, self.frames[self.i], self.fnp1, lib.qcCallbackDone|lib.qcCallbackExposeDone, 0, self.i) self.i = ( self.i+1) % self.ringSize
def handleFrame(self, frame): ## Request each device handles its own data ## Note that this is only used to display results; data storage is handled by Manager and the individual devices. #print "got frame", frame prof = Profiler('TaskRunner.handleFrame', disabled=True) for d in frame['result']: try: if d != 'protocol': self.docks[d].widget().handleResult(frame['result'][d], frame['params']) prof.mark('finished %s' % d) except: printExc("Error while handling result from device '%s'" % d) #self.emit(QtCore.SIGNAL('newFrame'), frame) self.sigNewFrame.emit(frame) prof.mark('emit newFrame') ## If this is a single-mode task and looping is turned on, schedule the next run if self.loopEnabled: ct = self.protoStateGroup.state()['loopCycleTime'] t = max(0, ct - (ptime.time() - self.lastProtoTime)) QtCore.QTimer.singleShot(int(t*1000.), self.loop) prof.finish() # good time to collect garbage gc.collect()
def newFrames(self): """Return a list of all frames acquired since the last call to newFrames.""" now = ptime.time() dt = now - self.lastFrameTime exp = self.getParam('exposure') bin = self.getParam('binning') fps = 1.0 / (exp + (40e-3 / (bin[0] * bin[1]))) nf = int(dt * fps) if nf == 0: return [] region = self.getParam('region') bg = self.getBackground()[region[0]:region[0] + region[2], region[1]:region[1] + region[3]] ## update cells spikes = np.random.poisson(min(dt, 0.4) * self.cells['rate']) self.cells['value'] *= np.exp(-dt / self.cells['decayTau']) self.cells['value'] = np.clip(self.cells['value'] + spikes * 0.2, 0, 1) shape = region[2:] self.lastFrameTime = now + exp data = self.getNoise(shape) data[data < 0] = 0 data += bg * (exp * 1000) ## draw cells px = (self.pixelVectors()[0]**2).sum()**0.5 ## Generate transform that maps grom global coordinates to image coordinates cameraTr = pg.SRTTransform3D(self.inverseGlobalTransform()) # note we use binning=(1,1) here because the image is downsampled later. frameTr = self.makeFrameTransform(region, [1, 1]).inverted()[0] tr = pg.SRTTransform(frameTr * cameraTr) for cell in self.cells: w = cell['size'] / px pos = pg.Point(cell['x'], cell['y']) imgPos = tr.map(pos) start = (int(imgPos.x()), int(imgPos.y())) stop = (int(start[0] + w), int(start[1] + w)) val = cell['intensity'] * cell['value'] * self.getParam('exposure') data[max(0, start[0]):max(0, stop[0]), max(0, start[1]):max(0, stop[1])] += val data = fn.downsample(data, bin[0], axis=0) data = fn.downsample(data, bin[1], axis=1) data = data.astype(np.uint16) self.frameId += 1 frames = [] for i in range(nf): frames.append({ 'data': data, 'time': now + (i / fps), 'id': self.frameId }) return frames
def newFrames(self): """Return a list of all frames acquired since the last call to newFrames.""" now = ptime.time() dt = now - self.lastFrameTime exp = self.getParam('exposure') region = self.getParam('region') bg = self.getBackground()[region[0]:region[0]+region[2], region[1]:region[1]+region[3]] ## update cells spikes = np.random.poisson(max(dt, 0.4) * self.cells['rate']) self.cells['value'] *= np.exp(-dt / self.cells['decayTau']) self.cells['value'] = np.clip(self.cells['value'] + spikes * 0.2, 0, 1) shape = region[2:] bin = self.getParam('binning') nf = int(dt / (exp+(40e-3/(bin[0]*bin[1])))) if nf > 0: self.lastFrameTime = now #data = np.random.normal(size=(shape[0], shape[1]), loc=100, scale=50) data = self.getNoise(shape) data[data<0] = 0 #sig = self.signal[region[0]:region[0]+region[2], region[1]:region[1]+region[3]] data += bg * (exp*1000) ## draw cells px = (self.pixelVectors()[0]**2).sum() ** 0.5 ## Generate transform that maps grom global coordinates to image coordinates cameraTr = pg.SRTTransform3D(self.inverseGlobalTransform()) frameTr = self.makeFrameTransform(region, [1, 1]).inverted()[0] # note we use binning=(1,1) here because the image is downsampled later. tr = pg.SRTTransform(frameTr * cameraTr) for cell in self.cells: w = cell['size'] / px pos = pg.Point(cell['x'], cell['y']) imgPos = tr.map(pos) start = (int(imgPos.x()), int(imgPos.y())) stop = (start[0]+w, start[1]+w) val = cell['intensity'] * cell['value'] * self.getParam('exposure') data[max(0,start[0]):max(0,stop[0]), max(0,start[1]):max(0,stop[1])] += val data = fn.downsample(data, bin[0], axis=0) data = fn.downsample(data, bin[1], axis=1) data = data.astype(np.uint16) self.frameId += 1 frames = [] for i in range(nf): frames.append({'data': data, 'time': now, 'id': self.frameId}) return frames else: return []
def collectBgClicked(self, checked): if checked: if not self.ui.contAvgBgCheck.isChecked(): self.backgroundFrame = None ## reset background frame self.bgFrameCount = 0 self.bgStartTime = ptime.time() self.ui.collectBgBtn.setText("Collecting...") else: self.ui.collectBgBtn.setText("Collect Background")
def stop(self, abort=False): if abort: with self.abortLock: print "Abort!" self.aborted = True with MutexLocker(self.dev.lock): for t in self.daqTasks: t.stop(abort=abort) self.dev.lastRunTime = ptime.time()
def stop(self, abort=False): if abort: with self.abortLock: print("Abort!") self.aborted = True with self.dev.lock: for t in self.daqTasks: t.stop(abort=abort) self.dev.lastRunTime = ptime.time()
def runSequence(self, store=True): ## Disable all start buttons self.enableStartBtns(False) # good time to collect garbage gc.collect() ## Find all top-level items in the sequence parameter list try: ## make sure all devices are reporting their correct sequence lists items = self.ui.sequenceParamList.listParams() ## Generate parameter space params = OrderedDict() paramInds = OrderedDict() linkedParams = {} pLen = 1 for i in items: key = i[:2] params[key] = i[2] paramInds[key] = range(len(i[2])) pLen *= len(i[2]) linkedParams[key] = i[3] ## Set storage dir if store: currentDir = self.manager.getCurrentDir() name = self.currentTask.name() if name is None: name = 'protocol' info = self.taskInfo(params) info['dirType'] = 'ProtocolSequence' dh = currentDir.mkdir(name, autoIncrement=True, info=info) else: dh = None ## Tell devices to prepare for task start. for d in self.currentTask.devices: if self.currentTask.deviceEnabled(d): self.docks[d].widget().prepareTaskStart() #print params, linkedParams ## Generate the complete array of command structures. This can take a long time, so we start a progress dialog. with pg.ProgressDialog("Generating task commands..", 0, pLen) as progressDlg: self.lastQtProcessTime = ptime.time() prot = runSequence(lambda p: self.generateTask(dh, p, progressDlg), paramInds, paramInds.keys(), linkedParams=linkedParams) if dh is not None: dh.flushSignals() ## do this now rather than later when task is running self.sigTaskSequenceStarted.emit({}) logMsg('Started %s task sequence of length %i' %(self.currentTask.name(),pLen), importance=6) #print 'PR task positions: self.taskThread.startTask(prot, paramInds) except: self.enableStartBtns(True) raise
def start(self, block=True): #print "PVCam: start" if not self.isRunning(): self.lastIndex = None #print " not running already; start camera" Camera.start(self, block) ## Start the acquisition thread self.startTime = ptime.time() ## pvcams can take a long time if block: tm = self.getParam('triggerMode') if tm != 'Normal': #print " waiting for trigger to arm" waitTime = 0.3 ## trigger needs about 300ms to prepare (?) else: waitTime = 0 sleepTime = (self.startTime + waitTime) - ptime.time() if sleepTime > 0: #print " sleep for", sleepTime time.sleep(sleepTime)
def runSingle(self, store=True): if self.protoStateGroup.state()['loop']: self.loopEnabled = True # good time to collect garbage gc.collect() #print "RunSingle" #if self.taskThread.isRunning(): #import traceback #traceback.print_stack() #print "Task already running." self.lastProtoTime = ptime.time() ## Disable all start buttons self.enableStartBtns(False) ## Set storage dir try: if store: currentDir = self.manager.getCurrentDir() name = self.currentTask.name() if name is None: name = 'protocol' info = self.taskInfo() info['dirType'] = 'Protocol' ## Create storage directory with all information about the task to be executed dh = currentDir.mkdir(name, autoIncrement=True, info=info) else: dh = None ## Tell devices to prepare for task start. for d in self.currentTask.devices: if self.currentTask.deviceEnabled(d): self.docks[d].widget().prepareTaskStart() ## Generate executable conf from task object prot = self.generateTask(dh) #print prot self.sigTaskSequenceStarted.emit({}) #print "runSingle: Starting taskThread.." self.taskThread.startTask(prot) #print "runSingle: taskThreadStarted" except: exc = sys.exc_info() self.enableStartBtns(True) self.loopEnabled = False #print "Error starting task. " raise HelpfulException("Error occurred while starting task", exc=exc)
def newFrame(self, frame): lf = None if self.nextFrame is not None: lf = self.nextFrame elif self.currentFrame is not None: lf = self.currentFrame if lf is not None: fps = frame.info()['fps'] if fps is not None: self.ui.fpsLabel.setValue(fps) ## Update ROI plots, if any #if self.ui.checkEnableROIs.isChecked(): #self.addPlotFrame(frame) ## self.nextFrame gets picked up by drawFrame() at some point if self.nextFrame is not None: self.ui.displayPercentLabel.setValue(0.) else: self.ui.displayPercentLabel.setValue(100.) self.nextFrame = frame ## stop collecting bg frames if we are in static mode and time is up if self.ui.collectBgBtn.isChecked() and not self.ui.contAvgBgCheck.isChecked(): timeLeft = self.ui.bgTimeSpin.value() - (ptime.time()-self.bgStartTime) if timeLeft > 0: self.ui.collectBgBtn.setText("Collecting... (%d)" % int(timeLeft+1)) else: self.ui.collectBgBtn.setChecked(False) self.ui.collectBgBtn.setText("Collect Background") if self.ui.collectBgBtn.isChecked(): if self.ui.contAvgBgCheck.isChecked(): x = 1.0 - 1.0 / (self.ui.bgTimeSpin.value()+1.0) else: x = float(self.bgFrameCount)/(self.bgFrameCount + 1) self.bgFrameCount += 1 if self.backgroundFrame == None or self.backgroundFrame.shape != frame.data().shape: self.backgroundFrame = frame.data().astype(float) else: self.backgroundFrame = x * self.backgroundFrame + (1-x)*frame.data().astype(float) self.sigNewFrame.emit(self, frame)
def runSingle(self, store=True): if self.protoStateGroup.state()['loop']: self.loopEnabled = True # good time to collect garbage gc.collect() self.lastProtoTime = ptime.time() ## Disable all start buttons self.enableStartBtns(False) ## Set storage dir try: if store: currentDir = self.manager.getCurrentDir() name = self.currentTask.name() if name is None: name = 'protocol' info = self.taskInfo() info['dirType'] = 'Protocol' ## Create storage directory with all information about the task to be executed dh = currentDir.mkdir(name, autoIncrement=True, info=info) else: dh = None ## Tell devices to prepare for task start. for d in self.currentTask.devices: if self.currentTask.deviceEnabled(d): self.docks[d].widget().prepareTaskStart() ## Generate executable conf from task object prot = self.generateTask(dh) #print prot self.sigTaskSequenceStarted.emit({}) #print "runSingle: Starting taskThread.." self.taskThread.startTask(prot) #print "runSingle: taskThreadStarted" except: exc = sys.exc_info() self.enableStartBtns(True) self.loopEnabled = False #print "Error starting task. " raise HelpfulException("Error occurred while starting task", exc=exc)
def finish(self, msg=None): if self.disabled or self.finished: return if msg is not None: self.mark(msg) t1 = ptime.time() msg = self.msg + ' <<< Finished, total time: %gms' % ((t1-self.t0)*1000) if self.delayed: self.msgs.append(msg) if self.depth == 0: for line in self.msgs: print line Profiler.msgs = [] else: print msg Profiler.depth = self.depth self.finished = True
def newFrames(self): """Return a list of all frames acquired since the last call to newFrames.""" with self.camLock: index = self.cam.lastFrame() now = ptime.time() if self.lastFrameTime is None: self.lastFrameTime = now if index is None: ## no frames available yet return [] if index == self.lastIndex: ## no new frames since last check return [] self.stopOk = True ## Determine how many new frames have arrived since last check if self.lastIndex is not None: diff = (index - self.lastIndex) % self.ringSize if diff > (self.ringSize / 2): print("Image acquisition buffer is at least half full (possible dropped frames)") else: self.lastIndex = index-1 diff = 1 dt = (now - self.lastFrameTime) / diff frames = [] for i in range(diff): fInd = (i+self.lastIndex+1) % self.ringSize frame = {} frame['time'] = self.lastFrameTime + (dt * (i+1)) frame['id'] = self.frameId frame['data'] = self.acqBuffer[fInd].copy() #print frame['data'] frames.append(frame) self.frameId += 1 self.lastFrame = frame self.lastFrameTime = now self.lastIndex = index return frames
def newFrames(self): """Return a list of all frames acquired since the last call to newFrames.""" with self.camLock: index = self.cam.lastFrame() now = ptime.time() if self.lastFrameTime is None: self.lastFrameTime = now if index is None: ## no frames available yet return [] if index == self.lastIndex: ## no new frames since last check return [] self.stopOk = True ## Determine how many new frames have arrived since last check if self.lastIndex is not None: diff = (index - self.lastIndex) % self.ringSize if diff > (self.ringSize / 2): print "Image acquisition buffer is at least half full (possible dropped frames)" else: self.lastIndex = index-1 diff = 1 dt = (now - self.lastFrameTime) / diff frames = [] for i in range(diff): fInd = (i+self.lastIndex+1) % self.ringSize frame = {} frame['time'] = self.lastFrameTime + (dt * (i+1)) frame['id'] = self.frameId frame['data'] = self.acqBuffer[fInd].copy() #print frame['data'] frames.append(frame) self.frameId += 1 self.lastFrame = frame self.lastFrameTime = now self.lastIndex = index return frames
def __init__(self, msg="Profiler", disabled=False, delayed=True, globalDelay=True): self.disabled = disabled if disabled: return self.markCount = 0 self.finished = False self.depth = Profiler.depth Profiler.depth += 1 if not globalDelay: self.msgs = [] self.delayed = delayed self.msg = " "*self.depth + msg msg2 = self.msg + " >>> Started" if self.delayed: self.msgs.append(msg2) else: print msg2 self.t0 = ptime.time() self.t1 = self.t0
def start(self): #print "start" with MutexLocker(self.dev.lock): lastRunTime = self.dev.lastRunTime if lastRunTime is None: #print " no wait" return # Task specifies that we have a minimum wait from the end of the previous # task to the start of this one. This is used in photostimulation experiments # that require variable downtime depending on the proximity of subsequent # stimulations. if 'minWaitTime' in self.cmd: while True: now = ptime.time() wait = min(0.1, self.cmd['minWaitTime'] - (now - lastRunTime)) if wait <= 0: break with self.abortLock: if self.aborted: return time.sleep(wait)
def start(self): #print "start" with self.dev.lock: lastRunTime = self.dev.lastRunTime if lastRunTime is None: #print " no wait" return # Task specifies that we have a minimum wait from the end of the previous # task to the start of this one. This is used in photostimulation experiments # that require variable downtime depending on the proximity of subsequent # stimulations. if 'minWaitTime' in self.cmd: while True: now = ptime.time() wait = min(0.1, self.cmd['minWaitTime'] - (now - lastRunTime)) if wait <= 0: break with self.abortLock: if self.aborted: return time.sleep(wait)
def callBack1(self, *args): #print "Callback1: args:", args if args[3] == lib.qcCallbackExposeDone: now = ptime.time() self.frameTimes[args[1]] = now #print "Exposure done. Time: %f, Duration: %f" % return if args[2] != 0: for x in lib('enums', 'QCam_Err'): if lib('enums', 'QCam_Err')[x] == args[2]: raise QCamFunctionError( args[2], "There was an error during QueueFrame/Callback. Error code = %s" % (x)) #self.mutex.lock() with self.mutex: #print "Mutex locked from qcam.callBack1()" #print "set last index", args[1] self.lastImages.append({ 'id': self.counter, 'data': self.arrays[args[1]].copy(), 'time': self.frameTimes[args[1]], 'exposeDoneTime': self.frameTimes[args[1]] }) self.counter += 1 if self.stopSignal == False: #self.mutex.unlock() #size = self.getImageSize() #if len(self.arrays[self.i]) != size/2: #self.frames[self.i],self.arrays[self.i] = self.mkFrame() #### Need to check that frame is the right size given settings, and if not, make a new frame. self.call(lib.QueueFrame, self.handle, self.frames[self.i], self.fnp1, lib.qcCallbackDone | lib.qcCallbackExposeDone, 0, self.i) self.i = (self.i + 1) % self.ringSize
def runOnce(self, params=None): # good time to collect garbage gc.collect() #print "TaskThread:runOnce" prof = Profiler("TaskRunner.TaskThread.runOnce", disabled=True, delayed=False) startTime = ptime.time() if params is None: params = {} with MutexLocker(self.lock) as l: l.unlock() ## Select correct command to execute cmd = self.task #print "Sequence array:", cmd.shape, cmd.infoCopy() if params is not None: for p in params: #print "Selecting %s: %s from sequence array" % (str(p), str(params[p])) cmd = cmd[p: params[p]] prof.mark('select command') #print "Task:", cmd ## Wait before starting if we've already run too recently #print "sleep until next run time..", ptime.time(), self.lastRunTime, cmd['protocol']['cycleTime'] while (self.lastRunTime is not None) and (ptime.time() < self.lastRunTime + cmd['protocol']['cycleTime']): l.relock() if self.abortThread or self.stopThread: l.unlock() #print "Task run aborted by user" return l.unlock() time.sleep(1e-3) #print "slept until", ptime.time() prof.mark('sleep') # If paused, hang here for a bit. emitSig = True while True: l.relock() if self.abortThread or self.stopThread: l.unlock() return pause = self.paused l.unlock() if not pause: break if emitSig: emitSig = False #self.emit(QtCore.SIGNAL('paused')) self.sigPaused.emit() time.sleep(10e-3) prof.mark('pause') #print "BEFORE:\n", cmd if type(cmd) is not dict: print "========= TaskRunner.runOnce cmd: ==================" print cmd print "========= TaskRunner.runOnce params: ==================" print "Params:", params print "===========================" raise Exception("TaskRunner.runOnce failed to generate a proper command structure. Object type was '%s', should have been 'dict'." % type(cmd)) task = self.dm.createTask(cmd) prof.mark('create task') self.lastRunTime = ptime.time() #self.emit(QtCore.SIGNAL('taskStarted'), params) try: l.relock() self._currentTask = task l.unlock() task.execute(block=False) self.sigTaskStarted.emit(params) prof.mark('execute') except: l.relock() self._currentTask = None l.unlock() try: task.stop(abort=True) except: pass printExc("\nError starting task:") exc = sys.exc_info() raise HelpfulException("\nError starting task:", exc) prof.mark('start task') ### Do not put code outside of these try: blocks; may cause device lockup try: ## wait for finish, watch for abort requests while True: if task.isDone(): prof.mark('task done') break l.relock() if self.abortThread: l.unlock() # should be taken care of in TaskThread.abort() #task.stop(abort=True) return l.unlock() time.sleep(1e-3) result = task.getResult() except: ## Make sure the task is fully stopped if there was a failure at any point. #printExc("\nError during task execution:") print "\nStopping task.." task.stop(abort=True) print "" raise HelpfulException("\nError during task execution:", sys.exc_info()) finally: l.relock() self._currentTask = None l.unlock() #print "\nAFTER:\n", cmd prof.mark('getResult') frame = {'params': params, 'cmd': cmd, 'result': result} #self.emit(QtCore.SIGNAL('newFrame'), frame) self.sigNewFrame.emit(frame) prof.mark('emit newFrame') if self.stopThread: raise Exception('stop', result) #print "Total run time: %gms" % ((ptime.time() - startTime) * 1000 ) ## Give everyone else a chance to catch up QtCore.QThread.yieldCurrentThread() prof.mark('yield') prof.finish()
def generateTask(self, dh, params=None, progressDlg=None): #prof = Profiler("Generate Task: %s" % str(params)) ## params should be in the form {(dev, param): value, ...} ## Generate executable conf from task object #prot = {'protocol': { #'duration': self.currentTask.conf['duration'], #'storeData': store, #'mode': 'single', #'name': self.currentTask.fileName, #'cycleTime': self.currentTask.conf['cycleTime'], #}} #print "generate:", params ## Never put {} in the function signature if params is None: params = {} prot = {'protocol': self.protoStateGroup.state()} #prof.mark('protocol state') store = (dh is not None) prot['protocol']['storeData'] = store if store: if params != {}: name = '_'.join(map(lambda i: '%03d'%i, params.values())) #print "mkdir", name info = params.copy() info['dirType'] = 'Protocol' dh1 = dh.mkdir(name, info=info) #prof.mark('create storage dir') else: dh1 = dh prot['protocol']['storageDir'] = dh1 #prof.mark('selected storage dir.') prot['protocol']['name'] = self.currentTask.fileName for d in self.currentTask.devices: if self.currentTask.deviceEnabled(d): ## select out just the parameters needed for this device p = dict([(i[1], params[i]) for i in params.keys() if i[0] == d]) ## Ask the device to generate its task command if d not in self.docks: raise HelpfulException("The device '%s' currently has no dock loaded." % d, reasons=[ "This device name does not exist in the system's configuration", "There was an error when creating the device at program startup", ], tags={}, importance=8, docSections=['userGuide/modules/TaskRunner/loadingNonexistentDevices'] ) prot[d] = self.docks[d].widget().generateTask(p) #prof.mark("get task from %s" % d) #print prot['protocol']['storageDir'].name() if progressDlg is not None: progressDlg.setValue(progressDlg.value()+1) ## only do UI updates every 1 sec. now = ptime.time() if now - self.lastQtProcessTime > 1.0: self.lastQtProcessTime = now QtGui.QApplication.processEvents() if progressDlg.wasCanceled(): raise Exception("Target sequence computation canceled by user.") #prof.mark('done') return prot
def startCamera(self): self.cameraStarted = True self.lastFrameTime = ptime.time()
def run(self): #import cProfile ##cProfile.runctx('self._run()', globals(), locals(), sort='cumulative') #pr = cProfile.Profile() #pr.enable() #self._run() #pr.disable() #pr.print_stats(sort='cumulative') #def _run(self): size = self.dev.getParam('sensorSize') lastFrame = None lastFrameTime = None lastFrameId = None fps = None camState = dict( self.dev.getParams( ['binning', 'exposure', 'region', 'triggerMode'])) binning = camState['binning'] exposure = camState['exposure'] region = camState['region'] mode = camState['triggerMode'] try: #self.dev.setParam('ringSize', self.ringSize, autoRestart=False) self.dev.startCamera() lastFrameTime = lastStopCheck = ptime.time() frameInfo = {} scopeState = None while True: ti = 0 now = ptime.time() frames = self.dev.newFrames() ## If a new frame is available, process it and inform other threads if len(frames) > 0: if lastFrameId is not None: drop = frames[0]['id'] - lastFrameId - 1 if drop > 0: print "WARNING: Camera dropped %d frames" % drop ## Build meta-info for this frame(s) info = camState.copy() ss = self.dev.getScopeState() if ss['id'] != scopeState: scopeState = ss['id'] ## regenerate frameInfo here ps = ss['pixelSize'] ## size of CCD pixel transform = pg.SRTTransform3D(ss['transform']) frameInfo = { 'pixelSize': [ps[0] * binning[0], ps[1] * binning[1]], ## size of image pixel 'objective': ss.get('objective', None), 'deviceTransform': transform, } ## Copy frame info to info array info.update(frameInfo) ## Process all waiting frames. If there is more than one frame waiting, guess the frame times. dt = (now - lastFrameTime) / len(frames) if dt > 0: info['fps'] = 1.0 / dt else: info['fps'] = None for frame in frames: frameInfo = info.copy() data = frame.pop('data') frameInfo.update( frame) # copies 'time' key supplied by camera out = Frame(data, frameInfo) with self.connectMutex: conn = list(self.connections) for c in conn: c(out) self.sigNewFrame.emit(out) lastFrameTime = now lastFrameId = frames[-1]['id'] loopCount = 0 time.sleep(1e-3) ## check for stop request every 10ms if now - lastStopCheck > 10e-3: lastStopCheck = now ## If no frame has arrived yet, do NOT allow the camera to stop (this can hang the driver) << bug should be fixed in pvcam driver, not here. self.lock.lock() if self.stopThread: self.stopThread = False self.lock.unlock() break self.lock.unlock() diff = ptime.time() - lastFrameTime if diff > (10 + exposure): if mode == 'Normal': self.dev.noFrameWarning(diff) break else: pass ## do not exit loop if there is a possibility we are waiting for a trigger #from debug import Profiler #prof = Profiler() with self.camLock: #self.cam.stop() self.dev.stopCamera() #prof.mark(' camera stop:') except: printExc("Error starting camera acquisition:") try: with self.camLock: #self.cam.stop() self.dev.stopCamera() except: pass self.sigShowMessage.emit( "ERROR starting acquisition (see console output)") finally: pass
def drawFrame(self): if self.hasQuit: return #sys.stdout.write('+') try: ## If we last drew a frame < 1/30s ago, return. t = ptime.time() if (self.lastDrawTime is not None) and (t - self.lastDrawTime < .033333): #sys.stdout.write('-') return ## if there is no new frame and no controls have changed, just exit if not self.updateFrame and self.nextFrame is None: #sys.stdout.write('-') return self.updateFrame = False ## If there are no new frames and no previous frames, then there is nothing to draw. if self.currentFrame is None and self.nextFrame is None: #sys.stdout.write('-') return prof = Profiler() ## We will now draw a new frame (even if the frame is unchanged) if self.lastDrawTime is not None: fps = 1.0 / (t - self.lastDrawTime) self.ui.displayFpsLabel.setValue(fps) self.lastDrawTime = t prof() ## Handle the next available frame, if there is one. if self.nextFrame is not None: self.currentFrame = self.nextFrame self.nextFrame = None data = self.currentFrame.data() info = self.currentFrame.info() prof() ## divide the background out of the current frame if needed if self.ui.divideBgBtn.isChecked(): bg = self.getBackgroundFrame() if bg is not None and bg.shape == data.shape: data = data / bg elif self.ui.subtractBgBtn.isChecked(): bg = self.getBackgroundFrame() if bg is not None and bg.shape == data.shape: data = data - bg prof() ## Set new levels if auto gain is enabled if self.ui.btnAutoGain.isChecked(): cw = self.ui.spinAutoGainCenterWeight.value() (w,h) = data.shape center = data[w/2.-w/6.:w/2.+w/6., h/2.-h/6.:h/2.+h/6.] minVal = data.min() * (1.0-cw) + center.min() * cw maxVal = data.max() * (1.0-cw) + center.max() * cw ## If there is inf/nan in the image, strip it out before computing min/max if any([np.isnan(minVal), np.isinf(minVal), np.isnan(minVal), np.isinf(minVal)]): nanMask = np.isnan(data) infMask = np.isinf(data) valid = data[~nanMask * ~infMask] minVal = valid.min() * (1.0-cw) + center.min() * cw maxVal = valid.max() * (1.0-cw) + center.max() * cw ## Smooth min/max range to avoid noise if self.lastMinMax is None: minVal = minVal maxVal = maxVal else: s = 1.0 - 1.0 / (self.ui.spinAutoGainSpeed.value()+1.0) minVal = self.lastMinMax[0] * s + minVal * (1.0-s) maxVal = self.lastMinMax[1] * s + maxVal * (1.0-s) self.lastMinMax = [minVal, maxVal] ## and convert fraction of previous range into new levels bl = self.autoGainLevels[0] * (maxVal-minVal) + minVal wl = self.autoGainLevels[1] * (maxVal-minVal) + minVal self.ignoreLevelChange = True try: self.ui.histogram.setLevels(bl, wl) self.ui.histogram.setHistogramRange(minVal, maxVal, padding=0.05) finally: self.ignoreLevelChange = False prof() ## update image in viewport self.imageItem.updateImage(data)#, levels=[bl, wl]) self.imageItem.setOpacity(self.alpha) self.imageItem.setTransform(self.currentFrame.frameTransform().as2D()) prof() ## Update viewport to correct for scope movement/scaling tr = pg.SRTTransform(self.currentFrame.cameraTransform()) self.updateTransform(tr) self.imageItemGroup.setTransform(tr) prof() prof() prof.finish() except: printExc('Error while drawing new frames:') finally: pass
def runOnce(self, params=None): # good time to collect garbage gc.collect() prof = Profiler("TaskRunner.TaskThread.runOnce", disabled=True, delayed=False) startTime = ptime.time() if params is None: params = {} ## Select correct command to execute cmd = self.task if params is not None: for p in params: cmd = cmd[p:params[p]] prof.mark('select command') ## Wait before starting if we've already run too recently while (self.lastRunTime is not None) and (ptime.time() < self.lastRunTime + cmd['protocol']['cycleTime']): with self.lock: if self.abortThread or self.stopThread: #print "Task run aborted by user" return time.sleep(1e-3) prof.mark('sleep') emitSig = True while True: with self.lock: if self.abortThread or self.stopThread: return pause = self.paused if not pause: break if emitSig: emitSig = False self.sigPaused.emit() time.sleep(10e-3) prof.mark('pause') if type(cmd) is not dict: print("========= TaskRunner.runOnce cmd: ==================") print(cmd) print("========= TaskRunner.runOnce params: ==================") print("Params:", params) print("===========================") raise Exception( "TaskRunner.runOnce failed to generate a proper command structure. Object type was '%s', should have been 'dict'." % type(cmd)) task = self.dm.createTask(cmd) prof.mark('create task') self.lastRunTime = ptime.time() try: with self.lock: self._currentTask = task task.execute(block=False) # record estimated end time endTime = time.time() + cmd['protocol']['duration'] self.sigTaskStarted.emit(params) prof.mark('execute') except: with self.lock: self._currentTask = None try: task.stop(abort=True) except: pass printExc("\nError starting task:") exc = sys.exc_info() raise HelpfulException("\nError starting task:", exc) prof.mark('start task') ### Do not put code outside of these try: blocks; may cause device lockup try: ## wait for finish, watch for abort requests while True: if task.isDone(): prof.mark('task done') break with self.lock: if self.abortThread: # should be taken care of in TaskThread.abort() # NO -- task.stop() is not thread-safe. task.stop(abort=True) return # adjust sleep time based on estimated time remaining in the task. sleep = np.clip((endTime - time.time()) * 0.5, 1e-3, 20e-3) time.sleep(sleep) result = task.getResult() except: ## Make sure the task is fully stopped if there was a failure at any point. #printExc("\nError during task execution:") print("\nStopping task..") task.stop(abort=True) print("") raise HelpfulException("\nError during task execution:", sys.exc_info()) finally: with self.lock: self._currentTask = None prof.mark('getResult') frame = {'params': params, 'cmd': cmd, 'result': result} self.sigNewFrame.emit(frame) prof.mark('emit newFrame') if self.stopThread: raise Exception('stop', result) ## Give everyone else a chance to catch up Qt.QThread.yieldCurrentThread() prof.mark('yield') prof.finish()
def run(self): #import cProfile ##cProfile.runctx('self._run()', globals(), locals(), sort='cumulative') #pr = cProfile.Profile() #pr.enable() #self._run() #pr.disable() #pr.print_stats(sort='cumulative') #def _run(self): size = self.dev.getParam('sensorSize') lastFrame = None lastFrameTime = None lastFrameId = None fps = None camState = dict(self.dev.getParams(['binning', 'exposure', 'region', 'triggerMode'])) binning = camState['binning'] exposure = camState['exposure'] region = camState['region'] mode = camState['triggerMode'] try: #self.dev.setParam('ringSize', self.ringSize, autoRestart=False) self.dev.startCamera() lastFrameTime = lastStopCheck = ptime.time() frameInfo = {} scopeState = None while True: ti = 0 now = ptime.time() frames = self.dev.newFrames() #with self.camLock: #frame = self.cam.lastFrame() ## If a new frame is available, process it and inform other threads if len(frames) > 0: if lastFrameId is not None: drop = frames[0]['id'] - lastFrameId - 1 if drop > 0: print "WARNING: Camera dropped %d frames" % drop ## Build meta-info for this frame(s) info = camState.copy() ## frameInfo includes pixelSize, objective, centerPosition, scopePosition, imagePosition ss = self.dev.getScopeState() if ss['id'] != scopeState: #print "scope state changed" scopeState = ss['id'] ## regenerate frameInfo here ps = ss['pixelSize'] ## size of CCD pixel #pos = ss['centerPosition'] #pos2 = [pos[0] - size[0]*ps[0]*0.5 + region[0]*ps[0], pos[1] - size[1]*ps[1]*0.5 + region[1]*ps[1]] transform = pg.SRTTransform3D(ss['transform']) #transform.translate(region[0]*ps[0], region[1]*ps[1]) ## correct for ROI here frameInfo = { 'pixelSize': [ps[0] * binning[0], ps[1] * binning[1]], ## size of image pixel #'scopePosition': ss['scopePosition'], #'centerPosition': pos, 'objective': ss.get('objective', None), #'imagePosition': pos2 #'cameraTransform': ss['transform'], 'cameraTransform': transform, } ## Copy frame info to info array info.update(frameInfo) #for k in frameInfo: #info[k] = frameInfo[k] ## Process all waiting frames. If there is more than one frame waiting, guess the frame times. dt = (now - lastFrameTime) / len(frames) if dt > 0: info['fps'] = 1.0/dt else: info['fps'] = None for frame in frames: frameInfo = info.copy() data = frame['data'] #print data del frame['data'] frameInfo.update(frame) out = Frame(data, frameInfo) with self.connectMutex: conn = list(self.connections) for c in conn: c(out) #self.emit(QtCore.SIGNAL("newFrame"), out) self.sigNewFrame.emit(out) lastFrameTime = now lastFrameId = frames[-1]['id'] loopCount = 0 time.sleep(1e-3) ## check for stop request every 10ms if now - lastStopCheck > 10e-3: lastStopCheck = now ## If no frame has arrived yet, do NOT allow the camera to stop (this can hang the driver) << bug should be fixed in pvcam driver, not here. self.lock.lock() if self.stopThread: self.stopThread = False self.lock.unlock() break self.lock.unlock() diff = ptime.time()-lastFrameTime if diff > (10 + exposure): if mode == 'Normal': print "Camera acquisition thread has been waiting %02f sec but no new frames have arrived; shutting down." % diff break else: pass ## do not exit loop if there is a possibility we are waiting for a trigger #from debug import Profiler #prof = Profiler() with self.camLock: #self.cam.stop() self.dev.stopCamera() #prof.mark(' camera stop:') except: try: with self.camLock: #self.cam.stop() self.dev.stopCamera() except: pass printExc("Error starting camera acquisition:") #self.emit(QtCore.SIGNAL("showMessage"), "ERROR starting acquisition (see console output)") self.sigShowMessage.emit("ERROR starting acquisition (see console output)") finally: pass
def runSequence(self, store=True): ## Disable all start buttons self.enableStartBtns(False) # good time to collect garbage gc.collect() ## Find all top-level items in the sequence parameter list try: ## make sure all devices are reporting their correct sequence lists items = self.ui.sequenceParamList.listParams() #for i in self.ui.sequenceParamList.topLevelItems: #items.append(i) ## Generate parameter space params = OrderedDict() paramInds = OrderedDict() linkedParams = {} pLen = 1 for i in items: key = i[:2] params[key] = i[2] paramInds[key] = range(len(i[2])) pLen *= len(i[2]) linkedParams[key] = i[3] ## Set storage dir if store: currentDir = self.manager.getCurrentDir() name = self.currentTask.name() if name is None: name = 'protocol' info = self.taskInfo(params) info['dirType'] = 'ProtocolSequence' dh = currentDir.mkdir(name, autoIncrement=True, info=info) else: dh = None ## Tell devices to prepare for task start. for d in self.currentTask.devices: if self.currentTask.deviceEnabled(d): self.docks[d].widget().prepareTaskStart() #print params, linkedParams ## Generate the complete array of command structures. This can take a long time, so we start a progress dialog. with pg.ProgressDialog("Generating task commands..", 0, pLen) as progressDlg: #progressDlg.setMinimumDuration(500) ## If this takes less than 500ms, progress dialog never appears. self.lastQtProcessTime = ptime.time() prot = runSequence(lambda p: self.generateTask(dh, p, progressDlg), paramInds, paramInds.keys(), linkedParams=linkedParams) #progressDlg.setValue(pLen) if dh is not None: dh.flushSignals() ## do this now rather than later as task is running #print "==========Sequence Task==============" #print prot #self.emit(QtCore.SIGNAL('taskSequenceStarted'), {}) self.sigTaskSequenceStarted.emit({}) logMsg('Started %s task sequence of length %i' %(self.currentTask.name(),pLen), importance=6) #print 'PR task positions: self.taskThread.startTask(prot, paramInds) except: self.enableStartBtns(True) raise