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 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 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 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 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 _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 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 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')