Compensation for a non-linear charge sensor

We analyse the effect of a non-linear sensing dot on the value for the tunnel coupling obtained from the fitting of an inter-dot transition line. The sensing dot shape is simulated based on a Gaussian, while the data of the inter-dot transition is experimental data.

First we load all necessary packages

[1]:
import os
import qcodes
import matplotlib.pyplot as plt
import time
import numpy as np
import scipy

from qcodes.data.hdf5_format import HDF5Format

import qtt
import qtt.pgeometry
from qtt.data import load_example_dataset
from qtt.algorithms.functions import gaussian
from qtt.algorithms.tunneling import polmod_all_2slopes, fit_pol_all
from qtt.algorithms.chargesensor import DataLinearizer, correctChargeSensor
%matplotlib inline

np.set_printoptions(suppress=True, precision=3)
[2]:
def show_pol_fit(delta, signal, par_fit, fig=1):
    """ Show data of a polarization fit """
    plt.figure(fig)
    plt.clf()
    plt.plot(delta, signal, 'bo')
    plt.plot(delta, polmod_all_2slopes(delta, par_fit, kT), 'r')
    plt.title('Tunnel coupling: %.2f (ueV) = %.2f (GHz)' %
              (par_fit[0], par_fit[0] / h))
    plt.xlabel('Difference in chemical potentials (ueV)')
    _ = plt.ylabel('Signal (a.u.)')

Define physical constants and parameters

[3]:
h = 1e9*scipy.constants.h/(1e-6*scipy.constants.elementary_charge)  # Planck's constant in units [ueV/GHz]
kb = scipy.constants.k/(1e-6*scipy.constants.elementary_charge)  # [ueV/K], Boltzmann constant
kT = 10e-3 * kb  # effective electron temperature in ueV

Load example dataset and define signal of charge sensor

[4]:
dataset = load_example_dataset('polarization_line')

signal = np.array(dataset.default_parameter_array('signal'))
delta = np.array(dataset.default_parameter_array('signal').set_arrays[0])

# Define signal of the sensing dot
xs = np.arange(-600, 0, 3.)
ys = gaussian(xs, -300, std=70, amplitude=510, offset=2)
ys = gaussian(xs, -300, std=70, amplitude=510, offset=20)

Find range of sensing dot used

The correction to the non-linearity of the charge sensor is done by fitting a linear function in the region of interest.

[5]:
dl, results = correctChargeSensor(delta, signal, xs, ys, fig=100)
plt.plot(xs, ys, '.b', label='raw data of charge sensor')
plt.legend()
plt.title('Data of charge sensor', fontsize=16)
_ = plt.xlabel('Plunger [mV]')
_ = plt.ylabel('Signal (a.u.)')
fitCoulombPeaks: peak 0: position -300.00 max 530.00 valid 1
filterPeaks: 1 -> 1 good peaks
peakScores: noise factor 1.00
peakScores: 0: height 268.3 halfwidth 27.0, score 144.87
../../_images/notebooks_analysis_example_charge_sensor_10_1.png

Determine the corrected data points

[6]:
xsignal = dl.backward_curve(signal)
signal_corrected = dl.forward(xsignal)  # make sure data is in similar range

Fit the polarization line

The effect of the non-linear charge sensor is a 5% error in the estimated tunnel coupling.

[7]:
par_fit,_ , _ = fit_pol_all(delta, signal, kT, par_guess=None)
show_pol_fit(delta, signal, par_fit, fig=1)

par_fit_corrected, _, _ = fit_pol_all(delta, signal_corrected, kT)
show_pol_fit(delta, signal_corrected, par_fit_corrected, fig=2)

print('tunnel coupling: %.1f [GHz]' % (par_fit[0] / h))
print('tunnel coupling with compensation: %.1f [GHz]' % (par_fit_corrected[0] / h))
tunnel coupling: 4.9 [GHz]
tunnel coupling with compensation: 5.2 [GHz]
../../_images/notebooks_analysis_example_charge_sensor_15_1.png
../../_images/notebooks_analysis_example_charge_sensor_15_2.png
[8]:
print('### fitted parameters ###')
print(par_fit)
print(par_fit_corrected)
### fitted parameters ###
[ 20.16    1.969  99.64   -0.505  -0.442 300.373]
[ 21.38   -1.59  112.843  -0.558  -0.406 280.184]
[ ]: