From 86b0322a6246bce39dfc9df6359170a5e70fe12d Mon Sep 17 00:00:00 2001 From: Jens Hedegaard Nielsen Date: Mon, 6 Nov 2017 15:27:45 +0100 Subject: [PATCH] Znb spectroscopy (#834) * beginnings of vna driver extension to get spectroscopy mode working * debug spec mode on ZNB * measuting with ZNB * removed T3 specific modifications, now in wrappers pr #1 * removed unused imports, time and partial * The znb may return a float so round before casting to an int --- .../instrument_drivers/rohde_schwarz/ZNB.py | 65 ++++++++++++------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/qcodes/instrument_drivers/rohde_schwarz/ZNB.py b/qcodes/instrument_drivers/rohde_schwarz/ZNB.py index 6369e362902..0c280a852c0 100644 --- a/qcodes/instrument_drivers/rohde_schwarz/ZNB.py +++ b/qcodes/instrument_drivers/rohde_schwarz/ZNB.py @@ -34,6 +34,7 @@ class FrequencySweepMagPhase(MultiParameter): TODO: - ability to choose for linear or db in magnitude return """ + def __init__(self, name, instrument, start, stop, npts, channel): super().__init__(name, names=("", ""), shapes=((), ())) self._instrument = instrument @@ -56,11 +57,11 @@ def set_sweep(self, start, stop, npts): def get(self): if not self._instrument._parent.rf_power(): - log.warning("RF output is off") + log.warning("RF output is off when getting mag phase") # it is possible that the instrument and qcodes disagree about # which parameter is measured on this channel instrument_parameter = self._instrument.vna_parameter() - if instrument_parameter != self._instrument._vna_parameter: + if instrument_parameter != self._instrument._vna_parameter: raise RuntimeError("Invalid parameter. Tried to measure " "{} got {}".format(self._instrument._vna_parameter, instrument_parameter)) @@ -72,7 +73,8 @@ def get(self): # need to ensure averaged result is returned for avgcount in range(self._instrument.avg()): self._instrument.write('INIT{}:IMM; *WAI'.format(self._channel)) - data_str = self._instrument.ask('CALC{}:DATA? SDAT'.format(self._channel)).split(',') + data_str = self._instrument.ask( + 'CALC{}:DATA? SDAT'.format(self._channel)).split(',') data_list = [float(v) for v in data_str] # data_list of complex numbers [re1,im1,re2,im2...] @@ -106,11 +108,13 @@ class FrequencySweep(ArrayParameter): get(): executes a sweep and returns magnitude and phase arrays """ + def __init__(self, name, instrument, start, stop, npts, channel): super().__init__(name, shape=(npts,), instrument=instrument, unit='dB', - label='{} magnitude'.format(instrument._vna_parameter), + label='{} magnitude'.format( + instrument._vna_parameter), setpoint_units=('Hz',), setpoint_names=('{}_frequency'.format(instrument._vna_parameter),)) self.set_sweep(start, stop, npts) @@ -125,11 +129,11 @@ def set_sweep(self, start, stop, npts): def get(self): if not self._instrument._parent.rf_power(): - log.warning("RF output is off") + log.warning("RF output is off when getting mag") # it is possible that the instrument and qcodes disagree about # which parameter is measured on this channel instrument_parameter = self._instrument.vna_parameter() - if instrument_parameter != self._instrument._vna_parameter: + if instrument_parameter != self._instrument._vna_parameter: raise RuntimeError("Invalid parameter. Tried to measure " "{} got {}".format(self._instrument._vna_parameter, instrument_parameter)) @@ -141,13 +145,14 @@ def get(self): # need to ensure averaged result is returned for avgcount in range(self._instrument.avg()): self._instrument.write('INIT{}:IMM; *WAI'.format(self._channel)) - data_str = self._instrument.ask('CALC{}:DATA? FDAT'.format(self._channel)) + data_str = self._instrument.ask( + 'CALC{}:DATA? FDAT'.format(self._channel)) data = np.array(data_str.rstrip().split(',')).astype('float64') if self._instrument.format() in ['Polar', 'Complex', 'Smith', 'Inverse Smith']: log.warning("QCoDeS Dataset does not currently support Complex " "values. Will discard the imaginary part.") - data = data[0::2] + 1j*data[1::2] + data = data[0::2] + 1j * data[1::2] self._instrument._parent.cont_meas_on() return data @@ -171,14 +176,14 @@ def __init__(self, parent, name, channel): self.add_parameter(name='vna_parameter', label='VNA parameter', get_cmd="CALC{}:PAR:MEAS? '{}'".format(self._instrument_channel, - self._tracename), + self._tracename), get_parser=self._strip) self.add_parameter(name='power', label='Power', unit='dBm', get_cmd='SOUR{}:POW?'.format(n), set_cmd='SOUR{}:POW {{:.4f}}'.format(n), - get_parser=int, + get_parser=lambda x: int(round(float(x))), vals=vals.Numbers(-150, 25)) self.add_parameter(name='bandwidth', label='Bandwidth', @@ -193,7 +198,7 @@ def __init__(self, parent, name, channel): get_cmd='SENS{}:AVER:COUN?'.format(n), set_cmd='SENS{}:AVER:COUN {{:.4f}}'.format(n), get_parser=int, - vals=vals.Numbers(1, 5000)) + vals=vals.Ints(1, 5000)) self.add_parameter(name='start', get_cmd='SENS{}:FREQ:START?'.format(n), set_cmd=self._set_start, @@ -218,6 +223,10 @@ def __init__(self, parent, name, channel): get_cmd='SENS{}:SWE:POIN?'.format(n), set_cmd=self._set_npts, get_parser=int) + self.add_parameter(name='status', + get_cmd='CONF:CHAN{}:MEAS?'.format(n), + set_cmd='CONF:CHAN{}:MEAS {{}}'.format(n), + get_parser=int) self.add_parameter(name='format', get_cmd='CALC{}:FORM?'.format(n), set_cmd=self._set_format, @@ -279,7 +288,8 @@ def _set_format(self, val): channel = self._instrument_channel self.write('CALC{}:FORM {}'.format(channel, val)) self.trace.unit = unit_mapping[val] - self.trace.label = "{} {}".format(self.vna_parameter(), label_mapping[val]) + self.trace.label = "{} {}".format( + self.vna_parameter(), label_mapping[val]) def _strip(self, var): "Strip newline and quotes from instrument reply" @@ -292,11 +302,13 @@ def _set_start(self, val): npts = self.npts() if val >= stop: - raise ValueError("Stop frequency must be larger than start frequency.") + raise ValueError( + "Stop frequency must be larger than start frequency.") # we get start as the vna may not be able to set it to the exact value provided start = self.start() if val != start: - log.warning("Could not set start to {} setting it to {}".format(val, start)) + log.warning( + "Could not set start to {} setting it to {}".format(val, start)) # update setpoints for FrequencySweep param self.trace.set_sweep(start, stop, npts) self.trace_mag_phase.set_sweep(start, stop, npts) @@ -306,12 +318,14 @@ def _set_stop(self, val): start = self.start() npts = self.npts() if val <= start: - raise ValueError("Stop frequency must be larger than start frequency.") + raise ValueError( + "Stop frequency must be larger than start frequency.") self.write('SENS{}:FREQ:STOP {:.4f}'.format(channel, val)) # we get stop as the vna may not be able to set it to the exact value provided stop = self.stop() if val != stop: - log.warning("Could not set stop to {} setting it to {}".format(val, stop)) + log.warning( + "Could not set stop to {} setting it to {}".format(val, stop)) # update setpoints for FrequencySweep param self.trace.set_sweep(start, stop, npts) self.trace_mag_phase.set_sweep(start, stop, npts) @@ -343,6 +357,7 @@ def _set_center(self, val): self.trace.set_sweep(start, stop, npts) self.trace_mag_phase.set_sweep(start, stop, npts) + class ZNB(VisaInstrument): """ qcodes driver for the Rohde & Schwarz ZNB8 and ZNB20 @@ -361,6 +376,7 @@ class ZNB(VisaInstrument): TODO: - check initialisation settings and test functions """ + def __init__(self, name: str, address: str, init_s_params: bool=True, **kwargs): super().__init__(name=name, address=address, **kwargs) @@ -382,15 +398,14 @@ def __init__(self, name: str, address: str, init_s_params: bool=True, **kwargs): self._max_freq = 20e9 self._min_freq = 100e3 self.add_parameter(name='num_ports', - get_cmd='INST:PORT:COUN?', - get_parser=int) + get_cmd='INST:PORT:COUN?', + get_parser=int) num_ports = self.num_ports() self.add_parameter(name='rf_power', get_cmd='OUTP1?', set_cmd='OUTP1 {}', val_mapping={True: '1\n', False: '0\n'}) - self.add_function('reset', call_cmd='*RST') self.add_function('tooltip_on', call_cmd='SYST:ERR:DISP ON') self.add_function('tooltip_off', call_cmd='SYST:ERR:DISP OFF') @@ -399,8 +414,10 @@ def __init__(self, name: str, address: str, init_s_params: bool=True, **kwargs): self.add_function('update_display_once', call_cmd='SYST:DISP:UPD ONCE') self.add_function('update_display_on', call_cmd='SYST:DISP:UPD ON') self.add_function('update_display_off', call_cmd='SYST:DISP:UPD OFF') - self.add_function('display_sij_split', call_cmd='DISP:LAY GRID;:DISP:LAY:GRID {},{}'.format(num_ports, num_ports)) - self.add_function('display_single_window', call_cmd='DISP:LAY GRID;:DISP:LAY:GRID 1,1') + self.add_function('display_sij_split', call_cmd='DISP:LAY GRID;:DISP:LAY:GRID {},{}'.format( + num_ports, num_ports)) + self.add_function('display_single_window', + call_cmd='DISP:LAY GRID;:DISP:LAY:GRID 1,1') self.add_function('rf_off', call_cmd='OUTP1 OFF') self.add_function('rf_on', call_cmd='OUTP1 ON') self.clear_channels() @@ -409,8 +426,8 @@ def __init__(self, name: str, address: str, init_s_params: bool=True, **kwargs): self.add_submodule("channels", channels) if init_s_params: n = 1 - for i in range(1, num_ports+1): - for j in range(1, num_ports+1): + for i in range(1, num_ports + 1): + for j in range(1, num_ports + 1): ch_name = 'S' + str(i) + str(j) self.add_channel(ch_name) n += 1 @@ -429,7 +446,6 @@ def display_grid(self, rows: int, cols: int): """ self.write('DISP:LAY GRID;:DISP:LAY:GRID {},{}'.format(rows, cols)) - def add_channel(self, vna_parameter: str): n_channels = len(self.channels) channel = ZNBChannel(self, vna_parameter, n_channels + 1) @@ -437,7 +453,6 @@ def add_channel(self, vna_parameter: str): if n_channels == 0: self.display_single_window() - def _set_default_values(self): for channel in self.channels: channel.start(1e6)