sqil-core 0.0.2__tar.gz → 1.0.0__tar.gz
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-0.0.2 → sqil_core-1.0.0}/PKG-INFO +40 -7
- {sqil_core-0.0.2 → sqil_core-1.0.0}/README.md +27 -3
- {sqil_core-0.0.2 → sqil_core-1.0.0}/pyproject.toml +15 -5
- sqil_core-1.0.0/sqil_core/__init__.py +7 -0
- sqil_core-1.0.0/sqil_core/config.py +13 -0
- sqil_core-1.0.0/sqil_core/config_log.py +42 -0
- sqil_core-1.0.0/sqil_core/experiment/__init__.py +11 -0
- sqil_core-1.0.0/sqil_core/experiment/_analysis.py +95 -0
- sqil_core-1.0.0/sqil_core/experiment/_events.py +25 -0
- sqil_core-1.0.0/sqil_core/experiment/_experiment.py +553 -0
- sqil_core-1.0.0/sqil_core/experiment/data/plottr.py +778 -0
- sqil_core-1.0.0/sqil_core/experiment/helpers/_function_override_handler.py +111 -0
- sqil_core-1.0.0/sqil_core/experiment/helpers/_labone_wrappers.py +12 -0
- sqil_core-1.0.0/sqil_core/experiment/instruments/__init__.py +2 -0
- sqil_core-1.0.0/sqil_core/experiment/instruments/_instrument.py +190 -0
- sqil_core-1.0.0/sqil_core/experiment/instruments/drivers/SignalCore_SC5511A.py +515 -0
- sqil_core-1.0.0/sqil_core/experiment/instruments/local_oscillator.py +205 -0
- sqil_core-1.0.0/sqil_core/experiment/instruments/server.py +175 -0
- sqil_core-1.0.0/sqil_core/experiment/instruments/setup.yaml +21 -0
- sqil_core-1.0.0/sqil_core/experiment/instruments/zurich_instruments.py +55 -0
- sqil_core-1.0.0/sqil_core/fit/__init__.py +38 -0
- sqil_core-1.0.0/sqil_core/fit/_core.py +1084 -0
- sqil_core-1.0.0/sqil_core/fit/_fit.py +1191 -0
- sqil_core-1.0.0/sqil_core/fit/_guess.py +232 -0
- sqil_core-1.0.0/sqil_core/fit/_models.py +127 -0
- sqil_core-1.0.0/sqil_core/fit/_quality.py +266 -0
- sqil_core-1.0.0/sqil_core/resonator/__init__.py +13 -0
- sqil_core-1.0.0/sqil_core/resonator/_resonator.py +989 -0
- sqil_core-1.0.0/sqil_core/utils/__init__.py +86 -0
- sqil_core-1.0.0/sqil_core/utils/_analysis.py +415 -0
- sqil_core-1.0.0/sqil_core/utils/_const.py +105 -0
- sqil_core-1.0.0/sqil_core/utils/_formatter.py +259 -0
- sqil_core-1.0.0/sqil_core/utils/_plot.py +373 -0
- sqil_core-1.0.0/sqil_core/utils/_read.py +262 -0
- sqil_core-1.0.0/sqil_core/utils/_utils.py +164 -0
- sqil_core-0.0.2/sqil_core/__init__.py +0 -3
- sqil_core-0.0.2/sqil_core/utils/__init__.py +0 -6
- sqil_core-0.0.2/sqil_core/utils/analysis.py +0 -68
- sqil_core-0.0.2/sqil_core/utils/const.py +0 -38
- sqil_core-0.0.2/sqil_core/utils/formatter.py +0 -134
- sqil_core-0.0.2/sqil_core/utils/read.py +0 -156
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.3
|
2
2
|
Name: sqil-core
|
3
|
-
Version: 0.0
|
3
|
+
Version: 1.0.0
|
4
4
|
Summary: The codebase of the SQIL group in EPFL
|
5
5
|
Author: Andrea Duina
|
6
6
|
Requires-Python: >=3.10,<4.0
|
@@ -9,12 +9,21 @@ Classifier: Programming Language :: Python :: 3.10
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.11
|
10
10
|
Classifier: Programming Language :: Python :: 3.12
|
11
11
|
Classifier: Programming Language :: Python :: 3.13
|
12
|
+
Requires-Dist: blinker (>=1.9.0,<2.0.0)
|
12
13
|
Requires-Dist: h5py (>=3.12.1,<4.0.0)
|
13
14
|
Requires-Dist: isort (==5.9.3)
|
15
|
+
Requires-Dist: laboneq (>=2.54.0,<3.0.0)
|
16
|
+
Requires-Dist: laboneq-applications (>=2.4.0,<3.0.0)
|
17
|
+
Requires-Dist: lmfit (>=1.3.2,<2.0.0)
|
14
18
|
Requires-Dist: matplotlib (>=3.9.3,<4.0.0)
|
15
|
-
Requires-Dist:
|
19
|
+
Requires-Dist: mpld3 (>=0.5.10,<0.6.0)
|
20
|
+
Requires-Dist: numpy (>=2.2.3,<3.0.0)
|
21
|
+
Requires-Dist: plottr (>=0.14.0,<0.15.0)
|
22
|
+
Requires-Dist: pyro5 (>=5.15,<6.0)
|
23
|
+
Requires-Dist: qcodes (>=0.51.0,<0.52.0)
|
24
|
+
Requires-Dist: qcodes-contrib-drivers (>=0.23.0,<0.24.0)
|
16
25
|
Requires-Dist: scipy (>=1.14.1,<2.0.0)
|
17
|
-
Requires-Dist:
|
26
|
+
Requires-Dist: tabulate (>=0.9.0,<0.10.0)
|
18
27
|
Description-Content-Type: text/markdown
|
19
28
|
|
20
29
|
# For users
|
@@ -38,34 +47,44 @@ path = 'path to your data folder'
|
|
38
47
|
mag, phase, freq = sqil.extract_h5_data(path, ['mag_dB', 'phase', 'ro_freq'])
|
39
48
|
```
|
40
49
|
|
50
|
+
## Documentation
|
51
|
+
You can find the documentation for this package [here](https://sqil-epfl.github.io/sqil-core/)
|
52
|
+
|
41
53
|
# For developers
|
42
54
|
|
43
55
|
## Development
|
44
56
|
|
45
57
|
1. **Install poetry if you haven't already**
|
58
|
+
|
46
59
|
```bash
|
47
60
|
$ pip install poetry
|
61
|
+
$ pip install poetry-plugin-shell
|
48
62
|
```
|
49
63
|
|
50
64
|
2. **Install the required packages using poetry**
|
65
|
+
|
51
66
|
```bash
|
52
67
|
$ poetry install
|
53
68
|
```
|
54
69
|
|
55
70
|
3. **Install the pre-commit hooks**
|
56
|
-
If you are on windows you need to install git ([https://git-scm.com/downloads](here)) and add it to your windows PATH.
|
57
|
-
After the installation open a new terminal.
|
71
|
+
If you are on windows you need to install git ([https://git-scm.com/downloads](here)) and add it to your windows PATH.
|
72
|
+
After the installation open a new terminal.
|
73
|
+
|
58
74
|
```bash
|
59
75
|
$ poetry run pre-commit install
|
60
76
|
```
|
77
|
+
|
61
78
|
This will check if your python files are formatted correctly when you try to commit.
|
62
79
|
If that's not the case the commit will be canceled and the files will be automatically formatted.
|
63
80
|
Then you'll have to add and commit again the new files.
|
64
81
|
|
65
82
|
4. **Start the virtual environment**
|
83
|
+
|
66
84
|
```bash
|
67
85
|
$ poetry shell
|
68
86
|
```
|
87
|
+
|
69
88
|
To exit the virtual environment just use `exit`
|
70
89
|
|
71
90
|
#### Test your changes
|
@@ -91,7 +110,11 @@ $ poetry run build
|
|
91
110
|
$ pip install PATH_TO_SQIL_CORE_FOLDER/dist/SQIL_CORE-VERSION.whl
|
92
111
|
```
|
93
112
|
|
94
|
-
If you're
|
113
|
+
If you're testing a new function remember to import it in the folder's `__init__.py` file.
|
114
|
+
|
115
|
+
|
116
|
+
If you're using a jupyter notebook remember to restart the kernel.
|
117
|
+
|
95
118
|
|
96
119
|
## Build
|
97
120
|
|
@@ -99,6 +122,16 @@ If you're using a jupyter notebook remember to restart the kernel
|
|
99
122
|
$ poetry run build
|
100
123
|
```
|
101
124
|
|
125
|
+
## Publish
|
126
|
+
|
127
|
+
To publish version X.X.X run the commands below. This will trigger a GitHub action that deploys to release to PyPi (pip) and GitHub.
|
128
|
+
Remember also to change the version number in the `pyproject.toml` file.
|
129
|
+
|
130
|
+
```bash
|
131
|
+
$ git tag vX.X.X
|
132
|
+
$ git push origin vX.X.X
|
133
|
+
```
|
134
|
+
|
102
135
|
## Docs
|
103
136
|
|
104
137
|
Serve docs
|
@@ -19,34 +19,44 @@ path = 'path to your data folder'
|
|
19
19
|
mag, phase, freq = sqil.extract_h5_data(path, ['mag_dB', 'phase', 'ro_freq'])
|
20
20
|
```
|
21
21
|
|
22
|
+
## Documentation
|
23
|
+
You can find the documentation for this package [here](https://sqil-epfl.github.io/sqil-core/)
|
24
|
+
|
22
25
|
# For developers
|
23
26
|
|
24
27
|
## Development
|
25
28
|
|
26
29
|
1. **Install poetry if you haven't already**
|
30
|
+
|
27
31
|
```bash
|
28
32
|
$ pip install poetry
|
33
|
+
$ pip install poetry-plugin-shell
|
29
34
|
```
|
30
35
|
|
31
36
|
2. **Install the required packages using poetry**
|
37
|
+
|
32
38
|
```bash
|
33
39
|
$ poetry install
|
34
40
|
```
|
35
41
|
|
36
42
|
3. **Install the pre-commit hooks**
|
37
|
-
If you are on windows you need to install git ([https://git-scm.com/downloads](here)) and add it to your windows PATH.
|
38
|
-
After the installation open a new terminal.
|
43
|
+
If you are on windows you need to install git ([https://git-scm.com/downloads](here)) and add it to your windows PATH.
|
44
|
+
After the installation open a new terminal.
|
45
|
+
|
39
46
|
```bash
|
40
47
|
$ poetry run pre-commit install
|
41
48
|
```
|
49
|
+
|
42
50
|
This will check if your python files are formatted correctly when you try to commit.
|
43
51
|
If that's not the case the commit will be canceled and the files will be automatically formatted.
|
44
52
|
Then you'll have to add and commit again the new files.
|
45
53
|
|
46
54
|
4. **Start the virtual environment**
|
55
|
+
|
47
56
|
```bash
|
48
57
|
$ poetry shell
|
49
58
|
```
|
59
|
+
|
50
60
|
To exit the virtual environment just use `exit`
|
51
61
|
|
52
62
|
#### Test your changes
|
@@ -72,7 +82,11 @@ $ poetry run build
|
|
72
82
|
$ pip install PATH_TO_SQIL_CORE_FOLDER/dist/SQIL_CORE-VERSION.whl
|
73
83
|
```
|
74
84
|
|
75
|
-
If you're
|
85
|
+
If you're testing a new function remember to import it in the folder's `__init__.py` file.
|
86
|
+
|
87
|
+
|
88
|
+
If you're using a jupyter notebook remember to restart the kernel.
|
89
|
+
|
76
90
|
|
77
91
|
## Build
|
78
92
|
|
@@ -80,6 +94,16 @@ If you're using a jupyter notebook remember to restart the kernel
|
|
80
94
|
$ poetry run build
|
81
95
|
```
|
82
96
|
|
97
|
+
## Publish
|
98
|
+
|
99
|
+
To publish version X.X.X run the commands below. This will trigger a GitHub action that deploys to release to PyPi (pip) and GitHub.
|
100
|
+
Remember also to change the version number in the `pyproject.toml` file.
|
101
|
+
|
102
|
+
```bash
|
103
|
+
$ git tag vX.X.X
|
104
|
+
$ git push origin vX.X.X
|
105
|
+
```
|
106
|
+
|
83
107
|
## Docs
|
84
108
|
|
85
109
|
Serve docs
|
@@ -1,23 +1,32 @@
|
|
1
1
|
[tool.poetry]
|
2
2
|
name = "sqil-core"
|
3
|
-
version = "
|
3
|
+
version = "v1.0.0"
|
4
4
|
description = "The codebase of the SQIL group in EPFL"
|
5
5
|
authors = ["Andrea Duina"]
|
6
6
|
readme = "README.md"
|
7
7
|
|
8
8
|
[tool.poetry.scripts]
|
9
9
|
build = "scripts:build"
|
10
|
-
docs-
|
10
|
+
docs-dev = "scripts:docs_dev"
|
11
11
|
docs-build = "scripts:docs_build"
|
12
12
|
|
13
13
|
[tool.poetry.dependencies]
|
14
|
-
python = "
|
15
|
-
numpy = "^2.2.0"
|
14
|
+
python = ">=3.10,<4.0"
|
16
15
|
scipy = "^1.14.1"
|
17
16
|
h5py = "^3.12.1"
|
18
17
|
matplotlib = "^3.9.3"
|
19
|
-
seaborn = "^0.13.2"
|
20
18
|
isort = "5.9.3"
|
19
|
+
tabulate = "^0.9.0"
|
20
|
+
numpy = "^2.2.3"
|
21
|
+
lmfit = "^1.3.2"
|
22
|
+
pyro5 = "^5.15"
|
23
|
+
qcodes = "^0.51.0"
|
24
|
+
qcodes-contrib-drivers = "^0.23.0"
|
25
|
+
blinker = "^1.9.0"
|
26
|
+
laboneq-applications = "^2.4.0"
|
27
|
+
plottr = "^0.14.0"
|
28
|
+
laboneq = "^2.54.0"
|
29
|
+
mpld3 = "^0.5.10"
|
21
30
|
|
22
31
|
|
23
32
|
[tool.poetry.group.dev.dependencies]
|
@@ -27,6 +36,7 @@ mkdocs = "^1.6.1"
|
|
27
36
|
mkdocs-material = "^9.5.48"
|
28
37
|
mkdocstrings-python = "^1.12.2"
|
29
38
|
pytest = "^8.3.4"
|
39
|
+
mkdocs-jupyter = "^0.25.1"
|
30
40
|
|
31
41
|
[build-system]
|
32
42
|
requires = ["poetry-core"]
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import logging
|
2
|
+
|
3
|
+
from colorama import Fore, Style, init
|
4
|
+
|
5
|
+
# Initialize Colorama
|
6
|
+
init(autoreset=True, strip=False, convert=False)
|
7
|
+
|
8
|
+
|
9
|
+
class SqilFormatter(logging.Formatter):
|
10
|
+
FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
|
11
|
+
|
12
|
+
COLOR_MAP = {
|
13
|
+
"DEBUG": Fore.BLUE,
|
14
|
+
"INFO": Fore.GREEN,
|
15
|
+
"WARNING": Fore.YELLOW,
|
16
|
+
"ERROR": Fore.RED,
|
17
|
+
"CRITICAL": Fore.RED + Style.BRIGHT,
|
18
|
+
}
|
19
|
+
|
20
|
+
def format(self, record):
|
21
|
+
log_color = self.COLOR_MAP.get(record.levelname, "")
|
22
|
+
record.levelname = f"{log_color}{record.levelname}{Style.RESET_ALL}"
|
23
|
+
return super().format(record)
|
24
|
+
|
25
|
+
|
26
|
+
class SqilLogger(logging.Logger):
|
27
|
+
# By default show the stack trace when errors are logged
|
28
|
+
def error(self, msg, *args, exc_info=True, **kwargs):
|
29
|
+
super().error(msg, *args, exc_info=exc_info, **kwargs)
|
30
|
+
|
31
|
+
|
32
|
+
logging.setLoggerClass(SqilLogger)
|
33
|
+
logger = logging.getLogger("sqil_logger")
|
34
|
+
logger.setLevel(logging.DEBUG)
|
35
|
+
|
36
|
+
console_handler = logging.StreamHandler()
|
37
|
+
console_handler.setLevel(logging.DEBUG)
|
38
|
+
console_handler.setFormatter(SqilFormatter(SqilFormatter.FORMAT))
|
39
|
+
|
40
|
+
# Avoid adding multiple handlers if the logger is reused
|
41
|
+
if not logger.hasHandlers():
|
42
|
+
logger.addHandler(console_handler)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
from ._analysis import AnalysisResult
|
2
|
+
from ._events import after_experiment, before_experiment
|
3
|
+
from ._experiment import ExperimentHandler
|
4
|
+
from .instruments._instrument import Instrument
|
5
|
+
from .instruments.local_oscillator import LocalOscillator
|
6
|
+
from .instruments.server import (
|
7
|
+
InstrumentServer,
|
8
|
+
link_instrument_server,
|
9
|
+
start_instrument_server,
|
10
|
+
unlink_instrument_server,
|
11
|
+
)
|
@@ -0,0 +1,95 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
from pathlib import Path
|
5
|
+
from typing import TYPE_CHECKING
|
6
|
+
|
7
|
+
import h5py
|
8
|
+
import mpld3
|
9
|
+
import numpy as np
|
10
|
+
|
11
|
+
from sqil_core.utils import get_measurement_id
|
12
|
+
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
from matplotlib.figure import Figure
|
15
|
+
|
16
|
+
from sqil_core.fit import FitResult
|
17
|
+
|
18
|
+
|
19
|
+
class AnalysisResult:
|
20
|
+
updated_params: dict[str, dict] = {}
|
21
|
+
figures: dict[str, Figure] = {}
|
22
|
+
fits: dict[str, FitResult] = {}
|
23
|
+
extra_data: dict[str, np.ndarray] = {}
|
24
|
+
|
25
|
+
def __init__(
|
26
|
+
self,
|
27
|
+
updated_params: dict[str, dict] = {},
|
28
|
+
figures: dict[str, Figure] = {},
|
29
|
+
fits: dict[str, FitResult] = {},
|
30
|
+
extra_data: dict[str, np.ndarray] = {},
|
31
|
+
):
|
32
|
+
self.updated_params = updated_params or {}
|
33
|
+
self.figures = figures or {}
|
34
|
+
self.fits = fits or {}
|
35
|
+
self.extra_data = extra_data or {}
|
36
|
+
|
37
|
+
def add_exp_info_to_figures(self, dir_path: str):
|
38
|
+
if not self.figures:
|
39
|
+
return
|
40
|
+
id = get_measurement_id(dir_path)
|
41
|
+
cooldown_name = Path(dir_path).parts[-3]
|
42
|
+
for _, fig in self.figures.items():
|
43
|
+
# Add dummy text to infer font size
|
44
|
+
dummy_text = fig.text(0, 0, "dummy", visible=False)
|
45
|
+
font_size = dummy_text.get_fontsize()
|
46
|
+
dummy_text.remove()
|
47
|
+
fig.text(
|
48
|
+
0.98,
|
49
|
+
0.98,
|
50
|
+
f"{cooldown_name}\n{id} | {dir_path[-16:]}",
|
51
|
+
ha="right",
|
52
|
+
va="top",
|
53
|
+
color="gray",
|
54
|
+
fontsize=font_size * 0.8,
|
55
|
+
)
|
56
|
+
|
57
|
+
def save_figures(self, dir_path: str):
|
58
|
+
"""Saves figures both as png and interactive html."""
|
59
|
+
for key, fig in self.figures.items():
|
60
|
+
path = os.path.join(dir_path, key)
|
61
|
+
fig.savefig(os.path.join(f"{path}.png"), bbox_inches="tight", dpi=300)
|
62
|
+
html = mpld3.fig_to_html(fig)
|
63
|
+
with open(f"{path}.html", "w") as f:
|
64
|
+
f.write(html)
|
65
|
+
|
66
|
+
def aggregate_fit_summaries(self):
|
67
|
+
"""Aggreate all the fit summaries and include model name."""
|
68
|
+
result = ""
|
69
|
+
for key, fit in self.fits.items():
|
70
|
+
summary = fit.summary(no_print=True)
|
71
|
+
result += f"{key}\nModel: {fit.model_name}\n{summary}\n"
|
72
|
+
return result
|
73
|
+
|
74
|
+
def save_fits(self, dir_path: str):
|
75
|
+
if not self.fits:
|
76
|
+
return
|
77
|
+
with open(os.path.join(dir_path, "fit.mono.md"), "w", encoding="utf-8") as f:
|
78
|
+
f.write(self.aggregate_fit_summaries())
|
79
|
+
|
80
|
+
def save_extra_data(self, dir_path: str):
|
81
|
+
if not self.extra_data:
|
82
|
+
return
|
83
|
+
with h5py.File(os.path.join(dir_path, "extra.ddh5"), "a") as f:
|
84
|
+
grp = f.require_group("data")
|
85
|
+
for key, array in self.extra_data.items():
|
86
|
+
# Overwrite if already exists
|
87
|
+
if key in grp:
|
88
|
+
del grp[key]
|
89
|
+
grp.create_dataset(key, data=array)
|
90
|
+
|
91
|
+
def save_all(self, dir_path: str):
|
92
|
+
self.add_exp_info_to_figures(dir_path)
|
93
|
+
self.save_figures(dir_path)
|
94
|
+
self.save_fits(dir_path)
|
95
|
+
self.save_extra_data(dir_path)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
from blinker import NamedSignal
|
2
|
+
|
3
|
+
before_experiment = NamedSignal("before_experiment")
|
4
|
+
after_experiment = NamedSignal("after_experiment")
|
5
|
+
|
6
|
+
before_sequence = NamedSignal("before_sequence")
|
7
|
+
after_sequence = NamedSignal("after_sequence")
|
8
|
+
|
9
|
+
|
10
|
+
def clear_signal(signal):
|
11
|
+
"""Removes all listeners (receivers) from an event (signal)."""
|
12
|
+
receivers = list(signal.receivers.values())
|
13
|
+
for receiver in receivers:
|
14
|
+
signal.disconnect(receiver)
|
15
|
+
|
16
|
+
|
17
|
+
def one_time_listener(signal, func):
|
18
|
+
"""Listens for an event only once."""
|
19
|
+
|
20
|
+
def wrapper(*args, **kwargs):
|
21
|
+
signal.disconnect(wrapper)
|
22
|
+
return func(*args, **kwargs)
|
23
|
+
|
24
|
+
signal.connect(wrapper, weak=False)
|
25
|
+
return wrapper
|