def main(): import sys from ab.abclient import getProtocol DEBUG = len(sys.argv) > 1 and sys.argv[1] == 'debug' polarizerProtocol = yield getProtocol( TEST_POLARIZER_SERVER if DEBUG else POLARIZER_SERVER) stepperMotorProtocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER) #memory management nonsense container.append(PolarizerWidget(polarizerProtocol, stepperMotorProtocol)) container[0].show() container[0].setWindowTitle('polarizer client ' + ('debug ' if DEBUG else 'real '))
def main(): import sys from ab.abclient import getProtocol DEBUG = len(sys.argv) > 1 and sys.argv[1] == 'debug' polarizerProtocol = yield getProtocol( TEST_POLARIZER_SERVER if DEBUG else POLARIZER_SERVER ) stepperMotorProtocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER ) #memory management nonsense container.append(PolarizerWidget(polarizerProtocol,stepperMotorProtocol)) container[0].show() container[0].setWindowTitle('polarizer client ' + ('debug ' if DEBUG else 'real '))
def main(): import sys from ab.abclient import getProtocol DEBUG = len(sys.argv) > 1 and sys.argv[1] == 'debug' wavelengthProtocol = yield getProtocol( TEST_WAVELENGTH_SERVER if DEBUG else WAVELENGTH_SERVER ) stepperMotorProtocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER ) #memory management nonsense trackingWidget = TrackingWidget(wavelengthProtocol,stepperMotorProtocol) container.append(trackingWidget) container[0].show() trackingWidget.setWindowTitle('tracking client')
def main(): protocol = yield getProtocol(URL) widget = VoltMeterWidget(protocol) container.append(widget) widget.show() widget.setWindowTitle('voltmeter client ' + ('debug ' if DEBUG else 'real '))
def initializeConsoleClient(self): url = VM_SERVER_CONFIG["url"] if not DEBUG else VM_DEBUG_SERVER_CONFIG["url"] self.protocol = yield getProtocol(url) def onMessage(d): print "message: %s" % d self.protocol.messageSubscribe("channel-parameter-changed", onMessage)
def main(): URL = VM_SERVER_CONFIG['url'] protocol = yield getProtocol(URL) vmClient = VoltMeterClient(protocol) widget = ChartRecordWidget(vmClient) container.append(widget) widget.show() widget.setWindowTitle('Chart Recorder 2015')
def initializeWAMP(self): protocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER) self.polSM = ChunkedStepperMotorClient(protocol, POL) angle = yield getType(float, 'enter polarizer angle: ') self.offset = {} BaseWAMP.initializeWAMP(self) yield self.calibrateAngle(angle)
def main(container): protocol = yield getProtocol( TEST_DELAY_GENERATOR_SERVER if LOCAL else DELAY_GENERATOR_SERVER) widget = DelayGeneratorWidget(protocol) container.append(widget) widget.setWindowTitle('delay generator client ' + ('debug ' if DEBUG else 'real ') + ('local' if LOCAL else 'sitz lab'))
def initializeConsoleClient(self): url = VM_SERVER_CONFIG['url'] if not DEBUG else VM_DEBUG_SERVER_CONFIG[ 'url'] self.protocol = yield getProtocol(url) def onMessage(d): print 'message: %s' % d self.protocol.messageSubscribe('channel-parameter-changed', onMessage)
def main(container): protocol = yield getProtocol( TEST_DELAY_GENERATOR_SERVER if LOCAL else DELAY_GENERATOR_SERVER ) widget = DelayGeneratorWidget(protocol) container.append(widget) widget.setWindowTitle('delay generator client ' + ('debug ' if DEBUG else 'real ') + ('local' if LOCAL else 'sitz lab'))
def main(): from ab.abclient import getProtocol from ab.abbase import selectFromList, getFloat, getType from types import LongType from config.serverURLs import DELAY_GENERATOR_SERVER, TEST_DELAY_GENERATOR_SERVER from sitz import printDict from config.delaygenerator import DG_CONFIG, DEBUG_DG_CONFIG import sys print sys.argv DEBUG = len(sys.argv) > 1 and 'debug' in sys.argv LOCAL = len(sys.argv) > 1 and 'local' in sys.argv print 'debug: %s' % DEBUG print 'local: %s' % LOCAL protocol = yield getProtocol( TEST_DELAY_GENERATOR_SERVER if LOCAL else DELAY_GENERATOR_SERVER ) client = DelayGeneratorClient(protocol) delay = yield client.getDelays() dgNameList = delay.keys() activeDGs = {} for dg in dgNameList: if DEBUG: activeDGs[dg] = DEBUG_DG_CONFIG[dg] else: activeDGs[dg] = DG_CONFIG[dg] dgNameList.insert(0,'Refresh') dgNameList.append('Done') while True: delay = yield client.getDelays() print 'current settings:' for key,val in delay.items(): print '\t %s: %s' % (key,val) dgToMod = yield selectFromList(dgNameList,"Which delay generator to adjust?") if dgToMod == "Refresh": continue if dgToMod == "Done": break delayVal = yield getType(LongType,prompt="Enter a new delay (in ns):") if activeDGs[dgToMod]['partner'] is not None: print 'this delay has a partner. the partner will automatically adjust unless you override.' override = raw_input("override? (y/n)") if override == 'Y' or override == 'y': client.setDelay(dgToMod,delayVal) else: print 'setting partnered delay' client.setPartnerDelay(dgToMod,delayVal) if activeDGs[dgToMod]['partner'] is None: client.setDelay(dgToMod,delayVal) print 'shutting down' reactor.stop()
def onReady(): vm_prot = yield getProtocol(VOLTMETER_SERVER) sm_prot = yield getProtocol(STEPPER_MOTOR_SERVER) dg_prot = yield getProtocol(DELAY_GENERATOR_SERVER) vm = VoltMeterClient(vm_prot) sm = StepperMotorClient(sm_prot,POL) dg = DelayGeneratorClient(dg_prot) delays = yield dg.getDelays() pumpTime = delays[MAV_PUMP_QSW] times = np.arange(TIME_START+pumpTime,TIME_STOP+pumpTime+TIME_STEP,TIME_STEP) angles = np.arange(ANGLE_START,ANGLE_STOP+ANGLE_STEP,ANGLE_STEP) channels = yield vm.getChannels() channel = yield selectFromList(channels,'pick the mcp channel') trans = yield selectFromList(['Q3','S3','Q1'],'pick the transition you are at') bsang = yield selectFromList(['020','110'],'pick the angle of the beam splitter') for i in range(REPEAT): for angle in np.concatenate((angles,angles[::-1])): yield sm.setPosition(int(degrees_to_steps(angle))) angleStr = str(angle).zfill(3) relPath, fileName = filenameGen(path.join(trans,'TimeOfFlight','BS'+str(bsang),'HWP'+angleStr)) absPath = path.join(POOHDATAPATH,relPath) checkPath(absPath) logName = path.join(absPath,fileName+'.tsv') thisLog = LogFile(logName) for time in times[::-1]: yield dg.setPartnerDelay(MAV_PROBE_QSW, int(time)) voltage, std = yield vm.getNVoltages(channel,SHOTS) stdom = std/np.sqrt(SHOTS) print (angle,time-pumpTime,voltage,stdom) thisLog.update([time,voltage,stdom]) thisLog.close() print BELL if WAIT_FOR_TUNE: pause(None,None) reactor.stop()
def main(): from ab.abclient import getProtocol from ab.abbase import selectFromList, getFloat, getType from types import LongType from config.serverURLs import DELAY_GENERATOR_SERVER, TEST_DELAY_GENERATOR_SERVER from sitz import printDict from config.delaygenerator import DG_CONFIG, DEBUG_DG_CONFIG import sys print sys.argv DEBUG = len(sys.argv) > 1 and 'debug' in sys.argv LOCAL = len(sys.argv) > 1 and 'local' in sys.argv print 'debug: %s' % DEBUG print 'local: %s' % LOCAL protocol = yield getProtocol( TEST_DELAY_GENERATOR_SERVER if LOCAL else DELAY_GENERATOR_SERVER) client = DelayGeneratorClient(protocol) delay = yield client.getDelays() dgNameList = delay.keys() activeDGs = {} for dg in dgNameList: if DEBUG: activeDGs[dg] = DEBUG_DG_CONFIG[dg] else: activeDGs[dg] = DG_CONFIG[dg] dgNameList.insert(0, 'Refresh') dgNameList.append('Done') while True: delay = yield client.getDelays() print 'current settings:' for key, val in delay.items(): print '\t %s: %s' % (key, val) dgToMod = yield selectFromList(dgNameList, "Which delay generator to adjust?") if dgToMod == "Refresh": continue if dgToMod == "Done": break delayVal = yield getType(LongType, prompt="Enter a new delay (in ns):") if activeDGs[dgToMod]['partner'] is not None: print 'this delay has a partner. the partner will automatically adjust unless you override.' override = raw_input("override? (y/n)") if override == 'Y' or override == 'y': client.setDelay(dgToMod, delayVal) else: print 'setting partnered delay' client.setPartnerDelay(dgToMod, delayVal) if activeDGs[dgToMod]['partner'] is None: client.setDelay(dgToMod, delayVal) print 'shutting down' reactor.stop()
def initializeWAMP(self): protocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER ) self.polSM = ChunkedStepperMotorClient(protocol,POL) angle = yield getType(float,'enter polarizer angle: ') self.offset = {} BaseWAMP.initializeWAMP(self) yield self.calibrateAngle(angle)
def initializeWAMP(self): self.tracking = False protocol = yield getProtocol(TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER) stepperMotors = self.stepperMotors = {id: ChunkedStepperMotorClient(protocol, id) for id in STEPPER_MOTOR_KEYS} calibrators = self.calibrators = { id: Calibrator() for id, Calibrator in ((KDP, KDPCrystalCalibrator), (BBO, BBOCrystalCalibrator)) } self.offsets = {} wavelength = yield getType(float, "enter surf wavelength: ") BaseWAMP.initializeWAMP(self) yield self.calibrateWavelength(wavelength)
def onReady(): vm_prot = yield getProtocol(VOLTMETER_SERVER) sm_prot = yield getProtocol(STEPPER_MOTOR_SERVER) vm = VoltMeterClient(vm_prot) sm = StepperMotorClient(sm_prot,POL) channels = yield vm.getChannels() channel = yield selectFromList(channels,'pick the mcp channel') trans = yield selectFromList(['Q3','S3','Q1'],'pick the transition you are at') bsang = yield selectFromList(['020','110'],'pick the angle of the beam splitter') # #suffix = yield selectFromList(['pump','unpump'],'are you pumping?') suffix = 'mBeamOff_diffZeroed' numPoints = (ANGLE_STOP-ANGLE_START+1)/ANGLE_STEP totalAcqTime = SWEEPS*2*(SHOTS/10.)*numPoints totalStepTime = ((ANGLE_STEP*SLOPE)/500.)*numPoints print 'ETA is: '+str((totalAcqTime + totalStepTime)/60.)+' minutes.' for sweep in range(SWEEPS): for direction in (FORWARDS,BACKWARDS): relPath, fileName = filenameGen(trans) absPath = path.join(POOHDATAPATH,relPath) checkPath(absPath) logName = path.join(absPath,fileName+'_pol_sweep_'+bsang+'_'+suffix+'.tsv') thisLog = LogFile(logName) for angle in { FORWARDS:forwards, BACKWARDS:backwards }[direction]: yield sm.setPosition(int(degrees_to_steps(angle))) voltage, std = yield vm.getNVoltages(channel,SHOTS) stdom = std/np.sqrt(SHOTS) print (sweep,angle,voltage, stdom) thisLog.update([angle,voltage,stdom]) thisLog.close() reactor.stop()
def main(): from sitz import TEST_STEPPER_MOTOR_SERVER from ab.abbase import getUserInput, sleep from ab.abclient import getProtocol from twisted.internet.defer import Deferred ## connect to server protocol = yield getProtocol(TEST_STEPPER_MOTOR_SERVER) ## get sm configuration config = yield protocol.sendCommand('get-configuration') delta = 2000 for id in config.keys(): # create client client = ChunkedStepperMotorClient(protocol, id) ## register for position updates def log(prompt, x): print '%s: %s' % (prompt, x) listener = partial(log, 'update for client %s' % client.id) client.addListener(client.POSITION, listener) ## change positions position = yield client.getPosition() delta /= 2 yield client.setPosition(position + delta) position = yield client.getPosition() # demonstrate canceling capabilities delta = -10000 d = Deferred() def onPositionChanged(newPosition): if d.called: print 'canceling!' client.cancel() client.removeListener(client.POSITION, onPositionChanged) else: print 'new pos: %d' % newPosition client.removeListener(client.POSITION, listener) client.addListener(client.POSITION, onPositionChanged) print '' yield sleep(.5) print 'starting long journey: press enter to quit' yield sleep(1.5) print '' e = client.setPosition(position + delta) yield getUserInput('') d.callback(None) yield e print 'shutting down' reactor.stop()
def main(): URL = VM_SERVER_CONFIG['url'] protocol = yield getProtocol(URL) client = VoltMeterClient(protocol) callbackRate = yield client.getCallbackRate() timeBetweenNewVoltages = 1.0/callbackRate chanList = yield client.getChannels() chan = chanList[0] range = yield getRange(client,chan) print range while True: newVoltages = yield getVoltages(client,timeBetweenNewVoltages) print newVoltages
def main(container): # check if debugging / testing import sys DEBUG = len(sys.argv) > 1 and sys.argv[1] == 'debug' #from sitz import STEPPER_MOTOR_SERVER, TEST_STEPPER_MOTOR_SERVER from config.serverURLs import STEPPER_MOTOR_SERVER, TEST_STEPPER_MOTOR_SERVER from ab.abclient import getProtocol protocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER) widget = StepperMotorWidget(protocol) container.append(widget) widget.setWindowTitle('%s stepper motor gui' % ('debug' if DEBUG else 'real'))
def main(container): # check if debugging / testing import sys DEBUG = len(sys.argv) > 1 and sys.argv[1] == 'debug' #from sitz import STEPPER_MOTOR_SERVER, TEST_STEPPER_MOTOR_SERVER from config.serverURLs import STEPPER_MOTOR_SERVER, TEST_STEPPER_MOTOR_SERVER from ab.abclient import getProtocol protocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER ) widget = StepperMotorWidget(protocol) container.append(widget) widget.setWindowTitle('%s stepper motor gui' % ('debug' if DEBUG else 'real'))
def initializeWAMP(self): self.tracking = False protocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER) stepperMotors = self.stepperMotors = { id: ChunkedStepperMotorClient(protocol, id) for id in STEPPER_MOTOR_KEYS } calibrators = self.calibrators = { id: Calibrator() for id, Calibrator in ((KDP, KDPCrystalCalibrator), (BBO, BBOCrystalCalibrator)) } self.offsets = {} wavelength = yield getType(float, 'enter surf wavelength: ') BaseWAMP.initializeWAMP(self) yield self.calibrateWavelength(wavelength)
def main(): from config.serverURLs import SPECTROMETER_SERVER, TEST_SPECTROMETER_SERVER from ab.abclient import getProtocol from twisted.internet.defer import Deferred ## connect to server ipAddress = TEST_SPECTROMETER_SERVER if DEBUG else SPECTROMETER_SERVER protocol = yield getProtocol(ipAddress) ## create a client client = SpectrometerClient(protocol) @inlineCallbacks def displayNew(): payload = yield client.getSpectrum() print len(payload) @inlineCallbacks def getRange(): range = yield client.getWavelengths() print len(range) @inlineCallbacks def getTime(): time = yield client.getLastTime() print time ## get spectrum yield displayNew() yield getRange() yield getTime() ## quit reactor.stop()
def main(): protocol = yield getProtocol(WAVELENGTH_SERVER) runConsoleClient(TrackingConsoleClient,protocol)
def main(): protocol = yield getProtocol(WAVELENGTH_SERVER) runConsoleClient(TrackingConsoleClient, protocol)
def SmartScanGUI(): # oh god i'm so sorry class self: x,y,err = [], [], [] #configure a layout for the plot widget & controls to go side by side on widget = QtGui.QWidget() container.append(widget) widget.show() layout = QtGui.QHBoxLayout() widget.setLayout(layout) # create a plot and associated widget plotWidget = PlotWidget() plot = plotWidget.plot() layout.addWidget(plotWidget,1) # configure a control panel layout cpLayout = QtGui.QVBoxLayout() layout.addLayout(cpLayout) # configure the output widget outputWidget = ComboWidget() cpLayout.addWidget(LabelWidget('output',outputWidget)) # add volt meter to scan output vmProtocol = yield getProtocol( (VM_DEBUG_SERVER_CONFIG if DEBUG else VM_SERVER_CONFIG)['url'] ) vmClient = VoltMeterClient(vmProtocol) vmWidget = VoltMeterOutputWidget(vmClient) outputWidget.addTab(vmWidget,'voltmeter') # configure the input widget inputWidget = ComboWidget() inputWidget.setTabPosition(inputWidget.West) cpLayout.addWidget(LabelWidget('input',inputWidget),1) inputWidget.addTab( ManualInputWidget(widget), 'manual' ) inputWidget.addTab( ManualScanInputWidget(widget), 'manual scan' ) # algorithm for scan inputs is: # 0. check to see if input is disabled # 1. create client for server from protocol object # 2. create combo widget to hold interval and list widgets # 3. create interval widget using client object, add to combo # 4. same for list widget # 5. add combo widget to base combo widget (resulting in 2-D tab widget) if INPUTS_TOGGLE[SM_BOOL]: # add stepper motors to scan input smProtocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER ) smClients = { smID:ChunkedStepperMotorClient(smProtocol,smID) for smID in (KDP,BBO,PDL) } for smID,smClient in smClients.items(): combo_input_widget = ComboWidget() combo_input_widget.addTab( CenterInputWidget( smClient.setPosition, smClient.cancel, -99999, 99999, 0, 0, 0, 1000, 0, 10, smClient.getPosition ), 'interval' ) combo_input_widget.addTab( ListInputWidget( smClient.setPosition, smClient.cancel ), 'list' ) inputWidget.addTab( combo_input_widget, { KDP:'kdp', BBO:'bbo', PDL:'pdl' }[smID] ) if INPUTS_TOGGLE[WL_BOOL]: # add wavelength client to scan input wlProtocol = yield getProtocol( TEST_WAVELENGTH_SERVER if DEBUG else WAVELENGTH_SERVER ) wlClient = WavelengthClient(wlProtocol) wlInputWidget = ComboWidget() wlInputWidget.addTab( CenterInputWidget( wlClient.setWavelength, wlClient.cancelWavelengthSet, 24100.0, 25000.0, 2, 24200.0, 0.01, 100.0, 2, .2, wlClient.getWavelength ), 'interval' ) wlInputWidget.addTab( ListInputWidget( wlClient.setWavelength, wlClient.cancelWavelengthSet ), 'list' ) inputWidget.addTab( wlInputWidget, 'surf' ) if INPUTS_TOGGLE[DDG_BOOL]: # add delay generator to scan input dgProtocol = yield getProtocol( TEST_DELAY_GENERATOR_SERVER if DEBUG else DELAY_GENERATOR_SERVER ) dgClient = DelayGeneratorClient(dgProtocol) delays = yield dgClient.getDelays() for dgID in delays.keys(): def setter(dgID): @inlineCallbacks def _setter(delay): yield dgClient.setPartnerDelay(dgID,delay) returnValue(delay) return _setter def getter(dgID): @inlineCallbacks def _getter(): delays = yield dgClient.getDelays() returnValue(delays[dgID]) return _getter def cancel(dgID): def _cancel(): pass return _cancel dgCombo = ComboWidget() dgCombo.addTab( CenterInputWidget( setter(dgID), cancel(dgID), 1, 50000000, 0, 3896550.0, 0, 1000000, 1, 100, getter(dgID) ), 'interval' ) dgCombo.addTab( ListInputWidget( setter(dgID), cancel(dgID) ), 'list' ) inputWidget.addTab( dgCombo, dgID ) #create a scan toggle scanToggle = SmartScanToggleObject() cpLayout.addWidget( LabelWidget( 'scan',ToggleWidget(scanToggle) ) ) def onActivationRequested(): # empty data for l in (self.x,self.y,self.err): while l: l.pop() # get current selected scan output, scan input scanOutput = outputWidget.getOutput() scanInput = inputWidget.getInput() scanToggle.setOutput(scanOutput.next) scanToggle.setInput(scanInput.next) # on stop request, send cancel signal to scan input and output def cancel(): scanInput.cancel() scanOutput.cancel() scanToggle.setCancel(cancel) # start scan scanToggle.toggle() scanToggle.activationRequested.connect(onActivationRequested) # plot on step completion def onStepped(data): # unpack scan step data position, output = data # unpack output as mean and error mean, err = output # update plot data self.x.append(position) self.y.append(mean) self.err.append(err) # update plot plotWidget.clear() plotWidget.plot(self.x,self.y) plotWidget.addItem( ErrorBarItem( x=np.asarray(self.x), y=np.asarray(self.y), top=np.asarray(self.err), bottom=np.asarray(self.err), beam=.05 ) ) # ready for next step! scanToggle.completeStep() scanToggle.stepped.connect(onStepped) # set up data saving capabilities (ask bobby re: this) saveLayout = QtGui.QVBoxLayout() def onSaveClicked(): dataArray = np.asarray( [self.x,self.y,self.err], dtype=np.dtype(np.float32) ) date = datetime.datetime.now().strftime("%Y-%m-%d") time = datetime.datetime.now().strftime("%H%M") dir = os.path.join( POOHDATAPATH, date ) if not os.path.exists(dir): os.makedirs(dir) path = QtGui.QFileDialog.getExistingDirectory( widget, 'select filename', dir ) if not path: return desc, valid = QtGui.QInputDialog.getText( widget, 'enter file description', 'description' ) filename = '%s_%s.csv' % (time,desc) if valid else '%s.csv' % time np.savetxt( os.path.join( path, filename ), dataArray.transpose(), delimiter=',' ) saveCSVButton = QtGui.QPushButton('save (csv)') saveCSVButton.clicked.connect(onSaveClicked) saveLayout.addWidget(SqueezeRow(saveCSVButton)) cpLayout.addWidget( LabelWidget( 'save', saveLayout ) )
def SmartScanGUI(): # oh god i'm so sorry. don't listen to him; he's never sorry. class self: x,y,err = [], [], [] refData = {} #configure a layout for the plot widget & controls to go side by side on widget = QtGui.QWidget() container.append(widget) widget.show() layout = QtGui.QHBoxLayout() widget.setLayout(layout) # create a plot and associated widget plotWidget = PlotWidget() plot = plotWidget.plot() layout.addWidget(plotWidget,1) # configure a control panel layout cpLayout = QtGui.QVBoxLayout() layout.addLayout(cpLayout) # configure the output widget outputPane = ComboWidget() cpLayout.addWidget(LabelWidget('output',outputPane)) ############################################################# VOLTMETER OUTPUT ########################################################### # add volt meter to scan output vmProtocol = yield getProtocol( (VM_DEBUG_SERVER_CONFIG if DEBUG else VM_SERVER_CONFIG)['url'] ) vmClient = VoltMeterClient(vmProtocol) vmWidget = VoltMeterOutputWidget(vmClient) outputPane.addTab(vmWidget,'voltmeter') ############################################################# BEGIN INPUTS ########################################################### # configure the input widget inputPane = ComboWidget() inputPane.setTabPosition(inputPane.West) cpLayout.addWidget(LabelWidget('input',inputPane),1) inputPane.addTab( ManualInputWidget(widget), 'manual' ) inputPane.addTab( ManualScanInputWidget(widget), 'manual scan' ) # algorithm for scan inputs is: # 0. check to see if input is disabled # 1. create client for server from protocol object # 2. create combo widget to hold interval and list widgets # 3. create interval widget using client object, add to combo # 4. same for list widget # 5. add combo widget to base combo widget (resulting in 2-D tab widget) ############################################################# STEPPER MOTOR INPUTS ########################################################### if INPUTS_TOGGLE[SM_BOOL]: # add stepper motors to scan input smProtocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER ) smClients = { smID:ChunkedStepperMotorClient(smProtocol,smID) for smID in (KDP,BBO,PDL,LID,POL) } for smID,smClient in smClients.items(): thisInputWidget = CenterInputWidget( smClient.setPosition, smClient.cancel, -99999, 99999, 0, 0, 0, 1000, 0, 10, smClient.getPosition ) inputPane.addTab( thisInputWidget, { KDP:'kdp', BBO:'bbo', PDL:'pdl', LID:'lid', POL:'pol' }[smID] ) ''' ############################################################# WAVELENGTH SERVER INPUT ########################################################### if INPUTS_TOGGLE[WL_BOOL]: # add wavelength client to scan input wlProtocol = yield getProtocol( TEST_WAVELENGTH_SERVER if DEBUG else WAVELENGTH_SERVER ) wlClient = WavelengthClient(wlProtocol) wlInputWidget = CenterInputWidget( wlClient.setWavelength, wlClient.cancelWavelengthSet, 24100.0, 25000.0, 2, 24200.0, 0.01, 100.0, 2, .2, wlClient.getWavelength ) inputPane.addTab( wlInputWidget, 'surf' ) ############################################################# POLARIZER SERVER INPUT ########################################################### if INPUTS_TOGGLE[POL_BOOL]: # add wavelength client to scan input polProtocol = yield getProtocol( TEST_POLARIZER_SERVER if DEBUG else POLARIZER_SERVER ) polClient = PolarizerClient(polProtocol) polInputWidget = CenterInputWidget( polClient.setAngle, #agent to progress the scan polClient.cancelAngleSet, #agent to abort the scan -720.0, #minimum value of scan bounds 720.0, #maximum value of scan bounds 2, #precision (number of zeroes after decimal) on bounds 90.0, #initial value for scan bounds 0.01, #minimum value of step size 180.0, #maximum value of scan bounds 2, #precision (number of zeroes after decimal) on step size 5.0, #initial value for step size polClient.getAngle #agent to read position for scan ) inputPane.addTab( polInputWidget, 'polServ' ) ''' ############################################################# DDG INPUTS ########################################################### if INPUTS_TOGGLE[DDG_BOOL]: # add delay generator to scan input dgProtocol = yield getProtocol( TEST_DELAY_GENERATOR_SERVER if DEBUG else DELAY_GENERATOR_SERVER ) dgClient = DelayGeneratorClient(dgProtocol) delays = yield dgClient.getDelays() for dgID in delays.keys(): def setter(dgID): @inlineCallbacks def _setter(delay): yield dgClient.setPartnerDelay(dgID,delay) returnValue(delay) return _setter def getter(dgID): @inlineCallbacks def _getter(): delays = yield dgClient.getDelays() returnValue(delays[dgID]) return _getter def cancel(dgID): def _cancel(): pass return _cancel dgCombo = CenterInputWidget( setter(dgID), cancel(dgID), 1, 50000000, 0, 3896550.0, 0, 1000000, 1, 100, getter(dgID) ) inputPane.addTab( dgCombo, dgID ) ############################################################# END INPUTS ########################################################### ############################################################# SCANNING ########################################################### #create a scan toggle scanToggle = CancelScanToggleObject() scanPane = QtGui.QVBoxLayout() scanPane.addWidget(ToggleWidget(scanToggle)) repeatSpinBox = QtGui.QSpinBox() repeatSpinBox.setRange(1,10000) repeatSpinBox.setValue(1) scanPane.addWidget(LabelWidget('repeat',repeatSpinBox)) cpLayout.addWidget(LabelWidget('scan',scanPane)) def onActivationRequested(): # empty data for l in (self.x,self.y,self.err): while l: l.pop() # get current selected scan output, scan input scanOutput = outputPane.getOutput() scanInput = inputPane.getInput() scanToggle.setOutput(scanOutput.next) scanToggle.setInput(scanInput.next) # on stop request, send cancel signal to scan input and output def cancel(): scanInput.cancel() scanOutput.cancel() scanToggle.setCancel(cancel) # set autoscale on x & y axes when a new scan is started plotWidget.enableAutoRange() # start scan scanToggle.toggle() scanToggle.activationRequested.connect(onActivationRequested) ############################################################# PLOTTING ########################################################### def xYPlot(plotWidget,x,y,yerr=None,xerr=None,color='w',name='Current'): thisPlot = plotWidget.plot(x,y,pen=mkPen(color,width=2)) plotWidget.addItem( ErrorBarItem( x=np.asarray(x), y=np.asarray(y), top=np.asarray(yerr) if yerr is not None else None, bottom=np.asarray(yerr) if yerr is not None else None, left=np.asarray(xerr) if xerr is not None else None, right=np.asarray(xerr) if xerr is not None else None, beam=.05, pen=mkPen(color) ) ) # plot on step completion def updatePlot(): plotWidget.clear() for name, refData in self.refData.iteritems(): xYPlot( plotWidget, refData['data'][0], refData['data'][1], yerr=refData['data'][2], color=refData['color'], name=name ) if len(self.x) >= 1: xYPlot(plotWidget,self.x,self.y,yerr=self.err) def onStepped(data): # unpack scan step data position, output = data # unpack output as mean and error mean, err = output # update plot data self.x.append(position) self.y.append(mean) self.err.append(err) # update plot updatePlot() # ready for next step! scanToggle.completeStep() scanToggle.stepped.connect(onStepped) ############################################################# LOAD FUNCTIONS ########################################################### # set up reference data capabilities refLayout = QtGui.QHBoxLayout() def onLoadClicked(): date = datetime.datetime.now().strftime("%Y-%m-%d") time = datetime.datetime.now().strftime("%H%M") dir = os.path.join( POOHDATAPATH, date ) refFileName = QtGui.QFileDialog.getOpenFileName( widget, 'select file', dir, "CSV Files (*.csv)" ) refData = np.loadtxt(open(refFileName[0],"rb"),delimiter=",") name = refFileName[0].rpartition('/')[2] color = QtGui.QColorDialog.getColor() self.refData[name] = { 'color': color, 'data': [refData[:,0], refData[:,1], refData[:,2]] } updatePlot() loadButton = QtGui.QPushButton('load') loadButton.clicked.connect(onLoadClicked) refLayout.addWidget(SqueezeRow(loadButton)) def onClearClicked(): for refs in self.refData.keys(): del self.refData[refs] updatePlot() clearButton = QtGui.QPushButton('clear all') clearButton.clicked.connect(onClearClicked) refLayout.addWidget(SqueezeRow(clearButton)) cpLayout.addWidget( LabelWidget( 'reference', refLayout ) ) # set up data saving capabilities saveLayout = QtGui.QVBoxLayout() ############################################################# SAVE FUNCTIONS ########################################################### def onSaveClicked(): dataArray = np.asarray( [self.x,self.y,self.err], dtype=np.dtype(np.float32) ) date = datetime.datetime.now().strftime("%Y-%m-%d") time = datetime.datetime.now().strftime("%H%M") dir = os.path.join( POOHDATAPATH, date ) if not os.path.exists(dir): os.makedirs(dir) path = QtGui.QFileDialog.getExistingDirectory( widget, 'select filename', dir ) if not path: return desc, valid = QtGui.QInputDialog.getText( widget, 'enter file description', 'description' ) filename = '%s_%s.csv' % (time,desc) if valid else '%s.csv' % time np.savetxt( os.path.join( path, filename ), dataArray.transpose(), delimiter=',' ) saveButton = QtGui.QPushButton('save') saveButton.clicked.connect(onSaveClicked) saveLayout.addWidget(SqueezeRow(saveButton)) cpLayout.addWidget( LabelWidget( 'save', saveLayout ) )
def onInit(): # connect to server ipAddress = TEST_SPECTROMETER_SERVER if DEBUG else SPECTROMETER_SERVER protocol = yield getProtocol(ipAddress) # create a client self.client = SpectrometerClient(protocol) self.wave = yield self.client.getWavelengths() self.numberToAverage = 1 self.numberAcquired = 0 self.darkSpectrum = np.zeros(NUM_PIXELS) self.specProcessed = np.zeros(NUM_PIXELS) self.gettingDark = False # set up overall layout: 1 large panel (plot) to left of 1 narrow / # panel (controls) all above 1 skinny panel (timestamp) fullLayout = QtGui.QVBoxLayout() self.layout().addLayout(fullLayout) topHalfLayout = QtGui.QHBoxLayout() fullLayout.addLayout(topHalfLayout) # define the plot self.plotWidget = PlotWidget() self.plot = self.plotWidget.plot() topHalfLayout.addWidget(self.plotWidget, 1) # define the controls panel cpLayout = QtGui.QVBoxLayout() topHalfLayout.addLayout(cpLayout) # define the capture controls (to go on controls panel) capLayout = QtGui.QVBoxLayout() def updatePlot(x, y): x = np.asarray(x) y = np.asarray(y) self.plotWidget.clear() self.plotWidget.plot(x, y, pen=mkPen("w", width=1)) self.plotWidget.addItem(self.cursorVert) self.plotWidget.addItem(self.cursorHori) vertLabel.setText(str(round(self.cursorVert.pos()[0], 2))) horiLabel.setText(str(round(self.cursorHori.pos()[1], 2))) def avgSpec(): oldAvgSpec = self.specProcessed addThis = self.spec - self.darkSpectrum self.numberAcquired += 1 if self.numberAcquired < self.numberToAverage: scale = self.numberAcquired else: scale = self.numberToAverage newAvg = ((scale - 1) * oldAvgSpec + addThis) / scale self.specProcessed = newAvg @inlineCallbacks def capture(): self.spec = yield self.client.getSpectrum() self.spec = np.asarray(self.spec) self.time = yield self.client.getLastTime() yield avgSpec() updatePlot(self.wave, self.specProcessed) self.timestamp.setText("last update: " + str(self.time)) @inlineCallbacks def forcePress(): self.numberAcquired = 0 yield capture() forceButton = QtGui.QPushButton("force") forceButton.clicked.connect(forcePress) capLayout.addWidget(forceButton) autoRunLayout = QtGui.QHBoxLayout() self.freeRunCall = LoopingCall(capture) self.freeRunStatus = False def freeRun(): if self.freeRunStatus: freeButton.setText("start auto") forceButton.setEnabled(True) self.freeRunCall.stop() self.freeRunStatus = False self.numberAcquired = 0 return if not self.freeRunStatus: freeButton.setText("stop auto") forceButton.setEnabled(False) self.freeRunCall.start(autoRateSpin.value(), now=True) self.freeRunStatus = True freeButton = QtGui.QPushButton("start auto") freeButton.clicked.connect(freeRun) autoRunLayout.addWidget(freeButton) def updateAutoRate(): if self.freeRunStatus: self.freeRunCall.stop() self.freeRunCall.start(autoRateSpin.value(), now=True) autoRateSpin = QtGui.QDoubleSpinBox() autoRateSpin.setRange(0.1, 10000.0) autoRateSpin.setValue(0.5) autoRateSpin.setSuffix("s") autoRateSpin.setSingleStep(0.1) autoRateSpin.valueChanged.connect(updateAutoRate) autoRunLayout.addWidget(autoRateSpin) capLayout.addLayout(autoRunLayout) cpLayout.addWidget(LabelWidget("capture", capLayout)) # define the cursor/analysis controls curLayout = QtGui.QVBoxLayout() cpLayout.addWidget(LabelWidget("analysis", curLayout)) self.cursorVert = InfiniteLine( pos=self.wave[NUM_PIXELS / 2], angle=90, pen=mkPen("g", width=0.5), movable=True ) self.cursorHori = InfiniteLine(pos=0, angle=0, pen=mkPen("g", width=0.5), movable=True) self.plotWidget.addItem(self.cursorVert) self.plotWidget.addItem(self.cursorHori) vertLayout = QtGui.QHBoxLayout() vertName = QtGui.QLabel() vertName.setText("wavelength: ") vertLayout.addWidget(vertName) vertLabel = QtGui.QLabel() vertLabel.setText(str(round(self.cursorVert.pos()[0], 2))) vertLayout.addWidget(vertLabel) curLayout.addLayout(vertLayout) horiLayout = QtGui.QHBoxLayout() horiName = QtGui.QLabel() horiName.setText("intensity: ") horiLayout.addWidget(horiName) horiLabel = QtGui.QLabel() horiLabel.setText(str(round(self.cursorHori.pos()[0], 2))) horiLayout.addWidget(horiLabel) curLayout.addLayout(horiLayout) # define the acquisition controls acqLayout = QtGui.QVBoxLayout() cpLayout.addWidget(LabelWidget("acquisition", acqLayout)) # integration integLayout = QtGui.QHBoxLayout() acqLayout.addLayout(integLayout) integTimeLabel = QtGui.QLabel() integTimeLabel.setText("integration: ") integLayout.addWidget(integTimeLabel) def integTimeUpdate(): newTime = integTimeSpin.value() self.client.setIntegrationTime(newTime) integTimeSpin = QtGui.QDoubleSpinBox() integTimeSpin.setRange(0.001, 10) integTimeSpin.setDecimals(3) integTimeSpin.setValue(0.100) integTimeSpin.setSingleStep(0.05) integTimeSpin.setSuffix("s") integTimeSpin.editingFinished.connect(integTimeUpdate) integLayout.addWidget(integTimeSpin) # averaging avgLayout = QtGui.QHBoxLayout() acqLayout.addLayout(avgLayout) avgLabel = QtGui.QLabel() avgLabel.setText("averaging: ") avgLayout.addWidget(avgLabel) def avgUpdate(): self.numberToAverage = avgSpin.value() avgSpin = QtGui.QSpinBox() avgSpin.setRange(1, 10000) avgSpin.setValue(1) avgSpin.valueChanged.connect(avgUpdate) avgLayout.addWidget(avgSpin) # dark spectrum darkLayout = QtGui.QHBoxLayout() acqLayout.addLayout(darkLayout) @inlineCallbacks def getDark(): resetDark() self.gettingDark = True self.numberAcquired = 0 wasInAuto = self.freeRunStatus if self.freeRunStatus: freeRun() # if in auto mode, stop it self.specProcessed = np.zeros(NUM_PIXELS) for specCount in range(self.numberToAverage): yield capture() self.darkSpectrum = self.specProcessed self.specProcessed = np.zeros(NUM_PIXELS) if wasInAuto: freeRun() self.numberAcquired = 0 self.gettingDark = False darkSpecButton = QtGui.QPushButton("dark") darkSpecButton.clicked.connect(getDark) darkLayout.addWidget(darkSpecButton) def resetDark(): self.darkSpectrum = np.zeros(NUM_PIXELS) self.specProcessed = np.zeros(NUM_PIXELS) resetDarkButton = QtGui.QPushButton("reset") resetDarkButton.clicked.connect(resetDark) darkLayout.addWidget(resetDarkButton) # define the timestamp panel self.timestamp = QtGui.QLabel() self.timestamp.setText("last update: never") self.timestamp.setAlignment(QtCore.Qt.AlignCenter) fullLayout.addWidget(self.timestamp)
def pollVMServer(serverURL): from ab.abclient import getProtocol protocol = yield getProtocol(serverURL) client = VoltMeterClient(protocol) vmNameList = yield client.getChannels() returnValue(vmNameList)
def onInit(): ############################################################# VOLTMETER OUTPUT ########################################################### # add volt meter to scan output if DEBUG: vmURL = TEST_VOLTMETER_SERVER else: vmURL = VOLTMETER_SERVER vmProtocol = yield getProtocol(vmURL) vmClient = VoltMeterClient(vmProtocol) vmWidget = VoltMeterOutputWidget(vmClient) outputPane.addTab(vmWidget,'voltmeter') ############################################################# BEGIN INPUTS ########################################################### # configure the input widget inputPane = QtGui.QTabWidget() inputPane.setTabPosition(inputPane.West) cpLayout.addWidget(LabelWidget('input',inputPane),1) # algorithm for scan inputs is: # 0. check to see if input is disabled # 1. create client for server from protocol object # 2. create combo widget to hold interval and list widgets # 3. create interval widget using client object, add to combo # 4. same for list widget # 5. add combo widget to base combo widget (resulting in 2-D tab widget) ############################################################# MANUAL INPUT ########################################################### class ManualInputWidget(QtGui.QWidget): def __init__(self,parentWidget): QtGui.QWidget.__init__(self) self.parentWidget = parentWidget self.done = False def initScan(self): return def checkIfDone(self): return def next(self): result, valid = QtGui.QInputDialog.getDouble( self.parentWidget, 'next x value', 'enter next x value', decimals=6 ) if valid: return result else: return None def cancel(self): return inputPane.addTab( ManualInputWidget(self), 'manual' ) ############################################################# MANUAL SCAN INPUT ########################################################### class ManualScanInputWidget(InputWidget): def __init__(self,parent): spinBoxProps = { 'rangeMin':-100000, 'rangeMax':100000, 'stepMin':.000001, 'stepMax':100000, 'startInit':0, 'stopInit':1, 'stepSizeInit':.1 } def setPosition(position): msgBox = QtGui.QMessageBox() msgBox.setText("next position:\t"+str(position)) msgBox.setStandardButtons(QtGui.QMessageBox.Ok | QtGui.QMessageBox.Cancel) msgBox.setDefaultButton(QtGui.QMessageBox.Ok) ret = msgBox.exec_() if ret == QtGui.QMessageBox.Ok: return position elif ret == QtGui.QMessageBox.Cancel: return None InputWidget.__init__(self,lambda(x):None,setPosition,spinBoxProperties = spinBoxProps) inputPane.addTab( ManualScanInputWidget(self), 'manual scan' ) ############################################################# STEPPER MOTOR INPUTS ########################################################### # load in the stepper motor names from config.steppermotor import KDP, BBO, PDL, LID, POL # get stepper motor protocol (how to communicate to stepper motor server) smProtocol = yield getProtocol( TEST_STEPPER_MOTOR_SERVER if DEBUG else STEPPER_MOTOR_SERVER ) # define a chunked (cancellable) client for each stepper motor stepperMotorsClients = {} for stepperMotorName in (KDP,BBO,PDL,LID,POL): stepperMotorsClients[stepperMotorName] = ChunkedStepperMotorClient(smProtocol,stepperMotorName) # define an input widget for each stepper motor, each add to input pane for smID,smClient in stepperMotorsClients.items(): spinBoxProps = { 'rangeMin':-100000, 'rangeMax':100000, 'stepMin':1, 'stepMax':100000, 'startInit':0, 'stopInit':100, 'stepSizeInit':1 } thisInputWidget = InputWidget( smClient.getPosition, smClient.setPosition, cancelCommand = smClient.cancel, spinBoxProperties = spinBoxProps ) inputPane.addTab( thisInputWidget, smID ) ############################################################# WAVELENGTH SERVER INPUT ########################################################### ''' # add wavelength client to scan input wlProtocol = yield getProtocol( TEST_WAVELENGTH_SERVER if DEBUG else WAVELENGTH_SERVER ) wlClient = WavelengthClient(wlProtocol) spinBoxProps = { 'rangeMin':24100, 'rangeMax':25000, 'stepMin':.01, 'stepMax':900, 'startInit':24200, 'stopInit':24220, 'stepSizeInit':1 } wlInputWidget = InputWidget( wlClient.getWavelength, wlClient.setWavelength, cancelCommand = wlClient.cancelWavelengthSet, spinBoxProperties = spinBoxProps ) inputPane.addTab( wlInputWidget, 'wl' ) ''' ############################################################# POLARIZER SERVER INPUT ########################################################### ''' # get protocol polProtocol = yield getProtocol( TEST_POLARIZER_SERVER if DEBUG else POLARIZER_SERVER ) # define the client polClient = PolarizerClient(polProtocol) # set limits on spinboxes spinBoxProps = { 'rangeMin':-720, 'rangeMax':720, 'stepMin':.01, 'stepMax':720, 'startInit':0, 'stopInit':90, 'stepSizeInit':5 } polInputWidget = InputWidget( polClient.getAngle, polClient.setAngle, cancelCommand = polClient.cancelAngleSet, spinBoxProperties = spinBoxProps ) inputPane.addTab( polInputWidget, 'pol' ) ''' ############################################################# DDG INPUTS ########################################################### # load in the delay generator names from config.delaygenerator import MAV_PUMP_LAMP, MAV_PUMP_QSW, MAV_PROBE_LAMP, MAV_PROBE_QSW, MAV_NOZZLE # load in the delay generator limits from config.delaygenerator import MIN_DELAY, MAX_DELAY, DELAY_RES # get the delay generator protocol dgProtocol = yield getProtocol( TEST_DELAY_GENERATOR_SERVER if DEBUG else DELAY_GENERATOR_SERVER ) dgClient = DelayGeneratorClient(dgProtocol) # define an input widget for each delay generator, each add to input pane for dgName in (MAV_PUMP_LAMP, MAV_PUMP_QSW, MAV_PROBE_LAMP, MAV_PROBE_QSW, MAV_NOZZLE): spinBoxProps = { 'rangeMin':MIN_DELAY, 'rangeMax':MAX_DELAY, 'stepMin':DELAY_RES, 'stepMax':MAX_DELAY-MIN_DELAY, 'startInit':1, 'stopInit':1001, 'stepSizeInit':10 } # because there is one DG client for all DGs (unlike SM client), we use partial to map the client\ # commands to individual DGs so that we preserve as much of the same structure as possible. thisInputWidget = InputWidget( partial(dgClient.getDelay,dgName), partial(dgClient.setPartnerDelay,dgName), spinBoxProperties = spinBoxProps ) inputPane.addTab( thisInputWidget, dgName ) ############################################################# END INPUTS ########################################################### ############################################################# SCANNING ########################################################### #define fundamental scan logic: # 1: ask independent variable to change, wait # 2: measure dependent # 3: perform onStep task with x-y pair (e.g. update plot) class Scan: def __init__(self,inputWidget,outputWidget,onStepFunct,repeats=1,plotWidget=None): self.input = inputWidget self.output = outputWidget self.onStep = onStepFunct self.output.plot = plotWidget self.repeatTotal = repeats self.activeRepeat = 1 self.startScan() def startScan(self): if len(self.input.scanValues) == 0: self.input.initScan() self.output.initScan() self.paused = False self.done = False self.loop() @inlineCallbacks def loop(self): # pause if paused if self.paused: resumeCancelDialog = QtGui.QMessageBox() resumeCancelDialog.setText("the scan has been paused.") resumeCancelDialog.setInformativeText("do you want to cancel the scan?") resumeCancelDialog.setStandardButtons(QtGui.QMessageBox.Yes | QtGui.QMessageBox.No) resumeCancelDialog.setDefaultButton(QtGui.QMessageBox.No) option = resumeCancelDialog.exec_() if option == QtGui.QMessageBox.Yes: #quit the scan self.cancel() return if option == QtGui.QMessageBox.No: #resume the scan self.resume() while self.paused: QtGui.QApplication.processEvents() sleep(.1) # check if done by asking input self.input.checkIfDone() inputDone = self.input.done # if done, finish to clean up if inputDone: self.finish() # if not done, continue onto next point & measure if not inputDone: inputData = yield self.input.next() if inputData == None: yield self.cancel() return else: self.output.setPlotterXVal(inputData) outputDataDefer = self.output.startAcquisition() outputData = yield outputDataDefer yield self.onStep(inputData,outputData) self.loop() def pause(self): self.paused = True def resume(self): self.paused = False def cancel(self): self.done = True self.input.cancel() self.output.cancel() scanToggleClicked() @inlineCallbacks def finish(self): if self.activeRepeat == self.repeatTotal: self.done = True yield self.input.cancel() self.output.cancel() scanToggleClicked() else: self.activeRepeat += 1 if self.activeRepeat % 2 == 0: self.input.initFlipScan() else: self.input.initScan() self.startScan() # define what to do after values are acquired at a position def onStepped(input,output): # unpack scan step data position, output = input, output if position == None or output == None: return else: # update data array if position not in self.dataMatrix.keys(): self.dataMatrix[position] = [] for value in output: self.dataMatrix[position].append(value) # update plot updatePlot() # define scanning start/pause/cancel logic def scanToggleClicked(): if self.scanning: #currently scanning so check if the scan is done, if not this was a pause if not self.thisScan.done: #pause the scan, pop resume/cancel dialog self.thisScan.pause() else: self.scanning = False scanToggleButton.setText("start") return if not self.scanning: #not currently scanning, so start the scan self.scanning = True #gather the agents (classes with specific methods) that progress scan and measure values inputAgent = inputPane.currentWidget() outputAgent = outputPane.currentWidget() updateAgent = onStepped #dump whatever data is in the matrix, prepare the plot for xVal in self.dataMatrix.keys(): del self.dataMatrix[xVal] # clear the lists that the plot uses to plot self.xVals = [] self.yVals = [] self.errVals = [] updatePlot() self.plotWidget.enableAutoRange() #define the scan, which automatically starts it numToRepeat = self.repeatSpinBox.value() self.thisScan = Scan(inputAgent, outputAgent, updateAgent, numToRepeat, self.plotWidget) #rename our button so users know about the other half of this function scanToggleButton.setText("pause/cancel") return self.scanning = False # set up the GUI to have the scan start/pause/cancel button and repeat spinbox scanPane = QtGui.QHBoxLayout() scanToggleButton = QtGui.QPushButton("start") scanToggleButton.clicked.connect(scanToggleClicked) scanPane.addWidget(scanToggleButton) self.repeatSpinBox = QtGui.QSpinBox() self.repeatSpinBox.setRange(1,10000) self.repeatSpinBox.setValue(1) scanPane.addWidget(self.repeatSpinBox) cpLayout.addWidget(LabelWidget('scan',scanPane)) ############################################################# LOAD FUNCTIONS ########################################################### refLayout = QtGui.QHBoxLayout() def onLoadClicked(): dir, filePrefix = filenameGen() dir = join(POOHDATAPATH,dir) refFileName = QtGui.QFileDialog.getOpenFileName(self,'select file', dir,"CSV Files (*.csv)") rData = np.loadtxt(open(refFileName[0],"rb"),delimiter=",") name = refFileName[0].rpartition('/')[2] color = QtGui.QColorDialog.getColor() if 'matrix' in refFileName[0]: xVals = rData[:,0] yVals = [] errVals = [] for rowNum in range(len(xVals)): thisYList = rData[rowNum,1:] yVals.append(np.mean(thisYList)) errVals.append(np.std(thisYList)/np.sqrt(len(thisYList))) self.refData[name] = { 'color': color, 'data': [xVals, yVals, errVals] } else: self.refData[name] = { 'color': color, 'data': [rData[:,0], rData[:,1], rData[:,2]] } updatePlot() loadButton = QtGui.QPushButton('load') loadButton.clicked.connect(onLoadClicked) refLayout.addWidget(SqueezeRow(loadButton)) def onClearClicked(): for refs in self.refData.keys(): del self.refData[refs] updatePlot() clearButton = QtGui.QPushButton('clear all') clearButton.clicked.connect(onClearClicked) refLayout.addWidget(SqueezeRow(clearButton)) cpLayout.addWidget(LabelWidget('reference',refLayout)) ############################################################# SAVE FUNCTIONS ########################################################### saveLayout = QtGui.QHBoxLayout() def onSaveRawClicked(): dataType = np.dtype(np.float32) orderedDataDict = OrderedDict(sorted(self.dataMatrix.items())) data = np.reshape(np.asarray(orderedDataDict.keys(),dtype=dataType),(len(orderedDataDict.keys()),1)) #just x values as a column yVals = np.asarray(orderedDataDict.values(),dtype=dataType) data = np.hstack((data,yVals)) saveFile(data,'matrix') saveRawButton = QtGui.QPushButton('save (raw)') saveRawButton.clicked.connect(onSaveRawClicked) saveLayout.addWidget(SqueezeRow(saveRawButton)) def onSaveStatsClicked(): xData = self.dataMatrix.keys() yData = [] errData = [] for rawValues in self.dataMatrix.values(): yData.append(np.mean(rawValues)) errData.append(np.std(rawValues)/np.sqrt(len(rawValues))) data = np.asarray([xData, yData, errData], dtype=np.dtype(np.float32)) saveFile(np.transpose(data),'stats') saveStatsButton = QtGui.QPushButton('save (stats)') saveStatsButton.clicked.connect(onSaveStatsClicked) saveLayout.addWidget(SqueezeRow(saveStatsButton)) def saveFile(dataToSave,prefix): dir, filePrefix = filenameGen() dir = join(POOHDATAPATH,dir) checkPath(dir) subDir = QtGui.QFileDialog.getExistingDirectory(self,'select folder', dir) desc, valid = QtGui.QInputDialog.getText(self, 'enter file description','description' ) if not valid: desc = None else: saveCSV(dataToSave, subDir=subDir, description=prefix+'_'+desc) cpLayout.addWidget(LabelWidget('save',saveLayout))
def main(): protocol = yield getProtocol(URL) widget = VoltMeterWidget(protocol) container.append(widget) widget.show() widget.setWindowTitle('voltmeter gui ' + ('debug ' if DEBUG else 'real '))