From d852244059bd60be8ab161a434e9154d5fac5839 Mon Sep 17 00:00:00 2001 From: Simon Zihlmann Date: Wed, 30 Sep 2020 18:50:30 +0200 Subject: [PATCH 01/10] add first version of Lakeshore/Model_625.py driver and example --- docs/examples/Lakeshore_625.ipynb | 330 ++++++++++++++ .../drivers/Lakeshore/Model_625.py | 419 ++++++++++++++++++ 2 files changed, 749 insertions(+) create mode 100644 docs/examples/Lakeshore_625.ipynb create mode 100644 qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py diff --git a/docs/examples/Lakeshore_625.ipynb b/docs/examples/Lakeshore_625.ipynb new file mode 100644 index 000000000..7b49bd9a6 --- /dev/null +++ b/docs/examples/Lakeshore_625.ipynb @@ -0,0 +1,330 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Example with Lakeshore Model 625 Superconducting Magnet power supply" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import qcodes as qc" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "from qcodes_contrib_drivers.drivers.Lakeshore.Model_625 import Lakeshore625" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "c:\\users\\g-gre-gre054789\\qcodes\\qcodes\\instrument\\parameter.py:258: UserWarning: _BaseParameter got unexpected kwargs: {'full_name': 'magnet_field'}. These are unused and will be discarded. This will be an error in the future.\n", + " warnings.warn(f\"_BaseParameter got unexpected kwargs: {kwargs}.\"\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connected to: LSCI 625 (serial:6251287, firmware:1.3/1.1) in 0.68s\n" + ] + } + ], + "source": [ + "# Initialize a single power supply for a superconducting magnet using GPIB\n", + "# specify coil constant of the magnet in units of T/A\n", + "# specifz field ramp rate in units of T/min\n", + "magnet = Lakeshore625(name = 'magnet', address = 'GPIB0::4::INSTR', coil_constant = 0.0166614, field_ramp_rate = 0.15)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'vendor': 'LSCI', 'model': '625', 'serial': '6251287', 'firmware': '1.3/1.1'}" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "magnet.IDN()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "magnet:\n", + "\tparameter value\n", + "--------------------------------------------------------------------------------\n", + "IDN :\t{'vendor': 'LSCI', 'model': '625', 'serial': '625...\n", + "coil_constant :\t0.01666 (magnet_coil_constant_unit)\n", + "coil_constant_unit :\tT/A \n", + "current :\t0.0015 (A)\n", + "current_limit :\t55 (A)\n", + "current_ramp_rate :\t0.15 (A/s)\n", + "current_rate_limit :\t0.3 (A/s)\n", + "field :\t2.5e-05 (T)\n", + "field_ramp_rate :\t0.14994 (T/min)\n", + "oer_quench :\tno quench detected \n", + "operational_error_status :\t000000000 \n", + "persistent_switch_heater :\tdisabled \n", + "quench_current_step_limit :\t0.4 (A/s)\n", + "quench_detection :\tenabled \n", + "ramp_segments :\tdisabled \n", + "ramping_state :\tnot ramping \n", + "timeout :\t10 (s)\n", + "voltage :\t0.0027 (V)\n", + "voltage_limit :\t1 (V)\n" + ] + } + ], + "source": [ + "# Let's look at all parameters\n", + "magnet.print_readable_snapshot(update=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Check current to field conversion" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "coil constant = 0.02 T/A\n", + "current limit = 55.0 A\n", + "current ramp rate limit = 0.3 A/s\n" + ] + } + ], + "source": [ + "# Since the set method of the driver only excepts fields in Tesla and we want to check if the correct \n", + "# currents are applied, we need to convert target currents to target fields. For this reason we need \n", + "# the coil constant. \n", + "coil_const = magnet.coil_constant()\n", + "current_limit = magnet.current_limit()\n", + "current_rate_limit = magnet.current_rate_limit()\n", + "print(\"coil constant = {} T/A\".format(coil_const))\n", + "print(\"current limit = {} A\".format(current_limit))\n", + "print(\"current ramp rate limit = {} A/s\".format(current_rate_limit))" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Target field is 0.002 T\n", + "Measured field is 0.00203 T\n", + "Measured current is = 0.1015 A\n" + ] + } + ], + "source": [ + "# Let see if we can set and get the field in Tesla \n", + "target_current = 0.1 # [A] The current we want to set \n", + "target_field = coil_const * target_current # [T]\n", + "print(\"Target field is {} T\".format(target_field))\n", + "magnet.field(target_field)\n", + "\n", + "field = magnet.field() # This gives us the measured field\n", + "print(\"Measured field is {} T\".format(field))\n", + "# The current should be \n", + "current = field / coil_const\n", + "print(\"Measured current is = {} A\".format(current))\n", + "# We have verified with manual inspection that the current has indeed ben reached" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Let's have a look at other parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Field" + ] + }, + { + "cell_type": "code", + "execution_count": 41, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "0.00202" + ] + }, + "execution_count": 41, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Let's read the field\n", + "magnet.field()" + ] + }, + { + "cell_type": "code", + "execution_count": 42, + "metadata": {}, + "outputs": [], + "source": [ + "# Let's set a field (blocking mode)\n", + "magnet.field(0.01)" + ] + }, + { + "cell_type": "code", + "execution_count": 43, + "metadata": {}, + "outputs": [], + "source": [ + "# Let's set a field (non-blocking mode)\n", + "magnet.set_field(0.01, block=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Ramp rate" + ] + }, + { + "cell_type": "code", + "execution_count": 45, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Field ramp rate: 0.09996 T/min.\n", + "Current ramp rate: 0.0833 A/s.\n", + "Field ramp rate: 0.19992 T/min.\n", + "Current ramp rate: 0.1666 A/s.\n" + ] + } + ], + "source": [ + "# The field ramp rate can easily be changed (this will update the current ramp rate as well since the power supply only works in current)\n", + "magnet.field_ramp_rate(0.1)\n", + "print('Field ramp rate: {} {}.'.format(magnet.field_ramp_rate(), magnet.field_ramp_rate.unit))\n", + "print('Current ramp rate: {} {}.'.format(magnet.current_ramp_rate(), magnet.current_ramp_rate.unit))\n", + "\n", + "magnet.field_ramp_rate(0.2)\n", + "print('Field ramp rate: {} {}.'.format(magnet.field_ramp_rate(), magnet.field_ramp_rate.unit))\n", + "print('Current ramp rate: {} {}.'.format(magnet.current_ramp_rate(), magnet.current_ramp_rate.unit))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Quench detection" + ] + }, + { + "cell_type": "code", + "execution_count": 29, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Quench detection is enabled.\n", + "Current rate limit for quench detection:0.4 A/s\n", + "There was no no quench detected.\n" + ] + } + ], + "source": [ + "# Quenches detection can be enabled, which it is by default\n", + "print('Quench detection is {}.'.format(magnet.quench_detection()))\n", + "\n", + "# A quench is detected if the current rate is above the follwoing limit\n", + "print('Current rate limit for quench detection:{} {}'.format(magnet.quench_current_step_limit(), magnet.quench_current_step_limit.unit))\n", + "\n", + "# Let's check if there was a quench detected\n", + "print('There was no {}.'.format(magnet.oer_quench()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py new file mode 100644 index 000000000..f83921960 --- /dev/null +++ b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py @@ -0,0 +1,419 @@ +import logging +import time + + +from qcodes import VisaInstrument +from qcodes.utils.validators import Numbers, Enum + +log = logging.getLogger(__name__) + +class Lakeshore625(VisaInstrument): + """ + Driver for the Lakeshore 625 magnet power supply. + + This class uses T/A and A/s as units. + + Args: + name (str): a name for the instrument + address (str): VISA address of the device + current_ramp_limit: A current ramp limit, in units of A/s + """ + + def __init__(self, name, coil_constant, field_ramp_rate, address=None, + reset=False, terminator='', **kwargs): + + super().__init__(name, address, terminator=terminator, **kwargs) + + # Add reset function + self.add_function('reset', call_cmd='*RST') + if reset: + self.reset() + + # Add solenoid parameters + self.add_parameter('coil_constant_unit', + set_cmd=self._set_coil_constant_unit, + get_cmd=self._get_coil_constant_unit, + get_parser=float, + val_mapping={'T/A': 0, + 'kG/A': 1}) + + self.add_parameter('coil_constant', + unit = self.coil_constant_unit, + get_cmd=self._get_coil_constant, + set_cmd=self._update_coil_constant, + vals=Numbers(0.001, 999.99999)) # what are good numbers here? + + self.add_parameter('current_limit', + unit="A", + set_cmd=lambda x: self._set_curent_limit(x), + get_cmd=self._get_current_limit, + get_parser=float, + vals=Numbers(0, 60.1)) + + self.add_parameter('field_ramp_rate', + unit = 'T/min', + get_cmd=self._get_field_ramp_rate, + set_cmd=self._set_field_ramp_rate) + + self.add_parameter('voltage_limit', + unit="V", + set_cmd=lambda x: self._set_voltage_limit(x), + get_cmd=self._get_voltage_limit, + get_parser=float, + vals=Numbers(0, 5)) # what are good numbers here? + + self.add_parameter('current_rate_limit', + unit="A/s", + set_cmd=lambda x: self._set_current_rate_limit(x), + get_cmd=self._get_current_rate_limit, + get_parser=float, + vals=Numbers(0, 99.999)) # what are good numbers here? + + + + + # Add current solenoid parameters + # Note that field is validated in set_field + self.add_parameter('field', + unit = 'T', + full_name = self.name + '_' + 'field', + set_cmd=self.set_field, + get_cmd='RDGF?', + get_parser=float) + + self.add_parameter('voltage', + unit = 'V', + set_cmd="SETV {}", + get_cmd='RDGV?', + get_parser=float, + vals=Numbers(-5, 5)) + + self.add_parameter('current', + unit = 'A', + set_cmd="SETI {}", + get_cmd='RDGI?', + get_parser=float, + vals=Numbers(-60, 60)) + + self.add_parameter('current_ramp_rate', + unit = 'A/s', + set_cmd="RATE {}", + get_cmd='RATE?', + get_parser=float) + + self.add_parameter('ramp_segments', + set_cmd="RSEG {}", + get_cmd='RSEG?', + get_parser=float, + val_mapping={'disabled': 0, + 'enabled': 1}) + + self.add_parameter('persistent_switch_heater', + set_cmd=lambda x: self._set_persistent_switch_heater_status(x), + get_cmd=self._get_persistent_switch_heater_status, + get_parser=float, + val_mapping={'disabled': 0, + 'enabled': 1}) + + self.add_parameter('quench_detection', + set_cmd=lambda x: self._set_quench_detection_status(x), + get_cmd=self._get_quench_detection_status, + get_parser=float, + val_mapping={'disabled': 0, + 'enabled': 1}) + + self.add_parameter('quench_current_step_limit', + unit = 'A/s', + set_cmd=lambda x: self._set_quench_current_step_limit(x), + get_cmd=self._get_quench_current_step_limit, + get_parser=float, + vals=Numbers(0.01, 10)) + + self.add_parameter('ramping_state', + get_cmd=self._get_ramping_state, + vals=Enum('ramping', 'not ramping')) + + self.add_parameter('operational_error_status', + get_cmd=self._get_operational_errors, + get_parser=str) + + self.add_parameter('oer_quench', + get_cmd=self._get_oer_quench_bit, + get_parser=int, + val_mapping={'no quench detected': 0, + 'quench detected': 1}) + + # Add clear function + self.add_function('clear', call_cmd='*CLS') + + # disable persistent switch heater by default + self.persistent_switch_heater('disabled') + + # disable ramp segments by default + self.ramp_segments('disabled') + + # set coil constant unit to T/A by default + self.coil_constant_unit('T/A') + + # assign init parameters + self.coil_constant(coil_constant) + self.field_ramp_rate(field_ramp_rate) + + self.connect_message() + + + + + def _sleep(self, t): + """ + Sleep for a number of seconds t. If we are or using + the PyVISA 'sim' backend, omit this + """ + + simmode = getattr(self, 'visabackend', False) == 'sim' + + if simmode: + return + else: + time.sleep(t) + + # get functions returning several values + def _get_limit(self): + """ + Gets the limits of the supply + """ + raw_string = self.ask('LIMIT?') + current_limit, voltage_limit, current_rate_limit = raw_string.split(',') + return float(current_limit), float(voltage_limit), float(current_rate_limit) + + def _get_persistent_switch_heater_setup(self): + """ + Gets the persistant switch heater setup + """ + raw_string = self.ask('PSHS?') + status, psh_current, psh_delay = raw_string.split(',') + return float(status), float(psh_current), float(psh_delay) + + def _get_quench_detection_setup(self): + """ + Gets the quench detections setup, returns 'status' and 'current step limit' + """ + raw_string = self.ask('QNCH?') + status, current_step_limit = raw_string.split(',') + return float(status), float(current_step_limit) + + def _get_field_setup(self): + """ + Gets the field setup, returns 'coil constant unit' and 'coil constant' + """ + raw_string = self.ask('FLDS?') + unit, coil_constant = raw_string.split(',') + return str(unit), float(coil_constant) + + + # get functions for parameters + def _get_current_limit(self): + """ + Gets the current limit of the coil + """ + current_limit, voltage_limit, current_rate_limit = self._get_limit() + return current_limit + + def _get_voltage_limit(self): + """ + Gets the current limit of the coil + """ + current_limit, voltage_limit, current_rate_limit = self._get_limit() + return voltage_limit + + def _get_current_rate_limit(self): + """ + Gets the current limit of the coil + """ + current_limit, voltage_limit, current_rate_limit = self._get_limit() + return current_rate_limit + + def _get_persistent_switch_heater_status(self): + """ + Sets the status of the persistant switch heater + """ + status, psh_current, psh_delay = self._get_persistent_switch_heater_setup() + return status + + def _get_quench_detection_status(self): + """ + Gets the quench detections status + """ + status, current_step_limit = self._get_quench_detection_setup() + return float(status) + + def _get_quench_current_step_limit(self): + """ + Gets the quench detections status + """ + status, current_step_limit = self._get_quench_detection_setup() + return float(current_step_limit) + + def _get_coil_constant(self): + """ + Gets the coil_constant + """ + coil_constant_unit, coil_constant = self._get_field_setup() + return float(coil_constant) + + def _get_coil_constant_unit(self): + """ + Gets the coil_constant + """ + coil_constant_unit, coil_constant = self._get_field_setup() + return str(coil_constant_unit) + + def _get_field_ramp_rate(self): + """ + Gets the field ramp rate + """ + coil_constant_unit, coil_constant = self._get_field_setup() # in T/A by default + current_ramp_rate = self.current_ramp_rate() # in A/s + field_ramp_rate = current_ramp_rate * coil_constant * 60 # in T/min + return float(field_ramp_rate) + + def _get_ramping_state(self): + """ + Gets the ramping state of the power supply (corresponds to blue LED on panel) + Is inferred from the status bit register + """ + operation_condition_register = self.ask('OPST?') + bin_OPST = bin(int(operation_condition_register))[2:] + if len(bin_OPST)<2: + rampbit = 1 + else: + # read second bit, 0 = ramping, 1 = not ramping + rampbit = int(bin_OPST[-2]) + if rampbit == 1: + return 'not ramping' + else: + return 'ramping' + + def _get_operational_errors(self): + """ + Reads the Error status register to infer the operational errors + """ + error_status_register = self.ask('ERST?') + # three bytes are read at the same time, the middle one is the operational error status + operational_error_registor = error_status_register.split(',')[1] + + #prepend zeros to bit-string such that it always has length 9 + oer_bit = bin(int(operational_error_registor))[2:].zfill(9) + return(oer_bit) + + def _get_oer_quench_bit(self): + """ + Returns the oer quench bit + """ + return self._get_operational_errors()[3] + + + # set functions for parameters + def _set_curent_limit(self, current_limit_setpoint): + """ + Sets the current limit of the coil + """ + current_limit, voltage_limit, current_rate_limit = self._get_limit() + self.write_raw('LIMIT {}, {}, {}'.format(current_limit_setpoint, voltage_limit, current_rate_limit)) + + def _set_voltage_limit(self, voltage_limit_setpoint): + """ + Sets the current limit of the coil + """ + current_limit, voltage_limit, current_rate_limit = self._get_limit() + self.write_raw('LIMIT {}, {}, {}'.format(current_limit, voltage_limit_setpoint, current_rate_limit)) + + def _set_current_rate_limit(self, current_rate_limit_setpoint): + """ + Sets the current limit of the coil + """ + current_limit, voltage_limit, current_rate_limit = self._get_limit() + self.write_raw('LIMIT {}, {}, {}'.format(current_limit, voltage_limit, current_rate_limit_setpoint)) + + def _set_persistent_switch_heater_status(self, status_setpoint): + """ + Sets the status of the persistant switch heater + """ + status, psh_current, psh_delay = self._get_persistent_switch_heater_setup() + self.write_raw('PSHS {}, {}, {}'.format(status_setpoint, psh_current, psh_delay)) + + def _set_quench_detection_status(self, status_setpoint): + """ + Sets the quench detections status + """ + status, current_step_limit = self._get_quench_detection_setup() + self.write_raw('QNCH {}, {}'.format(status_setpoint, current_step_limit)) + + def _set_quench_current_step_limit(self, current_step_limit_setpoint): + """ + Sets the quench detections status + """ + status, current_step_limit = self._get_quench_detection_setup() + self.write_raw('QNCH {}, {}'.format(status, current_step_limit_setpoint)) + + def _set_coil_constant(self, coil_constant_setpoint): + """ + Sets the coil_constant + """ + coil_constant_unit, coil_constant = self._get_field_setup() + self.write_raw('FLDS {}, {}'.format(coil_constant_unit, coil_constant_setpoint)) + + def _set_coil_constant_unit(self, coil_constant_unit_setpoint): + """ + Sets the coil_constant + """ + coil_constant_unit, coil_constant = self._get_field_setup() + self.write_raw('FLDS {}, {}'.format(coil_constant_unit_setpoint, coil_constant)) + + def _update_coil_constant(self, coil_constant_setpoint): + """ + Updates the coil_constant and with it all linked parameters + """ + # read field_ramp_rate before chaning coil constant + field_ramp_rate = self.field_ramp_rate() + # set the coil constant + self._set_coil_constant(coil_constant_setpoint) + # update the current ramp rate, leaving the field ramp rate unchanged + current_ramp_rate_setpoint = field_ramp_rate / coil_constant_setpoint / 60 # current_ramp_rate is in A/s + self.current_ramp_rate(current_ramp_rate_setpoint) + + def _set_field_ramp_rate(self, field_ramp_rate_setpoint): + """ + Sets the field ramp rate in units of T/min by setting the corresponding current_ramp_rate + """ + coil_constant_unit, coil_constant = self._get_field_setup() # in T/A by default + current_ramp_rate_setpoint = field_ramp_rate_setpoint / coil_constant / 60 # current_ramp_rate is in A/s + self.current_ramp_rate(current_ramp_rate_setpoint) + + + + + def set_field(self, value, block=True): + """ + Ramp to a certain field + + Args: + block (bool): Whether to wait unit the field has finished setting + perform_safety_check (bool): Whether to set the field via a parent + driver (if present), which might perform additional safety + checks. + """ + + self.write('SETF {}'.format(value)) + # Check if we want to block + if not block: + return + + # Otherwise, wait until no longer ramping + self.log.debug(f'Starting blocking ramp of {self.name} to {value}') + self._sleep(0.5) # wait for a short time for the power supply to fall into the ramping state + while self.ramping_state() == 'ramping': + self._sleep(0.3) + self._sleep(2.0) + self.log.debug(f'Finished blocking ramp') + return From b639854210931e6ef4cd27ec21a5c2673ddfa2dc Mon Sep 17 00:00:00 2001 From: Simon Zihlmann Date: Fri, 27 Nov 2020 17:59:57 +0100 Subject: [PATCH 02/10] finish docstring of Model_625.py --- .../drivers/Lakeshore/Model_625.py | 391 +++++++++++------- 1 file changed, 248 insertions(+), 143 deletions(-) diff --git a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py index f83921960..e58f6ad93 100644 --- a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py +++ b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py @@ -1,5 +1,6 @@ import logging import time +from typing import Union, Tuple from qcodes import VisaInstrument @@ -9,7 +10,7 @@ class Lakeshore625(VisaInstrument): """ - Driver for the Lakeshore 625 magnet power supply. + Driver for the Lakeshore Model 625 spuerconducting magnet power supply. This class uses T/A and A/s as units. @@ -19,8 +20,8 @@ class Lakeshore625(VisaInstrument): current_ramp_limit: A current ramp limit, in units of A/s """ - def __init__(self, name, coil_constant, field_ramp_rate, address=None, - reset=False, terminator='', **kwargs): + def __init__(self, name: str, coil_constant: float, field_ramp_rate: float, address: str=None, + reset: bool=False, terminator:str='', **kwargs) -> None: super().__init__(name, address, terminator=terminator, **kwargs) @@ -29,119 +30,141 @@ def __init__(self, name, coil_constant, field_ramp_rate, address=None, if reset: self.reset() - # Add solenoid parameters - self.add_parameter('coil_constant_unit', - set_cmd=self._set_coil_constant_unit, - get_cmd=self._get_coil_constant_unit, - get_parser=float, - val_mapping={'T/A': 0, - 'kG/A': 1}) - - self.add_parameter('coil_constant', - unit = self.coil_constant_unit, - get_cmd=self._get_coil_constant, - set_cmd=self._update_coil_constant, - vals=Numbers(0.001, 999.99999)) # what are good numbers here? - - self.add_parameter('current_limit', + # Add power supply parameters + self.add_parameter(name='current_limit', unit="A", set_cmd=lambda x: self._set_curent_limit(x), get_cmd=self._get_current_limit, get_parser=float, - vals=Numbers(0, 60.1)) - - self.add_parameter('field_ramp_rate', - unit = 'T/min', - get_cmd=self._get_field_ramp_rate, - set_cmd=self._set_field_ramp_rate) + vals=Numbers(0, 60.1), + docstring="Maximum output current" + ) - self.add_parameter('voltage_limit', + self.add_parameter(name='voltage_limit', unit="V", set_cmd=lambda x: self._set_voltage_limit(x), get_cmd=self._get_voltage_limit, get_parser=float, - vals=Numbers(0, 5)) # what are good numbers here? + vals=Numbers(0, 5), + docstring="Maximum compliance voltage" + ) - self.add_parameter('current_rate_limit', + self.add_parameter(name='current_rate_limit', unit="A/s", set_cmd=lambda x: self._set_current_rate_limit(x), get_cmd=self._get_current_rate_limit, get_parser=float, - vals=Numbers(0, 99.999)) # what are good numbers here? - - - - - # Add current solenoid parameters - # Note that field is validated in set_field - self.add_parameter('field', - unit = 'T', - full_name = self.name + '_' + 'field', - set_cmd=self.set_field, - get_cmd='RDGF?', - get_parser=float) + vals=Numbers( 0.0001, 99.999), + docstring="Maximum current ramp rate" + ) - self.add_parameter('voltage', + self.add_parameter(name='voltage', unit = 'V', set_cmd="SETV {}", get_cmd='RDGV?', get_parser=float, - vals=Numbers(-5, 5)) + vals=Numbers(-5, 5) + ) - self.add_parameter('current', + self.add_parameter(name='current', unit = 'A', set_cmd="SETI {}", get_cmd='RDGI?', get_parser=float, - vals=Numbers(-60, 60)) + vals=Numbers(-60, 60) + ) - self.add_parameter('current_ramp_rate', + self.add_parameter(name='current_ramp_rate', unit = 'A/s', set_cmd="RATE {}", get_cmd='RATE?', - get_parser=float) + get_parser=float + ) - self.add_parameter('ramp_segments', + self.add_parameter(name='ramp_segments', set_cmd="RSEG {}", get_cmd='RSEG?', get_parser=float, val_mapping={'disabled': 0, - 'enabled': 1}) + 'enabled': 1} + ) - self.add_parameter('persistent_switch_heater', + self.add_parameter(name='persistent_switch_heater', set_cmd=lambda x: self._set_persistent_switch_heater_status(x), get_cmd=self._get_persistent_switch_heater_status, get_parser=float, val_mapping={'disabled': 0, - 'enabled': 1}) + 'enabled': 1} + ) - self.add_parameter('quench_detection', + self.add_parameter(name='quench_detection', set_cmd=lambda x: self._set_quench_detection_status(x), get_cmd=self._get_quench_detection_status, get_parser=float, val_mapping={'disabled': 0, - 'enabled': 1}) + 'enabled': 1} + ) - self.add_parameter('quench_current_step_limit', + self.add_parameter(name='quench_current_step_limit', unit = 'A/s', set_cmd=lambda x: self._set_quench_current_step_limit(x), get_cmd=self._get_quench_current_step_limit, get_parser=float, - vals=Numbers(0.01, 10)) - - self.add_parameter('ramping_state', + vals=Numbers(0.01, 10) + ) + + self.add_parameter(name='ramping_state', get_cmd=self._get_ramping_state, - vals=Enum('ramping', 'not ramping')) + vals=Enum('ramping', 'not ramping') + ) - self.add_parameter('operational_error_status', + self.add_parameter(name='operational_error_status', get_cmd=self._get_operational_errors, - get_parser=str) + get_parser=str + ) - self.add_parameter('oer_quench', + self.add_parameter(name='oer_quench', get_cmd=self._get_oer_quench_bit, get_parser=int, val_mapping={'no quench detected': 0, - 'quench detected': 1}) + 'quench detected': 1} + ) + + + # Add solenoid parameters + self.add_parameter(name='coil_constant_unit', + set_cmd=self._set_coil_constant_unit, + get_cmd=self._get_coil_constant_unit, + get_parser=float, + val_mapping={'T/A': 0, + 'kG/A': 1}, + docstring="unit of the coil constant, either T/A (default) or kG/A" + ) + + self.add_parameter(name='coil_constant', + unit = self.coil_constant_unit, + set_cmd=self._update_coil_constant, + get_cmd=self._get_coil_constant, + get_parser=float, + vals=Numbers(0.001, 999.99999) # what are good numbers here? + ) + + self.add_parameter(name='field', + full_name = self.name + '_' + 'field', + unit = 'T', + set_cmd=self.set_field, + get_cmd='RDGF?', + get_parser=float + ) + + self.add_parameter(name='field_ramp_rate', + unit = 'T/min', + set_cmd=self._set_field_ramp_rate, + get_cmd=self._get_field_ramp_rate, + get_parser=float, + docstring="Field ramp rate (T/min)" + ) + # Add clear function self.add_function('clear', call_cmd='*CLS') @@ -159,128 +182,195 @@ def __init__(self, name, coil_constant, field_ramp_rate, address=None, self.coil_constant(coil_constant) self.field_ramp_rate(field_ramp_rate) + # print connect message self.connect_message() - - - def _sleep(self, t): + def _sleep(self, t: float) -> None: """ Sleep for a number of seconds t. If we are or using the PyVISA 'sim' backend, omit this """ - simmode = getattr(self, 'visabackend', False) == 'sim' if simmode: return else: time.sleep(t) - + + # get functions returning several values - def _get_limit(self): + def _get_limit(self) -> Tuple[float, float, float]: """ - Gets the limits of the supply + Limit Output Settings Query + + Returns + ------- + , , """ raw_string = self.ask('LIMIT?') current_limit, voltage_limit, current_rate_limit = raw_string.split(',') return float(current_limit), float(voltage_limit), float(current_rate_limit) - - def _get_persistent_switch_heater_setup(self): + + + def _get_persistent_switch_heater_setup(self) -> Tuple[float, float, float]: """ - Gets the persistant switch heater setup + Persistent Switch Heater Parameter Query + + Returns + ------- + , , """ raw_string = self.ask('PSHS?') status, psh_current, psh_delay = raw_string.split(',') return float(status), float(psh_current), float(psh_delay) - - def _get_quench_detection_setup(self): + + + def _get_quench_detection_setup(self) -> Tuple[float, float]: """ - Gets the quench detections setup, returns 'status' and 'current step limit' + Quench Parameter Query + + Returns + ------- + , """ raw_string = self.ask('QNCH?') status, current_step_limit = raw_string.split(',') return float(status), float(current_step_limit) - def _get_field_setup(self): + + def _get_field_setup(self) -> Tuple[str, float]: """ - Gets the field setup, returns 'coil constant unit' and 'coil constant' + Computed Magnetic Field Parameter Query + + Returns + ------- + , """ raw_string = self.ask('FLDS?') unit, coil_constant = raw_string.split(',') return str(unit), float(coil_constant) - - + + # get functions for parameters - def _get_current_limit(self): + def _get_current_limit(self) -> float: """ - Gets the current limit of the coil + Get maximum allowed output current setting. + + Returns + ------- + """ current_limit, voltage_limit, current_rate_limit = self._get_limit() return current_limit - - def _get_voltage_limit(self): + + + def _get_voltage_limit(self) -> float: """ - Gets the current limit of the coil + Gets maximum allowed compliance voltage setting + + Returns + ------- + """ current_limit, voltage_limit, current_rate_limit = self._get_limit() return voltage_limit - def _get_current_rate_limit(self): + + def _get_current_rate_limit(self) -> float: """ - Gets the current limit of the coil + Gets maximum allowed output current ramp rate setting + + Returns + ------- + """ current_limit, voltage_limit, current_rate_limit = self._get_limit() return current_rate_limit - - def _get_persistent_switch_heater_status(self): + + + def _get_persistent_switch_heater_status(self) -> float: """ - Sets the status of the persistant switch heater + Queries if there is a persistent switch: 0 = Disabled (no PSH), 1 = Enabled + + Returns + ------- + status """ status, psh_current, psh_delay = self._get_persistent_switch_heater_setup() return status - - def _get_quench_detection_status(self): + + + def _get_quench_detection_status(self) -> float: """ - Gets the quench detections status + Queries if quench detection is to be used: 0 = Disabled, 1 = Enabled + + Returns + ------- + status """ status, current_step_limit = self._get_quench_detection_setup() return float(status) - - def _get_quench_current_step_limit(self): + + + def _get_quench_current_step_limit(self) -> float: """ - Gets the quench detections status + Gets current step limit for quench detection + + Returns + ------- + """ status, current_step_limit = self._get_quench_detection_setup() return float(current_step_limit) - - def _get_coil_constant(self): + + + def _get_coil_constant(self) -> float: """ - Gets the coil_constant + Gets magnetic field constant in either T/A or kG/A depending on units + + Returns + ------- + """ coil_constant_unit, coil_constant = self._get_field_setup() return float(coil_constant) - - def _get_coil_constant_unit(self): + + + def _get_coil_constant_unit(self) -> str: """ - Gets the coil_constant + Gets the units of the magnetic field constant: 0 = T/A, 1 = kG/A + + Returns + ------- + """ coil_constant_unit, coil_constant = self._get_field_setup() return str(coil_constant_unit) - - def _get_field_ramp_rate(self): + + + def _get_field_ramp_rate(self) -> float: """ - Gets the field ramp rate + Gets the field ramp rate in units of T/min + + Returns + ------- + field_ramp_rate (T/min) """ coil_constant_unit, coil_constant = self._get_field_setup() # in T/A by default current_ramp_rate = self.current_ramp_rate() # in A/s field_ramp_rate = current_ramp_rate * coil_constant * 60 # in T/min return float(field_ramp_rate) - - def _get_ramping_state(self): + + + def _get_ramping_state(self) -> str: """ Gets the ramping state of the power supply (corresponds to blue LED on panel) Is inferred from the status bit register + + Returns + ------- + ramping state """ operation_condition_register = self.ask('OPST?') bin_OPST = bin(int(operation_condition_register))[2:] @@ -293,10 +383,15 @@ def _get_ramping_state(self): return 'not ramping' else: return 'ramping' - - def _get_operational_errors(self): + + + def _get_operational_errors(self) -> bin: """ - Reads the Error status register to infer the operational errors + Error Status Query + + Returns + ------- + error status """ error_status_register = self.ask('ERST?') # three bytes are read at the same time, the middle one is the operational error status @@ -305,72 +400,85 @@ def _get_operational_errors(self): #prepend zeros to bit-string such that it always has length 9 oer_bit = bin(int(operational_error_registor))[2:].zfill(9) return(oer_bit) - + + def _get_oer_quench_bit(self): """ Returns the oer quench bit + + Returns + ------- + quench bit """ return self._get_operational_errors()[3] - - + + # set functions for parameters - def _set_curent_limit(self, current_limit_setpoint): + def _set_curent_limit(self, current_limit_setpoint: float) -> None: """ - Sets the current limit of the coil + Sets maximum allowed output current """ current_limit, voltage_limit, current_rate_limit = self._get_limit() self.write_raw('LIMIT {}, {}, {}'.format(current_limit_setpoint, voltage_limit, current_rate_limit)) - def _set_voltage_limit(self, voltage_limit_setpoint): + + def _set_voltage_limit(self, voltage_limit_setpoint: float) -> None: """ - Sets the current limit of the coil + Sets maximum allowed compliance voltage """ current_limit, voltage_limit, current_rate_limit = self._get_limit() self.write_raw('LIMIT {}, {}, {}'.format(current_limit, voltage_limit_setpoint, current_rate_limit)) - - def _set_current_rate_limit(self, current_rate_limit_setpoint): + + + def _set_current_rate_limit(self, current_rate_limit_setpoint: float) -> None: """ - Sets the current limit of the coil + Sets maximum allowed output current ramp rate """ current_limit, voltage_limit, current_rate_limit = self._get_limit() self.write_raw('LIMIT {}, {}, {}'.format(current_limit, voltage_limit, current_rate_limit_setpoint)) - - def _set_persistent_switch_heater_status(self, status_setpoint): + + + def _set_persistent_switch_heater_status(self, status_setpoint: float) -> None: """ - Sets the status of the persistant switch heater + Specifies if there is a persistent switch: 0 = Disabled (no PSH), 1 = Enabled """ status, psh_current, psh_delay = self._get_persistent_switch_heater_setup() self.write_raw('PSHS {}, {}, {}'.format(status_setpoint, psh_current, psh_delay)) - - def _set_quench_detection_status(self, status_setpoint): + + + def _set_quench_detection_status(self, status_setpoint: float) -> None: """ - Sets the quench detections status + Specifies if quench detection is to be used: 0 = Disabled, 1 = Enabled """ status, current_step_limit = self._get_quench_detection_setup() self.write_raw('QNCH {}, {}'.format(status_setpoint, current_step_limit)) - - def _set_quench_current_step_limit(self, current_step_limit_setpoint): + + + def _set_quench_current_step_limit(self, current_step_limit_setpoint: float) -> None: """ - Sets the quench detections status + Specifies the current step limit for quench detection """ status, current_step_limit = self._get_quench_detection_setup() self.write_raw('QNCH {}, {}'.format(status, current_step_limit_setpoint)) - - def _set_coil_constant(self, coil_constant_setpoint): + + + def _set_coil_constant(self, coil_constant_setpoint: float) -> None: """ - Sets the coil_constant + Specifies the magnetic field constant in either T/A or kG/A depending on units """ coil_constant_unit, coil_constant = self._get_field_setup() self.write_raw('FLDS {}, {}'.format(coil_constant_unit, coil_constant_setpoint)) - - def _set_coil_constant_unit(self, coil_constant_unit_setpoint): + + + def _set_coil_constant_unit(self, coil_constant_unit_setpoint: str) -> None: """ - Sets the coil_constant + Specifies the units of the magnetic field constant: 0 = T/A, 1 = kG/A """ coil_constant_unit, coil_constant = self._get_field_setup() self.write_raw('FLDS {}, {}'.format(coil_constant_unit_setpoint, coil_constant)) - - def _update_coil_constant(self, coil_constant_setpoint): + + + def _update_coil_constant(self, coil_constant_setpoint: float) -> None: """ Updates the coil_constant and with it all linked parameters """ @@ -382,7 +490,8 @@ def _update_coil_constant(self, coil_constant_setpoint): current_ramp_rate_setpoint = field_ramp_rate / coil_constant_setpoint / 60 # current_ramp_rate is in A/s self.current_ramp_rate(current_ramp_rate_setpoint) - def _set_field_ramp_rate(self, field_ramp_rate_setpoint): + + def _set_field_ramp_rate(self, field_ramp_rate_setpoint: float) -> None: """ Sets the field ramp rate in units of T/min by setting the corresponding current_ramp_rate """ @@ -391,17 +500,13 @@ def _set_field_ramp_rate(self, field_ramp_rate_setpoint): self.current_ramp_rate(current_ramp_rate_setpoint) - - - def set_field(self, value, block=True): + def set_field(self, value: float, block: bool=True) -> None: """ Ramp to a certain field Args: - block (bool): Whether to wait unit the field has finished setting - perform_safety_check (bool): Whether to set the field via a parent - driver (if present), which might perform additional safety - checks. + value: field setpoint + block: Whether to wait until the field has finished setting """ self.write('SETF {}'.format(value)) From c8a05acd50b124d8a06d9de71517f35604db893d Mon Sep 17 00:00:00 2001 From: Simon Zihlmann Date: Mon, 30 Nov 2020 14:23:36 +0100 Subject: [PATCH 03/10] add example notebook for Lakeshore_625.ipynb --- docs/examples/Lakeshore_625.ipynb | 61 ++++++++++++++----------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/docs/examples/Lakeshore_625.ipynb b/docs/examples/Lakeshore_625.ipynb index 7b49bd9a6..bc55d89bc 100644 --- a/docs/examples/Lakeshore_625.ipynb +++ b/docs/examples/Lakeshore_625.ipynb @@ -18,7 +18,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -27,7 +27,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -42,7 +42,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Connected to: LSCI 625 (serial:6251287, firmware:1.3/1.1) in 0.68s\n" + "Connected to: LSCI 625 (serial:6251287, firmware:1.3/1.1) in 0.73s\n" ] } ], @@ -55,7 +55,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -64,7 +64,7 @@ "{'vendor': 'LSCI', 'model': '625', 'serial': '6251287', 'firmware': '1.3/1.1'}" ] }, - "execution_count": 7, + "execution_count": 4, "metadata": {}, "output_type": "execute_result" } @@ -75,7 +75,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -88,11 +88,11 @@ "IDN :\t{'vendor': 'LSCI', 'model': '625', 'serial': '625...\n", "coil_constant :\t0.01666 (magnet_coil_constant_unit)\n", "coil_constant_unit :\tT/A \n", - "current :\t0.0015 (A)\n", + "current :\t0.6019 (A)\n", "current_limit :\t55 (A)\n", "current_ramp_rate :\t0.15 (A/s)\n", "current_rate_limit :\t0.3 (A/s)\n", - "field :\t2.5e-05 (T)\n", + "field :\t0.010028 (T)\n", "field_ramp_rate :\t0.14994 (T/min)\n", "oer_quench :\tno quench detected \n", "operational_error_status :\t000000000 \n", @@ -102,7 +102,7 @@ "ramp_segments :\tdisabled \n", "ramping_state :\tnot ramping \n", "timeout :\t10 (s)\n", - "voltage :\t0.0027 (V)\n", + "voltage :\t0.1063 (V)\n", "voltage_limit :\t1 (V)\n" ] } @@ -121,14 +121,14 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "coil constant = 0.02 T/A\n", + "coil constant = 0.01666 T/A\n", "current limit = 55.0 A\n", "current ramp rate limit = 0.3 A/s\n" ] @@ -148,16 +148,16 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Target field is 0.002 T\n", - "Measured field is 0.00203 T\n", - "Measured current is = 0.1015 A\n" + "Target field is 0.0016660000000000002 T\n", + "Measured field is 0.001685 T\n", + "Measured current is = 0.10114045618247298 A\n" ] } ], @@ -192,16 +192,16 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "0.00202" + "0.001685" ] }, - "execution_count": 41, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -213,17 +213,17 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "# Let's set a field (blocking mode)\n", - "magnet.field(0.01)" + "magnet.field(0.005)" ] }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -240,17 +240,17 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Field ramp rate: 0.09996 T/min.\n", - "Current ramp rate: 0.0833 A/s.\n", - "Field ramp rate: 0.19992 T/min.\n", - "Current ramp rate: 0.1666 A/s.\n" + "Field ramp rate: 0.09996000000000001 T/min.\n", + "Current ramp rate: 0.1 A/s.\n", + "Field ramp rate: 0.19992000000000001 T/min.\n", + "Current ramp rate: 0.2 A/s.\n" ] } ], @@ -274,7 +274,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -297,13 +297,6 @@ "# Let's check if there was a quench detected\n", "print('There was no {}.'.format(magnet.oer_quench()))" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { From 4e02d3982050f98b47aab558ef12afb9bd34da28 Mon Sep 17 00:00:00 2001 From: Simon Zihlmann Date: Wed, 9 Dec 2020 17:51:06 +0100 Subject: [PATCH 04/10] fix typos and fix type of error bit return function --- qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py index e58f6ad93..a03113722 100644 --- a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py +++ b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py @@ -10,7 +10,7 @@ class Lakeshore625(VisaInstrument): """ - Driver for the Lakeshore Model 625 spuerconducting magnet power supply. + Driver for the Lakeshore Model 625 superconducting magnet power supply. This class uses T/A and A/s as units. @@ -385,7 +385,7 @@ def _get_ramping_state(self) -> str: return 'ramping' - def _get_operational_errors(self) -> bin: + def _get_operational_errors(self) -> str: """ Error Status Query @@ -398,8 +398,8 @@ def _get_operational_errors(self) -> bin: operational_error_registor = error_status_register.split(',')[1] #prepend zeros to bit-string such that it always has length 9 - oer_bit = bin(int(operational_error_registor))[2:].zfill(9) - return(oer_bit) + oer_bit_str = bin(int(operational_error_registor))[2:].zfill(9) + return oer_bit_str def _get_oer_quench_bit(self): From 73dd8ed6b8b8abac4a5ad92f8e1aaa6d461acdcf Mon Sep 17 00:00:00 2001 From: Simon Zihlmann Date: Wed, 16 Dec 2020 11:17:20 +0100 Subject: [PATCH 05/10] fix default value of address in init-function and mark example notebook as non-executable --- docs/examples/Lakeshore_625.ipynb | 3 +++ qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/examples/Lakeshore_625.ipynb b/docs/examples/Lakeshore_625.ipynb index bc55d89bc..55fc02149 100644 --- a/docs/examples/Lakeshore_625.ipynb +++ b/docs/examples/Lakeshore_625.ipynb @@ -316,6 +316,9 @@ "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.7" + }, + "nbsphinx": { + "execute": "never" } }, "nbformat": 4, diff --git a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py index a03113722..9c15b74c6 100644 --- a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py +++ b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py @@ -20,7 +20,7 @@ class Lakeshore625(VisaInstrument): current_ramp_limit: A current ramp limit, in units of A/s """ - def __init__(self, name: str, coil_constant: float, field_ramp_rate: float, address: str=None, + def __init__(self, name: str, coil_constant: float, field_ramp_rate: float, address: str, reset: bool=False, terminator:str='', **kwargs) -> None: super().__init__(name, address, terminator=terminator, **kwargs) From 365958f5546053d1aaa9c61bdd95ce79bb53bc6c Mon Sep 17 00:00:00 2001 From: Simon Zihlmann Date: Mon, 4 Jan 2021 10:08:53 +0100 Subject: [PATCH 06/10] minor improvements --- .../drivers/Lakeshore/Model_625.py | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py index 9c15b74c6..6917f511f 100644 --- a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py +++ b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py @@ -33,7 +33,7 @@ def __init__(self, name: str, coil_constant: float, field_ramp_rate: float, add # Add power supply parameters self.add_parameter(name='current_limit', unit="A", - set_cmd=lambda x: self._set_curent_limit(x), + set_cmd=self._set_curent_limit, get_cmd=self._get_current_limit, get_parser=float, vals=Numbers(0, 60.1), @@ -42,7 +42,7 @@ def __init__(self, name: str, coil_constant: float, field_ramp_rate: float, add self.add_parameter(name='voltage_limit', unit="V", - set_cmd=lambda x: self._set_voltage_limit(x), + set_cmd=self._set_voltage_limit, get_cmd=self._get_voltage_limit, get_parser=float, vals=Numbers(0, 5), @@ -51,7 +51,7 @@ def __init__(self, name: str, coil_constant: float, field_ramp_rate: float, add self.add_parameter(name='current_rate_limit', unit="A/s", - set_cmd=lambda x: self._set_current_rate_limit(x), + set_cmd=self._set_current_rate_limit, get_cmd=self._get_current_rate_limit, get_parser=float, vals=Numbers( 0.0001, 99.999), @@ -84,30 +84,30 @@ def __init__(self, name: str, coil_constant: float, field_ramp_rate: float, add self.add_parameter(name='ramp_segments', set_cmd="RSEG {}", get_cmd='RSEG?', - get_parser=float, + get_parser=int, val_mapping={'disabled': 0, 'enabled': 1} ) self.add_parameter(name='persistent_switch_heater', - set_cmd=lambda x: self._set_persistent_switch_heater_status(x), + set_cmd=self._set_persistent_switch_heater_status, get_cmd=self._get_persistent_switch_heater_status, - get_parser=float, + get_parser=int, val_mapping={'disabled': 0, 'enabled': 1} ) self.add_parameter(name='quench_detection', - set_cmd=lambda x: self._set_quench_detection_status(x), + set_cmd=self._set_quench_detection_status, get_cmd=self._get_quench_detection_status, - get_parser=float, + get_parser=int, val_mapping={'disabled': 0, 'enabled': 1} ) self.add_parameter(name='quench_current_step_limit', unit = 'A/s', - set_cmd=lambda x: self._set_quench_current_step_limit(x), + set_cmd=self._set_quench_current_step_limit, get_cmd=self._get_quench_current_step_limit, get_parser=float, vals=Numbers(0.01, 10) @@ -135,7 +135,7 @@ def __init__(self, name: str, coil_constant: float, field_ramp_rate: float, add self.add_parameter(name='coil_constant_unit', set_cmd=self._set_coil_constant_unit, get_cmd=self._get_coil_constant_unit, - get_parser=float, + get_parser=int, val_mapping={'T/A': 0, 'kG/A': 1}, docstring="unit of the coil constant, either T/A (default) or kG/A" @@ -150,7 +150,6 @@ def __init__(self, name: str, coil_constant: float, field_ramp_rate: float, add ) self.add_parameter(name='field', - full_name = self.name + '_' + 'field', unit = 'T', set_cmd=self.set_field, get_cmd='RDGF?', @@ -213,7 +212,7 @@ def _get_limit(self) -> Tuple[float, float, float]: return float(current_limit), float(voltage_limit), float(current_rate_limit) - def _get_persistent_switch_heater_setup(self) -> Tuple[float, float, float]: + def _get_persistent_switch_heater_setup(self) -> Tuple[int, float, float]: """ Persistent Switch Heater Parameter Query @@ -223,10 +222,10 @@ def _get_persistent_switch_heater_setup(self) -> Tuple[float, float, float]: """ raw_string = self.ask('PSHS?') status, psh_current, psh_delay = raw_string.split(',') - return float(status), float(psh_current), float(psh_delay) + return int(status), float(psh_current), float(psh_delay) - def _get_quench_detection_setup(self) -> Tuple[float, float]: + def _get_quench_detection_setup(self) -> Tuple[int, float]: """ Quench Parameter Query @@ -236,7 +235,7 @@ def _get_quench_detection_setup(self) -> Tuple[float, float]: """ raw_string = self.ask('QNCH?') status, current_step_limit = raw_string.split(',') - return float(status), float(current_step_limit) + return int(status), float(current_step_limit) def _get_field_setup(self) -> Tuple[str, float]: @@ -289,7 +288,7 @@ def _get_current_rate_limit(self) -> float: return current_rate_limit - def _get_persistent_switch_heater_status(self) -> float: + def _get_persistent_switch_heater_status(self) -> int: """ Queries if there is a persistent switch: 0 = Disabled (no PSH), 1 = Enabled @@ -298,10 +297,10 @@ def _get_persistent_switch_heater_status(self) -> float: status """ status, psh_current, psh_delay = self._get_persistent_switch_heater_setup() - return status + return int(status) - def _get_quench_detection_status(self) -> float: + def _get_quench_detection_status(self) -> int: """ Queries if quench detection is to be used: 0 = Disabled, 1 = Enabled @@ -310,7 +309,7 @@ def _get_quench_detection_status(self) -> float: status """ status, current_step_limit = self._get_quench_detection_setup() - return float(status) + return int(status) def _get_quench_current_step_limit(self) -> float: @@ -402,7 +401,7 @@ def _get_operational_errors(self) -> str: return oer_bit_str - def _get_oer_quench_bit(self): + def _get_oer_quench_bit(self) -> int: """ Returns the oer quench bit @@ -438,7 +437,7 @@ def _set_current_rate_limit(self, current_rate_limit_setpoint: float) -> None: self.write_raw('LIMIT {}, {}, {}'.format(current_limit, voltage_limit, current_rate_limit_setpoint)) - def _set_persistent_switch_heater_status(self, status_setpoint: float) -> None: + def _set_persistent_switch_heater_status(self, status_setpoint: int) -> None: """ Specifies if there is a persistent switch: 0 = Disabled (no PSH), 1 = Enabled """ @@ -446,7 +445,7 @@ def _set_persistent_switch_heater_status(self, status_setpoint: float) -> None: self.write_raw('PSHS {}, {}, {}'.format(status_setpoint, psh_current, psh_delay)) - def _set_quench_detection_status(self, status_setpoint: float) -> None: + def _set_quench_detection_status(self, status_setpoint: int) -> None: """ Specifies if quench detection is to be used: 0 = Disabled, 1 = Enabled """ From 57d24365da0cfc23a79e362c67d2575f090061ba Mon Sep 17 00:00:00 2001 From: Simon Zihlmann Date: Tue, 5 Jan 2021 09:05:05 +0100 Subject: [PATCH 07/10] removing type definitions in return statements of get functions --- .../drivers/Lakeshore/Model_625.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py index 6917f511f..790966565 100644 --- a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py +++ b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py @@ -297,7 +297,7 @@ def _get_persistent_switch_heater_status(self) -> int: status """ status, psh_current, psh_delay = self._get_persistent_switch_heater_setup() - return int(status) + return status def _get_quench_detection_status(self) -> int: @@ -309,7 +309,7 @@ def _get_quench_detection_status(self) -> int: status """ status, current_step_limit = self._get_quench_detection_setup() - return int(status) + return status def _get_quench_current_step_limit(self) -> float: @@ -321,7 +321,7 @@ def _get_quench_current_step_limit(self) -> float: """ status, current_step_limit = self._get_quench_detection_setup() - return float(current_step_limit) + return current_step_limit def _get_coil_constant(self) -> float: @@ -333,7 +333,7 @@ def _get_coil_constant(self) -> float: """ coil_constant_unit, coil_constant = self._get_field_setup() - return float(coil_constant) + return coil_constant def _get_coil_constant_unit(self) -> str: @@ -345,7 +345,7 @@ def _get_coil_constant_unit(self) -> str: """ coil_constant_unit, coil_constant = self._get_field_setup() - return str(coil_constant_unit) + return coil_constant_unit def _get_field_ramp_rate(self) -> float: @@ -359,7 +359,7 @@ def _get_field_ramp_rate(self) -> float: coil_constant_unit, coil_constant = self._get_field_setup() # in T/A by default current_ramp_rate = self.current_ramp_rate() # in A/s field_ramp_rate = current_ramp_rate * coil_constant * 60 # in T/min - return float(field_ramp_rate) + return field_ramp_rate def _get_ramping_state(self) -> str: From 8d2433fe4851d4f412465e488d17d1fca40821ac Mon Sep 17 00:00:00 2001 From: Simon Zihlmann Date: Tue, 12 Jan 2021 08:53:54 +0100 Subject: [PATCH 08/10] update example notebook --- docs/examples/Lakeshore_625.ipynb | 71 ++++++++++++++++++++++++------- 1 file changed, 56 insertions(+), 15 deletions(-) diff --git a/docs/examples/Lakeshore_625.ipynb b/docs/examples/Lakeshore_625.ipynb index 55fc02149..4924e1eaa 100644 --- a/docs/examples/Lakeshore_625.ipynb +++ b/docs/examples/Lakeshore_625.ipynb @@ -30,19 +30,11 @@ "execution_count": 3, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "c:\\users\\g-gre-gre054789\\qcodes\\qcodes\\instrument\\parameter.py:258: UserWarning: _BaseParameter got unexpected kwargs: {'full_name': 'magnet_field'}. These are unused and will be discarded. This will be an error in the future.\n", - " warnings.warn(f\"_BaseParameter got unexpected kwargs: {kwargs}.\"\n" - ] - }, { "name": "stdout", "output_type": "stream", "text": [ - "Connected to: LSCI 625 (serial:6251287, firmware:1.3/1.1) in 0.73s\n" + "Connected to: LSCI 625 (serial:6251287, firmware:1.3/1.1) in 0.77s\n" ] } ], @@ -88,11 +80,11 @@ "IDN :\t{'vendor': 'LSCI', 'model': '625', 'serial': '625...\n", "coil_constant :\t0.01666 (magnet_coil_constant_unit)\n", "coil_constant_unit :\tT/A \n", - "current :\t0.6019 (A)\n", + "current :\t0.0014 (A)\n", "current_limit :\t55 (A)\n", "current_ramp_rate :\t0.15 (A/s)\n", "current_rate_limit :\t0.3 (A/s)\n", - "field :\t0.010028 (T)\n", + "field :\t2.4e-05 (T)\n", "field_ramp_rate :\t0.14994 (T/min)\n", "oer_quench :\tno quench detected \n", "operational_error_status :\t000000000 \n", @@ -102,7 +94,7 @@ "ramp_segments :\tdisabled \n", "ramping_state :\tnot ramping \n", "timeout :\t10 (s)\n", - "voltage :\t0.1063 (V)\n", + "voltage :\t0.0048 (V)\n", "voltage_limit :\t1 (V)\n" ] } @@ -156,8 +148,8 @@ "output_type": "stream", "text": [ "Target field is 0.0016660000000000002 T\n", - "Measured field is 0.001685 T\n", - "Measured current is = 0.10114045618247298 A\n" + "Measured field is 0.001678 T\n", + "Measured current is = 0.1007202881152461 A\n" ] } ], @@ -198,7 +190,7 @@ { "data": { "text/plain": [ - "0.001685" + "0.001678" ] }, "execution_count": 8, @@ -297,6 +289,13 @@ "# Let's check if there was a quench detected\n", "print('There was no {}.'.format(magnet.oer_quench()))" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -319,6 +318,48 @@ }, "nbsphinx": { "execute": "never" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false } }, "nbformat": 4, From 6c9823def9fa54d20ad80ef4e75293e331c917c2 Mon Sep 17 00:00:00 2001 From: Simon Zihlmann Date: Tue, 12 Jan 2021 09:48:26 +0100 Subject: [PATCH 09/10] fix type of return statement of quench detection function --- qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py index 790966565..a6204cc2b 100644 --- a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py +++ b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py @@ -409,7 +409,7 @@ def _get_oer_quench_bit(self) -> int: ------- quench bit """ - return self._get_operational_errors()[3] + return int(self._get_operational_errors()[3]) # set functions for parameters From 0e3a5ecbddc8c5636f891ead2ba7b5627d91d2a0 Mon Sep 17 00:00:00 2001 From: Simon Zihlmann Date: Tue, 12 Jan 2021 10:27:51 +0100 Subject: [PATCH 10/10] remove logging statement and clarify init docstring --- qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py index a6204cc2b..bcd0436d3 100644 --- a/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py +++ b/qcodes_contrib_drivers/drivers/Lakeshore/Model_625.py @@ -6,7 +6,6 @@ from qcodes import VisaInstrument from qcodes.utils.validators import Numbers, Enum -log = logging.getLogger(__name__) class Lakeshore625(VisaInstrument): """ @@ -16,8 +15,9 @@ class Lakeshore625(VisaInstrument): Args: name (str): a name for the instrument + coil_constant (float): Coil contant of magnet, in untis of T/A + field_ramp_rate (float): Magnetic field ramp rate, in units of T/min address (str): VISA address of the device - current_ramp_limit: A current ramp limit, in units of A/s """ def __init__(self, name: str, coil_constant: float, field_ramp_rate: float, address: str,