def generate_code(self, hdf5_file): IntermediateDevice.generate_code(self, hdf5_file) group = self.init_device_group(hdf5_file) clockline = self.parent_device pseudoclock = clockline.parent_device times = pseudoclock.times[clockline] # out_table = np.empty((len(times),len(self.child_devices)), dtype=np.float32) # determine dtypes dtypes = [] for device in self.child_devices: if isinstance(device, DigitalOut): device_dtype = np.int8 elif isinstance(device, AnalogOut): device_dtype = np.float64 dtypes.append((device.name, device_dtype)) # create dataset out_table = np.zeros(len(times), dtype=dtypes) for device in self.child_devices: out_table[device.name][:] = device.raw_output group.create_dataset('OUTPUTS', compression=config.compression, data=out_table)
def __init__(self, name, parent_device, addr=None, port=7802, **kwargs): IntermediateDevice.__init__(self, name, parent_device, **kwargs) # # Get a device objsect # dev = MOGDevice(addr, port) # # print 'Device info:', dev.ask('info') self.BLACS_connection = '%s,%s'%(addr, str(port))
def __init__(self, name, parent_device, server='192.168.1.100', port=21845): IntermediateDevice.__init__(self, name, parent_device) self.BLACS_connection = '%s:%d' % (server, port)
def __init__(self, name, parent_device, addr=None, port=7802, **kwargs): IntermediateDevice.__init__(self, name, parent_device, **kwargs) # # Get a device objsect # dev = MOGDevice(addr, port) # # print 'Device info:', dev.ask('info') self.BLACS_connection = '%s,%s' % (addr, str(port))
def __init__(self, name, parent, BLACS_connection='dummy_connection', **kwargs): self.BLACS_connection = BLACS_connection IntermediateDevice.__init__(self, name, parent, **kwargs)
def add_device(self, device): if isinstance(device, WaitMonitor): IntermediateDevice.add_device(self, device) else: raise LabscriptError( 'You can only connect an instance of WaitMonitor to the device %s.internal_wait_monitor_outputs' % (self.pseudoclock_device.name))
def __init__(self, name, parent_device, com_port="", baud_rate=115200, default_baud_rate=None, update_mode='synchronous', synchronous_first_line_repeat=False, phase_mode='continuous', **kwargs): IntermediateDevice.__init__(self, name, parent_device, **kwargs) self.BLACS_connection = '%s,%s' % (com_port, str(baud_rate)) if not update_mode in ['synchronous', 'asynchronous']: raise LabscriptError( 'update_mode must be \'synchronous\' or \'asynchronous\'') if not baud_rate in bauds: raise LabscriptError('baud_rate must be one of {0}'.format( list(bauds))) if not default_baud_rate in bauds and default_baud_rate is not None: raise LabscriptError( 'default_baud_rate must be one of {0} or None (to indicate no default)' .format(list(bauds))) if not phase_mode in ['aligned', 'continuous']: raise LabscriptError( 'phase_mode must be \'aligned\' or \'continuous\'') self.update_mode = update_mode self.phase_mode = phase_mode self.synchronous_first_line_repeat = synchronous_first_line_repeat
def generate_code(self, hdf5_file): IntermediateDevice.generate_code(self, hdf5_file) analogs = {} digitals = {} inputs = {} for device in self.child_devices: if isinstance(device,AnalogOut): analogs[device.connection] = device elif isinstance(device,DigitalOut): digitals[device.connection] = device elif isinstance(device,AnalogIn): inputs[device.connection] = device else: raise Exception('Got unexpected device.') analog_out_table = np.empty((len(self.parent_device.times[self.clock_type]),len(analogs)), dtype=np.float32) analog_connections = analogs.keys() analog_connections.sort() analog_out_attrs = [] for i, connection in enumerate(analog_connections): output = analogs[connection] if any(output.raw_output > 10 ) or any(output.raw_output < -10 ): # Bounds checking: raise LabscriptError('%s %s '%(output.description, output.name) + 'can only have values between -10 and 10 Volts, ' + 'the limit imposed by %s.'%self.name) analog_out_table[:,i] = output.raw_output analog_out_attrs.append(self.MAX_name +'/'+connection) input_connections = inputs.keys() input_connections.sort() input_attrs = [] acquisitions = [] for connection in input_connections: input_attrs.append(self.MAX_name+'/'+connection) for acq in inputs[connection].acquisitions: acquisitions.append((connection,acq['label'],acq['start_time'],acq['end_time'],acq['wait_label'],acq['scale_factor'],acq['units'])) # The 'a256' dtype below limits the string fields to 256 # characters. Can't imagine this would be an issue, but to not # specify the string length (using dtype=str) causes the strings # to all come out empty. acquisitions_table_dtypes = [('connection','a256'), ('label','a256'), ('start',float), ('stop',float), ('wait label','a256'),('scale factor',float), ('units','a256')] acquisition_table= np.empty(len(acquisitions), dtype=acquisitions_table_dtypes) for i, acq in enumerate(acquisitions): acquisition_table[i] = acq digital_out_table = [] if digitals: digital_out_table = self.convert_bools_to_bytes(digitals.values()) grp = hdf5_file.create_group('/devices/'+self.name) if all(analog_out_table.shape): # Both dimensions must be nonzero analog_dataset = grp.create_dataset('ANALOG_OUTS',compression=config.compression,data=analog_out_table) grp.attrs['analog_out_channels'] = ', '.join(analog_out_attrs) if len(digital_out_table): # Table must be non empty digital_dataset = grp.create_dataset('DIGITAL_OUTS',compression=config.compression,data=digital_out_table) grp.attrs['digital_lines'] = '/'.join((self.MAX_name,'port0','line0:%d'%(self.n_digitals-1))) if len(acquisition_table): # Table must be non empty input_dataset = grp.create_dataset('ACQUISITIONS',compression=config.compression,data=acquisition_table) grp.attrs['analog_in_channels'] = ', '.join(input_attrs) grp.attrs['acquisition_rate'] = self.acquisition_rate grp.attrs['clock_terminal'] = self.clock_terminal
def __init__(self, name, parent_device, com_port): IntermediateDevice.__init__(self, name, parent_device) self.BLACS_connection = com_port p=64 b=1080 a=62 r=805 self._scale = (p*b + a)/r
def add_device(self, device): if isinstance(device, DigitalOut): IntermediateDevice.add_device(self, device) else: raise LabscriptError( f'You have connected {device.name} to {self.name} (the IntermediateDevice ' + f'embedded in {self.parent_device.parent_device.name}), but {self.name} only ' + f'supports DigitalOut children.')
def generate_code(self, hdf5_file): """Generates the hardware code from the script and saves it to the shot h5 file. This is called automatically when a shot is compiled. Args: hdf5_file (str): Path to shot's hdf5 file to save the instructions to. """ IntermediateDevice.generate_code(self, hdf5_file) analogs = {} digitals = {} inputs = {} for device in self.child_devices: if isinstance(device, (AnalogOut, StaticAnalogOut)): analogs[device.connection] = device elif isinstance(device, (DigitalOut, StaticDigitalOut)): digitals[device.connection] = device elif isinstance(device, AnalogIn): inputs[device.connection] = device else: raise TypeError(device) clockline = self.parent_device if clockline is None: # No pseudoclock to call expand_timeseries() on our children. # Call it ourselves: for device in self.child_devices: if isinstance(device, (StaticDigitalOut, StaticAnalogOut)): device.expand_timeseries() times = None else: times = clockline.parent_device.times[clockline] self._check_even_children(analogs, digitals) self._check_bounds(analogs) AO_table = self._make_analog_out_table(analogs, times) DO_table = self._make_digital_out_table(digitals, times) AI_table = self._make_analog_input_table(inputs) self._check_AI_not_too_fast(AI_table) self._check_wait_monitor_timeout_device_config() grp = self.init_device_group(hdf5_file) if AO_table is not None: grp.create_dataset('AO', data=AO_table, compression=config.compression) if DO_table is not None: grp.create_dataset('DO', data=DO_table, compression=config.compression) if AI_table is not None: grp.create_dataset('AI', data=AI_table, compression=config.compression)
def generate_code(self, hdf5_file): IntermediateDevice.generate_code(self, hdf5_file) stages = {stage.connection: stage for stage in self.child_devices} connections = sorted(stages, key=get_device_number) dtypes = [(connection, int) for connection in connections] static_value_table = np.empty(1, dtype=dtypes) for connection, stage in stages.items(): static_value_table[connection][0] = stage.static_value grp = self.init_device_group(hdf5_file) grp.create_dataset('static_values', data=static_value_table)
def __init__(self, name, parent_device, clock_terminal, MAX_name=None, acquisition_rate=0): IntermediateDevice.__init__(self, name, parent_device) self.acquisition_rate = acquisition_rate self.clock_terminal = clock_terminal self.MAX_name = name if MAX_name is None else MAX_name self.BLACS_connection = self.MAX_name
def generate_code(self, hdf5_file): IntermediateDevice.generate_code(self, hdf5_file) if len(self.child_devices) != 3: raise LabscriptError( "Wrong number of child_devices. This device expects exactly 3 children" ) grp = hdf5_file.create_group('/devices/' + self.name) profile_dtypes = [ ('freq', np.float), ('phase', np.float), ('amp', np.float), ('ext_in', bool), #EE ('freq_dev', np.float) ] #EE profile_table = np.zeros(1, dtype=profile_dtypes) profile_table['freq'] = self.RFSettings['freq'] profile_table['amp'] = self.RFSettings['amp'] profile_table['phase'] = self.RFSettings['phase'] profile_table['ext_in'] = 0 ##EE profile_table['freq_dev'] = 0 #EE ## Emily edit if self.ext_in: profile_table['ext_in'] = 1 profile_table['freq_dev'] = self.RFSettings['freq_dev'] grp.create_dataset('RF_DATA', compression=config.compression, data=profile_table) if self.sweep: sweep_dtypes = [('sweep_low', np.float), ('sweep_high', np.float), ('sweep_duration', np.float), ('sweep_samplerate', np.float)] sweep_table = np.empty(1, dtype=sweep_dtypes) # sweep_table['sweep_type'] = sweep_types[output.sweep_params['type']] sweep_table['sweep_low'] = self.sweep_params['low'] sweep_table['sweep_high'] = self.sweep_params['high'] sweep_table['sweep_duration'] = self.sweep_params['duration'] # sweep_table['sweep_falltime'] = output.sweep_params['falltime'] sweep_table['sweep_samplerate'] = self.sweep_params['sample_rate'] grp.create_dataset('SWEEP_DATA', compression=config.compression, data=sweep_table)
def __init__(self, name, parent_device, clock_terminal=None, MAX_name=None, sample_rate_AI=0, **kwargs): IntermediateDevice.__init__(self, name, parent_device, **kwargs) self.sample_rate_AI = sample_rate_AI self.clock_terminal = clock_terminal self.MAX_name = name if MAX_name is None else MAX_name self.BLACS_connection = self.MAX_name # Now these are just defined at __init__ time self.num_AO = 4 self.num_DO = 32 self.dtype_DO = np.uint32 self.clock_limit = 500e3
def __init__( self, name, parent_device, clock_terminal, BoardNum=0, sync="slave", ): IntermediateDevice.__init__(self, name, parent_device) self.name = name self.clock_terminal = clock_terminal self.BLACS_connection = self.name self.sync = sync self.BoardNum = BoardNum
def __init__(self,name,parent_device,com_port='COM1',FMSignal=None,RFOnOff=None,freq_limits = None,freq_conv_class = None,freq_conv_params = {},amp_limits=None,amp_conv_class = None,amp_conv_params = {},phase_limits=None,phase_conv_class = None,phase_conv_params = {}): #self.clock_type = parent_device.clock_type # Don't see that this is needed anymore IntermediateDevice.__init__(self,name,parent_device) self.BLACS_connection = com_port self.sweep_dt = 2e-6 self.RFSettings = { 'freq': 0, 'amp': 0, 'phase': 0, 'freq_dev':0 ##EE } self.sweep_params = { # 'type': None, 'low': 0, 'high': 1, 'duration': 0, # 'falltime': 0, 'sample_rate': self.sweep_dt } self.sweep = False self.ext_in = False self.frequency = StaticAnalogQuantity(self.name+'_freq',self,'freq',freq_limits,freq_conv_class,freq_conv_params) self.amplitude = StaticAnalogQuantity(self.name+'_amp',self,'amp',amp_limits,amp_conv_class,amp_conv_params) self.phase = StaticAnalogQuantity(self.name+'_phase',self,'phase',phase_limits,phase_conv_class,phase_conv_params) self.FMSignal = {} self.RFOnOff = {} if FMSignal: if 'device' in FMSignal and 'connection' in FMSignal: self.FMSignal = AnalogOut(self.name+'_FMSignal', FMSignal['device'], FMSignal['connection']) else: raise LabscriptError('You must specify the "device" and "connection" for the analog output FMSignal of '+self.name) else: raise LabscriptError('Expected analog output for "FMSignal" control') if RFOnOff: if 'device' in RFOnOff and 'connection' in RFOnOff: self.RFOnOff = DigitalOut(self.name+'_RFOnOff', RFOnOff['device'], RFOnOff['connection']) else: raise LabscriptError('You must specify the "device" and "connection" for the digital output RFOnOff of '+self.name) else: raise LabscriptError('Expected digital output for "RFOnOff" control')
def add_device(self, device): try: prefix, number = device.connection.split() assert int(number) in range(2) assert prefix == 'dds' except Exception: raise LabscriptError('invalid connection string. Please use the format \'dds n\' with n 0 or 1') if isinstance(device, DDS): # Check that the user has not specified another digital line as the gate for this DDS, that doesn't make sense. if device.gate is not None: raise LabscriptError('You cannot specify a digital gate ' + 'for a DDS connected to %s. '% (self.name)) IntermediateDevice.add_device(self, device)
def __init__(self, name, parent_device, com_port="", baud_rate=115200, update_mode='synchronous', **kwargs): IntermediateDevice.__init__(self, name, parent_device, **kwargs) self.BLACS_connection = '%s,%s' % (com_port, str(baud_rate)) if not update_mode in ['synchronous', 'asynchronous']: raise LabscriptError( 'update_mode must be \'synchronous\' or \'asynchronous\'') self.update_mode = update_mode
def generate_code(self, hdf5_file): IntermediateDevice.generate_code(self, hdf5_file) analogs = {} digitals = {} inputs = {} for device in self.child_devices: if isinstance(device, (AnalogOut, StaticAnalogOut)): analogs[device.connection] = device elif isinstance(device, (DigitalOut, StaticDigitalOut)): digitals[device.connection] = device elif isinstance(device, AnalogIn): inputs[device.connection] = device else: raise TypeError(device) clockline = self.parent_device if clockline is None: # No pseudoclock to call expand_timeseries() on our children. # Call it ourselves: for device in self.child_devices: if isinstance(device, (StaticDigitalOut, StaticAnalogOut)): device.expand_timeseries() times = None else: times = clockline.parent_device.times[clockline] self._check_even_children(analogs, digitals) self._check_bounds(analogs) AO_table = self._make_analog_out_table(analogs, times) DO_table = self._make_digital_out_table(digitals, times) AI_table = self._make_analog_input_table(inputs) self._check_AI_not_too_fast(AI_table) grp = self.init_device_group(hdf5_file) if AO_table is not None: grp.create_dataset('AO', data=AO_table, compression=config.compression) if DO_table is not None: grp.create_dataset('DO', data=DO_table, compression=config.compression) if AI_table is not None: grp.create_dataset('AI', data=AI_table, compression=config.compression)
def __init__(self, name, parent_device, com_port = "", baud_rate=115200, update_mode='synchronous', synchronous_first_line_repeat=False, phase_mode='default', **kwargs): IntermediateDevice.__init__(self, name, parent_device, **kwargs) self.BLACS_connection = '%s,%s'%(com_port, str(baud_rate)) if not update_mode in ['synchronous', 'asynchronous']: raise LabscriptError('update_mode must be \'synchronous\' or \'asynchronous\'') if not phase_mode in ['default', 'aligned', 'continuous']: raise LabscriptError('phase_mode must be \'default\', \'aligned\' or \'continuous\'') self.update_mode = update_mode self.phase_mode = phase_mode self.synchronous_first_line_repeat = synchronous_first_line_repeat
def __init__(self, name, parent_device, com_port = "", baud_rate=115200, default_baud_rate=0, update_mode='synchronous', synchronous_first_line_repeat=False, **kwargs): IntermediateDevice.__init__(self, name, parent_device, **kwargs) self.BLACS_connection = '%s,%s'%(com_port, str(baud_rate)) if not update_mode in ['synchronous', 'asynchronous']: raise LabscriptError('update_mode must be \'synchronous\' or \'asynchronous\'') if not baud_rate in bauds: raise LabscriptError('baud_rate must be one of {0}'.format(bauds.keys())) if not default_baud_rate in bauds and default_baud_rate != 0: raise LabscriptError('default_baud_rate must be one of {0} or 0 (to indicate no default)'.format(bauds.keys())) self.update_mode = update_mode self.synchronous_first_line_repeat = synchronous_first_line_repeat
def __init__(self, name, parent_device, com_port="", baud_rate=19200, update_mode='synchronous', synchronous_first_line_repeat=False, phase_mode='continuous', ext_clk=False, clk_freq=None, clk_mult=None, R_option=False, **kwargs): '''Labscript device class for NovaTech 409B-AC variant DDS. This device has two dynamic channels (0,1) and two static channels (2,3). If an external clock frequency is enabled, and /R option is not being used, clk_freq (in MHz) and clk_mult (int) must also be defined.''' IntermediateDevice.__init__(self, name, parent_device, **kwargs) self.BLACS_connection = '%s,%s' % (com_port, str(baud_rate)) if not update_mode in ['synchronous', 'asynchronous']: raise LabscriptError( 'update_mode must be \'synchronous\' or \'asynchronous\'') if not phase_mode in ['aligned', 'continuous']: raise LabscriptError( 'phase_mode must be \'aligned\' or \'continuous\'') self.update_mode = update_mode self.phase_mode = phase_mode self.synchronous_first_line_repeat = synchronous_first_line_repeat self.ext_clk = ext_clk self.clk_freq = clk_freq self.R_option = R_option self.clk_mult = clk_mult # validate clocking parameters and get frequency scaling factor self.clk_scale = self.clock_check() # save dds reference frequency, defined as clk_freq*clk_mult self.set_property('reference_frequency', self.ref_freq, location='device_properties')
def __init__(self, name, parent_device, visa_resource="ASRL4::INSTR", **kwargs): IntermediateDevice.__init__(self, name, parent_device, **kwargs) self.BLACS_connection = visa_resource self.wireamps = [] #wireamps is a list of AnalogQuantity objects? for i in range(self.NUM_WIRES): self.wireamps.append(AnalogQuantity("%s_wire%02damp" % (self.name, i), self, 'wire%02damp' % i)) self.groupphases = [] for i in range(self.NUM_WIRE_GROUPS): self.groupphases.append(AnalogQuantity("%s_group%02dphase" % (self.name, i), self, 'group%02dphase' % i)) self.groupfreqs = [] for i in range(self.NUM_WIRE_GROUPS): self.groupfreqs.append(AnalogQuantity("%s_group%02dfreq" % (self.name, i), self, 'group%02dfreq' % i, unit_conversion_class=NovaTechDDS9mFreqConversion)) self.control_bytes = {} self.visa_resource = visa_resource
def __init__(self, name, com_port="COM1", mock=False, **kwargs): """Device for controlling a number of Zaber stages connected to a serial port. Add stages as child devices, either by using one of them model-specific classes in this module, or the generic `ZaberStage` class. Args: name (str) device name com_port (str), default: `'COM1'` Serial port for communication, i.e. `'COM1' etc on Windows or `'/dev/USBtty0'` or similar on unix. mock (bool, optional), default: False For testing purpses, simulate a device instead of communicating with actual hardware. **kwargs: Further keyword arguments to be passed to the `__init__` method of the parent class (IntermediateDevice). """ IntermediateDevice.__init__(self, name, None, **kwargs) self.BLACS_connection = com_port
def __init__(self, name, parent_device=None, clock_terminal=None, MAX_name=None, static_AO=None, static_DO=None, clock_mirror_terminal=None, acquisition_rate=None, AI_range=None, AI_start_delay=0, AO_range=None, max_AI_multi_chan_rate=None, max_AI_single_chan_rate=None, max_AO_sample_rate=None, max_DO_sample_rate=None, min_semiperiod_measurement=None, num_AI=0, num_AO=0, num_CI=0, ports=None, supports_buffered_AO=False, supports_buffered_DO=False, supports_semiperiod_measurement=False, **kwargs): """Generic class for NI_DAQmx devices.""" # Default static output setting based on whether the device supports buffered # output: if static_AO is None: static_AO = not supports_buffered_AO if static_DO is None: static_DO = not supports_buffered_DO # Parent is only allowed to be None if output is static: if parent_device is None and not (static_DO and static_AO): msg = """Must specify a parent clockline, unless both static_AO and static_DO are True""" raise LabscriptError(dedent(msg)) # If parent device is not None though, then clock terminal must be specified: if parent_device is not None and clock_terminal is None: msg = """If parent_device is given, then clock_terminal must be specified as well as the terminal to which the parent pseudoclock is connected.""" raise ValueError(dedent(msg)) if acquisition_rate is not None and num_AI == 0: msg = "Cannot set set acquisition rate on device with no analog inputs" raise ValueError(msg) # Acquisition rate cannot be larger than the single channel rate: if acquisition_rate is not None and acquisition_rate > max_AI_single_chan_rate: msg = """acquisition_rate %f is larger than the maximum single-channel rate %f for this device""" raise ValueError( dedent(msg) % (acquisition_rate, max_AI_single_chan_rate)) self.clock_terminal = clock_terminal self.MAX_name = MAX_name if MAX_name is not None else name self.static_AO = static_AO self.static_DO = static_DO self.acquisition_rate = acquisition_rate self.AO_range = AO_range self.max_AI_multi_chan_rate = max_AI_multi_chan_rate self.max_AI_single_chan_rate = max_AI_single_chan_rate self.max_AO_sample_rate = max_AO_sample_rate self.max_DO_sample_rate = max_DO_sample_rate self.min_semiperiod_measurement = min_semiperiod_measurement self.num_AI = num_AI self.num_AO = num_AO self.num_CI = num_CI self.ports = ports if ports is not None else {} self.supports_buffered_AO = supports_buffered_AO self.supports_buffered_DO = supports_buffered_DO self.supports_semiperiod_measurement = supports_semiperiod_measurement if self.supports_buffered_DO and self.supports_buffered_AO: self.clock_limit = min(self.max_DO_sample_rate, self.max_AO_sample_rate) elif self.supports_buffered_DO: self.clock_limit = self.max_DO_sample_rate elif self.supports_buffered_AO: self.clock_limit = self.max_AO_sample_rate else: self.clock_limit = None if not (static_AO and static_DO): msg = """Device does not support buffered output, please instantiate it with static_AO=True and static_DO=True""" raise LabscriptError(dedent(msg)) self.wait_monitor_minimum_pulse_width = self.min_semiperiod_measurement # Set allowed children based on capabilities: self.allowed_children = [] if self.num_AI > 0: self.allowed_children += [AnalogIn] if self.num_AO > 0 and static_AO: self.allowed_children += [StaticAnalogOut] if self.num_AO > 0 and not static_AO: self.allowed_children += [AnalogOut] if self.ports and static_DO: self.allowed_children += [StaticDigitalOut] if self.ports and not static_DO: self.allowed_children += [DigitalOut] if clock_terminal is None and not (static_AO and static_DO): msg = """Clock terminal must be specified unless static_AO and static_DO are both True""" raise LabscriptError(dedent(msg)) self.BLACS_connection = self.MAX_name # Cannot be set with set_passed_properties because of name mangling with the # initial double underscore: self.set_property('__version__', __version__, 'connection_table_properties') # This is called late since it must be called after our clock_limit attribute is # set: IntermediateDevice.__init__(self, name, parent_device, **kwargs)
def add_device(self, device): """Error checking for adding a child device""" # Verify static/dynamic outputs compatible with configuration: if isinstance(device, StaticAnalogOut) and not self.static_AO: msg = """Cannot add StaticAnalogOut to NI_DAQmx device configured for dynamic analog output. Pass static_AO=True for static analog output""" raise LabscriptError(dedent(msg)) if isinstance(device, StaticDigitalOut) and not self.static_DO: msg = """Cannot add StaticDigitalOut to NI_DAQmx device configured for dynamic digital output. Pass static_DO=True for static digital output""" raise LabscriptError(dedent(msg)) if isinstance(device, AnalogOut) and self.static_AO: msg = """Cannot add AnalogOut to NI_DAQmx device configured for static analog output. Pass static_AO=False for dynamic analog output""" raise LabscriptError(dedent(msg)) if isinstance(device, DigitalOut) and self.static_DO: msg = """Cannot add DigitalOut to NI_DAQmx device configured for static digital output. Pass static_DO=False for dynamic digital output""" raise LabscriptError(dedent(msg)) # Verify connection string is OK: if isinstance(device, (AnalogOut, StaticAnalogOut)): ao_num = split_conn_AO(device.connection) if ao_num >= self.num_AO: msg = """Cannot add output with connection string '%s' to device with num_AO=%d""" raise ValueError( dedent(msg) % (device.connection, self.num_AO)) elif isinstance(device, (DigitalOut, StaticDigitalOut)): port, line = split_conn_DO(device.connection) port_str = 'port%d' % port if port_str not in self.ports: msg = "Parent device has no such DO port '%s'" % port_str raise ValueError(msg) nlines = self.ports[port_str]['num_lines'] if line >= nlines: msg = """Canot add output with connection string '%s' to port '%s' with only %d lines""" raise ValueError( dedent(msg) % (device.connection, port_str, nlines)) supports_buffered = self.ports[port_str]['supports_buffered'] if isinstance(device, DigitalOut) and not supports_buffered: msg = """Cannot add DigitalOut port '%s', which does not support buffered output""" raise ValueError(dedent(msg) % port_str) elif isinstance(device, AnalogIn): ai_num = split_conn_AI(device.connection) if ai_num >= self.num_AI: msg = """Cannot add analog input with connection string '%s' to device with num_AI=%d""" raise ValueError( dedent(msg) % (device.connection, self.num_AI)) if self.acquisition_rate is None: msg = """Cannot add analog input to NI_DAQmx device with acquisition_rate=None. Please set acquisition_rate as an instantiation argument to the parent NI_DAQmx device.""" raise ValueError(dedent(msg)) if self.parent_device is None: msg = """Cannot add analog input to device with no parent pseudoclock. Even if there is no buffered output, a pseudoclock is still required to trigger the start of acquisition. Please specify a parent_device and clock_terminal for device %s""" raise ValueError(dedent(msg) % self.name) IntermediateDevice.add_device(self, device)
def generate_code(self, hdf5_file): IntermediateDevice.generate_code(self, hdf5_file) analogs = {} digitals = {} inputs = {} for device in self.child_devices: if isinstance(device, AnalogOut): analogs[device.connection] = device elif isinstance(device, DigitalOut): digitals[device.connection] = device elif isinstance(device, AnalogIn): inputs[device.connection] = device else: raise Exception('Got unexpected device.') clockline = self.parent_device pseudoclock = clockline.parent_device times = pseudoclock.times[clockline] analog_out_table = np.empty((len(times), len(analogs)), dtype=np.float32) analog_connections = analogs.keys() analog_connections.sort() analog_out_attrs = [] for i, connection in enumerate(analog_connections): output = analogs[connection] if any(output.raw_output > 10) or any(output.raw_output < -10): # Bounds checking: raise LabscriptError( '%s %s ' % (output.description, output.name) + 'can only have values between -10 and 10 Volts, ' + 'the limit imposed by %s.' % self.name) analog_out_table[:, i] = output.raw_output analog_out_attrs.append(self.MAX_name + '/' + connection) input_connections = inputs.keys() input_connections.sort() input_attrs = [] acquisitions = [] for connection in input_connections: input_attrs.append(self.MAX_name + '/' + connection) for acq in inputs[connection].acquisitions: acquisitions.append( (connection, acq['label'], acq['start_time'], acq['end_time'], acq['wait_label'], acq['scale_factor'], acq['units'])) # The 'a256' dtype below limits the string fields to 256 # characters. Can't imagine this would be an issue, but to not # specify the string length (using dtype=str) causes the strings # to all come out empty. acquisitions_table_dtypes = [('connection', 'a256'), ('label', 'a256'), ('start', float), ('stop', float), ('wait label', 'a256'), ('scale factor', float), ('units', 'a256')] acquisition_table = np.empty(len(acquisitions), dtype=acquisitions_table_dtypes) for i, acq in enumerate(acquisitions): acquisition_table[i] = acq digital_out_table = [] if digitals: digital_out_table = self.convert_bools_to_bytes(digitals.values()) grp = self.init_device_group(hdf5_file) if all(analog_out_table.shape): # Both dimensions must be nonzero grp.create_dataset('ANALOG_OUTS', compression=config.compression, data=analog_out_table) self.set_property('analog_out_channels', ', '.join(analog_out_attrs), location='device_properties') if len(digital_out_table): # Table must be non empty grp.create_dataset('DIGITAL_OUTS', compression=config.compression, data=digital_out_table) # construct a single string that has each port and line distribution separated by commas # this should coincide with the convention used by the create/write functions in the DAQmx library ports_str = "" for i in range(self.n_ports): ports_str = ports_str + self.MAX_name + '/port%d' % ( i) + '/line0:%d' % (self.n_lines - 1) + ',' ports_str = ports_str[:-1] # delete final comma in string self.set_property('digital_lines', (ports_str), location='device_properties') if len(acquisition_table): # Table must be non empty grp.create_dataset('ACQUISITIONS', compression=config.compression, data=acquisition_table) self.set_property('analog_in_channels', ', '.join(input_attrs), location='device_properties') # TODO: move this to decorator (requires ability to set positional args with @set_passed_properties) self.set_property('clock_terminal', self.clock_terminal, location='connection_table_properties')
def __init__(self, name, parent_device, clock_type, com_port): IntermediateDevice.__init__(self, name, parent_device, clock_type) self.BLACS_connection = com_port
def _generate_code(self, hdf5_file): IntermediateDevice.generate_code(self, hdf5_file) analogs = {} digitals = {} inputs = {} for device in self.child_devices: if isinstance(device, AnalogOut): analogs[device.connection] = device elif isinstance(device, DigitalOut): digitals[device.connection] = device elif isinstance(device, AnalogIn): inputs[device.connection] = device else: raise Exception('Got unexpected device.') clockline = self.parent_device pseudoclock = clockline.parent_device times = pseudoclock.times[clockline] analog_connections = analogs.keys() analog_connections.sort() analog_out_attrs = [] #KLUGGEEEE #get lenth of one output connection output_length = len(analogs[analog_connections[0]].raw_output) analog_out_table = np.empty((output_length, len(analogs)), dtype=np.float32) #analog_out_table = np.empty((len(times),len(analogs)), dtype=np.float32) for i, connection in enumerate(analog_connections): output = analogs[connection] if any(output.raw_output > 10) or any(output.raw_output < -10): # Bounds checking: raise LabscriptError( '%s %s ' % (output.description, output.name) + 'can only have values between -10 and 10 Volts, ' + 'the limit imposed by %s.' % self.name) analog_out_table[:, i] = output.raw_output analog_out_attrs.append(self.MAX_name + '/' + connection) """ if self.name == 'ni_card_B': #kluge to double every cell new_out_table = np.empty((output_length*2, len(analogs)), dtype=np.float32) for i, row in enumerate(analog_out_table): new_out_table[2*i] = row new_out_table[2*i+1] = row analog_out_table = new_out_table """ #now we know that the last column should be randomized for one of the #CHOOSE CHANNEL HERE if self.name == 'ni_card_B': random_column = 0 #randint(0,6) else: # CHANGE THIS FOR CARD A random_column = 1 #analog_out_table[:,-1] = analog_out_table[:,random_column] input_connections = inputs.keys() input_connections.sort() input_attrs = [] acquisitions = [] for connection in input_connections: input_attrs.append(self.MAX_name + '/' + connection) for acq in inputs[connection].acquisitions: acquisitions.append( (connection, acq['label'], acq['start_time'], acq['end_time'], acq['wait_label'], acq['scale_factor'], acq['units'])) # The 'a256' dtype below limits the string fields to 256 # characters. Can't imagine this would be an issue, but to not # specify the string length (using dtype=str) causes the strings # to all come out empty. acquisitions_table_dtypes = [('connection', 'a256'), ('label', 'a256'), ('start', float), ('stop', float), ('wait label', 'a256'), ('scale factor', float), ('units', 'a256')] acquisition_table = np.empty(len(acquisitions), dtype=acquisitions_table_dtypes) for i, acq in enumerate(acquisitions): acquisition_table[i] = acq digital_out_table = [] if digitals: digital_out_table = self.convert_bools_to_bytes(digitals.values()) grp = self.init_device_group(hdf5_file) if all(analog_out_table.shape): # Both dimensions must be nonzero grp.create_dataset('ANALOG_OUTS', compression=config.compression, data=analog_out_table) self.set_property('analog_out_channels', ', '.join(analog_out_attrs), location='device_properties') if len(digital_out_table): # Table must be non empty grp.create_dataset('DIGITAL_OUTS', compression=config.compression, data=digital_out_table) self.set_property('digital_lines', '/'.join((self.MAX_name, 'port0', 'line0:%d' % (self.n_digitals - 1))), location='device_properties') if len(acquisition_table): # Table must be non empty grp.create_dataset('ACQUISITIONS', compression=config.compression, data=acquisition_table) self.set_property('analog_in_channels', ', '.join(input_attrs), location='device_properties') # TODO: move this to decorator (requires ability to set positional args with @set_passed_properties) self.set_property('clock_terminal', self.clock_terminal, location='connection_table_properties')
def add_device(self, device): # Error-check the connection string: _ = get_device_number(device.connection) IntermediateDevice.add_device(self, device)
def generate_code(self, hdf5_file): IntermediateDevice.generate_code(self, hdf5_file) DDSProfs = {} if len(self.child_devices) > 1: raise LabscriptError( "Too many child_devices. This device expects exactly 1 AD_DDS child output." ) output = self.child_devices[0] if isinstance(output, AD_DDS): prefix = output.connection[0] channel = int(output.connection[1]) else: raise Exception('Got unexpected device.') numDDSProfs = len(output.profiles) grp = hdf5_file.create_group('/devices/' + self.name) if numDDSProfs: profile_dtypes = [('freq%d'%i,np.float) for i in range(numDDSProfs)] + \ [('phase%d'%i,np.float) for i in range(numDDSProfs)] + \ [('amp%d'%i,np.float) for i in range(numDDSProfs)] profile_table = np.zeros(1, dtype=profile_dtypes) for profile in output.profiles: profile_table['freq' + profile[-1:]] = output.profiles[profile]['freq'] profile_table['amp' + profile[-1:]] = output.profiles[profile]['amp'] profile_table['phase' + profile[-1:]] = output.profiles[profile]['phase'] grp.create_dataset('PROFILE_DATA', compression=config.compression, data=profile_table) if output.sweep: sweep_dtypes = [('sweep_type', np.int), ('sweep_low', np.float), ('sweep_high', np.float), ('sweep_risetime', np.float), ('sweep_falltime', np.float), ('sweep_dt', np.float)] sweep_table = np.empty(1, dtype=sweep_dtypes) sweep_types = {'freq': 0, 'phase': 1, 'amp': 2} sweep_table['sweep_type'] = sweep_types[ output.sweep_params['type']] sweep_table['sweep_low'] = output.sweep_params['low'] sweep_table['sweep_high'] = output.sweep_params['high'] sweep_table['sweep_risetime'] = output.sweep_params['risetime'] sweep_table['sweep_falltime'] = output.sweep_params['falltime'] sweep_table['sweep_dt'] = output.sweep_params['sweep_dt'] grp.create_dataset('SWEEP_DATA', compression=config.compression, data=sweep_table)
def add_device(self, output): # TODO: check there are no duplicates, check that connection # string is formatted correctly. IntermediateDevice.add_device(self, output)