Rake probe campaign for Irakli Nanobashvili

The campaign goal is to simultanously measure ion saturated current $I_{sat}$ and floating voltge $V_f$ profiles by the double rake probe.

The double rake probe diagnostic

This is the double rake probe:

Its wiki page is located here. 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.

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.

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.

Import basic libraries

To visualise and process the double rake probe data, first we import basic libraries, Numpy and Matplotlib.

In [1]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as pl

# Define measurement mode of the two pin rows
L_mode = 'Isat'
R_mode = 'Vf'

# Number of the test discharge; 0 means the last one
shot = 0

Prepare switching between two modes of operation

In the following, we define the various constants and plot necessities which are different in the floating and $I_{sat}$ mode.

In [2]:
# Constants converting collected voltages to physical quantities
const = {'Isat': 1/46.7,
         'Vf': 100}

# Y axis labels
labels = {'Isat': '$I_{sat}$ [A]',
          'Vf': '$V_f$ [V]'}

# Y axis limits
ylims = {'Isat': [-0.5e-3, 4e-3],
         'Vf': [-60, 30]}

Load double rake probe data

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.

In the following, we write a function to download the rake probe data.

In [3]:
from urllib.error import HTTPError # recognise the error stemming from missing data
import pandas as pd # for reading csv files

#Define an exception which will be raised if the data is missing and stop the notebook execution
class StopExecution(Exception):
    def _render_traceback_(self):
        pass

def get_data(shot, identifier):
    URL = "http://golem.fjfi.cvut.cz/shots/{shot}/Diagnostics/DoubleRakeProbe/{identifier}.csv"
    url = URL.format(shot=shot, identifier=identifier)
    try:
        df = pd.read_csv(url, names=['time', identifier], index_col='time')
    except HTTPError:
        print('File not found at %s. Aborting notebook execution.' % url)
        raise StopExecution
    t = np.array(df.index)
    data = np.transpose(np.array(df))[0]
    return t, data

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.

Load the discharge beginning and end

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.

In [4]:
from urllib.request import urlopen

def get_file(url, shot, silent=False):
    URL = 'http://golem.fjfi.cvut.cz/shots/%i/%s' % (shot, url)
    if not silent:
        print(URL)
    f = urlopen(URL)
    try:
        return np.loadtxt(f)
    except ValueError: # the data couldn't be converted to a row of numbers
        return np.genfromtxt(f)

t1 = get_file('Diagnostics/BasicDiagnostics/t_plasma_start', shot)
t2 = get_file('Diagnostics/BasicDiagnostics/t_plasma_end', shot)
print('Discharge %i: %.1f ms - %.1f ms' % (shot, t1, t2))
http://golem.fjfi.cvut.cz/shots/0/Diagnostics/BasicDiagnostics/t_plasma_start
http://golem.fjfi.cvut.cz/shots/0/Diagnostics/BasicDiagnostics/t_plasma_end
Discharge 0: 3.5 ms - 13.4 ms

Plot all the signals from the double rake probe pins

Next, we load the double rake probe data for the current discharge and plot them.

In [5]:
# Load the signals of all the rake probe pins
DRP_L = []
DRP_R = []
for i in range(1, 7):
    t, data = get_data(shot, 'DRP-L%i' % i)
    DRP_L.append(data * const[L_mode])
for i in range(1, 7):
    t, data = get_data(shot, 'DRP-R%i' % i)
    DRP_R.append(data * const[R_mode])
DRP_L = np.array(DRP_L)
DRP_R = np.array(DRP_R)

# Plot the rake probe pin signals
fig, axs = pl.subplots(6, 2, num=('All rake probe signals in the current discharge'), figsize=(9,9),
                       sharex=True)
for i in range(0, 6):
    axs[i, 0].plot(t*1000, DRP_L[i], label='DRP-L%i' % (i+1))
for i in range(0, 6):
    axs[i, 1].plot(t*1000, DRP_R[i], label='DRP-R%i' % (i+1))
fig.tight_layout()
fig.subplots_adjust(hspace=0, wspace=0.3)
for i in range(6):
    for j in range(2):
        mode = L_mode if j==0 else R_mode
        axs[i,j].legend(loc=2)
        axs[i,j].grid(True)
        axs[i,j].set_xlim(t1-3, t2+3)
        axs[i,j].set_ylim(ylims[mode])
        axs[i,j].axhline(c='k')
        axs[i,j].set_ylabel(labels[mode])

# Label the row pins
axs[0,0].set_title(L_mode)
axs[0,1].set_title(R_mode)
axs[5,0].set_xlabel('$t$ [ms]')
axs[5,1].set_xlabel('$t$ [ms]')
R_probe = get_file('Diagnostics/DoubleRakeProbe/Parameters/r_first_tip', shot)
fig.suptitle('$R_{\mathrm{first-pin}} = %i$ mm' % R_probe)

# Save the figure
pl.savefig('icon-fig')
http://golem.fjfi.cvut.cz/shots/0/Diagnostics/DoubleRakeProbe/Parameters/r_first_tip