def add_additional_parameters(self): """ Dummy version, parameters are added as manual parameters """ self.add_parameter( 'eqasm_program', label=('Upload instructions'), docstring='It uploads the instructions to the CC-Light. ' + 'Valid input is a string representing the filename', parameter_class=ManualParameter, vals=vals.Strings() ) self.add_parameter( 'control_store', label=('Upload microcode'), docstring='It uploads the microcode to the CC-Light. ' + 'Valid input is a string representing the filename', parameter_class=ManualParameter, vals=vals.Strings() ) self.add_parameter( 'qisa_opcode', parameter_class=ManualParameter, vals=vals.Strings() )
def __init__(self, name, address, **kwargs): super().__init__(name, address, **kwargs) self.add_parameter(name='frequency', label='Frequency', unit='Hz', get_cmd='SOUR:FREQ' + '?', set_cmd='SOUR:FREQ' + ' {:.2f}', get_parser=float, vals=vals.Numbers(1e9, 20e9)) self.add_parameter(name='phase', label='Phase', unit='deg', get_cmd='SOUR:PHAS' + '?', set_cmd='SOUR:PHAS' + ' {:.2f}', get_parser=float, vals=vals.Numbers(0, 360)) self.add_parameter(name='power', label='Power', unit='dBm', get_cmd='SOUR:POW' + '?', set_cmd='SOUR:POW' + ' {:.2f}', get_parser=float, vals=vals.Numbers(-120, 25)) self.add_parameter('status', get_cmd=':OUTP:STAT?', set_cmd=self.set_status, get_parser=self.parse_on_off, vals=vals.Strings()) self.add_parameter('pulsemod_state', get_cmd=':SOUR:PULM:STAT?', set_cmd=self.set_pulsemod_state, get_parser=self.parse_on_off, vals=vals.Strings()) self.add_parameter('pulsemod_source', get_cmd='SOUR:PULM:SOUR?', set_cmd=self.set_pulsemod_source, vals=vals.Strings()) self.add_parameter('ref_osc_source', label='Reference oscillator source', get_cmd='SOUR:ROSC:SOUR?', set_cmd='SOUR:ROSC:SOUR {}', vals=vals.Enum('INT', 'EXT')) # Frequency mw_source outputs when used as a reference self.add_parameter('ref_osc_output_freq', label='Reference oscillator output frequency', get_cmd='SOUR:ROSC:OUTP:FREQ?', set_cmd='SOUR:ROSC:OUTP:FREQ {}', vals=vals.Enum('10MHz', '100MHz', '1000MHz')) # Frequency of the external reference mw_source uses self.add_parameter('ref_osc_external_freq', label='Reference oscillator external frequency', get_cmd='SOUR:ROSC:EXT:FREQ?', set_cmd='SOUR:ROSC:EXT:FREQ {}', vals=vals.Enum('10MHz', '100MHz', '1000MHz')) self.add_function('reset', call_cmd='*RST') self.add_function('run_self_tests', call_cmd='*TST?') self.connect_message()
def add_qubit_parameters(self): # Qubit attributes are set per channel row (so all modules in one go) for channel in self.channels: ch_name = '_ch{c}'.format(c=channel) ch_scpi = ':CHANNEL{c}'.format(c=channel) doc_description = 'Qubit description on display ' \ 'for row {c}'.format(c=channel) self.add_parameter('qubit' + ch_name + '_description', docstring=doc_description, get_cmd='QUBIT' + ch_scpi + ':DESCRIPTION?', set_cmd='QUBIT' + ch_scpi + ':DESCRIPTION {}', vals=validators.Strings()) doc_frequency = 'Qubit frequency in Hz for row {c}. ' \ 'Range 4.0E9--8.0E9 Hz.'.format(c=channel) self.add_parameter('qubit' + ch_name + '_frequency', docstring=doc_frequency, unit='Hz', get_cmd='QUBIT' + ch_scpi + ':FREQUENCY?', set_cmd='QUBIT' + ch_scpi + ':FREQUENCY {}', vals=validators.Numbers(), get_parser=float) colors = ', '.join([ 'black', 'blue', 'green', 'grey', 'orange', 'red', 'white', 'yellow', 'dcl_blue', 'dcl_green', 'dcl_red', 'dcl_violet' ]) doc_color = 'Qubit led and display color for row {c}. ' \ 'Can either be one of the predefined colors ({lst})' \ 'or a RGB hex string like "#rrggbb".'.format(c=channel, lst=colors) self.add_parameter('qubit' + ch_name + '_led_color', docstring=doc_color, get_cmd='QUBIT' + ch_scpi + ':LEDCOLOR?', set_cmd='QUBIT' + ch_scpi + ':LEDCOLOR {}', vals=validators.Strings()) # Individual channels can be switched on or off for mod in self.modules: mod_ch_name = '_mod{m}_ch{c}'.format(m=mod, c=channel) mod_ch_scpi = ':MODULE{m}:CHANNEL{c}'.format(m=mod, c=channel) doc_on_off = 'On/off state for channel {c} of ' \ 'module {m}'.format(m=mod, c=channel) self.add_parameter('qubit' + mod_ch_name, docstring=doc_on_off, get_cmd='QUBIT' + mod_ch_scpi + '?', set_cmd='QUBIT' + mod_ch_scpi + ' {}', vals=validators.OnOff())
def __init__(self, name, address, **kwargs): super().__init__(name, **kwargs) self.add_parameter(name='frequency', label='Frequency', unit='Hz', parameter_class=ManualParameter, get_parser=float, vals=vals.Numbers(1e6, 20e9)) self.add_parameter(name='phase', label='Phase', unit='deg', parameter_class=ManualParameter, get_parser=float, vals=vals.Numbers(0, 360)) self.add_parameter(name='power', label='Power', unit='dBm', parameter_class=ManualParameter, get_parser=float, vals=vals.Numbers(-120, 25)) self.add_parameter('status', parameter_class=ManualParameter, get_parser=self.parse_on_off, vals=vals.Strings()) self.add_parameter('pulsemod_state', parameter_class=ManualParameter, get_parser=self.parse_on_off, vals=vals.Strings()) self.add_parameter('pulsemod_source', parameter_class=ManualParameter, vals=vals.Strings()) self.add_parameter('ref_osc_source', label='Reference oscillator source', parameter_class=ManualParameter, vals=vals.Enum('INT', 'EXT')) # Frequency mw_source outputs when used as a reference self.add_parameter('ref_osc_output_freq', label='Reference oscillator output frequency', parameter_class=ManualParameter, vals=vals.Enum('10MHz', '100MHz', '1000MHz')) # Frequency of the external reference mw_source uses self.add_parameter('ref_osc_external_freq', label='Reference oscillator external frequency', parameter_class=ManualParameter, vals=vals.Enum('10MHz', '100MHz', '1000MHz')) self.add_function('reset', call_cmd='*RST') self.add_function('run_self_tests', call_cmd='*TST?') self.connect_message()
def __init__( self, parent: InstrumentBase, dac_instrument: DACInterface, channel_id: int, ohmic_id: int, name: str = "ohmic", label: str = "ohmic", **kwargs, ) -> None: 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="label", label="ohmic label", set_cmd=self._dac_channel.set_label, get_cmd=self._dac_channel.get_label, initial_value=label, vals=vals.Strings(), ) super().add_parameter( name="ohmic_id", label=self.label() + " ohmic number", set_cmd=None, get_cmd=None, initial_value=ohmic_id, vals=vals.Ints(0), ) 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(), )
def __init__(self, name, address, verbose=1, reset=False, **kwargs): self.verbose = verbose log.debug(__name__ + ' : Initializing instrument') super().__init__(name, address, **kwargs) # TODO(TF): check what parser parameters can do # check what 'tags=['sweep']' and 'types' do in qtlab # fix format types self.add_parameter('frequency', label='Frequency', get_cmd=self.do_get_frequency, set_cmd=self.do_set_frequency, vals=vals.Numbers(10e6, 40e9), unit='Hz') self.add_parameter('power', label='Power', get_cmd=self.do_get_power, set_cmd=self.do_set_power, vals=vals.Numbers(-30, 25), unit='dBm') self.add_parameter('status', get_cmd=self.do_get_status, set_cmd=self.do_set_status, vals=vals.Strings()) # TODO(TF): check how to fix the get functions self.add_parameter('status_of_modulation', get_cmd=self.do_get_status_of_modulation, set_cmd=self.do_set_status_of_modulation, vals=vals.Strings()) self.add_parameter('status_of_ALC', get_cmd=self.do_get_status_of_ALC, set_cmd=self.do_set_status_of_ALC, vals=vals.Strings()) self.add_parameter('pulse_delay', get_cmd=self.do_get_pulse_delay, set_cmd=self.do_set_pulse_delay) # TODO(TF): check the way of defining this type of functions, where logging is added # self.add_function('reset') # self.add_function('get_all') if reset: self.reset() else: self.get_all() self.connect_message()
def __init__(self, parent: Instrument, name: str, **kwargs): super().__init__(parent, name, **kwargs) self.add_parameter( 'decimation', ManualParameter, vals=vals.Ints(1), initial_value=1, docstring='The sample rate is reduced by the decimation factor ' 'after filtering.') self.add_parameter('coefficients', ManualParameter, vals=vals.Arrays(), docstring='FIR filter coefficients') self.add_parameter('description', ManualParameter, vals=vals.Strings(), docstring='FIR filter description') self.add_parameter( 'mode', ManualParameter, vals=vals.Enum('full', 'valid'), initial_value='full', docstring='Convolution mode. If `valid`, only points where the ' 'filter and signal overlap completely are returned.') self.coefficients.set(np.array([1.]))
def _sync_time_and_add_parameter(self): doc_description = 'Parameter to sync the time from user computer to VSM' self.add_parameter('sync_time', docstring=doc_description, set_cmd='SYSTEM'+':TIME {}', vals=validators.Strings()) current_time_str = datetime.now().strftime('%YT%mT%dT%HT%MT%S') self.sync_time(current_time_str)
def init(): a_property = Parameter('a_property', set_cmd=None, get_cmd=None, initial_value=0) another_property = Parameter('another_property', set_cmd=None, get_cmd=None, initial_value='abc', vals=validators.Strings()) station = Station(a_property, another_property) return station
def __init__(self, name, address=None, **kwargs): super().__init__(name, **kwargs) self.add_parameter(name='frequency', label='Frequency', unit='Hz', parameter_class=ManualParameter, vals=vals.Numbers(1e6, 20e9)) self.add_parameter(name='phase', label='Phase', unit='deg', parameter_class=ManualParameter, vals=vals.Numbers(0, 360)) self.add_parameter(name='power', label='Power', unit='dBm', parameter_class=ManualParameter, vals=vals.Numbers(-120, 25)) self.add_parameter('status', parameter_class=ManualParameter, vals=vals.Strings()) self.add_parameter('pulsemod_state', parameter_class=ManualParameter, vals=vals.Strings()) self.add_parameter('pulsemod_source', parameter_class=ManualParameter, vals=vals.Strings()) self.add_parameter('ref_osc_source', label='Reference oscillator source', parameter_class=ManualParameter, vals=vals.Enum('INT', 'EXT')) # Frequency it outputs when used as a reference self.add_parameter('ref_osc_output_freq', label='Reference oscillator output frequency', parameter_class=ManualParameter, vals=vals.Enum('10MHz', '100MHz', '1000MHz')) # Frequency of the external reference it uses self.add_parameter('ref_osc_external_freq', label='Reference oscillator external frequency', parameter_class=ManualParameter, vals=vals.Enum('10MHz', '100MHz', '1000MHz')) self.connect_message()
def __init__(self, name, address, **kwargs): super().__init__(name, address, **kwargs) self.add_parameter(name='frequency', label='Frequency', units='Hz', get_cmd='SOUR:FREQ' + '?', set_cmd='SOUR:FREQ' + ' {:.2f}', get_parser=float, vals=vals.Numbers(1e9, 20e9)) self.add_parameter(name='phase', label='Phase', units='deg', get_cmd='SOUR:PHAS' + '?', set_cmd='SOUR:PHAS' + ' {:.2f}', get_parser=float, vals=vals.Numbers(0, 360)) self.add_parameter(name='power', label='Power', units='dBm', get_cmd='SOUR:POW' + '?', set_cmd='SOUR:POW' + ' {:.2f}', get_parser=float, vals=vals.Numbers(-120, 25)) self.add_parameter('status', get_cmd=':OUTP:STAT?', set_cmd=self.set_status, get_parser=self.parse_on_off, vals=vals.Strings()) self.add_parameter('pulsemod_state', get_cmd=':SOUR:PULM:STAT?', set_cmd=self.set_pulsemod_state, get_parser=self.parse_on_off, vals=vals.Strings()) self.add_parameter('pulsemod_source', get_cmd='SOUR:PULM:SOUR?', set_cmd=self.set_pulsemod_source, vals=vals.Strings()) self.add_function('reset', call_cmd='*RST') self.add_function('run_self_tests', call_cmd='*TST?') self.connect_message()
def add_additional_parameters(self): """ Certain hardware specific parameters cannot be generated automatically. This function generates the functions to upload instructions for the user. They are special because these functions use the _upload_instructions and _upload_microcode functions internally, and they output binary data using the SCPI.py driver, which is not qcodes standard. Therefore, we have to manually created them specifically for CC-Light. """ self.add_parameter( 'eqasm_program', label=('eQASM program'), docstring='Uploads the eQASM program to the CC-Light. ' + 'Valid input is a string representing the filename.', set_cmd=self._upload_instructions, vals=vals.Strings() ) self.add_parameter( 'control_store', label=('Control store'), docstring='Uploads the microcode to the CC-Light. ' + 'Valid input is a string representing the filename.', set_cmd=self._upload_microcode, vals=vals.Strings() ) self.add_parameter( 'qisa_opcode', label=('QISA opcode qmap'), docstring='Uploads the opcode.qmap to the CC-Light assembler. ' + 'Valid input is a string representing the filename.', set_cmd=self._upload_opcode_qmap, vals=vals.Strings() ) self.add_parameter('last_loaded_instructions', vals=vals.Strings(), initial_value='', parameter_class=ManualParameter)
def __init__( self, parent: InstrumentBase, name: str = "node", label: str = "", node_type: Optional[str] = None, n_init: int = 0, v_init: float = 0, ): docstring = """ """ super().__init__(parent, name) self.add_parameter( "node_type", label="node type " + label, unit=None, get_cmd=None, set_cmd=None, initial_value=node_type, vals=vals.Strings(), ) self.add_parameter( "n", label="number of charges " + label, unit=None, set_cmd=self._set_n, get_cmd=self._get_n, initial_value=n_init, vals=vals.Ints(-100000, 100000), ) self.add_parameter( "v", label="voltage node " + label, unit="V", set_cmd=self._set_v, get_cmd=self._get_v, initial_value=v_init, vals=vals.Numbers(-100000, 100000), )
def add_parameters(self): ####################################################################### # QWG specific ####################################################################### for i in range(self.device_descriptor.numChannels // 2): ch_pair = i * 2 + 1 sfreq_cmd = 'qutech:output{}:frequency'.format(ch_pair) sph_cmd = 'qutech:output{}:phase'.format(ch_pair) # NB: sideband frequency has a resolution of ~0.23 Hz: self.add_parameter('ch_pair{}_sideband_frequency'.format(ch_pair), parameter_class=HandshakeParameter, unit='Hz', label=('Sideband frequency channel ' + 'pair {} (Hz)'.format(i)), get_cmd=sfreq_cmd + '?', set_cmd=sfreq_cmd + ' {}', vals=vals.Numbers(-300e6, 300e6), get_parser=float) self.add_parameter('ch_pair{}_sideband_phase'.format(ch_pair), parameter_class=HandshakeParameter, unit='deg', label=('Sideband phase channel' + ' pair {} (deg)'.format(i)), get_cmd=sph_cmd + '?', set_cmd=sph_cmd + ' {}', vals=vals.Numbers(-180, 360), get_parser=float) self.add_parameter( 'ch_pair{}_transform_matrix'.format(ch_pair), parameter_class=HandshakeParameter, label=('Transformation matrix channel' + 'pair {}'.format(i)), get_cmd=self._gen_ch_get_func(self._getMatrix, ch_pair), set_cmd=self._gen_ch_set_func(self._setMatrix, ch_pair), # NB range is not a hardware limit vals=vals.Arrays(-2, 2, shape=(2, 2))) for i in range(1, self.device_descriptor.numTriggers + 1): triglev_cmd = 'qutech:trigger{}:level'.format(i) # individual trigger level per trigger input: self.add_parameter('tr{}_trigger_level'.format(i), unit='V', label='Trigger level channel {} (V)'.format(i), get_cmd=triglev_cmd + '?', set_cmd=triglev_cmd + ' {}', vals=self.device_descriptor.mvals_trigger_level, get_parser=float) self.add_parameter('run_mode', get_cmd='AWGC:RMO?', set_cmd='AWGC:RMO ' + '{}', vals=vals.Enum('NONE', 'CONt', 'SEQ', 'CODeword')) # NB: setting mode "CON" (valid SCPI abbreviation) reads back as "CONt" # Channel parameters # for ch in range(1, self.device_descriptor.numChannels + 1): amp_cmd = 'SOUR{}:VOLT:LEV:IMM:AMPL'.format(ch) offset_cmd = 'SOUR{}:VOLT:LEV:IMM:OFFS'.format(ch) state_cmd = 'OUTPUT{}:STATE'.format(ch) waveform_cmd = 'SOUR{}:WAV'.format(ch) output_voltage_cmd = 'QUTEch:OUTPut{}:Voltage'.format(ch) dac_temperature_cmd = 'STATus:DAC{}:TEMperature'.format(ch) gain_adjust_cmd = 'DAC{}:GAIn:DRIFt:ADJust'.format(ch) dac_digital_value_cmd = 'DAC{}:DIGitalvalue'.format(ch) # Set channel first to ensure sensible sorting of pars # Compatibility: 5014, QWG self.add_parameter('ch{}_state'.format(ch), label='Status channel {}'.format(ch), get_cmd=state_cmd + '?', set_cmd=state_cmd + ' {}', val_mapping={ True: '1', False: '0' }, vals=vals.Bool()) self.add_parameter( 'ch{}_amp'.format(ch), parameter_class=HandshakeParameter, label='Channel {} Amplitude '.format(ch), unit='Vpp', docstring='Amplitude channel {} (Vpp into 50 Ohm)'.format(ch), get_cmd=amp_cmd + '?', set_cmd=amp_cmd + ' {:.6f}', vals=vals.Numbers(-1.6, 1.6), get_parser=float) self.add_parameter( 'ch{}_offset'.format(ch), # parameter_class=HandshakeParameter, label='Offset channel {}'.format(ch), unit='V', get_cmd=offset_cmd + '?', set_cmd=offset_cmd + ' {:.3f}', vals=vals.Numbers(-.25, .25), get_parser=float) self.add_parameter('ch{}_default_waveform'.format(ch), get_cmd=waveform_cmd + '?', set_cmd=waveform_cmd + ' "{}"', vals=vals.Strings()) self.add_parameter('status_dac{}_temperature'.format(ch), unit='C', label=('DAC {} temperature'.format(ch)), get_cmd=dac_temperature_cmd + '?', get_parser=float, docstring='Reads the temperature of a DAC.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') self.add_parameter('output{}_voltage'.format(ch), unit='V', label=('Channel {} voltage output').format(ch), get_cmd=output_voltage_cmd + '?', get_parser=float, docstring='Reads the output voltage of a channel.\n' \ +'Notes:\n Measurement interval is 10 seconds.\n' \ +' The output voltage will only be read if the channel is disabled:\n' \ +' E.g.: qwg.chX_state(False)\n' \ +' If the channel is enabled it will return an low value: >0.1\n' \ +'Return:\n float in voltage') self.add_parameter('dac{}_gain_drift_adjust'.format(ch), unit='', label=('DAC {}, gain drift adjust').format(ch), get_cmd=gain_adjust_cmd + '?', set_cmd=gain_adjust_cmd + ' {}', vals=vals.Ints(0, 4095), get_parser=int, docstring='Gain drift adjust setting of the DAC of a channel.\n' \ +'Used for calibration of the DAC. Do not use to set the gain of a channel!\n' \ +'Notes:\n The gain setting is from 0 to 4095 \n' \ +' Where 0 is 0 V and 4095 is 3.3V \n' \ +'Get Return:\n Setting of the gain in interger (0 - 4095)\n'\ +'Set parameter:\n Integer: Gain of the DAC in , min: 0, max: 4095') self.add_parameter('_dac{}_digital_value'.format(ch), unit='', label=('DAC {}, set digital value').format(ch), set_cmd=dac_digital_value_cmd + ' {}', vals=vals.Ints(0, 4095), docstring='FOR DEVELOPMENT ONLY: Set a digital value directly into the DAC\n' \ +'Used for testing the DACs.\n' \ +'Notes:\n\tThis command will also set the ' \ +'\tinternal correction matrix (Phase and amplitude) of the channel pair to [0,0,0,0], ' \ +'disabling any influence from the wave memory.' \ +'This will also stop the wave the other channel of the pair!\n\n' \ +'Set parameter:\n\tInteger: Value to write to the DAC, min: 0, max: 4095\n' \ +'\tWhere 0 is minimal DAC scale and 4095 is maximal DAC scale \n') self.add_parameter('status_frontIO_temperature', unit='C', label=('FrontIO temperature'), get_cmd='STATus:FrontIO:TEMperature?', get_parser=float, docstring='Reads the temperature of the frontIO.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') self.add_parameter('status_fpga_temperature', unit='C', label=('FPGA temperature'), get_cmd='STATus:FPGA:TEMperature?', get_parser=int, docstring='Reads the temperature of the FPGA.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') for cw in range(self.device_descriptor.numCodewords): for j in range(self.device_descriptor.numChannels): ch = j + 1 # Codeword 0 corresponds to bitcode 0 cw_cmd = 'sequence:element{:d}:waveform{:d}'.format(cw, ch) self.add_parameter('codeword_{}_ch{}_waveform'.format(cw, ch), get_cmd=cw_cmd + '?', set_cmd=cw_cmd + ' "{:s}"', vals=vals.Strings()) # Waveform parameters self.add_parameter('WlistSize', label='Waveform list size', unit='#', get_cmd='wlist:size?', get_parser=int) self.add_parameter('Wlist', label='Waveform list', get_cmd=self._getWlist) self.add_parameter('get_system_status', unit='JSON', label=('System status'), get_cmd='SYSTem:STAtus?', vals=vals.Strings(), get_parser=self.JSON_parser, docstring='Reads the current system status. E.q. channel ' \ +'status: on or off, overflow, underdrive.\n' \ +'Return:\n JSON object with system status') # Trigger parameters doc_trgs_log_inp = 'Reads the current input values on the all the trigger ' \ +'inputs.\nReturn:\n uint32 where trigger 1 (T1) ' \ +'is on the Least significant bit (LSB), T2 on the second ' \ +'bit after LSB, etc.\n\n For example, if only T3 is ' \ +'connected to a high signal, the return value is: ' \ +'4 (0b0000100)\n\n Note: To convert the return value ' \ +'to a readable ' \ +'binary output use: `print(\"{0:#010b}\".format(qwg.' \ +'triggers_logic_input()))`' self.add_parameter( 'triggers_logic_input', label='Read triggers input value', get_cmd='QUTEch:TRIGgers:LOGIcinput?', get_parser=np.uint32, # Did not convert to readable # string because a uint32 is more # usefull when other logic is needed docstring=doc_trgs_log_inp) self._add_codeword_parameters() self.add_function('deleteWaveformAll', call_cmd='wlist:waveform:delete all') doc_sSG = "Synchronize both sideband frequency" \ + " generators, i.e. restart them with their defined phases." self.add_function('syncSidebandGenerators', call_cmd='QUTEch:OUTPut:SYNCsideband', docstring=doc_sSG)
def __init__(self, name: str, address: str, num_channels: int, timeout: float = 10, **kwargs) -> None: """ Args: name: The name used internally by QCoDeS in the DataSet address: The VISA resource name of the instrument timeout: The VISA timeout time (in seconds) num_channels: Number of channels on the AWG """ self.num_channels = num_channels super().__init__(name, address, timeout=timeout, terminator='\n', **kwargs) # The 'model' value begins with 'AWG' self.model = self.IDN()['model'][3:] if self.model not in ['70001A', '70002A']: raise ValueError('Unknown model type: {}. Are you using ' 'the right driver for your instrument?' ''.format(self.model)) self.add_parameter('current_directory', label='Current file system directory', set_cmd='MMEMory:CDIRectory "{}"', get_cmd='MMEMory:CDIRectory?', vals=vals.Strings()) self.add_parameter('mode', label='Instrument operation mode', set_cmd='INSTrument:MODE {}', get_cmd='INSTrument:MODE?', vals=vals.Enum('AWG', 'FGEN')) ################################################## # Clock parameters self.add_parameter('sample_rate', label='Clock sample rate', set_cmd='CLOCk:SRATe {}', get_cmd='CLOCk:SRATe?', unit='Sa/s', get_parser=float, vals=SRValidator(self)) self.add_parameter('clock_source', label='Clock source', set_cmd='CLOCk:SOURce {}', get_cmd='CLOCk:SOURce?', val_mapping={ 'Internal': 'INT', 'Internal, 10 MHZ ref.': 'EFIX', 'Internal, variable ref.': 'EVAR', 'External': 'EXT' }) self.add_parameter('clock_external_frequency', label='External clock frequency', set_cmd='CLOCk:ECLock:FREQuency {}', get_cmd='CLOCk:ECLock:FREQuency?', get_parser=float, unit='Hz', vals=vals.Numbers(6.25e9, 12.5e9)) for ch_num in range(1, num_channels + 1): ch_name = 'ch{}'.format(ch_num) channel = AWGChannel(self, ch_name, ch_num) self.add_submodule(ch_name, channel) # Folder on the AWG where to files are uplaoded by default self.wfmxFileFolder = "\\Users\\OEM\\Documents" self.seqxFileFolder = "\\Users\\OEM\Documents" self.current_directory(self.wfmxFileFolder) self.connect_message()
def __init__(self, parent: "Infiniium", name: str, channel: int, **kwargs: Any): """ Initialize an infiniium channel. """ self._channel = channel super().__init__(parent, name, **kwargs) # display self.display = Parameter( name="display", instrument=self, label=f"Function {channel} display on/off", set_cmd=f"FUNC{channel}:DISP {{}}", get_cmd=f"FUNC{channel}:DISP?", val_mapping=create_on_off_val_mapping(on_val=1, off_val=0), ) # Retrieve basic settings of the function self.function = Parameter( name="function", instrument=self, label=f"Function {channel} function", get_cmd=self._get_func, vals=vals.Strings(), ) self.source = Parameter( name="source", instrument=self, label=f"Function {channel} source", get_cmd=f"FUNC{channel}?", ) # Trace settings self.points = Parameter( name="points", instrument=self, label=f"Function {channel} points", get_cmd=self._get_points, ) self.frequency_axis = DSOFrequencyAxisParam( name="frequency_axis", instrument=self, label="Frequency", unit="Hz", xorigin=0.0, xincrement=0.0, points=1, vals=vals.Arrays(shape=(self.points, )), snapshot_value=False, ) self.time_axis = DSOTimeAxisParam( name="time_axis", instrument=self, label="Time", unit="s", xorigin=0.0, xincrement=0.0, points=1, vals=vals.Arrays(shape=(self.points, )), snapshot_value=False, ) self.trace = DSOTraceParam( name="trace", instrument=self, label=f"Function {channel} trace", channel=self.channel_name, vals=vals.Arrays(shape=(self.points, )), snapshot_value=False, ) # Measurement subsystem self.add_submodule("measure", BoundMeasurement(self, "measure"))
def add_parameters(self): ####################################################################### # QWG specific ####################################################################### # Channel pair parameters for i in range(self.device_descriptor.numChannels // 2): ch_pair = i * 2 + 1 sfreq_cmd = 'qutech:output{}:frequency'.format(ch_pair) sph_cmd = 'qutech:output{}:phase'.format(ch_pair) # NB: sideband frequency has a resolution of ~0.23 Hz: self.add_parameter('ch_pair{}_sideband_frequency'.format(ch_pair), parameter_class=HandshakeParameter, unit='Hz', label=('Sideband frequency channel ' + 'pair {} (Hz)'.format(i)), get_cmd=sfreq_cmd + '?', set_cmd=sfreq_cmd + ' {}', vals=vals.Numbers(-300e6, 300e6), get_parser=float) self.add_parameter('ch_pair{}_sideband_phase'.format(ch_pair), parameter_class=HandshakeParameter, unit='deg', label=('Sideband phase channel' + ' pair {} (deg)'.format(i)), get_cmd=sph_cmd + '?', set_cmd=sph_cmd + ' {}', vals=vals.Numbers(-180, 360), get_parser=float) self.add_parameter( 'ch_pair{}_transform_matrix'.format(ch_pair), parameter_class=HandshakeParameter, label=('Transformation matrix channel' + 'pair {}'.format(i)), get_cmd=self._gen_ch_get_func(self._getMatrix, ch_pair), set_cmd=self._gen_ch_set_func(self._setMatrix, ch_pair), # NB range is not a hardware limit vals=vals.Arrays(-2, 2, shape=(2, 2))) # Triggers parameter for i in range(1, self.device_descriptor.numTriggers + 1): triglev_cmd = 'qutech:trigger{}:level'.format(i) # individual trigger level per trigger input: self.add_parameter('tr{}_trigger_level'.format(i), unit='V', label='Trigger level channel {} (V)'.format(i), get_cmd=triglev_cmd + '?', set_cmd=triglev_cmd + ' {}', vals=self.device_descriptor.mvals_trigger_level, get_parser=float) self.add_parameter('run_mode', get_cmd='AWGC:RMO?', set_cmd='AWGC:RMO ' + '{}', vals=vals.Enum('NONE', 'CONt', 'SEQ', 'CODeword')) # NB: setting mode "CON" (valid SCPI abbreviation) reads back as "CONt" self.add_parameter('dio_mode', unit='', label='DIO input operation mode', get_cmd='DIO:MODE?', set_cmd='DIO:MODE ' + '{}', vals=vals.Enum('MASTER', 'SLAVE'), val_mapping={'MASTER': 'MASter', 'SLAVE': 'SLAve'}, docstring='Get or set the DIO input operation mode\n' \ 'Paramaters:\n' \ '\tMASTER: Use DIO codeword (lower 14 bits) input '\ 'from its own IORearDIO board' \ '\t\tEnables single-ended and differential inputs\n' \ '\tSLAVE; Use DIO codeword (upper 14 bits) input '\ 'from the connected master IORearDIO board\n' '\t\tDisables SE and DIFF inputs\n' ) self.add_parameter('dio_is_calibrated', unit='', label='DIO calibration status', get_cmd='DIO:CALibrate?', val_mapping={ True: '1', False: '0' }, docstring="""Get DIO calibration status\n Result:\n \tTrue: DIO is calibrated\n \tFalse: DIO is not calibrated""") self.add_parameter('dio_active_index', unit='', label='DIO calibration index', get_cmd='DIO:INDexes:ACTive?', set_cmd='DIO:INDexes:ACTive {}', get_parser=np.uint32, vals=vals.Ints(0, 20), docstring='Get and set DIO calibration index\n' \ 'See dio_calibrate() paramater\n' ) self.add_parameter('dio_suitable_indexes', unit='', label='DIO suitable indexes', get_cmd='DIO:INDexes?', get_parser=self._int_to_array, docstring='Get DIO all suitable indexes\n' \ '\t- The array is ordered by most preferable index first\n' ) self.add_parameter( 'dio_calibrated_inputs', unit='', label='DIO calibrated inputs', get_cmd='DIO:INPutscalibrated?', get_parser=int, docstring='Get all DIO inputs which are calibrated\n') self.add_parameter('dio_lvds', unit='bool', label='LVDS DIO connection detected', get_cmd='DIO:LVDS?', val_mapping={ True: '1', False: '0' }, docstring='Get the DIO LVDS connection status.\n' 'Result:\n' '\tTrue: Cable detected\n' '\tFalse: No cable detected') self.add_parameter( 'dio_interboard', unit='bool', label='DIO interboard detected', get_cmd='DIO:IB?', val_mapping={ True: '1', False: '0' }, docstring='Get the DIO interboard status.\n' 'Result:\n' '\tTrue: To master interboard connection detected\n' '\tFalse: No interboard connection detected') # Channel parameters # for ch in range(1, self.device_descriptor.numChannels + 1): amp_cmd = 'SOUR{}:VOLT:LEV:IMM:AMPL'.format(ch) offset_cmd = 'SOUR{}:VOLT:LEV:IMM:OFFS'.format(ch) state_cmd = 'OUTPUT{}:STATE'.format(ch) waveform_cmd = 'SOUR{}:WAV'.format(ch) output_voltage_cmd = 'QUTEch:OUTPut{}:Voltage'.format(ch) dac_temperature_cmd = 'STATus:DAC{}:TEMperature'.format(ch) gain_adjust_cmd = 'DAC{}:GAIn:DRIFt:ADJust'.format(ch) dac_digital_value_cmd = 'DAC{}:DIGitalvalue'.format(ch) # Set channel first to ensure sensible sorting of pars # Compatibility: 5014, QWG self.add_parameter('ch{}_state'.format(ch), label='Status channel {}'.format(ch), get_cmd=state_cmd + '?', set_cmd=state_cmd + ' {}', val_mapping={ True: '1', False: '0' }, vals=vals.Bool()) self.add_parameter( 'ch{}_amp'.format(ch), parameter_class=HandshakeParameter, label='Channel {} Amplitude '.format(ch), unit='Vpp', docstring='Amplitude channel {} (Vpp into 50 Ohm)'.format(ch), get_cmd=amp_cmd + '?', set_cmd=amp_cmd + ' {:.6f}', vals=vals.Numbers(-1.6, 1.6), get_parser=float) self.add_parameter( 'ch{}_offset'.format(ch), # parameter_class=HandshakeParameter, label='Offset channel {}'.format(ch), unit='V', get_cmd=offset_cmd + '?', set_cmd=offset_cmd + ' {:.3f}', vals=vals.Numbers(-.25, .25), get_parser=float) self.add_parameter('ch{}_default_waveform'.format(ch), get_cmd=waveform_cmd + '?', set_cmd=waveform_cmd + ' "{}"', vals=vals.Strings()) self.add_parameter('status_dac{}_temperature'.format(ch), unit='C', label=('DAC {} temperature'.format(ch)), get_cmd=dac_temperature_cmd + '?', get_parser=float, docstring='Reads the temperature of a DAC.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') self.add_parameter('output{}_voltage'.format(ch), unit='V', label=('Channel {} voltage output').format(ch), get_cmd=output_voltage_cmd + '?', get_parser=float, docstring='Reads the output voltage of a channel.\n' \ +'Notes:\n Measurement interval is 10 seconds.\n' \ +' The output voltage will only be read if the channel is disabled:\n' \ +' E.g.: qwg.chX_state(False)\n' \ +' If the channel is enabled it will return an low value: >0.1\n' \ +'Return:\n float in voltage') self.add_parameter('dac{}_gain_drift_adjust'.format(ch), unit='', label=('DAC {}, gain drift adjust').format(ch), get_cmd=gain_adjust_cmd + '?', set_cmd=gain_adjust_cmd + ' {}', vals=vals.Ints(0, 4095), get_parser=int, docstring='Gain drift adjust setting of the DAC of a channel.\n' \ +'Used for calibration of the DAC. Do not use to set the gain of a channel!\n' \ +'Notes:\n The gain setting is from 0 to 4095 \n' \ +' Where 0 is 0 V and 4095 is 3.3V \n' \ +'Get Return:\n Setting of the gain in interger (0 - 4095)\n'\ +'Set parameter:\n Integer: Gain of the DAC in , min: 0, max: 4095') self.add_parameter('_dac{}_digital_value'.format(ch), unit='', label=('DAC {}, set digital value').format(ch), set_cmd=dac_digital_value_cmd + ' {}', vals=vals.Ints(0, 4095), docstring='FOR DEVELOPMENT ONLY: Set a digital value directly into the DAC\n' \ +'Used for testing the DACs.\n' \ +'Notes:\n\tThis command will also set the ' \ +'\tinternal correction matrix (Phase and amplitude) of the channel pair to [0,0,0,0], ' \ +'disabling any influence from the wave memory.' \ +'This will also stop the wave the other channel of the pair!\n\n' \ +'Set parameter:\n\tInteger: Value to write to the DAC, min: 0, max: 4095\n' \ +'\tWhere 0 is minimal DAC scale and 4095 is maximal DAC scale \n') self.add_parameter('ch{}_bit_select'.format(ch), unit='', label=('Channel {}, set bit selection for this channel').format(ch), get_cmd=self._gen_ch_get_func( self._get_bit_select, ch), set_cmd=self._gen_ch_set_func( self._set_bit_select, ch), get_parser=np.uint32, docstring='Codeword bit select for a channel\n' \ +'Set: \n' \ +'\tParamater: Integer, the bit select\n' \ +'\nWhen a bit is enabled (1) in the bitSelect, this bit is used as part of the codeword for that channel. ' \ +' If a bit is disabled (0), it will be ignored.\n' \ +'This can be used to control individual channels with a their own codeword.\n' \ +'Note that codeword 1 will start on the first enabled bit. Bit endianness: LSB, lowest bit right \n' \ +'\nExamples:\n' \ +'\tCh1: 0b000011(0x03); Only the first and second bit will be used as codeword for channel 1.\n'\ +'\tCh2: 0b001100(0x0C); Only the third and forth bit will be used as codeword for channel 2.\n'\ +'\tCh3: 0b110000(0x30); Only the fifth and sixth bit will be used as codeword for channel 3.\n'\ +'\tCh4: 0b110000(0x30); Only the fifth and sixth bit will be used as codeword for channel 4.\n'\ +'The bit select of different channels are only allowed to overlap each other if their least significant bit is the same.\n' \ +'So a bitSelect of ch1: 0b011, and ch2: 0b010 is not allowed. This will be checked on `start()`. Errors are reported by `getError()` or `getErrors()`.' \ +'\n\n Get:\n' \ +'\tResult: Integer that represent the bit select of the channel\n') self.add_parameter( 'ch{}_bit_map'.format(ch), unit='', label='Channel {}, set bit map for this channel'.format(ch), get_cmd=f"DAC{ch}:BITmap?", set_cmd=self._gen_ch_set_func(self._set_bit_map, ch), get_parser=self._int_to_array, docstring='Codeword bit map for a channel\n') # Trigger parameters doc_trgs_log_inp = 'Reads the current input values on the all the trigger ' \ +'inputs for a channel, after the bitSelect.\nReturn:\n uint32 where trigger 1 (T1) ' \ +'is on the Least significant bit (LSB), T2 on the second ' \ +'bit after LSB, etc.\n\n For example, if only T3 is ' \ +'connected to a high signal, the return value is: ' \ +'4 (0b0000100)\n\n Note: To convert the return value ' \ +'to a readable ' \ +'binary output use: `print(\"{0:#010b}\".format(qwg.' \ +'triggers_logic_input()))`' self.add_parameter( 'ch{}_triggers_logic_input'.format(ch), label='Read triggers input value', get_cmd='QUTEch:TRIGgers{}:LOGIcinput?'.format(ch), get_parser=np.uint32, # Did not convert to readable # string because a uint32 is more # usefull when other logic is needed docstring=doc_trgs_log_inp) # Single parameters self.add_parameter('status_frontIO_temperature', unit='C', label='FrontIO temperature', get_cmd='STATus:FrontIO:TEMperature?', get_parser=float, docstring='Reads the temperature of the frontIO.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') self.add_parameter('status_fpga_temperature', unit='C', label=('FPGA temperature'), get_cmd='STATus:FPGA:TEMperature?', get_parser=int, docstring='Reads the temperature of the FPGA.\n' \ +'Temperature measurement interval is 10 seconds\n' \ +'Return:\n float with temperature in Celsius') # Paramater for codeword per channel for cw in range(self.device_descriptor.numCodewords): for j in range(self.device_descriptor.numChannels): ch = j + 1 # Codeword 0 corresponds to bitcode 0 cw_cmd = 'sequence:element{:d}:waveform{:d}'.format(cw, ch) self.add_parameter('codeword_{}_ch{}_waveform'.format(cw, ch), get_cmd=cw_cmd + '?', set_cmd=cw_cmd + ' "{:s}"', vals=vals.Strings()) # Waveform parameters self.add_parameter('WlistSize', label='Waveform list size', unit='#', get_cmd='wlist:size?', get_parser=int) self.add_parameter('Wlist', label='Waveform list', get_cmd=self._getWlist) self.add_parameter('get_system_status', unit='JSON', label="System status", get_cmd='SYSTem:STAtus?', vals=vals.Strings(), get_parser=self.JSON_parser, docstring='Reads the current system status. E.q. channel ' \ +'status: on or off, overflow, underdrive.\n' \ +'Return:\n JSON object with system status') self.add_parameter( 'get_max_codeword_bits', unit='', label=('Max codeword bits'), get_cmd=self._nr_cw_bits_cmd, vals=vals.Strings(), get_parser=int, docstring= 'Reads the maximal number of codeword bits for all channels') self.add_parameter('codeword_protocol', unit='', label='Codeword protocol', get_cmd=self._getCodewordProtocol, set_cmd=self._setCodewordProtocol, vals=vals.Enum('MICROWAVE', 'FLUX'), docstring='Reads the current system status. E.q. channel ' \ +'status: on or off, overflow, underdrive.\n' \ +'Return:\n JSON object with system status') self._add_codeword_parameters() self.add_function('deleteWaveformAll', call_cmd='wlist:waveform:delete all') doc_sSG = "Synchronize both sideband frequency" \ + " generators, i.e. restart them with their defined phases." self.add_function('syncSidebandGenerators', call_cmd='QUTEch:OUTPut:SYNCsideband', docstring=doc_sSG)
def __init__(self, name, setup_folder, address, reset=False, clock=1e9, numpoints=1000, timeout=180, **kwargs): ''' Initializes the AWG5014. Input: name (string) : name of the instrument setup_folder (string) : folder where externally generate seqs are stored address (string) : GPIB or ethernet address reset (bool) : resets to default values, default=false numpoints (int) : sets the number of datapoints timeout (float) : visa timeout, in secs. long default (180) to accommodate large waveforms Output: None ''' super().__init__(name, address, timeout=timeout, **kwargs) self._address = address self._values = {} self._values['files'] = {} self._clock = clock self._numpoints = numpoints self.add_function('reset', call_cmd='*RST') self.add_parameter('state', get_cmd=self.get_state) self.add_parameter('run_mode', get_cmd='AWGC:RMOD?', set_cmd='AWGC:RMOD ' + '{}', vals=vals.Enum('CONT', 'TRIG', 'SEQ', 'GAT')) # Trigger parameters # # ! Warning this is the same as run mode, do not use! exists # Solely for legacy purposes self.add_parameter('trigger_mode', get_cmd='AWGC:RMOD?', set_cmd='AWGC:RMOD ' + '{}', vals=vals.Enum('CONT', 'TRIG', 'SEQ', 'GAT')) self.add_parameter('trigger_impedance', label='Trigger impedance (Ohm)', units='Ohm', get_cmd='TRIG:IMP?', set_cmd='TRIG:IMP ' + '{}', vals=vals.Enum(50, 1000), get_parser=float) self.add_parameter('trigger_level', units='V', label='Trigger level (V)', get_cmd='TRIG:LEV?', set_cmd='TRIG:LEV ' + '{:.3f}', vals=vals.Numbers(-5, 5), get_parser=float) self.add_parameter('trigger_slope', get_cmd='TRIG:SLOP?', set_cmd='TRIG:SLOP ' + '{}', vals=vals.Enum('POS', 'NEG')) # , # get_parser=self.parse_int_pos_neg) self.add_parameter('trigger_source', get_cmd='TRIG:source?', set_cmd='TRIG:source ' + '{}', vals=vals.Enum('INT', 'EXT')) # Event parameters # self.add_parameter('event_polarity', get_cmd='EVEN:POL?', set_cmd='EVEN:POL ' + '{}', vals=vals.Enum('POS', 'NEG')) self.add_parameter('event_impedance', label='Event impedance (Ohm)', get_cmd='EVEN:IMP?', set_cmd='EVEN:IMP ' + '{}', vals=vals.Enum(50, 1000), get_parser=float) self.add_parameter('event_level', label='Event level (V)', get_cmd='EVEN:LEV?', set_cmd='EVEN:LEV ' + '{:.3f}', vals=vals.Numbers(-5, 5), get_parser=float) self.add_parameter('event_jump_timing', get_cmd='EVEN:JTIM?', set_cmd='EVEN:JTIM {}', vals=vals.Enum('SYNC', 'ASYNC')) self.add_parameter('clock_freq', label='Clock frequency (Hz)', get_cmd='SOUR:FREQ?', set_cmd='SOUR:FREQ ' + '{}', vals=vals.Numbers(1e6, 1.2e9), get_parser=float) self.add_parameter('numpoints', label='Number of datapoints per wave', get_cmd=self._do_get_numpoints, set_cmd=self._do_set_numpoints, vals=vals.Ints(100, int(1e9))) self.add_parameter('setup_filename', get_cmd='AWGC:SNAM?') # set_cmd=self.do_set_setup_filename, # vals=vals.Strings()) # set function has optional args and therefore # does not work with QCodes # Channel parameters # for i in range(1, 5): amp_cmd = 'SOUR{}:VOLT:LEV:IMM:AMPL'.format(i) offset_cmd = 'SOUR{}:VOLT:LEV:IMM:OFFS'.format(i) state_cmd = 'OUTPUT{}:STATE'.format(i) waveform_cmd = 'SOUR{}:WAV'.format(i) # Set channel first to ensure sensible sorting of pars self.add_parameter('ch{}_state'.format(i), label='Status channel {}'.format(i), get_cmd=state_cmd + '?', set_cmd=state_cmd + ' {}', vals=vals.Ints(0, 1)) self.add_parameter('ch{}_amp'.format(i), label='Amplitude channel {} (Vpp)'.format(i), units='Vpp', get_cmd=amp_cmd + '?', set_cmd=amp_cmd + ' {:.6f}', vals=vals.Numbers(0.02, 4.5), get_parser=float) self.add_parameter('ch{}_offset'.format(i), label='Offset channel {} (V)'.format(i), units='V', get_cmd=offset_cmd + '?', set_cmd=offset_cmd + ' {:.3f}', vals=vals.Numbers(-.1, .1), get_parser=float) self.add_parameter('ch{}_waveform'.format(i), label='Waveform channel {}'.format(i), get_cmd=waveform_cmd + '?', set_cmd=waveform_cmd + ' "{}"', vals=vals.Strings(), get_parser=parsestr) # Marker channels for j in range(1, 3): m_del_cmd = 'SOUR{}:MARK{}:DEL'.format(i, j) m_high_cmd = 'SOUR{}:MARK{}:VOLT:LEV:IMM:HIGH'.format(i, j) m_low_cmd = 'SOUR{}:MARK{}:VOLT:LEV:IMM:LOW'.format(i, j) self.add_parameter( 'ch{}_m{}_del'.format(i, j), label='Channel {} Marker {} delay (ns)'.format(i, j), get_cmd=m_del_cmd + '?', set_cmd=m_del_cmd + ' {:.3f}e-9', vals=vals.Numbers(0, 1), get_parser=float) self.add_parameter( 'ch{}_m{}_high'.format(i, j), label='Channel {} Marker {} high level (V)'.format(i, j), get_cmd=m_high_cmd + '?', set_cmd=m_high_cmd + ' {:.3f}', vals=vals.Numbers(-2.7, 2.7), get_parser=float) self.add_parameter( 'ch{}_m{}_low'.format(i, j), label='Channel {} Marker {} low level (V)'.format(i, j), get_cmd=m_low_cmd + '?', set_cmd=m_low_cmd + ' {:.3f}', vals=vals.Numbers(-2.7, 2.7), get_parser=float) # # Add functions # self.add_function('get_state') # self.add_function('set_event_jump_timing') # self.add_function('get_event_jump_timing') # self.add_function('generate_awg_file') # self.add_function('send_awg_file') # self.add_function('load_awg_file') # self.add_function('get_error') # self.add_function('pack_waveform') # self.add_function('clear_visa') # self.add_function('initialize_dc_waveforms') # # Setup filepaths self.waveform_folder = "Waveforms" self._rem_file_path = "Z:\\Waveforms\\" # NOTE! this directory has to exist on the AWG!! self._setup_folder = setup_folder self.goto_root() self.change_folder(self.waveform_folder) self.set('trigger_impedance', 50) if self.get('clock_freq') != 1e9: logging.warning('AWG clock freq not set to 1GHz') self.connect_message()
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)]})
def __init__(self, name, address, **kwargs): super().__init__(name, address, terminator='\n', **kwargs) self.add_parameter('trigger', get_cmd='*TRG', label='Trigger list/fixed measurement') self.add_parameter('status', get_cmd=':OUTP:STAT?', set_cmd=self.set_status, get_parser=self.parse_on_off, vals=vals.Strings()) self.add_parameter('fetchi', get_cmd='FETC:CURR?', get_parser=float, label='Current', unit='A') self.add_parameter('fetchv', get_cmd='FETC:VOLT?', get_parser=float, label='Voltage', unit='V') self.add_parameter('fetchp', get_cmd='FETC:POW?', get_parser=float, label='Power', unit='W') self.add_parameter('measurei', get_cmd='MEAS:CURR?', get_parser=float, label='Execute current measurement', unit='A') self.add_parameter('measurev', get_cmd='MEAS:VOLT?', get_parser=float, label='Execute voltage measurement', unit='V') self.add_parameter('resistance', get_cmd=self.measureR, get_parser=float, label='Execute resistance measurement', unit='Ohm') self.add_parameter( 'seti', get_cmd='CURR?', get_parser=float, set_cmd= 'CURR {:f}A', # {<current>|MIN|MAX|DEF} (one element required) label='Set current', unit='A') self.add_parameter( 'setv', get_cmd='VOLT?', get_parser=float, set_cmd= 'VOLT {:f}V', # {<current>|MIN|MAX|DEF} (one element required) label='Set voltage', unit='V') self.add_parameter('rangev', get_cmd='VOLTage:RANGe?', get_parser=float, set_cmd='VOLTage:RANGe {:f}', unit='V') self.add_parameter( 'command_mode', get_cmd='FUNCtion:MODE?', get_parser=str, set_cmd='FUNCtion:MODE "{:s}"', # {FIXed|LIST} set_parser=str, label='Set mode to FIXed or LIST') self.add_parameter( 'list_repeats', get_cmd='LIST:COUNt?', get_parser=float, set_cmd='LIST:COUNt {}', # {<NR1>|ONCE|REPeat} set_parser=int or str, label='Set repeats to amount or ONCE or REPeat (continuously)') self.add_parameter( 'step_duration', get_cmd='LIST:WIDth? {:f}', # get_parser=float, set_cmd='LIST:WIDth {:f}, {:f}', # <NR1>,{<duration>|MIN|MAX} label='Set step duration') self.add_parameter( 'no_of_steps', get_cmd='LIST:STEP?', get_parser=float, set_cmd='LIST:STEP {:f}', # {<NR1>|MIN|MAX} label='Set # of steps') # max is 80 self.add_parameter( 'liststepi', get_cmd='LIST:CURR?', get_parser=float, set_cmd='LIST:CURR {:f}', # <NR1>,<current> = step no., value label='Set current for a list step', unit='A') self.add_parameter( 'liststepv', get_cmd='LIST:VOLT?', get_parser=float, set_cmd='LIST:VOLT {:f}', # <NR1>,<voltage> = step no., value label='Set voltage for a list step', unit='V')
import logging import re from functools import partial from time import sleep, time from qcodes import validators as vals from qcodes import Instrument, InstrumentChannel, VisaInstrument from qcodes import Parameter log = logging.getLogger(__name__) DLCpro_val_dict = { int: vals.Ints(), float: vals.Numbers(), str: vals.Strings(), bool: vals.Bool() } DLCpro_get_parser_dict = { int: int, float: float, str: lambda s: s.strip('\"'), bool: None } DLCpro_set_parser_dict = { int: None, float: None, str: lambda s: f'\"{s}\"', bool: None }
def __init__(self, name, address, timeout=600, **kwargs): super().__init__(name, address, timeout=timeout, **kwargs) self.add_parameter(name='power', label='Power', unit='dBm', get_cmd='SOURce:POWer?', set_cmd='SOURce:POWer' + ' {:.4f}', get_parser=float, set_parser=float, vals=vals.Numbers(-130, 20)) self.add_parameter(name='IFBW', label='IFBW', unit='Hz', get_cmd='SENSe:BANDwidth?', set_cmd='SENSe:BANDwidth' + ' {:.4f}', get_parser=float, set_parser=float, vals=vals.Numbers(1, 1e7)) self.add_parameter(name='frequency_start', label='frequency Start', unit='Hz', get_cmd='SENSe:FREQuency:STARt?', set_cmd='SENSe:FREQuency:STARt ' + ' {:.9f}', get_parser=float, set_parser=float, vals=vals.Numbers(300e6, 13.5e9)) self.add_parameter(name='frequency_stop', label='frequency Stop', unit='Hz', get_cmd='SENSe:FREQuency:STOP?', set_cmd='SENSe:FREQuency:STOP ' + ' {:.9f}', get_parser=float, set_parser=float, vals=vals.Numbers(300e6, 13.5e9)) self.add_parameter(name='frequency_center', label='frequency center', unit='Hz', get_cmd='SENSe:FREQuency:CENTer?', set_cmd='SENSe:FREQuency:CENTer ' + ' {:.9f}', get_parser=float, set_parser=float, vals=vals.Numbers(300e6, 13.5e9)) self.add_parameter(name='frequency_span', label='frequency span', unit='Hz', get_cmd='SENSe:FREQuency:SPAN?', set_cmd='SENSe:FREQuency:SPAN ' + ' {:.9f}', get_parser=float, set_parser=float, vals=vals.Numbers(300e6, 13.5e9)) self.add_parameter(name='frequency_number_of_points', label='Number of points', get_cmd='SENSe:SWEep:POINts?', set_cmd='SENSe:SWEep:POINts ' + ' {:d}', get_parser=int, set_parser=int, vals=vals.Numbers(1, 100001)) self.add_parameter(name='display_format', label='display format', get_cmd='CALC:FORMat?', set_cmd='CALC:FORMat ' + ' {}', vals=vals.Strings()) self.add_parameter( name='frequencies', label='frequencies', unit='Hz', get_cmd=lambda: [float(f) for f in self.ask("CALCulate:X?").split(",")], snapshot_value=False) self.add_parameter(name='active_trace', label='active trace', set_cmd='CALC:PAR:MNUM ' + ' {:d}') self.add_parameter(name='current_trace', parameter_class=PNA_parameter, get_cmd=lambda: self.data_value(new_trace=False)) self.add_parameter(name='new_trace', parameter_class=PNA_parameter, get_cmd=lambda: self.data_value(new_trace=True)) self.connect_message()
def _add_awg_parameters(self): # Channel pair parameters for i in range(self._dev_desc.numChannels // 2): ch_pair = i * 2 + 1 self.add_parameter( f'ch_pair{ch_pair}_sideband_frequency', parameter_class=HandshakeParameter, unit='Hz', label=('Sideband frequency channel pair {} (Hz)'.format(i)), get_cmd=_gen_get_func_1par(self.get_sideband_frequency, ch_pair), set_cmd=_gen_set_func_1par(self.set_sideband_frequency, ch_pair), vals=vals.Numbers(-300e6, 300e6), get_parser=float, docstring='Frequency of the sideband modulator\n' 'Resolution: ~0.23 Hz') self.add_parameter( f'ch_pair{ch_pair}_sideband_phase', parameter_class=HandshakeParameter, unit='deg', label=('Sideband phase channel pair {} (deg)'.format(i)), get_cmd=_gen_get_func_1par(self.get_sideband_phase, ch_pair), set_cmd=_gen_set_func_1par(self.set_sideband_phase, ch_pair), vals=vals.Numbers(-180, 360), get_parser=float, docstring='Sideband phase difference between channels') self.add_parameter( f'ch_pair{ch_pair}_transform_matrix', parameter_class=HandshakeParameter, unit='%', label=('Transformation matrix channel pair {}'.format(i)), get_cmd=_gen_get_func_1par(self._get_matrix, ch_pair), set_cmd=_gen_set_func_1par(self._set_matrix, ch_pair), vals=vals.Arrays( -2, 2, shape=(2, 2)), # NB range is not a hardware limit docstring= 'Transformation matrix for mixer correction per channel pair') # Channel parameters for ch in range(1, self._dev_desc.numChannels + 1): self.add_parameter( f'ch{ch}_state', label=f'Output state channel {ch}', get_cmd=_gen_get_func_1par(self.get_output_state, ch), set_cmd=_gen_set_func_1par(self.set_output_state, ch), val_mapping={ True: '1', False: '0' }, vals=vals.Bool(), docstring='Enables or disables the output of channels\n' 'Default: Disabled') self.add_parameter( f'ch{ch}_amp', parameter_class=HandshakeParameter, label=f'Channel {ch} Amplitude ', unit='Vpp', get_cmd=_gen_get_func_1par(self.get_amplitude, ch), set_cmd=_gen_set_func_1par(self.set_amplitude, ch), vals=vals.Numbers(-1.6, 1.6), get_parser=float, docstring=f'Amplitude channel {ch} (Vpp into 50 Ohm)') self.add_parameter( f'ch{ch}_offset', # parameter_class=HandshakeParameter, FIXME: was commented out label=f'Offset channel {ch}', unit='V', get_cmd=_gen_get_func_1par(self.get_offset, ch), set_cmd=_gen_set_func_1par(self.set_offset, ch), vals=vals.Numbers(-.25, .25), get_parser=float, docstring=f'Offset channel {ch}') self.add_parameter( f'ch{ch}_default_waveform', get_cmd=_gen_get_func_1par(self.get_waveform, ch), set_cmd=_gen_set_func_1par(self.set_waveform, ch), # FIXME: docstring vals=vals.Strings()) # end for(ch... # FIXME: enable if/when support for marker/trigger board is added again # Triggers parameter # for trigger in range(1, self._dev_desc.numTriggers+1): # triglev_cmd = f'qutech:trigger{trigger}:level' # # individual trigger level per trigger input: # self.add_parameter( # f'tr{trigger}_trigger_level', # unit='V', # label=f'Trigger level channel {trigger} (V)', # # FIXME # get_cmd=triglev_cmd + '?', # set_cmd=triglev_cmd + ' {}', # vals=self._dev_desc.mvals_trigger_level, # get_parser=float, # snapshot_exclude=True) # # FIXME: docstring # Single parameters self.add_parameter('run_mode', get_cmd=self.get_run_mode, set_cmd=self.set_run_mode, vals=vals.Enum('NONE', 'CONt', 'SEQ', 'CODeword'), docstring=_run_mode_doc + '\n Effective after start command')
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, name: str, address: str, **kwargs): """ Create an instance of the instrument. Args: name: Instrument name. address: Used to connect to the instrument. Run :meth:`.ERASynthBase.print_pyvisa_resources` to list available list. """ super().__init__(name=name, address=address, terminator="\r\n", **kwargs) # ############################################################################## # Standard LO parameters # ############################################################################## # NB `initial_value` is not used because that would make the initialization slow self.status = Parameter( name="status", instrument=self, val_mapping={ False: "0", True: "1" }, get_cmd="RA:rfoutput", set_cmd=self._set_status, ) """Sets the output state (`True`/`False`).""" self.power = Parameter( name="power", instrument=self, label="Power", unit="dBm", vals=validators.Numbers(min_value=-60.0, max_value=20.0), get_cmd="RA:amplitude", get_parser=float, set_parser=lambda power: f"{power:.2f}", set_cmd=self._set_power, ) """Signal power in dBm of the ERASynth signal, 'amplitude' in EraSynth docs.""" self.ref_osc_source = Parameter( name="ref_osc_source", instrument=self, val_mapping={ "int": "0", "ext": "1" }, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['P1']}", set_cmd="P1{}", ) """ Set to external if a 10 MHz reference is connected to the REF input connector. """ # ############################################################################## # ERASynth specific parameters # ############################################################################## self.temperature = Parameter( name="temperature", instrument=self, label="Temperature", unit="\u00B0C", get_cmd="RD:temperature", ) """Temperature of the device.""" self.voltage = Parameter( name="voltage", instrument=self, label="Voltage", unit="V", get_cmd="RD:voltage", ) """The input voltage value from power input of the ERASynth.""" self.current = Parameter( name="current", instrument=self, label="Current", unit="V", get_cmd="RD:current", ) """The current value drawn by the ERASynth.""" self.embedded_version = Parameter( name="embedded_version", instrument=self, label="Embedded version", get_cmd="RD:em", ) """The firmware version of the ERASynth.""" self.wifi_rssi = Parameter( name="wifi_rssi", instrument=self, label="WiFi RSSI", get_cmd="RD:rssi", ) """The Wifi received signal power.""" self.pll_lmx1_status = Parameter( name="pll_lmx1_status", instrument=self, label="PLL LMX1 status", val_mapping={ "locked": "1", "unlocked": "0" }, get_cmd="RD:lock_lmx1", ) """PLL lock status of LMX1.""" self.pll_lmx2_status = Parameter( name="pll_lmx2_status", instrument=self, label="PLL LMX2 status", val_mapping={ "locked": "1", "unlocked": "0" }, get_cmd="RD:lock_lmx2", ) """PLL lock status of LMX2.""" self.pll_xtal_status = Parameter( name="pll_xtal_status", instrument=self, label="PLL XTAL status", val_mapping={ "locked": "1", "unlocked": "0" }, get_cmd="RD:lock_xtal", ) """PLL lock status of XTAL.""" self.modulation_en = Parameter( name="modulation_en", instrument=self, val_mapping={ False: "0", True: "1" }, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['MS']}", set_cmd="MS{}", ) """Modulation on/off.""" self.modulation_signal_waveform = Parameter( name="modulation_signal_waveform", instrument=self, val_mapping={ "sine": "0", "triangle": "1", "ramp": "2", "square": "3" }, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M2']}", set_cmd="M2{}", ) """Internal modulation waveform.""" self.modulation_source = Parameter( name="modulation_source", instrument=self, val_mapping={ "internal": "0", "external": "1", "microphone": "2" }, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M1']}", set_cmd="M1{}", ) """Modulation source.""" self.modulation_type = Parameter( name="modulation_type", instrument=self, val_mapping={ "narrowband_fm": "0", "wideband_fm": "1", "am": "2", "pulse": "3", }, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M0']}", set_cmd="M0{}", ) """Modulation type.""" self.modulation_freq = Parameter( name="modulation_freq", instrument=self, label="Modulation frequency", unit="Hz", vals=validators.Numbers(min_value=0, max_value=20e9), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M3']}", get_parser=int, set_cmd="M3{}", set_parser=lambda freq: str(int(freq)), ) """Internal modulation frequency in Hz.""" self.modulation_am_depth = Parameter( name="modulation_am_depth", instrument=self, label="AM depth", unit="%", vals=validators.Numbers(min_value=0, max_value=100), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M5']}", get_parser=int, set_cmd="M5{}", set_parser=lambda depth: str(int(depth)), ) """AM modulation depth.""" self.modulation_fm_deviation = Parameter( name="modulation_fm_deviation", instrument=self, label="FM deviation", unit="Hz", vals=validators.Numbers(min_value=0, max_value=20e9), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M4']}", get_parser=int, set_cmd="M4{}", set_parser=lambda freq: str(int(freq)), ) """FM modulation deviation.""" self.modulation_pulse_period = Parameter( name="modulation_pulse_period", instrument=self, label="Pulse period", unit="s", vals=validators.Numbers(min_value=1e-6, max_value=10), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M6']}", get_parser=lambda val: int(val) * 1e-6, set_cmd="M6{}", set_parser=lambda period: str(int(period * 1e6)), ) """Pulse period in seconds.""" self.modulation_pulse_width = Parameter( name="modulation_pulse_width", instrument=self, label="Pulse width", unit="s", vals=validators.Numbers(min_value=1e-6, max_value=10), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['M7']}", get_parser=lambda val: int(val) * 1e-6, set_cmd="M7{}", set_parser=lambda period: str(int(period * 1e6)), ) """Pulse width in s.""" self.sweep_en = Parameter( name="sweep_en", instrument=self, val_mapping={ False: "0", True: "1" }, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['SS']}", set_cmd="SS{}", ) """Sweep on/off.""" self.sweep_trigger = Parameter( name="sweep_trigger", instrument=self, val_mapping={ "freerun": "0", "external": "1" }, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['S0']}", set_cmd="S0{}", ) """Sweep trigger freerun/external.""" self.sweep_dwell = Parameter( name="sweep_dwell", instrument=self, label="Sweep dwell", unit="s", vals=validators.Numbers(min_value=1e-3, max_value=10), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['S4']}", get_parser=lambda val: int(val) * 1e-3, set_cmd="S4{}", set_parser=lambda period: str(int(period * 1e3)), ) """Sweep dwell time in s. Requires sweep_trigger('freerun').""" self.synthesizer_mode = Parameter( name="synthesizer_mode", instrument=self, val_mapping={ "low_spurious": "0", "low_phase_noise": "1" }, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['P9']}", set_cmd="P9{}", ) """Synthesizer mode, low spurious/low phase noise.""" # WiFi control, NB initial_cache_value is used to avoid overriding these values self.wifi_mode = Parameter( name="wifi_mode", instrument=self, val_mapping={ "station": "0", "hotspot": "1", "": "" }, get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEW']}", set_cmd="PEW{}", ) """WiFi Mode, station/hotspot.""" self.wifi_station_ssid = Parameter( name="wifi_station_ssid", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PES0']}", set_cmd="PES0{}", ) """Sets network SSID for WiFi module.""" self.wifi_station_password = Parameter( name="wifi_station_password", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEP0']}", set_cmd="PEP0{}", ) """Sets network password for WiFi module.""" self.wifi_hotspot_ssid = Parameter( name="wifi_hotspot_ssid", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PES1']}", set_cmd="PES1{}", ) """Sets hotspot SSID for WiFi module.""" self.wifi_hotspot_password = Parameter( name="wifi_hotspot_password", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEP1']}", set_cmd="PEP1{}", ) """Sets hotspot password for WiFi module.""" self.wifi_ip_address = Parameter( name="wifi_ip_address", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEI']}", set_cmd="PEI{}", ) """Sets IP address for WiFi module.""" self.wifi_subnet_address = Parameter( name="wifi_subnet_address", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEN']}", set_cmd="PEN{}", ) """Sets Subnet mask for WiFi module.""" self.wifi_gateway_address = Parameter( name="wifi_gateway_address", instrument=self, vals=validators.Strings(), get_cmd=f"RA:{_CMD_TO_JSON_MAPPING['PEG']}", set_cmd="PEG{}", ) """Sets default gateway for WiFi module.""" self.debug_messages_en = Parameter( name="debug_messages_en", instrument=self, vals=validators.Strings(), initial_cache_value=None, val_mapping={ True: "1", False: "0" }, set_cmd="PD{}", ) """Enables/disables debug printing on the serial port.""" setattr(self.visa_handle, "baud_rate", BAUDRATE) self.timeout(10) # generous timeout to avoid disrupting measurements self.connect_message() self._prep_communication()
def __init__(self, name: str, address: str, verbose: int = 1, reset: bool = False, server_name: Optional[str] = None, **kwargs: Any): """ Driver for HP_83650A """ self.verbose = verbose log.debug('Initializing instrument') super().__init__(name, address, **kwargs) self.add_parameter('frequency', label='Frequency', get_cmd='FREQ:CW?', set_cmd='FREQ:CW {}', vals=vals.Numbers(10e6, 40e9), docstring='Microwave frequency, ....', get_parser=float, unit='Hz') self.add_parameter('freqmode', label='Frequency mode', get_cmd='FREQ:MODE?', set_cmd='FREQ:MODE {}', vals=vals.Strings(), get_parser=parsestr, docstring='Microwave frequency mode, ....') self.add_parameter('power', label='Power', get_cmd='SOUR:POW?', set_cmd='SOUR:POW {}', vals=vals.Numbers(-20, 20), get_parser=float, unit='dBm', docstring='Microwave power, ....') self.add_parameter('rfstatus', label='RF status', get_cmd=':POW:STAT?', set_cmd=':POW:STAT {}', val_mapping={ 'on': '1', 'off': '0' }, vals=vals.Strings(), get_parser=parsestr, docstring='Status, ....') self.add_parameter('fmstatus', label='FM status', get_cmd=':FM:STAT?', set_cmd=':FM:STAT {}', val_mapping={ 'on': '1', 'off': '0' }, vals=vals.Strings(), get_parser=parsestr, docstring='FM status, ....') self.add_parameter('fmcoup', label='FM coupling', get_cmd=':FM:COUP?', set_cmd=':FM:COUP {}', vals=vals.Strings(), get_parser=parsestr, docstring='FM coupling, ....') self.add_parameter('amstatus', label='AM status', get_cmd=':AM:STAT?', set_cmd=':AM:STAT {}', val_mapping={ 'on': '1', 'off': '0' }, vals=vals.Strings(), get_parser=parsestr, docstring='AM status, ....') self.add_parameter('pulsestatus', label='Pulse status', get_cmd=':PULS:STAT?', set_cmd=':PULS:STAT {}', val_mapping={ 'on': '1', 'off': '0' }, vals=vals.Strings(), get_parser=parsestr, docstring='Pulse status, ....') self.add_parameter('pulsesource', label='Pulse source', get_cmd=':PULS:SOUR?', set_cmd=':PULS:SOUR {}', vals=vals.Strings(), get_parser=parsestr, docstring='Pulse source, ....') self.connect_message()
def __init__( self, name: str, device_type: str, readout_methods: Optional[Dict[str, qc.Parameter]] = None, gate_parameters: Optional[Dict[int, Any]] = None, ohmic_parameters: Optional[Dict[int, Any]] = None, sensor_parameters: Optional[Dict[int, Any]] = None, measurement_options: Optional[Dict[str, Dict[str, Any]]] = None, sensor_side: str = "left", initial_valid_ranges: Optional[vltg_rngs_tp] = None, normalization_constants: Optional[nrm_cnst_tp] = None, ) -> None: super().__init__(name) super().add_parameter( name="device_type", label="device type", docstring="", set_cmd=None, get_cmd=None, initial_value=device_type, vals=vals.Strings(), ) all_meths = nt.config['core']['readout_methods'] if readout_methods is not None: assert list(set(all_meths).intersection(readout_methods.keys())) else: readout_methods = {} self._readout_methods = readout_methods super().add_parameter( name="readout_methods", label=f"{name} readout methods", docstring="readout methods to use for measurements", set_cmd=self.set_readout_methods, get_cmd=self.get_readout_methods, initial_value=readout_methods, vals=vals.Dict(), ) self._measurement_options = measurement_options super().add_parameter( name="measurement_options", label=f"{name} measurement options", docstring="readout methods to use for measurements", set_cmd=self.set_measurement_options, get_cmd=self.get_measurement_options, initial_value=measurement_options, vals=vals.Dict(), ) super().add_parameter( name="sensor_side", label="sensor side", docstring="side where the sensor is located", set_cmd=None, get_cmd=None, initial_value=sensor_side, vals=vals.Enum("left", "right"), ) self.layout = nt.config["device"][self.device_type()] self.gates: List[Gate] = [] self.sensor_gates: List[Gate] = [] self.ohmics: List[Ohmic] = [] required_parameter_fields = ['channel_id', 'dac_instrument'] if gate_parameters is not None: for layout_id, gate_param in gate_parameters.items(): for required_param in required_parameter_fields: assert gate_param.get(required_param) is not None alias = self.layout[layout_id] gate_param['layout_id'] = layout_id gate_param['use_ramp'] = True gate = Gate( parent=self, name=alias, **gate_param, ) super().add_submodule(alias, gate) self.gates.append(gate) # if self.sensor_side() == "right": # self.outer_barriers.reverse() # self.plungers.reverse() if sensor_parameters is not None: for layout_id, sens_param in sensor_parameters.items(): for required_param in required_parameter_fields: assert sens_param.get(required_param) is not None alias = self.layout[layout_id] sens_param['layout_id'] = layout_id sens_param['use_ramp'] = True gate = Gate( parent=self, name=alias, **sens_param, ) super().add_submodule(alias, gate) self.sensor_gates.append(gate) if ohmic_parameters is not None: for ohmic_id, ohm_param in ohmic_parameters.items(): for required_param in required_parameter_fields: assert ohm_param.get(required_param) is not None alias = f"ohmic_{ohmic_id}" ohm_param['ohmic_id'] = ohmic_id ohmic = Ohmic( parent=self, name=alias, **ohm_param, ) super().add_submodule(alias, ohmic) self.ohmics.append(ohmic) if initial_valid_ranges is None: initial_valid_ranges = {} for gate in self.gates: initial_valid_ranges[gate.layout_id()] = gate.safety_range() self._initial_valid_ranges: vltg_rngs_tp = {} super().add_parameter( name="initial_valid_ranges", label="initial valid ranges", docstring="", set_cmd=self.set_initial_valid_ranges, get_cmd=self.get_initial_valid_ranges, initial_value=initial_valid_ranges, vals=vals.Dict(), ) super().add_parameter( name="quality", label="device quality", docstring="", set_cmd=None, get_cmd=None, initial_value=0, vals=vals.Numbers(), ) if normalization_constants is not None: self._normalization_constants = normalization_constants else: self._normalization_constants = { key: (0, 1) for key in ["dc_current", "rf", "dc_sensor"] } super().add_parameter( name="normalization_constants", label="open circuit signal", docstring=("Signal measured with all gates at zero. Used as " "normalization during data post processing"), set_cmd=self.set_normalization_constants, get_cmd=self.get_normalization_constants, initial_value=self._normalization_constants, vals=vals.Dict(), )
def __init__(self, name, address=None, password='******', axis_names=None, timeout=30, **kwargs): """ Args: name: The name of the instrument address: The VISA resource name of the instrument (e.g. "tcpip0::192.168.1.2::7230::socket") password: Password for authenticating into the instrument (default: '123456') axis_names(optional): List of names to give to the individual channels """ super().__init__(name, address, terminator='\r\n', timeout=timeout, **kwargs) self.visa_handle.encoding = 'ascii' # Wait for terminal to fire up and clear welcome message sleep(0.1) self.visa_handle.clear() # Authenticate self.visa_handle.write(password) self.visa_handle.read_raw() # Flush console echo resp = self.visa_handle.read() # Read password prompt response if resp == "Authorization success": sleep(0.1) self.visa_handle.clear() else: raise ConnectionRefusedError("Authentication failed") # Add available modules as channels to the instrument # Maximum aid depends on model aid = 1 while True: try: # Attempt communication with module self.ask('getser {:d}'.format(aid)) except ANC300WrongAxisType: # Slot is empty pass except ANC300WrongAxisId: # Slot does not exist break else: # If module is present, create channel and add to instrument axis_name = (axis_names[aid-1] if axis_names else 'axis{}'.format(aid)) module = ANMxx0(self, axis_name, aid) self.add_submodule(axis_name, module) finally: aid += 1 # TODO(ThibaudRuelle): add output triggers as channels self.add_parameter('serial_no', get_cmd='getcser', vals=vals.Strings()) # unnecessary when #651 in pip self.add_parameter('instrument_info', get_cmd='ver', vals=vals.Strings()) # unnecessary when #651 in pip self.connect_message()
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: Instrument, name: str, channum: int) -> None: """ Args: parent: The instrument to which the channel is attached. name: The name of the channel channum: The number of the channel in question (1-2) """ super().__init__(parent, name) self._channum = channum def val_parser(parser: type, inputstring: str) -> Union[float, int]: """ Parses return values from instrument. Meant to be used when a query can return a meaningful finite number or a numeric representation of infinity Args: parser: Either int or float, what to return in finite cases inputstring: The raw return value """ inputstring = inputstring.strip() if float(inputstring) == 9.9e37: output = float('inf') else: output = float(inputstring) if parser == int: output = parser(output) return output self.model = self._parent.model self.add_parameter('function_type', label='Channel {} function type'.format(channum), set_cmd='SOURce{}:FUNCtion {{}}'.format(channum), get_cmd='SOURce{}:FUNCtion?'.format(channum), get_parser=str.rstrip, vals=vals.Enum('SIN', 'SQU', 'TRI', 'RAMP', 'PULS', 'PRBS', 'NOIS', 'ARB', 'DC')) max_freq = self._parent._max_freqs[self.model] if self._parent.model in ['33511B', '33512B', '33522B', '33622A']: # FUNC ARB self.add_parameter( 'arb_waveform_fname', label='Channel {} arb waveform filename'.format(channum), set_cmd='SOURce{}:FUNC:ARB {{}}'.format(channum), get_cmd='SOURce{}:FUNC:ARB?'.format(channum), get_parser=str.rstrip, vals=vals.Strings()) self.add_parameter( 'arb_waveform_adv', label='Channel {} arb waveform advance mode'.format(channum), set_cmd='SOURce{}:FUNCtion:ARBitrary:ADVance {{}}'.format( channum), get_cmd='SOURce{}:FUNCtion:ARBitrary:ADVance?'.format(channum), get_parser=str.rstrip, vals=vals.Enum('TRIG', 'SRAT')) self.add_parameter( 'arb_waveform_filter', label='Channel {} arb waveform filter'.format(channum), set_cmd='SOURce{}:FUNCtion:ARBitrary:FILTer {{}}'.format( channum), get_cmd='SOURce{}:FUNCtion:ARBitrary:FILTer?'.format(channum), get_parser=str.rstrip, vals=vals.Enum('NORM', 'STEP', 'OFF')) self.add_parameter( 'arb_waveform_frequency', label='Channel {} arb waveform frequency'.format(channum), set_cmd='SOURce{}:FUNCtion:ARBitrary:FREQuency {{}}'.format( channum), get_cmd='SOURce{}:FUNCtion:ARBitrary:FREQuency?'.format( channum), get_parser=float, unit='Hz', # TODO: max. freq. actually really tricky vals=vals.Numbers(1e-6, max_freq)) self.add_parameter( 'arb_waveform_period', label='Channel {} arb waveform period'.format(channum), set_cmd='SOURce{}:FUNCtion:ARBitrary:PERiod {{}}'.format( channum), get_cmd='SOURce{}:FUNCtion:ARBitrary:PERiod?'.format(channum), get_parser=float, unit='s', vals=vals.Numbers(0)) self.add_parameter( 'arb_waveform_points', label='Channel {} arb waveform number of points'.format( channum), get_cmd='SOURce{}:FUNCtion:ARBitrary:POINts?'.format(channum), get_parser=int) max_rate = self._parent._max_rates[self.model] self.add_parameter( 'arb_waveform_srate', label='Channel {} arb waveform sampling rate'.format(channum), set_cmd='SOURce{}:FUNCtion:ARBitrary:SRATe {{}}'.format( channum), get_cmd='SOURce{}:FUNCtion:ARBitrary:SRATe?'.format(channum), get_parser=float, unit='Sa/s', # TODO: max. rate. actually really tricky vals=vals.Numbers(1e-6, max_rate)) self.add_parameter( 'frequency_mode', label='Channel {} frequency mode'.format(channum), set_cmd='SOURce{}:FREQuency:MODE {{}}'.format(channum), get_cmd='SOURce{}:FREQuency:MODE?'.format(channum), get_parser=str.rstrip, vals=vals.Enum('CW', 'LIST', 'SWEEP', 'FIXED')) self.add_parameter( 'frequency', label='Channel {} frequency'.format(channum), set_cmd='SOURce{}:FREQuency {{}}'.format(channum), get_cmd='SOURce{}:FREQuency?'.format(channum), get_parser=float, unit='Hz', # TODO: max. freq. actually really tricky vals=vals.Numbers(1e-6, max_freq)) self.add_parameter('phase', label='Channel {} phase'.format(channum), set_cmd='SOURce{}:PHASe {{}}'.format(channum), get_cmd='SOURce{}:PHASe?'.format(channum), get_parser=float, unit='deg', vals=vals.Numbers(0, 360)) self.add_parameter( 'amplitude_unit', label='Channel {} amplitude unit'.format(channum), set_cmd='SOURce{}:VOLTage:UNIT {{}}'.format(channum), get_cmd='SOURce{}:VOLTage:UNIT?'.format(channum), vals=vals.Enum('VPP', 'VRMS', 'DBM'), get_parser=str.rstrip) self.add_parameter( 'amplitude', label='Channel {} amplitude'.format(channum), set_cmd='SOURce{}:VOLTage {{}}'.format(channum), get_cmd='SOURce{}:VOLTage?'.format(channum), unit='', # see amplitude_unit get_parser=float) self.add_parameter( 'offset', label='Channel {} voltage offset'.format(channum), set_cmd='SOURce{}:VOLTage:OFFSet {{}}'.format(channum), get_cmd='SOURce{}:VOLTage:OFFSet?'.format(channum), unit='V', get_parser=float) self.add_parameter('output', label='Channel {} output state'.format(channum), set_cmd='OUTPut{} {{}}'.format(channum), get_cmd='OUTPut{}?'.format(channum), val_mapping={ 'ON': 1, 'OFF': 0 }) self.add_parameter( 'ramp_symmetry', label='Channel {} ramp symmetry'.format(channum), set_cmd='SOURce{}:FUNCtion:RAMP:SYMMetry {{}}'.format(channum), get_cmd='SOURce{}:FUNCtion:RAMP:SYMMetry?'.format(channum), get_parser=float, unit='%', vals=vals.Numbers(0, 100)) self.add_parameter( 'pulse_width', label="Channel {} pulse width".format(channum), set_cmd='SOURce{}:FUNCtion:PULSE:WIDTh {{}}'.format(channum), get_cmd='SOURce{}:FUNCtion:PULSE:WIDTh?'.format(channum), get_parser=float, unit='S') # TRIGGER MENU self.add_parameter( 'trigger_source', label='Channel {} trigger source'.format(channum), set_cmd='TRIGger{}:SOURce {{}}'.format(channum), get_cmd='TRIGger{}:SOURce?'.format(channum), vals=vals.Enum('IMM', 'EXT', 'TIM', 'BUS'), get_parser=str.rstrip, ) self.add_parameter('trigger_slope', label='Channel {} trigger slope'.format(channum), set_cmd='TRIGger{}:SLOPe {{}}'.format(channum), get_cmd='TRIGger{}:SLOPe?'.format(channum), vals=vals.Enum('POS', 'NEG'), get_parser=str.rstrip) # Older models do not have all the fancy trigger options if self._parent.model[2] in ['5', '6']: self.add_parameter( 'trigger_count', label='Channel {} trigger count'.format(channum), set_cmd='TRIGger{}:COUNt {{}}'.format(channum), get_cmd='TRIGger{}:COUNt?'.format(channum), vals=vals.Ints(1, 1000000), get_parser=partial(val_parser, int)) self.add_parameter( 'trigger_delay', label='Channel {} trigger delay'.format(channum), set_cmd='TRIGger{}:DELay {{}}'.format(channum), get_cmd='TRIGger{}:DELay?'.format(channum), vals=vals.Numbers(0, 1000), get_parser=float, unit='s') self.add_parameter( 'trigger_timer', label='Channel {} trigger timer'.format(channum), set_cmd='TRIGger{}:TIMer {{}}'.format(channum), get_cmd='TRIGger{}:TIMer?'.format(channum), vals=vals.Numbers(1e-6, 8000), get_parser=float) # TODO: trigger level doesn't work remotely. Why? # output menu self.add_parameter('output_polarity', label='Channel {} output polarity'.format(channum), set_cmd='OUTPut{}:POLarity {{}}'.format(channum), get_cmd='OUTPut{}:POLarity?'.format(channum), get_parser=str.rstrip, vals=vals.Enum('NORM', 'INV')) # BURST MENU self.add_parameter('burst_state', label='Channel {} burst state'.format(channum), set_cmd='SOURce{}:BURSt:STATe {{}}'.format(channum), get_cmd='SOURce{}:BURSt:STATe?'.format(channum), val_mapping={ 'ON': 1, 'OFF': 0 }, vals=vals.Enum('ON', 'OFF')) self.add_parameter('burst_mode', label='Channel {} burst mode'.format(channum), set_cmd='SOURce{}:BURSt:MODE {{}}'.format(channum), get_cmd='SOURce{}:BURSt:MODE?'.format(channum), get_parser=str.rstrip, val_mapping={ 'N Cycle': 'TRIG', 'Gated': 'GAT' }, vals=vals.Enum('N Cycle', 'Gated')) self.add_parameter( 'burst_ncycles', label='Channel {} burst no. of cycles'.format(channum), set_cmd='SOURce{}:BURSt:NCYCles {{}}'.format(channum), get_cmd='SOURce{}:BURSt:NCYCLes?'.format(channum), get_parser=partial(val_parser, int), vals=vals.MultiType(vals.Ints(1), vals.Enum('MIN', 'MAX', 'INF'))) self.add_parameter( 'burst_phase', label='Channel {} burst start phase'.format(channum), set_cmd='SOURce{}:BURSt:PHASe {{}}'.format(channum), get_cmd='SOURce{}:BURSt:PHASe?'.format(channum), vals=vals.Numbers(-360, 360), unit='degrees', get_parser=float) self.add_parameter( 'burst_polarity', label='Channel {} burst gated polarity'.format(channum), set_cmd='SOURce{}:BURSt:GATE:POLarity {{}}'.format(channum), get_cmd='SOURce{}:BURSt:GATE:POLarity?'.format(channum), vals=vals.Enum('NORM', 'INV')) self.add_parameter( 'burst_int_period', label=('Channel {}'.format(channum) + ' burst internal period'), set_cmd='SOURce{}:BURSt:INTernal:PERiod {{}}'.format(channum), get_cmd='SOURce{}:BURSt:INTernal:PERiod?'.format(channum), unit='s', vals=vals.Numbers(1e-6, 8e3), get_parser=float, docstring=('The burst period is the time ' 'between the starts of consecutive ' 'bursts when trigger is immediate.'))