def listMaps(self, cells): """List all maps associated with the file handle for each cell in a list""" self.ui.mapTable.clear() self.maps = [] for cell in cells: dbui = self.host.getElement('Database') db = dbui.getDb() if db is None: logMsg("No database loaded in Data Manager.", msgType='error') ident = self.dbIdentity+'.maps' table = dbui.getTableName(ident) if not db.hasTable(table): return if db.tableOwner(table) != ident: raise Exception("Table %s not owned by %s" % (table, ident)) #row = db.getDirRowID(cell) #if row is None: #return maps = db.select(table, ['rowid','*'], where={'cell': cell}) #print maps for rec in maps: scans = [] for rowid in rec['scans']: if isinstance(rowid, tuple): fh = db.getDir(rowid[0], rowid[1]) ## single-spot maps specify the Protocol table instead else: fh = db.getDir('ProtocolSequence', rowid) ## NOTE: single-spot maps use a different table! scans.append((fh, rowid)) rec['scans'] = scans self.newMap(rec)
def newFolder(self): if self.ui.newFolderList.currentIndex() < 1: return ftype = str(self.ui.newFolderList.currentText()) self.ui.newFolderList.setCurrentIndex(0) cdir = self.manager.getCurrentDir() if not cdir.isManaged(): cdir.createIndex() if ftype == 'Folder': nd = cdir.mkdir('NewFolder', autoIncrement=True) #item = self.model.handleIndex(nd) self.ui.fileTreeWidget.editItem(nd) else: spec = self.manager.config['folderTypes'][ftype] name = time.strftime(spec['name']) ## Determine where to put the new directory parent = cdir try: checkDir = cdir for i in range(5): if not checkDir.isManaged(): break inf = checkDir.info() if 'dirType' in inf and inf['dirType'] == ftype: parent = checkDir.parent() break #else: #print "dir no match:", spec, inf checkDir = checkDir.parent() except: printExc("Error while deciding where to put new folder (using currentDir by default)") ## make nd = parent.mkdir(name, autoIncrement=True) ## Add meta-info info = {'dirType': ftype} if spec.get('experimentalUnit', False): info['expUnit'] = True nd.setInfo(info) ## set display to info #self.showFileInfo(nd) #index = self.model.handleIndex(nd) #self.ui.fileTreeView.selectionModel().select(index, QtGui.QItemSelectionModel.Clear) #self.ui.fileTreeView.selectionModel().select(index, QtGui.QItemSelectionModel.Select) self.ui.fileTreeWidget.refresh(parent) ## fileTreeWidget waits a while before updating; force it to refresh immediately. self.ui.fileTreeWidget.select(nd) ##self.ui.fileInfo.setCurrentFile(nd) logMsg("Created new folder: %s" %nd.name(relativeTo=self.baseDir), msgType='status', importance=7) self.manager.setCurrentDir(nd)
def setCommand(self, vals): """Requests to set the command output to the mirrors. (The request is denied if the virtual shutter is closed)""" with self.lock: self.currentCommand = vals if self.getShutterOpen(): ## make sure we have not requested a command outside the allowed limits (mn, mx) = self.config['commandLimits'] v0 = max(mn, min(mx, vals[0])) v1 = max(mn, min(mx, vals[1])) self.setVoltage([v0, v1]) else: logMsg("Virtual shutter closed, not setting mirror position.", msgType='warning')
def startTask(self, task, paramSpace=None): #print "TaskThread:startTask", self.lock.depth(), self.lock with MutexLocker(self.lock): #print "TaskThread:startTask got lock", self.lock.depth(), " tracebacks follow:\n===========" #print "\n\n".join(self.lock.traceback()) #print "======================" while self.isRunning(): #l.unlock() raise Exception("Already running another task") self.task = task self.paramSpace = paramSpace self.lastRunTime = None #l.unlock() #print "TaskThread:startTask starting..", self.lock.depth() self.start() ### causes self.run() to be called from somewhere in C code #name = '' if task.fileName is None else task.fileName logMsg("Task started.", importance=1)
def getCalibration(self, laser, opticState=None): with self.lock: index = self.getCalibrationIndex() if opticState is None: opticState = self.getDeviceStateKey() ## this tells us about objectives, filters, etc if laser in index: index1 = index[laser] else: logMsg("Warning: No calibration found for laser %s" % laser, msgType='warning') return None if opticState in index1: index2 = index1[opticState] else: logMsg("Warning: No calibration found for state: %s" % opticState, msgType='warning') return None return index2.copy()
def mcUpdate(self, state=None, mode=None): """MC state (or internal holding state) has changed, handle the update.""" with self.stateLock: if state is None: state = self.lastState[mode] mode = state['mode'] state['holding'] = self.holding[mode] self.lastState[mode] = state.copy() if self.lastMode != state['mode']: if self.lastMode is not None and state[ 'mode'] != self._switchingToMode and state[ 'mode'] != 'I=0': # User changed the mode manually; we need to update the holding value immediately. self.setHolding(state['mode']) logMsg( "Warning: MultiClamp mode should be changed from ACQ4, not from the MultiClamp Commander window.", msgType='error') self.lastMode = state['mode'] self._switchingToMode = None self.sigStateChanged.emit(state)
def getCalibration(self, laser, opticState=None): with self.lock: index = self.getCalibrationIndex() if opticState is None: opticState = self.getDeviceStateKey( ) ## this tells us about objectives, filters, etc if laser in index: index1 = index[laser] else: logMsg("Warning: No calibration found for laser %s" % laser, msgType='warning') return None if opticState in index1: index2 = index1[opticState] else: logMsg("Warning: No calibration found for state: %s" % opticState, msgType='warning') return None return index2.copy()
def newFolder(self): if self.ui.newFolderList.currentIndex() < 1: return ftype = str(self.ui.newFolderList.currentText()) self.ui.newFolderList.setCurrentIndex(0) cdir = self.manager.getCurrentDir() if not cdir.isManaged(): cdir.createIndex() if ftype == 'Folder': nd = cdir.mkdir('NewFolder', autoIncrement=True) #item = self.model.handleIndex(nd) self.ui.fileTreeWidget.editItem(nd) else: spec = self.manager.config['folderTypes'][ftype] name = time.strftime(spec['name']) ## Determine where to put the new directory parent = cdir try: checkDir = cdir for i in range(5): if not checkDir.isManaged(): break inf = checkDir.info() if 'dirType' in inf and inf['dirType'] == ftype: parent = checkDir.parent() break #else: #print "dir no match:", spec, inf checkDir = checkDir.parent() except: printExc( "Error while deciding where to put new folder (using currentDir by default)" ) ## make nd = parent.mkdir(name, autoIncrement=True) ## Add meta-info info = {'dirType': ftype} if spec.get('experimentalUnit', False): info['expUnit'] = True nd.setInfo(info) ## set display to info #self.showFileInfo(nd) #index = self.model.handleIndex(nd) #self.ui.fileTreeView.selectionModel().select(index, QtGui.QItemSelectionModel.Clear) #self.ui.fileTreeView.selectionModel().select(index, QtGui.QItemSelectionModel.Select) self.ui.fileTreeWidget.refresh( parent ) ## fileTreeWidget waits a while before updating; force it to refresh immediately. self.ui.fileTreeWidget.select(nd) ##self.ui.fileInfo.setCurrentFile(nd) logMsg("Created new folder: %s" % nd.name(relativeTo=self.baseDir), msgType='status', importance=7) self.manager.setCurrentDir(nd)
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
def _measurePower(self): if self.hasPowerIndicator: ## run a task that checks the power daqName = self.getDAQName('shutter') powerInd = self.config['powerIndicator']['channel'] rate = self.config['powerIndicator']['rate'] pConfig = getManager().getDevice( self.config['powerIndicator']['channel'][0]).listChannels()[ self.config['powerIndicator']['channel'][1]] sTime = pConfig.get('settlingTime', None) mTime = pConfig.get('measurementTime', None) if mTime is None or sTime is None: raise Exception( "The power indicator (%s) specified for %s needs to be configured with both a 'settlingTime' value and a 'measurementTime' value." % (self.config['powerIndicator']['channel'], self.name())) dur = 0.1 + (sTime + mTime) nPts = int(dur * rate) ### create a waveform that flashes the QSwitch(or other way of turning on) the number specified by reps waveform = np.zeros(nPts, dtype=np.byte) #for i in range(reps): #waveform[(i+1)/10.*rate:((i+1)/10.+sTime+mTime)*rate] = 1 ## divide i+1 by 10 to increment by hundreds of milliseconds waveform[0.1 * rate:-2] = 1 measureMode = self.measurementMode() cmd = { 'protocol': { 'duration': dur }, self.name(): { 'switchWaveform': waveform, 'shutterMode': measureMode['shutter'] }, powerInd[0]: { powerInd[1]: { 'record': True, 'recordInit': False } }, daqName: { 'numPts': nPts, 'rate': rate } } #print "outputPowerCmd: ", cmd task = getManager().createTask(cmd) task.execute( processEvents=False ) # disable event processing to prevent recurrent requests result = task.getResult() ## pull out time that laser was on and off so that power can be measured in each state -- discard the settlingTime around each state change #onMask = np.zeros(nPts, dtype=np.byte) #offMask = np.zeros(nPts, dtype=np.byte) #for i in range(reps): #onMask[((i+1)/10+sTime)*rate:((i+1)/10+sTime+mTime)*rate] = 1 #offMask[(i/10.+2*sTime+mTime)*rate:(i+1/10.)*rate] = 1 powerIndTrace = result[powerInd[0]] if powerIndTrace is None: raise Exception("No data returned from power indicator") laserOn = powerIndTrace[0][0.1 * rate:-2].asarray() laserOff = powerIndTrace[0][:0.1 * rate].asarray() t, prob = stats.ttest_ind(laserOn, laserOff) if prob < 0.01: ### if powerOn is statistically different from powerOff powerOn = laserOn.mean() if powerOn < 0: powerOn = 0.0 powerOff = laserOff.mean() #self.devGui.ui.outputPowerLabel.setText(siFormat(powerOn, suffix='W')) ## NO! device does not talk to GUI! self.setParam(currentPower=powerOn) powerOk = self.checkPowerValidity(powerOn) self.sigOutputPowerChanged.emit(powerOn, powerOk) self.updateSamplePower() return powerOn else: logMsg( "No laser pulse detected by power indicator '%s' while measuring Laser.outputPower()" % powerInd[0], msgType='warning') self.setParam(currentPower=0.0) self.updateSamplePower() return 0.0 ## return the power specified in the config file if there's no powerIndicator else: return self.config.get('power', None)
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, list(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 outputPower(self): """ Return a tuple: (current output power, bool power within expected range) The output power returned excludes the effect of pockel 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 """ if self.hasPowerIndicator: ## run a task that checks the power daqName = self.getDAQName('shutter') powerInd = self.config['powerIndicator']['channel'] rate = self.config['powerIndicator']['rate'] pConfig = getManager().getDevice(self.config['powerIndicator']['channel'][0]).listChannels()[self.config['powerIndicator']['channel'][1]] sTime = pConfig.get('settlingTime', None) mTime = pConfig.get('measurementTime', None) if mTime is None or sTime is None: raise Exception("The power indicator (%s) specified for %s needs to be configured with both a 'settlingTime' value and a 'measurementTime' value." %(self.config['powerIndicator']['channel'], self.name())) dur = 0.1 + (sTime+mTime) nPts = int(dur*rate) ### create a waveform that flashes the QSwitch(or other way of turning on) the number specified by reps waveform = np.zeros(nPts, dtype=np.byte) #for i in range(reps): #waveform[(i+1)/10.*rate:((i+1)/10.+sTime+mTime)*rate] = 1 ## divide i+1 by 10 to increment by hundreds of milliseconds waveform[0.1*rate:-2] = 1 cmd = { 'protocol': {'duration': dur}, self.name(): {'switchWaveform':waveform, 'shutterMode':'closed'}, powerInd[0]: {powerInd[1]: {'record':True, 'recordInit':False}}, daqName: {'numPts': nPts, 'rate': rate} } #print "outputPowerCmd: ", cmd task = getManager().createTask(cmd) task.execute() result = task.getResult() ## pull out time that laser was on and off so that power can be measured in each state -- discard the settlingTime around each state change #onMask = np.zeros(nPts, dtype=np.byte) #offMask = np.zeros(nPts, dtype=np.byte) #for i in range(reps): #onMask[((i+1)/10+sTime)*rate:((i+1)/10+sTime+mTime)*rate] = 1 #offMask[(i/10.+2*sTime+mTime)*rate:(i+1/10.)*rate] = 1 powerIndTrace = result[powerInd[0]] if powerIndTrace is None: raise Exception("No data returned from power indicator") laserOn = powerIndTrace[0][0.1*rate:-2].asarray() laserOff = powerIndTrace[0][:0.1*rate].asarray() t, prob = stats.ttest_ind(laserOn, laserOff) if prob < 0.01: ### if powerOn is statistically different from powerOff powerOn = laserOn.mean() if powerOn < 0: powerOn = 0.0 powerOff = laserOff.mean() #self.devGui.ui.outputPowerLabel.setText(siFormat(powerOn, suffix='W')) ## NO! device does not talk to GUI! self.setParam(currentPower=powerOn) powerOk = self.checkPowerValidity(powerOn) self.sigOutputPowerChanged.emit(powerOn, powerOk) self.updateSamplePower() return powerOn, powerOk else: logMsg("No laser pulse detected by power indicator '%s' while measuring Laser.outputPower()" % powerInd[0], msgType='warning') self.setParam(currentPower=0.0) self.updateSamplePower() return 0.0, self.checkPowerValidity(0.0) ## return the power specified in the config file if there's no powerIndicator else: power = self.config.get('power', None) if power is None: return None, None else: return power, self.checkPowerValidity(power)