def __init__(self, dm, clampName): QtGui.QMainWindow.__init__(self) self.setWindowTitle(clampName) self.startTime = None self.redrawCommand = 1 self.analysisItems = { 'inputResistance': u'Ω', 'accessResistance': u'Ω', 'capacitance': 'F', 'restingPotential': 'V', 'restingCurrent': 'A', 'fitError': '' } self.params = { 'mode': 'vc', 'rate': 400000, 'downsample': 10, 'cycleTime': .2, 'recordTime': 0.1, 'delayTime': 0.03, 'pulseTime': 0.05, 'icPulse': -30e-12, 'vcPulse': -10e-3, 'icHolding': 0, 'vcHolding': -65e-3, 'icHoldingEnabled': False, 'icPulseEnabled': True, 'vcHoldingEnabled': False, 'vcPulseEnabled': True, 'drawFit': True, 'average': 1, } self.paramLock = Mutex(QtCore.QMutex.Recursive) self.manager = dm self.clampName = clampName self.thread = PatchThread(self) self.cw = QtGui.QWidget() self.setCentralWidget(self.cw) self.ui = Ui_Form() self.ui.setupUi(self.cw) #self.logBtn = LogButton("Log") #self.statusBar().addPermanentWidget(self.logBtn) self.setStatusBar(StatusBar()) self.stateFile = os.path.join('modules', self.clampName + '_ui.cfg') uiState = Manager.getManager().readConfigFile(self.stateFile) if 'geometry' in uiState: geom = QtCore.QRect(*uiState['geometry']) self.setGeometry(geom) if 'window' in uiState: ws = QtCore.QByteArray.fromPercentEncoding(uiState['window']) self.restoreState(ws) self.ui.splitter_2.setSizes([self.width()/4, self.width()*3./4.]) self.plots = {} for k in self.analysisItems: p = PlotWidget() p.setLabel('left', text=k, units=self.analysisItems[k]) self.ui.plotLayout.addWidget(p) self.plots[k] = p #irp = self.plots['inputResistance'] #irp.setManualYScale() #irp.setYLog(True) #irp.setYRange(1e6, 1e11) self.ui.icPulseSpin.setOpts(dec=True, step=1, minStep=1e-12, bounds=[None,None], siPrefix=True, suffix='A') self.ui.vcPulseSpin.setOpts(dec=True, step=1, minStep=1e-3, bounds=[None,None], siPrefix=True, suffix='V') self.ui.icHoldSpin.setOpts(dec=True, step=1, minStep=1e-12, bounds=[None,None], siPrefix=True, suffix='A') self.ui.vcHoldSpin.setOpts(dec=True, step=1, minStep=1e-3, bounds=[None,None], siPrefix=True, suffix='V') self.ui.cycleTimeSpin.setOpts(dec=True, step=1, minStep=1e-6, bounds=[0,None], siPrefix=True, suffix='s') self.ui.pulseTimeSpin.setOpts(dec=True, step=1, minStep=1e-6, bounds=[0,1.], siPrefix=True, suffix='s') self.ui.delayTimeSpin.setOpts(dec=True, step=1, minStep=1e-6, bounds=[0,1.], siPrefix=True, suffix='s') self.stateGroup = WidgetGroup([ (self.ui.icPulseSpin, 'icPulse'), (self.ui.vcPulseSpin, 'vcPulse'), (self.ui.icHoldSpin, 'icHolding'), (self.ui.vcHoldSpin, 'vcHolding'), (self.ui.icPulseCheck, 'icPulseEnabled'), (self.ui.vcPulseCheck, 'vcPulseEnabled'), (self.ui.icHoldCheck, 'icHoldingEnabled'), (self.ui.vcHoldCheck, 'vcHoldingEnabled'), (self.ui.cycleTimeSpin, 'cycleTime'), (self.ui.pulseTimeSpin, 'pulseTime'), (self.ui.delayTimeSpin, 'delayTime'), (self.ui.drawFitCheck, 'drawFit'), (self.ui.averageSpin, 'average'), ]) self.stateGroup.setState(self.params) self.ui.patchPlot.setLabel('left', text='Primary', units='A') self.patchCurve = self.ui.patchPlot.plot(pen=QtGui.QPen(QtGui.QColor(200, 200, 200))) self.patchFitCurve = self.ui.patchPlot.plot(pen=QtGui.QPen(QtGui.QColor(0, 100, 200))) self.ui.commandPlot.setLabel('left', text='Command', units='V') self.commandCurve = self.ui.commandPlot.plot(pen=QtGui.QPen(QtGui.QColor(200, 200, 200))) self.ui.startBtn.clicked.connect(self.startClicked) self.ui.recordBtn.clicked.connect(self.recordClicked) self.ui.bathModeBtn.clicked.connect(self.bathMode) self.ui.patchModeBtn.clicked.connect(self.patchMode) self.ui.cellModeBtn.clicked.connect(self.cellMode) self.ui.monitorModeBtn.clicked.connect(self.monitorMode) self.ui.resetBtn.clicked.connect(self.resetClicked) self.thread.finished.connect(self.threadStopped) self.thread.sigNewFrame.connect(self.handleNewFrame) self.ui.vcModeRadio.toggled.connect(self.updateParams) self.stateGroup.sigChanged.connect(self.updateParams) ## Configure analysis plots, curves, and data arrays self.analysisCurves = {} self.analysisData = {'time': []} for n in self.analysisItems: w = getattr(self.ui, n+'Check') w.clicked.connect(self.showPlots) p = self.plots[n] self.analysisCurves[n] = p.plot(pen=QtGui.QPen(QtGui.QColor(200, 200, 200))) for suf in ['', 'Std']: self.analysisData[n+suf] = [] self.showPlots() self.updateParams() self.show() self.bathMode()
def __init__(self, dm, clampName, modes): QtGui.QMainWindow.__init__(self) self.setWindowTitle(clampName) self.startTime = None self.redrawCommand = 1 self.analysisItems = { 'inputResistance': u'Ω', 'accessResistance': u'Ω', 'capacitance': 'F', 'restingPotential': 'V', 'restingCurrent': 'A', 'fitError': '' } self.params = modes.pop('default') self.modes = modes self.stylesheet = {} self.paramLock = Mutex(QtCore.QMutex.Recursive) self.manager = dm self.clampName = clampName self.thread = PatchThread(self) self.cw = QtGui.QWidget() self.setCentralWidget(self.cw) self.ui = Ui_Form() self.ui.setupUi(self.cw) self.setStatusBar(StatusBar()) # Create one button for each configured mode row = None self.modeRows = [] rowLen = 0 def mkModeCallback(name): return lambda: self.setMode(name) for modeName, mode in modes.items(): if modeName == 'default': continue if row is None: row = QtGui.QWidget() layout = QtGui.QHBoxLayout() row.setLayout(layout) self.ui.modeLayout.addWidget(row) self.modeRows.append(row) btn = QtGui.QPushButton(modeName) layout.addWidget(btn) rowLen += btn.sizeHint().width() if rowLen > 200: row = None rowLen = 0 btn.clicked.connect(mkModeCallback(modeName)) self.stateFile = os.path.join('modules', self.clampName + '_ui.cfg') uiState = Manager.getManager().readConfigFile(self.stateFile) if 'geometry' in uiState: geom = QtCore.QRect(*uiState['geometry']) self.setGeometry(geom) if 'window' in uiState: ws = QtCore.QByteArray.fromPercentEncoding(uiState['window']) self.restoreState(ws) self.ui.splitter_2.setSizes([self.width()/4, self.width()*3./4.]) self.plots = {} for k in self.analysisItems: p = PlotWidget() p.setLabel('left', text=k, units=self.analysisItems[k]) self.ui.plotLayout.addWidget(p) self.plots[k] = p self.ui.icPulseSpin.setOpts(dec=True, step=1, minStep=1e-12, bounds=[None,None], siPrefix=True, suffix='A') self.ui.vcPulseSpin.setOpts(dec=True, step=1, minStep=1e-3, bounds=[None,None], siPrefix=True, suffix='V') self.ui.icHoldSpin.setOpts(dec=True, step=1, minStep=1e-12, bounds=[None,None], siPrefix=True, suffix='A') self.ui.vcHoldSpin.setOpts(dec=True, step=1, minStep=1e-3, bounds=[None,None], siPrefix=True, suffix='V') self.ui.cycleTimeSpin.setOpts(dec=True, step=1, minStep=1e-6, bounds=[0,None], siPrefix=True, suffix='s') self.ui.pulseTimeSpin.setOpts(dec=True, step=1, minStep=1e-6, bounds=[0,1.], siPrefix=True, suffix='s') self.ui.delayTimeSpin.setOpts(dec=True, step=1, minStep=1e-6, bounds=[0,1.], siPrefix=True, suffix='s') self.stateGroup = WidgetGroup([ (self.ui.icPulseSpin, 'icPulse'), (self.ui.vcPulseSpin, 'vcPulse'), (self.ui.icHoldSpin, 'icHolding'), (self.ui.vcHoldSpin, 'vcHolding'), (self.ui.icPulseCheck, 'icPulseEnabled'), (self.ui.vcPulseCheck, 'vcPulseEnabled'), (self.ui.icHoldCheck, 'icHoldingEnabled'), (self.ui.vcHoldCheck, 'vcHoldingEnabled'), (self.ui.cycleTimeSpin, 'cycleTime'), (self.ui.pulseTimeSpin, 'pulseTime'), (self.ui.delayTimeSpin, 'delayTime'), (self.ui.drawFitCheck, 'drawFit'), (self.ui.averageSpin, 'average'), ]) self.stateGroup.setState(self.params) self.ui.patchPlot.setLabel('left', text='Primary', units='A') self.patchCurve = self.ui.patchPlot.plot(pen=QtGui.QPen(QtGui.QColor(200,200,200))) self.patchFitCurve = self.ui.patchPlot.plot(pen=QtGui.QPen(QtGui.QColor(0,100,200))) self.ui.commandPlot.setLabel('left', text='Command', units='V') self.commandCurve = self.ui.commandPlot.plot(pen=QtGui.QPen(QtGui.QColor(200,200,200))) self.ui.startBtn.clicked.connect(self.startClicked) self.ui.recordBtn.clicked.connect(self.recordClicked) self.ui.resetBtn.clicked.connect(self.resetClicked) self.thread.finished.connect(self.threadStopped) self.thread.sigNewFrame.connect(self.handleNewFrame) self.ui.vcModeRadio.toggled.connect(self.updateParams) self.stateGroup.sigChanged.connect(self.updateParams) ## Configure analysis plots, curves, and data arrays self.analysisCurves = {} self.analysisData = {'time': []} for n in self.analysisItems: w = getattr(self.ui, n+'Check') w.clicked.connect(self.showPlots) p = self.plots[n] self.analysisCurves[n] = p.plot(pen=QtGui.QPen(QtGui.QColor(200,200,200))) for suf in ['', 'Std']: self.analysisData[n+suf] = [] self.showPlots() self.updateParams() self.show()
class LaserTaskGui(DAQGenericTaskGui): def __init__(self, dev, task): DAQGenericTaskGui.__init__(self, dev, task, ownUi=False) self.ui = taskTemplate.Ui_Form() self.cache = {} self.layout = QtGui.QGridLayout() self.layout.setContentsMargins(0,0,0,0) self.setLayout(self.layout) self.splitter1 = QtGui.QSplitter() self.splitter1.setOrientation(QtCore.Qt.Horizontal) self.layout.addWidget(self.splitter1) self.ctrlLayout = QtGui.QVBoxLayout() wid1 = QtGui.QWidget() wid1.setLayout(self.ctrlLayout) self.plotSplitter = QtGui.QSplitter() self.plotSplitter.setOrientation(QtCore.Qt.Vertical) self.splitter1.addWidget(wid1) self.splitter1.addWidget(self.plotSplitter) #wid = QtGui.QWidget() #hLayout = QtGui.QHBoxLayout() #wid.setLayout(hLayout) #self.ctrlLayout.addLayout(hLayout) wid2 = QtGui.QWidget() self.ui.setupUi(wid2) self.ctrlLayout.addWidget(wid2) if not self.dev.hasPowerIndicator: self.ui.checkPowerBtn.setEnabled(False) self.ui.checkPowerCheck.hide() self.ui.checkPowerCheck.setChecked(False) if not self.dev.hasTunableWavelength: self.ui.wavelengthWidget.hide() self.powerWidget, self.powerPlot = self.createChannelWidget('power', daqName=self.dev.getDAQName()[0]) ## all we want is the function generator self.powerFnGenerator = self.powerWidget.ui.waveGeneratorWidget self.powerWidget.hide() self.ctrlLayout.addWidget(self.powerFnGenerator) self.powerFnGenerator.show() self.plotSplitter.addWidget(self.powerPlot) self.powerWidget.setMeta('y', units='W', siPrefix=True, dec=True, step=0.5, minStep=1e-3, limits=(0, None)) self.powerWidget.setMeta('xy', units='J', siPrefix=True, dec=True, step=0.5, minStep=1e-6, limits=(0, None)) self.powerWidget.setMeta('x', units='s', siPrefix=True, dec=True, step=0.5, minStep=1e-6, limits=(None, None)) if self.dev.hasTriggerableShutter: #(self.shutterWidget, self.shutterPlot) = self.createChannelWidget('shutter') self.shutterPlot = PlotWidget(name='%s.shutter'%self.dev.name) self.shutterPlot.setLabel('left', text='Shutter') self.plotSplitter.addWidget(self.shutterPlot) #self.shutterPlot.hide() if self.dev.hasQSwitch: #self.qSwitchWidget, self.qSwitchPlot = self.createChannelWidget('qSwitch') self.qSwitchPlot = PlotWidget(name='%s.qSwitch'%self.dev.name) self.qSwitchPlot.setLabel('left', text='Q-Switch') self.plotSplitter.addWidget(self.qSwitchPlot) #self.qSwitchPlot.hide() if self.dev.hasPCell: #self.pCellWidget, self.pCellPlot = self.createChannelWidget('pCell') self.pCellPlot = PlotWidget(name='%s.pCell'%self.dev.name) self.pCellPlot.setLabel('left', text='Pockel Cell', units='V') self.plotSplitter.addWidget(self.pCellPlot) #self.pCellPlot.hide() ## catch self.powerWidget.sigDataChanged and connect it to functions that calculate and plot raw shutter and qswitch traces self.powerWidget.sigDataChanged.connect(self.powerCmdChanged) self.ui.checkPowerBtn.clicked.connect(self.dev.outputPower) self.dev.sigOutputPowerChanged.connect(self.laserPowerChanged) self.dev.sigSamplePowerChanged.connect(self.samplePowerChanged) self.dev.outputPower() def laserPowerChanged(self, power, valid): #samplePower = self.dev.samplePower(power) ## we should get another signal for this later.. #samplePower = power*self.dev.getParam('scopeTransmission') ## update label if power is None: self.ui.outputPowerLabel.setText("?") else: self.ui.outputPowerLabel.setText(siFormat(power, suffix='W')) if not valid: self.ui.outputPowerLabel.setStyleSheet("QLabel {color: #B00}") else: self.ui.outputPowerLabel.setStyleSheet("QLabel {color: #000}") def samplePowerChanged(self, power): if power is None: self.ui.samplePowerLabel.setText("?") return else: self.ui.samplePowerLabel.setText(siFormat(power, suffix='W')) if self.dev.hasPCell: raise Exception('stub') else: ## adjust length of pulse to correct for new power if self.ui.adjustLengthCheck.isChecked(): en = {} for param in self.powerWidget.ui.waveGeneratorWidget.stimParams: en[param.name()] = param['sum'] self.powerWidget.setMeta('y', value=power, readonly=True) for param in self.powerWidget.ui.waveGeneratorWidget.stimParams: param['sum'] = en[param.name()] else: self.powerWidget.setMeta('y', value=power, readonly=True) def saveState(self): """Return a dictionary representing the current state of the widget.""" state = {} state['daqState'] = DAQGenericTaskGui.saveState(self) return state def restoreState(self, state): """Restore the state of the widget from a dictionary previously generated using saveState""" return DAQGenericTaskGui.restoreState(self, state['daqState']) def describe(self, params=None): state = self.saveState() ps = state['daqState']['channels']['power'] desc = {'mode': 'power', 'command': ps['waveGeneratorWidget']} return desc def prepareTaskStart(self): ## check power before starting task. if self.ui.checkPowerCheck.isChecked(): power, valid = self.dev.outputPower() ## request current power from laser if power is None: raise HelpfulException("The current laser power for '%s' is unknown." % self.dev.name) if not valid: powerStr = siFormat(power, suffix='W') raise HelpfulException("The current laser power for '%s' (%s) is outside the expected range." % (self.dev.name, powerStr)) def generateTask(self, params=None): """Return a cmd dictionary suitable for passing to LaserTask.""" ## Params looks like: {'amp': 7} where 'amp' is the name of a sequence parameter, and 7 is the 7th value in the list of 'amp' for k,v in params.items(): if k.startswith('power.'): del params[k] params[k[6:]] = v rate = self.powerWidget.rate wave = self.powerWidget.getSingleWave(params) rawCmds = self.getChannelCmds(wave, rate) #rawCmds = self.cache.get(id(wave), self.dev.getChannelCmds({'powerWaveform':wave}, rate)) ## returns {'shutter': array(...), 'qSwitch':array(..), 'pCell':array(...)} ### structure task in DAQGeneric-compatible way cmd = {} for k in rawCmds: cmd[k] = {} cmd[k]['command'] = rawCmds[k] cmd['powerWaveform'] = wave ## just to allow the device task to store this data cmd['ignorePowerWaveform'] = True return cmd def getChannelCmds(self, powerWave, rate): key = id(powerWave) if key in self.cache: rawCmds = self.cache[key] else: rawCmds = self.dev.getChannelCmds({'powerWaveform':powerWave}, rate) ## returns {'shutter': array(...), 'qSwitch':array(..), 'pCell':array(...)} self.cache[key] = rawCmds return rawCmds def powerCmdChanged(self): self.clearRawPlots() self.cache = {} rate = self.powerWidget.rate #### calculate, cache and display sequence waves for shutter/qSwitch/pCell params = {} ps = self.powerWidget.listSequence() for k in ps: params[k] = range(len(ps[k])) ## get power waveforms waves = [] runSequence(lambda p: waves.append(self.powerWidget.getSingleWave(p)), params, params.keys()) ## appends waveforms for the entire parameter space to waves for w in waves: if w is not None: ## need to translate w into raw traces, plot them, and cache them (using id(w) as a key) rawWaves = self.getChannelCmds(w, rate) #rawWaves = self.dev.getChannelCmds({'powerWaveform':w}, rate) ## calculate raw waveforms for shutter/qSwitch/pCell from powerWaveform #self.cache[id(w)] = rawWaves ## cache the calculated waveforms self.plotRawCurves(rawWaves, color=QtGui.QColor(100, 100, 100)) ## plot the raw waveform in it's appropriate plot in grey ## calculate (or pull from cache) and display single-mode wave in red single = self.powerWidget.getSingleWave() if single is not None: #rawSingle = self.cache.get(id(single), self.dev.getChannelCmds({'powerWaveform':single}, rate)) rawSingle = self.getChannelCmds(single, rate) self.plotRawCurves(rawSingle, color=QtGui.QColor(200, 100, 100)) def plotRawCurves(self, data, color=QtGui.QColor(100, 100, 100)): if 'shutter' in data: self.shutterPlot.plot(y=data['shutter'], x=self.powerWidget.timeVals, pen=QtGui.QPen(color)) if 'qSwitch' in data: self.qSwitchPlot.plot(y=data['qSwitch'], x=self.powerWidget.timeVals, pen=QtGui.QPen(color)) if 'pCell' in data: self.pCellPlot.plot(y=data['pCell'], x=self.powerWidget.timeVals, pen=QtGui.QPen(color)) def clearRawPlots(self): for p in ['shutterPlot', 'qSwitchPlot', 'pCellPlot']: if hasattr(self, p): getattr(self, p).clear() def quit(self): self.dev.lastResult = None DAQGenericTaskGui.quit(self)
def __init__(self, dm, config): clampName = config['clampDev'] QtGui.QMainWindow.__init__(self) self.setWindowTitle(clampName) self.startTime = None self.redrawCommand = 1 self.analysisItems = { 'inputResistance': u'Ω', 'accessResistance': u'Ω', 'capacitance': 'F', 'restingPotential': 'V', 'restingCurrent': 'A', 'fitError': '' } self.params = { 'mode': 'vc', 'rate': config.get('sampleRate', 100000), 'downsample': config.get('downsample', 3), 'cycleTime': .2, 'recordTime': 0.1, 'delayTime': 0.03, 'pulseTime': 0.05, 'icPulse': -30e-12, 'vcPulse': -10e-3, 'icHolding': 0, 'vcHolding': -65e-3, 'icHoldingEnabled': False, 'icPulseEnabled': True, 'vcHoldingEnabled': False, 'vcPulseEnabled': True, 'drawFit': True, 'average': 1, } self.paramLock = Mutex(QtCore.QMutex.Recursive) self.manager = dm self.clampName = clampName self.thread = PatchThread(self) self.cw = QtGui.QWidget() self.setCentralWidget(self.cw) self.ui = Ui_Form() self.ui.setupUi(self.cw) #self.logBtn = LogButton("Log") #self.statusBar().addPermanentWidget(self.logBtn) self.setStatusBar(StatusBar()) self.stateFile = os.path.join('modules', self.clampName + '_ui.cfg') uiState = Manager.getManager().readConfigFile(self.stateFile) if 'geometry' in uiState: geom = QtCore.QRect(*uiState['geometry']) self.setGeometry(geom) if 'window' in uiState: ws = QtCore.QByteArray.fromPercentEncoding(uiState['window']) self.restoreState(ws) self.ui.splitter_2.setSizes([self.width() / 4, self.width() * 3. / 4.]) self.ui.splitter.setStretchFactor(0, 30) self.ui.splitter.setStretchFactor(1, 10) self.plots = {} for k in self.analysisItems: p = PlotWidget() p.setLabel('left', text=k, units=self.analysisItems[k]) self.ui.plotLayout.addWidget(p) self.plots[k] = p irp = self.plots['inputResistance'] irp.setLogMode(y=True, x=False) irp.setYRange(6, 11) self.ui.icPulseSpin.setOpts(dec=True, step=1, minStep=1e-12, bounds=[None, None], siPrefix=True, suffix='A') self.ui.vcPulseSpin.setOpts(dec=True, step=1, minStep=1e-3, bounds=[None, None], siPrefix=True, suffix='V') self.ui.icHoldSpin.setOpts(dec=True, step=1, minStep=1e-12, bounds=[None, None], siPrefix=True, suffix='A') self.ui.vcHoldSpin.setOpts(dec=True, step=1, minStep=1e-3, bounds=[None, None], siPrefix=True, suffix='V') self.ui.cycleTimeSpin.setOpts(dec=True, step=1, minStep=1e-6, bounds=[0, None], siPrefix=True, suffix='s') self.ui.pulseTimeSpin.setOpts(dec=True, step=1, minStep=1e-6, bounds=[0, 1.], siPrefix=True, suffix='s') self.ui.delayTimeSpin.setOpts(dec=True, step=1, minStep=1e-6, bounds=[0, 1.], siPrefix=True, suffix='s') self.stateGroup = WidgetGroup([ (self.ui.icPulseSpin, 'icPulse'), (self.ui.vcPulseSpin, 'vcPulse'), (self.ui.icHoldSpin, 'icHolding'), (self.ui.vcHoldSpin, 'vcHolding'), (self.ui.icPulseCheck, 'icPulseEnabled'), (self.ui.vcPulseCheck, 'vcPulseEnabled'), (self.ui.icHoldCheck, 'icHoldingEnabled'), (self.ui.vcHoldCheck, 'vcHoldingEnabled'), (self.ui.cycleTimeSpin, 'cycleTime'), (self.ui.pulseTimeSpin, 'pulseTime'), (self.ui.delayTimeSpin, 'delayTime'), (self.ui.drawFitCheck, 'drawFit'), (self.ui.averageSpin, 'average'), ]) self.stateGroup.setState(self.params) self.ui.patchPlot.setLabel('left', text='Primary', units='A') self.patchCurve = self.ui.patchPlot.plot( pen=QtGui.QPen(QtGui.QColor(200, 200, 200))) self.patchFitCurve = self.ui.patchPlot.plot( pen=QtGui.QPen(QtGui.QColor(0, 100, 200))) self.ui.commandPlot.setLabel('left', text='Command', units='V') self.commandCurve = self.ui.commandPlot.plot( pen=QtGui.QPen(QtGui.QColor(200, 200, 200))) self.ui.startBtn.clicked.connect(self.startClicked) self.ui.recordBtn.clicked.connect(self.recordClicked) self.ui.bathModeBtn.clicked.connect(self.bathMode) self.ui.patchModeBtn.clicked.connect(self.patchMode) self.ui.cellModeBtn.clicked.connect(self.cellMode) self.ui.monitorModeBtn.clicked.connect(self.monitorMode) self.ui.resetBtn.clicked.connect(self.resetClicked) self.thread.finished.connect(self.threadStopped) self.thread.sigNewFrame.connect(self.handleNewFrame) self.ui.vcModeRadio.toggled.connect(self.updateParams) self.stateGroup.sigChanged.connect(self.updateParams) ## Configure analysis plots, curves, and data arrays self.analysisCurves = {} self.analysisData = {'time': []} for n in self.analysisItems: w = getattr(self.ui, n + 'Check') w.clicked.connect(self.showPlots) p = self.plots[n] self.analysisCurves[n] = p.plot( pen=QtGui.QPen(QtGui.QColor(200, 200, 200))) for suf in ['', 'Std']: self.analysisData[n + suf] = [] self.showPlots() self.updateParams() self.show() self.bathMode()
class LaserTaskGui(DAQGenericTaskGui): def __init__(self, dev, taskRunner): DAQGenericTaskGui.__init__(self, dev, taskRunner, ownUi=False) self.ui = taskTemplate.Ui_Form() self.cache = {} self.layout = QtGui.QGridLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.layout) self.splitter1 = QtGui.QSplitter() self.splitter1.setOrientation(QtCore.Qt.Horizontal) self.layout.addWidget(self.splitter1) self.ctrlLayout = QtGui.QVBoxLayout() wid1 = QtGui.QWidget() wid1.setLayout(self.ctrlLayout) self.plotSplitter = QtGui.QSplitter() self.plotSplitter.setOrientation(QtCore.Qt.Vertical) self.splitter1.addWidget(wid1) self.splitter1.addWidget(self.plotSplitter) #wid = QtGui.QWidget() #hLayout = QtGui.QHBoxLayout() #wid.setLayout(hLayout) #self.ctrlLayout.addLayout(hLayout) wid2 = QtGui.QWidget() self.ui.setupUi(wid2) self.ctrlLayout.addWidget(wid2) if not self.dev.hasPowerIndicator: self.ui.checkPowerBtn.setEnabled(False) self.ui.checkPowerCheck.hide() self.ui.checkPowerCheck.setChecked(False) if not self.dev.hasTunableWavelength: self.ui.wavelengthWidget.hide() self.powerWidget, self.powerPlot = self.createChannelWidget( 'power', daqName=self.dev.getDAQName()[0]) ## all we want is the function generator self.powerFnGenerator = self.powerWidget.ui.waveGeneratorWidget self.powerWidget.hide() self.ctrlLayout.addWidget(self.powerFnGenerator) self.powerFnGenerator.show() self.plotSplitter.addWidget(self.powerPlot) self.powerWidget.setMeta('y', units='W', siPrefix=True, dec=True, step=0.5, minStep=1e-3, limits=(0, None)) self.powerWidget.setMeta('xy', units='J', siPrefix=True, dec=True, step=0.5, minStep=1e-6, limits=(0, None)) self.powerWidget.setMeta('x', units='s', siPrefix=True, dec=True, step=0.5, minStep=1e-6, limits=(None, None)) if self.dev.hasTriggerableShutter: #(self.shutterWidget, self.shutterPlot) = self.createChannelWidget('shutter') self.shutterPlot = PlotWidget(name='%s.shutter' % self.dev.name) self.shutterPlot.setLabel('left', text='Shutter') self.plotSplitter.addWidget(self.shutterPlot) #self.shutterPlot.hide() if self.dev.hasQSwitch: #self.qSwitchWidget, self.qSwitchPlot = self.createChannelWidget('qSwitch') self.qSwitchPlot = PlotWidget(name='%s.qSwitch' % self.dev.name) self.qSwitchPlot.setLabel('left', text='Q-Switch') self.plotSplitter.addWidget(self.qSwitchPlot) #self.qSwitchPlot.hide() if self.dev.hasPCell: #self.pCellWidget, self.pCellPlot = self.createChannelWidget('pCell') self.pCellPlot = PlotWidget(name='%s.pCell' % self.dev.name) self.pCellPlot.setLabel('left', text='Pockel Cell', units='V') self.plotSplitter.addWidget(self.pCellPlot) #self.pCellPlot.hide() ## catch self.powerWidget.sigDataChanged and connect it to functions that calculate and plot raw shutter and qswitch traces self.powerWidget.sigDataChanged.connect(self.powerCmdChanged) self.ui.checkPowerBtn.clicked.connect(self.dev.outputPower) self.dev.sigOutputPowerChanged.connect(self.laserPowerChanged) self.dev.sigSamplePowerChanged.connect(self.samplePowerChanged) self.dev.outputPower() def laserPowerChanged(self, power, valid): #samplePower = self.dev.samplePower(power) ## we should get another signal for this later.. #samplePower = power*self.dev.getParam('scopeTransmission') ## update label if power is None: self.ui.outputPowerLabel.setText("?") else: self.ui.outputPowerLabel.setText(siFormat(power, suffix='W')) if not valid: self.ui.outputPowerLabel.setStyleSheet("QLabel {color: #B00}") else: self.ui.outputPowerLabel.setStyleSheet("QLabel {color: #000}") def samplePowerChanged(self, power): if power is None: self.ui.samplePowerLabel.setText("?") return else: self.ui.samplePowerLabel.setText(siFormat(power, suffix='W')) if self.dev.hasPCell: raise Exception('stub') else: ## adjust length of pulse to correct for new power if self.ui.adjustLengthCheck.isChecked(): en = {} for param in self.powerWidget.ui.waveGeneratorWidget.stimParams: en[param.name()] = param['sum'] self.powerWidget.setMeta('y', value=power, readonly=True) for param in self.powerWidget.ui.waveGeneratorWidget.stimParams: param['sum'] = en[param.name()] else: self.powerWidget.setMeta('y', value=power, readonly=True) def saveState(self): """Return a dictionary representing the current state of the widget.""" state = {} state['daqState'] = DAQGenericTaskGui.saveState(self) return state def restoreState(self, state): """Restore the state of the widget from a dictionary previously generated using saveState""" return DAQGenericTaskGui.restoreState(self, state['daqState']) def describe(self, params=None): state = self.saveState() ps = state['daqState']['channels']['power'] desc = {'mode': 'power', 'command': ps['waveGeneratorWidget']} return desc def prepareTaskStart(self): ## check power before starting task. if self.ui.checkPowerCheck.isChecked(): power = self.dev.outputPower() ## request current power from laser valid = self.dev.checkPowerValidity(power) if power is None: raise HelpfulException( "The current laser power for '%s' is unknown." % self.dev.name) if not valid: powerStr = siFormat(power, suffix='W') raise HelpfulException( "The current laser power for '%s' (%s) is outside the expected range." % (self.dev.name(), powerStr)) def generateTask(self, params=None): """Return a cmd dictionary suitable for passing to LaserTask.""" ## Params looks like: {'amp': 7} where 'amp' is the name of a sequence parameter, and 7 is the 7th value in the list of 'amp' for k, v in params.items(): if k.startswith('power.'): del params[k] params[k[6:]] = v rate = self.powerWidget.rate wave = self.powerWidget.getSingleWave(params) rawCmds = self.getChannelCmds(wave, rate) #rawCmds = self.cache.get(id(wave), self.dev.getChannelCmds({'powerWaveform':wave}, rate)) ## returns {'shutter': array(...), 'qSwitch':array(..), 'pCell':array(...)} ### structure task in DAQGeneric-compatible way cmd = {} for k in rawCmds: cmd[k] = {} cmd[k]['command'] = rawCmds[k] cmd['powerWaveform'] = wave ## just to allow the device task to store this data cmd['ignorePowerWaveform'] = True return cmd def getChannelCmds(self, powerWave, rate): key = id(powerWave) if key in self.cache: rawCmds = self.cache[key] else: rawCmds = self.dev.getChannelCmds( {'powerWaveform': powerWave}, rate ) ## returns {'shutter': array(...), 'qSwitch':array(..), 'pCell':array(...)} self.cache[key] = rawCmds return rawCmds def powerCmdChanged(self): self.clearRawPlots() self.cache = {} rate = self.powerWidget.rate #### calculate, cache and display sequence waves for shutter/qSwitch/pCell params = {} ps = self.powerWidget.listSequence() for k in ps: params[k] = range(len(ps[k])) ## get power waveforms waves = [] runSequence( lambda p: waves.append(self.powerWidget.getSingleWave(p)), params, params.keys( )) ## appends waveforms for the entire parameter space to waves for w in waves: if w is not None: ## need to translate w into raw traces, plot them, and cache them (using id(w) as a key) rawWaves = self.getChannelCmds(w, rate) #rawWaves = self.dev.getChannelCmds({'powerWaveform':w}, rate) ## calculate raw waveforms for shutter/qSwitch/pCell from powerWaveform #self.cache[id(w)] = rawWaves ## cache the calculated waveforms self.plotRawCurves( rawWaves, color=QtGui.QColor(100, 100, 100) ) ## plot the raw waveform in it's appropriate plot in grey ## calculate (or pull from cache) and display single-mode wave in red single = self.powerWidget.getSingleWave() if single is not None: #rawSingle = self.cache.get(id(single), self.dev.getChannelCmds({'powerWaveform':single}, rate)) rawSingle = self.getChannelCmds(single, rate) self.plotRawCurves(rawSingle, color=QtGui.QColor(200, 100, 100)) def plotRawCurves(self, data, color=QtGui.QColor(100, 100, 100)): if 'shutter' in data: self.shutterPlot.plot(y=data['shutter'], x=self.powerWidget.timeVals, pen=QtGui.QPen(color)) if 'qSwitch' in data: self.qSwitchPlot.plot(y=data['qSwitch'], x=self.powerWidget.timeVals, pen=QtGui.QPen(color)) if 'pCell' in data: self.pCellPlot.plot(y=data['pCell'], x=self.powerWidget.timeVals, pen=QtGui.QPen(color)) def clearRawPlots(self): for p in ['shutterPlot', 'qSwitchPlot', 'pCellPlot']: if hasattr(self, p): getattr(self, p).clear() def quit(self): self.dev.lastResult = None DAQGenericTaskGui.quit(self)