diff --git a/docs/examples/benchmarking/Benchmark of Keysight DMM software trigger vs set-get.ipynb b/docs/examples/benchmarking/Benchmark of Keysight DMM software trigger vs set-get.ipynb new file mode 100644 index 00000000000..1e97d3a0821 --- /dev/null +++ b/docs/examples/benchmarking/Benchmark of Keysight DMM software trigger vs set-get.ipynb @@ -0,0 +1,303 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Benchmark of Keysight 34465A\n", + "\n", + "We benchmark the acquisition of N voltages from a QDac on a Keysight DMM. Two acquisition modes are tested; the \"classical\" set voltage/get voltage and a set voltage / send software trigger method.\n", + "\n", + "The former method is cast as a standard QCoDeS measurement, whereas the latter is just the raw commands. If anything, this should add a bit of extra overhead to the first method.\n", + "\n", + "The QDac sweeps a voltage from 0 V to 1 V.\n", + "\n", + "Conclusion: there is **no** speed-up." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "import qcodes as qc\n", + "import numpy as np\n", + "import time\n", + "from qcodes.instrument_drivers.Keysight.Keysight_34465A import Keysight_34465A\n", + "from qcodes.instrument_drivers.QDev.QDac import QDac" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Connected to: Keysight Technologies 34465A (serial:MY54505281, firmware:A.02.14-02.40-02.14-00.49-02-01) in 7.14s\n" + ] + } + ], + "source": [ + "dmm = Keysight_34465A('dmm', 'TCPIP0::K-000000-00000.local::hislip0::INSTR')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "qdac = QDac('qdac', 'ASRL7::INSTR')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Pre-benchmark setting" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "ap_time = 1e-3\n", + "dmm.NPLC(0.06) # aperture time of 1 ms\n", + "dmm.range(1) # Voltage range of 1 V\n", + "qdac.ch01_v(0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## N = 1000, set-get" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# prepare the DMM for get-set mode\n", + "dmm.trigger_source('IMM')\n", + "dmm.sample_count(1)\n", + "dmm.trigger_count(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Started at 2017-09-08 11:33:51\n", + "DataSet:\n", + " location = 'data/2017-09-08/#013_N_1000_setget_11-33-51'\n", + " | | | \n", + " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n", + " Measured | dmm_volt | volt | (1000,)\n", + "Finished at 2017-09-08 11:34:23\n", + "Started at 2017-09-08 11:34:23\n", + "DataSet:\n", + " location = 'data/2017-09-08/#014_N_1000_setget_11-34-23'\n", + " | | | \n", + " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n", + " Measured | dmm_volt | volt | (1000,)\n", + "Finished at 2017-09-08 11:34:55\n", + "Started at 2017-09-08 11:34:55\n", + "DataSet:\n", + " location = 'data/2017-09-08/#015_N_1000_setget_11-34-55'\n", + " | | | \n", + " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n", + " Measured | dmm_volt | volt | (1000,)\n", + "Finished at 2017-09-08 11:35:27\n", + "Started at 2017-09-08 11:35:27\n", + "DataSet:\n", + " location = 'data/2017-09-08/#016_N_1000_setget_11-35-27'\n", + " | | | \n", + " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n", + " Measured | dmm_volt | volt | (1000,)\n", + "Finished at 2017-09-08 11:35:59\n", + "Started at 2017-09-08 11:35:59\n", + "DataSet:\n", + " location = 'data/2017-09-08/#017_N_1000_setget_11-35-59'\n", + " | | | \n", + " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n", + " Measured | dmm_volt | volt | (1000,)\n", + "Finished at 2017-09-08 11:36:32\n", + "Started at 2017-09-08 11:36:32\n", + "DataSet:\n", + " location = 'data/2017-09-08/#018_N_1000_setget_11-36-32'\n", + " | | | \n", + " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n", + " Measured | dmm_volt | volt | (1000,)\n", + "Finished at 2017-09-08 11:37:04\n", + "Started at 2017-09-08 11:37:04\n", + "DataSet:\n", + " location = 'data/2017-09-08/#019_N_1000_setget_11-37-04'\n", + " | | | \n", + " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n", + " Measured | dmm_volt | volt | (1000,)\n", + "Finished at 2017-09-08 11:37:36\n", + "Started at 2017-09-08 11:37:36\n", + "DataSet:\n", + " location = 'data/2017-09-08/#020_N_1000_setget_11-37-36'\n", + " | | | \n", + " Setpoint | qdac_ch01_v_set | ch01_v | (1000,)\n", + " Measured | dmm_volt | volt | (1000,)\n", + "Finished at 2017-09-08 11:38:08\n", + "32.2 s ± 110 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "\n", + "N = 1000\n", + "\n", + "# remember to turn off the display for better speed\n", + "dmm.display_text('Running set-get for {} points'.format(N))\n", + "\n", + "loop = qc.Loop(qdac.ch01_v.sweep(0, 1, num=N)).each(dmm.volt)\n", + "data = loop.get_data_set(name='N_{}_setget'.format(N))\n", + "_ = loop.run() # run the loop\n", + "\n", + "dmm.display_clear()\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## N = 1000, set-software triggered" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def software_triggered_readings(N: int) -> np.array:\n", + " \"\"\"\n", + " Try to get N measurement points\n", + " \"\"\"\n", + " \n", + " dmm.display_text('Sending {} software triggers'.format(N))\n", + " \n", + " dmm.trigger_source('BUS')\n", + " dmm.sample_count(1) # samples per trigger\n", + " dmm.trigger_count(N) # number of triggers to wait for\n", + " dmm.init_measurement()\n", + " \n", + " qdac_setpoints = np.linspace(0, 1, N)\n", + " \n", + " for n in range(N):\n", + " qdac.ch01_v(qdac_setpoints[n])\n", + " dmm.write('*TRG')\n", + " time.sleep(dmm.sample_timer_minimum()) # Wait to avoid losing triggers\n", + " \n", + " # even if we are losing triggers, can ABORt the measurement\n", + " # and then fetch whatever data the DMM holds\n", + " dmm.abort_measurement() \n", + " raw_vals = dmm.ask('FETCH?')\n", + " dmm.display_clear()\n", + "\n", + " numvals = np.array(list(map(float, raw_vals.split(','))))\n", + " \n", + " print('Requested {} samples, got {}.'.format(N, len(numvals)))\n", + " \n", + " return numvals" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requested 1000 samples, got 1000.\n", + "Requested 1000 samples, got 1000.\n", + "Requested 1000 samples, got 1000.\n", + "Requested 1000 samples, got 1000.\n", + "Requested 1000 samples, got 1000.\n", + "Requested 1000 samples, got 1000.\n", + "Requested 1000 samples, got 1000.\n", + "Requested 1000 samples, got 1000.\n", + "32.2 s ± 387 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%%timeit\n", + "\n", + "data = software_triggered_readings(1000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Results summary\n", + "\n", + "**N = 1000**\n", + "\n", + "Standard set-get: 32.2 s\n", + "\n", + "Software triggered: 32.2 s" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": 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.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py index 7fa991f746b..95562699cc3 100644 --- a/qcodes/instrument_drivers/Keysight/Keysight_34465A.py +++ b/qcodes/instrument_drivers/Keysight/Keysight_34465A.py @@ -185,6 +185,21 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, self.NPLC_list = PLCs[self.model] self._apt_times = apt_times[self.model] + def errorparser(rawmssg: str) -> (int, str): + """ + Parses the error message. + + Args: + rawmssg: The raw return value of 'SYSTem:ERRor?' + + Returns: + The error code and the error message. + """ + code = int(rawmssg.split(',')[0]) + mssg = rawmssg.split(',')[1].strip().replace('"', '') + + return code, mssg + #################################### # PARAMETERS @@ -306,6 +321,13 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, get_parser=float, unit='s') + # SYSTEM + self.add_parameter('error', + label='Error message', + get_cmd='SYSTem:ERRor?', + get_parser=errorparser + ) + # The array parameter self.add_parameter('data_buffer', parameter_class=ArrayMeasurement) @@ -335,6 +357,7 @@ def __init__(self, name, address, DIG=False, utility_freq=50, silent=False, 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')) + self.add_function('abort_measurement', call_cmd='ABORt') if not silent: self.connect_message() @@ -404,3 +427,27 @@ def _set_resolution(self, value): # NPLC settings change with resolution self.NPLC.get() + + def flush_error_queue(self, verbose: bool=True) -> None: + """ + Clear the instrument error queue. + + Args: + verbose: If true, the error messages are printed. + Default: True. + """ + + log.debug('Flushing error queue...') + + err_code, err_message = self.error() + log.debug(' {}, {}'.format(err_code, err_message)) + if verbose: + print(err_code, err_message) + + while err_code != 0: + err_code, err_message = self.error() + log.debug(' {}, {}'.format(err_code, err_message)) + if verbose: + print(err_code, err_message) + + log.debug('...flushing complete')