def __init__(self, instrument_name, **kwargs): super().__init__(instrument_name, **kwargs) self._output_channels = { f'ch{ch}': Channel(instrument_name=self.instrument_name(), name=f'ch{ch}', id=ch, output=True) for ch in self.instrument.channel_idxs} self._pxi_channels = { f'pxi{k}': Channel(instrument_name=self.instrument_name(), name=f'pxi{k}', id=4000 + k, input_trigger=True, output=True, input=True) for k in range(self.instrument.n_triggers)} self._channels = { **self._output_channels, **self._pxi_channels, 'trig_in': Channel(instrument_name=self.instrument_name(), name='trig_in', input_trigger=True, input_TTL=(0, 5.0)), 'trig_out': Channel(instrument_name=self.instrument_name(), name='trig_out', output_TTL=(0, 3.3))} self.pulse_implementations = [ # TODO fix sinepulseimplementation by using pulse_to_waveform_sequence SinePulseImplementation( pulse_requirements=[('frequency', {'min': 0, 'max': 200e6}), ('amplitude', {'max': 1.5})]), AWGPulseImplementation( pulse_requirements=[]), CombinationPulseImplementation( pulse_requirements=[]), DCPulseImplementation( pulse_requirements=[('amplitude', {'min': -1.5, 'max': 1.5})]), DCRampPulseImplementation( pulse_requirements=[]), TriggerPulseImplementation( pulse_requirements=[]), MarkerPulseImplementation( pulse_requirements=[]) ] self.add_parameter('channel_selection', vals=vals.Lists(), get_cmd=self._get_active_channel_names) self.add_parameter('default_sampling_rates', set_cmd=None, initial_value=[500e6] * len(self.instrument.channel_idxs)) self.add_parameter('trigger_mode', set_cmd=None, initial_value='software', vals=vals.Enum('none', 'hardware', 'software'), docstring='Selects the method to run through the AWG queue.') self.trigger_thread = None self.waveforms = None self.waveform_queue = None self.started = False
def __init__( self, parent: InstrumentBase, dac_instrument: DACInterface, channel_id: int, layout_id: int, name: str = "nanotune_gate", label: str = "nanotune gate", line_type: str = "dc_current", safety_range: Tuple[float, float] = (-3, 0), use_ramp: bool = True, ramp_rate: float = 0.1, max_jump: float = 0.05, delay: float = 0.001, fast_readout_source: Optional[InstrumentChannel] = None, **kwargs, ) -> None: """ Args: dac_instrument (Optional[Parameter]): line_type (Optional[str]): min_v (Optional[float]): max_v (Optional[float]): use_ramp (Optional[bool]): ramp_rate (Optional[float]): max_jump (Optional[float]): delay (Optional[float]): Delay in between setting and measuring another parameter """ assert issubclass(dac_instrument.__class__, DACInterface) super().__init__(parent, name) self._dac_instrument = dac_instrument self._dac_channel = self._dac_instrument.nt_channels[channel_id] super().add_parameter( name="channel_id", label="instrument channel id", set_cmd=None, get_cmd=None, initial_value=channel_id, vals=vals.Ints(0), ) super().add_parameter( name="dc_voltage", label=f"{label} dc voltage", set_cmd=self.set_dc_voltage, get_cmd=self._dac_channel.get_dc_voltage, vals=vals.Numbers(*safety_range), ) self.has_ramp = self._dac_channel.supports_hardware_ramp super().add_parameter( name="label", label="gate label", set_cmd=self._dac_channel.set_label, get_cmd=self._dac_channel.get_label, initial_value=label, vals=vals.Strings(), ) qc_safety_range = (safety_range[0] - 0.01, safety_range[1] + 0.01) super().add_parameter( name="safety_range", label=f"{label} DC voltage safety range", set_cmd=self.set_safety_range, get_cmd=self.get_safety_range, initial_value=list(safety_range), vals=vals.Lists(), ) super().add_parameter( name="inter_delay", label=f"{label} inter delay", set_cmd=self._dac_channel.set_inter_delay, get_cmd=self._dac_channel.get_inter_delay, initial_value=delay, vals=vals.Numbers(), ) super().add_parameter( name="post_delay", label=label + " post delay", set_cmd=self._dac_channel.set_post_delay, get_cmd=self._dac_channel.get_post_delay, initial_value=delay, vals=vals.Numbers(), ) super().add_parameter( name="max_jump", label=f"{label} maximum voltage jump", set_cmd=self.set_max_jump, get_cmd=self.get_max_jump, initial_value=max_jump, vals=vals.Numbers(), ) super().add_parameter( name="step", label=f"{label} voltage step", set_cmd=self._dac_channel.set_step, get_cmd=self._dac_channel.get_step, initial_value=max_jump, vals=vals.Numbers(), ) super().add_parameter( name="ramp_rate", label=f"{label} ramp rate", set_cmd=self._dac_channel.set_ramp_rate, get_cmd=self._dac_channel.get_ramp_rate, initial_value=ramp_rate, vals=vals.Numbers(), ) super().add_parameter( name="use_ramp", label=f"{label} ramp setting", set_cmd=self.set_ramp, get_cmd=self.get_ramp, initial_value=use_ramp, vals=vals.Bool(), ) super().add_parameter( name="relay_state", label=f"{label} DAC channel relay state", set_cmd=self._dac_channel.set_relay_state, get_cmd=self._dac_channel.get_relay_state, initial_value=self._dac_channel.get_relay_state(), vals=vals.Strings(), ) super().add_parameter( name="layout_id", label=f"{label} device layout id", set_cmd=None, get_cmd=None, initial_value=layout_id, vals=vals.Ints(0), ) super().add_parameter( name="current_valid_range", label=f"{label} current valid range", set_cmd=self.set_current_valid_range, get_cmd=self.get_current_valid_range, initial_value=[], vals=vals.Lists(), ) super().add_parameter( name="transition_voltage", label=f"{label} transition voltage", set_cmd=self.set_transition_voltage, get_cmd=self.compute_transition_voltage, initial_value=0, vals=vals.Numbers(), ) super().add_parameter( name="amplitude", label=f"{label} sawtooth amplitude", set_cmd=self._dac_channel.set_amplitude, get_cmd=self._dac_channel.get_amplitude, initial_value=0, vals=vals.Numbers(-0.5, 0.5), ) super().add_parameter( name="offset", label=f"{label} sawtooth offset", set_cmd=self._set_offset, get_cmd=self._dac_channel.get_offset, initial_value=0, vals=vals.Numbers(*qc_safety_range), ) super().add_parameter( name="frequency", label=f"{label} sawtooth frequency", set_cmd=self._dac_channel.set_frequency, get_cmd=self._dac_channel.get_frequency, initial_value=0, vals=vals.Numbers(), )
def __init__(self, instrument_name, max_amplitude=1.5, **kwargs): assert max_amplitude <= 1.5 super().__init__(instrument_name, **kwargs) self._output_channels = { f"ch{k}": Channel(instrument_name=self.instrument_name(), name=f"ch{k}", id=k, output=True) for k in [1, 2] } # TODO add marker outputs self._channels = { **self._output_channels, "trig_in": Channel( instrument_name=self.instrument_name(), name="trig_in", input_trigger=True, ), "event_in": Channel( instrument_name=self.instrument_name(), name="event_in", input_trigger=True, ), "sync": Channel(instrument_name=self.instrument_name(), name="sync", output=True), } self.pulse_implementations = [ DCPulseImplementation(pulse_requirements=[ ("amplitude", { "max": max_amplitude }), ("duration", { "min": 100e-9 }), ]), SinePulseImplementation(pulse_requirements=[ ("frequency", { "min": -1.5e9, "max": 1.5e9 }), ("amplitude", { "min": 0, "max": max_amplitude }), ("duration", { "min": 100e-9 }), ]), FrequencyRampPulseImplementation(pulse_requirements=[ ("frequency_start", { "min": -1.5e9, "max": 1.5e9 }), ("frequency_stop", { "min": -1.5e9, "max": 1.5e9 }), ("amplitude", { "min": 0, "max": max_amplitude }), ("duration", { "min": 100e-9 }), ]), ] self.add_parameter( "trigger_in_duration", parameter_class=ManualParameter, unit="s", initial_value=1e-6, ) self.add_parameter( "active_channels", parameter_class=ManualParameter, initial_value=[], vals=vals.Lists(vals.Strings()), ) self.instrument.ch1.clear_waveforms() self.instrument.ch2.clear_waveforms() self.waveforms = {} # List of waveform arrays for each channel # Optional initial waveform for each channel. Used to set the first point # to equal the last voltage of the final pulse (see docstring for details) self.waveforms_initial = {} self.sequences = {} # List of sequence instructions for each channel # offsets list of actual programmed sample points versus expected points self.point_offsets = {} self.max_point_offsets = {} # Maximum absolute sample point offset self.point = { } # Current sample point, incremented as sequence is programmed # Maximum tolerable absolute point offset before raising a warning self.point_offset_limit = 100 # Add parameters that are not set via setup self.additional_settings = ParameterNode() for instrument_channel in self.instrument.channels: channel = ParameterNode(instrument_channel.name) setattr(self.additional_settings, instrument_channel.name, channel) channel.output_coupling = instrument_channel.output_coupling channel.sample_rate = instrument_channel.sample_rate
def __init__(self, parent, name, id, **kwargs): super().__init__(parent, name, **kwargs) self.id = id self.write = self.parent.write self.visa_handle = self.parent.visa_handle self.add_parameter( "continuous_run_mode", get_cmd="INITIATE:CONTINUOUS?", set_cmd="INITIATE:CONTINUOUS {}", val_mapping={ True: "ON", False: "OFF" }, docstring= "Choose to run in continuous mode (1) or triggered and gated mode (0)" "Continuous run mode repeats a waveform indefinitely without" "requiring a trigger.", ) self.add_parameter( "continuous_armed", get_cmd="INITIATE:CONTINUOUS:ENABLE?", set_cmd="INITIATE:CONTINUOUS:ENABLE {}", val_mapping={ True: "ARM", False: "SELF" }, docstring="Whether continuous mode should wait to be armed:\n" "\tWhen False, waveforms are straight away generated as " "soon as the output is on. " "\tWhen True, the AWG remains idle until an enable signal " "is received. During idling, the output depends on the " "output function.", ) self.add_parameter( "sample_rate", get_cmd="FREQUENCY:RASTER?", set_cmd="FREQUENCY:RASTER {:.8f}", get_parser=float, vals=vals.Numbers(10e6, 4.2e9), docstring="Set the sample rate of the arbitrary waveforms. Has no " "effect on standard waveforms", ) self.add_parameter( "frequency_standard_waveforms", unit="Hz", get_cmd="FREQUENCY?", set_cmd="FREQUENCY {:.8f}", get_parser=float, vals=vals.Numbers(10e-3, 250e6), docstring="Set the frequency (Hz) of standard waveforms", ) self.add_parameter( "function_mode", get_cmd="FUNCTION:MODE?", set_cmd="FUNCTION:MODE {}", vals=EnumVisa("FIXed", "USER", "SEQuenced", "ASEQuenced", "MODulated", "PULSe"), docstring="Run mode defines the type of waveform that is " "available. Possible run modes are:\n" "\tfixed: standard waveform shapes.\n" "\tuser: arbitrary waveform shapes.\n" "\tsequenced: sequence of arbitrary waveforms.\n" "\tasequenced: advanced sequence of arbitrary " "waveforms.\n" "\tmodulated: modulated (standard) waveforms.\n" "\tpulse: digital pulse function", ) self.add_parameter( "output_coupling", get_cmd="OUTPUT:COUPLING?", set_cmd="OUTPUT:COUPLING {}", vals=vals.Enum("DC", "DAC", "AC"), docstring="Possible output couplings are:\n" "\tDC: optimized for pulses at high amplitudes.\n" "\tDAC: optimized for bandwidth but low amplitude.\n" "\tAC: optimized for bandwidth.\n" "Note that DC and DAC use the DC output, and AC uses " "the AC output. DC and DAC couplings also allow " "control of amplitude and offset", ) self.add_parameter( "output", get_cmd="OUTPUT?", set_cmd="OUTPUT {}", vals=EnumVisa("ON", "OFF"), ) self.add_parameter( "sync", get_cmd="OUTPUT:SYNC?", set_cmd="OUTPUT:SYNC {}", vals=EnumVisa("ON", "OFF"), ) self.add_parameter( "power", unit="dBm", get_cmd="POWER?", set_cmd="POWER {:.8f}", get_parser=float, vals=vals.Numbers(-5, 5), # Might be -5 to 5, manual is unclear docstring= "Set output power (dBm) from AC output path (50-ohm matched)", ) self.add_parameter( "voltage_DAC", unit="V", get_cmd="VOLTAGE:DAC?", set_cmd="VOLTAGE:DAC {:.8f}", get_parser=float, vals=vals.Numbers(50e-3, 2), docstring="Waveform amplitude (V) when routed through the DAC path", ) self.add_parameter( "voltage_DC", unit="V", get_cmd="VOLTAGE?", set_cmd="VOLTAGE {:.8f}", get_parser=float, vals=vals.Numbers(50e-3, 2), docstring="Waveform amplitude (V) when routed through the DC path", ) self.add_parameter( "voltage_offset", unit="V", get_cmd="VOLTAGE:OFFSET?", set_cmd="VOLTAGE:OFFSET {:.8f}", get_parser=float, vals=vals.Numbers(-1.5, 1.5), docstring="Voltage offset (V) when routed through DAC or DC path", ) self.add_parameter( "output_modulation", get_cmd="MODulation:TYPE?", set_cmd="MODulation:TYPE {}", vals=EnumVisa("OFF", "AM", "FM", "SWEEP"), ) # Trigger parameters self.add_parameter( "trigger_input", set_cmd="TRIGGER:{}", vals=vals.Enum("ECL", "TTL"), docstring="Set trigger input. Possible inputs are:\n" "\tECL: negative signal at fixed -1.3V.\n" "\tTTL: variable trigger_level", ) self.add_parameter( "trigger_source", get_cmd="TRIGGER:SOURCE:ADVANCE?", set_cmd="TRIGGER:SOURCE:ADVANCE {}", vals=EnumVisa("EXTernal", "BUS", "TIMer", "EVENt"), docstring="Possible trigger sources are:\n" "\texternal: Use TRIG IN port exclusively.\n" "\tbus: Use remote commands exclusively.\n" "\ttimer: Use internal trigger generator exclusively.\n" "\tevent: Use EVENT IN port exclusively.", ) self.add_parameter( "trigger_mode", get_cmd="TRIGGER:MODE?", set_cmd="TRIGGER:MODE {}", vals=EnumVisa("NORMal", "OVERride"), docstring="Possible trigger modes are:\n" "\tnormal: the first trigger activates the output and " "consecutive triggers are ignored for the duration of " "the output waveform.\n" "\toverride: the first trigger activates the output " "and consecutive triggers restart the output waveform, " "regardless if the current waveform has been completed " "or not.", ) self.add_parameter( "trigger_timer_mode", get_cmd="TRIGGER:TIMER:MODE?", set_cmd="TRIGGER:TIMER:MODE {}", vals=EnumVisa("TIME", "DELay"), docstring="Possible modes of internal trigger are:\n" "\ttime: Perform trigger at fixed time interval.\n" "\tdelay: Perform trigger at fixed time intervals after " "previous waveform finished.", ) self.add_parameter( "trigger_timer_time", get_cmd="TRIGGER:TIMER:TIME?", set_cmd="TRIGGER:TIMER:TIME {:f}", get_parser=float, unit="s", vals=vals.Numbers(100e-9, 20), docstring= "Triggering period (s) when in internal trigger timer mode") self.add_parameter( "trigger_timer_delay", get_cmd="TRIGGER:TIMER:DELAY?", set_cmd="TRIGGER:TIMER:DELAY {:d}", get_parser=int, unit="1/sample rate", vals=vals.Multiples(min_value=152, max_value=8000000, divisor=8), docstring="Delay of the internal trigger generator.") self.add_parameter( "trigger_level", get_cmd="TRIGGER:LEVEL?", set_cmd="TRIGGER:LEVEL {:.4f}", get_parser=float, vals=vals.Numbers(-5, 5), unit="V", docstring="Trigger level when trigger_mode is TTL", ) self.add_parameter( "trigger_slope", get_cmd="TRIGGER:SLOPE?", set_cmd="TRIGGER:SLOPE {}", vals=EnumVisa("POSitive", "NEGative", "EITher"), ) self.add_parameter( "trigger_delay", get_cmd="TRIGGER:DELAY?", set_cmd="TRIGGER:DELAY {:.4f}", get_parser=float, unit="1/sample rate", vals=vals.Multiples(min_value=0, max_value=8000000, divisor=8), docstring="Delay between receiving an external trigger, and " "outputting the first waveform") self.add_parameter( "burst_count", get_cmd="TRIGGER:COUNT?", set_cmd="TRIGGER:COUNT {}", set_parser=int, get_parser=int, vals=vals.Numbers(1, 1048576), docstring="Perform number of waveform cycles after trigger.", ) # Waveform parameters self.add_parameter("uploaded_waveforms", set_cmd=None, initial_value=[], vals=vals.Lists(), docstring="List of uploaded waveforms", snapshot_value=False) self.add_parameter( "waveform_timing", get_cmd="TRACE:SELECT:TIMING?", set_cmd="TRACE:SELECT:TIMING {}", vals=EnumVisa("COHerent", "IMMediate"), docstring="Possible waveform timings are:\n" "\tcoherent: finish current waveform before next.\n" "\timmediate: immediately skip to next waveform", ) # Sequence parameters self.add_parameter("uploaded_sequence", parameter_class=ManualParameter, vals=vals.Iterables()) self.add_parameter( "sequence_mode", get_cmd="SEQUENCE:ADVANCE?", set_cmd="SEQUENCE:ADVANCE {}", vals=EnumVisa("AUTOmatic", "ONCE", "STEPped"), docstring="Possible sequence modes are:\n" "\tautomatic: Automatically continue to next waveform, " "and repeat sequence from start when finished. When " "encountering jump command, wait for event input " "before continuing.\n" "\tonce: Automatically continue to next waveform. Stop " "when sequence completed.\n" "\tstepped: wait for event input after each waveform. " "Repeat sequence when completed.", ) self.add_parameter( "sequence_once_count", get_cmd="SEQUENCE:ONCE:COUNT?", set_cmd="SEQUENCE:ONCE:COUNT {}", set_parser=int, get_parser=int, vals=vals.Numbers(1, 1048575), docstring="Determines the number of times a waveform sequence will" "be repeated.", ) self.add_parameter( "sequence_jump", get_cmd="SEQUENCE:JUMP?", set_cmd="SEQUENCE:JUMP {}", vals=EnumVisa("BUS", "EVENt"), docstring="Determines the trigger source that will cause the " "sequence to advance after a jump bit. " "Possible jump modes are:\n" "\tbus: only advance after a remote trigger command.\n" "\tevent: only advance after an event input.", ) self.add_parameter( "sequence_select_source", get_cmd="SEQUENCE:SELECT:SOURCE?", set_cmd="SEUQENCE:SELECT:SOURCE {}", vals=EnumVisa("BUS", "EXTernal"), docstring="Possible sources that can select active sequence:\n" "\tbus: sequence switches when remote command is " "called.\n" "\texternal: rear panel connector can dynamically " "choose " "next sequence.", ) self.add_parameter( "sequence_select_timing", get_cmd="SEQUENCE:SELECT:TIMING?", set_cmd="SEQUENCE:SELECT:TIMING {}", vals=EnumVisa("COHerent", "IMMediate"), docstring="Possible ways in which the generator transitions from " "sequence to sequence:\n" "c\toherent: transition once current sequence is done.\n" "\timmediate: abort current sequence and progress to " "next", ) self.add_parameter( "sequence_pre_step", get_cmd="SEQUENCE:PREStep?", set_cmd="SEQUENCE:PREStep {}", vals=EnumVisa("WAVE", "DC"), docstring="Choose to play a blank DC segment while waiting for an " "event signal to initiate or continue a sequence.", ) # Functions self.add_function( "enable", call_cmd=f"INST {self.id};ENABLE", docstring="An immediate and unconditional generation of the " "selected output waveform. Must be armed and in " "continuous mode.", ) self.add_function( "abort", call_cmd=f"INST {self.id};ABORT", docstring="An immediate and unconditional termination of the " "output waveform.", ) self.add_function( "trigger", call_cmd=f"INST {self.id};TRIGGER", docstring="Perform software trigger", ) self.add_function("on", call_cmd=f"INST {self.id};OUTPUT ON", docstring="Turn output on") self.add_function("off", call_cmd=f"INST {self.id};OUTPUT OFF", docstring="Turn output off") # Query current values for all parameters for param_name, param in self.parameters.items(): param()
def __init__(self, parent: Instrument, name, aid): """ Args: parent: The ANC300 instance to which the channel is to be attached name: The name of the channel aid: The axis id (slot number) of the module """ super().__init__(parent, name) self.aid = aid serial_no = self.ask('getser {:d}'.format(aid)) self.model = serial_no.split('-')[0][:-1] if self.model in ('ANM300', 'NULL'): filter_mapping = {16: '16', 160: '160', 'off': 'off'} elif self.model == 'ANM200': filter_mapping = {1.6: "1.6", 16: '16', 160: '160', 1600: '1600', 'off': 'off'} elif self.model == 'ANM150': filter_mapping = None else: raise ValueError('Module model {!s} ' 'is not supported.'.format(self.model)) # TODO(ThibaudRuelle) add soft limits, initial values if adequate # TODO(Thibaud Ruelle) ans_parser = self._parent.ans_parser # leads to error in add_parameter at instantiation time # TODO(Thibaud Ruelle) use set_cmd = False instead of vals= ? def ans_parser(name, ans, unit=None, parser=str): """ Parse "{name} = {value} ({unit})" type answers from ANC300. Args: name: The expected name ans: The answer from the instrument unit: The expected unit(s). String of list of strings. Defaults to None. parser: Function to use to parse the value. Returns parser(value). """ ans = ans.strip().replace('=', ' ') ansparts = ans.split() ans_name, ans_val = ansparts[:2] if type(unit) == str or unit is None: unit = [unit,] if ans_val == '?': return None try: ans_unit = ansparts[2] except IndexError: ans_unit = None if ans_name != name: raise ValueError('Expected value name {!r}, ' 'received {!r}.'.format(name, ans_name)) if not ans_unit in unit: raise ValueError('Expected value unit {!r}, ' 'received {!r}.'.format(unit, ans_unit)) return parser(ans_val) # general parameters self.add_parameter('serial_no', get_cmd='getser {}'.format(self.aid), vals=vals.Strings()) # unnecessary when #651 in pip self.add_parameter('mode', get_cmd='getm {}'.format(self.aid), get_parser=partial(ans_parser, 'mode'), set_cmd='setm {} {{}}'.format(self.aid), label='Axis mode', vals=vals.Enum('gnd', 'inp', 'cap', 'stp', 'off', 'stp+', 'stp-')) self.add_parameter('output_voltage', get_cmd='geto {}'.format(self.aid), get_parser=partial(ans_parser, 'voltage', unit='V', parser=float), label='Output voltage', unit='V') self.add_parameter('capacitance', get_cmd='getc {}'.format(self.aid), get_parser=partial(ans_parser, 'capacitance', unit='nF', parser=float), label='Capacitance', unit='nF') self.add_function('update_capacitance', call_cmd='setm {} cap'.format(self.aid)) self.add_function('wait_capacitance_updated', call_cmd='stop {}'.format(self.aid)) # scanning parameters if self.model in ('ANM300', 'ANM200', 'NULL'): self.add_parameter('offset_voltage', get_cmd='geta {}'.format(self.aid), get_parser=partial(ans_parser, 'voltage', unit='V', parser=float), set_cmd='seta {} {{:.6f}}'.format(self.aid), label='Offset voltage', unit='V', vals=vals.Numbers(0, 150)) self.add_parameter('ac_in', get_cmd='getaci {}'.format(self.aid), get_parser=partial(ans_parser, 'acin'), set_cmd='setaci {} {{!s}}'.format(self.aid), label='AC input status', val_mapping={True: 'on', False: 'off'}) self.add_parameter('dc_in', get_cmd='getdci {}'.format(self.aid), get_parser=partial(ans_parser, 'dcin'), set_cmd='setdci {} {{!s}}'.format(self.aid), label='DC input status', val_mapping={True: 'on', False: 'off'}) if filter_mapping: self.add_parameter('outp_filter', get_cmd='getfil {}'.format(self.aid), get_parser=partial(ans_parser, 'filter'), set_cmd='setfil {} {{!s}}'.format(self.aid), label='Output low-pass filter', unit='Hz', val_mapping=filter_mapping) # stepping parameters if self.model in ('ANM300', 'ANM150', 'NULL'): self.add_parameter('step_frequency', get_cmd='getf {}'.format(self.aid), get_parser=partial(ans_parser, 'frequency', unit=['Hz','H'], parser=int), set_cmd='setf {} {{:.0f}}'.format(self.aid), label='Stepping frequency', unit='Hz', vals=vals.Ints(1, 10000)) self.add_parameter('step_amplitude', get_cmd='getv {}'.format(self.aid), get_parser=partial(ans_parser, 'voltage', unit='V', parser=float), set_cmd='setv {} {{:.6f}}'.format(self.aid), label='Stepping amplitude', unit='V', vals=vals.Numbers(0, 150)) # TODO(Thibaud Ruelle): define acceptable vals properly for patterns self.add_parameter('step_up_pattern', get_cmd='getpu {}'.format(self.aid), get_parser=lambda s: [int(u) for u in s.split('\r\n')], set_cmd='setpu {} {{!s}}'.format(self.aid), set_parser=lambda l: " ".join([str(u) for u in l]), vals=vals.Lists()) # unnecessary when #651 in pip self.add_parameter('step_down_pattern', get_cmd='getpd {}'.format(self.aid), get_parser=lambda s: [int(u) for u in s.split('\r\n')], set_cmd='setpd {} {{!s}}'.format(self.aid), set_parser=lambda l: " ".join([str(u) for u in l]), vals=vals.Lists()) # unnecessary when #651 in pip self.add_function('step_up_single', call_cmd='stepu {}'.format(self.aid)) self.add_function('step_up_cont', call_cmd='stepu {} c'.format(self.aid)) self.add_function('step_up', call_cmd='stepu {} {{:d}}'.format(self.aid), args=[vals.Ints(min_value=1)]) self.add_function('step_down_single', call_cmd='stepd {}'.format(self.aid)) self.add_function('step_down_cont', call_cmd='stepu {} c'.format(self.aid)) self.add_function('step_down', call_cmd='stepd {} {{:d}}'.format(self.aid), args=[vals.Ints(min_value=1)]) self.add_function('stop', call_cmd='stop {}'.format(self.aid)) def wait_steps_end(self): old_timeout = self.root_instrument.timeout() try: self.root_instrument.timeout.set(3600) self.write_raw(f'stepw {self.aid}') finally: self.root_instrument.timeout.set(old_timeout) self.wait_steps_end = types.MethodType(wait_steps_end, self) # be sure to import types # TODO(Thibaud Ruelle): test for range before adding param self.add_parameter('trigger_up_pin', get_cmd='gettu {}'.format(self.aid), get_parser=partial(ans_parser, 'trigger'), set_cmd='settu {} {{!s}}'.format(self.aid), label='Input trigger up pin', val_mapping={i: str(i) for i in ['off', *range(1, 15)]}) self.add_parameter('trigger_down_pin', get_cmd='gettd {}'.format(self.aid), get_parser=partial(ans_parser, 'trigger'), set_cmd='settd {} {{!s}}'.format(self.aid), label='Input trigger down pin', val_mapping={i: str(i) for i in ['off', *range(1, 15)]})