Coder Social home page Coder Social logo

qcodes / qcodes_contrib_drivers Goto Github PK

View Code? Open in Web Editor NEW
46.0 46.0 79.0 10.15 MB

A collection of community-contributed QCoDeS drivers for instruments

Home Page: https://qcodes.github.io/Qcodes_contrib_drivers/

License: MIT License

Python 94.80% C 5.20%

qcodes_contrib_drivers's Introduction

QCoDeS PyPi DOCS PyPI python versions DOI

Build Status Github Build Status Github Docs Ruff OpenSSF

QCoDeS is a Python-based data acquisition framework developed by the Copenhagen / Delft / Sydney / Microsoft quantum computing consortium. While it has been developed to serve the needs of nanoelectronic device experiments, it is not inherently limited to such experiments, and can be used anywhere a system with many degrees of freedom is controllable by computer. To learn more about QCoDeS, browse our homepage .

To get a feeling of QCoDeS read 15 minutes to QCoDeS, and/or browse the Jupyter notebooks in docs/examples .

QCoDeS is compatible with Python 3.10+. It is primarily intended for use from Jupyter notebooks, but can be used from traditional terminal-based shells and in stand-alone scripts as well. The features in qcodes.utils.magic are exclusively for Jupyter notebooks.

Default branch is now main

The default branch in QCoDeS has been renamed to main. If you are working with a local clone of QCoDeS 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.

Install

In general, refer to here for installation.

Docs

Read it here . Documentation is updated and deployed on every successful build in main.

We use sphinx for documentations, makefiles are provided both for Windows, and *nix, so that you can build the documentation locally.

Make sure that you have the extra dependencies required to install the docs

pip install -r docs_requirements.txt

Go to the directory docs and

make html

This generate a webpage, index.html, in docs/_build/html with the rendered html.

QCoDeS Loop

The modules qcodes.data, qcodes.plots, qcodes.actions, qcodes.loops, qcodes.measure, qcodes.extensions.slack and qcodes.utils.magic that were part of QCoDeS until version 0.37.0. have been moved into an independent package called qcodes_loop. Please see it's repository and documentation for more information.

For the time being it is possible to automatically install the qcodes_loop package when installing qcodes by executing pip install qcodes[loop].

Code of Conduct

QCoDeS strictly adheres to the Microsoft Open Source Code of Conduct

Contributing

The QCoDeS instrument drivers developed by the members of the QCoDeS community but not supported by the QCoDeS developers are contained in

https://github.com/QCoDeS/Qcodes_contrib_drivers

See Contributing for general information about bug/issue reports, contributing code, style, and testing.

License

See 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

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.

QDAC2 DC_List needs validator check

Before creating the List_Context, the dc_list method should check the min(voltages) and max(voltages) against the dc_constant_V validator or some other new validator to prevent sweeps from going beyond a desirable range.

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

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.

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

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.

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.

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?

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.

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.