Skip to content

Commit

Permalink
Merge pull request #121 from simonzihlmann/feat_CM_M5180_improvements
Browse files Browse the repository at this point in the history
Feat cm m5180 improvements
  • Loading branch information
jenshnielsen authored Mar 29, 2022
2 parents 0a580b1 + 79aa5fe commit e64f41d
Showing 1 changed file with 38 additions and 57 deletions.
95 changes: 38 additions & 57 deletions qcodes_contrib_drivers/drivers/CopperMountain/M5180.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
# Simon Zihlmannr <[email protected]>, february/march 2021
import logging
import numpy as np
from typing import Tuple, Optional, Any
import cmath, math
from typing import Tuple, Any

from qcodes import VisaInstrument
from qcodes.utils.validators import Numbers, Enum, Ints
from qcodes.utils.validators import Numbers, Enum, Ints, Bool
from qcodes.utils.helpers import create_on_off_val_mapping

from qcodes.instrument.parameter import (
MultiParameter,
ManualParameter,
ParamRawDataType
)

Expand Down Expand Up @@ -104,17 +106,13 @@ def get_raw(self) -> Tuple[ParamRawDataType, ParamRawDataType]:

class PointMagPhase(MultiParameter):
"""
Returns the first point of a sweep (at start frequency).
Returns the average Sxx of a frequency sweep.
Work around for a CW mode where only one point is read.
Ideally, npts is set to 2 and stop = start + 1 (in Hz), this will maximize
the measurement speed.
npts=2 and stop = start + 1 (in Hz) is required.
"""

def __init__(self,
name: str,
start: float,
stop: float,
npts: int,
instrument: "M5180",
**kwargs: Any,
) -> None:
Expand All @@ -123,10 +121,7 @@ def __init__(self,
Args:
name (str): Name of point measurement
start (float): Start frequency (frequency at which it will measure)
stop (float): Stop frequency, ideally start - 1 Hz
npts (int): Number of points of the sweep, ideally 2
instrument: Instrument to which sweep is bound to.
instrument: Instrument to which parameter is bound to.
"""

super().__init__(
Expand All @@ -140,39 +135,27 @@ def __init__(self,
f"{instrument.short_name} {name} phase",
),
units=("dB", "rad"),
setpoint_units=(("Hz",), ("Hz",)),
setpoint_labels=(
(f"{instrument.short_name} frequency",),
(f"{instrument.short_name} frequency",),
),
setpoint_names=(
(f"{instrument.short_name}_frequency",),
(f"{instrument.short_name}_frequency",),
),
shapes=((npts,), (npts,),),
setpoints=((), (),),
shapes=((), (),),
**kwargs,
)
self.set_sweep(start, stop, npts)

def set_sweep(self, start: float, stop: float, npts: int) -> None:
"""Updates the setpoints and shapes based on start, stop and npts.
Args:
start (float): start frequency
stop (float): stop frequency, not used
npts (int): number of points, not used
"""
f = tuple(np.linspace(int(start), int(stop), num=npts))
self.setpoints = ((start,), (start,))
self.shapes = ((), ())

def get_raw(self) -> Tuple[ParamRawDataType, ParamRawDataType]:
"""Gets data from instrument
Returns:
Tuple[ParamRawDataType, ...]: magnitude, phase
"""

assert isinstance(self.instrument, M5180)
# check that npts, start and stop fullfill requirements if point_check_sweep_first is True.
if self.instrument.point_check_sweep_first:
if self.instrument.npts() != 2:
raise ValueError('Npts is not 2 but {}. Please set it to 2'.format(self.instrument.npts()))
if self.instrument.stop() - self.instrument.start() != 1:
raise ValueError('Stop-start is not 1 Hz but {} Hz. Please adjust'
'start or stop.'.format(self.instrument.stop()-self.instrument.start()))

self.instrument.write('CALC1:PAR:COUN 1') # 1 trace
self.instrument.write('CALC1:PAR1:DEF {}'.format(self.name[-3:]))
self.instrument.trigger_source('bus') # set the trigger to bus
Expand All @@ -182,15 +165,15 @@ def get_raw(self) -> Tuple[ParamRawDataType, ParamRawDataType]:
# get data from instrument
self.instrument.write('CALC1:TRAC1:FORM SMITH') # ensure correct format
sxx_raw = self.instrument.ask("CALC1:TRAC1:DATA:FDAT?")
self.instrument.write('CALC1:TRAC1:FORM MLOG')

# Get data as numpy array
sxx = np.fromstring(sxx_raw, dtype=float, sep=',')
sxx = sxx[0::2] + 1j*sxx[1::2]

# Return only the first point of the trace, which will have "start" as
# Return the average of the trace, which will have "start" as
# its setpoint
return self.instrument._db(sxx[0]), np.angle(sxx[0])
sxx_mean = np.mean(sxx)
return 20*math.log10(abs(sxx_mean)), cmath.phase(sxx_mean)


class M5180(VisaInstrument):
Expand All @@ -204,7 +187,7 @@ def __init__(self, name : str,
timeout : int=100000,
**kwargs):
"""
QCoDeS driver for the VNA S5180 from Copper Mountain.
QCoDeS driver for the VNA M5180 from Copper Mountain.
This driver only uses one channel.
Args:
Expand Down Expand Up @@ -315,7 +298,7 @@ def __init__(self, name : str,
set_cmd=self._set_start,
unit='Hz',
vals=Numbers(min_value=300e3,
max_value=18e9))
max_value=18e9-1))

self.add_parameter(name='stop',
label='Stop Frequency',
Expand All @@ -332,17 +315,17 @@ def __init__(self, name : str,
get_cmd='SENS1:FREQ:CENT?',
set_cmd=self._set_center,
unit='Hz',
vals=Numbers(min_value=100e3,
max_value=18e9))
vals=Numbers(min_value=100e3+1,
max_value=18e9-1))

self.add_parameter(name='span',
label='Frequency Span',
get_parser=float,
get_cmd='SENS1:FREQ:SPAN?',
set_cmd=self._set_span,
unit='Hz',
vals=Numbers(min_value=100e3,
max_value=18e9))
vals=Numbers(min_value=1,
max_value=18e9-1))

self.add_parameter('npts',
label='Number of points',
Expand Down Expand Up @@ -403,29 +386,27 @@ def __init__(self, name : str,
parameter_class=FrequencySweepMagPhase)

self.add_parameter(name='point_s11',
start=self.start(),
stop=self.stop(),
npts=self.npts(),
parameter_class=PointMagPhase)

self.add_parameter(name='point_s12',
start=self.start(),
stop=self.stop(),
npts=self.npts(),
parameter_class=PointMagPhase)

self.add_parameter(name='point_s21',
start=self.start(),
stop=self.stop(),
npts=self.npts(),
parameter_class=PointMagPhase)

self.add_parameter(name='point_s22',
start=self.start(),
stop=self.stop(),
npts=self.npts(),
parameter_class=PointMagPhase)

self.add_parameter(name="point_check_sweep_first",
parameter_class=ManualParameter,
initial_value=True,
vals=Bool(),
docstring="Parameter that enables a few commands, which are called"
"before each get of a point_sxx parameter checking whether the vna"
"is setup correctly. Is recommended to be True, but can be turned"
"off if one wants to minimize overhead.",
)

self.connect_message()

def _set_start(self, val: float) -> None:
Expand Down Expand Up @@ -586,7 +567,7 @@ def update_lin_traces(self) -> None:
stop = self.stop()
npts = self.npts()
for _, parameter in self.parameters.items():
if isinstance(parameter, (FrequencySweepMagPhase, PointMagPhase)):
if isinstance(parameter, (FrequencySweepMagPhase)):
try:
parameter.set_sweep(start, stop, npts)
except AttributeError:
Expand Down

0 comments on commit e64f41d

Please sign in to comment.