Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Znb spectroscopy #834

Merged
merged 8 commits into from
Nov 6, 2017
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