From 5f05a196ba8c5e0bef41650e414a8f1f61e5ec25 Mon Sep 17 00:00:00 2001 From: "William H.P. Nielsen" Date: Wed, 14 Jun 2017 14:44:26 +0200 Subject: [PATCH] docs: Example notebook for QDev specifics (#39) * docs: Example notebook for QDev specifics * docs: reader-friendly linewraps --- docs/examples/Tutorial for QDevvies.ipynb | 2987 +++++++++++++++++++++ 1 file changed, 2987 insertions(+) create mode 100644 docs/examples/Tutorial for QDevvies.ipynb diff --git a/docs/examples/Tutorial for QDevvies.ipynb b/docs/examples/Tutorial for QDevvies.ipynb new file mode 100644 index 00000000000..64095a3824f --- /dev/null +++ b/docs/examples/Tutorial for QDevvies.ipynb @@ -0,0 +1,2987 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# QCoDeS tutorial for QDevvies\n", + "\n", + "Basic overview of the QDev flavour of QCoDeS. The QDev version shares most of the backbone structure with normal (international) QCoDeS, but differs in the exact function call used to acquire data. In particalur, QDev QCoDeS contains the following 4 extra functions:\n", + "\n", + "`init`, `do1d`, `do2d`, `show_num`.\n", + "\n", + "## Table of Contents \n", + " * [Workflow](#workflow)\n", + " * [Basic instrument interaction](#inst_io)\n", + " * [Measuring](#measurement)\n", + " * [1D loop with `do1d`](#do1d)\n", + " * [2D loop with `do2d`](#do2d)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Typical QCodes workflow \n", + "(back to [ToC](#toc))\n", + "\n", + "1. Start up an interactive python session (e.g. using jupyter) \n", + "2. Import desired modules \n", + "3. Instantiate/resume the experiment \n", + "4. Get data or die trying!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Importing" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": true, + "scrolled": false + }, + "outputs": [], + "source": [ + "%matplotlib notebook\n", + "\n", + "# usually, one imports QCoDeS and some instruments\n", + "import qcodes as qc\n", + "\n", + "# In QDev land, one imports a handful of helper functions\n", + "from qcodes.utils.wrappers import init, do1d, do2d, show_num\n", + "\n", + "# In this tutorial, we import the dummy instrument\n", + "from qcodes.tests.instrument_mocks import DummyInstrument\n", + "# real instruments are imported in a similar way, e.g.\n", + "# from qcodes.instrument_drivers.Keysight.Keysight_33500B import Keysight_33500B" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Instantiation of Experiment\n", + "\n", + "The special QDev function `init` is the function that sets up the entire experiment.\n", + "It\n", + " * Makes folders for the data\n", + " * Keeps track of how many measurements have been performed (across Python sessions)\n", + " * Annotates a device image for each measurement\n", + " * Logs the jupyter notebook execution" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Activating auto-logging. Current session state plus future input saved.\n", + "Filename : /Users/william/sourcecodes/qcodes-jenshnielsen/docs/examples/TutorialExperiment/TutorialSample/commands.log\n", + "Mode : append\n", + "Output logging : True\n", + "Raw input log : False\n", + "Timestamping : True\n", + "State : active\n" + ] + } + ], + "source": [ + "# It is not enough to import the instruments, they must also be instantiated\n", + "# Note that this can only be done once. If you try to \n", + "# re-instantiate an existing instrument, QCoDeS will \n", + "# complain that 'Another instrument has the name'.\n", + "\n", + "\n", + "# In this turotial, we consider a simple situation: \n", + "# A single DAC outputting voltages to a Digital Multi Meter\n", + "\n", + "dac = DummyInstrument(name=\"dac\", gates=['ch1', 'ch2']) # The DAC voltage source\n", + "dmm = DummyInstrument(name=\"dmm\", gates=['voltage']) # The DMM voltage reader\n", + "\n", + "# For pedagical purposes, we \"pimp\" the dummy instruments a bit\n", + "\n", + "# the default dummy instrument returns always a constant value, \n", + "# in the following line we make it random \n", + "# just for the looks 💅\n", + "import random\n", + "dmm.voltage.get = lambda: random.randint(0, 100)\n", + "\n", + "# We add a parameter that loudly prints what it is being set to\n", + "# (It is used below)\n", + "\n", + "chX = 0\n", + "def myget():\n", + " return chX\n", + " \n", + "def myset(x):\n", + " global chX\n", + " chX = x\n", + " print('Setting to {}'.format(x))\n", + " return None\n", + " \n", + "dac.add_parameter('verbose_channel',\n", + " label='Verbose Channel',\n", + " unit='V',\n", + " get_cmd=myget,\n", + " set_cmd=myset)\n", + "\n", + "# Next, the instruments should be bound to a Station. \n", + "# Only instruments bound to the Station get recorded in the\n", + "# measurement metadata, so your metadata is blind to \n", + "# any instrument not in the Station.\n", + "\n", + "station = qc.Station(dac, dmm)\n", + "\n", + "# Finally, we instantiate the experiment. \n", + "init(mainfolder='TutorialExperiment',\n", + " sample_name='TutorialSample',\n", + " station=station,\n", + " annotate_image=False)\n", + "# NB: In the tutorial we don't annotate an image, but change False to True to do so\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "By all means, have a look at the `commands.log` file. From this, you can find out EXACTLY what you did when and thus retrace your whole experiment. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We are now ready to play with the instruments!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Basic instrument interaction \n", + "(back to [ToC](#toc))\n", + "\n", + "The interaction with instruments mainly consists of `setting` and `getting` the instruments' `parameters`. A parameter can be anything from the frequency of a signal generator over the output impedance of an AWG to the traces from a lock-in amplifier. In this tutorial we --for didactical reasons-- only consider scalar parameters. " + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "8" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The voltages output by the dac can be set like so\n", + "dac.ch1.set(8) \n", + "# Now the output is 8 V. We can read this value back\n", + "dac.ch1.get()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Setting IMMEDIATELY changes a value. For voltages, that is sometimes undesired. The value can instead be ramped by stepping and waiting." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Setting to 0\n", + "Setting to 9\n", + "Setting to 8.9\n", + "Setting to 8.8\n", + "Setting to 8.7\n", + "Setting to 8.6\n", + "Setting to 8.5\n", + "Setting to 8.4\n", + "Setting to 8.3\n", + "Setting to 8.2\n", + "Setting to 8.1\n", + "Setting to 8.0\n", + "Setting to 7.9\n", + "Setting to 7.8\n", + "Setting to 7.7\n", + "Setting to 7.6\n", + "Setting to 7.5\n", + "Setting to 7.4\n", + "Setting to 7.3\n", + "Setting to 7.2\n", + "Setting to 7.1\n", + "Setting to 7.0\n", + "Setting to 6.9\n", + "Setting to 6.8\n", + "Setting to 6.699999999999999\n", + "Setting to 6.6\n", + "Setting to 6.5\n", + "Setting to 6.4\n", + "Setting to 6.3\n", + "Setting to 6.199999999999999\n", + "Setting to 6.1\n", + "Setting to 6.0\n", + "Setting to 5.9\n", + "Setting to 5.8\n", + "Setting to 5.699999999999999\n", + "Setting to 5.6\n", + "Setting to 5.5\n", + "Setting to 5.4\n", + "Setting to 5.3\n", + "Setting to 5.199999999999999\n", + "Setting to 5.1\n", + "Setting to 5\n" + ] + } + ], + "source": [ + "dac.verbose_channel.set(0) \n", + "dac.verbose_channel.set(9) # immediate voltage jump of 9 Volts (!)\n", + "\n", + "# first set a step size\n", + "dac.verbose_channel.set_step(0.1)\n", + "# and a wait time\n", + "dac.verbose_channel.set_delay(0.25) # in seconds\n", + "\n", + "# now a \"staircase ramp\" is performed by setting\n", + "dac.verbose_channel.set(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**NOTE**: that is ramp is blocking and has a low resolution since each `set` on a real instrument has a latency on the order of ms. Some instrument drivers support native-resolution asynchronous ramping. Always refer to your instrument driver if you need high performance of an instrument." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "# after such a ramp, it is a good idea to reset the step and delay\n", + "dac.verbose_channel.set_step(0)\n", + "# and a wait time\n", + "dac.verbose_channel.set_delay(0)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Measuring \n", + "(back to [ToC](#toc))\n", + "\n", + "The above foolin' about with instruments did not count as measurements; no data sets were produced or saved. To do\n", + "that, utilise the `do1d` or `do2d` function.\n", + "\n", + "### 1D Loop example \n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Started at 2017-06-14 13:31:37\n", + "DataSet:\n", + " location = '/Users/william/sourcecodes/qcodes-jenshnielsen/docs/examples/TutorialExperiment/TutorialSample/011'\n", + " | | | \n", + " Setpoint | dac_ch1_set | ch1 | (25,)\n", + " Measured | dmm_voltage | voltage | (25,)\n", + "Finished at 2017-06-14 13:31:40\n" + ] + }, + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('
');\n", + " var button = $('');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "(DataSet:\n", + " location = '/Users/william/sourcecodes/qcodes-jenshnielsen/docs/examples/TutorialExperiment/TutorialSample/002'\n", + " | | | \n", + " Setpoint | dac_ch1_set | ch1 | (25,)\n", + " Measured | dmm_voltage | voltage | (25,),\n", + " [])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# The data may be brought up easily by referecing the unique ID number\n", + "show_num(2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### Products of `do1d`\n", + "\n", + "The `do1d` function creates a DataSet. \n", + "The representation of the dataset shows what arrays it contains and where it is saved. \n", + "The dataset initially starts out empty (filled with NAN's) and gets filled while the `do1d` is being executed. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Once the measurement is done, take a look at the file in finder/explorer (the dataset.location should give you the relative path). \n", + "Note also the snapshot that captures the settings of all instruments at the start of the Loop. \n", + "This metadata is also accessible from the dataset and captures a snapshot of each instrument listed in the station. " + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'__class__': 'qcodes.tests.instrument_mocks.DummyInstrument',\n", + " 'functions': {},\n", + " 'name': 'dac',\n", + " 'parameters': {'IDN': {'__class__': 'qcodes.instrument.parameter.StandardParameter',\n", + " 'instrument': 'qcodes.tests.instrument_mocks.DummyInstrument',\n", + " 'instrument_name': 'dac',\n", + " 'label': 'IDN',\n", + " 'name': 'IDN',\n", + " 'ts': '2017-06-14 13:31:25',\n", + " 'unit': '',\n", + " 'vals': '',\n", + " 'value': {'firmware': None,\n", + " 'model': 'dac',\n", + " 'serial': None,\n", + " 'vendor': None}},\n", + " 'ch1': {'__class__': 'qcodes.instrument.parameter.ManualParameter',\n", + " 'instrument': 'qcodes.tests.instrument_mocks.DummyInstrument',\n", + " 'instrument_name': 'dac',\n", + " 'label': 'Gate ch1',\n", + " 'name': 'ch1',\n", + " 'ts': '2017-06-14 13:31:43',\n", + " 'unit': 'V',\n", + " 'vals': '',\n", + " 'value': 15.0},\n", + " 'ch2': {'__class__': 'qcodes.instrument.parameter.ManualParameter',\n", + " 'instrument': 'qcodes.tests.instrument_mocks.DummyInstrument',\n", + " 'instrument_name': 'dac',\n", + " 'label': 'Gate ch2',\n", + " 'name': 'ch2',\n", + " 'ts': '2017-06-14 13:31:25',\n", + " 'unit': 'V',\n", + " 'vals': '',\n", + " 'value': 0},\n", + " 'verbose_channel': {'__class__': 'qcodes.instrument.parameter.StandardParameter',\n", + " 'instrument': 'qcodes.tests.instrument_mocks.DummyInstrument',\n", + " 'instrument_name': 'dac',\n", + " 'label': 'Verbose Channel',\n", + " 'name': 'verbose_channel',\n", + " 'ts': '2017-06-14 13:31:35',\n", + " 'unit': 'V',\n", + " 'vals': '',\n", + " 'value': 5}}}" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "dac.snapshot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There is also a more human-readable version of the essential information." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "dac:\n", + "\tparameter value\n", + "--------------------------------------------------------------------------------\n", + "IDN :\t{'firmware': None, 'serial': None, 'vendor': None, 'model':...\n", + "ch1 :\t15 (V)\n", + "ch2 :\t0 (V)\n", + "verbose_channel :\t5 (V)\n" + ] + } + ], + "source": [ + "dac.print_readable_snapshot()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### 2D Loop example \n", + "\n", + "The `do2d` function works just the way you would expect." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Started at 2017-06-14 13:31:44\n", + "DataSet:\n", + " location = '/Users/william/sourcecodes/qcodes-jenshnielsen/docs/examples/TutorialExperiment/TutorialSample/013'\n", + " | | | \n", + " Setpoint | dac_ch1_set | ch1 | (25,)\n", + " Setpoint | dac_ch2_set | ch2 | (25, 10)\n", + " Measured | dmm_voltage | voltage | (25, 10)\n", + "Finished at 2017-06-14 13:31:47\n" + ] + }, + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('
');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '
');\n", + " var titletext = $(\n", + " '
');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('
');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", + " var rubberband = $('');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('
')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('