Skip to content

Commit

Permalink
Znb spectroscopy (microsoft#834)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
jenshnielsen authored Nov 6, 2017
1 parent db9f8b5 commit 86b0322
Showing 1 changed file with 40 additions and 25 deletions.
65 changes: 40 additions & 25 deletions qcodes/instrument_drivers/rohde_schwarz/ZNB.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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))
Expand All @@ -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...]
Expand Down Expand Up @@ -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)
Expand All @@ -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))
Expand All @@ -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

Expand All @@ -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',
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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"
Expand All @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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')
Expand All @@ -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()
Expand All @@ -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
Expand All @@ -429,15 +446,13 @@ 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)
self.channels.append(channel)
if n_channels == 0:
self.display_single_window()


def _set_default_values(self):
for channel in self.channels:
channel.start(1e6)
Expand Down

0 comments on commit 86b0322

Please sign in to comment.