simcats 1.0.0__py3-none-any.whl → 1.2.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.
- simcats/__init__.py +2 -3
- simcats/distortions/_dot_jumps.py +11 -6
- simcats/ideal_csd/__init__.py +1 -1
- simcats/ideal_csd/geometric/_ideal_csd_geometric.py +0 -145
- simcats/ideal_csd/geometric/_ideal_csd_geometric_class.py +158 -0
- simcats/ideal_csd/geometric/_tct_bezier.py +18 -7
- simcats/support_functions/__init__.py +4 -4
- simcats/support_functions/_parameter_sampling.py +193 -15
- simcats-1.2.0.dist-info/METADATA +218 -0
- {simcats-1.0.0.dist-info → simcats-1.2.0.dist-info}/RECORD +13 -12
- {simcats-1.0.0.dist-info → simcats-1.2.0.dist-info}/WHEEL +1 -1
- simcats-1.0.0.dist-info/METADATA +0 -187
- {simcats-1.0.0.dist-info → simcats-1.2.0.dist-info}/LICENSE +0 -0
- {simcats-1.0.0.dist-info → simcats-1.2.0.dist-info}/top_level.txt +0 -0
simcats/__init__.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
"""
|
|
2
|
-
SimCATS is a python framework for simulating charge stability diagrams (CSDs) typically measured during the tuning
|
|
1
|
+
"""SimCATS is a python framework for simulating charge stability diagrams (CSDs) typically measured during the tuning
|
|
3
2
|
process of qubits.
|
|
4
3
|
"""
|
|
5
4
|
|
|
@@ -7,4 +6,4 @@ from ._simulation import Simulation
|
|
|
7
6
|
from ._default_configs import default_configs
|
|
8
7
|
|
|
9
8
|
__all__ = ["Simulation", "default_configs"]
|
|
10
|
-
__version__ = "1.
|
|
9
|
+
__version__ = "1.2.0"
|
|
@@ -156,11 +156,16 @@ class OccupationDotJumps(OccupationDistortionInterface):
|
|
|
156
156
|
numpy array with the axis mapping to the CSD axis.
|
|
157
157
|
|
|
158
158
|
"""
|
|
159
|
-
if not
|
|
160
|
-
self.__activated = False
|
|
159
|
+
if freeze and not self.__activated:
|
|
161
160
|
return occupations, lead_transitions
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
|
|
162
|
+
# only resample activation if not frozen
|
|
163
|
+
if not freeze:
|
|
164
|
+
if not bool(self.rng.binomial(1, self.ratio)):
|
|
165
|
+
self.__activated = False
|
|
166
|
+
return occupations, lead_transitions
|
|
167
|
+
else:
|
|
168
|
+
self.__activated = True
|
|
164
169
|
|
|
165
170
|
resolution = occupations.shape[0:2]
|
|
166
171
|
if freeze:
|
|
@@ -467,8 +472,8 @@ class OccupationDotJumps(OccupationDistortionInterface):
|
|
|
467
472
|
volt_limits_g2=volt_limits_g2,
|
|
468
473
|
resolution=(max_jump, occupation.shape[0]) if max_jump > 1 else (occupation.shape[0]),
|
|
469
474
|
)
|
|
470
|
-
left_occupation = np.reshape(left_occupation, (occupation.shape[
|
|
471
|
-
left_charge_transitions = np.reshape(left_charge_transitions, (occupation.shape[
|
|
475
|
+
left_occupation = np.reshape(left_occupation, (occupation.shape[0], max_jump, 2))
|
|
476
|
+
left_charge_transitions = np.reshape(left_charge_transitions, (occupation.shape[0], max_jump))
|
|
472
477
|
occupation_stacked = np.hstack((left_occupation, occupation))
|
|
473
478
|
if lead_transitions is not None:
|
|
474
479
|
total_charge_transitions_stacked = np.hstack((left_charge_transitions, lead_transitions))
|
simcats/ideal_csd/__init__.py
CHANGED
|
@@ -3,6 +3,6 @@ SimCATS subpackage containing all functionalities related to the simulation of i
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from simcats.ideal_csd._ideal_csd_interface import IdealCSDInterface
|
|
6
|
-
from simcats.ideal_csd.geometric.
|
|
6
|
+
from simcats.ideal_csd.geometric._ideal_csd_geometric_class import IdealCSDGeometric
|
|
7
7
|
|
|
8
8
|
__all__ = ["IdealCSDInterface", "IdealCSDGeometric"]
|
|
@@ -8,7 +8,6 @@ from typing import List, Tuple, Union
|
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
|
|
11
|
-
from simcats.ideal_csd import IdealCSDInterface
|
|
12
11
|
from simcats.ideal_csd.geometric import (
|
|
13
12
|
calculate_all_bezier_anchors,
|
|
14
13
|
generate_lead_transition_mask_1d,
|
|
@@ -20,150 +19,6 @@ from simcats.ideal_csd.geometric import initialize_tct_functions
|
|
|
20
19
|
__all__ = []
|
|
21
20
|
|
|
22
21
|
|
|
23
|
-
class IdealCSDGeometric(IdealCSDInterface):
|
|
24
|
-
"""Geometric simulation approach implementation of the IdealCSDInterface."""
|
|
25
|
-
|
|
26
|
-
def __init__(
|
|
27
|
-
self,
|
|
28
|
-
tct_params: List[np.ndarray],
|
|
29
|
-
rotation: float = -np.pi / 4,
|
|
30
|
-
lut_entries: Union[int, None] = None,
|
|
31
|
-
cdf_type: str = "sigmoid",
|
|
32
|
-
cdf_gamma_factor: Union[float, None] = None,
|
|
33
|
-
) -> None:
|
|
34
|
-
"""Initializes an object of the class for the geometric simulation approach which is based on total charge
|
|
35
|
-
transitions (TCTs).
|
|
36
|
-
|
|
37
|
-
Args:
|
|
38
|
-
tct_params (List[np.ndarray]): List containing a numpy array with parameters for every TCT in the CSD.
|
|
39
|
-
Each array contains all required parameters to describe the TCT form. \n
|
|
40
|
-
The parameters for a TCT are: \n
|
|
41
|
-
[0] = length left (in x-/voltage-space, not number of points) \n
|
|
42
|
-
[1] = length right (in x-/voltage-space, not number of points) \n
|
|
43
|
-
[2] = gradient left (in voltages) \n
|
|
44
|
-
[3] = gradient right (in voltages) \n
|
|
45
|
-
[4] = start position x (bezier curve leftmost point) (in x-/voltage-space, not number of points) \n
|
|
46
|
-
[5] = start position y (bezier curve leftmost point) (in x-/voltage-space, not number of points) \n
|
|
47
|
-
[6] = end position x (bezier curve rightmost point) (in x-/voltage-space, not number of points) \n
|
|
48
|
-
[7] = end position y (bezier curve rightmost point) (in x-/voltage-space, not number of points)
|
|
49
|
-
rotation (float): Float value defining the rotation to be applied to the TCT (which is usually represented
|
|
50
|
-
with the tct_params rotated by 45 degrees). Default is -np.pi/4.
|
|
51
|
-
lut_entries (Union[int, None]): Number of samples for the lookup-table for bezier curves. If this is not None, a
|
|
52
|
-
lookup-table will be used to evaluate the points on the bezier curves, else they are solved explicitly.
|
|
53
|
-
Using a lookup-table speeds up the calculation at the possible cost of accuracy. Default is None.
|
|
54
|
-
cdf_type (str): Name of the type of cumulative distribution function (CDF) to be used. Can be either
|
|
55
|
-
"cauchy" or "sigmoid". Default is "sigmoid".
|
|
56
|
-
cdf_gamma_factor (Union[float, None]): The factor used for the calculation of the gamma values of the CDF. If set to None
|
|
57
|
-
(=default) the default values for the selected cdf_type are used (2.2 for sigmoid, 6.15 for cauchy).
|
|
58
|
-
Default is None. \n
|
|
59
|
-
Gamma is calculated as follows: \n
|
|
60
|
-
gamma = width_bezier_curve / cdf_gamma_factor
|
|
61
|
-
"""
|
|
62
|
-
self.tct_params = tct_params
|
|
63
|
-
self.rotation = rotation
|
|
64
|
-
self.lut_entries = lut_entries
|
|
65
|
-
self.cdf_type = cdf_type
|
|
66
|
-
self.cdf_gamma_factor = cdf_gamma_factor
|
|
67
|
-
|
|
68
|
-
@property
|
|
69
|
-
def tct_params(self) -> List[np.ndarray]:
|
|
70
|
-
"""List containing a numpy array with parameters for every TCT in the CSD. Each array contains all required
|
|
71
|
-
parameters to describe the TCT form.
|
|
72
|
-
"""
|
|
73
|
-
return self.__tct_params
|
|
74
|
-
|
|
75
|
-
@tct_params.setter
|
|
76
|
-
def tct_params(self, wave_params: list):
|
|
77
|
-
self.__tct_params = wave_params
|
|
78
|
-
|
|
79
|
-
@property
|
|
80
|
-
def rotation(self) -> float:
|
|
81
|
-
"""Float value defining the rotation to be applied to the TCT (which is usually represented with the tct_params
|
|
82
|
-
rotated by 45 degrees).
|
|
83
|
-
"""
|
|
84
|
-
return self.__rotation
|
|
85
|
-
|
|
86
|
-
@rotation.setter
|
|
87
|
-
def rotation(self, rotation: float) -> None:
|
|
88
|
-
self.__rotation = rotation
|
|
89
|
-
|
|
90
|
-
@property
|
|
91
|
-
def lut_entries(self) -> Union[int, None]:
|
|
92
|
-
"""Number of samples for the lookup-table for bezier curves. If this is not None, a lookup-table will be used to
|
|
93
|
-
evaluate the points on the bezier curves, else they are solved explicitly.
|
|
94
|
-
"""
|
|
95
|
-
return self.__lut_entries
|
|
96
|
-
|
|
97
|
-
@lut_entries.setter
|
|
98
|
-
def lut_entries(self, lut_entries: Union[int, None]):
|
|
99
|
-
self.__lut_entries = lut_entries
|
|
100
|
-
|
|
101
|
-
@property
|
|
102
|
-
def cdf_type(self) -> str:
|
|
103
|
-
"""Name of the type of cumulative distribution function (CDF) to be used."""
|
|
104
|
-
return self.__cdf_type
|
|
105
|
-
|
|
106
|
-
@cdf_type.setter
|
|
107
|
-
def cdf_type(self, cdf_type: str) -> None:
|
|
108
|
-
self.__cdf_type = cdf_type
|
|
109
|
-
|
|
110
|
-
@property
|
|
111
|
-
def cdf_gamma_factor(self) -> Union[float, None]:
|
|
112
|
-
"""The factor used for the calculation of the gamma values of the CDF. If set to None (=default) the default values
|
|
113
|
-
for the selected cdf_type are used (2.2 for sigmoid, 6.15 for cauchy).
|
|
114
|
-
"""
|
|
115
|
-
return self.__cdf_gamma_factor
|
|
116
|
-
|
|
117
|
-
@cdf_gamma_factor.setter
|
|
118
|
-
def cdf_gamma_factor(self, cdf_gamma_factor: Union[float, None]):
|
|
119
|
-
self.__cdf_gamma_factor = cdf_gamma_factor
|
|
120
|
-
|
|
121
|
-
def get_csd_data(
|
|
122
|
-
self,
|
|
123
|
-
volt_limits_g1: np.ndarray,
|
|
124
|
-
volt_limits_g2: np.ndarray,
|
|
125
|
-
resolution: Union[int, np.ndarray] = np.array([100, 100]),
|
|
126
|
-
) -> Tuple[np.ndarray, np.ndarray]:
|
|
127
|
-
"""Retrieve ideal data (occupation numbers and a lead transition mask) for given gate voltages.
|
|
128
|
-
|
|
129
|
-
Args:
|
|
130
|
-
volt_limits_g1 (np.ndarray): Voltage sweep range of (plunger) gate 1 (second-/x-axis). \n
|
|
131
|
-
Example: \n
|
|
132
|
-
[min_V1, max_V1]
|
|
133
|
-
volt_limits_g2 (np.ndarray): Voltage sweep range of (plunger) gate 2 (first-/y-axis). \n
|
|
134
|
-
Example: \n
|
|
135
|
-
[min_V2, max_V2]
|
|
136
|
-
resolution (np.ndarray): Desired resolution (in pixels) for the gates. If only one value is supplied, a 1D
|
|
137
|
-
sweep is performed. Then, both gates are swept simultaneously. Default is np.array([100, 100]). \n
|
|
138
|
-
Example: \n
|
|
139
|
-
[res_g1, res_g2]
|
|
140
|
-
|
|
141
|
-
Returns:
|
|
142
|
-
Tuple[np.ndarray, np.ndarray]: Occupation numbers and lead transition mask (in our case: total charge
|
|
143
|
-
transitions). The occupation numbers are stored in a 3-dimensional numpy array. The first two dimensions map
|
|
144
|
-
to the axis of the CSD, while the third dimension indicates the dot of the corresponding occupation value.
|
|
145
|
-
The label mask for the lead-to-dot transitions is stored in a 2-dimensional numpy array with the axis
|
|
146
|
-
mapping to the CSD axis.
|
|
147
|
-
|
|
148
|
-
"""
|
|
149
|
-
return ideal_csd_geometric(
|
|
150
|
-
tct_params=self.__tct_params,
|
|
151
|
-
volt_limits_g1=volt_limits_g1,
|
|
152
|
-
volt_limits_g2=volt_limits_g2,
|
|
153
|
-
resolution=resolution,
|
|
154
|
-
rotation=self.__rotation,
|
|
155
|
-
lut_entries=self.__lut_entries,
|
|
156
|
-
cdf_type=self.__cdf_type,
|
|
157
|
-
cdf_gamma_factor=self.__cdf_gamma_factor,
|
|
158
|
-
)
|
|
159
|
-
|
|
160
|
-
def __repr__(self):
|
|
161
|
-
return (
|
|
162
|
-
self.__class__.__name__
|
|
163
|
-
+ f"(tct_params={self.__tct_params}, rotation={self.__rotation}, lut_entries={self.__lut_entries}, cdf_type='{self.__cdf_type}', cdf_gamma_factor={self.__cdf_gamma_factor})"
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
|
|
167
22
|
def ideal_csd_geometric(
|
|
168
23
|
tct_params: List[np.ndarray],
|
|
169
24
|
volt_limits_g1: np.ndarray,
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"""This module contains the required functionalities to generate ideal CSD data using supplied total charge
|
|
2
|
+
transitions (TCTs), voltage ranges and a desired resolution. It also implements the IdealCSDInterface.
|
|
3
|
+
|
|
4
|
+
@author: f.hader
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import List, Tuple, Union
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from simcats.ideal_csd import IdealCSDInterface
|
|
12
|
+
from simcats.ideal_csd.geometric import ideal_csd_geometric
|
|
13
|
+
|
|
14
|
+
__all__ = []
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class IdealCSDGeometric(IdealCSDInterface):
|
|
18
|
+
"""Geometric simulation approach implementation of the IdealCSDInterface."""
|
|
19
|
+
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
tct_params: List[np.ndarray],
|
|
23
|
+
rotation: float = -np.pi / 4,
|
|
24
|
+
lut_entries: Union[int, None] = None,
|
|
25
|
+
cdf_type: str = "sigmoid",
|
|
26
|
+
cdf_gamma_factor: Union[float, None] = None,
|
|
27
|
+
) -> None:
|
|
28
|
+
"""Initializes an object of the class for the geometric simulation approach which is based on total charge
|
|
29
|
+
transitions (TCTs).
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
tct_params (List[np.ndarray]): List containing a numpy array with parameters for every TCT in the CSD.
|
|
33
|
+
Each array contains all required parameters to describe the TCT form. \n
|
|
34
|
+
The parameters for a TCT are: \n
|
|
35
|
+
[0] = length left (in x-/voltage-space, not number of points) \n
|
|
36
|
+
[1] = length right (in x-/voltage-space, not number of points) \n
|
|
37
|
+
[2] = gradient left (in voltages) \n
|
|
38
|
+
[3] = gradient right (in voltages) \n
|
|
39
|
+
[4] = start position x (bezier curve leftmost point) (in x-/voltage-space, not number of points) \n
|
|
40
|
+
[5] = start position y (bezier curve leftmost point) (in x-/voltage-space, not number of points) \n
|
|
41
|
+
[6] = end position x (bezier curve rightmost point) (in x-/voltage-space, not number of points) \n
|
|
42
|
+
[7] = end position y (bezier curve rightmost point) (in x-/voltage-space, not number of points)
|
|
43
|
+
rotation (float): Float value defining the rotation to be applied to the TCT (which is usually represented
|
|
44
|
+
with the tct_params rotated by 45 degrees). Default is -np.pi/4.
|
|
45
|
+
lut_entries (Union[int, None]): Number of samples for the lookup-table for bezier curves. If this is not None, a
|
|
46
|
+
lookup-table will be used to evaluate the points on the bezier curves, else they are solved explicitly.
|
|
47
|
+
Using a lookup-table speeds up the calculation at the possible cost of accuracy. Default is None.
|
|
48
|
+
cdf_type (str): Name of the type of cumulative distribution function (CDF) to be used. Can be either
|
|
49
|
+
"cauchy" or "sigmoid". Default is "sigmoid".
|
|
50
|
+
cdf_gamma_factor (Union[float, None]): The factor used for the calculation of the gamma values of the CDF. If set to None
|
|
51
|
+
(=default) the default values for the selected cdf_type are used (2.2 for sigmoid, 6.15 for cauchy).
|
|
52
|
+
Default is None. \n
|
|
53
|
+
Gamma is calculated as follows: \n
|
|
54
|
+
gamma = width_bezier_curve / cdf_gamma_factor
|
|
55
|
+
"""
|
|
56
|
+
self.tct_params = tct_params
|
|
57
|
+
self.rotation = rotation
|
|
58
|
+
self.lut_entries = lut_entries
|
|
59
|
+
self.cdf_type = cdf_type
|
|
60
|
+
self.cdf_gamma_factor = cdf_gamma_factor
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def tct_params(self) -> List[np.ndarray]:
|
|
64
|
+
"""List containing a numpy array with parameters for every TCT in the CSD. Each array contains all required
|
|
65
|
+
parameters to describe the TCT form.
|
|
66
|
+
"""
|
|
67
|
+
return self.__tct_params
|
|
68
|
+
|
|
69
|
+
@tct_params.setter
|
|
70
|
+
def tct_params(self, tct_params: list):
|
|
71
|
+
self.__tct_params = tct_params
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def rotation(self) -> float:
|
|
75
|
+
"""Float value defining the rotation to be applied to the TCT (which is usually represented with the tct_params
|
|
76
|
+
rotated by 45 degrees).
|
|
77
|
+
"""
|
|
78
|
+
return self.__rotation
|
|
79
|
+
|
|
80
|
+
@rotation.setter
|
|
81
|
+
def rotation(self, rotation: float) -> None:
|
|
82
|
+
self.__rotation = rotation
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def lut_entries(self) -> Union[int, None]:
|
|
86
|
+
"""Number of samples for the lookup-table for bezier curves. If this is not None, a lookup-table will be used to
|
|
87
|
+
evaluate the points on the bezier curves, else they are solved explicitly.
|
|
88
|
+
"""
|
|
89
|
+
return self.__lut_entries
|
|
90
|
+
|
|
91
|
+
@lut_entries.setter
|
|
92
|
+
def lut_entries(self, lut_entries: Union[int, None]):
|
|
93
|
+
self.__lut_entries = lut_entries
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def cdf_type(self) -> str:
|
|
97
|
+
"""Name of the type of cumulative distribution function (CDF) to be used."""
|
|
98
|
+
return self.__cdf_type
|
|
99
|
+
|
|
100
|
+
@cdf_type.setter
|
|
101
|
+
def cdf_type(self, cdf_type: str) -> None:
|
|
102
|
+
self.__cdf_type = cdf_type
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def cdf_gamma_factor(self) -> Union[float, None]:
|
|
106
|
+
"""The factor used for the calculation of the gamma values of the CDF. If set to None (=default) the default values
|
|
107
|
+
for the selected cdf_type are used (2.2 for sigmoid, 6.15 for cauchy).
|
|
108
|
+
"""
|
|
109
|
+
return self.__cdf_gamma_factor
|
|
110
|
+
|
|
111
|
+
@cdf_gamma_factor.setter
|
|
112
|
+
def cdf_gamma_factor(self, cdf_gamma_factor: Union[float, None]):
|
|
113
|
+
self.__cdf_gamma_factor = cdf_gamma_factor
|
|
114
|
+
|
|
115
|
+
def get_csd_data(
|
|
116
|
+
self,
|
|
117
|
+
volt_limits_g1: np.ndarray,
|
|
118
|
+
volt_limits_g2: np.ndarray,
|
|
119
|
+
resolution: Union[int, np.ndarray] = np.array([100, 100]),
|
|
120
|
+
) -> Tuple[np.ndarray, np.ndarray]:
|
|
121
|
+
"""Retrieve ideal data (occupation numbers and a lead transition mask) for given gate voltages.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
volt_limits_g1 (np.ndarray): Voltage sweep range of (plunger) gate 1 (second-/x-axis). \n
|
|
125
|
+
Example: \n
|
|
126
|
+
[min_V1, max_V1]
|
|
127
|
+
volt_limits_g2 (np.ndarray): Voltage sweep range of (plunger) gate 2 (first-/y-axis). \n
|
|
128
|
+
Example: \n
|
|
129
|
+
[min_V2, max_V2]
|
|
130
|
+
resolution (np.ndarray): Desired resolution (in pixels) for the gates. If only one value is supplied, a 1D
|
|
131
|
+
sweep is performed. Then, both gates are swept simultaneously. Default is np.array([100, 100]). \n
|
|
132
|
+
Example: \n
|
|
133
|
+
[res_g1, res_g2]
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Tuple[np.ndarray, np.ndarray]: Occupation numbers and lead transition mask (in our case: total charge
|
|
137
|
+
transitions). The occupation numbers are stored in a 3-dimensional numpy array. The first two dimensions map
|
|
138
|
+
to the axis of the CSD, while the third dimension indicates the dot of the corresponding occupation value.
|
|
139
|
+
The label mask for the lead-to-dot transitions is stored in a 2-dimensional numpy array with the axis
|
|
140
|
+
mapping to the CSD axis.
|
|
141
|
+
|
|
142
|
+
"""
|
|
143
|
+
return ideal_csd_geometric(
|
|
144
|
+
tct_params=self.__tct_params,
|
|
145
|
+
volt_limits_g1=volt_limits_g1,
|
|
146
|
+
volt_limits_g2=volt_limits_g2,
|
|
147
|
+
resolution=resolution,
|
|
148
|
+
rotation=self.__rotation,
|
|
149
|
+
lut_entries=self.__lut_entries,
|
|
150
|
+
cdf_type=self.__cdf_type,
|
|
151
|
+
cdf_gamma_factor=self.__cdf_gamma_factor,
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def __repr__(self):
|
|
155
|
+
return (
|
|
156
|
+
self.__class__.__name__
|
|
157
|
+
+ f"(tct_params={self.__tct_params}, rotation={self.__rotation}, lut_entries={self.__lut_entries}, cdf_type='{self.__cdf_type}', cdf_gamma_factor={self.__cdf_gamma_factor})"
|
|
158
|
+
)
|
|
@@ -84,12 +84,14 @@ def tct_bezier(
|
|
|
84
84
|
|
|
85
85
|
# initialize bezier curve
|
|
86
86
|
bezier_curve = bezier.Curve.from_nodes(nodes)
|
|
87
|
-
xb, yb = sympy.symbols("x y")
|
|
88
|
-
bezier_implicit = bezier_curve.implicitize()
|
|
89
87
|
# retrieve a lookup-table if the given lut_entries value is not None
|
|
90
88
|
if lut_entries:
|
|
91
89
|
t = np.linspace(0, 1, lut_entries)
|
|
92
90
|
bezier_lut = bezier_curve.evaluate_multi(t)
|
|
91
|
+
else:
|
|
92
|
+
xb, yb = sympy.symbols("x y")
|
|
93
|
+
bezier_implicit = bezier_curve.implicitize()
|
|
94
|
+
bezier_implicit_solved = sympy.solve(bezier_implicit, yb)
|
|
93
95
|
|
|
94
96
|
# retrieve length of bezier curve & period length. Both are required to calculate the region
|
|
95
97
|
# where the x-values to be evaluated are located
|
|
@@ -116,7 +118,12 @@ def tct_bezier(
|
|
|
116
118
|
# all other ids are simulated as linear parts
|
|
117
119
|
# lowest value = left bezier anchor
|
|
118
120
|
# highest value = right bezier anchor + #additional_peaks * period length
|
|
119
|
-
x_range_wave = np.array(
|
|
121
|
+
x_range_wave = np.array(
|
|
122
|
+
[
|
|
123
|
+
tct_params[4],
|
|
124
|
+
(tct_params[6] + (max_peaks - 1) * (tct_params[0] + tct_params[1])),
|
|
125
|
+
]
|
|
126
|
+
)
|
|
120
127
|
ids_wave = np.where((x_eval + offset_x >= x_range_wave[0]) & (x_eval + offset_x <= x_range_wave[1]))[0]
|
|
121
128
|
else:
|
|
122
129
|
x_range_wave = [x_eval[0], x_eval[-1]]
|
|
@@ -138,7 +145,10 @@ def tct_bezier(
|
|
|
138
145
|
y_res[x_id] = bezier_lut[1, np.argmin(np.abs(bezier_lut[0, :] - (x_mod_per + offset_x)))]
|
|
139
146
|
else:
|
|
140
147
|
# use sympy to solve symbolic expression for x, because s is not linearly mapped to x
|
|
141
|
-
temp_y =
|
|
148
|
+
temp_y = [
|
|
149
|
+
bezier_implicit_solution.subs({xb: x_mod_per + offset_x})
|
|
150
|
+
for bezier_implicit_solution in bezier_implicit_solved
|
|
151
|
+
]
|
|
142
152
|
# might get two solutions because implicit function might be quadratic. If so, the second solution
|
|
143
153
|
# is the positive one and selected therefore, as we assume to have only positive y-values after
|
|
144
154
|
# rotating a signal with only positive x- & y-values by 45 degree
|
|
@@ -168,9 +178,10 @@ def tct_bezier(
|
|
|
168
178
|
)
|
|
169
179
|
else:
|
|
170
180
|
# use sympy to solve symbolic expression for x, because s is not linearly mapped to x
|
|
171
|
-
temp_y =
|
|
172
|
-
|
|
173
|
-
|
|
181
|
+
temp_y = [
|
|
182
|
+
bezier_implicit_solution.subs({xb: 2 * bezier_length + right_lin_length - x_mod_per + offset_x})
|
|
183
|
+
for bezier_implicit_solution in bezier_implicit_solved
|
|
184
|
+
]
|
|
174
185
|
# might get two solutions because implicit function might be quadratic. If so, the second solution
|
|
175
186
|
# is the positive one and selected therefore, as we assume to have only positive y-values after
|
|
176
187
|
# rotating a signal with only positive x- & y-values by 45 degree
|
|
@@ -3,7 +3,7 @@ SimCATS subpackage with support functions that are not assigned to any specific
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from simcats.support_functions._parameter_sampling import ParameterSamplingInterface, NormalSamplingRange, \
|
|
6
|
-
UniformSamplingRange
|
|
6
|
+
LogNormalSamplingRange, UniformSamplingRange, ExponentialSamplingRange
|
|
7
7
|
from simcats.support_functions._fermi_filter1d import fermi_filter1d, fermi_dirac_derivative
|
|
8
8
|
from simcats.support_functions._cumulative_distribution_functions import cauchy_cdf, multi_cauchy_cdf, sigmoid_cdf, \
|
|
9
9
|
multi_sigmoid_cdf
|
|
@@ -11,6 +11,6 @@ from simcats.support_functions._signed_dist_points_line import signed_dist_point
|
|
|
11
11
|
from simcats.support_functions._rotate_points import rotate_points
|
|
12
12
|
from simcats.support_functions._plotting import plot_csd
|
|
13
13
|
|
|
14
|
-
__all__ = ["ParameterSamplingInterface", "NormalSamplingRange", "
|
|
15
|
-
"
|
|
16
|
-
"signed_dist_points_line", "rotate_points", "plot_csd"]
|
|
14
|
+
__all__ = ["ParameterSamplingInterface", "NormalSamplingRange", "LogNormalSamplingRange", "UniformSamplingRange",
|
|
15
|
+
"ExponentialSamplingRange", "fermi_filter1d", "fermi_dirac_derivative", "cauchy_cdf", "multi_cauchy_cdf",
|
|
16
|
+
"sigmoid_cdf", "multi_sigmoid_cdf", "signed_dist_points_line", "rotate_points", "plot_csd"]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The contained functions can be used for example for the parameter sampling in the distortions module.
|
|
4
4
|
|
|
5
|
-
@author: s.fleitmann
|
|
5
|
+
@author: s.fleitmann, f.fuchs
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
8
|
import warnings
|
|
@@ -42,12 +42,14 @@ class ParameterSamplingInterface(ABC):
|
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
class NormalSamplingRange(ParameterSamplingInterface):
|
|
45
|
+
"""Normal sampling range implementation of ParameterSamplingInterface."""
|
|
45
46
|
def __init__(
|
|
46
47
|
self,
|
|
47
48
|
total_range: Tuple,
|
|
48
49
|
std: float,
|
|
50
|
+
mean: Union[float, None] = None,
|
|
49
51
|
sampling_range: Union[float, None] = None,
|
|
50
|
-
rng: np.random.Generator =
|
|
52
|
+
rng: Union[np.random.Generator, None] = None,
|
|
51
53
|
) -> None:
|
|
52
54
|
"""This class can be used to generate randomly normal sampled parameters within a given range.
|
|
53
55
|
|
|
@@ -55,22 +57,30 @@ class NormalSamplingRange(ParameterSamplingInterface):
|
|
|
55
57
|
|
|
56
58
|
Args:
|
|
57
59
|
total_range (Tuple): The total range in which the parameters can be sampled. This can be narrowed down
|
|
58
|
-
randomly with the help of sampling_range.
|
|
60
|
+
randomly with the help of sampling_range. If the normal distribution generates a sample outside this
|
|
61
|
+
range, a new sample is drawn until a sample inside the sampling_range/total_range was generated,
|
|
62
|
+
leading to a truncated normal distribution.
|
|
59
63
|
std (float): The standard deviation of the sampled elements, which is used in the normal distribution.
|
|
64
|
+
mean (Union[float, None]): The mean to be used for the normal distribution. If None, the center of the
|
|
65
|
+
total range will be used. Defaults to None.
|
|
60
66
|
sampling_range (Union[float, None]): The maximum range in which the parameter is allowed to change during
|
|
61
67
|
the simulation. The explicit range is set up during the initialization, narrowing down the
|
|
62
68
|
supplied total_range. Default is None, which leads to no narrowing of the given total_range.
|
|
63
|
-
rng (np.random.Generator): random number generator used for the sampling of random numbers.
|
|
64
|
-
default generator of numpy (np.random.default_rng())
|
|
69
|
+
rng (np.random.Generator): random number generator used for the sampling of random numbers. If None, the
|
|
70
|
+
default generator of numpy (np.random.default_rng()) is used. Default is None.
|
|
65
71
|
"""
|
|
66
|
-
|
|
72
|
+
if rng:
|
|
73
|
+
self.__rng = rng
|
|
74
|
+
else:
|
|
75
|
+
self.__rng = np.random.default_rng()
|
|
67
76
|
if sampling_range is None:
|
|
68
77
|
self.__range = total_range
|
|
69
78
|
else:
|
|
70
79
|
if np.greater_equal(sampling_range, total_range[1] - total_range[0]):
|
|
71
80
|
warnings.warn(
|
|
72
81
|
"The given reduced sampling range is equal or larger than the given total range. As "
|
|
73
|
-
"default the given total sampling range is taken."
|
|
82
|
+
"default the given total sampling range is taken.",
|
|
83
|
+
stacklevel=2,
|
|
74
84
|
)
|
|
75
85
|
self.__range = total_range
|
|
76
86
|
else:
|
|
@@ -79,11 +89,17 @@ class NormalSamplingRange(ParameterSamplingInterface):
|
|
|
79
89
|
)
|
|
80
90
|
self.__range = (sampled - 0.5 * sampling_range, sampled + 0.5 * sampling_range)
|
|
81
91
|
self.__std = std
|
|
92
|
+
if mean is not None:
|
|
93
|
+
self.__mean = mean
|
|
94
|
+
else:
|
|
95
|
+
self.__mean = np.mean(self.__range)
|
|
82
96
|
self.__last_sample = None
|
|
83
97
|
|
|
84
98
|
def sample_parameter(self):
|
|
85
|
-
sampled = self.__rng.normal(loc=
|
|
86
|
-
sampled
|
|
99
|
+
sampled = self.__rng.normal(loc=self.__mean, scale=self.__std)
|
|
100
|
+
# repeat sampling until the sampled value is in self.__range
|
|
101
|
+
while sampled < self.__range[0] or sampled > self.__range[1]:
|
|
102
|
+
sampled = self.__rng.normal(loc=self.__mean, scale=self.__std)
|
|
87
103
|
self.__last_sample = sampled
|
|
88
104
|
return sampled
|
|
89
105
|
|
|
@@ -93,16 +109,17 @@ class NormalSamplingRange(ParameterSamplingInterface):
|
|
|
93
109
|
def __repr__(self) -> str:
|
|
94
110
|
return (
|
|
95
111
|
self.__class__.__name__
|
|
96
|
-
+ f"(last_sample={self.last_sample()}, range={self.__range}, std={self.__std}, rng={self.__rng})"
|
|
112
|
+
+ f"(last_sample={self.last_sample()}, range={self.__range}, mean={self.__mean}, std={self.__std}, rng={self.__rng})"
|
|
97
113
|
)
|
|
98
114
|
|
|
99
115
|
|
|
100
116
|
class UniformSamplingRange(ParameterSamplingInterface):
|
|
117
|
+
"""Uniform sampling range implementation of ParameterSamplingInterface."""
|
|
101
118
|
def __init__(
|
|
102
119
|
self,
|
|
103
120
|
total_range: Tuple,
|
|
104
121
|
sampling_range: Union[float, None] = None,
|
|
105
|
-
rng: np.random.Generator =
|
|
122
|
+
rng: Union[np.random.Generator, None] = None,
|
|
106
123
|
) -> None:
|
|
107
124
|
"""This class can be used to generate randomly uniform sampled parameters within a given range.
|
|
108
125
|
|
|
@@ -114,17 +131,21 @@ class UniformSamplingRange(ParameterSamplingInterface):
|
|
|
114
131
|
sampling_range (Union[float, None]): The maximum range in which the parameter is allowed to change during
|
|
115
132
|
the simulation. The explicit range is set up during the initialization, narrowing down the supplied
|
|
116
133
|
total_range. Default is None, which leads to no narrowing of the given total_range.
|
|
117
|
-
rng (np.random.Generator): random number generator used for the sampling of random numbers.
|
|
118
|
-
default generator of numpy (np.random.default_rng())
|
|
134
|
+
rng (np.random.Generator): random number generator used for the sampling of random numbers. If None, the
|
|
135
|
+
default generator of numpy (np.random.default_rng()) is used. Default is None.
|
|
119
136
|
"""
|
|
120
|
-
|
|
137
|
+
if rng:
|
|
138
|
+
self.__rng = rng
|
|
139
|
+
else:
|
|
140
|
+
self.__rng = np.random.default_rng()
|
|
121
141
|
if sampling_range is None:
|
|
122
142
|
self.__range = total_range
|
|
123
143
|
else:
|
|
124
144
|
if np.greater_equal(sampling_range, total_range[1] - total_range[0]):
|
|
125
145
|
warnings.warn(
|
|
126
146
|
"The given reduced sampling range is equal or larger than the given total range. As "
|
|
127
|
-
"default the given total sampling range is taken."
|
|
147
|
+
"default the given total sampling range is taken.",
|
|
148
|
+
stacklevel=2,
|
|
128
149
|
)
|
|
129
150
|
self.__range = total_range
|
|
130
151
|
else:
|
|
@@ -144,3 +165,160 @@ class UniformSamplingRange(ParameterSamplingInterface):
|
|
|
144
165
|
|
|
145
166
|
def __repr__(self) -> str:
|
|
146
167
|
return self.__class__.__name__ + f"(last_sample={self.last_sample()}, range={self.__range}, rng={self.__rng})"
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
class LogNormalSamplingRange(ParameterSamplingInterface):
|
|
171
|
+
"""Logarithmic normal sampling range implementation of ParameterSamplingInterface."""
|
|
172
|
+
def __init__(
|
|
173
|
+
self,
|
|
174
|
+
total_range: Tuple,
|
|
175
|
+
sampling_range: Union[float, None] = None,
|
|
176
|
+
rng: Union[np.random.Generator, None] = None,
|
|
177
|
+
mean: float = 0,
|
|
178
|
+
sigma: float = 1,
|
|
179
|
+
) -> None:
|
|
180
|
+
"""This class can be used to generate randomly log-normal sampled parameters within a given range.
|
|
181
|
+
|
|
182
|
+
For example, for the distortions used in the simulation of CSDs.
|
|
183
|
+
|
|
184
|
+
Args:
|
|
185
|
+
total_range (Tuple): The total range in which the parameters can be sampled. This can be narrowed down
|
|
186
|
+
randomly with the help of sampling_range. If the log-normal distribution generates a sample outside this
|
|
187
|
+
range, a new sample is drawn until a sample inside the sampling_range/total_range was generated, leading
|
|
188
|
+
toa truncated log-normal distribution.
|
|
189
|
+
sampling_range (Union[float, None]): The maximum range in which the parameter is allowed to change during
|
|
190
|
+
the simulation. The explicit range is set up during the initialization, narrowing down the supplied
|
|
191
|
+
total_range. Default is None, which leads to no narrowing of the given total_range.
|
|
192
|
+
rng (np.random.Generator): random number generator used for the sampling of random numbers. If None, the
|
|
193
|
+
default generator of numpy (np.random.default_rng()) is used. Default is None.
|
|
194
|
+
mean (float): Mean value of the underlying normal distribution. Default is 0.
|
|
195
|
+
sigma (float): Standard deviation of the underlying normal distribution. Must be non-negative. Default is 1.
|
|
196
|
+
"""
|
|
197
|
+
if rng:
|
|
198
|
+
self.__rng = rng
|
|
199
|
+
else:
|
|
200
|
+
self.__rng = np.random.default_rng()
|
|
201
|
+
self.__mean: float = mean
|
|
202
|
+
self.__sigma: float = sigma
|
|
203
|
+
if sampling_range is None:
|
|
204
|
+
self.__range = total_range
|
|
205
|
+
else:
|
|
206
|
+
if np.greater_equal(sampling_range, total_range[1] - total_range[0]):
|
|
207
|
+
warnings.warn(
|
|
208
|
+
"The given reduced sampling range is equal or larger than the given total range. As "
|
|
209
|
+
"default the given total sampling range is taken.",
|
|
210
|
+
stacklevel=2,
|
|
211
|
+
)
|
|
212
|
+
self.__range = total_range
|
|
213
|
+
else:
|
|
214
|
+
sampled = self.__rng.uniform(
|
|
215
|
+
total_range[0] + 0.5 * sampling_range,
|
|
216
|
+
total_range[1] - 0.5 * sampling_range,
|
|
217
|
+
)
|
|
218
|
+
self.__range = (
|
|
219
|
+
sampled - 0.5 * sampling_range,
|
|
220
|
+
sampled + 0.5 * sampling_range,
|
|
221
|
+
)
|
|
222
|
+
self.__last_sample = None
|
|
223
|
+
|
|
224
|
+
def sample_parameter(self):
|
|
225
|
+
sampled = self.__rng.lognormal(mean=self.__mean, sigma=self.__sigma)
|
|
226
|
+
# repeat sampling until the sampled value is in self.__range
|
|
227
|
+
while sampled < self.__range[0] or sampled > self.__range[1]:
|
|
228
|
+
sampled = self.__rng.lognormal(mean=self.__mean, sigma=self.__sigma)
|
|
229
|
+
self.__last_sample = sampled
|
|
230
|
+
return sampled
|
|
231
|
+
|
|
232
|
+
def last_sample(self):
|
|
233
|
+
return self.__last_sample
|
|
234
|
+
|
|
235
|
+
def __repr__(self) -> str:
|
|
236
|
+
return (
|
|
237
|
+
self.__class__.__name__
|
|
238
|
+
+ f"(last_sample={self.last_sample()}, range={self.__range}, mean={self.__mean}, sigma={self.__sigma}"
|
|
239
|
+
+ f", rng={self.__rng})"
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
class ExponentialSamplingRange(ParameterSamplingInterface):
|
|
244
|
+
"""Exponential distribution sampling range implementation of ParameterSamplingInterface."""
|
|
245
|
+
|
|
246
|
+
def __init__(
|
|
247
|
+
self,
|
|
248
|
+
total_range: Tuple,
|
|
249
|
+
scale: float,
|
|
250
|
+
sampling_range: Union[float, None] = None,
|
|
251
|
+
rng: Union[np.random.Generator, None] = None,
|
|
252
|
+
) -> None:
|
|
253
|
+
"""This class can be used to generate randomly sampled parameters from an exponential distribution within a given range.
|
|
254
|
+
|
|
255
|
+
The samples are calculated as follows:\n
|
|
256
|
+
min(sampling_range) + exponential_distribution_sample * (max(sampling_range) - min(Sampling_range))
|
|
257
|
+
|
|
258
|
+
To select the correct scale factor (1 / λ), take the following into consideration:\n
|
|
259
|
+
To have the p percent quantile at position q, the following must be valid:\n
|
|
260
|
+
q = ln( 1 / (1-p) ) / λ \n
|
|
261
|
+
with 1 / λ = scale \n
|
|
262
|
+
So in general the scale is calculated as: \n
|
|
263
|
+
scale = q / ln( 1 / (1-p) ) \n
|
|
264
|
+
For example: If it is desired to have 90% of the values in 50% of the sampling range, we get:\n
|
|
265
|
+
scale = 0.5 / ln( 1 / (1-0.9) ) = 0.21715
|
|
266
|
+
|
|
267
|
+
Further reading: https://en.wikipedia.org/wiki/Exponential_distribution#properties
|
|
268
|
+
|
|
269
|
+
Used for example for the distortions during the simulation of CSDs.
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
total_range (Tuple): The total range in which the parameters can be sampled. This can be narrowed down
|
|
273
|
+
randomly with the help of the parameter sampling_range. If the exponential distribution generates a
|
|
274
|
+
sample outside this range, a new sample is drawn until a sample inside the sampling_range/total_range
|
|
275
|
+
was generated, leading to a truncated exponential distribution.
|
|
276
|
+
scale (float): The scale of the exponential distribution. See __init__ docstring for more detailed
|
|
277
|
+
information.
|
|
278
|
+
sampling_range (Union[float, None]): The maximum range in which the parameter is allowed to change during
|
|
279
|
+
the simulation. The explicit range is set up during the initialization, narrowing down the
|
|
280
|
+
supplied total_range. Default is None, which leads to no narrowing of the given total_range.
|
|
281
|
+
rng (np.random.Generator): random number generator used for the sampling of random numbers. If None, the
|
|
282
|
+
default generator of numpy (np.random.default_rng()) is used. Default is None.
|
|
283
|
+
"""
|
|
284
|
+
if rng:
|
|
285
|
+
self.__rng = rng
|
|
286
|
+
else:
|
|
287
|
+
self.__rng = np.random.default_rng()
|
|
288
|
+
if sampling_range is None:
|
|
289
|
+
self.__range = total_range
|
|
290
|
+
else:
|
|
291
|
+
if np.greater_equal(sampling_range, np.max(total_range) - np.min(total_range)):
|
|
292
|
+
warnings.warn(
|
|
293
|
+
"The given reduced sampling range is equal or larger than the given total range. As "
|
|
294
|
+
"default the given total sampling range is taken.",
|
|
295
|
+
stacklevel=2,
|
|
296
|
+
)
|
|
297
|
+
self.__range = total_range
|
|
298
|
+
else:
|
|
299
|
+
sampled = self.__rng.uniform(
|
|
300
|
+
np.min(total_range) + 0.5 * sampling_range, np.max(total_range) - 0.5 * sampling_range
|
|
301
|
+
)
|
|
302
|
+
if total_range[0] < total_range[1]:
|
|
303
|
+
self.__range = (sampled - 0.5 * sampling_range, sampled + 0.5 * sampling_range)
|
|
304
|
+
else:
|
|
305
|
+
self.__range = (sampled + 0.5 * sampling_range, sampled - 0.5 * sampling_range)
|
|
306
|
+
self.__scale = scale
|
|
307
|
+
self.__last_sample = None
|
|
308
|
+
|
|
309
|
+
def sample_parameter(self):
|
|
310
|
+
sampled = self.__range[0] + self.__rng.exponential(scale=self.__scale) * (self.__range[1] - self.__range[0])
|
|
311
|
+
# repeat sampling until the sampled value is in self.__range
|
|
312
|
+
while sampled < np.min(self.__range) or sampled > np.max(self.__range):
|
|
313
|
+
sampled = self.__range[0] + self.__rng.exponential(scale=self.__scale) * (self.__range[1] - self.__range[0])
|
|
314
|
+
self.__last_sample = sampled
|
|
315
|
+
return sampled
|
|
316
|
+
|
|
317
|
+
def last_sample(self):
|
|
318
|
+
return self.__last_sample
|
|
319
|
+
|
|
320
|
+
def __repr__(self) -> str:
|
|
321
|
+
return (
|
|
322
|
+
self.__class__.__name__
|
|
323
|
+
+ f"(last_sample={self.last_sample()}, range={self.__range}, scale={self.__scale}, rng={self.__rng})"
|
|
324
|
+
)
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: simcats
|
|
3
|
+
Version: 1.2.0
|
|
4
|
+
Summary: SimCATS is a python framework for simulating charge stability diagrams (CSDs) typically measured during the tuning process of qubits.
|
|
5
|
+
Author-email: Fabian Hader <f.hader@fz-juelich.de>, Sarah Fleitmann <s.fleitmann@fz-juelich.de>, Fabian Fuchs <f.fuchs@fz-juelich.de>
|
|
6
|
+
License: CC BY-NC-SA 4.0
|
|
7
|
+
Project-URL: homepage, https://github.com/f-hader/SimCATS
|
|
8
|
+
Project-URL: documentation, https://simcats.readthedocs.io
|
|
9
|
+
Project-URL: source, https://github.com/f-hader/SimCATS
|
|
10
|
+
Project-URL: tracker, https://github.com/f-hader/SimCATS/issues
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.7
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
License-File: LICENSE
|
|
25
|
+
Requires-Dist: bezier
|
|
26
|
+
Requires-Dist: colorednoise
|
|
27
|
+
Requires-Dist: diplib
|
|
28
|
+
Requires-Dist: matplotlib
|
|
29
|
+
Requires-Dist: numpy
|
|
30
|
+
Requires-Dist: opencv-python
|
|
31
|
+
Requires-Dist: scipy
|
|
32
|
+
Requires-Dist: sympy
|
|
33
|
+
|
|
34
|
+
<h1 align="center">
|
|
35
|
+
<img src="https://raw.githubusercontent.com/f-hader/SimCATS/main/SimCATS_symbol.svg" alt="SimCATS logo">
|
|
36
|
+
<br>
|
|
37
|
+
</h1>
|
|
38
|
+
|
|
39
|
+
<div align="center">
|
|
40
|
+
<a href="https://github.com/f-hader/SimCATS/blob/main/LICENSE">
|
|
41
|
+
<img src="https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg" alt="License: CC BY-NC-SA 4.0"/>
|
|
42
|
+
</a>
|
|
43
|
+
<a href="https://pypi.org/project/simcats/">
|
|
44
|
+
<img src="https://img.shields.io/pypi/v/simcats.svg" alt="PyPi Latest Release"/>
|
|
45
|
+
</a>
|
|
46
|
+
<a href="https://simcats.readthedocs.io/en/latest/">
|
|
47
|
+
<img src="https://img.shields.io/readthedocs/simcats" alt="Read the Docs"/>
|
|
48
|
+
</a>
|
|
49
|
+
<a href="https://doi.org/10.1109/TQE.2024.3445967">
|
|
50
|
+
<img src="https://img.shields.io/badge/DOI-10.1109/TQE.2024.3445967-007ec6.svg" alt="DOI Publication"/>
|
|
51
|
+
</a>
|
|
52
|
+
</div>
|
|
53
|
+
|
|
54
|
+
# SimCATS
|
|
55
|
+
|
|
56
|
+
Simulation of CSDs for Automated Tuning Solutions (`SimCATS`) is a Python framework for simulating charge stability
|
|
57
|
+
diagrams (CSDs) typically measured during the tuning process of qubits.
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
The framework supports Python versions 3.7 - 3.11 and installs via pip:
|
|
62
|
+
```
|
|
63
|
+
pip install simcats
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Alternatively, the `SimCATS` package can be installed by cloning the GitHub repository, navigating to the folder
|
|
67
|
+
containing the `setup.py` file and executing
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
pip install .
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
For the installation in development/editable mode, use the option `-e`.
|
|
74
|
+
|
|
75
|
+
## Examples / Tutorials
|
|
76
|
+
After installing the package, a good starting point is a look into the Jupyter Notebook
|
|
77
|
+
`example_SimCATS_simulation_class.ipynb`, which provides an overview of the usage of the simulation class offered by
|
|
78
|
+
the framework.
|
|
79
|
+
For more detailed examples and explanations of the geometric ideal CSD simulation using Total Charge Transitions (TCTs), look at the Jupyter Notebook `example_SimCATS_IdealCSDGeometric.ipynb`. This notebook also includes a hint
|
|
80
|
+
regarding the generation of required labels for training algorithms that might need line labels defined as start and
|
|
81
|
+
end points or require semantic information about particular transitions.
|
|
82
|
+
|
|
83
|
+
## Tests
|
|
84
|
+
|
|
85
|
+
The tests are written for the `PyTest` framework but should also work with the `unittest` framework.
|
|
86
|
+
|
|
87
|
+
To run the tests, install the packages `pytest`, `pytest-cov`, and `pytest-xdist` with
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
pip install pytest pytest-cov pytest-xdist
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
and run the following command:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
pytest --cov=simcats -n auto --dist loadfile .\tests\
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The argument
|
|
100
|
+
- `--cov=simcats` enables a coverage summary of the `SimCATS` package,
|
|
101
|
+
- `-n auto` enables the test to run with multiple threads (auto will choose as many threads as possible, but can be replaced with a specific number of threads to use), and
|
|
102
|
+
- `--dist loadfile` specifies that each file should be executed only by one thread.
|
|
103
|
+
|
|
104
|
+
<!-- start sec:documentation -->
|
|
105
|
+
## Documentation
|
|
106
|
+
|
|
107
|
+
The official documentation is hosted on [ReadtheDocs](https://simcats.readthedocs.io), but can also be built locally.
|
|
108
|
+
To do this, first install the packages `sphinx`, `sphinx-rtd-theme`, `sphinx-autoapi`, `myst-nb `, and `jupytext` with
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
pip install sphinx sphinx-rtd-theme sphinx-autoapi myst-nb jupytext
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
and then, in the `docs` folder, execute the following command:
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
.\make html
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
To view the generated HTML documentation, open the file `docs\build\html\index.html`.
|
|
121
|
+
<!-- end sec:documentation -->
|
|
122
|
+
|
|
123
|
+
## Structure of SimCATS
|
|
124
|
+
|
|
125
|
+
The primary user interface for `SimCATS` is the class `Simulation`, which combines all the necessary functionalities to
|
|
126
|
+
measure (simulate) a CSD and adjust the parameters for the simulated measurement. The class `Simulation` and default
|
|
127
|
+
configurations for the simulation (`default_configs`) can be imported directly from `simcats`. Aside from that,
|
|
128
|
+
`SimCATS` contains the subpackages `ideal_csd`, `sensor`, `distortions`, and `support_functions`, described in
|
|
129
|
+
the following sections.
|
|
130
|
+
|
|
131
|
+
### Module `simulation`
|
|
132
|
+
|
|
133
|
+
An instance of the simulation class requires
|
|
134
|
+
|
|
135
|
+
- an implementation of the `IdealCSDInterface` for the simulation of ideal CSD data,
|
|
136
|
+
- an implementation of the `SensorInterface` for the simulation of the sensor (dot) reaction based on the ideal CSD
|
|
137
|
+
data, and
|
|
138
|
+
- (optionally) implementations of the desired types of distortions, which can be implementations from `OccupationDistortionInterface`, `SensorPotentialDistortionInterface`, or `SensorResponseDistortionInterface`.
|
|
139
|
+
|
|
140
|
+
With an initialized instance of the `Simulation` class, it is possible to run simulations using the `measure` function
|
|
141
|
+
(see `example_SimCATS_simulation_class.ipynb`).
|
|
142
|
+
|
|
143
|
+
### Subpackage `ideal_csd`
|
|
144
|
+
|
|
145
|
+
This subpackage contains the `IdealCSDInterface` used by the `Simulation` class and an implementation of
|
|
146
|
+
the `IdealCSDInterface` (`IdealCSDGeometric`) based on our geometric simulation approach.
|
|
147
|
+
Additionally, it contains in the subpackage `geometric` the functions used by `IdealCSDGeometric`, including the
|
|
148
|
+
implementation of the total charge transition (TCT) definition and functions for calculating the occupations using TCTs.
|
|
149
|
+
|
|
150
|
+
### Subpackage `distortions`
|
|
151
|
+
|
|
152
|
+
The distortions subpackage contains the `DistortionInterface` from which the `OccupationDistortionInterface`, the
|
|
153
|
+
`SensorPotentialDistortionInterface`, and the `SensorResponseDistortionInterface` are derived. Distortion functions used
|
|
154
|
+
in the `Simulation` class have to implement these specific interfaces. Implemented distortions included in the
|
|
155
|
+
subpackage are:
|
|
156
|
+
|
|
157
|
+
- white noise, generated by sampling from a normal distribution,
|
|
158
|
+
- pink noise, generated using the package colorednoise ([https://github.com/felixpatzelt/colorednoise](https://github.com/felixpatzelt/colorednoise)),
|
|
159
|
+
- random telegraph noise (RTN), generated using the algorithm described in ["Toward Robust Autotuning of Noisy Quantum Dot Devices" by Ziegler et al.](https://doi.org/10.1103/PhysRevApplied.17.024069) (RTN is called sensor jumps there),
|
|
160
|
+
- dot jumps, simulated using the algorithm described in ["Toward Robust Autotuning of Noisy Quantum Dot Devices" by Ziegler et al.](https://doi.org/10.1103/PhysRevApplied.17.024069) (In the `Simulation` class, this is applied to a whole block of rows or columns, but there is also a function for applying it linewise.), and
|
|
161
|
+
- lead transition blurring, simulated using Gaussian or Fermi-Dirac blurring.
|
|
162
|
+
|
|
163
|
+
The implementations also offer the option to set ratios (parameter `ratio`) for the occurrence of the distortion (e.g. dot jumps may only happen sometimes and not in every measurement). Moreover, it is also possible to sample the
|
|
164
|
+
noise parameters from a given sampling range using an object of type `ParameterSamplingInterface`.
|
|
165
|
+
Classes for randomly sampling from a normal distribution or a uniform distribution within a given range are available in
|
|
166
|
+
the subpackage `support_functions`.
|
|
167
|
+
In this case, the strength is randomly chosen from the given range for every measurement.
|
|
168
|
+
Additionally, it is possible to specify that this range should be a smaller subrange of the provided range.
|
|
169
|
+
This allows restricting distortion fluctuations during a simulation while enabling a large variety of different strengths
|
|
170
|
+
for the initialization of the objects. <br>
|
|
171
|
+
RTN, dot jumps, and lead transition blurring are applied in the pixel domain. However, the jump length or the blurring strength should be consistent in the voltage domain even if the resolution changes. Therefore, the parameters
|
|
172
|
+
are given in the voltage domain and adjusted according to the resolution in terms of pixel per voltage. <br>
|
|
173
|
+
For a simulated measurement with a continuous voltage sweep involving an averaging for each pixel, the noise strength of the
|
|
174
|
+
white and pink noise should be adjusted if the resolution (volt per pixel) changes, due to smoothing out the noise. This smoothing depends on the type of averaging used and is not incorporated in the default implementation.
|
|
175
|
+
|
|
176
|
+
### Subpackage `sensor`
|
|
177
|
+
|
|
178
|
+
This subpackage contains the `SensorInterface` that defines how a sensor simulation must be implemented to be used by the `Simulation` class. The `SensorPeakInterface` provides the desired representation for the definition of the Coulomb peaks the sensor uses. `SensorGeneric` implements the `SensorInterface` and offers functions for simulating the sensor response and potential. It offers the possibility to simulate with a single peak or multiple sensor peaks. Current implementations of the `SensorPeakInterface` are `SensorPeakGaussian` and `SensorPeakLorentzian`.
|
|
179
|
+
|
|
180
|
+
### Subpackage `support_functions`
|
|
181
|
+
|
|
182
|
+
This subpackage contains support functions, which are used by the end user and by different functions of the framework.
|
|
183
|
+
- `fermi_filter1d` is an implementation of a one-dimensional Fermi-Dirac filter.
|
|
184
|
+
- `plot_csd` plots one and two-dimensional CSDs. The function can also plot ground truth data (see `example_SimCATS_simulation_class.ipynb` for examples).
|
|
185
|
+
- `rotate_points` simply rotates coordinates (stored in a (n, 2) shaped array) by a given angle. It is especially used during the generation of the ideal data.
|
|
186
|
+
- `ParameterSamplingInterface` defines an interface for randomly sampled (fluctuated) strengths of distortions.
|
|
187
|
+
- `NormalSamplingRange` and `UniformSamplingRange` are implementations of the `ParameterSamplingInterface`.
|
|
188
|
+
|
|
189
|
+
## Citations
|
|
190
|
+
|
|
191
|
+
```bibtex
|
|
192
|
+
@article{hader2024simcats,
|
|
193
|
+
author={Hader, Fabian and Fleitmann, Sarah and Vogelbruch, Jan and Geck, Lotte and Waasen, Stefan van},
|
|
194
|
+
journal={IEEE Transactions on Quantum Engineering},
|
|
195
|
+
title={Simulation of Charge Stability Diagrams for Automated Tuning Solutions (SimCATS)},
|
|
196
|
+
year={2024},
|
|
197
|
+
volume={5},
|
|
198
|
+
pages={1-14},
|
|
199
|
+
doi={10.1109/TQE.2024.3445967}
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## License, CLA, and Copyright
|
|
204
|
+
|
|
205
|
+
[![CC BY-NC-SA 4.0][cc-by-nc-sa-shield]][cc-by-nc-sa]
|
|
206
|
+
|
|
207
|
+
This work is licensed under a
|
|
208
|
+
[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License][cc-by-nc-sa].
|
|
209
|
+
|
|
210
|
+
[![CC BY-NC-SA 4.0][cc-by-nc-sa-image]][cc-by-nc-sa]
|
|
211
|
+
|
|
212
|
+
[cc-by-nc-sa]: http://creativecommons.org/licenses/by-nc-sa/4.0/
|
|
213
|
+
[cc-by-nc-sa-image]: https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png
|
|
214
|
+
[cc-by-nc-sa-shield]: https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg
|
|
215
|
+
|
|
216
|
+
Contributions must follow the Contributor License Agreement. For more information, see the CONTRIBUTING.md file at the top of the GitHub repository.
|
|
217
|
+
|
|
218
|
+
Copyright © 2024 Forschungszentrum Jülich GmbH - Central Institute of Engineering, Electronics and Analytics (ZEA) - Electronic Systems (ZEA-2)
|
|
@@ -1,36 +1,37 @@
|
|
|
1
|
-
simcats/__init__.py,sha256=
|
|
1
|
+
simcats/__init__.py,sha256=pnTS1t8IQKm2SpadtblS8VKUFKm0OfBkiT7rQGzj8Ws,300
|
|
2
2
|
simcats/_default_configs.py,sha256=wHWa4wyTVtZf9J37WdcMlvM7XeI_OZhl8NB7lrBi-yI,6980
|
|
3
3
|
simcats/_simulation.py,sha256=xvKLnOzwc8uGGLfXvBZPaLYYPHBaXcwwtlYmJ3zTkUU,24795
|
|
4
4
|
simcats/distortions/__init__.py,sha256=3oXqKm1rkznDKhWeitZxYJyb1wFMdan6CBfBw673J7A,1368
|
|
5
5
|
simcats/distortions/_distortion_interfaces.py,sha256=8twWE8FX8fqiLlxrcSOBaMZCc3boDbE6n_b4587-ra4,6717
|
|
6
|
-
simcats/distortions/_dot_jumps.py,sha256=
|
|
6
|
+
simcats/distortions/_dot_jumps.py,sha256=6segzH8VWaUlRPMcWjkDacwyCcN8bPhfWyrYQD8UaoA,38162
|
|
7
7
|
simcats/distortions/_pink_noise.py,sha256=2-ZvNAvtsypNHqLXN_FfGR-iWnAGgXWZxTS7LKk73pQ,5233
|
|
8
8
|
simcats/distortions/_random_telegraph_noise.py,sha256=psRV-tosDXHC0xBSZyrKZAgRBMQoxSeeDTRIpUsJ9hg,16785
|
|
9
9
|
simcats/distortions/_transition_blurring.py,sha256=3kryfx3VEnJpAgPfoJF-Z4leoSFrzGUwf-5mb8bXD3o,13631
|
|
10
10
|
simcats/distortions/_white_noise.py,sha256=toxal_V2aPxxqoxpsJz3-lH7rtNjzsz5aoTbgNhiWxU,4413
|
|
11
|
-
simcats/ideal_csd/__init__.py,sha256=
|
|
11
|
+
simcats/ideal_csd/__init__.py,sha256=jxQkBf_z1xIclUcqeur6OVzrFJhd9eAXFF9PJdb091I,316
|
|
12
12
|
simcats/ideal_csd/_ideal_csd_interface.py,sha256=3PjLgv_MjIlN2YqbpLwrJysukntftZSBCrBBPwe0HSA,2334
|
|
13
13
|
simcats/ideal_csd/geometric/__init__.py,sha256=uXqR4qGbBcTQ8WdIO56ZxHWXqbn85yvuVlm5zJV7iVc,927
|
|
14
14
|
simcats/ideal_csd/geometric/_calculate_all_bezier_anchors.py,sha256=AvSsOsiu5H3HKoJwwZ1797T3yHoRc6Rj2YT-JJujaIY,6491
|
|
15
15
|
simcats/ideal_csd/geometric/_generate_lead_transition_mask.py,sha256=QOYSNSy5IHiNefmC37KsuM3484xJfsl8yNeo4o5Xdws,6316
|
|
16
16
|
simcats/ideal_csd/geometric/_get_electron_occupation.py,sha256=rEW9guTxM4pTGy9vtQ34NP4zxRaMNk-LQstfCkq4OEw,13461
|
|
17
|
-
simcats/ideal_csd/geometric/_ideal_csd_geometric.py,sha256=
|
|
17
|
+
simcats/ideal_csd/geometric/_ideal_csd_geometric.py,sha256=gpYVgRx_rRB46FyaKntg9CWIpGSP4uroJGeyeufmoKE,10077
|
|
18
|
+
simcats/ideal_csd/geometric/_ideal_csd_geometric_class.py,sha256=Qx1IQy4NX4gtkFQGBaQRxjW46urv95mMQI_enWRUl4M,7481
|
|
18
19
|
simcats/ideal_csd/geometric/_initialize_tct_functions.py,sha256=z1rCkKLM68e97xQkdwnUq5DGuCkHiOADRfwiDb2I3kE,3161
|
|
19
|
-
simcats/ideal_csd/geometric/_tct_bezier.py,sha256=
|
|
20
|
+
simcats/ideal_csd/geometric/_tct_bezier.py,sha256=xDBlEylwYvnX-xOdUt-N7P7k9i0yzTce9b3dXZa_Zx4,12067
|
|
20
21
|
simcats/sensor/__init__.py,sha256=v9aG6_WGYF5Dq_OFHHn2NQxZx2X2HGg0nkglz5wSoHw,611
|
|
21
22
|
simcats/sensor/_gaussian_sensor_peak.py,sha256=7xrSfl505MygBJ7Nu3V3RJpNq8q-mjukVDcrL-ezEuA,4039
|
|
22
23
|
simcats/sensor/_generic_sensor.py,sha256=88E6xP3r5GZCBKaR7TKtqrWovR4XW-mm6YUwL96L_AQ,10441
|
|
23
24
|
simcats/sensor/_lorentzian_sensor_peak.py,sha256=Rj3Tpk6dksZGfOAHhdSGQR-wJo3ehdmXnumXyGuaNC4,3952
|
|
24
25
|
simcats/sensor/_sensor_interface.py,sha256=mn5L9WbAIMun_ou0AHgOV6XiBeykYPugndLAeufadTo,5064
|
|
25
|
-
simcats/support_functions/__init__.py,sha256=
|
|
26
|
+
simcats/support_functions/__init__.py,sha256=6aXPXtvcaL4bcOADy1yWhhyehT6BDs3Yt_3uOFbBE50,1086
|
|
26
27
|
simcats/support_functions/_cumulative_distribution_functions.py,sha256=pE01RoSL2VwtkBP7xYivd-vcd6krSJrb4xb8MCfyRBA,3366
|
|
27
28
|
simcats/support_functions/_fermi_filter1d.py,sha256=F4GrdLt0bOXidRdg0P-163Op-bxKvgHte3ENI39qYAk,3706
|
|
28
|
-
simcats/support_functions/_parameter_sampling.py,sha256=
|
|
29
|
+
simcats/support_functions/_parameter_sampling.py,sha256=xEd4V0bUqpkE5DpZA0i1YNe8G86IZP1LB2dmkFTg3l0,15331
|
|
29
30
|
simcats/support_functions/_plotting.py,sha256=xc050m4W6RZm8XdOdqruc-6IYyhzW9UFvNlJEgkJRi8,9070
|
|
30
31
|
simcats/support_functions/_rotate_points.py,sha256=4tgzE4a4uykBVw2pSK55DzGe-5n9N38nsBYhfA38Qgs,778
|
|
31
32
|
simcats/support_functions/_signed_dist_points_line.py,sha256=dMnDoBARY7C48xCHFp8mNFNCkPk7YUiaWaRqAsindsE,908
|
|
32
|
-
simcats-1.
|
|
33
|
-
simcats-1.
|
|
34
|
-
simcats-1.
|
|
35
|
-
simcats-1.
|
|
36
|
-
simcats-1.
|
|
33
|
+
simcats-1.2.0.dist-info/LICENSE,sha256=aZs_e2FTt6geKaC1hd9FpoxERpb5YHhxJ608urp4nig,21294
|
|
34
|
+
simcats-1.2.0.dist-info/METADATA,sha256=QFMyj-AF9-K0_0u5mnPbCO1AXlB7l0gJqTDuIdT3ixg,11918
|
|
35
|
+
simcats-1.2.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
|
36
|
+
simcats-1.2.0.dist-info/top_level.txt,sha256=M-ExkkJ_NLsuuJiDo3iM2qPPPsEX29E2MQUmegBZ8Wk,8
|
|
37
|
+
simcats-1.2.0.dist-info/RECORD,,
|
simcats-1.0.0.dist-info/METADATA
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: simcats
|
|
3
|
-
Version: 1.0.0
|
|
4
|
-
Summary: SimCATS is a python framework for simulating charge stability diagrams (CSDs) typically measured during the tuning process of qubits.
|
|
5
|
-
Author-email: Fabian Hader <f.hader@fz-juelich.de>, Sarah Fleitmann <s.fleitmann@fz-juelich.de>, Fabian Fuchs <f.fuchs@fz-juelich.de>
|
|
6
|
-
License: CC BY-NC-SA 4.0
|
|
7
|
-
Project-URL: homepage, https://github.com/f-hader/SimCATS
|
|
8
|
-
Project-URL: documentation, https://simcats.readthedocs.io
|
|
9
|
-
Project-URL: source, https://github.com/f-hader/SimCATS
|
|
10
|
-
Project-URL: tracker, https://github.com/f-hader/SimCATS/issues
|
|
11
|
-
Classifier: Development Status :: 5 - Production/Stable
|
|
12
|
-
Classifier: Intended Audience :: Science/Research
|
|
13
|
-
Classifier: Programming Language :: Python
|
|
14
|
-
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
-
Classifier: Topic :: Scientific/Engineering
|
|
21
|
-
Classifier: Typing :: Typed
|
|
22
|
-
Requires-Python: >=3.7
|
|
23
|
-
Description-Content-Type: text/markdown
|
|
24
|
-
License-File: LICENSE
|
|
25
|
-
Requires-Dist: bezier
|
|
26
|
-
Requires-Dist: colorednoise
|
|
27
|
-
Requires-Dist: diplib
|
|
28
|
-
Requires-Dist: matplotlib
|
|
29
|
-
Requires-Dist: numpy
|
|
30
|
-
Requires-Dist: opencv-python
|
|
31
|
-
Requires-Dist: scipy
|
|
32
|
-
Requires-Dist: sympy
|
|
33
|
-
|
|
34
|
-
# SimCATS
|
|
35
|
-
|
|
36
|
-
Simulation of CSDs for Automated Tuning Solutions (`SimCATS`) is a python framework for simulating charge stability
|
|
37
|
-
diagrams (CSDs) typically measured during the tuning process of qubits.
|
|
38
|
-
|
|
39
|
-
## Installation
|
|
40
|
-
|
|
41
|
-
The framework supports python versions 3.7 - 3.11 and can be installed with pip:
|
|
42
|
-
```
|
|
43
|
-
pip install simcats
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Alternatively, the `SimCATS` package can be installed by cloning the GitHub repository, navigating to the folder
|
|
47
|
-
containing the `setup.py` file and executing
|
|
48
|
-
|
|
49
|
-
```
|
|
50
|
-
pip install .
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
For installation in development/editable mode use the option `-e`.
|
|
54
|
-
|
|
55
|
-
## Examples / Tutorials
|
|
56
|
-
After the package is installed, a good starting point is a look into the Jupyter Notebook
|
|
57
|
-
`example_SimCATS_simulation_class.ipynb`, which provides an overview for the usage of the simulation class offered by
|
|
58
|
-
the framework.
|
|
59
|
-
For more detailed examples and explanations of the geometric ideal CSD simulation using Total Charge Transitions (TCTs),
|
|
60
|
-
have a look at the Jupyter Notebook `example_SimCATS_IdealCSDGeometric.ipynb`. This notebook also includes a hint
|
|
61
|
-
regarding the generation of required labels for training algorithms, that might need line labels defined as start and
|
|
62
|
-
end points or require semantic information about particular transitions.
|
|
63
|
-
|
|
64
|
-
## Tests
|
|
65
|
-
|
|
66
|
-
The test are written for the `PyTest` framework but should also work with the `unittest` framework.
|
|
67
|
-
|
|
68
|
-
To run the tests install the packages `pytest`, `pytest-cov` and `pytest-xdist` with
|
|
69
|
-
|
|
70
|
-
```
|
|
71
|
-
pip install pytest pytest-cov pytest-xdist
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
and then simply run following command in the terminal of your choice:
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
pytest --cov=simcats -n auto --dist loadfile .\tests\
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
The argument `--cov=simcats` enables a coverage summary of the `SimCATS` package, the argument `-n auto` enables the
|
|
81
|
-
test to run with multiple threads (auto will choose as many threads as possible, but can be replaced with a specific
|
|
82
|
-
number of threads to use) and the argument `--dist loadfile` specifies that each file should be executed only by one
|
|
83
|
-
thread.
|
|
84
|
-
|
|
85
|
-
<!-- start sec:documentation -->
|
|
86
|
-
## Documentation
|
|
87
|
-
|
|
88
|
-
The official documentation is hosted on [ReadtheDocs](https://simcats.readthedocs.io), but can also be build locally.
|
|
89
|
-
To do this, first install the packages `sphinx`, `sphinx-rtd-theme`, `sphinx-autoapi`,`myst-nb ` and `jupytext` with
|
|
90
|
-
|
|
91
|
-
```
|
|
92
|
-
pip install sphinx sphinx-rtd-theme sphinx-autoapi myst-nb jupytext
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
and then, in the `docs` folder, execute the following command in a terminal of your choice:
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
.\make html
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
To view the generated HTML documentation open the file `docs\build\html\index.html` with a browser of your choice.
|
|
102
|
-
<!-- end sec:documentation -->
|
|
103
|
-
|
|
104
|
-
## Structure of SimCATS
|
|
105
|
-
|
|
106
|
-
The main user interface for `SimCATS` is the class `Simulation`, which combines all the necessary functionalities to
|
|
107
|
-
measure (simulate) a CSD and to adjust the parameters for the simulated measurement. The class `Simulation` and default
|
|
108
|
-
configurations for the simulation (`default_configs`) can be imported directly from `simcats`. Asides from that,
|
|
109
|
-
`SimCATS` contains the subpackages `ideal_csd`, `sensor`, `distortions`, and `support_functions`. These are described in
|
|
110
|
-
the following sections.
|
|
111
|
-
|
|
112
|
-
### Module `simulation`
|
|
113
|
-
|
|
114
|
-
An instance of the simulation class requires
|
|
115
|
-
|
|
116
|
-
- an implementation of the `IdealCSDInterface` for the simulation of ideal CSD data,
|
|
117
|
-
- an implementation of the `SensorInterface` for the simulation of the sensor (dot) reaction based on the ideal CSD
|
|
118
|
-
data, and
|
|
119
|
-
- (optionally) implementations of the desired types of distortions, which can be implementations from either
|
|
120
|
-
`OccupationDistortionInterface`, `SensorPotentialDistortionInterface`, or `SensorResponseDistortionInterface`.
|
|
121
|
-
|
|
122
|
-
With an initialized instance of the `Simulation` class it is possible to run simulations using the `measure` function
|
|
123
|
-
(see `example_SimCATS_simulation_class.ipynb`).
|
|
124
|
-
|
|
125
|
-
### Subpackage `ideal_csd`
|
|
126
|
-
|
|
127
|
-
This subpackage contains the `IdealCSDInterface`, that is used by the `Simulation` class for the generation of ideal CSD
|
|
128
|
-
data, and an implementation of the `IdealCSDInterface` (`IdealCSDGeometric`) based on our geometric simulation approach.
|
|
129
|
-
Additionally, in the subpackage `geometric`, it contains the functions used by `IdealCSDGeometric`, including the
|
|
130
|
-
implementation of the total charge transition (TCT) definition and functions for calculating the occupations using TCTs.
|
|
131
|
-
|
|
132
|
-
### Subpackage `distortions`
|
|
133
|
-
|
|
134
|
-
The distortions subpackage contains the `DistortionInterface` from which the `OccupationDistortionInterface`, the
|
|
135
|
-
`SensorPotentialDistortionInterface`, and the `SensorResponseDistortionInterface` are derived. Distortion functions used
|
|
136
|
-
in the `Simulation` class have to implement these specific interfaces. Implemented distortions included in the
|
|
137
|
-
subpackage are:
|
|
138
|
-
|
|
139
|
-
- white noise, generated by sampling from a normal distribution,
|
|
140
|
-
- pink noise, generated using the package colorednoise ([https://github.com/felixpatzelt/colorednoise](https://github.com/felixpatzelt/colorednoise)),
|
|
141
|
-
- random telegraph noise (RTN), generated using the algorithm described in ["Toward Robust Autotuning of Noisy Quantum Dot Devices" by Ziegler et al.](https://doi.org/10.1103/PhysRevApplied.17.024069) (RTN is called sensor jumps there),
|
|
142
|
-
- dot jumps, simulated using the algorithm described in ["Toward Robust Autotuning of Noisy Quantum Dot Devices" by Ziegler et al.](https://doi.org/10.1103/PhysRevApplied.17.024069) (In the `Simulation` class this is applied to a whole block of rows or columns, but there is also a function for applying it linewise.), and
|
|
143
|
-
- lead transition blurring, simulated using gaussian blurring.
|
|
144
|
-
|
|
145
|
-
The implementations also offer the option to set ratios (parameter `ratio`), for how often the distortion is active
|
|
146
|
-
(f.e. dot jumps may only happen sometimes and not in every measurement). Moreover, it is also possible to sample the
|
|
147
|
-
noise parameters from a given sampling range. This can be done by using an object of type `ParameterSamplingInterface`.
|
|
148
|
-
Classes for randomly sampling from a normal distribution or a uniform distribution within a given range are available in
|
|
149
|
-
the subpackage `support_functions`.
|
|
150
|
-
In this case the strength is randomly chosen from the given range for every measurement.
|
|
151
|
-
Additionally, it is possible to specify, that this range should be a smaller subrange of the provided range.
|
|
152
|
-
This allows to restrict distortion fluctuations during a simulation while allowing a large variety of different strengths
|
|
153
|
-
for the initialization of the objects. <br>
|
|
154
|
-
RTN, dot jumps and lead transition blurring are applied in the pixel domain. However, the length of jumps or the strength
|
|
155
|
-
of the blurring should be consistent in the voltage domain even if the resolution changes. Therefore, the parameters
|
|
156
|
-
are given in the voltage domain and adjusted according to the resolution in terms of pixel per voltage. <br>
|
|
157
|
-
If a measurement with a continuous voltage sweep and averaging for each pixel is simulated, the noise strength of the white and pink noise should be adjusted if the resolution (volt per pixel) changes, as some of the noise is smoothed out. This smoothing depends on the type of averaging that is used and is not incorporated in the default implementation.
|
|
158
|
-
|
|
159
|
-
### Subpackage `sensor`
|
|
160
|
-
|
|
161
|
-
This subpackage contains the `SensorInterface` that defines how a sensor simulation must be implemented to be used by the `Simulation` class. The `SensorPeakInterface` provides the desired representation for the definition of the Coulomb peaks used by the sensor. `SensorGeneric` implements the `SensorInterface` and offers functions for simulating the sensor response and the sensor potential. It offers the possibility to simulate with a single or multiple sensor peaks. Current implementations of the `SensorPeakInterface` are `SensorPeakGaussian` and `SensorPeakLorentzian`.
|
|
162
|
-
|
|
163
|
-
### Subpackage `support_functions`
|
|
164
|
-
|
|
165
|
-
This subpackage contains support functions, which are used by the end user as well as from different functions of the framework.
|
|
166
|
-
- `fermi_filter1d` is an implementation of a one dimensional Fermi-Dirac filter.
|
|
167
|
-
- `plot_csd` is a function for plotting one and two-dimensional CSDs. The function can also be used to plot ground truth data (see `example_SimCATS_simulation_class.ipynb` for examples).
|
|
168
|
-
- `rotate_points` is a function for simply rotating coordinates (stored in a (n, 2) shaped array) by a given angle. This is especially used during the generation of the ideal data.
|
|
169
|
-
- `ParameterSamplingInterface` defines an interface that can be implemented for randomly sampling (fluctuating) strengths of distortions.
|
|
170
|
-
- `NormalSamplingRange` and `UniformSamplingRange` are implementations of the `ParameterSamplingInterface`.
|
|
171
|
-
|
|
172
|
-
## License, CLA, and Copyright
|
|
173
|
-
|
|
174
|
-
[![CC BY-NC-SA 4.0][cc-by-nc-sa-shield]][cc-by-nc-sa]
|
|
175
|
-
|
|
176
|
-
This work is licensed under a
|
|
177
|
-
[Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License][cc-by-nc-sa].
|
|
178
|
-
|
|
179
|
-
[![CC BY-NC-SA 4.0][cc-by-nc-sa-image]][cc-by-nc-sa]
|
|
180
|
-
|
|
181
|
-
[cc-by-nc-sa]: http://creativecommons.org/licenses/by-nc-sa/4.0/
|
|
182
|
-
[cc-by-nc-sa-image]: https://licensebuttons.net/l/by-nc-sa/4.0/88x31.png
|
|
183
|
-
[cc-by-nc-sa-shield]: https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-lightgrey.svg
|
|
184
|
-
|
|
185
|
-
Contributions must follow the Contributor License Agreement. For more information see the CONTRIBUTING.md file at the top level of the GitHub repository.
|
|
186
|
-
|
|
187
|
-
Copyright © 2023 Forschungszentrum Jülich GmbH - Central Institute of Engineering, Electronics and Analytics (ZEA) - Electronic Systems (ZEA-2)
|
|
File without changes
|
|
File without changes
|