Exemple #1
0
    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))
Exemple #5
0
 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))
Exemple #7
0
    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
Exemple #8
0
 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
Exemple #9
0
 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.')
Exemple #11
0
    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)
Exemple #12
0
 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
Exemple #16
0
 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
Exemple #17
0
    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
Exemple #20
0
 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)
Exemple #21
0
    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
Exemple #24
0
    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
Exemple #26
0
    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
Exemple #27
0
    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)
Exemple #28
0
    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')
Exemple #30
0
 def __init__(self, name, parent_device, clock_type, com_port):
     IntermediateDevice.__init__(self, name, parent_device, clock_type)
     self.BLACS_connection = com_port
Exemple #31
0
    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')
Exemple #32
0
 def add_device(self, device):
     # Error-check the connection string:
     _ = get_device_number(device.connection)
     IntermediateDevice.add_device(self, device)
Exemple #33
0
    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)