Code Monkey home page Code Monkey logo

qcodes_contrib_drivers's Introduction

QCoDeS contrib drivers

This repository contains QCoDeS instrument drivers developed by members of the QCoDeS community. These drivers are not supported by the QCoDeS developers but instead supported on a best effort basis by the developers of the individual drivers.

Default branch is now main

The default branch in qcodes_contrib_drivers has been remamed to main. If you are working with a local clone of qcodes_contrib_drivers you should update it as follows.

  • Run git fetch origin and git checkout main
  • Run git symbolic-ref refs/remotes/origin/HEAD refs/remotes/origin/main to update your HEAD reference.

Getting started

Prerequisites

The drivers in this repository work with and heavily depend on QCoDeS. Start by installing QCoDeS .

Installation

Install the contrib drivers with pip

pip install qcodes_contrib_drivers

Drivers documentation

The documentations of the drivers in this repository can be read here.

Contributing

This repository is open for contribution of new drivers, as well as improvements to existing drivers. Each driver should contain an implementation of the driver and a Jupyter notebook showing how the driver should be used. In addition we strongly encourage writing tests for the drivers. An introduction for writing tests with PyVISA-sim can be found in the QCoDeS documentation linked below.

Drivers are expected to be added to qcodes_contrib_drivers/drivers/MakerOfInstrument/ folder while examples should be added to the docs/examples folder and tests placed in the qcodes_contrib_drivers/tests/MakerOfInstrument folder. Please follow naming conventions for consistency.

For general information about writing drivers and how to write tests refer to the QCoDeS documentation. Especially the examples here are useful.

LICENSE

QCoDeS-Contrib-drivers is licensed under the MIT license except the Tektronix AWG520 and Tektronix Keithley 2700 drivers which are licensed under the GPL 2 or later License.

qcodes_contrib_drivers's People

Contributors

akshita07 avatar alexcjohnson avatar astafan8 avatar caenrigen avatar dependabot[bot] avatar edumur avatar eendebakpt avatar farbo avatar gatebuilder avatar hp-peti avatar jajiko avatar jenshnielsen avatar jpsecher avatar julienbarrier avatar lakhotiaharshit avatar lankes-fzj avatar loganbvh avatar marcelhohn avatar mgunyho avatar michaelwagener avatar peendebak avatar qsaevar avatar rasmusbc59 avatar simonzihlmann avatar sldesnoo-delft avatar spauka avatar stefand986 avatar thangleiter avatar williamhpnielsen avatar yakbizzarro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

qcodes_contrib_drivers's Issues

Licensing mismatch

Hi QCoDeS folk,

I noticed that the Tektronix driver's license appears to be out of sync with the top level licensing of the project.

The project is licensed MIT, but the Tektronix code appears to be licensed GPL-2.0.

Would it be possible to make this clearer in the top level licensing and readme?

Location of QDevil QDAC 1 driver

@jpsecher I have been doing some cleanup on the driver shipped with QCoDeS tracked in microsoft/Qcodes#4457. Here I noticed that the QDevil QDAC 1 driver is shipped with QCoDeS while the QDac 2 driver is here. What do you think about moving the QDac 1 driver to here and deprecating the on in QCoDeS so that they are shipped as part of the same module?

NationalInstruments drivers missing when installing using pip

For some reason, the NationalInstruments folder and the drivers it contains are missing for me.

I tried the following:

Install version 0.5.0:

pip install qcodes_contrib_drivers

Install latest version from github:

pip install git+https://github.com/QCoDeS/Qcodes_contrib_drivers.git

In both cases, the drivers folder does not contain the NationalInstruments folder. Any ideas?

image

AimTTi and Vaunix are missing __init__.py

Hi all,

I see two driver folders (AimTTi and Vaunix) are missing init.py file in the folders.
I will try to add and run the init file locally to see if there is a problem. If no problem appears, I will make the pull request of init files.

Invalid zero based channel index in KeySight M3201A driver.

The channel numbers in the parameters of the KeySight SD_AWG are incorrect. The channels run from 1 until 4, but are implemented with zero-based index (0 till 3). This should solve the problem:

@@ -67,7 +67,7 @@ class SD_AWG(SD_Module):
                                docstring='The digital value of pxi trigger no. {}, 0 (ON) of 1 (OFF)'.format(i),
                                vals=validator.Enum(0, 1))
 
-        for i in range(channels):
+        for i in range(1, channels + 1):
             self.add_parameter('frequency_channel_{}'.format(i),
                                label='frequency channel {}'.format(i),
                                unit='Hz',

Steps to reproduce

  1. Connect to KeySight AWG:
from qcodes.instrument_drivers.Keysight.M3201A import Keysight_M3201A
awg = Keysight_M3201A('awg')
  1. Get the frequency of channel 0 and collect the error:
awg.frequency_channel_0

Expected behaviour

The frequency of channel 1 should be returned.

Actual behaviour

An SD_ERROR (INVALID_NCHANNEL) is returned.

System

operating system
Windows 7 x64

qcodes branch
master

qcodes commit
486432e319d2f302b6e2c2aed19486d38177a053

S5048 Network Analyzer driver:

This is my Qcodes driver for copper mountain S5048 network analyzer:

from typing import Union
from functools import partial
import logging

import numpy as np

from qcodes.instrument.visa import VisaInstrument
from qcodes.instrument.parameter import ArrayParameter
import qcodes.utils.validators as vals

log = logging.getLogger(name)

_unit_map = {'Log Mag': 'dB',
'Phase': 'degree',
'Group Delay': None,
'Smith': 'dim. less',
'Polar': 'dim. less',
'Lin mag': 'dim. less',
'Real': None,
'Imag': None,
'SWR': 'dim. less'}

def CMTIntParser(value: str) -> int:
"""
Small custom parser for ints

Args:
    value: the VISA return string using exponential notation
"""
return int(float(value))

class TraceNotReady(Exception):
pass

class VNAS504Trace(ArrayParameter):
"""
Class to hold a the trace from the S5048

Although the trace can have two values per frequency, this
class only returns the first value
"""

def __init__(self, name, instrument):
    super().__init__(name=name,
                     shape=(1,),  # is overwritten by prepare_trace
                     label='',  # is overwritten by prepare_trace
                     unit='',  # is overwritten by prepare_trace
                     setpoint_names=('Frequency',),
                     setpoint_labels=('Frequency',),
                     setpoint_units=('Hz',),
                     snapshot_get=False
                     )

    self._instrument = instrument

def prepare_trace(self):
    """
    Update setpoints, units and labels
    """

    # we don't trust users to keep their fingers off the front panel,
    # so we query the instrument for all values

    fstart = self._instrument.start_freq()
    fstop = self._instrument.stop_freq()
    npts = self._instrument.trace_points()

    sps = np.linspace(fstart, fstop, npts)
    self.setpoints = (tuple(sps),)
    self.shape = (len(sps),)

    self.label = self._instrument.s_parameter()
    self.unit = _unit_map[self._instrument.display_format()]

    self._instrument._traceready = True

def get_raw(self):
    """
    Return the trace
    """
    
    
    inst = self._instrument

    if not inst._traceready:
        raise TraceNotReady('Trace not ready. Please run prepare_trace.')

    inst.write('CALC:DATA:FDAT') 
    inst.visa_handle.read_termination = ''
    raw_resp = inst.visa_handle.read_raw()
    inst.visa_handle.read_termination = '\n'

    first_points = B''
    
    for n in range((len(raw_resp)-4)//4):
        first_points += raw_resp[4:][2*n*4:(2*n+1)*4]

    dt = np.dtype('f')
    trace1 = np.fromstring(first_points, dtype=dt)

class VNAS504(VisaInstrument):
"""
This is the QCoDeS driver for the VNAS5048 Network Analyzer
"""

def __init__(self, name: str, address: str, **kwargs) -> None:
    super().__init__(name, address, terminator='\n', **kwargs)

    self.add_parameter(
        'start_freq',
        label='Sweep start frequency',
        unit='Hz',
        set_cmd=partial(self.invalidate_trace, 'SENS:FREQ:STAR {}'),
        get_cmd='SENS:FREQ:STAR?',
        get_parser=float,
        vals=vals.Numbers(20000, 4800000000))

    self.add_parameter(
        'stop_freq',
        label='Sweep stop frequency',
        unit='Hz',
        set_cmd=partial(self.invalidate_trace, 'SENS:FREQ:STOP {}'),
        get_cmd='SENS:FREQ:STOP?',
        get_parser=float,
        vals=vals.Numbers(20000, 4800000000))

    self.add_parameter(
        'averaging',
        label='Averaging state',
        set_cmd='SENS:AVER{}',
        get_cmd='SENS:AVER?',
        val_mapping={'ON': 1, 'OFF': 0})

    self.add_parameter(
        'number_of_averages',
        label='Number of averages',
        set_cmd='SENS:AVER:COUN{}',
        get_cmd='SENS:AVER:COUN?',
        get_parser=CMTIntParser,
        vals=vals.Ints(0, 999))

    self.add_parameter(
        'trace_points',
        label='Number of points in trace',
        set_cmd=partial(self.invalidate_trace, 'SENS:SWE:POIN{}'),
        get_cmd='SENS:SWE:POIN?',
        get_parser=CMTIntParser,
        vals=vals.Enum(3, 11, 26, 51, 101, 201, 401,
                       801, 1601))

    self.add_parameter(
        'sweep_time',
        label='Sweep time',
        set_cmd='SENS:SWE:POIN:TIME{}',
        get_cmd='SENS:SWE:POIN:TIME?',
        unit='s',
        get_parser=float,
        vals=vals.Numbers(0, 0.3),
        )

    self.add_parameter(
        'output_power',
        label='Output power',
        unit='dBm',
        set_cmd='SOUR:POW{}',
        get_cmd='SOUR:POW?',
        get_parser=float,
        vals=vals.Numbers(-80, 20))
    
    self.add_parameter(
        's_parameter',
        label='S-parameter',
        set_cmd=self._s_parameter_setter,
        get_cmd=self._s_parameter_getter)


    # DISPLAY / Y SCALE PARAMETERS
    self.add_parameter(
        'display_format',
        label='Display format',
        set_cmd=self._display_format_setter,
        get_cmd=self._display_format_getter)

    # TODO: update this on startup and via display format
    self.add_parameter(
        'display_reference',
        label='Display reference level',
        unit=None,  # will be set by display_format
        get_cmd='DISP:WIND:TRAC:Y:RLEV?',
        set_cmd='DISP:WIND:TRAC:Y:RLEV{}',
        get_parser=float,
        vals=vals.Numbers(-10e-18, 1e18))

    self.add_parameter(
        'display_scale',
        label='Display scale',
        unit=None,  # will be set by display_format
        get_cmd='DISP:WIND:TRAC:Y:PDIV?',
        set_cmd='DISP:WIND:TRAC:Y:PDIV{}',
        get_parser=float,
        vals=vals.Numbers(-10e-18, 1e18))

    self.add_parameter(
        name='trace',
        parameter_class=VNAS504Trace)

    # Startup
    self.startup()
    self.connect_message()
    
def reset(self) -> None:
    """
    Resets the instrument to factory default state
    """
    # use OPC to make sure we wait for operation to finish
    self.ask('*OPC?;SYST:PRES')

def run_continously(self) -> None:
    """
    Set the instrument in run continously mode
    """
    self.write('INIT:CONT:ALL:ON')

def run_N_times(self, N: int) -> None:
    """
    Run N sweeps and then hold. We wait for a response before returning
    """

    st = self.sweep_time.get_latest()
    old_timeout = self.visa_handle.timeout

    if N not in range(1, 1000):
        raise ValueError('Can not run {} times.'.format(N) +
                         ' please select a number from 1-999.')

    # set a longer timeout, to not timeout during the sweep
    new_timeout = 1000*st*N + 1000
    self.visa_handle.timeout = new_timeout

    log.debug('Making {} blocking sweeps.'.format(N) +
              ' Setting VISA timeout to {} s.'.format(new_timeout/1000))

    self.ask('*OPC?;NUMG{}'.format(N))

    self.visa_handle.timeout = old_timeout

def invalidate_trace(self, cmd: str,
                     value: Union[float, int, str]) -> None:
    """
    Wrapper for set_cmds that make the trace not ready
    """
    self._traceready = False
    self.write(cmd.format(value))

def startup(self) -> None:
    self._traceready = False
    self.display_format(self.display_format())

def _s_parameter_setter(self, param: str) -> None:
    """
    set_cmd for the s_parameter parameter
    """
    if param not in ['S11', 'S12', 'S21', 'S22']:
        raise ValueError('Cannot set s-parameter to {}')

    # the trace labels changes
    self._traceready = False

    self.write(f"CALC:PAR:DEF \"{param}\"")

def _s_parameter_getter(self) -> str:
    """
    get_cmd for the s_parameter parameter
    """
    for cmd in ['S11', 'S12', 'S21', 'S22']:
        resp = self.ask('CALC:PAR:DEF?')
        if resp in ['1', '1\n']:
            break

    return cmd.replace('?', '')

def _display_format_setter(self, fmt: str) -> None:
    """
    set_cmd for the display_format parameter
    """
    val_mapping = {'Log Mag': 'MLOG',
                   'Phase': 'PHAS',
                   'Group Delay': 'GDEL',
                   'Smith': 'SMIT',
                   'Polar': 'POL',
                   'Lin Mag': 'MLIN',
                   'Real': 'REAL',
                   'Imag': 'IMAG',
                   'SWR': 'SWR'}

    if fmt not in val_mapping.keys():
        raise ValueError('Cannot set display_format to {}.'.format(fmt))

    self._traceready = False
    
    self.display_reference.unit = _unit_map[fmt]
    self.display_scale.unit = _unit_map[fmt] 
    
    self.write(f"CALC:FORM \"{fmt}\"")

def _display_format_getter(self) -> str:
    """
    get_cmd for the display_format parameter
    """
    val_mapping = {'MLOG': 'Log Mag',
                   'PHAS': 'Phase',
                   'GDEL': 'Group Delay',
                   'SMIT': 'Smith',
                   'POL': 'Polar',
                   'MLIN': 'Lin Mag',
                   'REAL': 'Real',
                   'IMAG': 'Imag',
                   'SWR': 'SWR'}

    # keep asking until we find the currently used format
    for cmd in val_mapping.keys():
        resp = self.ask('CALC:FORM?'.format(cmd))
        if resp in ['1', '1\n']:
            break

    return val_mapping[cmd]

I have followed the QCoDeS driver script of HP 8753D Network Analyzer. My driver can connect to the instrument, but not responding to the commands. Can anyone please let me know where I am making mistakes. Thank you very much.

zhinst update makes HF2LI qcodes driver not working

Dear all,

I am not sure if I should post that here or on the zhinst repo.

The code to reproduce the error:

from Qcodes_contrib_drivers.qcodes_contrib_drivers.drivers.ZurichInstruments.HF2LI import HF2LI

hf2li = HF2LI(...)
hf2li.sigouts.sigouts0.range()

The error:

ValueError                                Traceback (most recent call last)
Input In [8], in <cell line: 1>()
----> 1 hf2li.sigouts.sigouts0.range()

File ~\Miniconda3\envs\python38\lib\site-packages\zhinst\qcodes\qcodes_adaptions.py:208, in ZIParameter.__call__(self, *args, **kwargs)
    206 if len(args) == 0:
    207     if self.gettable:
--> 208         return self.get(**kwargs)
    209     else:
    210         raise NotImplementedError(
    211             "no get cmd found in" + f" Parameter {self.name}"
    212         )

File ~\Miniconda3\envs\python38\lib\site-packages\qcodes\instrument\parameter.py:661, in _BaseParameter._wrap_get.<locals>.get_wrapper(*args, **kwargs)
    659 except Exception as e:
    660     e.args = e.args + (f'getting {self}',)
--> 661     raise e

File ~\Miniconda3\envs\python38\lib\site-packages\qcodes\instrument\parameter.py:648, in _BaseParameter._wrap_get.<locals>.get_wrapper(*args, **kwargs)
    643     raise NotImplementedError(
    644         f"Trying to get an abstract parameter: {self.full_name}"
    645     )
    646 try:
    647     # There might be cases where a .get also has args/kwargs
--> 648     raw_value = get_function(*args, **kwargs)
    650     value = self._from_raw_value_to_value(raw_value)
    652     if self._validate_on_get:

File ~\Miniconda3\envs\python38\lib\site-packages\zhinst\toolkit\nodetree\node.py:503, in Node._get(self, deep, enum, parse, **kwargs)
    501     else:
    502         value = self._get_cached(**kwargs)
--> 503     value = self._parse_get_value(value, enum=enum, parse=parse)
    504     return (timestamp, value) if deep else value
    505 if readable is None and (
    506     self.node_info.contains_wildcards or self.node_info.is_partial
    507 ):

File ~\Miniconda3\envs\python38\lib\site-packages\zhinst\toolkit\nodetree\node.py:455, in Node._parse_get_value(self, value, enum, parse)
    443 """Parse the raw value from the data server.
    444 
    445 Args:
   (...)
    452     Parsed value
    453 """
    454 if enum and isinstance(value, int):
--> 455     enum_info = self.node_info.options.get(value, None)
    456     value = (
    457         getattr(self.node_info.enum, enum_info.enum)
    458         if enum_info and enum_info.enum
    459         else value
    460     )
    461 if parse:

File ~\Miniconda3\envs\python38\lib\site-packages\zhinst\toolkit\nodetree\node.py:227, in NodeInfo.options(self)
    225 for key, value in self._info.get("Options", {}).items():
    226     node_options = re.findall(r'("(.+?)"[,:]+)? ?(.*)', value)
--> 227     option_map[int(key)] = self._option_info(
    228         node_options[0][1], node_options[0][2]
    229     )
    230 return option_map

ValueError: ("invalid literal for int() with base 10: '0.01'", 'getting zi_baseinstrument_dev***_sigouts0_range')

I guess someone has to update the qcodes driver to the new zhinst dict.

Latest versions of packaging break QDAC2 driver

Somewhere in the recent changes of packaging, using packaging.version.parse on strings like 'w-x.y.z' raises an error about an invalid firmware version. Explicitly installing an older version (I used packaging 20.0) circumvents this issue.

AFG3000 validators

I wanted to use AFG3000.py, but it relied on Multiples(divisor: float) which throws a TypeError:

 Traceback (most recent call last):                                                                                                                                                                                                                                               
  File "/usr/lib/python-exec/python3.9/qcodestool", line 12, in <module>                                                                                                                                                                                                         
    sys.exit(cli())                                                                                                                                                                                                                                                              
  File "/usr/lib/python3.9/site-packages/click/core.py", line 1128, in __call__                                                                                                                                                                                                  
    return self.main(*args, **kwargs)                                                                                                                                                                                                                                            
  File "/usr/lib/python3.9/site-packages/click/core.py", line 1053, in main                                                             
    rv = self.invoke(ctx)                                                                                                                                                                                                                                                        
  File "/usr/lib/python3.9/site-packages/click/core.py", line 1659, in invoke                                                                                                                                                                                                    
    return _process_result(sub_ctx.command.invoke(sub_ctx))                                                                                                                                                                                                                      
  File "/usr/lib/python3.9/site-packages/click/core.py", line 1395, in invoke                                                                                                                                                                                                    
    return ctx.invoke(self.callback, **ctx.params)                                                                                      
  File "/usr/lib/python3.9/site-packages/click/core.py", line 754, in invoke                                                            
    return __callback(*args, **kwargs)                                                                                                                                                                                                                                           
  File "/usr/lib/python3.9/site-packages/click/decorators.py", line 26, in new_func                                                                                                                                                                                              
    return f(get_current_context(), *args, **kwargs)                                                                                                                                                                                                                             
  File "/usr/lib/python3.9/site-packages/qcodestool/qcodestool.py", line 119, in afg3022b                                               
    afg = afg3000.AFG3000(address='GPIB0::1::INSTR', name='afg3022b')                                                                   
  File "/usr/lib/python3.9/site-packages/qcodes/instrument/base.py", line 508, in __call__                                                                                                                                                                                       
    new_inst = super().__call__(*args, **kwargs)
  File "/usr/lib/python3.9/site-packages/qcodes_contrib_drivers/drivers/Tektronix/AFG3000.py", line 62, in __init__
    vals=vals.Multiples(divisor=0.1, min_value=0, max_value=120)
  File "/usr/lib/python3.9/site-packages/qcodes/utils/validators.py", line 492, in __init__
    raise TypeError('divisor must be a positive integer')
TypeError: divisor must be a positive integer

I ended up adding an AND version of MultiType: jakeogh/Qcodes@8c79eb1

and patched AFG3000.py: jakeogh@baa1c50

99% sure I'm missing something obvious. First time using Qcodes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.