{ "cells": [ { "cell_type": "markdown", "metadata": { "golem": {} }, "source": [ "# Rake probe campaign for Irakli Nanobashvili\n", "\n", "The campaign goal is to simultanously measure ion saturated current $I_{sat}$ and floating voltge $V_f$ profiles by the double rake probe.\n", "\n", "\n", "## The double rake probe diagnostic\n", "\n", "This is the double rake probe:\n", "\n", "\n", "\n", "Its wiki page is located [here](http://golem.fjfi.cvut.cz/wiki/Diagnostics/ParticleFlux/DoubleRakeProbe/index). The double rake probe has two rows of pins (\"rakes\"), out of which the first 6 in each row are connected to the data acquisition system. The pin signals are called `DRP-R1` to `DRP-R6` and `DRP-L1` to `DRP-L6`.\n", "\n", "Like any Langmuir probe, the rake probe pins can be electrically insulated (measuring the floating potential $V_f$), biased to a negative voltage -100 V (measuring the ion saturated current $I_{sat}$), their biasing voltage may be swept (measuring $V_f$, $I_{sat}$ *and* the electron temperature $T_e$ if the $I$-$V$ characteristic is fitted with an exponential function) or they can perform other measurements.\n", "\n", "When measuring the ion saturated current $I_{sat}$, the data collected by the DAS have to be divided by 46.7, which is the resistance of the measuring capacitor. When measuring the floating potential $V_f$, the data have to be multiplied by 100, which is given by the voltage divider.\n", "\n", "\n", "## Import basic libraries\n", "\n", "To visualise and process the double rake probe data, first we import basic libraries, Numpy and Matplotlib." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "import numpy as np\n", "import matplotlib.pyplot as pl\n", "\n", "# Define measurement mode of the two pin rows\n", "L_mode = 'Isat'\n", "R_mode = 'Vf'\n", "\n", "# Number of the test discharge; 0 means the last one\n", "shot = 0" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Prepare switching between two modes of operation\n", "\n", "In the following, we define the various constants and plot necessities which are different in the floating and $I_{sat}$ mode." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Constants converting collected voltages to physical quantities\n", "const = {'Isat': 1/46.7,\n", " 'Vf': 100}\n", "\n", "# Y axis labels\n", "labels = {'Isat': '$I_{sat}$ [A]',\n", " 'Vf': '$V_f$ [V]'}\n", "\n", "# Y axis limits\n", "ylims = {'Isat': [-0.5e-3, 4e-3],\n", " 'Vf': [-60, 30]}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Load double rake probe data\n", "\n", "The data directory of the double rake probe is `http://golem.fjfi.cvut.cz/shots/{shot}/Diagnostics/DoubleRakeProbe/`, where `{shot}` stands for the discharge number. Note that in different sessions, the data may be saved elsewhere and it might be needed to update the `URL` variable in the following text. The data directory may be located from the individual shot homepage, and tends to be the same within a single session.\n", "\n", "In the following, we write a function to download the rake probe data." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from urllib.error import HTTPError # recognise the error stemming from missing data\n", "import pandas as pd # for reading csv files\n", "\n", "#Define an exception which will be raised if the data is missing and stop the notebook execution\n", "class StopExecution(Exception):\n", " def _render_traceback_(self):\n", " pass\n", "\n", "def get_data(shot, identifier):\n", " URL = \"http://golem.fjfi.cvut.cz/shots/{shot}/Diagnostics/DoubleRakeProbe/{identifier}.csv\"\n", " url = URL.format(shot=shot, identifier=identifier)\n", " try:\n", " df = pd.read_csv(url, names=['time', identifier], index_col='time')\n", " except HTTPError:\n", " print('File not found at %s. Aborting notebook execution.' % url)\n", " raise StopExecution\n", " t = np.array(df.index)\n", " data = np.transpose(np.array(df))[0]\n", " return t, data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Notice that the collected data has yet to be converted into physical units, that is, volts for $V_f$ and amperes for $I_{sat}$. This is done later in the code.\n", "\n", "## Load the discharge beginning and end\n", "\n", "Prior to plotting the double rake probe data, we'll write a little function which loads the time of the discharge beginning (plasma formation) and end (recombination). We'll use it to set the X axis limits later. Notice that `t1` and `t2` are in ms." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from urllib.request import urlopen\n", "\n", "def get_file(url, shot, silent=False):\n", " URL = 'http://golem.fjfi.cvut.cz/shots/%i/%s' % (shot, url)\n", " if not silent:\n", " print(URL)\n", " f = urlopen(URL)\n", " try:\n", " return np.loadtxt(f)\n", " except ValueError: # the data couldn't be converted to a row of numbers\n", " return np.genfromtxt(f)\n", "\n", "t1 = get_file('Diagnostics/BasicDiagnostics/t_plasma_start', shot)\n", "t2 = get_file('Diagnostics/BasicDiagnostics/t_plasma_end', shot)\n", "print('Discharge %i: %.1f ms - %.1f ms' % (shot, t1, t2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Plot all the signals from the double rake probe pins\n", "\n", "Next, we load the double rake probe data for the current discharge and plot them." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Load the signals of all the rake probe pins\n", "DRP_L = []\n", "DRP_R = []\n", "for i in range(1, 7):\n", " t, data = get_data(shot, 'DRP-L%i' % i)\n", " DRP_L.append(data * const[L_mode])\n", "for i in range(1, 7):\n", " t, data = get_data(shot, 'DRP-R%i' % i)\n", " DRP_R.append(data * const[R_mode])\n", "DRP_L = np.array(DRP_L)\n", "DRP_R = np.array(DRP_R)\n", "\n", "# Plot the rake probe pin signals\n", "fig, axs = pl.subplots(6, 2, num=('All rake probe signals in the current discharge'), figsize=(9,9),\n", " sharex=True)\n", "for i in range(0, 6):\n", " axs[i, 0].plot(t*1000, DRP_L[i], label='DRP-L%i' % (i+1))\n", "for i in range(0, 6):\n", " axs[i, 1].plot(t*1000, DRP_R[i], label='DRP-R%i' % (i+1))\n", "fig.tight_layout()\n", "fig.subplots_adjust(hspace=0, wspace=0.3)\n", "for i in range(6):\n", " for j in range(2):\n", " mode = L_mode if j==0 else R_mode\n", " axs[i,j].legend(loc=2)\n", " axs[i,j].grid(True)\n", " axs[i,j].set_xlim(t1-3, t2+3)\n", " axs[i,j].set_ylim(ylims[mode])\n", " axs[i,j].axhline(c='k')\n", " axs[i,j].set_ylabel(labels[mode])\n", "\n", "# Label the row pins\n", "axs[0,0].set_title(L_mode)\n", "axs[0,1].set_title(R_mode)\n", "axs[5,0].set_xlabel('$t$ [ms]')\n", "axs[5,1].set_xlabel('$t$ [ms]')\n", "R_probe = get_file('Diagnostics/DoubleRakeProbe/Parameters/r_first_tip', shot)\n", "fig.suptitle('$R_{\\mathrm{first-pin}} = %i$ mm' % R_probe)\n", "\n", "# Save the figure\n", "pl.savefig('icon-fig')" ] } ], "metadata": { "celltoolbar": "Edit 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.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }