sqil-core 0.0.2__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sqil_core/__init__.py +6 -2
- sqil_core/config.py +13 -0
- sqil_core/config_log.py +42 -0
- sqil_core/experiment/__init__.py +11 -0
- sqil_core/experiment/_analysis.py +95 -0
- sqil_core/experiment/_events.py +25 -0
- sqil_core/experiment/_experiment.py +553 -0
- sqil_core/experiment/data/plottr.py +778 -0
- sqil_core/experiment/helpers/_function_override_handler.py +111 -0
- sqil_core/experiment/helpers/_labone_wrappers.py +12 -0
- sqil_core/experiment/instruments/__init__.py +2 -0
- sqil_core/experiment/instruments/_instrument.py +190 -0
- sqil_core/experiment/instruments/drivers/SignalCore_SC5511A.py +515 -0
- sqil_core/experiment/instruments/local_oscillator.py +205 -0
- sqil_core/experiment/instruments/server.py +175 -0
- sqil_core/experiment/instruments/setup.yaml +21 -0
- sqil_core/experiment/instruments/zurich_instruments.py +55 -0
- sqil_core/fit/__init__.py +38 -0
- sqil_core/fit/_core.py +1084 -0
- sqil_core/fit/_fit.py +1191 -0
- sqil_core/fit/_guess.py +232 -0
- sqil_core/fit/_models.py +127 -0
- sqil_core/fit/_quality.py +266 -0
- sqil_core/resonator/__init__.py +13 -0
- sqil_core/resonator/_resonator.py +989 -0
- sqil_core/utils/__init__.py +85 -5
- sqil_core/utils/_analysis.py +415 -0
- sqil_core/utils/_const.py +105 -0
- sqil_core/utils/_formatter.py +259 -0
- sqil_core/utils/_plot.py +373 -0
- sqil_core/utils/_read.py +262 -0
- sqil_core/utils/_utils.py +164 -0
- {sqil_core-0.0.2.dist-info → sqil_core-1.0.0.dist-info}/METADATA +40 -7
- sqil_core-1.0.0.dist-info/RECORD +36 -0
- {sqil_core-0.0.2.dist-info → sqil_core-1.0.0.dist-info}/WHEEL +1 -1
- {sqil_core-0.0.2.dist-info → sqil_core-1.0.0.dist-info}/entry_points.txt +1 -1
- sqil_core/utils/analysis.py +0 -68
- sqil_core/utils/const.py +0 -38
- sqil_core/utils/formatter.py +0 -134
- sqil_core/utils/read.py +0 -156
- sqil_core-0.0.2.dist-info/RECORD +0 -10
sqil_core/utils/formatter.py
DELETED
@@ -1,134 +0,0 @@
|
|
1
|
-
from decimal import ROUND_DOWN, Decimal
|
2
|
-
|
3
|
-
import numpy as np
|
4
|
-
|
5
|
-
from .const import EXP_UNIT_MAP, PARAM_METADATA
|
6
|
-
from .read import read_json
|
7
|
-
|
8
|
-
|
9
|
-
def _cut_to_significant_digits(number, n):
|
10
|
-
"""Cut a number to n significant digits."""
|
11
|
-
if number == 0:
|
12
|
-
return 0 # Zero has no significant digits
|
13
|
-
d = Decimal(str(number))
|
14
|
-
shift = d.adjusted() # Get the exponent of the number
|
15
|
-
rounded = d.scaleb(-shift).quantize(
|
16
|
-
Decimal("1e-{0}".format(n - 1)), rounding=ROUND_DOWN
|
17
|
-
)
|
18
|
-
return float(rounded.scaleb(shift))
|
19
|
-
|
20
|
-
|
21
|
-
def format_number(
|
22
|
-
num: float | np.ndarray, precision: int = 3, unit: str = "", latex: bool = True
|
23
|
-
) -> str:
|
24
|
-
"""Format a number (or an array of numbers) in a nice way for printing.
|
25
|
-
|
26
|
-
Parameters
|
27
|
-
----------
|
28
|
-
num : float | np.ndarray
|
29
|
-
Input number (or array). Should not be rescaled,
|
30
|
-
e.g. input values in Hz, NOT GHz
|
31
|
-
precision : int
|
32
|
-
The number of digits of the output number. Must be >= 3.
|
33
|
-
unit : str, optional
|
34
|
-
Unit of measurement, by default ''
|
35
|
-
latex : bool, optional
|
36
|
-
Include Latex syntax, by default True
|
37
|
-
|
38
|
-
Returns
|
39
|
-
-------
|
40
|
-
str
|
41
|
-
Formatted number
|
42
|
-
"""
|
43
|
-
# Handle arrays
|
44
|
-
if isinstance(num, (list, np.ndarray)):
|
45
|
-
return [format_number(n, unit, latex) for n in num]
|
46
|
-
|
47
|
-
# Return if not a number
|
48
|
-
if not isinstance(num, (int, float, complex)):
|
49
|
-
return num
|
50
|
-
|
51
|
-
# Format number
|
52
|
-
exp_form = f"{num:.12e}"
|
53
|
-
base, exponent = exp_form.split("e")
|
54
|
-
# Make exponent a multiple of 3
|
55
|
-
base = float(base) * 10 ** (int(exponent) % 3)
|
56
|
-
exponent = (int(exponent) // 3) * 3
|
57
|
-
# Apply precision to the base
|
58
|
-
if precision < 3:
|
59
|
-
precision = 3
|
60
|
-
base_precise = _cut_to_significant_digits(
|
61
|
-
base, precision + 1
|
62
|
-
) # np.round(base, precision - (int(exponent) % 3))
|
63
|
-
base_precise = np.round(
|
64
|
-
base_precise, precision - len(str(base_precise).split(".")[0])
|
65
|
-
)
|
66
|
-
if int(base_precise) == float(base_precise):
|
67
|
-
base_precise = int(base_precise)
|
68
|
-
|
69
|
-
# Build string
|
70
|
-
if unit:
|
71
|
-
res = f"{base_precise}{'~' if latex else ' '}{EXP_UNIT_MAP[exponent]}{unit}"
|
72
|
-
else:
|
73
|
-
res = f"{base_precise}" + (f" x 10^{{{exponent}}}" if exponent != 0 else "")
|
74
|
-
return f"${res}$" if latex else res
|
75
|
-
|
76
|
-
|
77
|
-
def get_name_and_unit(param_id: str) -> str:
|
78
|
-
"""Get the name and unit of measurement of a prameter, e.g. Frequency [GHz].
|
79
|
-
|
80
|
-
Parameters
|
81
|
-
----------
|
82
|
-
param : str
|
83
|
-
Parameter ID, as defined in the param_dict.json file.
|
84
|
-
|
85
|
-
Returns
|
86
|
-
-------
|
87
|
-
str
|
88
|
-
Name and [unit]
|
89
|
-
"""
|
90
|
-
meta = PARAM_METADATA[param_id]
|
91
|
-
scale = meta["scale"] if "scale" in meta else 1
|
92
|
-
exponent = -(int(f"{scale:.0e}".split("e")[1]) // 3) * 3
|
93
|
-
return f"{meta['name']} [{EXP_UNIT_MAP[exponent]}{meta['unit']}]"
|
94
|
-
|
95
|
-
|
96
|
-
def get_x_id_by_plot_dim(exp_id: str, plot_dim: str, sweep_param: str | None) -> str:
|
97
|
-
if exp_id == "CW_onetone":
|
98
|
-
if plot_dim == "1":
|
99
|
-
return sweep_param or "ro_freq"
|
100
|
-
return "ro_freq"
|
101
|
-
|
102
|
-
|
103
|
-
def build_title(title: str, path: str, params: list[str]) -> str:
|
104
|
-
"""Build a plot title that includes the values of given parameters found in
|
105
|
-
the params_dict.json file, e.g. One tone with I = 0.5 mA.
|
106
|
-
|
107
|
-
Parameters
|
108
|
-
----------
|
109
|
-
title : str
|
110
|
-
Title of the plot to which the parameters will be appended.
|
111
|
-
|
112
|
-
path: str
|
113
|
-
Path to the param_dict.json file.
|
114
|
-
|
115
|
-
params : List[str]
|
116
|
-
List of keys of parameters in the param_dict.json file.
|
117
|
-
|
118
|
-
Returns
|
119
|
-
-------
|
120
|
-
str
|
121
|
-
The original title followed by parameter values.
|
122
|
-
"""
|
123
|
-
dic = read_json(f"{path}/param_dict.json")
|
124
|
-
title += " with "
|
125
|
-
for idx, param in enumerate(params):
|
126
|
-
if not (param in PARAM_METADATA.keys()) or not (param in dic):
|
127
|
-
title += f"{param} = ? & "
|
128
|
-
continue
|
129
|
-
meta = PARAM_METADATA[param]
|
130
|
-
value = format_number(dic[param], meta["unit"])
|
131
|
-
title += f"${meta['symbol']} =${value} & "
|
132
|
-
if idx % 2 == 0 and idx != 0:
|
133
|
-
title += "\n"
|
134
|
-
return title[0:-3]
|
sqil_core/utils/read.py
DELETED
@@ -1,156 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import os
|
3
|
-
|
4
|
-
import h5py
|
5
|
-
import numpy as np
|
6
|
-
|
7
|
-
from .const import PARAM_METADATA
|
8
|
-
|
9
|
-
|
10
|
-
def extract_h5_data(
|
11
|
-
path: str, keys: list[str] | None = None
|
12
|
-
) -> dict | tuple[np.ndarray, ...]:
|
13
|
-
"""Extract data at the given keys from an HDF5 file. If no keys are
|
14
|
-
given (None) returns the data field of the object.
|
15
|
-
|
16
|
-
Parameters
|
17
|
-
----------
|
18
|
-
path : str
|
19
|
-
path to the HDF5 file or a folder in which is contained a data.ddh5 file
|
20
|
-
keys : None or List, optional
|
21
|
-
list of keys to extract from file['data'], by default None
|
22
|
-
|
23
|
-
Returns
|
24
|
-
-------
|
25
|
-
Dict or Tuple[np.ndarray, ...]
|
26
|
-
The full data dictionary if keys = None.
|
27
|
-
The tuple with the requested keys otherwise.
|
28
|
-
|
29
|
-
Example
|
30
|
-
-------
|
31
|
-
Extract the data object from the dataset:
|
32
|
-
>>> data = extract_h5_data(path)
|
33
|
-
Extracting only 'amp' and 'phase' from the dataset:
|
34
|
-
>>> amp, phase = extract_h5_data(path, ['amp', 'phase'])
|
35
|
-
Extracting only 'phase':
|
36
|
-
>>> phase, = extract_h5_data(path, ['phase'])
|
37
|
-
"""
|
38
|
-
# If the path is to a folder open /data.ddh5
|
39
|
-
if os.path.isdir(path):
|
40
|
-
path = os.path.join(path, "data.ddh5")
|
41
|
-
|
42
|
-
with h5py.File(path, "r") as h5file:
|
43
|
-
data = h5file["data"]
|
44
|
-
data_keys = data.keys()
|
45
|
-
# Extract only the requested keys
|
46
|
-
if bool(keys) and (len(keys) > 0):
|
47
|
-
res = []
|
48
|
-
for key in keys:
|
49
|
-
key = str(key)
|
50
|
-
if (not bool(key)) | (key not in data_keys):
|
51
|
-
res.append([])
|
52
|
-
continue
|
53
|
-
res.append(np.array(data[key][:]))
|
54
|
-
return tuple(res)
|
55
|
-
# Extract the whole data dictionary
|
56
|
-
return _h5_to_dict(data)
|
57
|
-
|
58
|
-
|
59
|
-
def _h5_to_dict(obj) -> dict:
|
60
|
-
"""Convert h5 data into a dictionary"""
|
61
|
-
data_dict = {}
|
62
|
-
for key in obj.keys():
|
63
|
-
item = obj[key]
|
64
|
-
if isinstance(item, h5py.Dataset):
|
65
|
-
data_dict[key] = item[:]
|
66
|
-
elif isinstance(item, h5py.Group):
|
67
|
-
data_dict[key] = extract_h5_data(item)
|
68
|
-
return data_dict
|
69
|
-
|
70
|
-
|
71
|
-
def read_json(path: str) -> dict:
|
72
|
-
"""Reads a json file and returns the data as a dictionary."""
|
73
|
-
with open(path) as f:
|
74
|
-
dictionary = json.load(f)
|
75
|
-
return dictionary
|
76
|
-
|
77
|
-
|
78
|
-
class ParamInfo:
|
79
|
-
"""Parameter information for items of param_dict
|
80
|
-
|
81
|
-
Attributes:
|
82
|
-
id (str): param_dict key
|
83
|
-
value (any): the value of the parameter
|
84
|
-
name (str): full name of the parameter (e.g. Readout frequency)
|
85
|
-
symbol (str): symbol of the parameter in Latex notation (e.g. f_{RO})
|
86
|
-
unit (str): base unit of measurement (e.g. Hz)
|
87
|
-
scale (int): the scale that should be generally applied to raw data (e.g. 1e-9 to take raw Hz to GHz)
|
88
|
-
"""
|
89
|
-
|
90
|
-
def __init__(self, id, value):
|
91
|
-
self.id = id
|
92
|
-
self.value = value
|
93
|
-
if id in PARAM_METADATA:
|
94
|
-
meta = PARAM_METADATA[id]
|
95
|
-
else:
|
96
|
-
meta = {}
|
97
|
-
self.name = meta["name"] if "name" in meta else id
|
98
|
-
self.symbol = meta["symbol"] if "symbol" in meta else id
|
99
|
-
self.unit = meta["unit"] if "unit" in meta else ""
|
100
|
-
self.scale = meta["scale"] if "scale" in meta else 1
|
101
|
-
|
102
|
-
def to_dict(self):
|
103
|
-
"""Convert ParamInfo to a dictionary."""
|
104
|
-
return {
|
105
|
-
"id": self.id,
|
106
|
-
"value": self.value,
|
107
|
-
"name": self.name,
|
108
|
-
"symbol": self.symbol,
|
109
|
-
"unit": self.unit,
|
110
|
-
"scale": self.scale,
|
111
|
-
}
|
112
|
-
|
113
|
-
def __str__(self):
|
114
|
-
"""Return a JSON-formatted string of the object."""
|
115
|
-
return json.dumps(self.to_dict())
|
116
|
-
|
117
|
-
def __eq__(self, other):
|
118
|
-
if isinstance(other, ParamInfo):
|
119
|
-
return (self.id == other.id) & (self.value == other.value)
|
120
|
-
if isinstance(other, (int, float, complex, str)):
|
121
|
-
return self.value == other
|
122
|
-
return False
|
123
|
-
|
124
|
-
|
125
|
-
ParamDict = dict[str, ParamInfo | dict[str, ParamInfo]]
|
126
|
-
|
127
|
-
|
128
|
-
def _enrich_param_dict(param_dict: dict) -> ParamDict:
|
129
|
-
"""Add metadata to param_dict entries."""
|
130
|
-
res = {}
|
131
|
-
for key, value in param_dict.items():
|
132
|
-
if isinstance(value, dict):
|
133
|
-
# Recursive step for nested dictionaries
|
134
|
-
res[key] = _enrich_param_dict(value)
|
135
|
-
else:
|
136
|
-
res[key] = ParamInfo(key, value)
|
137
|
-
return res
|
138
|
-
|
139
|
-
|
140
|
-
def read_param_dict(path: str) -> ParamDict:
|
141
|
-
"""Read param_dict and include additional information for each entry.
|
142
|
-
|
143
|
-
Parameters
|
144
|
-
----------
|
145
|
-
path : str
|
146
|
-
Path to the file or a folder in which is contained a param_dict.json file
|
147
|
-
|
148
|
-
Returns
|
149
|
-
-------
|
150
|
-
ParamDict
|
151
|
-
The param_dict with additional metadata
|
152
|
-
"""
|
153
|
-
# If the path is to a folder open /param_dict.json
|
154
|
-
if os.path.isdir(path):
|
155
|
-
path = os.path.join(path, "param_dict.json")
|
156
|
-
return _enrich_param_dict(read_json(path))
|
sqil_core-0.0.2.dist-info/RECORD
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
sqil_core/__init__.py,sha256=JzMIz-0dEtF2rpf7ZBoIG4Ypd-0R4Xt87E8UKk6Was4,105
|
2
|
-
sqil_core/utils/__init__.py,sha256=KzCQaJ11jGja82QXC7lHI1MYKi4Gxz_qwxCr8oTxK3k,156
|
3
|
-
sqil_core/utils/analysis.py,sha256=CrtZ06KlNq-CcROoJiKgQWtUV9xnN3Ppv7QsUGFAY08,2106
|
4
|
-
sqil_core/utils/const.py,sha256=gfZL9MOzAxJ0BeKMxIelVN3yY0dG-Px9W5fwGiZRYfw,953
|
5
|
-
sqil_core/utils/formatter.py,sha256=VyYY2qGhWnt6TU3dOcwGpPUsNqMt-0TIZdzw3CnyCh4,4190
|
6
|
-
sqil_core/utils/read.py,sha256=BSbv-audrnILJceCMOTr8KWsjza-4OypGBiV1FVY4yM,4963
|
7
|
-
sqil_core-0.0.2.dist-info/METADATA,sha256=Zz1mChc4jhii-k8TLfS_oLlLTTDWyxUOLIh8w7_wp5s,2434
|
8
|
-
sqil_core-0.0.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
9
|
-
sqil_core-0.0.2.dist-info/entry_points.txt,sha256=2IYIJomhGZYKEZRBeCuH07ng82_2RzvrZOfhmBdhYxY,99
|
10
|
-
sqil_core-0.0.2.dist-info/RECORD,,
|