This page was generated from docs/examples/DataSet/Paramtypes explained.ipynb. Interactive online version: .
Paramtypes explained¶
Internally in the SQLite database on disk, data are registered as being of one of (currently) four allowed types:
numeric
array
text
complex
This notebook seeks to exemplify when each type should be used, and how differently the Measurement
object treats data of each type.
We start with necessary imports, and then initialising our database and creating an experiment.
[1]:
import os
import time
import numpy as np
from qcodes.dataset import (
Measurement,
initialise_or_create_database_at,
load_or_create_experiment,
)
from qcodes.instrument_drivers.mock_instruments import DummyInstrument
from qcodes.parameters import ArrayParameter
Logging hadn't been started.
Activating auto-logging. Current session state plus future input saved.
Filename : /home/runner/.qcodes/logs/command_history.log
Mode : append
Output logging : True
Raw input log : False
Timestamping : True
State : active
Qcodes Logfile : /home/runner/.qcodes/logs/241006-16591-qcodes.log
[2]:
initialise_or_create_database_at(os.path.join(os.getcwd(), "paramtypes_explained.db"))
exp = load_or_create_experiment("paramtypes", sample_name="not_available")
Let us, now, create two dummy instruments to be used in our experiment.
[3]:
dac = DummyInstrument("dac", gates=["ch1", "ch2"])
SA = DummyInstrument("SA")
[4]:
# some array-like data types
class Spectrum(ArrayParameter):
def __init__(self, name, instrument):
self.N = 7
setpoints = (np.linspace(0, 1, self.N),)
super().__init__(
name=name,
instrument=instrument,
setpoints=setpoints,
shape=(20,),
label="Noisy spectrum",
unit="V/sqrt(Hz)",
setpoint_names=("Frequency",),
setpoint_units=("Hz",),
)
def get_raw(self):
return np.random.randn(self.N)
class MultiDimSpectrum(ArrayParameter):
def __init__(self, name, instrument):
self.start = 0
self.stop = 1
self.npts = (2, 5, 3)
sp1 = np.linspace(self.start, self.stop, self.npts[0])
sp2 = np.linspace(self.start, self.stop, self.npts[1])
sp3 = np.linspace(self.start, self.stop, self.npts[2])
setpoints = (
sp1,
np.tile(sp2, (len(sp1), 1)),
np.tile(sp3, (len(sp1), len(sp2), 1)),
)
super().__init__(
name=name,
instrument=instrument,
setpoints=setpoints,
shape=(100, 50, 20),
label="Flower Power Spectrum in 3D",
unit="V/sqrt(Hz)",
setpoint_names=("Frequency0", "Frequency1", "Frequency2"),
setpoint_units=("Hz", "Other Hz", "Third Hz"),
)
def get_raw(self):
a = self.npts[0]
b = self.npts[1]
c = self.npts[2]
return np.reshape(np.arange(a * b * c), (a, b, c))
# a string-valued parameter
def dac1_too_high():
return "Too high" if dac.ch1() > 5 else "OK"
Finally, we add our parameters to the dummy instruments:
[5]:
dac.add_parameter("control", get_cmd=dac1_too_high)
SA.add_parameter("spectrum", parameter_class=Spectrum)
SA.add_parameter("spectrum3D", parameter_class=MultiDimSpectrum)
2024-10-06 08:26:26,152 ¦ py.warnings ¦ WARNING ¦ warnings ¦ _showwarnmsg ¦ 110 ¦ /opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/qcodes/instrument/instrument_base.py:172: QCoDeSDeprecationWarning: Parameter spectrum on instrument SA does not correctly pass kwargs to its baseclass. A Parameter class must take `**kwargs` and forward them to its baseclass.
warnings.warn(
2024-10-06 08:26:26,153 ¦ py.warnings ¦ WARNING ¦ warnings ¦ _showwarnmsg ¦ 110 ¦ /opt/hostedtoolcache/Python/3.11.10/x64/lib/python3.11/site-packages/qcodes/instrument/instrument_base.py:172: QCoDeSDeprecationWarning: Parameter spectrum3D on instrument SA does not correctly pass kwargs to its baseclass. A Parameter class must take `**kwargs` and forward them to its baseclass.
warnings.warn(
[5]:
<__main__.MultiDimSpectrum: spectrum3D at 139838766392080>
Numeric¶
The numeric
datatype is simply a number. Data registered with this type are saved as individual numbers. This is the default datatype when registering parameters.
Numeric example 1¶
In this example, all parameters get registered as numeric
type. This entails that the array in unraveled and inserted point-by-point.
[6]:
meas = Measurement(exp=exp)
meas.register_parameter(dac.ch1)
meas.register_parameter(SA.spectrum, setpoints=(dac.ch1,))
t0 = time.perf_counter()
with meas.run() as datasaver:
for dac_v in np.linspace(0, 2, 5):
dac.ch1(dac_v)
datasaver.add_result((dac.ch1, dac_v), (SA.spectrum, SA.spectrum()))
t1 = time.perf_counter()
print(f"Finished run in {(t1-t0):.3f} s")
dataset1 = datasaver.dataset
Starting experimental run with id: 1.
Finished run in 0.016 s
The data may be retrieved using the get_parameter_data
method. This function will bring back the data in a way that reflects the datastructure as it is stored.
[7]:
dataset1.get_parameter_data()
[7]:
{'SA_spectrum': {'SA_spectrum': array([[ 1.44843017, -1.65046449, -2.25466855, 0.41480377, -1.1726757 ,
0.40209088, -0.59149401],
[ 0.64205298, 0.60722855, 0.43143444, 1.38744989, -0.91286672,
-0.90260246, 1.39591179],
[ 2.52482021, 0.04959441, 0.86115218, -1.10993684, 0.12214949,
0.01157972, 1.51004132],
[-0.5395737 , 1.87468598, -0.78307165, 1.07885827, -0.62126678,
1.95191843, 1.365849 ],
[-1.2622564 , 3.10917681, -1.40353404, 1.4681986 , 0.60606648,
-1.67685743, 0.1993829 ]]),
'dac_ch1': array([[0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5],
[1. , 1. , 1. , 1. , 1. , 1. , 1. ],
[1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5],
[2. , 2. , 2. , 2. , 2. , 2. , 2. ]]),
'SA_Frequency': array([[0. , 0.16666667, 0.33333333, 0.5 , 0.66666667,
0.83333333, 1. ],
[0. , 0.16666667, 0.33333333, 0.5 , 0.66666667,
0.83333333, 1. ],
[0. , 0.16666667, 0.33333333, 0.5 , 0.66666667,
0.83333333, 1. ],
[0. , 0.16666667, 0.33333333, 0.5 , 0.66666667,
0.83333333, 1. ],
[0. , 0.16666667, 0.33333333, 0.5 , 0.66666667,
0.83333333, 1. ]])}}
Array¶
The array
paramtype stores data as binary blobs in the database. Insertion is faster (asymptotically much faster) this way, but the data are “dead” to SQL queries inside the database. Be informed that a BLOB in sqlite has a default max length limit set at 1 billion (1,000,000,000) bytes (for more information, refer to Sqlite docs).
Array example 1¶
Let us repeat the above measurement, but this time using array
paramtypes.
[8]:
meas = Measurement(exp=exp)
meas.register_parameter(dac.ch1)
meas.register_parameter(SA.spectrum, setpoints=(dac.ch1,), paramtype="array")
t0 = time.perf_counter()
with meas.run() as datasaver:
for dac_v in np.linspace(0, 2, 5):
dac.ch1(dac_v)
datasaver.add_result((dac.ch1, dac_v), (SA.spectrum, SA.spectrum()))
t1 = time.perf_counter()
print(f"Finished run in {(t1-t0):.3f} s")
dataset2 = datasaver.dataset
Starting experimental run with id: 2.
Finished run in 0.014 s
[9]:
dataset2.get_parameter_data()
[9]:
{'SA_spectrum': {'SA_spectrum': array([[-1.10327632, 0.6482124 , -0.56198647, 0.96299112, 0.23375117,
0.55662253, -0.19798479],
[ 1.84733715, -2.97827451, 1.3084027 , -0.39991898, 0.00903446,
0.25889713, 0.6124456 ],
[-2.22083808, -0.92969076, -0.10814209, 0.9448846 , 0.67833312,
0.33669985, 0.91605089],
[ 0.56290623, -1.34107981, 0.06062822, -0.91099379, 0.38313828,
-1.08215912, 1.44915751],
[ 0.76017712, 0.66535657, 0.40337856, -0.14928641, -0.66095006,
1.00955277, -0.60407545]]),
'dac_ch1': array([[0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5],
[1. , 1. , 1. , 1. , 1. , 1. , 1. ],
[1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5],
[2. , 2. , 2. , 2. , 2. , 2. , 2. ]]),
'SA_Frequency': array([[0. , 0.16666667, 0.33333333, 0.5 , 0.66666667,
0.83333333, 1. ],
[0. , 0.16666667, 0.33333333, 0.5 , 0.66666667,
0.83333333, 1. ],
[0. , 0.16666667, 0.33333333, 0.5 , 0.66666667,
0.83333333, 1. ],
[0. , 0.16666667, 0.33333333, 0.5 , 0.66666667,
0.83333333, 1. ],
[0. , 0.16666667, 0.33333333, 0.5 , 0.66666667,
0.83333333, 1. ]])}}
Array example 2¶
When storing multidimensional array
data (think: Alazar cards), both numeric
and array
types can be used.
[10]:
meas = Measurement(exp=exp)
meas.register_parameter(SA.spectrum3D, paramtype="array")
with meas.run() as datasaver:
datasaver.add_result((SA.spectrum3D, SA.spectrum3D()))
dataset3 = datasaver.dataset
Starting experimental run with id: 3.
The data come out the way we expect them to.
[11]:
dataset3.get_parameter_data()
[11]:
{'SA_spectrum3D': {'SA_spectrum3D': array([[[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]],
[[15, 16, 17],
[18, 19, 20],
[21, 22, 23],
[24, 25, 26],
[27, 28, 29]]]]),
'SA_Frequency0': array([[[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]]]),
'SA_Frequency1': array([[[[0. , 0. , 0. ],
[0.25, 0.25, 0.25],
[0.5 , 0.5 , 0.5 ],
[0.75, 0.75, 0.75],
[1. , 1. , 1. ]],
[[0. , 0. , 0. ],
[0.25, 0.25, 0.25],
[0.5 , 0.5 , 0.5 ],
[0.75, 0.75, 0.75],
[1. , 1. , 1. ]]]]),
'SA_Frequency2': array([[[[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ]],
[[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ]]]])}}
Array example 3¶
For completeness, here, we provide an example where the multidimensional array has an auxiliary setpoint.
[12]:
meas = Measurement(exp=exp)
meas.register_parameter(dac.ch1)
meas.register_parameter(SA.spectrum3D, paramtype="array", setpoints=(dac.ch1,))
with meas.run() as datasaver:
for dac_v in [3, 4, 5]:
dac.ch1(dac_v)
datasaver.add_result((dac.ch1, dac_v), (SA.spectrum3D, SA.spectrum3D()))
dataset4 = datasaver.dataset
Starting experimental run with id: 4.
[13]:
dataset4.get_parameter_data()
[13]:
{'SA_spectrum3D': {'SA_spectrum3D': array([[[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]],
[[15, 16, 17],
[18, 19, 20],
[21, 22, 23],
[24, 25, 26],
[27, 28, 29]]],
[[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]],
[[15, 16, 17],
[18, 19, 20],
[21, 22, 23],
[24, 25, 26],
[27, 28, 29]]],
[[[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11],
[12, 13, 14]],
[[15, 16, 17],
[18, 19, 20],
[21, 22, 23],
[24, 25, 26],
[27, 28, 29]]]]),
'dac_ch1': array([[[[3., 3., 3.],
[3., 3., 3.],
[3., 3., 3.],
[3., 3., 3.],
[3., 3., 3.]],
[[3., 3., 3.],
[3., 3., 3.],
[3., 3., 3.],
[3., 3., 3.],
[3., 3., 3.]]],
[[[4., 4., 4.],
[4., 4., 4.],
[4., 4., 4.],
[4., 4., 4.],
[4., 4., 4.]],
[[4., 4., 4.],
[4., 4., 4.],
[4., 4., 4.],
[4., 4., 4.],
[4., 4., 4.]]],
[[[5., 5., 5.],
[5., 5., 5.],
[5., 5., 5.],
[5., 5., 5.],
[5., 5., 5.]],
[[5., 5., 5.],
[5., 5., 5.],
[5., 5., 5.],
[5., 5., 5.],
[5., 5., 5.]]]]),
'SA_Frequency0': array([[[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]],
[[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]],
[[[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]],
[[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]]]]),
'SA_Frequency1': array([[[[0. , 0. , 0. ],
[0.25, 0.25, 0.25],
[0.5 , 0.5 , 0.5 ],
[0.75, 0.75, 0.75],
[1. , 1. , 1. ]],
[[0. , 0. , 0. ],
[0.25, 0.25, 0.25],
[0.5 , 0.5 , 0.5 ],
[0.75, 0.75, 0.75],
[1. , 1. , 1. ]]],
[[[0. , 0. , 0. ],
[0.25, 0.25, 0.25],
[0.5 , 0.5 , 0.5 ],
[0.75, 0.75, 0.75],
[1. , 1. , 1. ]],
[[0. , 0. , 0. ],
[0.25, 0.25, 0.25],
[0.5 , 0.5 , 0.5 ],
[0.75, 0.75, 0.75],
[1. , 1. , 1. ]]],
[[[0. , 0. , 0. ],
[0.25, 0.25, 0.25],
[0.5 , 0.5 , 0.5 ],
[0.75, 0.75, 0.75],
[1. , 1. , 1. ]],
[[0. , 0. , 0. ],
[0.25, 0.25, 0.25],
[0.5 , 0.5 , 0.5 ],
[0.75, 0.75, 0.75],
[1. , 1. , 1. ]]]]),
'SA_Frequency2': array([[[[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ]],
[[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ]]],
[[[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ]],
[[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ]]],
[[[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ]],
[[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ],
[0. , 0.5, 1. ]]]])}}
Text¶
Text is strings. Sometimes it may be useful to capture categorial data that is represented as string values, or a log message, or else.
Note that the paramtype
setting is important. The datasaver will not allow to save numeric
data for a parameter that was registered as text
. The opposite it also true: the datasaver will not allow to save strings for a parameter what was registered as non-text
(numeric
or array
).
[14]:
meas = Measurement(exp=exp)
meas.register_parameter(dac.ch1)
meas.register_parameter(dac.control, setpoints=(dac.ch1,), paramtype="text")
with meas.run() as datasaver:
for dac_v in np.linspace(4, 6, 10):
dac.ch1(dac_v)
datasaver.add_result((dac.ch1, dac_v), (dac.control, dac.control()))
dataset5 = datasaver.dataset
Starting experimental run with id: 5.
[15]:
dataset5.get_parameter_data()
[15]:
{'dac_control': {'dac_control': array(['OK', 'OK', 'OK', 'OK', 'OK', 'Too high', 'Too high', 'Too high',
'Too high', 'Too high'], dtype='<U8'),
'dac_ch1': array([4. , 4.22222222, 4.44444444, 4.66666667, 4.88888889,
5.11111111, 5.33333333, 5.55555556, 5.77777778, 6. ])}}
[ ]: