{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# QCoDeS Example with Mercury iPS" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Initial instantiation/connection" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "from qcodes.instrument_drivers.oxford.MercuryiPS_VISA import MercuryiPS\n", "from time import sleep" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Connected to: OXFORD INSTRUMENTS MERCURY IPS (serial:170150002, firmware:2.6.04.000) in 0.15s\n" ] } ], "source": [ "# Note that the MercuryiPS_VISA is a VISA instrument using\n", "# a socket connection. The VISA resource name therefore \n", "# contains the port number and the word 'SOCKET'\n", "mips = MercuryiPS('mips', 'TCPIP0::192.168.15.106::7020::SOCKET')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Basic driver idea\n", "\n", "The driver mainly deals with **field values** in Tesla. The driver is aware of the field values in three coordinate systems, cartesian, spherical, and cylindrical. The driver thus exposes the field coordinates x, y, z, phi, theta, rho, and r. Each coordinate comes in two versions: **target** and **measured**.\n", "\n", "The idea is that the magnetic field is always changed in two steps; first a target is set, then the magnet is asked to ramp to said target." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Safe regions\n", "\n", "In addition to the safety limits baked in to the physical instrument, the driver can accept a safety limit function provided by the user. The function checks - upon receiving a new field target - whether the target is inside an allowed region.\n", "\n", "The limit function must take input arguments Bx, By, Bz (in Tesla) and return a boolean that tells us whether that field value is safe." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# example: the safe region is a sphere\n", "import numpy as np\n", "\n", "\n", "def spherical_limit(x, y, z):\n", " \"\"\"\n", " Safe region is a sphere of radius 1 T\n", " \"\"\"\n", " return np.sqrt(x**2 + y**2 + z**2) <= 1\n", "\n", "# assign the limit function (this can also be done at init)\n", "mips.set_new_field_limits(spherical_limit)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Two different ramps\n", "\n", "The driver can perfom the ramp in two different ways: *simultaneous* ramping or *safe* ramping.\n", "\n", "When simultaneously ramping, all three field components are ramped at the same time.\n", "This method is non-blocking, and it is thus possible to query the field while it is ramping. The method does, however, **not** guarantee that the field stays inside the allowed region during the ramp. If the different axes have different ramp speeds, this is a real risk.\n", "\n", "When safely ramping, all field components that are ramped *towards* the origin are ramped before those who are ramped *away from* the origin. The ramp is thus sequential and blocking, but if the safe region is convex (and contains the origin), you are guaranteed the the field never exceeds the safe region." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parameter overview" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "mips:\n", "\tparameter value\n", "--------------------------------------------------------------------------------\n", "IDN :\t{'model': 'MERCURY IPS', 'vendor': 'OXFORD INSTRUMENTS', 'se...\n", "phi_measured :\t-0 (T)\n", "phi_target :\t0 (degres)\n", "r_measured :\t0.1 (T)\n", "r_target :\t0.1 (T)\n", "rho_measured :\t0.1 (T)\n", "rho_target :\t0.1 (T)\n", "theta_measured :\t90 (T)\n", "theta_target :\t90 (degrees)\n", "timeout :\t5 (s)\n", "x_measured :\t0.1 (T)\n", "x_target :\t0.1 (T)\n", "y_measured :\t-0 (T)\n", "y_target :\t0 (T)\n", "z_measured :\t-0 (T)\n", "z_target :\t-0 (T)\n", "mips_GRPX:\n", "\tparameter value\n", "--------------------------------------------------------------------------------\n", "ATOB :\t59.451 (A/T)\n", "current :\t5.945 (A)\n", "current_persistent :\t5.945 (A)\n", "current_ramp_rate :\t0.59451 (A/s)\n", "current_target :\t0 (A)\n", "field :\t0.1 (T)\n", "field_persistent :\t0.1 (T)\n", "field_ramp_rate :\t0.01 (T/s)\n", "field_target :\t0 (T)\n", "ramp_status :\tTO SET \n", "voltage :\t0.0023 (V)\n", "mips_GRPY:\n", "\tparameter value\n", "--------------------------------------------------------------------------------\n", "ATOB :\t59.301 (A/T)\n", "current :\t-0.0005 (A)\n", "current_persistent :\t-0.0005 (A)\n", "current_ramp_rate :\t0.59301 (A/s)\n", "current_target :\t0 (A)\n", "field :\t-0 (T)\n", "field_persistent :\t-0 (T)\n", "field_ramp_rate :\t0.01 (T/s)\n", "field_target :\t0 (T)\n", "ramp_status :\tHOLD \n", "voltage :\t-0.0002 (V)\n", "mips_GRPZ:\n", "\tparameter value\n", "--------------------------------------------------------------------------------\n", "ATOB :\t18.168 (A/T)\n", "current :\t0.0002 (A)\n", "current_persistent :\t0.0002 (A)\n", "current_ramp_rate :\t0.18168 (A/s)\n", "current_target :\t0 (A)\n", "field :\t0 (T)\n", "field_persistent :\t0 (T)\n", "field_ramp_rate :\t0.01 (T/s)\n", "field_target :\t0 (T)\n", "ramp_status :\tHOLD \n", "voltage :\t0.0003 (V)\n" ] } ], "source": [ "mips.print_readable_snapshot(update=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Ramp examples" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### First example: invalid targets" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Can not set that\n" ] } ], "source": [ "mips.x_target(1) # so far, so good\n", "try:\n", " mips.y_target(0.5) # this takes us out of the unit sphere\n", "except ValueError as e:\n", " print(\"Can not set that\")" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Can not set that\n" ] } ], "source": [ "# reset and try in a different coordinate system\n", "mips.x_target(0)\n", "try:\n", " mips.r_target(1.1)\n", "except ValueError as e:\n", " print(\"Can not set that\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Second example: simul ramps to the origin\n", "\n", "First we ramp the field to Bx = 1, By = 0, Bz = 0, then rotate out to thea=46, phi=30, then finally ramp it down to zero while measuring r, theta, and phi." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### STEP A" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ramping X to 0.1 T, now at 0.1 T\n", "Ramping X to 0.1 T, now at 0.1 T\n", "Done ramping, now at 0.1 T\n" ] } ], "source": [ "mips.GRPX.field_ramp_rate(0.01)\n", "mips.GRPY.field_ramp_rate(0.01)\n", "mips.GRPZ.field_ramp_rate(0.01)\n", "\n", "mips.x_target(0.1)\n", "mips.y_target(0)\n", "mips.z_target(0)\n", "\n", "mips.ramp(mode='simul')\n", "\n", "# since simul mode is non-blocking, \n", "# we can read out during the ramp\n", "while mips.is_ramping():\n", " print(f'Ramping X to {mips.x_target()} T, now at {mips.x_measured()} T')\n", " sleep(1)\n", "sleep(1)\n", "print(f'Done ramping, now at {mips.x_measured()} T')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### STEP B\n", "\n", "Note that since the magnet itself has no notion of any other coordinate system than cartesian coordinates, it does **NOT** follow a path where r is constant. The user must **MANUALLY** ensure to break up a ramp where r is meant to be constant into sufficiently many small steps." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ramping... r: 0.100000 T, theta: 90.00, phi: -0.00\n", "Ramping... r: 0.100000 T, theta: 90.00, phi: 0.00\n", "Ramping... r: 0.099000 T, theta: 90.00, phi: 0.00\n", "Ramping... r: 0.084369 T, theta: 82.86, phi: 11.52\n", "Ramping... r: 0.076622 T, theta: 75.26, phi: 20.29\n", "Ramping... r: 0.077474 T, theta: 67.38, phi: 27.21\n", "Ramping... r: 0.080937 T, theta: 61.35, phi: 28.87\n", "Ramping... r: 0.087963 T, theta: 53.60, phi: 29.53\n", "Ramping... r: 0.093565 T, theta: 49.15, phi: 29.83\n", "Ramping... r: 0.097914 T, theta: 46.26, phi: 29.94\n", "Ramping... r: 0.099167 T, theta: 45.51, phi: 29.94\n", "Ramping... r: 0.099729 T, theta: 45.14, phi: 29.98\n", "Ramping... r: 0.099809 T, theta: 45.06, phi: 29.98\n", "Ramping... r: 0.099915 T, theta: 45.04, phi: 30.05\n", "Ramping... r: 0.099985 T, theta: 45.00, phi: 30.05\n", "Done... r: 0.099985 T, theta: 45.00, phi: 30.05\n" ] } ], "source": [ "mips.theta_target(45)\n", "mips.phi_target(30)\n", "mips.r_target(0.1)\n", "\n", "mips.ramp(mode='simul')\n", "\n", "while mips.is_ramping():\n", " print(f\"Ramping... r: {mips.r_measured():.6f} T, \"\n", " f\"theta: {mips.theta_measured():.2f}, \"\n", " f\"phi: {mips.phi_measured():.2f}\")\n", " sleep(1)\n", "print(f\"Done... r: {mips.r_measured():.6f} T, \"\n", " f\"theta: {mips.theta_measured():.2f}, \"\n", " f\"phi: {mips.phi_measured():.2f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### STEP C" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ramping... r: 0.099985 T, theta: 45.00, phi: 30.05\n", "Ramping... r: 0.099985 T, theta: 45.00, phi: 30.05\n", "Ramping... r: 0.099985 T, theta: 45.00, phi: 30.05\n", "Ramping... r: 0.079511 T, theta: 36.45, phi: 25.40\n", "Ramping... r: 0.060216 T, theta: 31.76, phi: 17.06\n", "Ramping... r: 0.045938 T, theta: 27.09, phi: 8.25\n", "Ramping... r: 0.033194 T, theta: 18.38, phi: 6.58\n", "Ramping... r: 0.021813 T, theta: 8.91, phi: 9.46\n", "Ramping... r: 0.009555 T, theta: 6.13, phi: 11.31\n", "Ramping... r: 0.002929 T, theta: 8.09, phi: 14.04\n", "Ramping... r: 0.001315 T, theta: 8.75, phi: 0.00\n", "Ramping... r: 0.000608 T, theta: 9.46, phi: 0.00\n", "Ramping... r: 0.000200 T, theta: 0.00, phi: 0.00\n", "Ramping... r: 0.000100 T, theta: 0.00, phi: 0.00\n", "Ramping... r: 0.000100 T, theta: 0.00, phi: 0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 180.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: -180.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: -180.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: -0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: -0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: -0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: -0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: -180.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 180.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 180.00\n", "Ramping... r: 0.000100 T, theta: 180.00, phi: -180.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: -0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: -0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 180.00\n", "Ramping... r: 0.000100 T, theta: 180.00, phi: 180.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 180.00\n", "Ramping... r: 0.000100 T, theta: 180.00, phi: 180.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: -0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 0.00\n", "Ramping... r: 0.000000 T, theta: 0.00, phi: 180.00\n", "Done... r: 0.000000 T, theta: 0.00, phi: 0.00\n" ] } ], "source": [ "mips.theta_target(45)\n", "mips.phi_target(30)\n", "mips.r_target(0)\n", "\n", "mips.ramp(mode='simul')\n", "\n", "# since simul mode is non-blocking, \n", "# we can read out during the ramp\n", "while mips.is_ramping():\n", " print(f\"Ramping... r: {mips.r_measured():.6f} T, \"\n", " f\"theta: {mips.theta_measured():.2f}, \"\n", " f\"phi: {mips.phi_measured():.2f}\")\n", " sleep(1)\n", "print(f\"Done... r: {mips.r_measured():.6f} T, \"\n", " f\"theta: {mips.theta_measured():.2f}, \"\n", " f\"phi: {mips.phi_measured():.2f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Third example: safe ramp away from the origin" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At the origin, we can not meaningfully **measure** what theta and phi is, but the target values are persistent.\n", "\n", "If we ramp up again and measure, we should thus get back to our target values. We use blocking safe ramp for this (just to also test/show a blocking ramp)." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Ramped back out again.\n", "Field values are: theta: 44.95982350797425, phi: 30.046435246810503\n" ] } ], "source": [ "mips.r_target(0.05)\n", "\n", "mips.ramp(mode='safe')\n", "\n", "print('Ramped back out again.')\n", "print(f'Field values are: theta: {mips.theta_measured()}, phi: {mips.phi_measured()}')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### That's it for now! Happy sweeping." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "# sweep back down for good measures\n", "mips.x_target(0)\n", "mips.y_target(0)\n", "mips.z_target(0)\n", "\n", "mips.ramp(mode='safe')\n", "\n", "mips.close()" ] } ], "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.5" }, "nbsphinx": { "execute": "never" } }, "nbformat": 4, "nbformat_minor": 2 }