示例#1
0
文件: IVVI.py 项目: jatinw21/Qcodes
    def __init__(self,
                 name,
                 address,
                 reset=False,
                 numdacs=16,
                 dac_step=10,
                 dac_delay=.1,
                 dac_max_delay=0.2,
                 safe_version=True,
                 polarity=['BIP', 'BIP', 'BIP', 'BIP'],
                 use_locks=False,
                 **kwargs):
        '''
        Initialzes the IVVI, and communicates with the wrapper

        Args:
            name (string)        : name of the instrument
            address (string)     : ASRL address
            reset (bool)         : resets to default values, default=false
            numdacs (int)        : number of dacs, multiple of 4, default=16
            polarity (string[4]) : list of polarities of each set of 4 dacs
                                   choose from 'BIP', 'POS', 'NEG',
                                   default=['BIP', 'BIP', 'BIP', 'BIP']
            dac_step (float)         : max step size for dac parameter
            dac_delay (float)        : delay (in seconds) for dac
            dac_max_delay (float)    : maximum delay before emitting a warning
            safe_version (bool)    : if True then do not send version commands
                                     to the IVVI controller
            use_locks (bool) : if True then locks are used in the `ask`
                              function of the driver. The IVVI driver is not
                              thread safe, this locking mechanism makes it
                              thread safe at the cost of making the call to ask
                              blocking.
        '''
        t0 = time.time()
        super().__init__(name, address, **kwargs)
        if use_locks:
            self.lock = threading.Lock()
        else:
            self.lock = None

        self.safe_version = safe_version

        if numdacs % 4 == 0 and numdacs > 0:
            self._numdacs = int(numdacs)
        else:
            raise ValueError('numdacs must be a positive multiple of 4, '
                             'not {}'.format(numdacs))

        # values based on descriptor
        self.visa_handle.baud_rate = 115200
        self.visa_handle.parity = visa.constants.Parity(1)  # odd parity
        self.visa_handle.write_termination = ''
        self.visa_handle.read_termination = ''

        self.add_parameter('version', get_cmd=self._get_version)

        self.add_parameter('check_setpoints',
                           parameter_class=ManualParameter,
                           initial_value=False,
                           label='Check setpoints',
                           vals=Bool(),
                           docstring=('Whether to check if the setpoint is the'
                                      ' same as the current DAC value to '
                                      'prevent an unnecessary set command.'))

        # Time to wait before sending a set DAC command to the IVVI
        self.add_parameter('dac_set_sleep',
                           parameter_class=ManualParameter,
                           initial_value=0.05,
                           label='DAC set sleep',
                           unit='s',
                           vals=Numbers(0),
                           docstring=('When check_setpoints is set to True, '
                                      'this is the waiting time between the'
                                      'command that checks the current DAC '
                                      'values and the final set DAC command'))

        # Minimum time to wait before the read buffer contains data
        self.add_parameter('dac_read_buffer_sleep',
                           parameter_class=ManualParameter,
                           initial_value=0.025,
                           label='DAC read buffer sleep',
                           unit='s',
                           vals=Numbers(0),
                           docstring=('While receiving bytes from the IVVI, '
                                      'sleeping is done in multiples of this '
                                      'value. Change to a lower value for '
                                      'a shorter minimum time to wait.'))

        self.add_parameter('dac voltages',
                           label='Dac voltages',
                           get_cmd=self._get_dacs)

        self.add_function('trigger', call_cmd=self._send_trigger)

        # initialize pol_num, the voltage offset due to the polarity
        self.pol_num = np.zeros(self._numdacs)
        for i in range(int(self._numdacs / 4)):
            self.set_pol_dacrack(polarity[i],
                                 np.arange(1 + i * 4, 1 + (i + 1) * 4),
                                 get_all=False)

        for i in range(1, numdacs + 1):
            self.add_parameter('dac{}'.format(i),
                               label='Dac {}'.format(i),
                               unit='mV',
                               get_cmd=self._gen_ch_get_func(self._get_dac, i),
                               set_cmd=self._gen_ch_set_func(self._set_dac, i),
                               vals=vals.Numbers(
                                   self.pol_num[i - 1],
                                   self.pol_num[i - 1] + self.Fullrange),
                               step=dac_step,
                               delay=dac_delay,
                               max_delay=dac_max_delay,
                               max_val_age=10)

        self._update_time = 5  # seconds
        self._time_last_update = 0  # ensures first call will always update

        t1 = time.time()

        # make sure we ignore termination characters
        # See http://www.ni.com/tutorial/4256/en/#toc2 on Termination Character
        # Enabled
        v = self.visa_handle
        v.set_visa_attribute(visa.constants.VI_ATTR_TERMCHAR_EN, 0)
        v.set_visa_attribute(visa.constants.VI_ATTR_ASRL_END_IN, 0)
        v.set_visa_attribute(visa.constants.VI_ATTR_ASRL_END_OUT, 0)
        v.set_visa_attribute(visa.constants.VI_ATTR_SEND_END_EN, 0)

        # basic test to confirm we are properly connected
        try:
            self.get_all()
        except Exception as ex:
            print('IVVI: get_all() failed, maybe connected to wrong port?')
            print(traceback.format_exc())

        print('Initialized IVVI-rack in %.2fs' % (t1 - t0))
示例#2
0
    def __init__(self,
                 name: str,
                 address: str,
                 terminator: str = '\n',
                 **kwargs: Any):
        """
        Create an instance of the instrument.

        Args:
            name: Name of the instrument instance
            address: Visa-resolvable instrument address.
        """
        super().__init__(name, address, terminator=terminator, **kwargs)

        idn = self.IDN.get()

        self.has_firmware_a_02_10_or_above = version.parse(
            convert_legacy_version_to_supported_version(
                idn["firmware"])) >= version.parse(
                    convert_legacy_version_to_supported_version("A.02.10"))

        self.has_option_001 = '001' in self._options()
        self._dc_bias_v_level_range: Union[Numbers, Enum]
        if self.has_option_001:
            self._v_level_range = Numbers(0, 20)
            self._i_level_range = Numbers(0, 0.1)
            self._imp_range = Enum(0.1, 1, 10, 100, 300, 1000, 3000, 10000,
                                   30000, 100000)
            self._dc_bias_v_level_range = Numbers(-40, 40)
        else:
            self._v_level_range = Numbers(0, 2)
            self._i_level_range = Numbers(0, 0.02)
            self._imp_range = Enum(1, 10, 100, 300, 1000, 3000, 10000, 30000,
                                   100000)
            self._dc_bias_v_level_range = Enum(0, 1.5, 2)

        self._measurement_pair = MeasurementPair(
            "CPD", ("capacitance", "dissipation_factor"), ("F", ""))

        self.add_parameter(
            "frequency",
            get_cmd=":FREQuency?",
            set_cmd=":FREQuency {}",
            get_parser=float,
            unit="Hz",
            vals=Numbers(20, 2E6),
            docstring="Gets and sets the frequency for normal measurement.")

        self.add_parameter(
            "current_level",
            get_cmd=self._get_current_level,
            set_cmd=self._set_current_level,
            unit="A",
            vals=self._i_level_range,
            docstring="Gets and sets the current level for measurement signal."
        )

        self.add_parameter(
            "voltage_level",
            get_cmd=self._get_voltage_level,
            set_cmd=self._set_voltage_level,
            unit="V",
            vals=self._v_level_range,
            docstring="Gets and sets the AC bias voltage level for measurement "
            "signal.")

        self.add_parameter("measurement_function",
                           get_cmd=":FUNCtion:IMPedance?",
                           set_cmd=self._set_measurement)

        self.add_parameter(
            "range",
            get_cmd=":FUNCtion:IMPedance:RANGe?",
            set_cmd=self._set_range,
            unit='Ohm',
            vals=self._imp_range,
            docstring="Selects the impedance measurement range, also turns "
            "the auto range function OFF.")

        self.add_parameter(
            "imp_autorange_enabled",
            get_cmd=":FUNCtion:IMPedance:RANGe:AUTO?",
            set_cmd=":FUNCtion:IMPedance:RANGe:AUTO {}",
            val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"),
            docstring="Enables the auto-range for impedance measurement.")

        self.add_parameter(
            "dc_bias_enabled",
            get_cmd=":BIAS:STATe?",
            set_cmd=":BIAS:STATe {}",
            vals=Bool(),
            val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"),
            docstring="Enables DC bias. DC bias is automatically turned "
            "off after recalling the state from memory.")

        self.add_parameter(
            "dc_bias_voltage_level",
            get_cmd=":BIAS:VOLTage:LEVel?",
            set_cmd=":BIAS:VOLTage:LEVel {}",
            get_parser=float,
            unit="V",
            vals=self._dc_bias_v_level_range,
            docstring="Sets the DC bias voltage. Setting does not "
            "implicitly turn the DC bias ON.")

        self.add_parameter("meas_time_mode",
                           val_mapping={
                               "short": "SHOR",
                               "medium": "MED",
                               "long": "LONG"
                           },
                           parameter_class=GroupParameter)

        self.add_parameter("averaging_rate",
                           vals=Ints(1, 256),
                           parameter_class=GroupParameter,
                           get_parser=int,
                           docstring="Averaging rate for the measurement.")

        self._aperture_group = Group(
            [self.meas_time_mode, self.averaging_rate],
            set_cmd=":APERture {meas_time_mode},{averaging_rate}",
            get_cmd=":APERture?")

        if self.has_firmware_a_02_10_or_above:
            self.add_parameter(
                "dc_bias_autorange_enabled",
                get_cmd=":BIAS:RANGe:AUTO?",
                set_cmd=":BIAS:RANGe:AUTO {}",
                vals=Bool(),
                val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"),
                docstring="Enables DC Bias range AUTO setting. When DC bias "
                "range is fixed (not AUTO), '#' is displayed in "
                "the BIAS field of the display.")

        self.add_parameter(
            "signal_mode",
            initial_value=None,
            vals=Enum("Voltage", "Current", None),
            parameter_class=ManualParameter,
            docstring="This parameter tracks the signal mode which is being "
            "set.")

        self.add_submodule("_correction", Correction4980A(self, "correction"))
        self._set_signal_mode_on_driver_initialization()
        self.connect_message()
示例#3
0
def test_valid_bool_values():
    val = Bool()
    for vval in val.valid_values:
        val.validate(vval)
示例#4
0
    def __init__(self,
                 name: str,
                 address: str,
                 terminator: str = "\n",
                 **kwargs: Any) -> None:
        super().__init__(name, address, terminator=terminator, **kwargs)

        self.add_parameter('output',
                           label='Output State',
                           get_cmd=self.state,
                           set_cmd=lambda x: self.on() if x else self.off(),
                           val_mapping={
                               'off': 0,
                               'on': 1,
                           })

        self.add_parameter('source_mode',
                           label='Source Mode',
                           get_cmd=':SOUR:FUNC?',
                           set_cmd=self._set_source_mode,
                           vals=Enum('VOLT', 'CURR'))

        # We need to get the source_mode value here as we cannot rely on the
        # default value that may have been changed before we connect to the
        # instrument (in a previous session or via the frontpanel).
        self.source_mode()

        self.add_parameter('voltage_range',
                           label='Voltage Source Range',
                           unit='V',
                           get_cmd=partial(self._get_range, "VOLT"),
                           set_cmd=partial(self._set_range, "VOLT"),
                           vals=Enum(10e-3, 100e-3, 1e0, 10e0, 30e0),
                           snapshot_exclude=self.source_mode() == 'CURR')

        self.add_parameter('current_range',
                           label='Current Source Range',
                           unit='I',
                           get_cmd=partial(self._get_range, "CURR"),
                           set_cmd=partial(self._set_range, "CURR"),
                           vals=Enum(1e-3, 10e-3, 100e-3, 200e-3),
                           snapshot_exclude=self.source_mode() == "VOLT")

        self.add_parameter('range',
                           parameter_class=DelegateParameter,
                           source=None)

        # The instrument does not support auto range. The parameter
        # auto_range is introduced to add this capability with
        # setting the initial state at False mode.
        self.add_parameter('auto_range',
                           label='Auto Range',
                           set_cmd=self._set_auto_range,
                           get_cmd=None,
                           initial_cache_value=False,
                           vals=Bool())

        self.add_parameter('voltage',
                           label='Voltage',
                           unit='V',
                           set_cmd=partial(self._get_set_output, "VOLT"),
                           get_cmd=partial(self._get_set_output, "VOLT"),
                           snapshot_exclude=self.source_mode() == "CURR")

        self.add_parameter('current',
                           label='Current',
                           unit='I',
                           set_cmd=partial(self._get_set_output, "CURR"),
                           get_cmd=partial(self._get_set_output, "CURR"),
                           snapshot_exclude=self.source_mode() == 'VOLT')

        self.add_parameter('output_level',
                           parameter_class=DelegateParameter,
                           source=None)

        # We need to pass the source parameter for delegate parameters
        # (range and output_level) here according to the present
        # source_mode.
        if self.source_mode() == 'VOLT':
            self.range.source = self.voltage_range
            self.output_level.source = self.voltage
        else:
            self.range.source = self.current_range
            self.output_level.source = self.current

        self.add_parameter('voltage_limit',
                           label='Voltage Protection Limit',
                           unit='V',
                           vals=Ints(1, 30),
                           get_cmd=":SOUR:PROT:VOLT?",
                           set_cmd=":SOUR:PROT:VOLT {}",
                           get_parser=float_round,
                           set_parser=int)

        self.add_parameter('current_limit',
                           label='Current Protection Limit',
                           unit='I',
                           vals=Numbers(1e-3, 200e-3),
                           get_cmd=":SOUR:PROT:CURR?",
                           set_cmd=":SOUR:PROT:CURR {:.3f}",
                           get_parser=float,
                           set_parser=float)

        self.add_parameter('four_wire',
                           label='Four Wire Sensing',
                           get_cmd=':SENS:REM?',
                           set_cmd=':SENS:REM {}',
                           val_mapping={
                               'off': 0,
                               'on': 1,
                           })

        # Note: The guard feature can be used to remove common mode noise.
        # Read the manual to see if you would like to use it
        self.add_parameter('guard',
                           label='Guard Terminal',
                           get_cmd=':SENS:GUAR?',
                           set_cmd=':SENS:GUAR {}',
                           val_mapping={
                               'off': 0,
                               'on': 1
                           })

        # Return measured line frequency
        self.add_parameter("line_freq",
                           label='Line Frequency',
                           unit="Hz",
                           get_cmd="SYST:LFR?",
                           get_parser=int)

        # Check if monitor is present, and if so enable measurement
        monitor_present = '/MON' in self.ask("*OPT?")
        measure = GS200_Monitor(self, 'measure', monitor_present)
        self.add_submodule('measure', measure)

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

        self.add_submodule('program', GS200Program(self, 'program'))

        self.add_parameter("BNC_out",
                           label="BNC trigger out",
                           get_cmd=":ROUT:BNCO?",
                           set_cmd=":ROUT:BNCO {}",
                           vals=Enum("trigger", "output", "ready"),
                           docstring="Sets or queries the output BNC signal")

        self.add_parameter("BNC_in",
                           label="BNC trigger in",
                           get_cmd=":ROUT:BNCI?",
                           set_cmd=":ROUT:BNCI {}",
                           vals=Enum("trigger", "output"),
                           docstring="Sets or queries the input BNC signal")

        self.add_parameter(
            "system_errors",
            get_cmd=":SYSTem:ERRor?",
            docstring="returns the oldest unread error message from the event "
            "log and removes it from the log.")

        self.connect_message()
    def __init__(self, name: str, address: str, **kwargs: Any) -> None:
        super().__init__(name, address, terminator='\n', **kwargs)
        min_freq = 300e3
        max_freq = 20e9
        min_power = -85
        max_power = 10
        nports = 2

        #
        #        #Ports
        #        ports = ChannelList(self, "PNAPorts", PNAPort)
        #        self.add_submodule("ports", ports)
        #        for port_num in range(1, nports+1):
        #            port = PNAPort(self, f"port{port_num}", port_num,
        #                           min_power, max_power)
        #            ports.append(port)
        ##            self.add_submodule(f"port{port_num}", port)
        #        ports.lock()

        # Drive power
        self.add_parameter('power',
                           label='Power',
                           get_cmd='SOUR:POW?',
                           get_parser=float,
                           set_cmd='SOUR:POW {:.2f}',
                           unit='dBm',
                           vals=Numbers(min_value=min_power,
                                        max_value=max_power))

        # IF bandwidth
        self.add_parameter(
            'if_bandwidth',
            label='IF Bandwidth',
            get_cmd='SENS:BAND?',
            get_parser=float,
            set_cmd='SENS:BAND {:.2f}',
            unit='Hz',
            #vals=Numbers(min_value=10, max_value=15e6))
            vals=Enum(*np.append(
                [10**6, 15 *
                 10**5], np.kron([10, 15, 20, 30, 50, 70], 10**np.arange(5)))))

        # Number of averages (also resets averages)
        self.add_parameter('averages_enabled',
                           label='Averages Enabled',
                           get_cmd="SENS:AVER?",
                           set_cmd="SENS:AVER {}",
                           val_mapping={
                               True: '1',
                               False: '0'
                           })
        self.add_parameter('averages',
                           label='Averages',
                           get_cmd='SENS:AVER:COUN?',
                           get_parser=int,
                           set_cmd='SENS:AVER:COUN {:d}',
                           unit='',
                           vals=Numbers(min_value=1, max_value=999))
        self.add_parameter('average_trigger',
                           label='Average Trigger',
                           get_cmd=':TRIG:AVER?',
                           set_cmd=':TRIG:AVER {}',
                           vals=Enum('on', 'On', 'ON', 'off', 'Off', 'OFF'))

        # Setting frequency range
        self.add_parameter('start',
                           label='Start Frequency',
                           get_cmd='SENS:FREQ:STAR?',
                           get_parser=float,
                           set_cmd='SENS:FREQ:STAR {}',
                           unit='Hz',
                           vals=Numbers(min_value=min_freq,
                                        max_value=max_freq))
        self.add_parameter('stop',
                           label='Stop Frequency',
                           get_cmd='SENS:FREQ:STOP?',
                           get_parser=float,
                           set_cmd='SENS:FREQ:STOP {}',
                           unit='Hz',
                           vals=Numbers(min_value=min_freq,
                                        max_value=max_freq))
        self.add_parameter('center',
                           label='Center Frequency',
                           get_cmd='SENS:FREQ:CENT?',
                           get_parser=float,
                           set_cmd='SENS:FREQ:CENT {}',
                           unit='Hz',
                           vals=Numbers(min_value=min_freq,
                                        max_value=max_freq))
        self.add_parameter('span',
                           label='Frequency Span',
                           get_cmd='SENS:FREQ:SPAN?',
                           get_parser=float,
                           set_cmd='SENS:FREQ:SPAN {}',
                           unit='Hz',
                           vals=Numbers(min_value=min_freq,
                                        max_value=max_freq))

        # Number of points in a sweep
        self.add_parameter('points',
                           label='Points',
                           get_cmd='SENS:SWE:POIN?',
                           get_parser=int,
                           set_cmd='SENS:SWE:POIN {}',
                           unit='',
                           vals=Numbers(min_value=1, max_value=20001))

        # Electrical delay
        self.add_parameter('electrical_delay',
                           label='Electrical Delay',
                           get_cmd='CALC:CORR:EDEL:TIME?',
                           get_parser=float,
                           set_cmd='CALC:CORR:EDEL:TIME {:.6e}',
                           unit='s',
                           vals=Numbers(min_value=0, max_value=100000))

        # Sweep Time
        self.add_parameter('sweep_time',
                           label='Time',
                           get_cmd='SENS:SWE:TIME?',
                           set_cmd='SENS:SWE:TIME {}',
                           get_parser=float,
                           unit='s',
                           vals=Numbers(0, 1e6))
        # Trigger Mode
        self.add_parameter('continuous_mode',
                           label='Continuous Mode',
                           get_cmd=':INIT:CONT?',
                           set_cmd=':INIT:CONT {}',
                           vals=Enum('on', 'On', 'ON', 1, 'off', 'Off', 'OFF',
                                     0))
        # Trigger Source
        self.add_parameter(name='trigger_source',
                           label='Trigger source',
                           get_cmd=":TRIG:SEQ:SOUR?",
                           set_cmd=':TRIG:SEQ:SOUR {}',
                           get_parser=str,
                           vals=Enum('bus', 'BUS', 'Bus', 'EXT', 'external',
                                     'EXTERNAL', 'External', 'INT', 'internal',
                                     'INTERNAL', 'Internal', 'MAN', 'manual',
                                     'MANUAL', 'Manual'))
        # Traces
        self.add_parameter(name='num_traces',
                           label='Number of Traces',
                           get_cmd='CALC:PAR:COUN?',
                           set_cmd='CALC:PAR:Coun {}',
                           get_parser=int,
                           vals=Numbers(min_value=1, max_value=4))
        self.add_parameter('active_trace',
                           label='Active Trace',
                           set_cmd="CALC:PAR{}:SEL",
                           vals=Numbers(min_value=1, max_value=4))

        #Init the names of the traces on the VNA
        for n in range(self.num_traces()):
            self.write("CALC:PAR{}:TNAME:DATA TR{}".format(n + 1, n + 1))

        # Initialize the trigger source to "BUS"
        self.trigger_source('BUS')

        # Initialize sweep time to auto
        self.sweep_time(0)

        # Note: Traces will be accessed through the traces property which
        # updates the channellist to include only active trace numbers
        self._traces = ChannelList(self, "PNATraces", PNATrace)
        self.add_submodule("traces", self._traces)
        #        # Add shortcuts to first trace
        #        trace1 = self.traces[0]
        #        for param in trace1.parameters.values():
        #            self.parameters[param.name] = param
        #        # And also add a link to run sweep
        #        self.run_sweep = trace1.run_sweep
        #        # Set this trace to be the default (it's possible to end up in a
        #        # situation where no traces are selected, causing parameter snapshots
        #        # to fail)
        #        self.active_trace(trace1.trace_num)

        # Add markers to instrument
        self._markers = ChannelList(self, "ENAMarkers", ENAMarker)
        self.add_submodule("markers", self._markers)

        # Set auto_sweep parameter
        # If we want to return multiple traces per setpoint without sweeping
        # multiple times, we should set this to false
        self.add_parameter('auto_sweep',
                           label='Auto Sweep',
                           set_cmd=None,
                           get_cmd=None,
                           vals=Bool(),
                           initial_value=True)

        self.connect_message()
示例#6
0
    def __init__(self,
                 name: str,
                 address: str,
                 # Set frequency ranges
                 min_freq: Union[int, float], max_freq: Union[int, float],
                 # Set power ranges
                 min_power: Union[int, float], max_power: Union[int, float],
                 nports: int, # Number of ports on the PNA
                 **kwargs: Any) -> None:
        super().__init__(name, address, terminator='\n', **kwargs)
        self.min_freq = min_freq
        self.max_freq = max_freq

        #Ports
        ports = ChannelList(self, "PNAPorts", PNAPort)
        for port_num in range(1, nports+1):
            port = PNAPort(self, f"port{port_num}", port_num,
                           min_power, max_power)
            ports.append(port)
            self.add_submodule(f"port{port_num}", port)
        ports.lock()
        self.add_submodule("ports", ports)

        # Drive power
        self.add_parameter('power',
                           label='Power',
                           get_cmd='SOUR:POW?',
                           get_parser=float,
                           set_cmd='SOUR:POW {:.2f}',
                           unit='dBm',
                           vals=Numbers(min_value=min_power,
                                        max_value=max_power))

        # IF bandwidth
        self.add_parameter('if_bandwidth',
                           label='IF Bandwidth',
                           get_cmd='SENS:BAND?',
                           get_parser=float,
                           set_cmd='SENS:BAND {:.2f}',
                           unit='Hz',
                           vals=Numbers(min_value=1, max_value=15e6))

        # Number of averages (also resets averages)
        self.add_parameter('averages_enabled',
                           label='Averages Enabled',
                           get_cmd="SENS:AVER?",
                           set_cmd="SENS:AVER {}",
                           val_mapping={True: '1', False: '0'})
        self.add_parameter('averages',
                           label='Averages',
                           get_cmd='SENS:AVER:COUN?',
                           get_parser=int,
                           set_cmd='SENS:AVER:COUN {:d}',
                           unit='',
                           vals=Numbers(min_value=1, max_value=65536))
        # RF OUT -> Turns the VNA ON/OFF

        self.add_parameter('rf_out',
                           label='RF Out',
                           get_cmd="OUTP:STAT?",
                           set_cmd="OUTP:STAT {}",
                           val_mapping={True: '1', False: '0'})


        # Setting frequency range
        self.add_parameter('start',
                           label='Start Frequency',
                           get_cmd='SENS:FREQ:STAR?',
                           get_parser=float,
                           set_cmd='SENS:FREQ:STAR {}',
                           unit='Hz',
                           vals=Numbers(min_value=min_freq,
                                        max_value=max_freq))
        self.add_parameter('stop',
                           label='Stop Frequency',
                           get_cmd='SENS:FREQ:STOP?',
                           get_parser=float,
                           set_cmd='SENS:FREQ:STOP {}',
                           unit='Hz',
                           vals=Numbers(min_value=min_freq,
                                        max_value=max_freq))
        self.add_parameter('center',
                           label='Center Frequency',
                           get_cmd='SENS:FREQ:CENT?',
                           get_parser=float,
                           set_cmd='SENS:FREQ:CENT {}',
                           unit='Hz',
                           vals=Numbers(min_value=min_freq,
                                        max_value=max_freq))
        self.add_parameter('span',
                           label='Frequency Span',
                           get_cmd='SENS:FREQ:SPAN?',
                           get_parser=float,
                           set_cmd='SENS:FREQ:SPAN {}',
                           unit='Hz',
                           vals=Numbers(min_value=0,
                                        max_value=max_freq))

        # Number of points in a sweep
        self.add_parameter('points',
                           label='Points',
                           get_cmd='SENS:SWE:POIN?',
                           get_parser=int,
                           set_cmd='SENS:SWE:POIN {}',
                           unit='',
                           vals=Numbers(min_value=1, max_value=100001))

        # Electrical delay
        self.add_parameter('electrical_delay',
                           label='Electrical Delay',
                           get_cmd='CALC:CORR:EDEL:TIME?',
                           get_parser=float,
                           set_cmd='CALC:CORR:EDEL:TIME {:.6e}',
                           unit='s',
                           vals=Numbers(min_value=0, max_value=100000))

        # Sweep Time
        self.add_parameter('sweep_time',
                           label='Time',
                           get_cmd='SENS:SWE:TIME?',
                           get_parser=float,
                           unit='s',
                           vals=Numbers(0, 1e6))
        # Sweep Mode
        self.add_parameter('sweep_mode',
                           label='Mode',
                           get_cmd='SENS:SWE:MODE?',
                           set_cmd='SENS:SWE:MODE {}',
                           vals=Enum("HOLD", "CONT", "GRO", "SING"))
        # Group trigger count
        self.add_parameter('group_trigger_count',
                           get_cmd="SENS:SWE:GRO:COUN?",
                           get_parser=int,
                           set_cmd="SENS:SWE:GRO:COUN {}",
                           vals=Ints(1, 2000000))
        # Trigger Source
        self.add_parameter('trigger_source',
                           get_cmd="TRIG:SOUR?",
                           set_cmd="TRIG:SOUR {}",
                           vals=Enum("EXT", "IMM", "MAN"))

        # Traces
        self.add_parameter('active_trace',
                           label='Active Trace',
                           get_cmd="CALC:PAR:MNUM?",
                           get_parser=int,
                           set_cmd="CALC:PAR:MNUM {}",
                           vals=Numbers(min_value=1, max_value=24))
        # Note: Traces will be accessed through the traces property which
        # updates the channellist to include only active trace numbers
        self._traces = ChannelList(self, "PNATraces", PNATrace)
        self.add_submodule("traces", self._traces)
        # Add shortcuts to first trace
        trace1 = self.traces[0]
        params = trace1.parameters
        if not isinstance(params, dict):
            raise RuntimeError(f"Expected trace.parameters to be a dict got "
                               f"{type(params)}")
        for param in params.values():
            self.parameters[param.name] = param
        # And also add a link to run sweep
        self.run_sweep = trace1.run_sweep
        # Set this trace to be the default (it's possible to end up in a
        # situation where no traces are selected, causing parameter snapshots
        # to fail)
        self.active_trace(trace1.trace_num)

        # Set auto_sweep parameter
        # If we want to return multiple traces per setpoint without sweeping
        # multiple times, we should set this to false
        self.add_parameter('auto_sweep',
                           label='Auto Sweep',
                           set_cmd=None,
                           get_cmd=None,
                           vals=Bool(),
                           initial_value=True)

        # A default output format on initialisation
        self.write('FORM REAL,32')
        self.write('FORM:BORD NORM')

        self.connect_message()
示例#7
0
    def __init__(self, name, address, reset_device=False, **kwargs):
        """ Driver for the Keithley 6500 multimeter. Based on the Keithley 2000 driver,
            commands have been adapted for the Keithley 6500. This driver does not contain
            all commands available, but only the ones most commonly used.

            Status: beta-version.

        Args:
            name (str): The name used internally by QCoDeS in the DataSet.
            address (str): The VISA device address.
            reset_device (bool): Reset the device on startup if true.
        """
        super().__init__(name, address, terminator='\n', **kwargs)

        command_set = self.ask('*LANG?')
        if command_set != 'SCPI':
            error_msg = "This driver only compatible with the 'SCPI' command " \
                        "set, not '{}' set".format(command_set)
            raise CommandSetError(error_msg)

        self._trigger_sent = False

        self._mode_map = {
            'ac current': 'CURR:AC',
            'dc current': 'CURR:DC',
            'ac voltage': 'VOLT:AC',
            'dc voltage': 'VOLT:DC',
            '2w resistance': 'RES',
            '4w resistance': 'FRES',
            'temperature': 'TEMP',
            'frequency': 'FREQ'
        }

        self.add_parameter('mode',
                           get_cmd='SENS:FUNC?',
                           set_cmd="SENS:FUNC {}",
                           val_mapping=self._mode_map)

        self.add_parameter('nplc',
                           get_cmd=partial(self._get_mode_param, 'NPLC',
                                           float),
                           set_cmd=partial(self._set_mode_param, 'NPLC'),
                           vals=Numbers(min_value=0.01, max_value=10))

        #  TODO: validator, this one is more difficult since different modes
        #  require different validation ranges.
        self.add_parameter('range',
                           get_cmd=partial(self._get_mode_param, 'RANG',
                                           float),
                           set_cmd=partial(self._set_mode_param, 'RANG'),
                           vals=Numbers())

        self.add_parameter('auto_range_enabled',
                           get_cmd=partial(self._get_mode_param, 'RANG:AUTO',
                                           _parse_output_bool),
                           set_cmd=partial(self._set_mode_param, 'RANG:AUTO'),
                           vals=Bool())

        self.add_parameter('digits',
                           get_cmd='DISP:VOLT:DC:DIG?',
                           get_parser=int,
                           set_cmd='DISP:VOLT:DC:DIG? {}',
                           vals=Ints(min_value=4, max_value=7))

        self.add_parameter('averaging_type',
                           get_cmd=partial(self._get_mode_param, 'AVER:TCON',
                                           _parse_output_string),
                           set_cmd=partial(self._set_mode_param, 'AVER:TCON'),
                           vals=Enum('moving', 'repeat'))

        self.add_parameter('averaging_count',
                           get_cmd=partial(self._get_mode_param, 'AVER:COUN',
                                           int),
                           set_cmd=partial(self._set_mode_param, 'AVER:COUN'),
                           vals=Ints(min_value=1, max_value=100))

        self.add_parameter('averaging_enabled',
                           get_cmd=partial(self._get_mode_param, 'AVER:STAT',
                                           _parse_output_bool),
                           set_cmd=partial(self._set_mode_param, 'AVER:STAT'),
                           vals=Bool())

        # Global parameters
        self.add_parameter('display_backlight',
                           docstring='Control the brightness of the display '
                           'backligt. Off turns the display off and'
                           'Blackout also turns off indicators and '
                           'key lights on the device.',
                           get_cmd='DISP:LIGH:STAT?',
                           set_cmd='DISP:LIGH:STAT {}',
                           val_mapping={
                               'On 100': 'ON100',
                               'On 75': 'ON75',
                               'On 50': 'ON50',
                               'On 25': 'ON25',
                               'Off': 'OFF',
                               'Blackout': 'BLACkout'
                           })

        self.add_parameter('trigger_count',
                           get_parser=int,
                           get_cmd='ROUT:SCAN:COUN:SCAN?',
                           set_cmd='ROUT:SCAN:COUN:SCAN {}',
                           vals=MultiType(
                               Ints(min_value=1, max_value=9999),
                               Enum('inf', 'default', 'minimum', 'maximum')))

        for trigger in range(1, 5):
            self.add_parameter('trigger%i_delay' % trigger,
                               docstring='Set and read trigger delay for '
                               'timer %i.' % trigger,
                               get_parser=float,
                               get_cmd='TRIG:TIM%i:DEL?' % trigger,
                               set_cmd='TRIG:TIM%i:DEL {}' % trigger,
                               unit='s',
                               vals=Numbers(min_value=0, max_value=999999.999))

            self.add_parameter('trigger%i_source' % trigger,
                               docstring='Set the trigger source for '
                               'timer %i.' % trigger,
                               get_cmd='TRIG:TIM%i:STAR:STIM?' % trigger,
                               set_cmd='TRIG:TIM%i:STAR:STIM {}' % trigger,
                               val_mapping={
                                   'immediate': 'NONE',
                                   'timer1': 'TIM1',
                                   'timer2': 'TIM2',
                                   'timer3': 'TIM3',
                                   'timer4': 'TIM4',
                                   'notify1': 'NOT1',
                                   'notify2': 'NOT2',
                                   'notify3': 'NOT3',
                                   'front-panel': 'DISP',
                                   'bus': 'COMM',
                                   'external': 'EXT'
                               })

        # Control interval between scans; the default value from the instrument is 0,
        # hence 0 is included in the validator's range of this parameter.
        self.add_parameter('trigger_timer',
                           get_parser=float,
                           get_cmd='ROUT:SCAN:INT?',
                           set_cmd='ROUT:SCAN:INT {}',
                           unit='s',
                           vals=Numbers(min_value=0, max_value=999999.999))

        self.add_parameter('amplitude',
                           get_cmd=self._read_next_value,
                           set_cmd=False,
                           unit='a.u.')

        if reset_device:
            self.reset()
        self.write('FORM:DATA ASCII')
        self.connect_message()
示例#8
0
 def test_valid_values(self):
     val = Bool()
     for vval in val.valid_values:
         val.validate(vval)
示例#9
0
    def __init__(self, name, instrument_x, instrument_y, instrument_z,
                 field_limit: Union[numbers.Real,
                                    Iterable[CartesianFieldLimitFunction]],
                 **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

        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):
            # Convertion 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())
示例#10
0
    def __init__(self, name, address, timeout=20, **kwargs):
        """
        Initialises the DS4000.

        Args:
            name (str): Name of the instrument used by QCoDeS
        address (string): Instrument address as used by VISA
            timeout (float): visa timeout, in secs. long default (180)
              to accommodate large waveforms
        """

        # Init VisaInstrument. device_clear MUST NOT be issued, otherwise communications hangs
        # due a bug in firmware
        super().__init__(name,
                         address,
                         device_clear=False,
                         timeout=timeout,
                         **kwargs)
        self.connect_message()

        # functions
        self.add_function('run',
                          call_cmd=':RUN',
                          docstring='Start acquisition')
        self.add_function('stop',
                          call_cmd=':STOP',
                          docstring='Stop acquisition')
        self.add_function('single',
                          call_cmd=':SINGle',
                          docstring='Single trace acquisition')
        self.add_function('force_trigger',
                          call_cmd='TFORce',
                          docstring='Force trigger event')
        self.add_function("auto_scale",
                          call_cmd=":AUToscale",
                          docstring="Perform autoscale")

        # general parameters
        self.add_parameter('trigger_type',
                           label='Type of the trigger',
                           get_cmd=':TRIGger:MODE?',
                           set_cmd=':TRIGger:MODE {}',
                           vals=vals.Enum('EDGE', 'PULS', 'RUNT', 'NEDG',
                                          'SLOP', 'VID', 'PATT', 'RS232',
                                          'IIC', 'SPI', 'CAN', 'FLEX', 'USB'))
        self.add_parameter('trigger_mode',
                           label='Mode of the trigger',
                           get_cmd=':TRIGger:SWEep?',
                           set_cmd=':TRIGger:SWEep {}',
                           vals=vals.Enum('AUTO', 'NORM', 'SING'))
        self.add_parameter("time_base",
                           label="Horizontal time base",
                           get_cmd=":TIMebase:MAIN:SCALe?",
                           set_cmd=":TIMebase:MAIN:SCALe {}",
                           get_parser=float,
                           unit="s/div")
        self.add_parameter("sample_point_count",
                           label="Number of the waveform points",
                           get_cmd=":WAVeform:POINts?",
                           set_cmd=":WAVeform:POINts {}",
                           get_parser=int,
                           vals=Ints(min_value=1))
        self.add_parameter("enable_auto_scale",
                           label="Enable or disable autoscale",
                           get_cmd=":SYSTem:AUToscale?",
                           set_cmd=":SYSTem:AUToscale {}",
                           get_parser=bool,
                           vals=Bool())

        channels = ChannelList(self,
                               "Channels",
                               RigolDS4000Channel,
                               snapshotable=False)

        for channel_number in range(1, 5):
            channel = RigolDS4000Channel(self, "ch{}".format(channel_number),
                                         channel_number)
            channels.append(channel)

        channels.lock()
        self.add_submodule('channels', channels)
示例#11
0
    def __init__(self, name, address=None, port=7020, 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(
            'hold_after_set',
            get_cmd=None,
            set_cmd=None,
            vals=Bool(),
            initial_value=True,
            docstring=
            'Should the driver block while waiting for the Magnet power supply '
            'to go into hold mode.')

        self.add_parameter('setpoint',
                           names=tuple('B' + ax.lower() + '_setpoint'
                                       for ax in self.axes),
                           units=tuple('T' for ax in self.axes),
                           get_cmd=partial(self._get_fld, self.axes, 'FSET'),
                           set_cmd=partial(self._ramp_to_setpoint, self.axes,
                                           'FSET'),
                           parameter_class=MercuryiPSArray)

        self.add_parameter('rate',
                           names=tuple('rate_B' + ax.lower()
                                       for ax in self.axes),
                           units=tuple('T/m' for ax in self.axes),
                           get_cmd=partial(self._get_fld, self.axes, 'RFST'),
                           set_cmd=partial(self._ramp_to_setpoint, self.axes,
                                           'RFST'),
                           parameter_class=MercuryiPSArray)

        self.add_parameter('fld',
                           names=tuple('B' + ax.lower() for ax in self.axes),
                           units=tuple('T' for ax in self.axes),
                           get_cmd=partial(self._get_fld, self.axes, 'FLD'),
                           set_cmd=partial(self._ramp_to_setpoint, self.axes,
                                           'FSET'),
                           parameter_class=MercuryiPSArray)

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

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

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

        # 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,
                           unit='|B|')
        self.add_parameter('theta',
                           get_cmd=self._get_theta,
                           set_cmd=self._set_theta,
                           unit='rad')
        self.add_parameter('phi',
                           get_cmd=self._get_phi,
                           set_cmd=self._set_phi,
                           unit='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(),
                               unit='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(),
                               unit='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(),
                               unit='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'),
                               unit='T')
            self.add_parameter(ax.lower() + '_setpointC',
                               get_cmd=partial(self._get_fld, ax, 'CSET'),
                               set_cmd=partial(self._set_fld, ax, 'CSET'),
                               unit='T')
            self.add_parameter(ax.lower() + '_rate',
                               get_cmd=partial(self._get_fld, ax, 'RFST'),
                               set_cmd=partial(self._set_fld, ax, 'RFST'),
                               unit='T/m')
            self.add_parameter(ax.lower() + '_rateC',
                               get_cmd=partial(self._get_fld, ax, 'RCST'),
                               set_cmd=partial(self._set_fld, ax, 'RCST'),
                               unit='T/m')

            self.connect_message()
示例#12
0
 def test_valid_values(self):
     val = Bool()
     val.validate(val.valid_values[0])
示例#13
0
    def __init__(
            self,
            name: str,
            address: str,
            min_freq: Union[int, float],
            max_freq: Union[int, float],  # Set frequency ranges
            min_power: Union[int, float],
            max_power: Union[int, float],  # Set power ranges
            nports: int,  # Number of ports on the PNA
            **kwargs: Any) -> None:
        super().__init__(name, address, terminator='\n', **kwargs)

        #Ports
        ports = ChannelList(self, "PNAPorts", PNAPort)
        for port_num in range(1, nports + 1):
            port = PNAPort(self, f"port{port_num}", port_num, min_power,
                           max_power)
            ports.append(port)
            self.add_submodule(f"port{port_num}", port)
        ports.lock()
        self.add_submodule("ports", ports)

        # Drive power
        self.add_parameter('power',
                           label='Power',
                           get_cmd='SOUR:POW?',
                           get_parser=float,
                           set_cmd='SOUR:POW {:.2f}',
                           unit='dBm',
                           vals=Numbers(min_value=min_power,
                                        max_value=max_power))

        # IF bandwidth
        self.add_parameter('if_bandwidth',
                           label='IF Bandwidth',
                           get_cmd='SENS:BAND?',
                           get_parser=float,
                           set_cmd='SENS:BAND {:.2f}',
                           unit='Hz',
                           vals=Numbers(min_value=1, max_value=15e6))

        # Number of averages (also resets averages)
        self.add_parameter('averages_enabled',
                           label='Averages Enabled',
                           get_cmd="SENS:AVER?",
                           set_cmd="SENS:AVER {}",
                           val_mapping={
                               True: '1',
                               False: '0'
                           })
        self.add_parameter('averages',
                           label='Averages',
                           get_cmd='SENS:AVER:COUN?',
                           get_parser=int,
                           set_cmd='SENS:AVER:COUN {:d}',
                           unit='',
                           vals=Numbers(min_value=1, max_value=65536))

        # Setting frequency range
        self.add_parameter('start',
                           label='Start Frequency',
                           get_cmd='SENS:FREQ:STAR?',
                           get_parser=float,
                           set_cmd='SENS:FREQ:STAR {}',
                           unit='',
                           vals=Numbers(min_value=min_freq,
                                        max_value=max_freq))
        self.add_parameter('stop',
                           label='Stop Frequency',
                           get_cmd='SENS:FREQ:STOP?',
                           get_parser=float,
                           set_cmd='SENS:FREQ:STOP {}',
                           unit='',
                           vals=Numbers(min_value=min_freq,
                                        max_value=max_freq))

        # Number of points in a sweep
        self.add_parameter('points',
                           label='Points',
                           get_cmd='SENS:SWE:POIN?',
                           get_parser=int,
                           set_cmd='SENS:SWE:POIN {}',
                           unit='',
                           vals=Numbers(min_value=1, max_value=100001))

        # Electrical delay
        self.add_parameter('electrical_delay',
                           label='Electrical Delay',
                           get_cmd='CALC:CORR:EDEL:TIME?',
                           get_parser=float,
                           set_cmd='CALC:CORR:EDEL:TIME {:.6e}',
                           unit='s',
                           vals=Numbers(min_value=0, max_value=100000))

        # Sweep Time
        self.add_parameter('sweep_time',
                           label='Time',
                           get_cmd='SENS:SWE:TIME?',
                           get_parser=float,
                           unit='s',
                           vals=Numbers(0, 1e6))
        # Sweep Mode
        self.add_parameter('sweep_mode',
                           label='Mode',
                           get_cmd='SENS:SWE:MODE?',
                           set_cmd='SENS:SWE:MODE {}',
                           vals=Enum("HOLD", "CONT", "GRO", "SING"))

        # Traces
        self.add_parameter('active_trace',
                           label='Active Trace',
                           get_cmd="CALC:PAR:MNUM?",
                           get_parser=int,
                           set_cmd="CALC:PAR:MNUM {}",
                           vals=Numbers(min_value=1, max_value=24))
        # Note: Traces will be accessed through the traces property which updates
        # the channellist to include only active trace numbers
        self._traces = ChannelList(self, "PNATraces", PNATrace)
        self.add_submodule("traces", self._traces)
        # Add shortcuts to trace 1
        trace1 = PNATrace(self, "tr1", 1)
        for param in trace1.parameters.values():
            self.parameters[param.name] = param
        # Set this trace to be the default (it's possible to end up in a situation where
        # no traces are selected, causing parameter snapshots to fail)
        self.active_trace(1)

        # Set auto_sweep parameter
        # If we want to return multiple traces per setpoint without sweeping
        # multiple times, we should set this to false
        self.add_parameter('auto_sweep',
                           label='Auto Sweep',
                           set_cmd=None,
                           get_cmd=None,
                           vals=Bool(),
                           initial_value=True)

        # A default output format on initialisation
        self.write('FORM REAL,32')
        self.write('FORM:BORD NORM')

        self.connect_message()
示例#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"""
示例#15
0
    def __init__(self, name, address, reset=False, **kwargs):
        super().__init__(name, address, terminator='\n', **kwargs)

        self._trigger_sent = False

        # Unfortunately the strings have to contain quotation marks and a
        # newline character, as this is how the instrument returns it.
        self._mode_map = {
            'ac current': 'CURR:AC',
            'dc current': 'CURR:DC',
            'ac voltage': 'VOLT:AC',
            'dc voltage': 'VOLT:DC',
            '2w resistance': 'RES',
            '4w resistance': 'FRES',
            'temperature': 'TEMP',
            'frequency': 'FREQ',
            'none': 'NONE',  # instrument is in digitizer mode
        }

        self.add_parameter('mode',
                           get_cmd='SENS:FUNC?',
                           set_cmd="SENS:FUNC \"{}\"",
                           val_mapping=self._mode_map)

        # Mode specific parameters
        self.add_parameter('nplc',
                           get_cmd=partial(self._get_mode_param, 'NPLC',
                                           float),
                           set_cmd=partial(self._set_mode_param, 'NPLC'),
                           vals=Numbers(min_value=0.01, max_value=10))

        # TODO: validator, this one is more difficult since different modes
        # require different validation ranges
        self.add_parameter('range',
                           get_cmd=partial(self._get_mode_param, 'RANG',
                                           float),
                           set_cmd=partial(self._set_mode_param, 'RANG'),
                           vals=Numbers())

        self.add_parameter('auto_range_enabled',
                           get_cmd=partial(self._get_mode_param, 'RANG:AUTO',
                                           parse_output_bool),
                           set_cmd=partial(self._set_mode_param, 'RANG:AUTO'),
                           vals=Bool())

        self.add_parameter('digits',
                           get_cmd=partial(self._get_mode_param, 'DIG', int),
                           set_cmd=partial(self._set_mode_param, 'DIG'),
                           vals=Ints(min_value=4, max_value=7))

        self.add_parameter('averaging_type',
                           get_cmd=partial(self._get_mode_param, 'AVER:TCON',
                                           parse_output_string),
                           set_cmd=partial(self._set_mode_param, 'AVER:TCON'),
                           vals=Enum('moving', 'repeat'))

        self.add_parameter('averaging_count',
                           get_cmd=partial(self._get_mode_param, 'AVER:COUN',
                                           int),
                           set_cmd=partial(self._set_mode_param, 'AVER:COUN'),
                           vals=Ints(min_value=1, max_value=100))

        self.add_parameter('averaging_enabled',
                           get_cmd=partial(self._get_mode_param, 'AVER:STAT',
                                           parse_output_bool),
                           set_cmd=partial(self._set_mode_param, 'AVER:STAT'),
                           vals=Bool())

        # Global parameters
        self.add_parameter('display_enabled',
                           get_cmd='DISP:ENAB?',
                           get_parser=parse_output_bool,
                           set_cmd='DISP:ENAB {}',
                           set_parser=int,
                           vals=Bool())

        self.add_parameter('trigger_count',
                           get_cmd='TRIG:COUN?',
                           get_parser=int,
                           set_cmd='TRIG:COUN {}',
                           vals=MultiType(
                               Ints(min_value=1, max_value=9999),
                               Enum('inf', 'default', 'minimum', 'maximum')))

        self.add_parameter('trigger_delay',
                           get_cmd='TRIG:DEL?',
                           get_parser=float,
                           set_cmd='TRIG:DEL {}',
                           unit='s',
                           vals=Numbers(min_value=0, max_value=999999.999))

        self.add_parameter('trigger_source',
                           get_cmd='TRIG:SOUR?',
                           set_cmd='TRIG:SOUR {}',
                           val_mapping={
                               'immediate': 'IMM',
                               'timer': 'TIM',
                               'manual': 'MAN',
                               'bus': 'BUS',
                               'external': 'EXT',
                           })

        self.add_parameter('trigger_timer',
                           get_cmd='TRIG:TIM?',
                           get_parser=float,
                           set_cmd='TRIG:TIM {}',
                           unit='s',
                           vals=Numbers(min_value=0.001, max_value=999999.999))

        #        self.add_parameter('amplitude',
        #                           unit='arb.unit',
        #                           get_cmd=self._read_next_value)

        self.add_parameter('data_format', get_cmd=':FORMat:DATA?')
        # Trace subystem, also called reading buffers
        self.add_parameter(
            'buffer_readings',
            label='number of readings in buffer',
            get_cmd=':TRACe:ACTual?',
            get_parser=int,
        )

        self.add_function('clear_buffer', call_cmd=':TRACe:CLEar')
        self.add_function('reset', call_cmd='*RST')

        if reset:
            self.reset()

        # Set the data format to have only ascii data without units and channels
#        self.write('FORM:DATA ASCII')
#        self.write('FORM:ELEM READ')

        self.connect_message()
示例#16
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())
示例#17
0
    def __init__(self, name: str, address: str, terminator: str="\n", **kwargs):
        super().__init__(name, address, terminator=terminator, *kwargs)

        self.add_parameter('output',
                           label='Output State',
                           get_cmd=self.state,
                           set_cmd=lambda x: self.on() if x else self.off(),
                           val_mapping={
                               'off': 0,
                               'on': 1,
                           })

        self.add_parameter('source_mode',
                           label='Source Mode',
                           get_cmd=':SOUR:FUNC?',
                           set_cmd=self._set_source_mode,
                           vals=Enum('VOLT', 'CURR'))

        # When getting the mode internally in the driver, look up the mode as recorded by the _cached_mode property,
        # instead of calling source_mode(). This will prevent frequent VISA calls to the instrument. Calling
        # _set_source_mode will change the chased value.
        self._cached_mode = "VOLT"

        # We want to cache the range value so communication with the instrument only happens when the set the
        # range. Getting the range always returns the cached value. This value is adjusted when calling
        # self._set_range
        self._cached_range_value = None

        self.add_parameter('voltage_range',
                           label='Voltage Source Range',
                           unit='V',
                           get_cmd=partial(self._get_range, "VOLT"),
                           set_cmd=partial(self._set_range, "VOLT"),
                           vals=Enum(10e-3, 100e-3, 1e0, 10e0, 30e0))

        self.add_parameter('current_range',
                           label='Current Source Range',
                           unit='I',
                           get_cmd=partial(self._get_range, "CURR"),
                           set_cmd=partial(self._set_range, "CURR"),
                           vals=Enum(1e-3, 10e-3, 100e-3, 200e-3)
                           )

        # This is changed through the source_mode interface
        self.range = self.voltage_range

        self._auto_range = False
        self.add_parameter('auto_range',
                           label='Auto Range',
                           set_cmd=self._set_auto_range,
                           get_cmd=lambda: self._auto_range,
                           vals=Bool())

        self.add_parameter('voltage',
                           label='Voltage',
                           unit='V',
                           set_cmd=partial(self._get_set_output, "VOLT"),
                           get_cmd=partial(self._get_set_output, "VOLT")
                           )

        self.add_parameter('current',
                           label='Current',
                           unit='I',
                           set_cmd=partial(self._get_set_output, "CURR"),
                           get_cmd=partial(self._get_set_output, "CURR")
                           )

        # This is changed through the source_mode interface
        self.output_level = self.voltage

        self.add_parameter('voltage_limit',
                           label='Voltage Protection Limit',
                           unit='V',
                           vals=Ints(1, 30),
                           get_cmd=":SOUR:PROT:VOLT?",
                           set_cmd=":SOUR:PROT:VOLT {}",
                           get_parser=float_round,
                           set_parser=int)

        self.add_parameter('current_limit',
                           label='Current Protection Limit',
                           unit='I',
                           vals=Numbers(1e-3, 200e-3),
                           get_cmd=":SOUR:PROT:CURR?",
                           set_cmd=":SOUR:PROT:CURR {:.3f}",
                           get_parser=float,
                           set_parser=float)

        self.add_parameter('four_wire',
                           label='Four Wire Sensing',
                           get_cmd=':SENS:REM?',
                           set_cmd=':SENS:REM {}',
                           val_mapping={
                              'off': 0,
                              'on': 1,
                           })
        # Note: The guard feature can be used to remove common mode noise.
        # Read the manual to see if you would like to use it
        self.add_parameter('guard',
                          label='Guard Terminal',
                          get_cmd=':SENS:GUAR?',
                          set_cmd=':SENS:GUAR {}',
                          val_mapping={
                              'off': 0,
                              'on': 1,
                          })

        # Return measured line frequency
        self.add_parameter("line_freq",
                           label='Line Frequency',
                           unit="Hz",
                           get_cmd="SYST:LFR?",
                           get_parser=int)

        # Check if monitor is present, and if so enable measurement
        monitor_present = '/MON' in self.ask("*OPT?")
        measure = GS200_Monitor(self, 'measure', monitor_present)
        self.add_submodule('measure', measure)

        # Reset function
        self.add_function('reset', call_cmd='*RST')
        self.connect_message()

        self.output("off")
        self.source_mode("VOLT")
        self.auto_range(False)
    def __init__(self,
                 name: str,
                 address: str,
                 terminator="\n",
                 reset: bool = False,
                 **kwargs):

        super().__init__(name, address, terminator=terminator, **kwargs)

        self.add_parameter('source_current_compliance',
                           unit='A',
                           get_parser=float,
                           set_cmd='SENS:CURR:PROT {}',
                           get_cmd='SENS:CURR:PROT?',
                           vals=Numbers(1e-9, 105e-3))
        self.add_parameter('source_voltage_compliance',
                           unit='V',
                           get_parser=float,
                           set_cmd='SENS:VOLT:PROT {}',
                           get_cmd='SENS:VOLT:PROT?',
                           vals=Numbers(1e-12, 210))
        self.add_parameter(
            'source_current_compliance_tripped',
            get_cmd='SENS:CURR:PROT:TRIP?',
            val_mapping=on_off_vals,
            docstring='True if current has reached specified '
            'compliance.',
        )
        self.add_parameter(
            'source_voltage_compliance_tripped',
            get_cmd='SENS:VOLT:PROT:TRIP?',
            val_mapping=on_off_vals,
            docstring='True if voltage has reached specified '
            'compliance.',
        )
        self.add_parameter(
            'source_current',
            unit='A',
            get_parser=float,
            label='Source current',
            set_cmd='SOUR:CURR:LEV {}',
            get_cmd='SOUR:CURR:LEV?',
            vals=Numbers(-105e-3, 105e-3),
            docstring='When in current sourcing mode, tries to '
            'set current to this level.',
        )
        self.add_parameter(
            'sense_current',
            unit='A',
            get_parser=float,
            label='Measured current',
            get_cmd=partial(self._read_value, 'CURR:DC'),
            snapshot_get=False,
            docstring='Value of measured current, when in '
            'current sensing mode.',
        )
        self.add_parameter(
            'sense_voltage',
            unit='V',
            get_parser=float,
            label='Measured voltage',
            get_cmd=partial(self._read_value, 'VOLT:DC'),
            snapshot_get=False,
            docstring='Value of measured voltage, when in '
            'voltage sensing mode.',
        )
        self.add_parameter(
            'sense_resistance',
            unit='Ohm',
            get_parser=float,
            label='Measured resistance',
            get_cmd=partial(self._read_value, 'RES'),
            snapshot_get=False,
            docstring='Value of measured resistance, when in '
            'resistance sensing mode.',
        )
        self.add_parameter('source_current_range',
                           unit='A',
                           get_parser=float,
                           set_cmd='SOUR:CURR:RANG {}',
                           get_cmd='SOUR:CURR:RANG?',
                           vals=Numbers(1e-12, 105e-3))
        self.add_parameter(
            'source_voltage',
            unit='V',
            get_parser=float,
            label='Source voltage',
            set_cmd='SOUR:VOLT:LEV {}',
            get_cmd='SOUR:VOLT:LEV?',
            vals=Numbers(-210, 210),
            docstring='When in voltage sourcing mode, tries to '
            'set voltage to this level.',
        )
        self.add_parameter('source_voltage_range',
                           unit='V',
                           get_parser=float,
                           set_cmd='SOUR:VOLT:RANG {}',
                           get_cmd='SOUR:VOLT:RANG?',
                           vals=Numbers(200e-3, 200))
        self.add_parameter(
            'source_delay_auto',
            set_cmd=':SOUR:DEL:AUTO {}',
            get_cmd=':SOUR:DEL:AUTO?',
            val_mapping=on_off_vals,
            docstring="Automatically set a delay period that "
            "is appropriate for the present "
            "source/measure setup configuration.",
        )
        self.add_parameter(
            'source_delay',
            unit='s',
            get_parser=float,
            set_cmd=':SOUR:DEL {}',
            get_cmd=':SOUR:DEL?',
            vals=Numbers(0, 9999.998),
            docstring="Settling time after setting source "
            "value.",
        )
        self.add_parameter(
            'output_enabled',
            set_cmd='OUTP {}',
            get_cmd='OUTP?',
            val_mapping=on_off_vals,
            docstring='Turns the source on or off.',
        )
        self.add_parameter(
            'output_auto_off_enabled',
            set_cmd=':SOUR:CLE:AUTO {}',
            get_cmd='OUTP?',
            val_mapping=on_off_vals,
        )
        self.add_parameter(
            'source_mode',
            set_cmd='SOUR:FUNC {}',
            get_cmd=self._get_source_mode,
            vals=Enum('VOLT', 'CURR'),
            docstring="Either 'VOLT' to source voltage, "
            "or 'CURR' for current.",
        )
        self.add_parameter(
            'sense_mode',
            set_cmd=self._set_sense_mode,
            get_cmd=self._get_sense_mode,
            vals=Strings(),
            docstring="Sensing mode."
            "Set to 'VOLT:DC', "
            "'CURR:DC', or 'RES', or a combination "
            "thereof by using comma.",
        )
        self.add_parameter(
            'sense_autorange',
            set_cmd=self._set_sense_autorange,
            get_cmd=self._get_sense_autorange,
            vals=Bool(),
            docstring="If True, all ranges in all modes are"
            " chosen automatically",
        )
        self.add_parameter(
            'sense_current_range',
            unit='A',
            get_parser=float,
            set_cmd=':SENS:CURR:RANG {}',
            get_cmd=':SENS:CURR:RANG?',
            vals=Numbers(1e-12, 1e-1),
        )
        self.add_parameter(
            'sense_voltage_range',
            unit='V',
            get_parser=float,
            set_cmd=':SENS:VOLT:RANG {}',
            get_cmd=':SENS:VOLT:RANG?',
            vals=Enum(200, 20, 2, 0.2),
        )
        self.add_parameter(
            'sense_resistance_range',
            unit='Ohm',
            get_parser=float,
            set_cmd=':SENS:RES:RANG {}',
            get_cmd=':SENS:RES:RANG?',
            vals=Numbers(2, 2e13),
        )
        self.add_parameter(
            'sense_resistance_offset_comp_enabled',
            set_cmd=':SENS:RES:OCOM {}',
            get_cmd=':SENS:RES:OCOM?',
            val_mapping=on_off_vals,
            docstring="Set offset compensation on/off for "
            "resistance measurements.",
        )
        self.add_parameter(
            'trigger_source',
            set_cmd=':TRIG:SOUR {}',
            get_cmd=':TRIG:SOUR?',
            vals=Enum('IMM', 'TLIN'),
            docstring="Specify trigger control source."
            "IMMediate or TLINk.",
        )
        self.add_parameter(
            'arm_source',
            set_cmd=':ARM:SOUR {}',
            get_cmd=':ARM:SOUR?',
            vals=Enum('IMM', 'TLIN', "TIM", "MAN", "BUS", "NST", "PST", "BST"),
            docstring="Specify arm control source."
            "IMMediate, or TLINk, TIMer, MANual,"
            " BUS, NSTest, PSTest, or BSTest.",
        )
        self.add_parameter(
            'trigger_count',
            set_cmd=':TRIG:COUN {}',
            get_cmd=':TRIG:COUN?',
            vals=Ints(),
            docstring="How many times to trigger.",
        )
        self.add_parameter(
            'arm_count',
            set_cmd=':ARM:COUN {}',
            get_cmd=':ARM:COUN?',
            vals=Ints(),
            docstring="How many times to arm.",
        )
        self.add_parameter(
            'nplc',
            get_parser=float,
            set_cmd=':NPLC {}',
            get_cmd=':NPLC?',
            vals=Numbers(0.01, 10),
            docstring="Set integration time to the specified"
            "value in Number of Powerline Cycles.",
        )
        self.add_parameter(
            'digits',
            get_parser=int,
            set_cmd='DISP:DIG  {}',
            get_cmd='DISP:DIG?',
            vals=Ints(4, 7),
            docstring="Display resolution.",
        )
        self.add_parameter(
            'autozero',
            set_cmd='SYST:AZER:STAT {}',
            get_cmd='SYST:AZER:STAT?',
            val_mapping=on_off_vals,
            docstring="Enable autozero."
            "Enabling maximizes accuracy, "
            "disabling increases speed.",
        )
        self.add_parameter(
            'filter_auto',
            set_cmd='AVER:AUTO {}',
            get_cmd='AVER:AUTO?',
            val_mapping=on_off_vals,
            docstring="Automatically choose filtering.",
        )
        self.add_parameter(
            'filter_repeat_enabled',
            set_cmd=':AVER:REP:STAT {}',
            get_cmd='AVER:AUTO?',
            val_mapping=on_off_vals,
            docstring="Enable repeat filter.",
        )
        self.add_parameter(
            'filter_median_enabled',
            set_cmd=':MED:STAT {}',
            get_cmd=':MED:STAT?',
            val_mapping=on_off_vals,
            docstring="Enable median filter.",
        )
        self.add_parameter(
            'filter_moving_enabled',
            set_cmd=':AVER:STAT {}',
            get_cmd=':AVER:STAT?',
            val_mapping=on_off_vals,
            docstring="Enable moving average.",
        )
        self.add_parameter(
            'filter_repeat',
            get_parser=int,
            set_cmd=':AVER:REP:COUN {}',
            get_cmd=':AVER:REP:COUN?',
            vals=Ints(),
            docstring="Number of readings that are acquired"
            "and stored in the filter buffer.",
        )
        self.add_parameter(
            'filter_median',
            get_parser=int,
            set_cmd=':MED:RANK {}',
            get_cmd=':MED:RANK?',
            vals=Ints(),
            docstring="Number of reading samples"
            " for the median filter process.",
        )
        self.add_parameter(
            'filter_moving',
            get_parser=int,
            set_cmd=':AVER:COUN {}',
            get_cmd=':AVER:COUN?',
            vals=Ints(),
            docstring="Number of reading samples"
            " in the moving average filter.",
        )

        self.connect_message()

        if reset:
            self.reset()