def dwell(self, c, dwell=None): '''Set/query the dwell trigger. Input: dwell - Time in seconds if internal dwell timer used - Voltage threshold of external advance signal used Returns: (type, parameter) - Type is 'Internal' or 'External' with associated dwell time/threshold ''' if dwell is not None: if dwell.isCompatible('s'): if dwell['s'] < jobs.DWELL_MIN or dwell['s'] > jobs.DWELL_MAX: string = 'Dwell time must be between %f and %f seconds' %\ (jobs.DWELL_MIN, jobs.DWELL_MAX) raise Error(string) else: if dwell['V'] < jobs.DISC_MIN or dwell['V'] > jobs.DISC_MAX: string = 'Dwell trigger threshold must be between %f and %f volts' %\ (jobs.DISC_MIN, jobs.DISC_MAX) raise Error(string) self.params['Dwell'] = (dwell.isCompatible('s'), dwell) isInt, value = self.params['Dwell'] string = 'Internal' if isInt else 'External' return (string, value)
def scan_range(self, c, start=None, startPartial=0, stop=None, stopPartial=0): if start is not None: if stop is None: raise Error('Must provide stop position') elif stop < start or ((start == stop) and (startPartial > stopPartial)): raise Error('Stop position must be after start') self.params['Scan Range'] = ((start, startPartial), (stop, stopPartial)) return self.params['Scan Range']
def scan_range(self, c, start=None, stop=None): ''' Set/query scan channel range. Input: start - Channel to start scan at. Can be integer identifying start channel or a tuple (channel, partial) for partial channel increment. stop - Channel to stop at. Same format as start channel. Returns: [start, stop] - Scan pass bounds as a tuple. Both channels are returned as tuple elements (channel, partial) where partial indicates 8ths of a channel. (ie. partial=5 is 5/8 of a channel) ''' if start is not None: if stop is None: raise Error('Must inclide stop channel.') elif (not isValidCh(start)) or (not isValidCh(stop)): raise InvalidPositionError() if type(start) is not tuple: start = (start, 0) if type(stop) is not tuple: stop = (stop, 0) self.range = (start, stop) return self.range
def position(self, c, channel=None, partial=0, direction=True): '''Get or set the current stepper position. Input: channel - The current channel position partial - Channel fraction (8 steps per channel) direction - Either 'forward' or 'backward' or True/False for forward and backward Returns: Current position and direction as a tuple with direction as a string (channel, partial, direction) ''' if channel is not None: #if we're setting the channel by string, validate and set #boolean value as forward/backward (true/false) if type(direction) is str: d = direction.lower() if d not in DIR_MAP.keys(): raise Error('Direction must be Forward or Backward') dval = d == 'forward' else: dval = direction if not calc.isValidCh((channel, partial)): raise InvalidPosition() self.posn = (channel, partial, dval) c, f, d = self.posn dStr = 'Forward' if d else 'Backward' return (c, f, dStr)
def stop(self, c): running = yield self._isRunning() if not running: raise Error('Scan is not running') p = self.pulser.packet() p.removeListener(self._scanCallback, ID = self.ID) p.stop() yield p.send()
def scan_range(self, c, start=None, end=None): #ensure if there's a scan start there's an end if start is not None: if end is None: raise Error('No scan end position') #store possible new positions and retrieve sPos = self.position(c, start) ePos = self.move_to(c, end) return (sPos, ePos)
def discriminator_level(self, c, level=None): '''Set/query current discriminator voltage''' if level is not None: if level['V'] < jobs.DISC_MIN or level['V'] > jobs.DISC_MAX: string = 'Discriminator level must be between %f and %f'\ % (jobs.DISC_MIN, jobs.DISC_MAX) raise Error(string) self.params['DiscLevel'] = level return self.params['DiscLevel']
def sweeps(self, c, passes=None): '''Set/query the number of scan sweeps. (None queries)''' if passes is not None: if passes < jobs.PASS_MIN or passes > jobs.PASS_MAX: string = 'Pass count must be between %d and %d'\ % (jobs.PASS_MIN, jobs.PASS_MAX) raise Error(string) self.params['Passes'] = passes return self.params['Passes']
def pass_length(self, c, length=None): '''Set/query the number of bins in the scan pass. (None queries)''' if length is not None: if length < jobs.LEN_MIN or length > jobs.LEN_MAX: string = 'Pass length must be between %d and %d' %\ (jobs.LEN_MIN, jobs.LEN_MAX) raise Error(string) self.params['Length'] = length return self.params['Length']
def open(self, c, port=''): """Opens a serial port in the current context. args: port device name as returned by list_serial_ports. On windows, the device name will generally be of the form COM1 or COM42 (i.e., without the device prefix \\\\.\\). On linux, it will be the device node name (ttyUSB0) without the /dev/ prefix. This is case insensitive on windows, case sensitive on Linux. For compatibility, always use the same case. """ c['Timeout'] = 0 if 'PortObject' in c: c['PortObject'].close() del c['PortObject'] if not port: for i in range(len(self.SerialPorts)): try: c['PortObject'] = Serial(self.SerialPorts[i].devicepath, timeout=0) break except SerialException: pass if 'PortObject' not in c: raise NoPortsAvailableError() else: for x in self.SerialPorts: if os.path.normcase(x.name) == os.path.normcase(port): try: c['PortObject'] = Serial(x.devicepath, timeout=0) return x.name except SerialException as e: message = str(e) if message.find('cannot find') >= 0: raise Error(code=1, msg=message) else: raise Error(code=2, msg=message) raise Error(code=1, msg='Unknown port %s' % (port,))
def open(self, c, port=0): """Opens a serial port in the current context.""" c['Timeout'] = 0 if 'PortObject' in c: c['PortObject'].close() del c['PortObject'] if port == 0: for i in range(len(self.SerialPorts)): try: c['PortObject'] = Serial(self.SerialPorts[i], timeout=0) break except SerialException: pass if 'PortObject' not in c: raise NoPortsAvailableError() else: try: c['PortObject'] = Serial(port, timeout=0) except SerialException, e: if e.message.find('cannot find') >= 0: raise Error(code=1, msg=e.message) else: raise Error(code=2, msg=e.message)
def passes(self, c, passes=None): ''' Set/query number of scan passes. Input: passes - Number of sweeps to make over the scan range Returns Number of passes ''' if passes is not None: if passes < 1: raise Error('Invalid pass number') self.passes = passes return self.passes
def dwell_time(self, c, dwell=None): ''' Set/query the dwell time per MCS bin. Input: dwell - Dwell time in seconds per MCS bin. None for query Returns: Current dwell time per bin in seconds. ''' if dwell is not None: if dwell <= MIN_DWELL: raise Error('Dwell time must be at least %f' % MIN_DWELL['s']) self.dwell = dwell return self.dwell
def changeMonitor(self, channel, command, keys=None): settings = BUS_SETTINGS[channel] if keys is None: keys = sorted(settings.keys()) if command is None: returnValue(keys) if command not in settings: raise Error('Allowed commands: {}.'.format(', '.join(keys))) self.rackMonitor.updateBus(channel, self.activeCard, command) change = yield self.sendMonitorPacket(command, settings) returnValue(change)
def startProcessing(self): #self.cumulRawData = np.array() #self.cumulProcData = np.array() try: yield self.readhandle.call('cd', self.inputpath) yield self.readhandle.call('open', self.inputdataset) yield self.writehandle.call('cd', *(self.outputpath, True)) except: raise Error('Dataset not found in provided directory' ) #find a way to get this out to the user #start a timer 24 hours #connect endprocessing if self.followlive: yield self.processRepeatedly() else: yield self.processOnce()
def start(self, c): running = yield self._isRunning() if running: raise Error('A scan is currently in progress') #move stepper into position and wait until complete ch, frac = self.params['Scan Range'][0] yield self.stepper.move_to(ch, frac, True) yield self._waitForStepper() #now prepare for scan pass self.currentPass = 0 yield self._prepPulser() yield self._prepMCS() yield self._scanPass() self.onScanStart(self.params['Passes'])
def channel_ratio(self, c, ratio=None): ''' Set/query current channel ratio. Defines the number of stepper channels per MCS bin. Minimum must be 1/8 or 0.125. Input: ratio - Ratio to set. None if querying. Returns: Current ratio as floating point number ''' if ratio is not None: if ratio < MIN_RATIO: raise Error('Channel ratio must be at least %f' % MIN_RATIO) #round to nearest increment ratio -= (ratio % MIN_RATIO) self.ratio = ratio return self.ratio
def acquisition_mode(self, c, mode = None): '''Set/query acquisition mode. Input None : Query current setting Mode : Set mode to one of 'Rep', 'Sum', 'RepSum' Returns Currently set acquisition mode. ''' if mode is not None: if mode not in ACQ_MODES: opts = ', '.join(ACQ_MODES) string = 'Acquisition mode must be one of %s' % opts raise Error(string) self.params['AcqMode'] = mode return self.params['AcqMode']
def processData(self, c, path, dataset, process, followlive=False, arguments=None): """ Process the data by specifying the path and dataset name in datavault. If followlive is selected, any new updates to the selected dataset will be processed on the flu Arguements let user change the default processing settings """ if process not in self.processingFunctions.availableProcesses(): raise Error('Process not available') readhandle = ContextHandle(self.client, 'data_vault') writehandle = ContextHandle(self.client, 'data_vault') request = Request(path, dataset, process, readhandle, writehandle, followlive, arguments) outputInfo = request.getOutputInfo() reactor.callLater(0, request.startProcessing) return outputInfo
def mode(self, ch, mode=None, modeParameter=None): if mode is not None: if mode not in MODE_TYPES.keys(): raise Error('Mode type invalid.') tag = ':MODE' if ch == 0 else ':CMODE' modeVal = yield self._param(tag, mode, 'mode', ch) m = modeVal if mode is None else mode if m == 'Burst': param = yield self._param(':BCO', modeParameter, 'int', ch) elif m == 'DutyCycle': inP = (None, None) if modeParameter is None else modeParameter pco = yield self._param(':PCO', inP[0], 'int', ch) nco = yield self._param(':OCO', inP[1], 'int', ch) param = (pco, nco) else: param = 0 if mode is None: returnValue((modeVal, param))
def input_impedance(self, c, imped=None): '''Set/query input signal impedance None : Query current setting True : Input at 50 Ohm impedance False : Input at 1 kOhm impedance Value can also be actual impedance value Returns : Impedance value ''' if imped is not None: if type(imped) is bool: val = imped else: if imped['Ohm'] not in [50, 1000]: raise Error('Impedance must be 50, 1000 Ohms or boolean') else: val = imped['Ohm'] == 50 self.params['Impedance'] = val return U.Value(50 if self.params['Impedance'] else 1000, 'Ohm')
def discriminator_edge(self, c, rising=None): '''Set/query input channel discriminator edge. None queries input. Can be set with edge type 'Rising' or 'Falling' or by True/False for rising/falling edge. Returns the edge type as text ''' if rising is not None: if type(rising) is str: rStr = rising.lower() if rStr not in ['rising', 'falling']: rvals = ', '.join(['Rising', 'Falling']) raise Error('Edge must be one of %s' % rvals) else: rVal = rStr == 'rising' else: rVal = rising self.params['DiscEdge'] = rVal return 'Rising' if self.params['DiscEdge'] else 'Falling'
class SerialServer(LabradServer): """Provides access to a computer's serial (COM) ports.""" name = '%LABRADNODE% Serial Server' def initServer(self): if sys.platform.startswith('win32'): self.enumerate_serial_windows() else: self.enumerate_serial_pyserial() def enumerate_serial_windows(self): """Manually Enumerate the first 20 COM ports. pyserial includes a function to enumerate device names, but it possibly doesn't work right on windows for COM ports above 4. http://stackoverflow.com/questions/12090503/listing-available-com-ports-with-python """ self.SerialPorts = [] print 'Searching for COM ports:' for a in range(1, 20): COMexists = True dev_name = 'COM{}'.format(a) dev_path = r'\\.\{}'.format(dev_name) try: ser = Serial(dev_name) ser.close() except SerialException as e: if e.message.find('cannot find') >= 0: COMexists = False if COMexists: self.SerialPorts.append(SerialDevice(dev_name, dev_path)) print " ", dev_name if not len(self.SerialPorts): print ' none' def enumerate_serial_pyserial(self): """This uses the pyserial built-in device enumeration. We ignore the pyserial "human readable" device name because that appears to make no sense. For instance, a particular FTDI USB-Serial adapter shows up as 'Microsoft Corp. Optical Mouse 200'. Following the example from the above windows version, we try to open each port and ignore it if we can't. """ dev_list = serial.tools.list_ports.comports() self.SerialPorts = [] for d in dev_list: dev_path = d[0] try: ser = Serial(dev_path) ser.close() except SerialException as e: pass else: _, _, dev_name = dev_path.rpartition(os.sep) self.SerialPorts.append(SerialDevice(dev_name, dev_path)) def expireContext(self, c): if 'PortObject' in c: c['PortObject'].close() def getPort(self, c): try: return c['PortObject'] except: raise NoPortSelectedError() @setting(1, 'List Serial Ports', returns=['*s: List of serial ports']) def list_serial_ports(self, c): """Retrieves a list of all serial ports. NOTES: This list contains all ports installed on the computer, including ones that are already in use by other programs.""" print self.SerialPorts port_list = [x.name for x in self.SerialPorts] return port_list @setting( 10, 'Open', port=[': Open the first available port', 's: Port to open, e.g. COM4'], returns=['s: Opened port']) def open(self, c, port=''): """Opens a serial port in the current context. args: port device name as returned by list_serial_ports. On windows, the device name will generally be of the form COM1 or COM42 (i.e., without the device prefix \\\\.\\). On linux, it will be the device node name (ttyUSB0) without the /dev/ prefix. This is case insensitive on windows, case sensitive on Linux. For compatibility, always use the same case. """ c['Timeout'] = 0 if 'PortObject' in c: c['PortObject'].close() del c['PortObject'] if not port: for i in range(len(self.SerialPorts)): try: c['PortObject'] = Serial(self.SerialPorts[i].devicepath, timeout=0) break except SerialException: pass if 'PortObject' not in c: raise NoPortsAvailableError() else: for x in self.SerialPorts: if os.path.normcase(x.name) == os.path.normcase(port): try: c['PortObject'] = Serial(x.devicepath, timeout=0) return x.name except SerialException, e: if e.message.find('cannot find') >= 0: raise Error(code=1, msg=e.message) else: raise Error(code=2, msg=e.message) raise Error(code=1, msg='Unknown port %s' % (port, ))
def optionalInputs(self, c, process): """Returns a list of tuples of available inputs with the default values for a given process""" if process not in self.processingFunctions.availableProcesses(): raise Error('Process not available') return self.processingFunctions.availableInputs(process)