def __init__(self): """ 1. setup the VNA as an instrument (if it's not already setup) 2. specify experimental parameters 3. specify paths of the target files: database file and a new folder with raw (txt, png) files """ import pdb; pdb.set_trace() # noqa BREAKPOINT self.vna_name = 'VNA_Keysight' # this is a qcodes VisaInstrument (interface between visa and qcodes) self.vna_class = Keysight_P9373A self.vna_address = "TCPIP0::maip-franck::hislip0,4880::INSTR" # -- check if instrument 'VNA' already exists. If not, create it if Instrument.exist(self.vna_name, self.vna_class): # an instrument is created by qcodes in a global context, # from which it can be retrieved manually using find_instrument self.vna = Instrument.find_instrument( self.vna_name, self.vna_class) else: self.vna = self.vna_class(self.vna_name, self.vna_address, 300e3, 13.5e9, -90, 13, 2) # -- name the experiment -> automatic file names self.exp_name = 'test_exp' # name used by qcodes self.cooldown_date = '20-09-22' self.sample_name = 'test_sample' # -- set experiment parameters (global constants, used in different measurement functions) self.num_freq_points = 2001 # 2001 # number of measurement points self.vnapower = -30 # applied power # 3.7e9 #3.387015e9 #6.608e9-3.5e6 # start frequency of sweep self.start_frequency = 3e9 # 5.7e9 #3.387065e9 #6.611e9 +3.5e6 # stop frequency of sweep self.stop_frequency = 10.e9 self.frequency_span = self.stop_frequency - self.start_frequency self.center_frequency = (self.stop_frequency - self.start_frequency) / \ 2. + self.start_frequency # just used for power sweep self.measuredtrace = 'S21' # spectral density measured between port 1 and 2 # IF Bandwidth, must be in (10,30,50,70,100,300,500,700,1000,3000,5000,7000,10000)Hz self.ifbandwidth = 10 self.powersweepstart = -30 # start for power sweep self.powersweepstop = 13 # stop for powersweep # number of power sweeps (perhaps +/-1) MUST BE AN EVEN NUMBER AT LEAST 6 self.num_power_points = 3 # groupdelayref=0.0000000225 # vna.groupdelay.set(groupdelayref)#resets to 0 instead of working -> rounding to 0 # print(vna.groupdelay.get()) self.create_database_experiment_and_folders() self.ask_what_to_do()
def load_instrument(self, identifier: str, revive_instance: bool = False, **kwargs) -> Instrument: """ Creates an :class:`~.Instrument` instance as described by the loaded configuration file. Args: identifier: The identfying string that is looked up in the yaml configuration file, which identifies the instrument to be added. revive_instance: If ``True``, try to return an instrument with the specified name instead of closing it and creating a new one. **kwargs: Additional keyword arguments that get passed on to the ``__init__``-method of the instrument to be added. """ # try to revive the instrument if revive_instance and Instrument.exist(identifier): return Instrument.find_instrument(identifier) # load file # try to reload file on every call. This makes script execution a # little slower but makes the overall workflow more convenient. self.load_config_file(self.config_file) # load from config if identifier not in self._instrument_config.keys(): raise RuntimeError(f'Instrument {identifier} not found in ' 'instrument config file') instr_cfg = self._instrument_config[identifier] # TODO: add validation of config for better verbose errors: # check if instrument is already defined and close connection if instr_cfg.get('enable_forced_reconnect', get_config_enable_forced_reconnect()): with suppress(KeyError): self.close_and_remove_instrument(identifier) # instantiate instrument init_kwargs = instr_cfg.get('init', {}) # somebody might have a empty init section in the config init_kwargs = {} if init_kwargs is None else init_kwargs if 'address' in instr_cfg: init_kwargs['address'] = instr_cfg['address'] if 'port' in instr_cfg: init_kwargs['port'] = instr_cfg['port'] # make explicitly passed arguments overide the ones from the config # file. # We are mutating the dict below # so make a copy to ensure that any changes # does not leek into the station config object # specifically we may be passing non pickleable # instrument instances via kwargs instr_kwargs = deepcopy(init_kwargs) instr_kwargs.update(kwargs) name = instr_kwargs.pop('name', identifier) if 'driver' in instr_cfg: issue_deprecation_warning( 'use of the "driver"-keyword in the station ' 'configuration file', alternative='the "type"-keyword instead, prepending the ' 'driver value' ' to it') module_name = instr_cfg['driver'] instr_class_name = instr_cfg['type'] else: module_name = '.'.join(instr_cfg['type'].split('.')[:-1]) instr_class_name = instr_cfg['type'].split('.')[-1] module = importlib.import_module(module_name) instr_class = getattr(module, instr_class_name) instr = instr_class(name, **instr_kwargs) def resolve_instrument_identifier( instrument: ChannelOrInstrumentBase, identifier: str) -> ChannelOrInstrumentBase: """ Get the instrument, channel or channel_list described by a nested string. E.g: 'dac.ch1' will return the instance of ch1. """ try: for level in identifier.split('.'): instrument = checked_getattr(instrument, level, (InstrumentBase, ChannelList)) except TypeError: raise RuntimeError( f'Cannot resolve `{level}` in {identifier} to an ' f'instrument/channel for base instrument ' f'{instrument!r}.') return instrument def resolve_parameter_identifier(instrument: ChannelOrInstrumentBase, identifier: str) -> _BaseParameter: parts = identifier.split('.') if len(parts) > 1: instrument = resolve_instrument_identifier( instrument, '.'.join(parts[:-1])) try: return checked_getattr(instrument, parts[-1], _BaseParameter) except TypeError: raise RuntimeError( f'Cannot resolve parameter identifier `{identifier}` to ' f'a parameter on instrument {instrument!r}.') def setup_parameter_from_dict(parameter: _BaseParameter, options: Dict[str, Any]) -> None: for attr, val in options.items(): if attr in PARAMETER_ATTRIBUTES: # set the attributes of the parameter, that map 1 to 1 setattr(parameter, attr, val) # extra attributes that need parsing elif attr == 'limits': if isinstance(val, str): issue_deprecation_warning( ('use of a comma separated string for the limits ' 'keyword'), alternative='an array like "[lower_lim, upper_lim]"' ) lower, upper = [float(x) for x in val.split(',')] else: lower, upper = val parameter.vals = validators.Numbers(lower, upper) elif attr == 'monitor' and val is True: self._monitor_parameters.append(parameter) elif attr == 'alias': setattr(parameter.instrument, val, parameter) elif attr == 'initial_value': # skip value attribute so that it gets set last # when everything else has been set up pass else: log.warning(f'Attribute {attr} not recognized when ' f'instatiating parameter \"{parameter.name}\"') if 'initial_value' in options: parameter.set(options['initial_value']) def add_parameter_from_dict(instr: InstrumentBase, name: str, options: Dict[str, Any]) -> None: # keep the original dictionray intact for snapshot options = copy(options) param_type: type = _BaseParameter kwargs = {} if 'source' in options: param_type = DelegateParameter kwargs['source'] = resolve_parameter_identifier( instr.root_instrument, options['source']) options.pop('source') instr.add_parameter(name, param_type, **kwargs) setup_parameter_from_dict(instr.parameters[name], options) def update_monitor(): if ((self.use_monitor is None and get_config_use_monitor()) or self.use_monitor): # restart Monitor Monitor(*self._monitor_parameters) for name, options in instr_cfg.get('parameters', {}).items(): parameter = resolve_parameter_identifier(instr, name) setup_parameter_from_dict(parameter, options) for name, options in instr_cfg.get('add_parameters', {}).items(): parts = name.split('.') local_instr = (instr if len(parts) < 2 else resolve_instrument_identifier( instr, '.'.join(parts[:-1]))) add_parameter_from_dict(local_instr, parts[-1], options) self.add_component(instr) update_monitor() return instr
def __init__(self): """ 1. setup the VNA as an instrument (if it's not already setup) 2. specify experimental parameters 3. specify paths of the target files: database file and a new folder with raw (txt, png) files """ self.vna_name = "VNA_Anritsu" self.vna_class = Anritsu_MS46522B # this is a qcodes VisaInstrument (interface between visa and qcodes) self.vna_address = "TCPIP0::169.254.235.118::5001::SOCKET" # "TCPIP0::169.254.81.17::5001::SOCKET" # "TCPIP0::169.254.235.118::5001::SOCKET" # "TCPIP0::maip-franck::hislip0,4880::INSTR" # (# 'VNA', 'TCPIP0::169.254.235.118::5001::SOCKET', # 50e6, 20e9, -30, 30, 2 # ) # -- check if instrument 'VNA' already exists. If not, create it if Instrument.exist(self.vna_name, self.vna_class): # an instrument is created by qcodes in a global context, # from which it can be retrieved manually using find_instrument self.vna = Instrument.find_instrument(self.vna_name, self.vna_class) else: if self.vna_class == Anritsu_MS46522B: self.vna = self.vna_class(self.vna_name, self.vna_address, 50e6, 20e9, -30, 30, 2) else: exit(1) # -- name the experiment -> automatic file names self.exp_name = 'Anritsu_Something' # name used by qcodes self.cooldown_date = '20-09-21' self.sample_name = 'sample_not_important' self.numberofpoints=2001 #number of measurement points self.vnapower=13 #applied power self.start_frequency=3.4e9 #3.387015e9#6.608e9-3.5e6 #start frequency of sweep self.stop_frequency=7.4e9 #3.387065e9#6.611e9 +3.5e6 #stop frequency of sweep self.frequency_span=self.stop_frequency-self.start_frequency self.center_frequency=(self.stop_frequency-self.start_frequency)/2. + self.start_frequency #just used for power sweep self.measuredtrace='S21' #spectral density measured between port 1 and 2 self.ifbandwidth=100 #IF Bandwidth, must be in (10,30,50,70,100,300,500,700,1000,3000,5000,7000,10000)Hz self.powersweepstart=-30 #start for power sweep self.powersweepstop=20 #stop for powersweep self.powersweepnum=6 #number of power sweeps (perhaps +/-1) MUST BE AN EVEN NUMBER AT LEAST 6 # # -- set experiment parameters (global constants, used in different measurement functions) # self.numberofpoints = 50 # 2001 # number of measurement points # self.vnapower = -10 # applied power # self.start_frequency = 300e3 # 3.7e9 #3.387015e9 #6.608e9-3.5e6 # start frequency of sweep # self.stop_frequency = 13.5e9 # 5.7e9 #3.387065e9 #6.611e9 +3.5e6 # stop frequency of sweep # self.frequency_span = self.stop_frequency - self.start_frequency # self.center_frequency = (self.stop_frequency - self.start_frequency)/2. + self.start_frequency # just used for power sweep # self.measuredtrace='S21' # spectral density measured between port 1 and 2 # self.ifbandwidth=10 # IF Bandwidth, must be in (10,30,50,70,100,300,500,700,1000,3000,5000,7000,10000)Hz # self.powersweepstart=-30 # start for power sweep # self.powersweepstop=13 # stop for powersweep # self.powersweepnum=3 # number of power sweeps (perhaps +/-1) MUST BE AN EVEN NUMBER AT LEAST 6 # # groupdelayref=0.0000000225 # # vna.groupdelay.set(groupdelayref)#resets to 0 instead of working -> rounding to 0 # # print(vna.groupdelay.get()) self.create_database_experiment_and_folders()
def load_instrument(self, identifier: str, revive_instance: bool = False, **kwargs) -> Instrument: """ Creates an :class:`~.Instrument` instance as described by the loaded config file. Args: identifier: the identfying string that is looked up in the yaml configuration file, which identifies the instrument to be added revive_instance: If true, try to return an instrument with the specified name instead of closing it and creating a new one. **kwargs: additional keyword arguments that get passed on to the __init__-method of the instrument to be added. """ # try to revive the instrument if revive_instance and Instrument.exist(identifier): return Instrument.find_instrument(identifier) # load file # try to reload file on every call. This makes script execution a # little slower but makes the overall workflow more convenient. self.load_config_file(self.config_file) # load from config if identifier not in self._instrument_config.keys(): raise RuntimeError(f'Instrument {identifier} not found in ' 'instrument config file') instr_cfg = self._instrument_config[identifier] # TODO: add validation of config for better verbose errors: # check if instrument is already defined and close connection if instr_cfg.get('enable_forced_reconnect', get_config_enable_forced_reconnect()): with suppress(KeyError): self.close_and_remove_instrument(identifier) # instantiate instrument init_kwargs = instr_cfg.get('init', {}) # somebody might have a empty init section in the config init_kwargs = {} if init_kwargs is None else init_kwargs if 'address' in instr_cfg: init_kwargs['address'] = instr_cfg['address'] if 'port' in instr_cfg: init_kwargs['port'] = instr_cfg['port'] # make explicitly passed arguments overide the ones from the config # file. # We are mutating the dict below # so make a copy to ensure that any changes # does not leek into the station config object # specifically we may be passing non pickleable # instrument instances via kwargs instr_kwargs = deepcopy(init_kwargs) instr_kwargs.update(kwargs) name = instr_kwargs.pop('name', identifier) module = importlib.import_module(instr_cfg['driver']) instr_class = getattr(module, instr_cfg['type']) instr = instr_class(name, **instr_kwargs) # local function to refactor common code from defining new parameter # and setting existing one def resolve_parameter_identifier(instrument: InstrumentBase, identifier: str) -> Parameter: parts = identifier.split('.') try: for level in parts[:-1]: instrument = checked_getattr(instrument, level, InstrumentBase) except TypeError: raise RuntimeError( f'Cannot resolve `{level}` in {identifier} to an ' f'instrument/channel for base instrument ' f'{instrument!r}.') try: return checked_getattr(instrument, parts[-1], Parameter) except TypeError: raise RuntimeError( f'Cannot resolve parameter identifier `{identifier}` to ' f'a parameter on instrument {instrument!r}.') def setup_parameter_from_dict(instr: Instrument, name: str, options: Dict[str, Any]): parameter = resolve_parameter_identifier(instr, name) for attr, val in options.items(): if attr in PARAMETER_ATTRIBUTES: # set the attributes of the parameter, that map 1 to 1 setattr(parameter, attr, val) # extra attributes that need parsing elif attr == 'limits': lower, upper = [float(x) for x in val.split(',')] parameter.vals = validators.Numbers(lower, upper) elif attr == 'monitor' and val is True: self._monitor_parameters.append(parameter) elif attr == 'alias': setattr(instr, val, parameter) elif attr == 'initial_value': # skip value attribute so that it gets set last # when everything else has been set up pass else: log.warning(f'Attribute {attr} not recognized when ' f'instatiating parameter \"{parameter.name}\"') if 'initial_value' in options: parameter.set(options['initial_value']) def add_parameter_from_dict(instr: Instrument, name: str, options: Dict[str, Any]): # keep the original dictionray intact for snapshot options = copy(options) if 'source' in options: instr.add_parameter( name, DelegateParameter, source=resolve_parameter_identifier(instr, options['source'])) options.pop('source') else: instr.add_parameter(name, Parameter) setup_parameter_from_dict(instr, name, options) def update_monitor(): if ((self.use_monitor is None and get_config_use_monitor()) or self.use_monitor): # restart Monitor Monitor(*self._monitor_parameters) for name, options in instr_cfg.get('parameters', {}).items(): setup_parameter_from_dict(instr, name, options) for name, options in instr_cfg.get('add_parameters', {}).items(): add_parameter_from_dict(instr, name, options) self.add_component(instr) update_monitor() return instr
def __init__(self): """ 1. setup the VNA as an instrument (if it's not already setup) 2. specify experimental parameters 3. specify paths of the target files: database file and a new folder with raw (txt, png) files """ self.vna_name = 'VNA' self.vna_class = Anritsu_MS46522B # this is a qcodes VisaInstrument (interface between visa and qcodes) # Anritsu_MS46522B("VNA2", "TCPIP0::169.254.235.118::5001::SOCKET", 50e6, 20e9, -30, 30, 2) # -- check if instrument 'VNA' already exists. If not, create it if Instrument.exist(self.vna_name, self.vna_class): # an instrument is created by qcodes in a global context, # from which it can be retrieved manually using find_instrument self.vna = Instrument.find_instrument(self.vna_name, self.vna_class) else: self.vna = self.vna_class(self.vna_name, 'TCPIP0::169.254.235.118::5001::SOCKET', 50e6, 20e9, -30, 30, 2) # -- name the experiment -> automatic file names self.exp_name = 'Warm_VNA_Noise' # name used by qcodes self.cooldown_date = '20-09-18' self.sample_name = 'no_sample' # -- set experiment parameters (global constants, used in different measurement functions) self.numberofpoints = 20 # 2001 # number of measurement points self.vnapower = -10 # applied power self.start_frequency = 3.7e9 #3.387015e9 #6.608e9-3.5e6 # start frequency of sweep self.stop_frequency = 5.7e9 #3.387065e9 #6.611e9 +3.5e6 # stop frequency of sweep self.frequency_span = self.stop_frequency - self.start_frequency self.center_frequency = (self.stop_frequency - self.start_frequency)/2. + self.start_frequency # just used for power sweep self.measuredtrace='S21' # spectral density measured between port 1 and 2 self.ifbandwidth=10 # IF Bandwidth, must be in (10,30,50,70,100,300,500,700,1000,3000,5000,7000,10000)Hz self.powersweepstart=-30 # start for power sweep self.powersweepstop=20 # stop for powersweep self.powersweepnum=6 # number of power sweeps (perhaps +/-1) MUST BE AN EVEN NUMBER AT LEAST 6 # groupdelayref=0.0000000225 # vna.groupdelay.set(groupdelayref)#resets to 0 instead of working -> rounding to 0 # print(vna.groupdelay.get()) # -- set the path where the raw data should be saved to (pngs, txts) self.raw_path = ('C:\\Users\\Desktop\\tests' + '\\' + self.cooldown_date + '_' + self.sample_name + '\\' 'raw') # set the .db path qc.config["core"]["db_location"] = ( os.path.join('C:\\Users\\Desktop\\tests', 'test.db')) # store a qcodesrc file with the loaded .db path to the measurements folder qc.config.save_config( os.path.join("C:\\Users\\Desktop\\tests", ".qcodesrc")) # -- check if in the standard folder -see qcodes config file- an experiment with exp_name already exists # if not, create a new folder at path # if so, just print the last exp. ID and go on try: # qcodes interface of loading an experiment: # -- tries to connect to a database (specificed in config data structure) and searches for the exp_name self.exp = load_experiment_by_name(self.exp_name, sample=self.sample_name) print('Experiment loaded. Last ID no: ', self.exp.last_counter) # keep track of the experiment number except ValueError: print("Experiment name ", self.exp_name, " with sample name ", self.sample_name, " not found in ", qc.config["core"]["db_location"]) print('Starting new experiment.') self.exp = new_experiment(self.exp_name, self.sample_name) os.makedirs(self.raw_path, exist_ok=True) # ---- always create a new folder for each day of taking measurements self.raw_path_with_date = os.path.join(self.raw_path, date.today().strftime("%y-%m-%d")) if not os.path.isdir(self.raw_path_with_date): os.makedirs(self.raw_path_with_date, exist_ok=True) # force-create the directory