From b22a0fe35ad86a7e20af78986e1b59ee29db16e9 Mon Sep 17 00:00:00 2001 From: WilliamHPNielsen Date: Thu, 2 Mar 2017 14:01:28 +0100 Subject: [PATCH 1/9] feat: Add a Keysight_34465A driver Add a first file for a driver for the Keysight 34465A DMM and a benchmarking notebook --- ...gilent 34411A versus Keysight 34465A.ipynb | 442 ++++++++++++++++++ .../Keysight/Keysight_34465A.py | 209 +++++++++ 2 files changed, 651 insertions(+) create mode 100644 docs/examples/Agilent 34411A versus Keysight 34465A.ipynb create mode 100644 qcodes/instrument_drivers/Keysight/Keysight_34465A.py diff --git a/docs/examples/Agilent 34411A versus Keysight 34465A.ipynb b/docs/examples/Agilent 34411A versus Keysight 34465A.ipynb new file mode 100644 index 00000000000..0699f323e3d --- /dev/null +++ b/docs/examples/Agilent 34411A versus Keysight 34465A.ipynb @@ -0,0 +1,442 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "# Agilent 34411A versus Keysight 34465A\n", + "\n", + "The following notebook perfoms a benchmarking of the two DMMs. In part one, raw readings of immediate voltages are timed\n", + "and compared. In part two, actual sweeps are performed with a QDac." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "%matplotlib notebook\n", + "import time\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "import qcodes as qc\n", + "from qcodes.instrument_drivers.Keysight.Keysight_34465A import Keysight_34465A\n", + "from qcodes.instrument_drivers.agilent.Agilent_34400A import Agilent_34400A\n", + "from qcodes.instrument_drivers.QDev.QDac import QDac" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "## Import and setup" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connected to: Keysight Technologies 34465A (serial:MY54505388, firmware:A.02.14-02.40-02.14-00.49-02-01) in 6.93s\n", + "Connected to: Agilent Technologies 34411A (serial:MY48002016, firmware:2.35-2.35-0.09-46-09) in 0.06s\n" + ] + } + ], + "source": [ + "ks = Keysight_34465A('Keysight', 'TCPIP0::K-000000-00000::inst0::INSTR')\n", + "agi = Agilent_34400A('Agilent', 'TCPIP0::192.168.15.105::inst0::INSTR')\n", + "qdac = QDac('qdac', 'ASRL4::INSTR')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "station = qc.Station(ks, agi, qdac)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "# set up a NPLC of 0.06 corresponding to an aperture time of 1 ms\n", + "ks.NPLC(0.06)\n", + "agi.NPLC(0.06)\n", + "\n", + "# set the same range on both DMMs\n", + "ks.range(1)\n", + "agi.range(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "## Part one - raw readings" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reading with displays ON\n", + "----------\n", + "Read 512 values one at a time from Keysight in: 8.587134838104248 s\n", + "Read 512 values one at a time from Agilent in: 4.099916696548462 s\n", + "----------\n", + "Read 1024 values one at a time from Keysight in: 16.83395004272461 s\n", + "Read 1024 values one at a time from Agilent in: 8.229825019836426 s\n", + "----------\n", + "Read 2048 values one at a time from Keysight in: 33.76206350326538 s\n", + "Read 2048 values one at a time from Agilent in: 16.453675985336304 s\n", + "----------\n" + ] + } + ], + "source": [ + "# Preliminary testing, just get N readings from each instrument\n", + "# with the displays on\n", + "\n", + "ks.display_clear() # make sure that the display is on\n", + "agi.display_clear()\n", + "\n", + "print('Reading with displays ON')\n", + "print('-'*10)\n", + "\n", + "for N in [512, 1024, 2048]:\n", + "\n", + " t_start = time.time()\n", + " for ii in range(N):\n", + " ks.volt()\n", + " t_stop = time.time()\n", + " print('Read {} values one at a time from Keysight in: {} s'.format(N, t_stop-t_start))\n", + "\n", + " t_start = time.time()\n", + " for ii in range(N):\n", + " agi.volt()\n", + " t_stop = time.time()\n", + " print('Read {} values one at a time from Agilent in: {} s'.format(N, t_stop-t_start))\n", + "\n", + " print('-'*10)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reading with displays OFF\n", + "----------\n", + "Read 512 values one at a time from Keysight in: 4.5132529735565186 s\n", + "Read 512 values one at a time from Agilent in: 4.098856449127197 s\n", + "----------\n", + "Read 1024 values one at a time from Keysight in: 8.996399164199829 s\n", + "Read 1024 values one at a time from Agilent in: 8.227899074554443 s\n", + "----------\n", + "Read 2048 values one at a time from Keysight in: 17.969755172729492 s\n", + "Read 2048 values one at a time from Agilent in: 16.399696350097656 s\n", + "----------\n" + ] + } + ], + "source": [ + "# The same test, but with the displays off to decrease latency\n", + "\n", + "print('Reading with displays OFF')\n", + "print('-'*10)\n", + "\n", + "for N in [512, 1024, 2048]:\n", + "\n", + " ks.display_text('QCoDeS')\n", + " t_start = time.time()\n", + " for ii in range(N):\n", + " ks.volt()\n", + " t_stop = time.time()\n", + " print('Read {} values one at a time from Keysight in: {} s'.format(N, t_stop-t_start))\n", + " ks.display_clear()\n", + "\n", + " agi.display_text('QCoDes')\n", + " t_start = time.time()\n", + " for ii in range(N):\n", + " agi.volt()\n", + " t_stop = time.time()\n", + " print('Read {} values one at a time from Agilent in: {} s'.format(N, t_stop-t_start))\n", + " agi.display_clear()\n", + "\n", + " print('-'*10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "source": [ + "## Part two - QCoDeS looping" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "### 1D Sweep" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-07/#018_testsweep_12-32-13'\n", + " | | | \n", + " Setpoint | qdac_ch42_v_set | ch42_v | (512,)\n", + " Measured | Keysight_volt | volt | (512,)\n", + "started at 2017-03-07 12:32:29\n", + "\n", + "\n", + "Did a 512-point QCoDeS sweep of the QDac/Keysight pair in 16.5 s\n", + "\n", + "\n", + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-07/#019_testsweep_12-32-29'\n", + " | | | \n", + " Setpoint | qdac_ch41_v_set | ch41_v | (512,)\n", + " Measured | Agilent_volt | volt | (512,)\n", + "started at 2017-03-07 12:32:46\n", + "\n", + "\n", + "Did a 512-point QCoDeS sweep of the QDac/Agilent pair in 16.5 s\n", + "\n", + "\n" + ] + } + ], + "source": [ + "# Sweep a voltage from 0.2 V to 0.5 V in 512 steps\n", + "# Switch off displays for speed\n", + "\n", + "ks.display_text('QCoDeS')\n", + "agi.display_text('QCoDeS')\n", + "\n", + "N = 512 \n", + "V1 = 0.2\n", + "V2 = 0.5\n", + "dV = (V2-V1)/(N-1) # endpoint included in sweep\n", + "\n", + "loop = qc.Loop(qdac.ch42_v.sweep(V1, V2, dV)).each(ks.volt)\n", + "data = loop.get_data_set(name='testsweep')\n", + "t_start = time.time()\n", + "_ = loop.run()\n", + "t_stop = time.time()\n", + "print('\\n\\nDid a {}-point QCoDeS sweep of the QDac/Keysight pair in {:.1f} s\\n\\n'.format(N, t_stop-t_start))\n", + "\n", + "loop = qc.Loop(qdac.ch41_v.sweep(V1, V2, dV)).each(agi.volt)\n", + "data = loop.get_data_set(name='testsweep')\n", + "t_start = time.time()\n", + "_ = loop.run()\n", + "t_stop = time.time()\n", + "print('\\n\\nDid a {}-point QCoDeS sweep of the QDac/Agilent pair in {:.1f} s\\n\\n'.format(N, t_stop-t_start))\n", + "\n", + "agi.display_clear()\n", + "ks.display_clear()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "### 2D Sweep" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-07/#020_testsweep_12-33-46'\n", + " | | | \n", + " Setpoint | qdac_ch42_v_set | ch42_v | (100,)\n", + " Setpoint | qdac_ch41_v_set | ch41_v | (100, 100)\n", + " Measured | Keysight_volt | volt | (100, 100)\n", + "started at 2017-03-07 12:39:09\n", + "\n", + "\n", + "Did a 100x100-point QCoDeS sweep of the QDac/Keysight pair in 323.9 s\n", + "\n", + "\n", + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-07/#021_testsweep_12-39-09'\n", + " | | | \n", + " Setpoint | qdac_ch41_v_set | ch41_v | (100,)\n", + " Setpoint | qdac_ch42_v_set | ch42_v | (100, 100)\n", + " Measured | Agilent_volt | volt | (100, 100)\n", + "started at 2017-03-07 12:44:33\n", + "\n", + "\n", + "Did a 100x100-point QCoDeS sweep of the QDac/Agilent pair in 323.8 s\n", + "\n", + "\n" + ] + } + ], + "source": [ + "# Perform the same sweep as before, but this time nested inside another sweep of the same length,\n", + "# i.e. at each point of the original sweep, another QDac channel sweeps its voltage in the same number of steps\n", + "\n", + "ks.display_text('QCoDeS')\n", + "agi.display_text('QCoDeS')\n", + "\n", + "N = 100\n", + "V1 = 0.2\n", + "V2 = 0.5\n", + "dV = (V2-V1)/(N-1)\n", + "\n", + "loop = qc.Loop(qdac.ch42_v.sweep(V1, V2, dV)).loop(qdac.ch41_v.sweep(V1, V2, dV)).each(ks.volt)\n", + "data = loop.get_data_set(name='testsweep')\n", + "t_start = time.time()\n", + "_ = loop.run()\n", + "t_stop = time.time()\n", + "print('\\n\\nDid a {}x{}-point QCoDeS sweep of the QDac/Keysight pair in {:.1f} s\\n\\n'.format(N, N, t_stop-t_start))\n", + "\n", + "loop = qc.Loop(qdac.ch41_v.sweep(V1, V2, dV)).loop(qdac.ch42_v.sweep(V1, V2, dV)).each(agi.volt)\n", + "data = loop.get_data_set(name='testsweep')\n", + "t_start = time.time()\n", + "_ = loop.run()\n", + "t_stop = time.time()\n", + "print('\\n\\nDid a {}x{}-point QCoDeS sweep of the QDac/Agilent pair in {:.1f} s\\n\\n'.format(N, N, t_stop-t_start))\n", + "\n", + "ks.display_clear()\n", + "agi.display_clear()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "ks.close()\n", + "agi.close()\n", + "qdac.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "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.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py new file mode 100644 index 00000000000..17cf5526de0 --- /dev/null +++ b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py @@ -0,0 +1,209 @@ +# QCoDeS driver for the Keysight 34465A Digital Multimeter + +import qcodes.utils.validators as vals +from qcodes import VisaInstrument + + +class Keysight_34465A(VisaInstrument): + """ + Instrument class for Keysight 34465A. + + The driver is written such that usage which models + 34460A, 34461A, and 34470A should be seamless. + + Tested with: 34465A. + + The driver currently only supports using the instrument as a voltmeter. + + Attributes: + model (str): The model number of the instrument + NPLC_list (list): A list of the available Power Line Cycle settings + ranges (list): A list of the available voltage ranges + """ + + def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, + **kwargs): + """ + Create an instance of the instrument. + + Args: + name (str): Name used by QCoDeS. Appears in the DataSet + address (str): Visa-resolvable instrument address. + utility_freq (int): The local utility frequency in Hz. Default: 50 + DIG (bool): Is the DIG option installed on the instrument? + Default: False. + silent (bool): If True, the connect_message of the instrument + is supressed. Default: False + Returns: + Keysight_34465A + """ + if utility_freq not in [50, 60]: + raise ValueError('Can not set utility frequency to ' + '{}. '.format(utility_freq) + + 'Please enter either 50 Hz or 60 Hz.') + + super().__init__(name, address, terminator='\n', **kwargs) + + idn = self.IDN.get() + self.model = idn['model'] + + #################################### + # Instrument specifications + + PLCs = {'34460A': [0.02, 0.2, 1, 10, 100], + '34461A': [0.02, 0.2, 1, 10, 100], + '34465A': [0.02, 0.06, 0.2, 1, 10, 100], + '34470A': [0.02, 0.06, 0.2, 1, 10, 100] + } + if DIG: + PLCs['34465A'] = [0.001, 0.002, 0.006] + PLCs['34465A'] + PLCs['34470A'] = [0.001, 0.002, 0.006] + PLCs['34470A'] + + ranges = {'34460A': [10**n for n in range(-3, 9)], # 1 m to 100 M + '34461A': [10**n for n in range(-3, 9)], # 1 m to 100 M + '34465A': [10**n for n in range(-3, 10)], # 1 m to 1 G + '34470A': [10**n for n in range(-3, 10)], # 1 m to 1 G + } + + # The resolution factor order matches the order of PLCs + res_factors = {'34460A': [300e-6, 100e-6, 30e-6, 10e-6, 3e-6], + '34461A': [100e-6, 10e-6, 3e-6, 1e-6, 0.3e-6], + '34465A': [3e-6, 1.5e-6, 0.7e-6, 0.3e-6, 0.1e-6, + 0.03e-6], + '34470A': [1e-6, 0.5e-6, 0.3e-6, 0.1e-6, 0.03e-6, + 0.01e-6] + } + if DIG: + res_factors['34465A'] = [30e6, 15e-6, 6e-6] + res_factors['34464A'] + res_factors['34470A'] = [30e-6, 10e-6, 3e-6] + res_factors['34470A'] + + # Define the extreme aperture time values for the 34465A and 34470A + if utility_freq == 50: + apt_times = {'34465A': [0.3e-3, 2], + '34470A': [0.3e-3, 2]} + if utility_freq == 60: + apt_times = {'34465A': [0.3e-3, 1.67], + '34470A': [0.3e-3, 1.67]} + if DIG: + apt_times['34465A'][0] = 20e-6 + apt_times['34470A'][0] = 20e-6 + + self._resolution_factors = res_factors[self.model] + self.ranges = ranges[self.model] + self.NPLC_list = PLCs[self.model] + self._apt_times = apt_times[self.model] + + #################################### + # PARAMETERS + + self.add_parameter('NPLC', + get_cmd='SENSe:VOLTage:DC:NPLC?', + get_parser=float, + set_cmd=self._set_NPLC, + vals=vals.Enum(*self.NPLC_list), + label='Integration time', + unit='NPLC') + + self.add_parameter('volt', + get_cmd='READ?', + label='Voltage', + get_parser=float, + unit='V') + + self.add_parameter('range', + get_cmd='SENSe:VOLTage:DC:RANGe?', + get_parser=float, + set_cmd='SENSe:VOLTage:DC:RANGe {:f}', + vals=vals.Enum(*self.ranges)) + + self.add_parameter('resolution', + get_cmd='SENSe:VOLTage:DC:RESolution?', + get_parser=float, + set_cmd=self._set_resolution, + label='Resolution', + unit='V') + + self.add_parameter('autorange', + label='Autorange', + set_cmd='SENSe:VOLtage:DC:RANGe:AUTO {}', + get_cmd='SENSe:VOLtage:DC:RANGe:AUTO?', + val_mapping={'ON': 1, 'OFF': 0}, + vals=vals.Enum('ON', 'OFF')) + + self.add_parameter('display_text', + label='Display text', + set_cmd='DISPLAY:TEXT "{}"', + get_cmd='DISPLAY:TEXT?', + vals=vals.Strings()) + + #################################### + # Model-specific parameters + + if self.model in ['34465A', '34470A']: + + self.add_parameter('aperture_mode', + label='Aperture mode', + set_cmd='SENSe:VOLTage:DC:APERture:ENABled {}', + get_cmd='SENSe:VOLTage:DC:APERture:ENABled?', + val_mapping={'ON': 1, 'OFF': 0}, + vals=vals.Enum('ON', 'OFF')) + + self.add_parameter('aperture_time', + label='Aperture time', + set_cmd=self._set_apt_time, + get_cmd='SENSe:VOLTage:DC:APERture?', + get_parser=float, + vals=vals.Numbers(*self._apt_times), + docstring=('Setting the aperture time ' + 'automatically enables the aperture' + ' mode.')) + + self.add_function('init_measurement', call_cmd='INIT') + self.add_function('reset', call_cmd='*RST') + self.add_function('display_clear', call_cmd=('DISPLay:TEXT:CLEar')) + + if not silent: + self.connect_message() + + def _set_apt_time(self, value): + self.write('SENSe:VOLTage:DC:APERture {:f}'.format(value)) + + # setting aperture time switches aperture mode ON + self.aperture_mode.get() + + def _set_NPLC(self, value): + self.write('SENSe:VOLTage:DC:NPLC {:f}'.format(value)) + + # resolution settings change with NPLC + self.resolution.get() + + # setting NPLC switches off aperture mode + if self.model in ['34465A', '34470A']: + self.aperture_mode.get() + + def _set_range(self, value): + self.write('SENSe:VOLTage:DC:RANGe {:f}'.format(value)) + + # resolution settings change with range + + self.resolution.get() + + def _set_resolution(self, value): + rang = self.range.get() + + # convert both value*range and the resolution factors + # to strings with few digits, so we avoid floating point + # rounding errors. + res_fac_strs = ['{:.1e}'.format(v * rang) + for v in self._resolution_factors] + if '{:.1e}'.format(value) not in res_fac_strs: + raise ValueError( + 'Resolution setting {:.1e} ({} at range {}) ' + 'does not exist. ' + 'Possible values are {}'.format(value, value, rang, + res_fac_strs)) + + self.write('VOLT:DC:RES {:.1e}'.format(value)) + + # NPLC settings change with resolution + self.NPLC.get() \ No newline at end of file From 97b7fa412d5303572efa92862dcfdcf69d312f51 Mon Sep 17 00:00:00 2001 From: William Nielsen Date: Fri, 31 Mar 2017 14:52:52 +0200 Subject: [PATCH 2/9] Add trigger parameters to driver Add four trigger parameters to the driver. --- .../Keysight/Keysight_34465A.py | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py index 17cf5526de0..5ee82ae993e 100644 --- a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py +++ b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py @@ -8,7 +8,7 @@ class Keysight_34465A(VisaInstrument): """ Instrument class for Keysight 34465A. - The driver is written such that usage which models + The driver is written such that usage with models 34460A, 34461A, and 34470A should be seamless. Tested with: 34465A. @@ -136,6 +136,37 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, get_cmd='DISPLAY:TEXT?', vals=vals.Strings()) + # TRIGGERING + + self.add_parameter('trigger_count', + label='Trigger Count', + set_cmd='TRIGger:COUNt {}', + get_cmd='TRIGger:COUNt?', + get_parser=float, + vals=vals.MultiType(vals.Numbers(1, 1e6), + vals.Enum('MIN', 'MAX', 'DEF', + 'INF'))) + + self.add_parameter('trigger_delay', + label='Trigger Delay', + set_cmd='TRIGger:DELay {}', + get_cmd='TRIGger:DELay?', + vals=vals.MultiType(vals.Numbers(0, 3600), + vals.Enum('MIN', 'MAX', 'DEF')), + get_parser=float) + + self.add_parameter('trigger_slope', + label='Trigger Slope', + set_cmd='TRIGger:SLOPe {}', + get_cmd='TRIGger:SLOPe?', + vals=vals.Enum('POS', 'NEG')) + + self.add_parameter('trigger_source', + label='Trigger Source', + set_cmd='TRIGger:SOURce {}', + get_cmd='TRIGger:SOURce?', + vals=vals.Enum('IMM', 'EXT', 'BUS', 'INT')) + #################################### # Model-specific parameters @@ -206,4 +237,4 @@ def _set_resolution(self, value): self.write('VOLT:DC:RES {:.1e}'.format(value)) # NPLC settings change with resolution - self.NPLC.get() \ No newline at end of file + self.NPLC.get() From 35daa468870d51d496ec81627ddf02c0ab02ec1c Mon Sep 17 00:00:00 2001 From: William Nielsen Date: Fri, 31 Mar 2017 14:59:23 +0200 Subject: [PATCH 3/9] refactor: Remove 'READ?' as volt get_cmd Make a more general get_cmd for the volt parameter. Using simply 'READ?' is wrong in many cases. --- .../instrument_drivers/Keysight/Keysight_34465A.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py index 5ee82ae993e..9dd48c29852 100644 --- a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py +++ b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py @@ -105,9 +105,8 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, unit='NPLC') self.add_parameter('volt', - get_cmd='READ?', + get_cmd=_get_voltage, label='Voltage', - get_parser=float, unit='V') self.add_parameter('range', @@ -196,6 +195,15 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, if not silent: self.connect_message() + def _get_voltage(self): + # TODO: massive improvements! What if more than one number was + # asked for? + # What if mode is not voltage sensing? What if... + + response = self.ask('READ?') + + return float(response) + def _set_apt_time(self, value): self.write('SENSe:VOLTage:DC:APERture {:f}'.format(value)) From 19f6ed5615c656814ea7b384c3b15d6f5e37f85b Mon Sep 17 00:00:00 2001 From: William Nielsen Date: Fri, 31 Mar 2017 15:20:55 +0200 Subject: [PATCH 4/9] feat: Add sampling parameters Add four parameters for sampling. --- .../Keysight/Keysight_34465A.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py index 9dd48c29852..1e0723b8e5d 100644 --- a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py +++ b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py @@ -166,6 +166,47 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, get_cmd='TRIGger:SOURce?', vals=vals.Enum('IMM', 'EXT', 'BUS', 'INT')) + # SAMPLING + + self.add_parameter('sample_count', + label='Sample Count', + set_cmd='SAMPle:COUNt {}', + get_cmd='SAMPle:COUNt?', + vals=vals.MultiType(vals.Numbers(1, 1e6), + vals.Enum('MIN', 'MAX', 'DEF')), + get_parser=int) + + self.add_parameter('sample_count_pretrigger', + label='Sample Pretrigger Count', + set_cmd='SAMPle:COUNt:PRETrigger {}', + get_cmd='SAMPle:COUNt:PRETrigger?', + vals=vals.MultiType(vals.Numbers(0, 2e6-1), + vals.Enum('MIN', 'MAX', 'DEF')), + get_parser=int, + docstring=('Allows collection of the data ' + 'being digitized the trigger. Reserves ' + 'memory for pretrigger samples up to the' + ' specified num. of pretrigger samples.' + )) + + self.add_parameter('sample_source', + label='Sample Timing Source', + set_cmd='SAMPle:SOURce {}', + get_cmd='SAMPle:SOURce?', + vals=vals.Enum('IMM', 'TIM'), + docstring=('Determines sampling time, immediate' + ' or using sample_timer')) + + self.add_parameter('sample_timer', + label='Sample Timer', + set_cmd='SAMPle:TIMer {}', + get_cmd='SAMPle:TIMer?', + unit='s', + vals=vals.MultiType(vals.Numbers(0, 3600), + vals.Enum('MIN', 'MAX', 'DEF')), + get_parser=float) + + #################################### # Model-specific parameters From 363f64ab33ab0eeef357fa0bd94a5e29c3af7912 Mon Sep 17 00:00:00 2001 From: William Nielsen Date: Fri, 31 Mar 2017 15:25:50 +0200 Subject: [PATCH 5/9] fix: Fix wrong volt parameter get_cmd --- qcodes/instrument_drivers/Keysight/Keysight_34465A.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py index 1e0723b8e5d..e0d9877eedf 100644 --- a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py +++ b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py @@ -105,7 +105,7 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, unit='NPLC') self.add_parameter('volt', - get_cmd=_get_voltage, + get_cmd=self._get_voltage, label='Voltage', unit='V') From 6058490a859968f07b2eb3f8c99a0eed13fbe7ab Mon Sep 17 00:00:00 2001 From: William Nielsen Date: Fri, 31 Mar 2017 17:18:42 +0200 Subject: [PATCH 6/9] WIP: Add Array parameter --- .../Keysight/Keysight_34465A.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py index e0d9877eedf..e6960eca6f6 100644 --- a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py +++ b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py @@ -2,6 +2,47 @@ import qcodes.utils.validators as vals from qcodes import VisaInstrument +from qcodes.instrument.parameter import ArrayPa +import numpy as np + + +class ArrayMeasurement(ArrayParameter): + """ + Class to return several values. Really represents a measurement routine. + """ + + def __init__(self, name, *args, **kwargs): + + super().__init__(name, *args, **kwargs) + + self.label = '' + self.unit = '' + self.properly_prepared = False + + def prepare(self): + """ + Prepare the measurement, create the setpoints. + + To get deterministic times, we must set the timing to be + TWICE that derived from the NPLC value. + """ + + inst = self._instrument + + N = inst.sample_count() + inst.aperture_mode('OFF') # aperture mode seems slower ON than OFF + + t_expec = inst.NPLC()/50 # 50 Hz power + + self.setpoints = (tuple(np.linspace(0, 2*t_expec, N)),) + + self.properly_prepared = True + + def get(self): + + if not self.properly_prepared: + raise ValueError('ArrayMeasurement not properly_prepared. ' + 'Please run prepare') class Keysight_34465A(VisaInstrument): From ffb412d9c964136041ef4f50ed8c4122e259741e Mon Sep 17 00:00:00 2001 From: William Nielsen Date: Mon, 3 Apr 2017 14:43:47 +0200 Subject: [PATCH 7/9] feat: Add functioning data buffer parameter --- .../Keysight/Keysight_34465A.py | 93 ++++++++++++++++--- 1 file changed, 81 insertions(+), 12 deletions(-) diff --git a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py index e6960eca6f6..4113c7ba962 100644 --- a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py +++ b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py @@ -1,9 +1,14 @@ # QCoDeS driver for the Keysight 34465A Digital Multimeter +from functools import partial +import numpy as np +import logging + +from qcodes.instrument.parameter import ArrayParameter import qcodes.utils.validators as vals from qcodes import VisaInstrument -from qcodes.instrument.parameter import ArrayPa -import numpy as np + +log = logging.getLogger(__name__) class ArrayMeasurement(ArrayParameter): @@ -11,9 +16,9 @@ class ArrayMeasurement(ArrayParameter): Class to return several values. Really represents a measurement routine. """ - def __init__(self, name, *args, **kwargs): + def __init__(self, name, shape=(1,), *args, **kwargs): - super().__init__(name, *args, **kwargs) + super().__init__(name, shape=shape, *args, **kwargs) self.label = '' self.unit = '' @@ -23,18 +28,31 @@ def prepare(self): """ Prepare the measurement, create the setpoints. - To get deterministic times, we must set the timing to be - TWICE that derived from the NPLC value. + There is some randomness in the measurement times. """ inst = self._instrument N = inst.sample_count() + + # ensure correct instrument settings inst.aperture_mode('OFF') # aperture mode seems slower ON than OFF + inst.trigger_count(1) + inst.trigger_delay(0) + inst.sample_count_pretrigger(0) + inst.sample_source('TIM') + inst.autorange('OFF') + + if inst.trigger_source() is None: + raise ValueError('Trigger source unspecified! Please set ' + "trigger_source to 'INT' or 'EXT'.") - t_expec = inst.NPLC()/50 # 50 Hz power + # Final step + self.time_per_point = inst.sample_timer_minimum() + inst.sample_timer(self.time_per_point) - self.setpoints = (tuple(np.linspace(0, 2*t_expec, N)),) + self.setpoints = (tuple(np.linspace(0, N*self.time_per_point, N)),) + self.shape = (N,) self.properly_prepared = True @@ -42,13 +60,41 @@ def get(self): if not self.properly_prepared: raise ValueError('ArrayMeasurement not properly_prepared. ' - 'Please run prepare') + 'Please run prepare().') + + N = self._instrument.sample_count() + log.debug("Acquiring {} samples.".format(N)) + + # Ensure that the measurement doesn't time out + # TODO (WilliamHPNielsen): What if we wait really long for a trigger? + old_timeout = self._instrument.visa_handle.timeout + self._instrument.visa_handle.timeout = N*1000*1.2*self.time_per_point + self._instrument.visa_handle.timeout += old_timeout + + # Turn off the display to increase measurement speed + self._instrument.display_text('Acquiring {} samples'.format(N)) + + self._instrument.init_measurement() + rawvals = self._instrument.ask('FETCH?') + + self._instrument.visa_handle.timeout = old_timeout + + # parse the aqcuired values + try: + numvals = np.array(list(map(float, rawvals.split(',')))) + except AttributeError: + numvals = None + + self._instrument.display_clear() + + return numvals class Keysight_34465A(VisaInstrument): """ Instrument class for Keysight 34465A. + The driver is written such that usage with models 34460A, 34461A, and 34470A should be seamless. @@ -146,6 +192,7 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, unit='NPLC') self.add_parameter('volt', + get_cmd=self._get_voltage, label='Voltage', unit='V') @@ -211,7 +258,8 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, self.add_parameter('sample_count', label='Sample Count', - set_cmd='SAMPle:COUNt {}', + set_cmd=partial(self._set_databuffer_setpoints, + 'SAMPle:COUNt {}'), get_cmd='SAMPle:COUNt?', vals=vals.MultiType(vals.Numbers(1, 1e6), vals.Enum('MIN', 'MAX', 'DEF')), @@ -227,8 +275,8 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, docstring=('Allows collection of the data ' 'being digitized the trigger. Reserves ' 'memory for pretrigger samples up to the' - ' specified num. of pretrigger samples.' - )) + ' specified num. of pretrigger samples.') + ) self.add_parameter('sample_source', label='Sample Timing Source', @@ -247,6 +295,15 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, vals.Enum('MIN', 'MAX', 'DEF')), get_parser=float) + self.add_parameter('sample_timer_minimum', + label='Minimal sample time', + get_cmd='SAMPle:TIMer? MIN', + get_parser=float, + unit='s') + + # The array parameter + self.add_parameter('data_buffer', + parameter_class=ArrayMeasurement) #################################### # Model-specific parameters @@ -286,6 +343,14 @@ def _get_voltage(self): return float(response) + def _set_databuffer_setpoints(self, cmd, value): + """ + set_cmd for all databuffer-setpoint related parameters + """ + + self.data_buffer.properly_prepared = False + self.write(cmd.format(value)) + def _set_apt_time(self, value): self.write('SENSe:VOLTage:DC:APERture {:f}'.format(value)) @@ -295,6 +360,9 @@ def _set_apt_time(self, value): def _set_NPLC(self, value): self.write('SENSe:VOLTage:DC:NPLC {:f}'.format(value)) + # This will change data_buffer setpoints (timebase) + self.data_buffer.properly_prepared = False + # resolution settings change with NPLC self.resolution.get() @@ -327,4 +395,5 @@ def _set_resolution(self, value): self.write('VOLT:DC:RES {:.1e}'.format(value)) # NPLC settings change with resolution + self.NPLC.get() From f47375e8caceafecb48e6c13ab6e83ab8e1a02b7 Mon Sep 17 00:00:00 2001 From: WilliamHPNielsen Date: Tue, 4 Apr 2017 11:10:41 +0200 Subject: [PATCH 8/9] Move notebook --- ...gilent 34411A versus Keysight 34465A.ipynb | 442 ++++++++++++++++++ 1 file changed, 442 insertions(+) create mode 100644 docs/examples/benchmarking/Agilent 34411A versus Keysight 34465A.ipynb diff --git a/docs/examples/benchmarking/Agilent 34411A versus Keysight 34465A.ipynb b/docs/examples/benchmarking/Agilent 34411A versus Keysight 34465A.ipynb new file mode 100644 index 00000000000..0699f323e3d --- /dev/null +++ b/docs/examples/benchmarking/Agilent 34411A versus Keysight 34465A.ipynb @@ -0,0 +1,442 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "# Agilent 34411A versus Keysight 34465A\n", + "\n", + "The following notebook perfoms a benchmarking of the two DMMs. In part one, raw readings of immediate voltages are timed\n", + "and compared. In part two, actual sweeps are performed with a QDac." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "%matplotlib notebook\n", + "import time\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "import qcodes as qc\n", + "from qcodes.instrument_drivers.Keysight.Keysight_34465A import Keysight_34465A\n", + "from qcodes.instrument_drivers.agilent.Agilent_34400A import Agilent_34400A\n", + "from qcodes.instrument_drivers.QDev.QDac import QDac" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "## Import and setup" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connected to: Keysight Technologies 34465A (serial:MY54505388, firmware:A.02.14-02.40-02.14-00.49-02-01) in 6.93s\n", + "Connected to: Agilent Technologies 34411A (serial:MY48002016, firmware:2.35-2.35-0.09-46-09) in 0.06s\n" + ] + } + ], + "source": [ + "ks = Keysight_34465A('Keysight', 'TCPIP0::K-000000-00000::inst0::INSTR')\n", + "agi = Agilent_34400A('Agilent', 'TCPIP0::192.168.15.105::inst0::INSTR')\n", + "qdac = QDac('qdac', 'ASRL4::INSTR')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "station = qc.Station(ks, agi, qdac)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "# set up a NPLC of 0.06 corresponding to an aperture time of 1 ms\n", + "ks.NPLC(0.06)\n", + "agi.NPLC(0.06)\n", + "\n", + "# set the same range on both DMMs\n", + "ks.range(1)\n", + "agi.range(1)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "## Part one - raw readings" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reading with displays ON\n", + "----------\n", + "Read 512 values one at a time from Keysight in: 8.587134838104248 s\n", + "Read 512 values one at a time from Agilent in: 4.099916696548462 s\n", + "----------\n", + "Read 1024 values one at a time from Keysight in: 16.83395004272461 s\n", + "Read 1024 values one at a time from Agilent in: 8.229825019836426 s\n", + "----------\n", + "Read 2048 values one at a time from Keysight in: 33.76206350326538 s\n", + "Read 2048 values one at a time from Agilent in: 16.453675985336304 s\n", + "----------\n" + ] + } + ], + "source": [ + "# Preliminary testing, just get N readings from each instrument\n", + "# with the displays on\n", + "\n", + "ks.display_clear() # make sure that the display is on\n", + "agi.display_clear()\n", + "\n", + "print('Reading with displays ON')\n", + "print('-'*10)\n", + "\n", + "for N in [512, 1024, 2048]:\n", + "\n", + " t_start = time.time()\n", + " for ii in range(N):\n", + " ks.volt()\n", + " t_stop = time.time()\n", + " print('Read {} values one at a time from Keysight in: {} s'.format(N, t_stop-t_start))\n", + "\n", + " t_start = time.time()\n", + " for ii in range(N):\n", + " agi.volt()\n", + " t_stop = time.time()\n", + " print('Read {} values one at a time from Agilent in: {} s'.format(N, t_stop-t_start))\n", + "\n", + " print('-'*10)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Reading with displays OFF\n", + "----------\n", + "Read 512 values one at a time from Keysight in: 4.5132529735565186 s\n", + "Read 512 values one at a time from Agilent in: 4.098856449127197 s\n", + "----------\n", + "Read 1024 values one at a time from Keysight in: 8.996399164199829 s\n", + "Read 1024 values one at a time from Agilent in: 8.227899074554443 s\n", + "----------\n", + "Read 2048 values one at a time from Keysight in: 17.969755172729492 s\n", + "Read 2048 values one at a time from Agilent in: 16.399696350097656 s\n", + "----------\n" + ] + } + ], + "source": [ + "# The same test, but with the displays off to decrease latency\n", + "\n", + "print('Reading with displays OFF')\n", + "print('-'*10)\n", + "\n", + "for N in [512, 1024, 2048]:\n", + "\n", + " ks.display_text('QCoDeS')\n", + " t_start = time.time()\n", + " for ii in range(N):\n", + " ks.volt()\n", + " t_stop = time.time()\n", + " print('Read {} values one at a time from Keysight in: {} s'.format(N, t_stop-t_start))\n", + " ks.display_clear()\n", + "\n", + " agi.display_text('QCoDes')\n", + " t_start = time.time()\n", + " for ii in range(N):\n", + " agi.volt()\n", + " t_stop = time.time()\n", + " print('Read {} values one at a time from Agilent in: {} s'.format(N, t_stop-t_start))\n", + " agi.display_clear()\n", + "\n", + " print('-'*10)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "source": [ + "## Part two - QCoDeS looping" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "### 1D Sweep" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-07/#018_testsweep_12-32-13'\n", + " | | | \n", + " Setpoint | qdac_ch42_v_set | ch42_v | (512,)\n", + " Measured | Keysight_volt | volt | (512,)\n", + "started at 2017-03-07 12:32:29\n", + "\n", + "\n", + "Did a 512-point QCoDeS sweep of the QDac/Keysight pair in 16.5 s\n", + "\n", + "\n", + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-07/#019_testsweep_12-32-29'\n", + " | | | \n", + " Setpoint | qdac_ch41_v_set | ch41_v | (512,)\n", + " Measured | Agilent_volt | volt | (512,)\n", + "started at 2017-03-07 12:32:46\n", + "\n", + "\n", + "Did a 512-point QCoDeS sweep of the QDac/Agilent pair in 16.5 s\n", + "\n", + "\n" + ] + } + ], + "source": [ + "# Sweep a voltage from 0.2 V to 0.5 V in 512 steps\n", + "# Switch off displays for speed\n", + "\n", + "ks.display_text('QCoDeS')\n", + "agi.display_text('QCoDeS')\n", + "\n", + "N = 512 \n", + "V1 = 0.2\n", + "V2 = 0.5\n", + "dV = (V2-V1)/(N-1) # endpoint included in sweep\n", + "\n", + "loop = qc.Loop(qdac.ch42_v.sweep(V1, V2, dV)).each(ks.volt)\n", + "data = loop.get_data_set(name='testsweep')\n", + "t_start = time.time()\n", + "_ = loop.run()\n", + "t_stop = time.time()\n", + "print('\\n\\nDid a {}-point QCoDeS sweep of the QDac/Keysight pair in {:.1f} s\\n\\n'.format(N, t_stop-t_start))\n", + "\n", + "loop = qc.Loop(qdac.ch41_v.sweep(V1, V2, dV)).each(agi.volt)\n", + "data = loop.get_data_set(name='testsweep')\n", + "t_start = time.time()\n", + "_ = loop.run()\n", + "t_stop = time.time()\n", + "print('\\n\\nDid a {}-point QCoDeS sweep of the QDac/Agilent pair in {:.1f} s\\n\\n'.format(N, t_stop-t_start))\n", + "\n", + "agi.display_clear()\n", + "ks.display_clear()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "deletable": true, + "editable": true + }, + "source": [ + "### 2D Sweep" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false, + "deletable": true, + "editable": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-07/#020_testsweep_12-33-46'\n", + " | | | \n", + " Setpoint | qdac_ch42_v_set | ch42_v | (100,)\n", + " Setpoint | qdac_ch41_v_set | ch41_v | (100, 100)\n", + " Measured | Keysight_volt | volt | (100, 100)\n", + "started at 2017-03-07 12:39:09\n", + "\n", + "\n", + "Did a 100x100-point QCoDeS sweep of the QDac/Keysight pair in 323.9 s\n", + "\n", + "\n", + "DataSet:\n", + " mode = DataMode.LOCAL\n", + " location = 'data/2017-03-07/#021_testsweep_12-39-09'\n", + " | | | \n", + " Setpoint | qdac_ch41_v_set | ch41_v | (100,)\n", + " Setpoint | qdac_ch42_v_set | ch42_v | (100, 100)\n", + " Measured | Agilent_volt | volt | (100, 100)\n", + "started at 2017-03-07 12:44:33\n", + "\n", + "\n", + "Did a 100x100-point QCoDeS sweep of the QDac/Agilent pair in 323.8 s\n", + "\n", + "\n" + ] + } + ], + "source": [ + "# Perform the same sweep as before, but this time nested inside another sweep of the same length,\n", + "# i.e. at each point of the original sweep, another QDac channel sweeps its voltage in the same number of steps\n", + "\n", + "ks.display_text('QCoDeS')\n", + "agi.display_text('QCoDeS')\n", + "\n", + "N = 100\n", + "V1 = 0.2\n", + "V2 = 0.5\n", + "dV = (V2-V1)/(N-1)\n", + "\n", + "loop = qc.Loop(qdac.ch42_v.sweep(V1, V2, dV)).loop(qdac.ch41_v.sweep(V1, V2, dV)).each(ks.volt)\n", + "data = loop.get_data_set(name='testsweep')\n", + "t_start = time.time()\n", + "_ = loop.run()\n", + "t_stop = time.time()\n", + "print('\\n\\nDid a {}x{}-point QCoDeS sweep of the QDac/Keysight pair in {:.1f} s\\n\\n'.format(N, N, t_stop-t_start))\n", + "\n", + "loop = qc.Loop(qdac.ch41_v.sweep(V1, V2, dV)).loop(qdac.ch42_v.sweep(V1, V2, dV)).each(agi.volt)\n", + "data = loop.get_data_set(name='testsweep')\n", + "t_start = time.time()\n", + "_ = loop.run()\n", + "t_stop = time.time()\n", + "print('\\n\\nDid a {}x{}-point QCoDeS sweep of the QDac/Agilent pair in {:.1f} s\\n\\n'.format(N, N, t_stop-t_start))\n", + "\n", + "ks.display_clear()\n", + "agi.display_clear()" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "outputs": [], + "source": [ + "ks.close()\n", + "agi.close()\n", + "qdac.close()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true, + "deletable": true, + "editable": true + }, + "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.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 98f3f178241bcf22cf6ef110539250b47c2486ba Mon Sep 17 00:00:00 2001 From: WilliamHPNielsen Date: Tue, 4 Apr 2017 11:14:18 +0200 Subject: [PATCH 9/9] Respond to review --- qcodes/instrument_drivers/Keysight/Keysight_34465A.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py index 4113c7ba962..991288fb577 100644 --- a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py +++ b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py @@ -79,7 +79,7 @@ def get(self): self._instrument.visa_handle.timeout = old_timeout - # parse the aqcuired values + # parse the acquired values try: numvals = np.array(list(map(float, rawvals.split(',')))) except AttributeError: @@ -192,7 +192,6 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, unit='NPLC') self.add_parameter('volt', - get_cmd=self._get_voltage, label='Voltage', unit='V') @@ -335,9 +334,11 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, self.connect_message() def _get_voltage(self): - # TODO: massive improvements! What if more than one number was - # asked for? - # What if mode is not voltage sensing? What if... + # TODO: massive improvements! + # The 'READ?' command will return anything the instrument is set up + # to return, i.e. not necessarily a voltage (might be current or + # or resistance) and not necessarily a single value. This function + # should be aware of the configuration. response = self.ask('READ?')