Exemple #1
0
    def test_real_anything(self):
        a = Anything()
        for v in [None, 0, 1, 0.0, 1.2, '', 'hi!', [1, 2, 3], [],
                  {'a': 1, 'b': 2}, {}, set([1, 2, 3]), a, range(10),
                  True, False, float("nan"), float("inf"), b'good',
                  AClass, AClass(), a_func]:
            a.validate(v)

        self.assertEqual(repr(a), '<Anything>')
Exemple #2
0
def test_real_anything():
    a = Anything()
    for v in [
            None, 0, 1, 0.0, 1.2, '', 'hi!', [1, 2, 3], [], {
                'a': 1,
                'b': 2
            }, {}, {1, 2, 3}, a,
            range(10), True, False,
            float("nan"),
            float("inf"), b'good', AClass,
            AClass(), a_func
    ]:
        a.validate(v)

    assert repr(a) == '<Anything>'
Exemple #3
0
    def __init__(self, name: str, metadata: Optional[Dict] = None) -> None:
        self._t0 = time.time()

        super().__init__(name, metadata)

        self.add_parameter('IDN', get_cmd=self.get_idn, vals=Anything())

        self.record_instance(self)
Exemple #4
0
    def __init__(self,
                 name: str,
                 metadata: Optional[Mapping[Any, Any]] = None) -> None:

        self._t0 = time.time()

        super().__init__(name, metadata)

        self.add_parameter('IDN', get_cmd=self.get_idn, vals=Anything())
Exemple #5
0
    def __init__(self, name: str,
                 metadata: Optional[Dict]=None, **kwargs) -> None:
        self._t0 = time.time()
        if kwargs.pop('server_name', False):
            warnings.warn("server_name argument not supported any more",
                          stacklevel=0)
        super().__init__(name, **kwargs)

        self.add_parameter('IDN', get_cmd=self.get_idn,
                           vals=Anything())

        self.record_instance(self)
Exemple #6
0
    def __init__(self, name, **kwargs):
        self._t0 = time.time()
        if kwargs.pop('server_name', False):
            warnings.warn("server_name argument not supported any more",
                          stacklevel=0)
        super().__init__(name, **kwargs)

        self.add_parameter('IDN', get_cmd=self.get_idn, vals=Anything())

        self._meta_attrs = ['name']

        self.record_instance(self)
Exemple #7
0
    def __init__(self, name, server_name=None, **kwargs):
        self._t0 = time.time()
        super().__init__(**kwargs)
        self.parameters = {}
        self.functions = {}

        self.name = str(name)

        self.add_parameter('IDN', get_cmd=self.get_idn,
                           vals=Anything())

        self._meta_attrs = ['name']

        self._no_proxy_methods = {'__getstate__'}
Exemple #8
0
    def __init__(self, name, cardid='spcm0', **kwargs):
        """Driver for the Spectrum M4i.44xx-x8 cards.

        For more information see: http://spectrum-instrumentation.com/en/m4i-platform-overview

        Example:

            Example usage for acquisition with channel 2 using an external trigger
            that triggers multiple times with trigger mode HIGH::

                m4 = M4i(name='M4i', server_name=None)
                m4.enable_channels(pyspcm.CHANNEL2)
                m4.set_channel_settings(2,mV_range, input_path, termination, coupling, compensation)
                m4.set_ext0_OR_trigger_settings(pyspcm.SPC_TM_HIGH,termination,coupling,level0)
                calc = m4.multiple_trigger_acquisition(mV_range,memsize,seg_size,posttrigger_size)

        Todo:
          Whenever an error occurs (including validation errors) the python
          console needs to be restarted


        """
        super().__init__(name, **kwargs)

        self.hCard = pyspcm.spcm_hOpen(cardid)
        if self.hCard is None:
            logging.warning("M4i: no card found\n")

        # add parameters for getting
        self.add_parameter('card_id',
                           label='card id',
                           get_cmd=None, set_cmd=None,
                           initial_value=cardid,
                           vals=Anything(),
                           docstring='The card ID')
        self.add_parameter('max_sample_rate',
                           label='max sample rate',
                           unit='Hz',
                           get_cmd=self.get_max_sample_rate,
                           docstring='The maximumum sample rate')
        self.add_parameter('memory',
                           label='memory',
                           unit='bytes',
                           get_cmd=self.get_card_memory,
                           docstring='Amount of memory on card')
        self.add_parameter('resolution',
                           label='resolution',
                           unit='bits',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_MIINST_BITSPERSAMPLE),
                           docstring='Resolution of the card')
        self.add_parameter('pcidate',
                           label='pcidate',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_PCIDATE),
                           docstring='The PCI date')
        self.add_parameter('serial_number',
                           label='serial number',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_PCISERIALNO),
                           docstring='The serial number of the board')
        self.add_parameter('channel_count',
                           label='channel count',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_CHCOUNT),
                           docstring='Return number of enabled channels')
        self.add_parameter('input_path_count',
                           label='input path count',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_READAIPATHCOUNT),
                           docstring='Return number of analog input paths')
        self.add_parameter('input_ranges_count',
                           label='input ranges count',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_READIRCOUNT),
                           docstring='Return number of input ranges for the current input path')
        self.add_parameter('input_path_features',
                           label='input path features',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_READAIFEATURES),
                           docstring='Return a bitmap of features for current input path')
        self.add_parameter('available_card_modes',
                           label='available card modes',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_AVAILCARDMODES),
                           docstring='Return a bitmap of available card modes')
        self.add_parameter('card_status',
                           label='card status',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_M2STATUS),
                           docstring='Return a bitmap for the status information')
        self.add_parameter('read_range_min_0',
                           label='read range min 0', unit='mV',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_READRANGEMIN0),
                           docstring='Return the lower border of input range 0')

        # buffer handling
        self.add_parameter('user_available_length',
                           label='user available length',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_DATA_AVAIL_USER_LEN),
                           docstring='returns the number of currently to the user available bytes inside a sample data transfer')
        self.add_parameter('user_available_position',
                           label='user available position',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_DATA_AVAIL_USER_POS),
                           docstring='returns the position as byte index where the currently available data samles start')
        self.add_parameter('buffer_fill_size',
                           label='buffer fill size',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_FILLSIZEPROMILLE),
                           docstring='returns the current fill size of the on-board memory (FIFO buffer) in promille (1/1000)')

        # triggering
        self.add_parameter('available_trigger_or_mask',
                           label='available trigger or mask',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_AVAILORMASK),
                           docstring='bitmask, in which all bits of sources for the OR mask are set, if available')
        self.add_parameter('available_channel_or_mask',
                           label='available channel or mask',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_CH_AVAILORMASK0),
                           docstring='bitmask, in which all bits of sources/channels (0-31) for the OR mask are set, if available')
        self.add_parameter('available_trigger_and_mask',
                           label='available trigger and mask',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_AVAILANDMASK),
                           docstring='bitmask, in which all bits of sources for the AND mask are set, if available')
        self.add_parameter('available_channel_and_mask',
                           label='available channel and mask',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_CH_AVAILANDMASK0),
                           docstring='bitmask, in which all bits of sources/channels (0-31) for the AND mask are set, if available')
        self.add_parameter('available_trigger_delay',
                           label='available trigger delay',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_AVAILDELAY),
                           docstring='contains the maximum available delay as decimal integer value')
        self.add_parameter('available_external_trigger_modes',
                           label='available external trigger modes',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_EXT0_AVAILMODES),
                           docstring='bitmask showing all available trigger modes for external 0 (main analog trigger input)')
        self.add_parameter('external_trigger_min_level',
                           label='external trigger min level',
                           unit='mV',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_EXT_AVAIL0_MIN),
                           docstring='returns the minimum trigger level')
        self.add_parameter('external_trigger_max_level',
                           label='external trigger max level',
                           unit='mV',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_EXT_AVAIL0_MAX),
                           docstring='returns the maximum trigger level')
        self.add_parameter('external_trigger_level_step_size',
                           label='external trigger level step size',
                           unit='mV',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_EXT_AVAIL0_STEP),
                           docstring='returns the step size of the trigger level')
        self.add_parameter('available_channel_trigger_modes',
                           label='available channel trigger modes',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_CH_AVAILMODES),
                           docstring='bitmask, in which all bits of the modes for the channel trigger are set')
        self.add_parameter('trigger_counter',
                           label='trigger counter',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIGGERCOUNTER),
                           docstring='returns the number of triger events since acquisition start')
        # data per sample
        self.add_parameter('bytes_per_sample',
                           label='bytes per sample',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_MIINST_BYTESPERSAMPLE),
                           docstring='returns the number of bytes per sample')
        self.add_parameter('bits_per_sample',
                           label='bits per sample',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_MIINST_BITSPERSAMPLE),
                           docstring='returns the number of bits per sample')

        # available clock modes
        self.add_parameter('available_clock_modes',
                           label='available clock modes',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_AVAILCLOCKMODES),
                           docstring='returns a bitmask in which the bits of the clock modes are set, if available')

        # converting ADC samples to voltage values
        self.add_parameter('ADC_to_voltage',
                           label='ADC to voltage',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_MIINST_MAXADCVALUE),
                           docstring='contains the decimal code (in LSB) of the ADC full scale value')

        self.add_parameter('oversampling_factor',
                           label='oversampling factor',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_OVERSAMPLINGFACTOR),
                           docstring='Reads the oversampling factor')

        # add parameters for setting and getting (read/write direction
        # registers)

        self.add_parameter('enable_channels',
                           label='Channels enabled',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_CHENABLE),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_CHENABLE),
                           vals=Enum(1, 2, 4, 8, 3, 5, 9, 6, 10, 12, 15),
                           docstring='Set and get enabled channels')

        # analog input path functions
        # TODO: change Enum validator to set_parser for the numbered functions
        # if we want string inputs

        self.add_parameter('read_input_path',
                           label='read input path',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_READAIPATH),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_READAIPATH),
                           vals=Enum(0, 1, 2, 3),
                           docstring='Select the input path which is used to read out the features')

        for i in [0, 1, 2, 3]:
            self.add_parameter('input_path_{}'.format(i),
                               label='input path {}'.format(i),
                               get_cmd=partial(self._param32bit, getattr(
                                   pyspcm, 'SPC_PATH{}'.format(i))),
                               set_cmd=partial(self._set_param32bit, getattr(
                                   pyspcm, 'SPC_PATH{}'.format(i))),
                               vals=Enum(0, 1),
                               docstring='Set and get analog input path for channel {}'.format(i))

            # channel range functions
            # TODO: check the input path to set the right validator (either by
            # directly calling input_path_x() or by storing a variable)
            self.add_parameter('range_channel_{}'.format(i),
                               label='range channel {}'.format(i),
                               get_cmd=partial(self._param32bit, getattr(
                                   pyspcm, 'SPC_AMP{}'.format(i))),
                               set_cmd=partial(self._set_param32bit, getattr(
                                   pyspcm, 'SPC_AMP{}'.format(i))),
                               vals=Enum(200, 500, 1000, 2000,
                                         2500, 5000, 10000),
                               unit='mV',
                               docstring='Set and get input range of channel {} (in mV)'.format(i))

            # input termination functions
            self.add_parameter('termination_{}'.format(i),
                               label='termination {}'.format(i),
                               get_cmd=partial(self._param32bit, getattr(
                                   pyspcm, 'SPC_50OHM{}'.format(i))),
                               set_cmd=partial(self._set_param32bit, getattr(
                                   pyspcm, 'SPC_50OHM{}'.format(i))),
                               vals=Enum(0, 1),
                               docstring='if 1 sets termination to 50 Ohm, otherwise 1 MOhm for channel {}'.format(i))

            # input coupling
            self.add_parameter('ACDC_coupling_{}'.format(i),
                               label='ACDC coupling {}'.format(i),
                               get_cmd=partial(self._param32bit, getattr(
                                   pyspcm, 'SPC_ACDC{}'.format(i))),
                               set_cmd=partial(self._set_param32bit, getattr(
                                   pyspcm, 'SPC_ACDC{}'.format(i))),
                               vals=Enum(0, 1),
                               docstring='if 1 sets the AC coupling, otherwise sets the DC coupling for channel {}'.format(i))

            # AC/DC offset compensation
            self.add_parameter('ACDC_offs_compensation_{}'.format(i),
                               label='ACDC offs compensation {}'.format(i),
                               get_cmd=partial(self._get_compensation, i),
                               set_cmd=partial(self._set_compensation, i),
                               vals=Enum(0, 1),
                               docstring='if 1 enables compensation, if 0 disables compensation for channel {}'.format(i))

            # anti aliasing filter (Bandwidth limit)
            self.add_parameter('anti_aliasing_filter_{}'.format(i),
                               label='anti aliasing filter {}'.format(i),
                               get_cmd=partial(self._param32bit, getattr(
                                   pyspcm, 'SPC_FILTER{}'.format(i))),
                               set_cmd=partial(self._set_param32bit, getattr(
                                   pyspcm, 'SPC_FILTER{}'.format(i))),
                               vals=Enum(0, 1),
                               docstring='if 1 selects bandwidth limit, if 0 sets to full bandwidth for channel {}'.format(i))

            self.add_parameter('channel_{}'.format(i),
                               label='channel {}'.format(i),
                               unit='a.u.',
                               get_cmd=partial(self._read_channel, i))

        # acquisition modes
        # TODO: If required, the other acquisition modes can be added to the
        # validator
        self.add_parameter('card_mode',
                           label='card mode',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_CARDMODE),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_CARDMODE),
                           vals=Enum(pyspcm.SPC_REC_STD_SINGLE, pyspcm.SPC_REC_STD_MULTI, pyspcm.SPC_REC_STD_GATE, pyspcm.SPC_REC_STD_ABA,
                                     pyspcm.SPC_REC_FIFO_SINGLE, pyspcm.SPC_REC_FIFO_MULTI, pyspcm.SPC_REC_FIFO_GATE, pyspcm.SPC_REC_FIFO_ABA, pyspcm.SPC_REC_STD_AVERAGE),
                           docstring='defines the used operating mode')

        # wait command
        self.add_parameter('timeout',
                           label='timeout',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TIMEOUT),
                           unit='ms',
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_TIMEOUT),
                           docstring='defines the timeout for wait commands')

        # Single acquisition mode memory, pre- and posttrigger (pretrigger = memory size - posttrigger)
        # TODO: improve the validators to make them take into account the
        # current state of the instrument
        self.add_parameter('data_memory_size',
                           label='data memory size',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_MEMSIZE),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_MEMSIZE),
                           vals=Numbers(min_value=16),
                           docstring='sets the memory size in samples per channel')
        self.add_parameter('posttrigger_memory_size',
                           label='posttrigger memory size',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_POSTTRIGGER),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_POSTTRIGGER),
                           docstring='sets the number of samples to be recorded after trigger event')

        # FIFO single acquisition length and pretrigger
        self.add_parameter('pretrigger_memory_size',
                           label='pretrigger memory size',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_PRETRIGGER),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_PRETRIGGER),
                           docstring='sets the number of samples to be recorded before trigger event')
        self.add_parameter('segment_size',
                           label='segment size',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_SEGMENTSIZE),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_SEGMENTSIZE),
                           docstring='length of segments to acquire')
        self.add_parameter('total_segments',
                           label='total segments',
                           get_cmd=partial(self._param32bit, pyspcm.SPC_LOOPS),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_LOOPS),
                           docstring='number of segments to acquire in total. Setting 0 makes it run until stopped by user')

        # clock generation
        self.add_parameter('clock_mode',
                           label='clock mode',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_CLOCKMODE),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_CLOCKMODE),
                           vals=Enum(pyspcm.SPC_CM_INTPLL, pyspcm.SPC_CM_QUARTZ2,
                                     pyspcm.SPC_CM_EXTREFCLOCK, pyspcm.SPC_CM_PXIREFCLOCK),
                           docstring='defines the used clock mode or reads out the actual selected one')
        self.add_parameter('sample_rate',
                           label='sample rate',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_SAMPLERATE),
                           unit='Hz',
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_SAMPLERATE),
                           docstring='write the sample rate for internal sample generation or read rate nearest to desired')
        self.add_parameter('special_clock',
                           label='special clock',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_SPECIALCLOCK),
                           unit='Hz',
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_SPECIALCLOCK),
                           docstring='Activate/Deactivate the special clock mode (lower and more sampling clock rates)')

        # triggering
        self.add_parameter('trigger_or_mask',
                           label='trigger or mask',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_ORMASK),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_TRIG_ORMASK),
                           vals=Enum(pyspcm.SPC_TMASK_NONE, pyspcm.SPC_TMASK_SOFTWARE,
                                     pyspcm.SPC_TMASK_EXT0, pyspcm.SPC_TMASK_EXT1),
                           docstring='defines the events included within the  trigger OR mask card')
        self.add_parameter('channel_or_mask',
                           label='channel or mask',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_CH_ORMASK0),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_TRIG_CH_ORMASK0),
                           docstring='includes the channels (0-31) within the channel trigger OR mask of the card')
        self.add_parameter('trigger_and_mask',
                           label='trigger and mask',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_ANDMASK),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_TRIG_ANDMASK),
                           vals=Enum(pyspcm.SPC_TMASK_NONE,
                                     pyspcm.SPC_TMASK_EXT0, pyspcm.SPC_TMASK_EXT1),
                           docstring='defines the events included within the  trigger AND mask card')
        self.add_parameter('channel_and_mask',
                           label='channel and mask',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_CH_ANDMASK0),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_TRIG_CH_ANDMASK0),
                           docstring='includes the channels (0-31) within the channel trigger AND mask of the card')
        self.add_parameter('trigger_delay',
                           label='trigger delay',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_DELAY),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_TRIG_DELAY),
                           docstring='defines the delay for the detected trigger events')
        self.add_parameter('external_trigger_mode',
                           label='external trigger mode',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_EXT0_MODE),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_TRIG_EXT0_MODE),
                           docstring='defines the external trigger mode for the external SMA connector trigger input')
        self.add_parameter('external_trigger_termination',
                           label='external trigger termination',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_TERM),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_TRIG_TERM),
                           vals=Enum(0, 1),
                           docstring='A 1 sets the 50 Ohm termination, a 0 sets high impedance termination')
        self.add_parameter('external_trigger_input_coupling',
                           label='external trigger input coupling',
                           get_cmd=partial(self._param32bit,
                                           pyspcm.SPC_TRIG_EXT0_ACDC),
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_TRIG_EXT0_ACDC),
                           vals=Enum(0, 1),
                           docstring='A 1 sets the AC coupling for the external trigger, a 0 sets DC')

        for l in [0, 1]:
            self.add_parameter('external_trigger_level_{}'.format(l),
                               label='external trigger level {}'.format(l),
                               get_cmd=partial(self._param32bit, getattr(
                                   pyspcm, 'SPC_TRIG_EXT0_LEVEL{}'.format(l))),
                               set_cmd=partial(self._set_param32bit, getattr(
                                   pyspcm, 'SPC_TRIG_EXT0_LEVEL{}'.format(l))),
                               docstring='trigger level {} for external trigger'.format(l))

        for i in [0, 1, 2, 3]:
            self.add_parameter('trigger_mode_channel_{}'.format(i),
                               label='trigger mode channel {}'.format(i),
                               get_cmd=partial(self._param32bit, getattr(
                                   pyspcm, 'SPC_TRIG_CH{}_MODE'.format(i))),
                               set_cmd=partial(self._set_param32bit, getattr(
                                   pyspcm, 'SPC_TRIG_CH{}_MODE'.format(i))),
                               docstring='sets the trigger mode for channel {}'.format(i))
            for l in [0, 1]:
                self.add_parameter('trigger_channel_{}_level_{}'.format(i, l),
                                   label='trigger channel {} level {}'.format(
                                       i, l),
                                   get_cmd=partial(self._param32bit, getattr(
                                       pyspcm, 'SPC_TRIG_CH{}_LEVEL{}'.format(i, l))),
                                   set_cmd=partial(self._set_param32bit, getattr(
                                       pyspcm, 'SPC_TRIG_CH{}_LEVEL{}'.format(i, l))),
                                   docstring='trigger level {} channel {}'.format(l, i))

        # add parameters for setting (write only registers)

        # Buffer handling
        self.add_parameter('card_available_length',
                           label='card available length',
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_DATA_AVAIL_CARD_LEN),
                           docstring='writes the number of bytes that the card can now use for sample data transfer again')

        # General
        self.add_parameter('general_command',
                           label='general command',
                           set_cmd=partial(self._set_param32bit,
                                           pyspcm.SPC_M2CMD),
                           docstring='executes a command for the card or data transfer')

        # memsize used for simple channel read-out
        self._channel_memsize = 2**12
Exemple #9
0
    def __init__(self,
                 name: str,
                 address: str,
                 reset: bool = False,
                 **kwargs: Any):
        super().__init__(name, address, terminator='\n', **kwargs)

        model = self.get_idn()['model']

        models = ['DG4202', 'DG4162', 'DG4102', 'DG4062']

        if model in models:
            i = models.index(model)

            sine_freq = [200e6, 160e6, 100e6, 60e6][i]
            square_freq = [60e6, 50e6, 40e6, 25e6][i]
            ramp_freq = [5e6, 4e6, 3e6, 1e6][i]
            pulse_freq = [50e6, 40e6, 25e6, 15e6][i]
            harmonic_freq = [100e6, 80e6, 50e6, 30e6][i]
            arb_freq = [50e6, 40e6, 25e6, 15e6][i]
        elif model is None:
            raise KeyError('Could not determine model')
        else:
            raise KeyError('Model code ' + model + ' is not recognized')

        on_off_map = {True: 'ON', False: 'OFF'}

        # Counter
        self.add_parameter('counter_attenuation',
                           get_cmd='COUN:ATT?',
                           set_cmd='COUN:ATT {}',
                           val_mapping={
                               1: '1X',
                               10: '10X'
                           })

        self.add_function('auto_counter', call_cmd='COUN:AUTO')

        self.add_parameter('counter_coupling',
                           get_cmd='COUN:COUP?',
                           set_cmd='COUN:COUP {}',
                           vals=Enum('AC', 'DC'))

        self.add_parameter('counter_gate_time',
                           get_cmd='COUN:GATE?',
                           set_cmd='COUN:GATE {}',
                           unit='s',
                           val_mapping={
                               'auto': 'AUTO',
                               0.001: 'USER1',
                               0.01: 'USER2',
                               0.1: 'USER3',
                               1: 'USER4',
                               10: 'USER5',
                               '>10': 'USER6',
                           })

        self.add_parameter('counter_hf_reject_enabled',
                           get_cmd='COUN:HF?',
                           set_cmd='COUN:HF {}',
                           val_mapping=on_off_map)

        self.add_parameter('counter_impedance',
                           get_cmd='COUN:IMP?',
                           set_cmd='COUN:IMP {}',
                           unit='Ohm',
                           val_mapping={
                               50: '50',
                               1e6: '1M'
                           })

        self.add_parameter('counter_trigger_level',
                           get_cmd='COUN:LEVE?',
                           get_parser=float,
                           set_cmd='COUN:LEVE {}',
                           unit='V',
                           vals=Numbers(min_value=-2.5, max_value=2.5))

        self.add_parameter('counter_enabled',
                           get_cmd='COUN:STAT?',
                           set_cmd='COUN:STAT {}',
                           val_mapping=on_off_map)

        measure_params = [
            'frequency', 'period', 'duty_cycle', 'positive_width',
            'negative_width'
        ]

        # TODO: Check units of outputs
        for i, param in enumerate(measure_params):
            self.add_parameter(f'counter_{param}',
                               get_cmd='COUN:MEAS?',
                               get_parser=partial(parse_single_output, i))

        self.add_parameter('counter_trigger_sensitivity',
                           get_cmd='COUN:SENS?',
                           get_parser=float,
                           set_cmd='COUN:SENS {}',
                           unit='%',
                           vals=Numbers(min_value=0, max_value=100))

        # Output and Source parameters for both channel 1 and 2
        for i in [1, 2]:
            ch = f'ch{i}_'
            output = f'OUTP{i}:'
            source = f'SOUR{i}:'

            self.add_parameter(ch + 'output_impedance',
                               get_cmd=output + 'IMP?',
                               get_parser=parse_string_output,
                               set_cmd=output + 'IMP {}',
                               unit='Ohm',
                               vals=MultiType(
                                   Numbers(min_value=1, max_value=10e3),
                                   Enum('infinity', 'minimum', 'maximum')))

            self.add_parameter(ch + 'add_noise_scale',
                               get_cmd=output + 'NOIS:SCAL?',
                               get_parser=float,
                               set_cmd=output + 'NOIS:SCAL',
                               unit='%',
                               vals=Numbers(min_value=0, max_value=50))

            self.add_parameter(ch + 'add_noise_enabled',
                               get_cmd=output + 'NOIS?',
                               set_cmd=output + 'NOIS {}',
                               val_mapping=on_off_map)

            self.add_parameter(ch + 'output_polarity',
                               get_cmd=output + 'POL?',
                               set_cmd=output + 'POL {}',
                               val_mapping={
                                   'normal': 'NORM',
                                   'inverted': 'INV'
                               })

            self.add_parameter(ch + 'output_enabled',
                               get_cmd=output + 'STAT?',
                               set_cmd=output + 'STAT {}',
                               val_mapping=on_off_map)

            self.add_parameter(ch + 'sync_polarity',
                               get_cmd=output + 'SYNC:POL?',
                               set_cmd=output + 'SYNC:POL {}',
                               val_mapping={
                                   'positive': 'POS',
                                   'negative': 'NEG'
                               })

            self.add_parameter(ch + 'sync_enabled',
                               get_cmd=output + 'SYNC?',
                               set_cmd=output + 'SYNC {}',
                               val_mapping=on_off_map)

            # Source Apply
            # TODO: Various parameters are limited by
            # impedance/freq/period/amplitude settings, this might be very hard
            # to implement in here
            self.add_function(ch + 'custom',
                              call_cmd=source + 'APPL:CUST '
                              '{:.6e},{:.6e},{:.6e},{:.6e}',
                              args=[
                                  Numbers(1e-6, arb_freq),
                                  Numbers(),
                                  Numbers(),
                                  Numbers(0, 360)
                              ])

            self.add_function(ch + 'harmonic',
                              call_cmd=source + 'APPL:HARM '
                              '{:.6e},{:.6e},{:.6e},{:.6e}',
                              args=[
                                  Numbers(1e-6, harmonic_freq),
                                  Numbers(),
                                  Numbers(),
                                  Numbers(0, 360)
                              ])

            self.add_function(ch + 'noise',
                              call_cmd=source + 'APPL:NOIS {:.6e},{:.6e}',
                              args=[Numbers(0, 10), Numbers()])

            self.add_function(ch + 'pulse',
                              call_cmd=source + 'APPL:PULS '
                              '{:.6e},{:.6e},{:.6e},{:.6e}',
                              args=[
                                  Numbers(1e-6, pulse_freq),
                                  Numbers(),
                                  Numbers(),
                                  Numbers(0)
                              ])

            self.add_function(ch + 'ramp',
                              call_cmd=source + 'APPL:RAMP '
                              '{:.6e},{:.6e},{:.6e},{:.6e}',
                              args=[
                                  Numbers(1e-6, ramp_freq),
                                  Numbers(),
                                  Numbers(),
                                  Numbers(0, 360)
                              ])

            self.add_function(ch + 'sinusoid',
                              call_cmd=source + 'APPL:SIN '
                              '{:.6e},{:.6e},{:.6e},{:.6e}',
                              args=[
                                  Numbers(1e-6, sine_freq),
                                  Numbers(),
                                  Numbers(),
                                  Numbers(0, 360)
                              ])

            self.add_function(ch + 'square',
                              call_cmd=source + 'APPL:SQU '
                              '{:.6e},{:.6e},{:.6e},{:.6e}',
                              args=[
                                  Numbers(1e-6, square_freq),
                                  Numbers(),
                                  Numbers(),
                                  Numbers(0, 360)
                              ])

            self.add_function(ch + 'user',
                              call_cmd=source + 'APPL:USER '
                              '{:.6e},{:.6e},{:.6e},{:.6e}',
                              args=[
                                  Numbers(1e-6, arb_freq),
                                  Numbers(),
                                  Numbers(),
                                  Numbers(0, 360)
                              ])

            self.add_parameter(ch + 'configuration',
                               get_cmd=source + 'APPL?',
                               get_parser=parse_multiple_outputs)

            # Source Burst
            self.add_parameter(ch + 'burst_mode',
                               get_cmd=source + 'BURS:MODE?',
                               set_cmd=source + 'BURS:MODE {}',
                               val_mapping={
                                   'triggered': 'TRIG',
                                   'gated': 'GAT',
                                   'infinity': 'INF'
                               })

            self.add_parameter(ch + 'burst_cycles',
                               get_cmd=source + 'BURS:NCYC?',
                               get_parser=float,
                               set_cmd=source + 'BURS:NCYC {}',
                               vals=Ints(1, 1000000))

            self.add_parameter(ch + 'burst_period',
                               get_cmd=source + 'BURS:INT:PER?',
                               get_parser=float,
                               set_cmd=source + 'BURS:INT:PER {}',
                               unit='s',
                               vals=Numbers(1e-6))

            self.add_parameter(ch + 'burst_phase',
                               get_cmd=source + 'BURS:PHAS?',
                               get_parser=float,
                               set_cmd=source + 'BURS:PHAS {}',
                               unit='deg',
                               vals=Numbers(0, 360))

            self.add_parameter(ch + 'burst_trigger_edge',
                               get_cmd=source + 'BURS:TRIG:SLOP?',
                               set_cmd=source + 'BURS:TRIG:SLOP {}',
                               val_mapping={
                                   'positive': 'POS',
                                   'negative': 'NEG'
                               })

            self.add_parameter(ch + 'burst_trigger_source',
                               get_cmd=source + 'BURS:TRIG:SOUR?',
                               set_cmd=source + 'BURS:TRIG:SOUR {}',
                               val_mapping={
                                   'internal': 'INT',
                                   'external': 'EXT',
                                   'manual': 'MAN'
                               })

            self.add_parameter(ch + 'burst_trigger_out',
                               get_cmd=source + 'BURS:TRIG:TRIGO?',
                               set_cmd=source + 'BURS:TRIG:TRIGO {}',
                               val_mapping={
                                   'off': 'OFF',
                                   'positive': 'POS',
                                   'negative': 'NEG'
                               })

            # Source Frequency
            # TODO: The upper bounds of these parameters also depend on the
            # current waveform
            self.add_parameter(ch + 'frequency_center',
                               get_cmd=source + 'FREQ:CENT?',
                               get_parser=float,
                               set_cmd=source + 'FREQ:CENT {}',
                               unit='Hz',
                               vals=Numbers(1e-6))

            self.add_parameter(ch + 'frequency',
                               get_cmd=source + 'FREQ?',
                               get_parser=float,
                               set_cmd=source + 'FREQ {}',
                               unit='Hz',
                               vals=Numbers(1e-6))

            self.add_parameter(ch + 'frequency_start',
                               get_cmd=source + 'FREQ:STAR?',
                               get_parser=float,
                               set_cmd=source + 'FREQ:STAR {}',
                               unit='Hz',
                               vals=Numbers(1e-6))

            self.add_parameter(ch + 'frequency_stop',
                               get_cmd=source + 'FREQ:STOP?',
                               get_parser=float,
                               set_cmd=source + 'FREQ:STOP {}',
                               unit='Hz',
                               vals=Numbers(1e-6))

            # Source Function
            self.add_parameter(ch + 'ramp_symmetry',
                               get_cmd=source + 'FUNC:RAMP:SYMM?',
                               get_parser=float,
                               set_cmd=source + 'FUNC:RAMP:SYMM {}',
                               unit='%',
                               vals=Numbers(0, 100))

            self.add_parameter(ch + 'square_duty_cycle',
                               get_cmd=source + 'FUNC:SQU:DCYC?',
                               get_parser=float,
                               set_cmd=source + 'FUNC:SQU:DCYC {}',
                               unit='%',
                               vals=Numbers(20, 80))

            # Source Harmonic
            self.add_function(ch + 'set_harmonic_amplitude',
                              call_cmd=source + 'HARM:AMPL {},{:.6e}',
                              args=[Ints(2, 16), Numbers(0)])

            self.add_function(ch + 'get_harmonic_amplitude',
                              call_cmd=source + 'HARM:AMPL? {}',
                              args=[Ints(2, 16)],
                              return_parser=float)

            self.add_parameter(ch + 'harmonic_order',
                               get_cmd=source + 'HARM:ORDE?',
                               get_parser=int,
                               set_cmd=source + 'HARM:ORDE {}',
                               vals=Ints(2, 16))

            self.add_function(ch + 'set_harmonic_phase',
                              call_cmd=source + 'HARM:PHAS {},{:.6e}',
                              args=[Ints(2, 16), Numbers(0, 360)])

            self.add_function(ch + 'get_harmonic_phase',
                              call_cmd=source + 'HARM:PHAS? {}',
                              args=[Ints(2, 16)],
                              return_parser=float)

            self.add_parameter(ch + 'harmonic_type',
                               get_cmd=source + 'HARM:TYP?',
                               get_parser=str.lower,
                               set_cmd=source + 'HARM:TYP {}',
                               vals=Enum('even', 'odd', 'all', 'user'))

            # Source Marker
            self.add_parameter(ch + 'marker_frequency',
                               get_cmd=source + 'MARK:FREQ?',
                               get_parser=float,
                               set_cmd=source + 'HMARK:FREQ {}',
                               unit='Hz',
                               vals=Numbers(1e-6))

            self.add_parameter(ch + 'marker_enabled',
                               get_cmd=source + 'MARK?',
                               set_cmd=source + 'MARK {}',
                               val_mapping=on_off_map)

            # Source Modulation (not implemented yet)

            # Source Period (not implemented yet)

            # Source Phase
            self.add_parameter(ch + 'phase',
                               get_cmd=source + 'PHAS?',
                               get_parser=float,
                               set_cmd=source + 'PHAS {}',
                               unit='deg',
                               vals=Numbers(0, 360))

            self.add_function(ch + 'align_phase',
                              call_cmd=source + 'PHAS:INIT')

            # Source Pulse
            self.add_parameter(ch + 'pulse_duty_cycle',
                               get_cmd=source + 'PULS:DCYC?',
                               get_parser=float,
                               set_cmd=source + 'PULS:DCYC {}',
                               unit='%',
                               vals=Numbers(0, 100))

            self.add_parameter(ch + 'pulse_delay',
                               get_cmd=source + 'PULS:DEL?',
                               get_parser=float,
                               set_cmd=source + 'PULS:DEL {}',
                               unit='s',
                               vals=Numbers(0))

            self.add_parameter(ch + 'pulse_hold',
                               get_cmd=source + 'PULS:HOLD?',
                               set_cmd=source + 'PULS:HOLD {}',
                               unit='s',
                               val_mapping={
                                   'width': 'WIDT',
                                   'duty': 'DUTY'
                               })

            self.add_parameter(ch + 'pulse_leading_edge',
                               get_cmd=source + 'PULS:TRAN:LEAD?',
                               get_parser=float,
                               set_cmd=source + 'PULS:TRAN:LEAD {}',
                               unit='s',
                               vals=Numbers(0))

            self.add_parameter(ch + 'pulse_trailing_edge',
                               get_cmd=source + 'PULS:TRAN:TRA?',
                               get_parser=float,
                               set_cmd=source + 'PULS:TRAN:TRA {}',
                               unit='s',
                               vals=Numbers(0))

            self.add_parameter(ch + 'pulse_width',
                               get_cmd=source + 'PULS:WIDT?',
                               get_parser=float,
                               set_cmd=source + 'PULS:WIDT {}',
                               unit='s',
                               vals=Numbers(0))

            # Source Sweep
            self.add_parameter(ch + 'sweep_hold_start',
                               get_cmd=source + 'SWE:HTIM:STAR?',
                               get_parser=float,
                               set_cmd=source + 'SWE:HTIM:STAR {}',
                               unit='s',
                               vals=Numbers(0, 300))

            self.add_parameter(ch + 'sweep_hold_stop',
                               get_cmd=source + 'SWE:HTIM:STOP?',
                               get_parser=float,
                               set_cmd=source + 'SWE:HTIM:STOP {}',
                               unit='s',
                               vals=Numbers(0, 300))

            self.add_parameter(ch + 'sweep_return_time',
                               get_cmd=source + 'SWE:RTIM?',
                               get_parser=float,
                               set_cmd=source + 'SWE:RTIM {}',
                               unit='s',
                               vals=Numbers(0, 300))

            self.add_parameter(ch + 'sweep_spacing',
                               get_cmd=source + 'SWE:SPAC?',
                               set_cmd=source + 'SWE:SPAC {}',
                               val_mapping={
                                   'linear': 'LIN',
                                   'logarithmic': 'LOG',
                                   'step': 'STE'
                               })

            self.add_parameter(ch + 'sweep_enabled',
                               get_cmd=source + 'SWE:STAT?',
                               set_cmd=source + 'SWE:STAT {}',
                               val_mapping=on_off_map)

            self.add_parameter(ch + 'sweep_step',
                               get_cmd=source + 'SWE:STEP?',
                               get_parser=int,
                               set_cmd=source + 'SWE:STEP {}',
                               vals=Ints(2, 2048))

            self.add_parameter(ch + 'sweep_time',
                               get_cmd=source + 'SWE:TIME?',
                               get_parser=float,
                               set_cmd=source + 'SWE:TIME {}',
                               unit='s',
                               vals=Numbers(1e-3, 300))

            # Source Voltage
            self.add_parameter(ch + 'amplitude',
                               get_cmd=source + 'VOLT?',
                               get_parser=float,
                               set_cmd=source + 'VOLT {}',
                               unit='V',
                               vals=Numbers())

            self.add_parameter(ch + 'offset',
                               get_cmd=source + 'VOLT:OFFS?',
                               get_parser=float,
                               set_cmd=source + 'VOLT:OFFS {}',
                               unit='V',
                               vals=Numbers())

            self.add_parameter(ch + 'unit',
                               get_cmd=source + 'VOLT:UNIT?',
                               get_parser=str.lower,
                               set_cmd=source + 'VOLT:UNIT {}',
                               vals=Enum('vpp', 'vrms', 'dbm'))

        # System
        self.add_function('beep', call_cmd='SYST:BEEP')

        self.add_parameter('beeper_enabled',
                           get_cmd='SYST:BEEP:STAT?',
                           set_cmd='SYST:BEEP:STAT {}',
                           val_mapping=on_off_map)

        self.add_function('copy_config_to_ch1', call_cmd='SYST:CSC CH2,CH1')
        self.add_function('copy_config_to_ch2', call_cmd='SYST:CSC CH1,CH2')

        self.add_function('copy_waveform_to_ch1', call_cmd='SYST:CWC CH2,CH1')
        self.add_function('copy_waveform_to_ch2', call_cmd='SYST:CWC CH1,CH2')

        self.add_function('get_error', call_cmd='SYST:ERR?', return_parser=str)

        self.add_parameter('keyboard_locked',
                           get_cmd='SYST:KLOCK?',
                           set_cmd='SYST:KLOCK {}',
                           val_mapping=on_off_map)

        self.add_parameter('startup_mode',
                           get_cmd='SYST:POWS?',
                           get_parser=str.lower,
                           set_cmd='SYST:POWS {}',
                           vals=Enum('user', 'auto'))

        system_states = Enum('default', 'user1', 'user2', 'user3', 'user4',
                             'user5', 'user6', 'user7', 'user8', 'user9',
                             'user10')

        self.add_function('preset',
                          call_cmd='SYST:PRES {}',
                          args=[system_states])

        self.add_function('restart', call_cmd='SYST:RESTART')

        self.add_parameter('reference_clock_source',
                           get_cmd='SYST:ROSC:SOUR?',
                           set_cmd='SYST:ROSC:SOUR {}',
                           val_mapping={
                               'internal': 'INT',
                               'external': 'EXT'
                           })

        self.add_function('shutdown', call_cmd='SYST:SHUTDOWN')

        self.add_parameter('scpi_version', get_cmd='SYST:VERS?')

        # Trace
        self.add_function('upload_data',
                          call_cmd=self._upload_data,
                          args=[Anything()])

        self.add_function('reset', call_cmd='*RST')

        if reset:
            self.reset()

        self.connect_message()
Exemple #10
0
    def __init__(self, name, address=None, port=None, axes=None, **kwargs):
        super().__init__(name,
                         address=address,
                         port=port,
                         terminator='\n',
                         **kwargs)
        self.axes = axes
        self._ATOB = []
        self._latest_response = ''
        # for some reason the first call is always invalid?!
        # need some kind of init?
        self.ask('*IDN?')

        if axes is None:
            self._determine_magnet_axes()
        self._determine_current_to_field()

        self.add_parameter(
            'setpoint',
            names=['B' + ax.lower() + '_setpoint' for ax in self.axes],
            get_cmd=partial(self._get_fld, self.axes, 'FSET'),
            set_cmd=partial(self._ramp_to_setpoint, self.axes, 'FSET'),
            units=['T' for ax in self.axes],
            vals=Anything())

        self.add_parameter('rate',
                           names=['rate_B' + ax.lower() for ax in self.axes],
                           get_cmd=partial(self._get_fld, self.axes, 'RFST'),
                           set_cmd=partial(self._ramp_to_setpoint, self.axes,
                                           'RFST'),
                           units=['T/m' for ax in self.axes],
                           vals=Anything())

        self.add_parameter('fld',
                           names=['B' + ax.lower() for ax in self.axes],
                           get_cmd=partial(self._get_fld, self.axes, 'FLD'),
                           set_cmd=partial(self._ramp_to_setpoint, self.axes,
                                           'FSET'),
                           units=['T' for ax in self.axes],
                           vals=Anything())

        self.add_parameter('fldC',
                           names=['B' + ax.lower() for ax in self.axes],
                           get_cmd=partial(self._get_fld, self.axes, 'CURR'),
                           set_cmd=partial(self._ramp_to_setpoint, self.axes,
                                           'CSET'),
                           units=['T' for ax in self.axes],
                           vals=Anything())

        self.add_parameter('rtp',
                           names=['radius', 'theta', 'phi'],
                           get_cmd=partial(self._get_rtp, self.axes, 'FLD'),
                           set_cmd=partial(self._set_rtp, self.axes, 'FSET'),
                           units=['|B|', 'rad', 'rad'],
                           vals=Anything())

        self.add_parameter('rtpC',
                           names=['radius', 'theta', 'phi'],
                           get_cmd=partial(self._get_rtp, self.axes, 'CURR'),
                           set_cmd=partial(self._set_rtp, self.axes, 'CSET'),
                           units=['|B|', 'rad', 'rad'],
                           vals=Anything())

        # so we have radius, theta and phi in buffer
        self.rtp.get()

        self.add_parameter('radius',
                           get_cmd=self._get_r,
                           set_cmd=self._set_r,
                           units='|B|')
        self.add_parameter('theta',
                           get_cmd=self._get_theta,
                           set_cmd=self._set_theta,
                           units='rad')
        self.add_parameter('phi',
                           get_cmd=self._get_phi,
                           set_cmd=self._set_phi,
                           units='rad')

        for ax in self.axes:
            self.add_parameter(ax.lower() + '_fld',
                               get_cmd=partial(self._get_fld, ax, 'FLD'),
                               set_cmd=partial(self._ramp_to_setpoint, ax,
                                               'FSET'),
                               label='B' + ax.lower(),
                               units='T')
            self.add_parameter(ax.lower() + '_fldC',
                               get_cmd=partial(self._get_fld, ax, 'CURR'),
                               set_cmd=partial(self._ramp_to_setpoint, ax,
                                               'CSET'),
                               label='B' + ax.lower(),
                               units='T')
            self.add_parameter(ax.lower() + '_fld_wait',
                               get_cmd=partial(self._get_fld, ax, 'CURR'),
                               set_cmd=partial(self._ramp_to_setpoint_and_wait,
                                               ax, 'CSET'),
                               label='B' + ax.lower(),
                               units='T')
            self.add_parameter(ax.lower() + '_ACTN',
                               get_cmd=partial(
                                   self._get_cmd,
                                   'READ:DEV:GRP' + ax + ':PSU:ACTN?'),
                               set_cmd='SET:DEV:GRP' + ax + ':PSU:ACTN:{}',
                               vals=Enum('HOLD', 'RTOS', 'RTOZ', 'CLMP'))
            self.add_parameter(ax.lower() + '_setpoint',
                               get_cmd=partial(self._get_fld, ax, 'FSET'),
                               set_cmd=partial(self._set_fld, ax, 'FSET'),
                               units='T')
            self.add_parameter(ax.lower() + '_setpointC',
                               get_cmd=partial(self._get_fld, ax, 'CSET'),
                               set_cmd=partial(self._set_fld, ax, 'CSET'),
                               units='T')
            self.add_parameter(ax.lower() + '_rate',
                               get_cmd=partial(self._get_fld, ax, 'RFST'),
                               set_cmd=partial(self._set_fld, ax, 'RFST'),
                               units='T/m')
            self.add_parameter(ax.lower() + '_rateC',
                               get_cmd=partial(self._get_fld, ax, 'RCST'),
                               set_cmd=partial(self._set_fld, ax, 'RCST'),
                               units='T/m')

            self.connect_message()
Exemple #11
0
def test_failed_anything():
    with pytest.raises(TypeError):
        Anything(1)

    with pytest.raises(TypeError):
        Anything(values=[1, 2, 3])
Exemple #12
0
    def __init__(self, name: str, instrument_x: Union[AMI430, str],
                 instrument_y: Union[AMI430, str], instrument_z: Union[AMI430,
                                                                       str],
                 field_limit: Union[numbers.Real,
                                    Iterable[CartesianFieldLimitFunction]],
                 **kwargs: Any):
        super().__init__(name, **kwargs)

        if not isinstance(name, str):
            raise ValueError("Name should be a string")

        for instrument, arg_name in zip(
            (instrument_x, instrument_y, instrument_z),
            ("instrument_x", "instrument_y", "instrument_z"),
        ):
            if not isinstance(instrument, (AMI430, str)):
                raise ValueError(
                    f"Instruments need to be instances of the class AMI430 "
                    f"or be valid names of already instantiated instances "
                    f"of AMI430 class; {arg_name} argument is "
                    f"neither of those")

        def find_ami430_with_name(ami430_name: str) -> AMI430:
            found_ami430 = AMI430.find_instrument(name=ami430_name,
                                                  instrument_class=AMI430)
            return cast(AMI430, found_ami430)

        self._instrument_x = (instrument_x if isinstance(instrument_x, AMI430)
                              else find_ami430_with_name(instrument_x))
        self._instrument_y = (instrument_y if isinstance(instrument_y, AMI430)
                              else find_ami430_with_name(instrument_y))
        self._instrument_z = (instrument_z if isinstance(instrument_z, AMI430)
                              else find_ami430_with_name(instrument_z))

        self._field_limit: Union[float, Iterable[CartesianFieldLimitFunction]]
        if isinstance(field_limit, collections.abc.Iterable):
            self._field_limit = field_limit
        elif isinstance(field_limit, numbers.Real):
            # Conversion to float makes related driver logic simpler
            self._field_limit = float(field_limit)
        else:
            raise ValueError("field limit should either be a number or "
                             "an iterable of callable field limit functions.")

        self._set_point = FieldVector(x=self._instrument_x.field(),
                                      y=self._instrument_y.field(),
                                      z=self._instrument_z.field())

        # Get-only parameters that return a measured value
        self.add_parameter('cartesian_measured',
                           get_cmd=partial(self._get_measured, 'x', 'y', 'z'),
                           unit='T')

        self.add_parameter('x_measured',
                           get_cmd=partial(self._get_measured, 'x'),
                           unit='T')

        self.add_parameter('y_measured',
                           get_cmd=partial(self._get_measured, 'y'),
                           unit='T')

        self.add_parameter('z_measured',
                           get_cmd=partial(self._get_measured, 'z'),
                           unit='T')

        self.add_parameter('spherical_measured',
                           get_cmd=partial(self._get_measured, 'r', 'theta',
                                           'phi'),
                           unit='T')

        self.add_parameter('phi_measured',
                           get_cmd=partial(self._get_measured, 'phi'),
                           unit='deg')

        self.add_parameter('theta_measured',
                           get_cmd=partial(self._get_measured, 'theta'),
                           unit='deg')

        self.add_parameter('field_measured',
                           get_cmd=partial(self._get_measured, 'r'),
                           unit='T')

        self.add_parameter('cylindrical_measured',
                           get_cmd=partial(self._get_measured, 'rho', 'phi',
                                           'z'),
                           unit='T')

        self.add_parameter('rho_measured',
                           get_cmd=partial(self._get_measured, 'rho'),
                           unit='T')

        # Get and set parameters for the set points of the coordinates
        self.add_parameter('cartesian',
                           get_cmd=partial(self._get_setpoints,
                                           ('x', 'y', 'z')),
                           set_cmd=partial(self._set_setpoints,
                                           ('x', 'y', 'z')),
                           unit='T',
                           vals=Anything())

        self.add_parameter('x',
                           get_cmd=partial(self._get_setpoints, ('x', )),
                           set_cmd=partial(self._set_setpoints, ('x', )),
                           unit='T',
                           vals=Numbers())

        self.add_parameter('y',
                           get_cmd=partial(self._get_setpoints, ('y', )),
                           set_cmd=partial(self._set_setpoints, ('y', )),
                           unit='T',
                           vals=Numbers())

        self.add_parameter('z',
                           get_cmd=partial(self._get_setpoints, ('z', )),
                           set_cmd=partial(self._set_setpoints, ('z', )),
                           unit='T',
                           vals=Numbers())

        self.add_parameter('spherical',
                           get_cmd=partial(self._get_setpoints,
                                           ('r', 'theta', 'phi')),
                           set_cmd=partial(self._set_setpoints,
                                           ('r', 'theta', 'phi')),
                           unit='tuple?',
                           vals=Anything())

        self.add_parameter('phi',
                           get_cmd=partial(self._get_setpoints, ('phi', )),
                           set_cmd=partial(self._set_setpoints, ('phi', )),
                           unit='deg',
                           vals=Numbers())

        self.add_parameter('theta',
                           get_cmd=partial(self._get_setpoints, ('theta', )),
                           set_cmd=partial(self._set_setpoints, ('theta', )),
                           unit='deg',
                           vals=Numbers())

        self.add_parameter('field',
                           get_cmd=partial(self._get_setpoints, ('r', )),
                           set_cmd=partial(self._set_setpoints, ('r', )),
                           unit='T',
                           vals=Numbers())

        self.add_parameter('cylindrical',
                           get_cmd=partial(self._get_setpoints,
                                           ('rho', 'phi', 'z')),
                           set_cmd=partial(self._set_setpoints,
                                           ('rho', 'phi', 'z')),
                           unit='tuple?',
                           vals=Anything())

        self.add_parameter('rho',
                           get_cmd=partial(self._get_setpoints, ('rho', )),
                           set_cmd=partial(self._set_setpoints, ('rho', )),
                           unit='T',
                           vals=Numbers())

        self.add_parameter('block_during_ramp',
                           set_cmd=None,
                           initial_value=True,
                           unit='',
                           vals=Bool())
    def __init__(self,
                 name=None,
                 names=None,
                 label=None,
                 labels=None,
                 units=None,
                 shape=None,
                 shapes=None,
                 setpoints=None,
                 setpoint_names=None,
                 setpoint_labels=None,
                 vals=None,
                 docstring=None,
                 snapshot_get=True,
                 **kwargs):
        super().__init__(**kwargs)
        self._snapshot_get = snapshot_get

        self.has_get = hasattr(self, 'get')
        self.has_set = hasattr(self, 'set')
        self._meta_attrs = ['setpoint_names', 'setpoint_labels']

        # always let the parameter have a single name (in fact, require this!)
        # even if it has names too
        self.name = str(name)

        if names is not None:
            # check for names first - that way you can provide both name
            # AND names for instrument parameters - name is how you get the
            # object (from the parameters dict or the delegated attributes),
            # and names are the items it returns
            self.names = names
            self.labels = names if labels is None else names
            self.units = units if units is not None else [''] * len(names)

            self.set_validator(vals or Anything())
            self.__doc__ = os.linesep.join(
                ('Parameter class:', '* `names` %s' % ', '.join(self.names),
                 '* `labels` %s' % ', '.join(self.labels),
                 '* `units` %s' % ', '.join(self.units)))
            self._meta_attrs.extend(['names', 'labels', 'units'])

        elif name is not None:
            self.label = name if label is None else label
            self.units = units if units is not None else ''

            # vals / validate only applies to simple single-value parameters
            self.set_validator(vals)

            # generate default docstring
            self.__doc__ = os.linesep.join((
                'Parameter class:',
                '* `name` %s' % self.name,
                '* `label` %s' % self.label,
                # TODO is this unit s a typo? shouldnt that be unit?
                '* `units` %s' % self.units,
                '* `vals` %s' % repr(self._vals)))
            self._meta_attrs.extend(['name', 'label', 'units', 'vals'])

        else:
            raise ValueError('either name or names is required')

        if shape is not None or shapes is not None:
            nt = type(None)

            if shape is not None:
                if not is_sequence_of(shape, int):
                    raise ValueError('shape must be a tuple of ints, not ' +
                                     repr(shape))
                self.shape = shape
                depth = 1
                container_str = 'tuple'
            else:
                if not is_sequence_of(shapes, int, depth=2):
                    raise ValueError('shapes must be a tuple of tuples '
                                     'of ints, not ' + repr(shape))
                self.shapes = shapes
                depth = 2
                container_str = 'tuple of tuples'

            sp_types = (nt, DataArray, collections.Sequence,
                        collections.Iterator)
            if (setpoints is not None
                    and not is_sequence_of(setpoints, sp_types, depth)):
                raise ValueError(
                    'setpoints must be a {} of arrays'.format(container_str))
            if (setpoint_names is not None
                    and not is_sequence_of(setpoint_names, (nt, str), depth)):
                raise ValueError('setpoint_names must be a {} '
                                 'of strings'.format(container_str))
            if (setpoint_labels is not None
                    and not is_sequence_of(setpoint_labels, (nt, str), depth)):
                raise ValueError('setpoint_labels must be a {} '
                                 'of strings'.format(container_str))

            self.setpoints = setpoints
            self.setpoint_names = setpoint_names
            self.setpoint_labels = setpoint_labels

        # record of latest value and when it was set or measured
        # what exactly this means is different for different subclasses
        # but they all use the same attributes so snapshot is consistent.
        self._latest_value = None
        self._latest_ts = None

        if docstring is not None:
            self.__doc__ = docstring + os.linesep + self.__doc__

        self.get_latest = GetLatest(self)
Exemple #14
0
    def __init__(
        self,
        name: str,
        instrument_x: Union[AMI430, str],
        instrument_y: Union[AMI430, str],
        instrument_z: Union[AMI430, str],
        field_limit: Union[numbers.Real,
                           Iterable[CartesianFieldLimitFunction]],
        **kwargs: Any,
    ):
        """
        Driver for controlling three American Magnetics Model 430 magnet power
        supplies simultaneously for setting magnetic field vectors.

        The individual magnet power supplies can be passed in as either
        instances of AMI430 driver or as names of existing AMI430 instances.
        In the latter case, the instances will be found via the passed names.

        Args:
            name: a name for the instrument
            instrument_x: AMI430 instance or a names of existing AMI430
                instance for controlling the X axis of magnetic field
            instrument_y: AMI430 instance or a names of existing AMI430
                instance for controlling the Y axis of magnetic field
            instrument_z: AMI430 instance or a names of existing AMI430
                instance for controlling the Z axis of magnetic field
            field_limit: a number for maximum allows magnetic field or an
                iterable of callable field limit functions that define
                region(s) of allowed values in 3D magnetic field space
        """
        super().__init__(name, **kwargs)

        if not isinstance(name, str):
            raise ValueError("Name should be a string")

        for instrument, arg_name in zip(
            (instrument_x, instrument_y, instrument_z),
            ("instrument_x", "instrument_y", "instrument_z"),
        ):
            if not isinstance(instrument, (AMI430, str)):
                raise ValueError(
                    f"Instruments need to be instances of the class AMI430 "
                    f"or be valid names of already instantiated instances "
                    f"of AMI430 class; {arg_name} argument is "
                    f"neither of those")

        def find_ami430_with_name(ami430_name: str) -> AMI430:
            found_ami430 = AMI430.find_instrument(name=ami430_name,
                                                  instrument_class=AMI430)
            return found_ami430

        self._instrument_x = (instrument_x if isinstance(instrument_x, AMI430)
                              else find_ami430_with_name(instrument_x))
        self._instrument_y = (instrument_y if isinstance(instrument_y, AMI430)
                              else find_ami430_with_name(instrument_y))
        self._instrument_z = (instrument_z if isinstance(instrument_z, AMI430)
                              else find_ami430_with_name(instrument_z))

        self._field_limit: Union[float, Iterable[CartesianFieldLimitFunction]]
        if isinstance(field_limit, collections.abc.Iterable):
            self._field_limit = field_limit
        elif isinstance(field_limit, numbers.Real):
            # Conversion to float makes related driver logic simpler
            self._field_limit = float(field_limit)
        else:
            raise ValueError("field limit should either be a number or "
                             "an iterable of callable field limit functions.")

        self._set_point = FieldVector(
            x=self._instrument_x.field(),
            y=self._instrument_y.field(),
            z=self._instrument_z.field(),
        )

        # Get-only parameters that return a measured value
        self.add_parameter(
            "cartesian_measured",
            get_cmd=partial(self._get_measured, "x", "y", "z"),
            unit="T",
        )

        self.add_parameter("x_measured",
                           get_cmd=partial(self._get_measured, "x"),
                           unit="T")

        self.add_parameter("y_measured",
                           get_cmd=partial(self._get_measured, "y"),
                           unit="T")

        self.add_parameter("z_measured",
                           get_cmd=partial(self._get_measured, "z"),
                           unit="T")

        self.add_parameter(
            "spherical_measured",
            get_cmd=partial(self._get_measured, "r", "theta", "phi"),
            unit="T",
        )

        self.add_parameter("phi_measured",
                           get_cmd=partial(self._get_measured, "phi"),
                           unit="deg")

        self.add_parameter("theta_measured",
                           get_cmd=partial(self._get_measured, "theta"),
                           unit="deg")

        self.add_parameter("field_measured",
                           get_cmd=partial(self._get_measured, "r"),
                           unit="T")

        self.add_parameter(
            "cylindrical_measured",
            get_cmd=partial(self._get_measured, "rho", "phi", "z"),
            unit="T",
        )

        self.add_parameter("rho_measured",
                           get_cmd=partial(self._get_measured, "rho"),
                           unit="T")

        # Get and set parameters for the set points of the coordinates
        self.add_parameter(
            "cartesian",
            get_cmd=partial(self._get_setpoints, ("x", "y", "z")),
            set_cmd=partial(self._set_setpoints, ("x", "y", "z")),
            unit="T",
            vals=Anything(),
        )

        self.add_parameter(
            "x",
            get_cmd=partial(self._get_setpoints, ("x", )),
            set_cmd=partial(self._set_setpoints, ("x", )),
            unit="T",
            vals=Numbers(),
        )

        self.add_parameter(
            "y",
            get_cmd=partial(self._get_setpoints, ("y", )),
            set_cmd=partial(self._set_setpoints, ("y", )),
            unit="T",
            vals=Numbers(),
        )

        self.add_parameter(
            "z",
            get_cmd=partial(self._get_setpoints, ("z", )),
            set_cmd=partial(self._set_setpoints, ("z", )),
            unit="T",
            vals=Numbers(),
        )

        self.add_parameter(
            "spherical",
            get_cmd=partial(self._get_setpoints, ("r", "theta", "phi")),
            set_cmd=partial(self._set_setpoints, ("r", "theta", "phi")),
            unit="tuple?",
            vals=Anything(),
        )

        self.add_parameter(
            "phi",
            get_cmd=partial(self._get_setpoints, ("phi", )),
            set_cmd=partial(self._set_setpoints, ("phi", )),
            unit="deg",
            vals=Numbers(),
        )

        self.add_parameter(
            "theta",
            get_cmd=partial(self._get_setpoints, ("theta", )),
            set_cmd=partial(self._set_setpoints, ("theta", )),
            unit="deg",
            vals=Numbers(),
        )

        self.add_parameter(
            "field",
            get_cmd=partial(self._get_setpoints, ("r", )),
            set_cmd=partial(self._set_setpoints, ("r", )),
            unit="T",
            vals=Numbers(),
        )

        self.add_parameter(
            "cylindrical",
            get_cmd=partial(self._get_setpoints, ("rho", "phi", "z")),
            set_cmd=partial(self._set_setpoints, ("rho", "phi", "z")),
            unit="tuple?",
            vals=Anything(),
        )

        self.add_parameter(
            "rho",
            get_cmd=partial(self._get_setpoints, ("rho", )),
            set_cmd=partial(self._set_setpoints, ("rho", )),
            unit="T",
            vals=Numbers(),
        )

        self.add_parameter("block_during_ramp",
                           set_cmd=None,
                           initial_value=True,
                           unit="",
                           vals=Bool())

        self.ramp_mode = Parameter(
            name="ramp_mode",
            instrument=self,
            get_cmd=None,
            set_cmd=None,
            vals=Enum("default", "simultaneous"),
            initial_value="default",
        )

        self.ramping_state_check_interval = Parameter(
            name="ramping_state_check_interval",
            instrument=self,
            initial_value=0.05,
            unit="s",
            vals=Numbers(0, 10),
            set_cmd=None,
            get_cmd=None,
        )

        self.vector_ramp_rate = Parameter(
            name="vector_ramp_rate",
            instrument=self,
            unit="T/s",
            vals=Numbers(min_value=0.0),
            set_cmd=None,
            get_cmd=None,
            set_parser=self._set_vector_ramp_rate_units,
            docstring="Ramp rate along a line (vector) in 3D space. Only active"
            " if `ramp_mode='simultaneous'`.",
        )
        """Ramp rate along a line (vector) in 3D field space"""
    def test_failed_anything(self):
        with self.assertRaises(TypeError):
            Anything(1)

        with self.assertRaises(TypeError):
            Anything(values=[1, 2, 3])
Exemple #16
0
    def __init__(self, name, instrument_x, instrument_y, instrument_z,
                 field_limit, **kwargs):
        super().__init__(name, **kwargs)

        if not isinstance(name, str):
            raise ValueError("Name should be a string")

        instruments = [instrument_x, instrument_y, instrument_z]

        if not all(
            [isinstance(instrument, AMI430) for instrument in instruments]):
            raise ValueError("Instruments need to be instances "
                             "of the class AMI430")

        self._instrument_x = instrument_x
        self._instrument_y = instrument_y
        self._instrument_z = instrument_z

        if repr(field_limit).isnumeric() or isinstance(field_limit,
                                                       collections.Iterable):
            self._field_limit = field_limit
        else:
            raise ValueError("field limit should either be"
                             " a number or an iterable")

        self._set_point = FieldVector(x=self._instrument_x.field(),
                                      y=self._instrument_y.field(),
                                      z=self._instrument_z.field())

        # Get-only parameters that return a measured value
        self.add_parameter('cartesian_measured',
                           get_cmd=partial(self._get_measured, 'x', 'y', 'z'),
                           unit='T')

        self.add_parameter('x_measured',
                           get_cmd=partial(self._get_measured, 'x'),
                           unit='T')

        self.add_parameter('y_measured',
                           get_cmd=partial(self._get_measured, 'y'),
                           unit='T')

        self.add_parameter('z_measured',
                           get_cmd=partial(self._get_measured, 'z'),
                           unit='T')

        self.add_parameter('spherical_measured',
                           get_cmd=partial(self._get_measured, 'r', 'theta',
                                           'phi'),
                           unit='T')

        self.add_parameter('phi_measured',
                           get_cmd=partial(self._get_measured, 'phi'),
                           unit='deg')

        self.add_parameter('theta_measured',
                           get_cmd=partial(self._get_measured, 'theta'),
                           unit='deg')

        self.add_parameter('field_measured',
                           get_cmd=partial(self._get_measured, 'r'),
                           unit='T')

        self.add_parameter('cylindrical_measured',
                           get_cmd=partial(self._get_measured, 'rho', 'phi',
                                           'z'),
                           unit='T')

        self.add_parameter('rho_measured',
                           get_cmd=partial(self._get_measured, 'rho'),
                           unit='T')

        # Get and set parameters for the set points of the coordinates
        self.add_parameter('cartesian',
                           get_cmd=partial(self._get_setpoints, 'x', 'y', 'z'),
                           set_cmd=self._set_cartesian,
                           unit='T',
                           vals=Anything())

        self.add_parameter('x',
                           get_cmd=partial(self._get_setpoints, 'x'),
                           set_cmd=self._set_x,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('y',
                           get_cmd=partial(self._get_setpoints, 'y'),
                           set_cmd=self._set_y,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('z',
                           get_cmd=partial(self._get_setpoints, 'z'),
                           set_cmd=self._set_z,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('spherical',
                           get_cmd=partial(self._get_setpoints, 'r', 'theta',
                                           'phi'),
                           set_cmd=self._set_spherical,
                           unit='tuple?',
                           vals=Anything())

        self.add_parameter('phi',
                           get_cmd=partial(self._get_setpoints, 'phi'),
                           set_cmd=self._set_phi,
                           unit='deg',
                           vals=Numbers())

        self.add_parameter('theta',
                           get_cmd=partial(self._get_setpoints, 'theta'),
                           set_cmd=self._set_theta,
                           unit='deg',
                           vals=Numbers())

        self.add_parameter('field',
                           get_cmd=partial(self._get_setpoints, 'r'),
                           set_cmd=self._set_r,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('cylindrical',
                           get_cmd=partial(self._get_setpoints, 'rho', 'phi',
                                           'z'),
                           set_cmd=self._set_cylindrical,
                           unit='tuple?',
                           vals=Anything())

        self.add_parameter('rho',
                           get_cmd=partial(self._get_setpoints, 'rho'),
                           set_cmd=self._set_rho,
                           unit='T',
                           vals=Numbers())
Exemple #17
0
    def __init__(self,
                 name: str,
                 instrument_x: Union[AMI430, str],
                 instrument_y: Union[AMI430, str],
                 instrument_z: Union[AMI430, str],
                 field_limit: Union[numbers.Real,
                                    Iterable[CartesianFieldLimitFunction]],
                 **kwargs: Any):
        """
        Driver for controlling three American Magnetics Model 430 magnet power
        supplies simultaneously for setting magnetic field vectors.

        The individual magnet power supplies can be passed in as either
        instances of AMI430 driver or as names of existing AMI430 instances.
        In the latter case, the instances will be found via the passed names.

        Args:
            name: a name for the instrument
            instrument_x: AMI430 instance or a names of existing AMI430
                instance for controlling the X axis of magnetic field
            instrument_y: AMI430 instance or a names of existing AMI430
                instance for controlling the Y axis of magnetic field
            instrument_z: AMI430 instance or a names of existing AMI430
                instance for controlling the Z axis of magnetic field
            field_limit: a number for maximum allows magnetic field or an
                iterable of callable field limit functions that define
                region(s) of allowed values in 3D magnetic field space
        """
        super().__init__(name, **kwargs)

        if not isinstance(name, str):
            raise ValueError("Name should be a string")

        for instrument, arg_name in zip(
                (instrument_x, instrument_y, instrument_z),
                ("instrument_x", "instrument_y", "instrument_z"),
        ):
            if not isinstance(instrument, (AMI430, str)):
                raise ValueError(
                    f"Instruments need to be instances of the class AMI430 "
                    f"or be valid names of already instantiated instances "
                    f"of AMI430 class; {arg_name} argument is "
                    f"neither of those"
                )

        def find_ami430_with_name(ami430_name: str) -> AMI430:
            found_ami430 = AMI430.find_instrument(
                name=ami430_name, instrument_class=AMI430
            )
            return cast(AMI430, found_ami430)

        self._instrument_x = (
            instrument_x if isinstance(instrument_x, AMI430)
            else find_ami430_with_name(instrument_x)
        )
        self._instrument_y = (
            instrument_y if isinstance(instrument_y, AMI430)
            else find_ami430_with_name(instrument_y)
        )
        self._instrument_z = (
            instrument_z if isinstance(instrument_z, AMI430)
            else find_ami430_with_name(instrument_z)
        )

        self._field_limit: Union[float, Iterable[CartesianFieldLimitFunction]]
        if isinstance(field_limit, collections.abc.Iterable):
            self._field_limit = field_limit
        elif isinstance(field_limit, numbers.Real):
            # Conversion to float makes related driver logic simpler
            self._field_limit = float(field_limit)
        else:
            raise ValueError("field limit should either be a number or "
                             "an iterable of callable field limit functions.")

        self._set_point = FieldVector(
            x=self._instrument_x.field(),
            y=self._instrument_y.field(),
            z=self._instrument_z.field()
        )

        # Get-only parameters that return a measured value
        self.add_parameter(
            'cartesian_measured',
            get_cmd=partial(self._get_measured, 'x', 'y', 'z'),
            unit='T'
        )

        self.add_parameter(
            'x_measured',
            get_cmd=partial(self._get_measured, 'x'),
            unit='T'
        )

        self.add_parameter(
            'y_measured',
            get_cmd=partial(self._get_measured, 'y'),
            unit='T'
        )

        self.add_parameter(
            'z_measured',
            get_cmd=partial(self._get_measured, 'z'),
            unit='T'
        )

        self.add_parameter(
            'spherical_measured',
            get_cmd=partial(
                self._get_measured,
                'r',
                'theta',
                'phi'
            ),
            unit='T'
        )

        self.add_parameter(
            'phi_measured',
            get_cmd=partial(self._get_measured, 'phi'),
            unit='deg'
        )

        self.add_parameter(
            'theta_measured',
            get_cmd=partial(self._get_measured, 'theta'),
            unit='deg'
        )

        self.add_parameter(
            'field_measured',
            get_cmd=partial(self._get_measured, 'r'),
            unit='T')

        self.add_parameter(
            'cylindrical_measured',
            get_cmd=partial(self._get_measured,
                            'rho',
                            'phi',
                            'z'),
            unit='T')

        self.add_parameter(
            'rho_measured',
            get_cmd=partial(self._get_measured, 'rho'),
            unit='T'
        )

        # Get and set parameters for the set points of the coordinates
        self.add_parameter(
            'cartesian',
            get_cmd=partial(self._get_setpoints, ('x', 'y', 'z')),
            set_cmd=partial(self._set_setpoints, ('x', 'y', 'z')),
            unit='T',
            vals=Anything()
        )

        self.add_parameter(
            'x',
            get_cmd=partial(self._get_setpoints, ('x',)),
            set_cmd=partial(self._set_setpoints, ('x',)),
            unit='T',
            vals=Numbers()
        )

        self.add_parameter(
            'y',
            get_cmd=partial(self._get_setpoints, ('y',)),
            set_cmd=partial(self._set_setpoints, ('y',)),
            unit='T',
            vals=Numbers()
        )

        self.add_parameter(
            'z',
            get_cmd=partial(self._get_setpoints, ('z',)),
            set_cmd=partial(self._set_setpoints, ('z',)),
            unit='T',
            vals=Numbers()
        )

        self.add_parameter(
            'spherical',
            get_cmd=partial(
                self._get_setpoints, ('r', 'theta', 'phi')
            ),
            set_cmd=partial(
                self._set_setpoints, ('r', 'theta', 'phi')
            ),
            unit='tuple?',
            vals=Anything()
        )

        self.add_parameter(
            'phi',
            get_cmd=partial(self._get_setpoints, ('phi',)),
            set_cmd=partial(self._set_setpoints, ('phi',)),
            unit='deg',
            vals=Numbers()
        )

        self.add_parameter(
            'theta',
            get_cmd=partial(self._get_setpoints, ('theta',)),
            set_cmd=partial(self._set_setpoints, ('theta',)),
            unit='deg',
            vals=Numbers()
        )

        self.add_parameter(
            'field',
            get_cmd=partial(self._get_setpoints, ('r',)),
            set_cmd=partial(self._set_setpoints, ('r',)),
            unit='T',
            vals=Numbers()
        )

        self.add_parameter(
            'cylindrical',
            get_cmd=partial(
                self._get_setpoints, ('rho', 'phi', 'z')
            ),
            set_cmd=partial(
                self._set_setpoints, ('rho', 'phi', 'z')
            ),
            unit='tuple?',
            vals=Anything()
        )

        self.add_parameter(
            'rho',
            get_cmd=partial(self._get_setpoints, ('rho',)),
            set_cmd=partial(self._set_setpoints, ('rho',)),
            unit='T',
            vals=Numbers()
        )

        self.add_parameter(
            'block_during_ramp',
            set_cmd=None,
            initial_value=True,
            unit='',
            vals=Bool()
        )
Exemple #18
0
    def __init__(self,
                 name: str,
                 instrument_x: AMI430,
                 instrument_y: AMI430,
                 instrument_z: AMI430,
                 field_limit: Union[numbers.Real,
                                    Iterable[CartesianFieldLimitFunction]],
                 **kwargs: Any):
        super().__init__(name, **kwargs)

        if not isinstance(name, str):
            raise ValueError("Name should be a string")

        instruments = [instrument_x, instrument_y, instrument_z]

        if not all([isinstance(instrument, AMI430)
                    for instrument in instruments]):
            raise ValueError("Instruments need to be instances "
                             "of the class AMI430")

        self._instrument_x = instrument_x
        self._instrument_y = instrument_y
        self._instrument_z = instrument_z

        self._field_limit: Union[float, Iterable[CartesianFieldLimitFunction]]
        if isinstance(field_limit, collections.abc.Iterable):
            self._field_limit = field_limit
        elif isinstance(field_limit, numbers.Real):
            # Conversion to float makes related driver logic simpler
            self._field_limit = float(field_limit)
        else:
            raise ValueError("field limit should either be a number or "
                             "an iterable of callable field limit functions.")

        self._set_point = FieldVector(
            x=self._instrument_x.field(),
            y=self._instrument_y.field(),
            z=self._instrument_z.field()
        )

        # Get-only parameters that return a measured value
        self.add_parameter(
            'cartesian_measured',
            get_cmd=partial(self._get_measured, 'x', 'y', 'z'),
            unit='T'
        )

        self.add_parameter(
            'x_measured',
            get_cmd=partial(self._get_measured, 'x'),
            unit='T'
        )

        self.add_parameter(
            'y_measured',
            get_cmd=partial(self._get_measured, 'y'),
            unit='T'
        )

        self.add_parameter(
            'z_measured',
            get_cmd=partial(self._get_measured, 'z'),
            unit='T'
        )

        self.add_parameter(
            'spherical_measured',
            get_cmd=partial(
                self._get_measured,
                'r',
                'theta',
                'phi'
            ),
            unit='T'
        )

        self.add_parameter(
            'phi_measured',
            get_cmd=partial(self._get_measured, 'phi'),
            unit='deg'
        )

        self.add_parameter(
            'theta_measured',
            get_cmd=partial(self._get_measured, 'theta'),
            unit='deg'
        )

        self.add_parameter(
            'field_measured',
            get_cmd=partial(self._get_measured, 'r'),
            unit='T')

        self.add_parameter(
            'cylindrical_measured',
            get_cmd=partial(self._get_measured,
                            'rho',
                            'phi',
                            'z'),
            unit='T')

        self.add_parameter(
            'rho_measured',
            get_cmd=partial(self._get_measured, 'rho'),
            unit='T'
        )

        # Get and set parameters for the set points of the coordinates
        self.add_parameter(
            'cartesian',
            get_cmd=partial(self._get_setpoints, ('x', 'y', 'z')),
            set_cmd=partial(self._set_setpoints, ('x', 'y', 'z')),
            unit='T',
            vals=Anything()
        )

        self.add_parameter(
            'x',
            get_cmd=partial(self._get_setpoints, ('x',)),
            set_cmd=partial(self._set_setpoints, ('x',)),
            unit='T',
            vals=Numbers()
        )

        self.add_parameter(
            'y',
            get_cmd=partial(self._get_setpoints, ('y',)),
            set_cmd=partial(self._set_setpoints, ('y',)),
            unit='T',
            vals=Numbers()
        )

        self.add_parameter(
            'z',
            get_cmd=partial(self._get_setpoints, ('z',)),
            set_cmd=partial(self._set_setpoints, ('z',)),
            unit='T',
            vals=Numbers()
        )

        self.add_parameter(
            'spherical',
            get_cmd=partial(
                self._get_setpoints, ('r', 'theta', 'phi')
            ),
            set_cmd=partial(
                self._set_setpoints, ('r', 'theta', 'phi')
            ),
            unit='tuple?',
            vals=Anything()
        )

        self.add_parameter(
            'phi',
            get_cmd=partial(self._get_setpoints, ('phi',)),
            set_cmd=partial(self._set_setpoints, ('phi',)),
            unit='deg',
            vals=Numbers()
        )

        self.add_parameter(
            'theta',
            get_cmd=partial(self._get_setpoints, ('theta',)),
            set_cmd=partial(self._set_setpoints, ('theta',)),
            unit='deg',
            vals=Numbers()
        )

        self.add_parameter(
            'field',
            get_cmd=partial(self._get_setpoints, ('r',)),
            set_cmd=partial(self._set_setpoints, ('r',)),
            unit='T',
            vals=Numbers()
        )

        self.add_parameter(
            'cylindrical',
            get_cmd=partial(
                self._get_setpoints, ('rho', 'phi', 'z')
            ),
            set_cmd=partial(
                self._set_setpoints, ('rho', 'phi', 'z')
            ),
            unit='tuple?',
            vals=Anything()
        )

        self.add_parameter(
            'rho',
            get_cmd=partial(self._get_setpoints, ('rho',)),
            set_cmd=partial(self._set_setpoints, ('rho',)),
            unit='T',
            vals=Numbers()
        )

        self.add_parameter(
            'block_during_ramp',
            set_cmd=None,
            initial_value=True,
            unit='',
            vals=Bool()
        )
Exemple #19
0
    def __init__(self, name, magnet_x, magnet_y, magnet_z, field_limit,
                 **kwargs):
        super().__init__(name, **kwargs)

        # Register this instrument as the parent of the individual magnets
        for m in [magnet_x, magnet_y, magnet_z]:
            m._parent_instrument = self

        self._magnet_x = magnet_x
        self._magnet_y = magnet_y
        self._magnet_z = magnet_z

        # Make this into a parameter?
        self._field_limit = field_limit

        # Initialize the internal magnet field setpoints
        self.update_internal_setpoints()

        # Get-only parameters that return a measured value
        self.add_parameter('cartesian_measured',
                           get_cmd=partial(self._get_measured, 'x', 'y', 'z'),
                           unit='T')

        self.add_parameter('x_measured',
                           get_cmd=partial(self._get_measured, 'x'),
                           unit='T')

        self.add_parameter('y_measured',
                           get_cmd=partial(self._get_measured, 'y'),
                           unit='T')

        self.add_parameter('z_measured',
                           get_cmd=partial(self._get_measured, 'z'),
                           unit='T')

        self.add_parameter('spherical_measured',
                           get_cmd=partial(self._get_measured, 'field',
                                           'theta', 'phi'),
                           unit='T')

        self.add_parameter('phi_measured',
                           get_cmd=partial(self._get_measured, 'phi'),
                           unit='deg')

        self.add_parameter('theta_measured',
                           get_cmd=partial(self._get_measured, 'theta'),
                           unit='deg')

        self.add_parameter('field_measured',
                           get_cmd=partial(self._get_measured, 'field'),
                           unit='T')

        self.add_parameter('cylindrical_measured',
                           get_cmd=partial(self._get_measured, 'rho', 'phi',
                                           'z'),
                           unit='T')

        self.add_parameter('rho_measured',
                           get_cmd=partial(self._get_measured, 'rho'),
                           unit='T')

        # Get and set parameters for the setpoints of the coordinates
        self.add_parameter('cartesian',
                           get_cmd=partial(self._get_setpoints, 'x', 'y', 'z'),
                           set_cmd=self._set_fields,
                           unit='T',
                           vals=Anything())

        self.add_parameter('x',
                           get_cmd=partial(self._get_setpoints, 'x'),
                           set_cmd=self._set_x,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('y',
                           get_cmd=partial(self._get_setpoints, 'y'),
                           set_cmd=self._set_y,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('z',
                           get_cmd=partial(self._get_setpoints, 'z'),
                           set_cmd=self._set_z,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('spherical',
                           get_cmd=partial(self._get_setpoints, 'field',
                                           'theta', 'phi'),
                           set_cmd=self._set_spherical,
                           unit='tuple?',
                           vals=Anything())

        self.add_parameter('phi',
                           get_cmd=partial(self._get_setpoints, 'phi'),
                           set_cmd=self._set_phi,
                           unit='deg',
                           vals=Numbers())

        self.add_parameter('theta',
                           get_cmd=partial(self._get_setpoints, 'theta'),
                           set_cmd=self._set_theta,
                           unit='deg',
                           vals=Numbers())

        self.add_parameter('field',
                           get_cmd=partial(self._get_setpoints, 'field'),
                           set_cmd=self._set_field,
                           unit='T',
                           vals=Numbers())

        self.add_parameter('cylindrical',
                           get_cmd=partial(self._get_setpoints, 'rho', 'phi',
                                           'z'),
                           set_cmd=self._set_cylindrical,
                           unit='tuple?',
                           vals=Anything())

        self.add_parameter('rho',
                           get_cmd=partial(self._get_setpoints, 'rho'),
                           set_cmd=self._set_rho,
                           unit='T',
                           vals=Numbers())