class LoggedStepperMotor(CounterStepperMotor): def __init__(self, counter_channel, direction_channel, log_file=None, enable_channel=None, backlash=0, tasks=None): import os.path if log_file is None: logName = str(counter_channel).replace('/', '-') + '.txt' else: logName = log_file self.logName = os.path.join(SMLOGSPATH, logName) self._openLog() try: last_date, last_position, last_direction = self._getLastPosition() except TypeError: print 'error with log file! reverting to 0 & forwards' last_date, last_position, last_direction = ('never', 0, 'FORWARDS') last_direction = { 'FORWARDS': DigitalLineStepperMotor.FORWARDS, 'BACKWARDS': DigitalLineStepperMotor.BACKWARDS }[last_direction] CounterStepperMotor.__init__(self, counter_channel, direction_channel, enable_channel=enable_channel, initial_position=int(last_position), backlash=backlash, direction=last_direction, tasks=tasks) def _openLog(self): self.log_file = LogFile(self.logName) def _closeLog(self): self.log_file.close() def toggleStatus(self): if self._getEnableStatus() == self.ENABLED: self.updateLog() self._closeLog() self.disable() elif self._getEnableStatus() == self.DISABLED: self._openLog() self.enable() def _getLastPosition(self): return self.log_file.readLastLine() def updateLog(self): currPos = self.getPosition() currDir = self.getDirection() self.log_file.update((currPos, currDir)) def destroy(self): self._closeLog() EnabledStepperMotor.destroy(self)
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 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 onRecordStartRequested(): # build a list of selected channels, record only those, set text color to red for channel in channels: tile = tiles[channel] if tile.checkState() is QtCore.Qt.CheckState.Checked: recording.append(channel) tile.setForeground( QtGui.QBrush( QtGui.QColor('red') ) ) # initialize logfile in today's folder / voltmeter / start time relPath, fileName = filenameGen(self.MEASUREMENT_TYPE) absPath = os.path.join(POOHDATAPATH,relPath) checkPath(absPath) logName = os.path.join(absPath,fileName+'.txt') self.LogFile = LogFile(logName) headerLine = [] for channel in recording: headerLine.append(tiles[channel].text().replace('\t','_')) self.LogFile.update(headerLine) recordToggle.toggle()
def _openLog(self): self.log_file = LogFile(self.logName)
class LoggedStepperMotor(CounterStepperMotor): def __init__( self, counter_channel, direction_channel, log_file=None, enable_channel=None, backlash=0, tasks=None ): import os.path if log_file is None: logName = str(counter_channel).replace('/','-')+'.txt' else: logName = log_file self.logName = os.path.join(SMLOGSPATH,logName) self._openLog() try: last_date, last_position, last_direction = self._getLastPosition() except TypeError: print 'error with log file! reverting to 0 & forwards' last_date, last_position, last_direction = ('never',0,'FORWARDS') last_direction = {'FORWARDS':DigitalLineStepperMotor.FORWARDS,'BACKWARDS':DigitalLineStepperMotor.BACKWARDS}[last_direction] CounterStepperMotor.__init__( self, counter_channel, direction_channel, enable_channel=enable_channel, initial_position=int(last_position), backlash=backlash, direction=last_direction, tasks=tasks ) def _openLog(self): self.log_file = LogFile(self.logName) def _closeLog(self): self.log_file.close() def toggleStatus(self): if self._getEnableStatus() == self.ENABLED: self.updateLog() self._closeLog() self.disable() elif self._getEnableStatus() == self.DISABLED: self._openLog() self.enable() def _getLastPosition(self): return self.log_file.readLastLine() def updateLog(self): currPos = self.getPosition() currDir = self.getDirection() self.log_file.update((currPos,currDir)) def destroy(self): self._closeLog() EnabledStepperMotor.destroy(self)
class VoltMeterWidget(QtGui.QWidget): ID_ROLE = 999 HISTORY = 200 MEASUREMENT_TYPE = 'voltmeter' newBufferVal = False @staticmethod def vrngk2v(k): vrngKeys, vrngVals = zip(*VM.VOLTAGE_RANGES) return vrngVals[vrngKeys.index(k)] def __init__(self,protocol): @inlineCallbacks def init(): # to change displayed values of channel tiles @inlineCallbacks def setText(channel): description = yield protocol.sendCommand( 'get-channel-parameter', channel, VM.DESCRIPTION ) voltageRange = yield protocol.sendCommand( 'get-channel-parameter', channel, VM.VOLTAGE_RANGE ) voltageRange = self.vrngk2v(voltageRange) decimalPlaces = int(-1*log10(voltageRange)) + 1 formatString = '%.' + str(decimalPlaces if decimalPlaces > 0 else 0) + 'f' tiles[channel].setText( '%s\t%s\t%s V' % ( description, channel, ( formatString ) % voltageRange ) ) # to bring up channel edit dialogue def rightClicked(listWidget,p): item = listWidget.itemAt(p) if item is None: return channel = item.data(self.ID_ROLE) editDialog = ChannelEditDialog(protocol,channel,colors[channel],self) editDialog.colorChanged.connect(partial(colorChanged,channel)) editDialog.show() # to update a channel's color def colorChanged(channel,color): colors[channel] = color tiles[channel].setBackground(color) plots[channel].setPen( pg.mkPen( color, width=2 ) ) # the main execution loop @inlineCallbacks def loop(): # get latest values voltages = yield protocol.sendCommand('get-voltages') for channel, voltage in voltages.items(): # extend the size of arrays if user asks for more values to be stored if self.newBufferVal == True: onBufferUpdate() # populate arrays from historical values xData, yData = data[channel] # pop oldest voltage yData = np.delete(yData,0) #scale = yield protocol.sendCommand( # 'get-channel-parameter', # channel, # VM.VOLTAGE_RANGE #) #scale = self.vrngk2v(scale) # add newest voltage yData = np.append(yData,np.asarray(voltage)) # plot all voltages in range plots[channel].setData( xData, yData ) # set the historical values to these values data[channel] = (xData, yData) # log values, if requested if recordToggle.isToggled(): nextLine = [] for channel in recording: nextLine.append(voltages[channel]) self.LogFile.update(nextLine) # update selected list for channel in channels: tile = tiles[channel] if tile.checkState() is QtCore.Qt.CheckState.Checked: if channel not in checked: checked.append(channel) plotWidget.addItem( plots[channel] ) elif channel in checked: checked.remove(channel) plotWidget.removeItem( plots[channel] ) # wait for server's callback rate (nom. 10Hz), iterate callbackRate = yield protocol.sendCommand('get-callback-rate') yield sleep(1.0 / callbackRate) loop() # define overall layout: graph to left of control panel QtGui.QWidget.__init__(self) self.setLayout(QtGui.QHBoxLayout()) # define plot plotWidget = pg.PlotWidget() self.layout().addWidget(plotWidget,1) # define controls panel controlsLayout = QtGui.QVBoxLayout() self.layout().addLayout(controlsLayout) # define the list for variable tiles to go onto listWidget = QtGui.QListWidget() listWidget.setDragDropMode(QtGui.QAbstractItemView.InternalMove) listWidget.setContextMenuPolicy(QtCore.Qt.ContextMenuPolicy.CustomContextMenu) listWidget.customContextMenuRequested.connect( partial( rightClicked, listWidget ) ) controlsLayout.addWidget(listWidget) # iterate through channels on server and populate dictionaries for data, colors, and plots channels = yield protocol.sendCommand('get-channels') channels = sorted(channels,key = lambda channel: int(re.search('\d+$',channel).group())) data = {} colors = {} plots = {} tiles = {} for index, channel in enumerate(channels): data[channel] = (np.arange(self.HISTORY), np.zeros(self.HISTORY)) colors[channel] = QtGui.QColor.fromHsv( int(255*float(index)/len(channels)), 255, 255 ) plots[channel] = pg.PlotDataItem( data[channel][0], data[channel][1], name=channel, pen=pg.mkPen(colors[channel], width=2) ) description = yield protocol.sendCommand( 'get-channel-parameter', channel, VM.DESCRIPTION ) listWidgetTile = QtGui.QListWidgetItem() listWidgetTile.setData(self.ID_ROLE,channel) listWidgetTile.setBackground(QtGui.QBrush(colors[channel])) listWidgetTile.setCheckState(QtCore.Qt.CheckState.Unchecked) listWidget.addItem(listWidgetTile) tiles[channel] = listWidgetTile setText(channel) # when a channel is updated, update its associated tile def onChannelParameterChanged(channel,parameter,value): setText(channel) protocol.messageSubscribe( 'channel-parameter-changed', partial( apply, onChannelParameterChanged ) ) # set up buffer function and spinbox def onBufferUpdate(): oldBufferSize = data[channels[0]][0].size newBufferSize = bufferSpin.value() change = newBufferSize - oldBufferSize if change > 0: backendToAdd = np.zeros(change) for index, channel in enumerate(channels): data[channel] = ( np.arange(newBufferSize), np.hstack((backendToAdd,data[channel][1])) ) if change < 0: for index, channel in enumerate(channels): data[channel] = ( np.arange(newBufferSize), np.delete(data[channel][1],np.arange(abs(change))) ) self.newBufferVal = False def newBufferToggle(): self.newBufferVal = True bufferSpin = QtGui.QSpinBox() bufferSpin.setRange(1,100000) bufferSpin.setValue(self.HISTORY) controlsLayout.addWidget(LabelWidget('buffer',bufferSpin)) bufferSpin.editingFinished.connect(newBufferToggle) # set up recording functions and buttons checked = [] recording = [] recordToggle = ToggleObject() def onRecordStartRequested(): # build a list of selected channels, record only those, set text color to red for channel in channels: tile = tiles[channel] if tile.checkState() is QtCore.Qt.CheckState.Checked: recording.append(channel) tile.setForeground( QtGui.QBrush( QtGui.QColor('red') ) ) # initialize logfile in today's folder / voltmeter / start time relPath, fileName = filenameGen(self.MEASUREMENT_TYPE) absPath = os.path.join(POOHDATAPATH,relPath) checkPath(absPath) logName = os.path.join(absPath,fileName+'.txt') self.LogFile = LogFile(logName) headerLine = [] for channel in recording: headerLine.append(tiles[channel].text().replace('\t','_')) self.LogFile.update(headerLine) recordToggle.toggle() recordToggle.activationRequested.connect(onRecordStartRequested) def onRecordStopRequested(): while recording: tiles[recording.pop()].setForeground( QtGui.QBrush( QtGui.QColor('black') ) ) recordToggle.toggle() self.LogFile.close() recordToggle.deactivationRequested.connect(onRecordStopRequested) # add record & stop buttons to layout controlsLayout.addWidget(ToggleWidget(recordToggle,('record','stop'))) loop() init() def closeEvent(self, event): event.accept() quit()