simcats 1.1.0__py3-none-any.whl → 2.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.
- simcats/__init__.py +4 -3
- simcats/_default_configs.py +129 -13
- simcats/_simulation.py +451 -69
- simcats/config_samplers/_GaAs_v1_random_variations_v3_config_sampler.py +1059 -0
- simcats/config_samplers/__init__.py +9 -0
- simcats/distortions/_distortion_interfaces.py +1 -1
- simcats/distortions/_dot_jumps.py +8 -6
- simcats/distortions/_random_telegraph_noise.py +4 -4
- simcats/distortions/_transition_blurring.py +5 -5
- simcats/distortions/_white_noise.py +2 -2
- simcats/ideal_csd/geometric/_generate_lead_transition_mask.py +3 -3
- simcats/ideal_csd/geometric/_get_electron_occupation.py +5 -5
- simcats/ideal_csd/geometric/_ideal_csd_geometric.py +5 -5
- simcats/ideal_csd/geometric/_ideal_csd_geometric_class.py +9 -9
- simcats/ideal_csd/geometric/_tct_bezier.py +5 -5
- simcats/sensor/__init__.py +10 -6
- simcats/sensor/{_generic_sensor.py → _sensor_generic.py} +1 -1
- simcats/sensor/_sensor_interface.py +164 -11
- simcats/sensor/_sensor_rise_glf.py +229 -0
- simcats/sensor/_sensor_scan_sensor_generic.py +929 -0
- simcats/sensor/barrier_function/__init__.py +9 -0
- simcats/sensor/barrier_function/_barrier_function_glf.py +280 -0
- simcats/sensor/barrier_function/_barrier_function_interface.py +43 -0
- simcats/sensor/barrier_function/_barrier_function_multi_glf.py +157 -0
- simcats/sensor/deformation/__init__.py +9 -0
- simcats/sensor/deformation/_sensor_peak_deformation_circle.py +109 -0
- simcats/sensor/deformation/_sensor_peak_deformation_interface.py +65 -0
- simcats/sensor/deformation/_sensor_peak_deformation_linear.py +77 -0
- simcats/support_functions/__init__.py +11 -3
- simcats/support_functions/_generalized_logistic_function.py +146 -0
- simcats/support_functions/_linear_algebra.py +171 -0
- simcats/support_functions/_parameter_sampling.py +108 -19
- simcats/support_functions/_pixel_volt_transformation.py +24 -0
- simcats/support_functions/_reset_offset_mu_sens.py +43 -0
- {simcats-1.1.0.dist-info → simcats-2.0.0.dist-info}/METADATA +93 -29
- simcats-2.0.0.dist-info/RECORD +53 -0
- {simcats-1.1.0.dist-info → simcats-2.0.0.dist-info}/WHEEL +1 -1
- simcats-1.1.0.dist-info/RECORD +0 -37
- /simcats/sensor/{_gaussian_sensor_peak.py → _sensor_peak_gaussian.py} +0 -0
- /simcats/sensor/{_lorentzian_sensor_peak.py → _sensor_peak_lorentzian.py} +0 -0
- {simcats-1.1.0.dist-info → simcats-2.0.0.dist-info/licenses}/LICENSE +0 -0
- {simcats-1.1.0.dist-info → simcats-2.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Samplers for generating configurations for the Simulation class.
|
|
3
|
+
|
|
4
|
+
@author: f.hader, b.papajewski
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from simcats.config_samplers._GaAs_v1_random_variations_v3_config_sampler import sample_random_variations_v3_config
|
|
8
|
+
|
|
9
|
+
__all__ = ["sample_random_variations_v3_config"]
|
|
@@ -64,7 +64,7 @@ class OccupationDistortionInterface(DistortionInterface):
|
|
|
64
64
|
gate.
|
|
65
65
|
volt_limits_g2 (np.ndarray): Contains the beginning and ending of the swept range for the second (plunger)
|
|
66
66
|
gate.
|
|
67
|
-
generate_csd (
|
|
67
|
+
generate_csd (Optional[Callable]): Function which generates data points outside the swept gate range.
|
|
68
68
|
This is especially required for distortions, which shift the CSD structure. The generated data points
|
|
69
69
|
also have to contain the distortions, which have already been added to the occupation and
|
|
70
70
|
lead_transitions before. Default is None.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import warnings
|
|
7
|
-
from typing import Callable, Tuple, Union
|
|
7
|
+
from typing import Callable, Tuple, Union, Optional
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
|
|
@@ -106,7 +106,7 @@ class OccupationDotJumps(OccupationDistortionInterface):
|
|
|
106
106
|
self.__rng = rng
|
|
107
107
|
|
|
108
108
|
@property
|
|
109
|
-
def activated(self) ->
|
|
109
|
+
def activated(self) -> Optional[bool]:
|
|
110
110
|
"""This is true if the noise was activated during the last call of noise function."""
|
|
111
111
|
return self.__activated
|
|
112
112
|
|
|
@@ -139,14 +139,16 @@ class OccupationDotJumps(OccupationDistortionInterface):
|
|
|
139
139
|
gate.
|
|
140
140
|
volt_limits_g2 (np.ndarray): Contains the beginning and ending of the swept range for the second (plunger)
|
|
141
141
|
gate.
|
|
142
|
-
generate_csd (
|
|
142
|
+
generate_csd (Optional[Callable]): Function which generates data points outside the swept gate range.
|
|
143
143
|
This is especially required for distortions, which shift the CSD structure. The generated data points
|
|
144
144
|
also have to contain the distortions, which have already been added to the occupation and
|
|
145
145
|
lead_transitions before. Defaults to None.
|
|
146
146
|
freeze (bool): Indicates if the last used noise should be reused. This is important if there are noise
|
|
147
147
|
types which need to generate data from outside the current CSD (for example if a part of the structure
|
|
148
148
|
is shifted). This newly generated data also has to contain the noise which already has been applied to
|
|
149
|
-
the CSD before.
|
|
149
|
+
the CSD before. A use case for that is the application of dot jumps in vertical direction after the
|
|
150
|
+
application in horizontal direction. Due to the jumps in vertical direction new data might have to be
|
|
151
|
+
generated with generate_csd. In this data, the horizontal jumps also have to be applied.
|
|
150
152
|
|
|
151
153
|
Returns:
|
|
152
154
|
Tuple[np.ndarray, np.ndarray]: Occupation numbers and lead transition mask (in our case: total charge
|
|
@@ -686,7 +688,7 @@ def dot_jumps_pixelwise(
|
|
|
686
688
|
original: np.ndarray,
|
|
687
689
|
scale: float,
|
|
688
690
|
lam: float,
|
|
689
|
-
noise:
|
|
691
|
+
noise: Optional[np.ndarray] = None,
|
|
690
692
|
rng: np.random.Generator = np.random.default_rng(),
|
|
691
693
|
) -> Tuple[np.ndarray, np.ndarray]:
|
|
692
694
|
"""Adds dot jumps to the original image (pixelwise).
|
|
@@ -707,7 +709,7 @@ def dot_jumps_pixelwise(
|
|
|
707
709
|
this case, scale specifies the length in pixels, so that a jump can start in the middle of a line and end in
|
|
708
710
|
the middle of the next line. Given in pixels.
|
|
709
711
|
lam (float): Lambda for the poisson distribution which specifies the height of the jumps. Given in pixels.
|
|
710
|
-
noise (
|
|
712
|
+
noise (Optional[np.ndarray]): Noise which was generated with this method for a prior image and should be reapplied for
|
|
711
713
|
this image. Default is None.
|
|
712
714
|
rng (np.random.Generator): The random number generator used for the simulation of random numbers. Default is
|
|
713
715
|
np.random.default_rng().
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
@author: s.fleitmann
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from typing import Union
|
|
6
|
+
from typing import Union, Optional
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
|
|
@@ -102,7 +102,7 @@ class RandomTelegraphNoise(DistortionInterface):
|
|
|
102
102
|
self.__rng = rng
|
|
103
103
|
|
|
104
104
|
@property
|
|
105
|
-
def activated(self) ->
|
|
105
|
+
def activated(self) -> Optional[bool]:
|
|
106
106
|
"""This is true if the noise was activated during the last call of noise function."""
|
|
107
107
|
return self.__activated
|
|
108
108
|
|
|
@@ -149,8 +149,8 @@ class RandomTelegraphNoise(DistortionInterface):
|
|
|
149
149
|
)
|
|
150
150
|
else:
|
|
151
151
|
resolution = (original.shape[0], original.shape[0])
|
|
152
|
-
# sweep
|
|
153
|
-
scale *= resolution[0] / (np.max(volt_limits_g1) - np.min(volt_limits_g1))
|
|
152
|
+
# sweep between starting and ending point
|
|
153
|
+
scale *= resolution[0] / np.maximum(np.max(volt_limits_g1) - np.min(volt_limits_g1), np.max(volt_limits_g2) - np.min(volt_limits_g2))
|
|
154
154
|
|
|
155
155
|
try:
|
|
156
156
|
std = self.std.sample_parameter()
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
@author: s.fleitmann
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from typing import Callable, Tuple, Union
|
|
6
|
+
from typing import Callable, Tuple, Union, Optional
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
from scipy.ndimage import gaussian_filter1d
|
|
@@ -39,7 +39,7 @@ class OccupationTransitionBlurringFermiDirac(OccupationDistortionInterface):
|
|
|
39
39
|
self.__sigma = sigma
|
|
40
40
|
|
|
41
41
|
@property
|
|
42
|
-
def latest_sigma(self) ->
|
|
42
|
+
def latest_sigma(self) -> Optional[float]:
|
|
43
43
|
"""The sigma that was used for the latest simulation.
|
|
44
44
|
|
|
45
45
|
This is necessary because, depending on the setting, a sampler can be used instead of a fixed sigma.
|
|
@@ -75,7 +75,7 @@ class OccupationTransitionBlurringFermiDirac(OccupationDistortionInterface):
|
|
|
75
75
|
gate.
|
|
76
76
|
volt_limits_g2 (np.ndarray): Contains the beginning and ending of the swept range for the second (plunger)
|
|
77
77
|
gate.
|
|
78
|
-
generate_csd (
|
|
78
|
+
generate_csd (Optional[Callable]): Function which generates data points outside the swept gate range.
|
|
79
79
|
This is especially required for distortions, which shift the CSD structure. The generated data points
|
|
80
80
|
also have to contain the distortions, which have already been added to the occupation and
|
|
81
81
|
lead_transitions before.
|
|
@@ -155,7 +155,7 @@ class OccupationTransitionBlurringGaussian(OccupationDistortionInterface):
|
|
|
155
155
|
self.__sigma = sigma
|
|
156
156
|
|
|
157
157
|
@property
|
|
158
|
-
def latest_sigma(self) ->
|
|
158
|
+
def latest_sigma(self) -> Optional[float]:
|
|
159
159
|
"""The sigma that was used for the latest simulation.
|
|
160
160
|
|
|
161
161
|
This is necessary because, depending on the setting, a sampler can be used instead of a fixed sigma.
|
|
@@ -191,7 +191,7 @@ class OccupationTransitionBlurringGaussian(OccupationDistortionInterface):
|
|
|
191
191
|
gate.
|
|
192
192
|
volt_limits_g2 (np.ndarray): Contains the beginning and ending of the swept range for the second (plunger)
|
|
193
193
|
gate.
|
|
194
|
-
generate_csd (
|
|
194
|
+
generate_csd (Optional[Callable]): Function which generates data points outside the swept gate range.
|
|
195
195
|
This is especially required for distortions, which shift the CSD structure. The generated data points
|
|
196
196
|
also have to contain the distortions, which have already been added to the occupation and
|
|
197
197
|
lead_transitions before.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
@author: s.fleitmann
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
-
from typing import Union
|
|
6
|
+
from typing import Union, Optional
|
|
7
7
|
|
|
8
8
|
import numpy as np
|
|
9
9
|
|
|
@@ -51,7 +51,7 @@ class SensorResponseWhiteNoise(SensorResponseDistortionInterface):
|
|
|
51
51
|
self.__rng = rng
|
|
52
52
|
|
|
53
53
|
@property
|
|
54
|
-
def latest_sigma(self) ->
|
|
54
|
+
def latest_sigma(self) -> Optional[float]:
|
|
55
55
|
"""The sigma that was used for the latest simulation.
|
|
56
56
|
|
|
57
57
|
This is necessary because, depending on the setting, a sampler can be used instead of a fixed sigma.
|
|
@@ -4,7 +4,7 @@ measurements.
|
|
|
4
4
|
@author: f.hader
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from typing import Callable, Dict,
|
|
7
|
+
from typing import Callable, Dict, Optional
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
|
|
@@ -48,7 +48,7 @@ def generate_lead_transition_mask_2d(
|
|
|
48
48
|
volt_limits_g2: np.ndarray,
|
|
49
49
|
tct_functions: Dict[int, Callable],
|
|
50
50
|
rotation: float = -np.pi / 4,
|
|
51
|
-
lut_entries:
|
|
51
|
+
lut_entries: Optional[int] = None,
|
|
52
52
|
) -> np.ndarray:
|
|
53
53
|
"""Generates the ground truth label mask for the lead transitions of 2D scans.
|
|
54
54
|
|
|
@@ -71,7 +71,7 @@ def generate_lead_transition_mask_2d(
|
|
|
71
71
|
items should be partially initialized versions of the function "tct_bezier".
|
|
72
72
|
rotation (float): The rotation to be applied to the TCT(s) (which is/are usually represented rotated by 45
|
|
73
73
|
degrees). Default is -np.pi/4.
|
|
74
|
-
lut_entries (
|
|
74
|
+
lut_entries (Optional[int]): Number of samples for the lookup-table. If this is not None, a lookup-table will be used to
|
|
75
75
|
evaluate the points on the bezier curve. Default is None.
|
|
76
76
|
|
|
77
77
|
Returns:
|
|
@@ -8,7 +8,7 @@ numbers are calculated without the need for a lead transition mask.
|
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
from functools import partial
|
|
11
|
-
from typing import Callable, Dict, Tuple,
|
|
11
|
+
from typing import Callable, Dict, Tuple, Optional
|
|
12
12
|
|
|
13
13
|
# used to find all regions
|
|
14
14
|
import diplib as dip
|
|
@@ -86,9 +86,9 @@ def get_electron_occupation(
|
|
|
86
86
|
bezier_coords: Dict[int, np.ndarray],
|
|
87
87
|
tct_functions: Dict[int, Callable],
|
|
88
88
|
rotation: float = -np.pi / 4,
|
|
89
|
-
lut_entries:
|
|
89
|
+
lut_entries: Optional[int] = None,
|
|
90
90
|
cdf_type: str = "sigmoid",
|
|
91
|
-
cdf_gamma_factor:
|
|
91
|
+
cdf_gamma_factor: Optional[float] = None,
|
|
92
92
|
) -> np.ndarray:
|
|
93
93
|
"""Calculates the electron occupations for a given CSD represented by a numpy array.
|
|
94
94
|
|
|
@@ -113,11 +113,11 @@ def get_electron_occupation(
|
|
|
113
113
|
system) and the items should be partially initialized versions of the function "tct_bezier".
|
|
114
114
|
rotation (float): The rotation that has been applied to the TCT (which is usually represented with the
|
|
115
115
|
tct_params rotated by 45 degrees). Default: is -np.pi/4.
|
|
116
|
-
lut_entries (
|
|
116
|
+
lut_entries (Optional[int]): Number of samples for the lookup-table for the bezier curves. If this is not
|
|
117
117
|
None, a lookup-table will be used to evaluate the points on the bezier curve. Default is None.
|
|
118
118
|
cdf_type (str): Name of the type of cumulative distribution function (CDF) to be used for interdot transitions.
|
|
119
119
|
Can be either "cauchy" or "sigmoid. Default is "sigmoid".
|
|
120
|
-
cdf_gamma_factor (
|
|
120
|
+
cdf_gamma_factor (Optional[float]): The factor used for the calculation of the gamma values of the CDF.
|
|
121
121
|
If set to None, the default values for the selected cdf_type are used (2.2 for sigmoid, 6.15 for cauchy). \n
|
|
122
122
|
Gamma is calculated as follows: \n
|
|
123
123
|
gamma = width_bezier_curve / cdf_gamma_factor. \n
|
|
@@ -4,7 +4,7 @@ transitions (TCTs), voltage ranges and a desired resolution. It also implements
|
|
|
4
4
|
@author: f.hader
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from typing import List, Tuple, Union
|
|
7
|
+
from typing import List, Tuple, Union, Optional
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
|
|
@@ -25,9 +25,9 @@ def ideal_csd_geometric(
|
|
|
25
25
|
volt_limits_g2: np.ndarray,
|
|
26
26
|
resolution: Union[int, np.ndarray] = np.array([100, 100]),
|
|
27
27
|
rotation: float = -np.pi / 4,
|
|
28
|
-
lut_entries:
|
|
28
|
+
lut_entries: Optional[int] = None,
|
|
29
29
|
cdf_type: str = "sigmoid",
|
|
30
|
-
cdf_gamma_factor:
|
|
30
|
+
cdf_gamma_factor: Optional[float] = None,
|
|
31
31
|
) -> Tuple[np.ndarray, np.ndarray]:
|
|
32
32
|
"""Generate an ideal Charge Stability Diagram (CSD) based on the supplied parameters.
|
|
33
33
|
|
|
@@ -60,12 +60,12 @@ def ideal_csd_geometric(
|
|
|
60
60
|
[res_g1, res_g2]
|
|
61
61
|
rotation (float): Float value defining the rotation to be applied to the TCT (which is usually represented
|
|
62
62
|
with the tct_params rotated by 45 degrees). Default is -np.pi/4.
|
|
63
|
-
lut_entries (
|
|
63
|
+
lut_entries (Optional[int]): Number of samples for the lookup-table for bezier curves. If this is not None, a
|
|
64
64
|
lookup-table will be used to evaluate the points on the bezier curves, else they are solved explicitly.
|
|
65
65
|
Using a lookup-table speeds up the calculation at the possible cost of accuracy. Default is None.
|
|
66
66
|
cdf_type (str): Name of the type of cumulative distribution function (CDF) to be used. Can be either
|
|
67
67
|
"cauchy" or "sigmoid". Default is "sigmoid".
|
|
68
|
-
cdf_gamma_factor (
|
|
68
|
+
cdf_gamma_factor (Optional[float]): The factor used for the calculation of the gamma values of the CDF.
|
|
69
69
|
If set to None (=default) the default values for the selected cdf_type are used. \n
|
|
70
70
|
Gamma is calculated as follows: \n
|
|
71
71
|
gamma = width_bezier_curve / cdf_gamma_factor \n
|
|
@@ -4,7 +4,7 @@ transitions (TCTs), voltage ranges and a desired resolution. It also implements
|
|
|
4
4
|
@author: f.hader
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from typing import List, Tuple, Union
|
|
7
|
+
from typing import List, Tuple, Union, Optional
|
|
8
8
|
|
|
9
9
|
import numpy as np
|
|
10
10
|
|
|
@@ -21,9 +21,9 @@ class IdealCSDGeometric(IdealCSDInterface):
|
|
|
21
21
|
self,
|
|
22
22
|
tct_params: List[np.ndarray],
|
|
23
23
|
rotation: float = -np.pi / 4,
|
|
24
|
-
lut_entries:
|
|
24
|
+
lut_entries: Optional[int] = None,
|
|
25
25
|
cdf_type: str = "sigmoid",
|
|
26
|
-
cdf_gamma_factor:
|
|
26
|
+
cdf_gamma_factor: Optional[float] = None,
|
|
27
27
|
) -> None:
|
|
28
28
|
"""Initializes an object of the class for the geometric simulation approach which is based on total charge
|
|
29
29
|
transitions (TCTs).
|
|
@@ -42,12 +42,12 @@ class IdealCSDGeometric(IdealCSDInterface):
|
|
|
42
42
|
[7] = end position y (bezier curve rightmost point) (in x-/voltage-space, not number of points)
|
|
43
43
|
rotation (float): Float value defining the rotation to be applied to the TCT (which is usually represented
|
|
44
44
|
with the tct_params rotated by 45 degrees). Default is -np.pi/4.
|
|
45
|
-
lut_entries (
|
|
45
|
+
lut_entries (Optional[int]): Number of samples for the lookup-table for bezier curves. If this is not None, a
|
|
46
46
|
lookup-table will be used to evaluate the points on the bezier curves, else they are solved explicitly.
|
|
47
47
|
Using a lookup-table speeds up the calculation at the possible cost of accuracy. Default is None.
|
|
48
48
|
cdf_type (str): Name of the type of cumulative distribution function (CDF) to be used. Can be either
|
|
49
49
|
"cauchy" or "sigmoid". Default is "sigmoid".
|
|
50
|
-
cdf_gamma_factor (
|
|
50
|
+
cdf_gamma_factor (Optional[float]): The factor used for the calculation of the gamma values of the CDF. If set to None
|
|
51
51
|
(=default) the default values for the selected cdf_type are used (2.2 for sigmoid, 6.15 for cauchy).
|
|
52
52
|
Default is None. \n
|
|
53
53
|
Gamma is calculated as follows: \n
|
|
@@ -82,14 +82,14 @@ class IdealCSDGeometric(IdealCSDInterface):
|
|
|
82
82
|
self.__rotation = rotation
|
|
83
83
|
|
|
84
84
|
@property
|
|
85
|
-
def lut_entries(self) ->
|
|
85
|
+
def lut_entries(self) -> Optional[int]:
|
|
86
86
|
"""Number of samples for the lookup-table for bezier curves. If this is not None, a lookup-table will be used to
|
|
87
87
|
evaluate the points on the bezier curves, else they are solved explicitly.
|
|
88
88
|
"""
|
|
89
89
|
return self.__lut_entries
|
|
90
90
|
|
|
91
91
|
@lut_entries.setter
|
|
92
|
-
def lut_entries(self, lut_entries:
|
|
92
|
+
def lut_entries(self, lut_entries: Optional[int]):
|
|
93
93
|
self.__lut_entries = lut_entries
|
|
94
94
|
|
|
95
95
|
@property
|
|
@@ -102,14 +102,14 @@ class IdealCSDGeometric(IdealCSDInterface):
|
|
|
102
102
|
self.__cdf_type = cdf_type
|
|
103
103
|
|
|
104
104
|
@property
|
|
105
|
-
def cdf_gamma_factor(self) ->
|
|
105
|
+
def cdf_gamma_factor(self) -> Optional[float]:
|
|
106
106
|
"""The factor used for the calculation of the gamma values of the CDF. If set to None (=default) the default values
|
|
107
107
|
for the selected cdf_type are used (2.2 for sigmoid, 6.15 for cauchy).
|
|
108
108
|
"""
|
|
109
109
|
return self.__cdf_gamma_factor
|
|
110
110
|
|
|
111
111
|
@cdf_gamma_factor.setter
|
|
112
|
-
def cdf_gamma_factor(self, cdf_gamma_factor:
|
|
112
|
+
def cdf_gamma_factor(self, cdf_gamma_factor: Optional[float]):
|
|
113
113
|
self.__cdf_gamma_factor = cdf_gamma_factor
|
|
114
114
|
|
|
115
115
|
def get_csd_data(
|
|
@@ -9,7 +9,7 @@ import math
|
|
|
9
9
|
|
|
10
10
|
# used to check if a single x-value was passed to x_eval
|
|
11
11
|
import numbers
|
|
12
|
-
from typing import Union
|
|
12
|
+
from typing import Union, Optional
|
|
13
13
|
|
|
14
14
|
import bezier
|
|
15
15
|
import numpy as np
|
|
@@ -19,8 +19,8 @@ import sympy
|
|
|
19
19
|
def tct_bezier(
|
|
20
20
|
tct_params: np.ndarray,
|
|
21
21
|
x_eval: Union[np.ndarray, numbers.Number],
|
|
22
|
-
lut_entries:
|
|
23
|
-
max_peaks:
|
|
22
|
+
lut_entries: Optional[int] = None,
|
|
23
|
+
max_peaks: Optional[int] = None,
|
|
24
24
|
) -> Union[np.ndarray, numbers.Number]:
|
|
25
25
|
"""Evaluates a total charge transition (TCT) with bezier curves and linear parts.
|
|
26
26
|
A TCT separates the region with n electrons and the region with n+1 electrons in the system. The TCTs (series of
|
|
@@ -38,9 +38,9 @@ def tct_bezier(
|
|
|
38
38
|
[6] = end position x (bezier curve rightmost point) (in x-/voltage-space, not number of points) \n
|
|
39
39
|
[7] = end position y (bezier curve rightmost point) (in x-/voltage-space, not number of points)
|
|
40
40
|
x_eval (Union[np.ndarray, numbers.Number]): X-values for which the function is evaluated or a single x-value.
|
|
41
|
-
lut_entries (
|
|
41
|
+
lut_entries (Optional[int]): Number of samples for the lookup-table. If this is not None, a lookup-table will
|
|
42
42
|
be used to evaluate the points on the bezier curve, else it is solved explicitly. Default is None.
|
|
43
|
-
max_peaks (
|
|
43
|
+
max_peaks (Optional[int]): Limit for the number of peaks of the TCT. If multiple TCTs are supplied, max_peaks
|
|
44
44
|
is increased by 1 for every further wavefront. If None, all TCTs have an unlimited number of peaks and no
|
|
45
45
|
outer linear part. Default is None.
|
|
46
46
|
|
simcats/sensor/__init__.py
CHANGED
|
@@ -2,10 +2,14 @@
|
|
|
2
2
|
SimCATS subpackage containing all functionalities related to the sensor simulation.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from simcats.sensor._sensor_interface import SensorPeakInterface, SensorInterface
|
|
6
|
-
|
|
7
|
-
from simcats.sensor.
|
|
8
|
-
from simcats.sensor.
|
|
5
|
+
from simcats.sensor._sensor_interface import SensorPeakInterface, SensorRiseInterface, SensorInterface, \
|
|
6
|
+
SensorScanSensorInterface
|
|
7
|
+
from simcats.sensor._sensor_peak_gaussian import SensorPeakGaussian, sensor_response_gauss
|
|
8
|
+
from simcats.sensor._sensor_peak_lorentzian import SensorPeakLorentzian, sensor_response_lorentz
|
|
9
|
+
from simcats.sensor._sensor_rise_glf import SensorRiseGLF
|
|
10
|
+
from simcats.sensor._sensor_generic import SensorGeneric
|
|
11
|
+
from simcats.sensor._sensor_scan_sensor_generic import SensorScanSensorGeneric
|
|
9
12
|
|
|
10
|
-
__all__ = ["SensorPeakInterface", "
|
|
11
|
-
"
|
|
13
|
+
__all__ = ["SensorPeakInterface", "SensorRiseInterface", "SensorInterface", "SensorScanSensorInterface",
|
|
14
|
+
"SensorPeakGaussian", "SensorPeakLorentzian", "SensorRiseGLF", "SensorGeneric",
|
|
15
|
+
"SensorScanSensorGeneric", "sensor_response_gauss", "sensor_response_lorentz"]
|
|
@@ -155,7 +155,7 @@ class SensorGeneric(SensorInterface):
|
|
|
155
155
|
def __repr__(self):
|
|
156
156
|
return (
|
|
157
157
|
self.__class__.__name__
|
|
158
|
-
+ f"(sensor_peak_function={self.__sensor_peak_function}, alpha_dot={self.__alpha_dot}, alpha_gate={self.__alpha_gate}, offset_mu_sens={self.__offset_mu_sens})"
|
|
158
|
+
+ f"(sensor_peak_function={self.__sensor_peak_function}, alpha_dot={repr(self.__alpha_dot)}, alpha_gate={repr(self.__alpha_gate)}, offset_mu_sens={self.__offset_mu_sens})"
|
|
159
159
|
)
|
|
160
160
|
|
|
161
161
|
def sensor_response(self, mu_sens: np.ndarray) -> np.ndarray:
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"""This module contains functions for simulating the sensor response for a charge stability diagram (CSD) including the
|
|
2
2
|
cross coupling between the sensor and double dot (plunger) gates.
|
|
3
3
|
|
|
4
|
-
@author: f.hader
|
|
4
|
+
@author: f.hader, b.papajewski
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from abc import ABC, abstractmethod
|
|
8
|
-
from typing import List, Union
|
|
8
|
+
from typing import List, Union, Optional
|
|
9
9
|
|
|
10
10
|
import numpy as np
|
|
11
11
|
|
|
@@ -18,6 +18,17 @@ class SensorPeakInterface(ABC):
|
|
|
18
18
|
Implementations of the SensorInterface can consist of multiple peaks.
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
|
+
@property
|
|
22
|
+
@abstractmethod
|
|
23
|
+
def mu0(self) -> Optional[float]:
|
|
24
|
+
"""Mu0 of the sensor peak.
|
|
25
|
+
This property represents the potential value at which the sensor peak reaches its maximum.
|
|
26
|
+
|
|
27
|
+
The method is needed for the generation of labels of scans. An example for that is the generation of labels for
|
|
28
|
+
sensor scans.
|
|
29
|
+
"""
|
|
30
|
+
raise NotImplementedError()
|
|
31
|
+
|
|
21
32
|
@abstractmethod
|
|
22
33
|
def sensor_function(self, mu_sens: np.ndarray) -> np.ndarray:
|
|
23
34
|
"""This method has to be implemented in every object which should be used as sensor peak function during the simulation of CSDs.
|
|
@@ -39,16 +50,48 @@ class SensorPeakInterface(ABC):
|
|
|
39
50
|
return self.__class__.__name__ + str(self.__dict__)
|
|
40
51
|
|
|
41
52
|
|
|
53
|
+
class SensorRiseInterface(ABC):
|
|
54
|
+
"""Interface for all sensor rise functions that model a final rise of the sensor response.
|
|
55
|
+
|
|
56
|
+
This type of rise is needed to simulate the rise at the end of a sensor function, that can be observed in sensor
|
|
57
|
+
scans.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
@abstractmethod
|
|
62
|
+
def fully_conductive(self) -> float:
|
|
63
|
+
"""Potential value of the point at which the sensor rise reaches its maximum."""
|
|
64
|
+
raise NotImplementedError
|
|
65
|
+
|
|
66
|
+
@abstractmethod
|
|
67
|
+
def sensor_function(self, mu_sens: np.ndarray, offset: float) -> np.ndarray:
|
|
68
|
+
"""This method has to be implemented in every object which should be used as sensor rise function during the simulation of CSDs.
|
|
69
|
+
|
|
70
|
+
This function should return the sensor (rise) values which result from the given electrochemical potential.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
mu_sens (np.ndarray): The sensor potential, stored in a numpy array with the axis mapping to the scan axis.
|
|
74
|
+
offset (float): Potential value to which the fully conductive point is shifted.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
np.ndarray: The sensor response (for the corresponding rise), calculated from the given potential. It is
|
|
78
|
+
stored in a numpy array with the axis mapping to the CSD axis.
|
|
79
|
+
"""
|
|
80
|
+
raise NotImplementedError()
|
|
81
|
+
|
|
82
|
+
def __repr__(self) -> str:
|
|
83
|
+
return self.__class__.__name__ + str(self.__dict__)
|
|
84
|
+
|
|
85
|
+
|
|
42
86
|
class SensorInterface(ABC):
|
|
43
87
|
"""Interface for all sensor functions, which are used in the simulation of CSDs."""
|
|
44
88
|
|
|
45
89
|
@abstractmethod
|
|
46
|
-
def __init__(
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
offset_mu_sens: float,
|
|
90
|
+
def __init__(self,
|
|
91
|
+
sensor_peak_function: Union[SensorPeakInterface, List[SensorPeakInterface]],
|
|
92
|
+
alpha_dot: np.ndarray,
|
|
93
|
+
alpha_gate: np.ndarray,
|
|
94
|
+
offset_mu_sens: float,
|
|
52
95
|
) -> None:
|
|
53
96
|
"""Initializes an object of the class for the simulation of the sensor response for a CSD.
|
|
54
97
|
|
|
@@ -69,7 +112,7 @@ class SensorInterface(ABC):
|
|
|
69
112
|
|
|
70
113
|
The electrochemical potential at the sensor should be given as one- or two-dimensional numpy array to this
|
|
71
114
|
function. The parameters for this sensor function should be attributes of this class. This function should
|
|
72
|
-
return the sensor
|
|
115
|
+
return the sensor response which result from the given electrochemical potential.
|
|
73
116
|
|
|
74
117
|
Args:
|
|
75
118
|
mu_sens (np.ndarray): The sensor potential, stored in a 2-dimensional numpy array with the axis mapping to
|
|
@@ -82,8 +125,10 @@ class SensorInterface(ABC):
|
|
|
82
125
|
raise NotImplementedError
|
|
83
126
|
|
|
84
127
|
@abstractmethod
|
|
85
|
-
def sensor_potential(
|
|
86
|
-
|
|
128
|
+
def sensor_potential(self,
|
|
129
|
+
occupations: np.ndarray,
|
|
130
|
+
volt_limits_g1: np.ndarray,
|
|
131
|
+
volt_limits_g2: np.ndarray
|
|
87
132
|
) -> np.ndarray:
|
|
88
133
|
"""Simulates the electrochemical potential at the sensing dot.
|
|
89
134
|
|
|
@@ -106,3 +151,111 @@ class SensorInterface(ABC):
|
|
|
106
151
|
|
|
107
152
|
def __repr__(self) -> str:
|
|
108
153
|
return self.__class__.__name__ + str(self.__dict__)
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class SensorScanSensorInterface(SensorInterface):
|
|
157
|
+
def __init__(self,
|
|
158
|
+
sensor_peak_function: Union[SensorPeakInterface, List[SensorPeakInterface], None],
|
|
159
|
+
alpha_dot: np.ndarray,
|
|
160
|
+
alpha_gate: np.ndarray,
|
|
161
|
+
alpha_sensor_gate: np.ndarray,
|
|
162
|
+
offset_mu_sens: np.ndarray,
|
|
163
|
+
) -> None:
|
|
164
|
+
"""This method initializes an object of the class SensorScanSensorInterface.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
sensor_peak_function (Union[SensorPeakInterface, List[SensorPeakInterface], None]): An implementation of the
|
|
168
|
+
SensorPeakInterface. It is also possible to supply a list of such peaks, if a sensor with multiple peaks
|
|
169
|
+
should be simulated.
|
|
170
|
+
alpha_dot (np.ndarray): Lever-arm of the dots for the sensor potential(s). The values should be negative.
|
|
171
|
+
alpha_gate (np.ndarray): Lever-arm of the gates for the sensor potential(s). The values should be positive.
|
|
172
|
+
alpha_sensor_gate (np.ndarray): Lever-arm of the sensor gates for the sensor potential(s). The values should
|
|
173
|
+
be positive.
|
|
174
|
+
offset_mu_sens (np.ndarray): Electrochemical potential of the sensor dot for zero electrons in the dots and
|
|
175
|
+
no applied voltage at the gates.
|
|
176
|
+
"""
|
|
177
|
+
raise NotImplementedError
|
|
178
|
+
|
|
179
|
+
@abstractmethod
|
|
180
|
+
def sensor_potential(self,
|
|
181
|
+
occupations: np.ndarray,
|
|
182
|
+
volt_limits_g1: Union[np.ndarray, float, None],
|
|
183
|
+
volt_limits_g2: Union[np.ndarray, float, None],
|
|
184
|
+
volt_limits_sensor_g1: Union[np.ndarray, float, None],
|
|
185
|
+
volt_limits_sensor_g2: Union[np.ndarray, float, None]
|
|
186
|
+
) -> np.ndarray:
|
|
187
|
+
"""Simulates the electrochemical potential at the sensor dot and both barriers.
|
|
188
|
+
|
|
189
|
+
This is done in dependency on the electron occupation in the double dot, the voltages applied at the double
|
|
190
|
+
dot (plunger) gates, and voltages applied at the gates of sensor.
|
|
191
|
+
Either the double dot gates or the sensor gates can be swept.
|
|
192
|
+
|
|
193
|
+
Args:
|
|
194
|
+
occupations (np.ndarray): Occupation in left and right dot per applied voltage combination. The occupation
|
|
195
|
+
numbers are stored in a 3-dimensional numpy array. The first two dimensions map to the axis of the CSD,
|
|
196
|
+
while the third dimension indicates the dot of the corresponding occupation value.
|
|
197
|
+
volt_limits_g1 (Union[np.ndarray, float, None]): Voltages applied to the first (plunger) gate of the double
|
|
198
|
+
dot. When a fixed voltage is applied this is a float and when this gate should be swept it is a numpy
|
|
199
|
+
array with the minimum and maximum of the sweep.
|
|
200
|
+
volt_limits_g2 (Union[np.ndarray, float, None]): Voltages applied to the second (plunger) gate of the double
|
|
201
|
+
dot. When a fixed voltage is applied this is a float and when this gate should be swept it is a numpy
|
|
202
|
+
array with the minimum and maximum of the sweep.
|
|
203
|
+
volt_limits_sensor_g1 (Union[np.ndarray, float, None]): Voltages applied to the first sensor gate.
|
|
204
|
+
When a fixed voltage is applied this is a float and when this gate should be swept it is a numpy array
|
|
205
|
+
with the minimum and maximum of the sweep.
|
|
206
|
+
volt_limits_sensor_g2 (Union[np.ndarray, float, None]): voltages applied to the second sensor gate.
|
|
207
|
+
When a fixed voltage is applied this is a float and when this gate should be swept it is a numpy array
|
|
208
|
+
with the minimum and maximum of the sweep.
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
np.ndarray: The electrochemical potential of the sensor dot, and both barrier. It is returned as a
|
|
212
|
+
three-dimensional array with the shape (3, occupations.shape[0], occupations.shape[1]). The first dimension
|
|
213
|
+
corresponds to the three potentials involved. It is structured as follows:
|
|
214
|
+
[sensor dot potential, barrier 1 potential, barrier 2 potential]
|
|
215
|
+
The remaining two dimensions correspond to the swept voltages.
|
|
216
|
+
"""
|
|
217
|
+
raise NotImplementedError
|
|
218
|
+
|
|
219
|
+
def get_sensor_scan_labels(self,
|
|
220
|
+
volt_limits_g1: Union[np.ndarray, float, None],
|
|
221
|
+
volt_limits_g2: Union[np.ndarray, float, None],
|
|
222
|
+
volt_limits_sensor_g1: Union[np.ndarray, float, None],
|
|
223
|
+
volt_limits_sensor_g2: Union[np.ndarray, float, None],
|
|
224
|
+
potential: np.ndarray) -> np.ndarray:
|
|
225
|
+
"""This method returns the labels of the sensor scans.
|
|
226
|
+
|
|
227
|
+
There are two labels for sensor scans: the conductive area mask and the Coulomb peak mask. Both masks are numpy
|
|
228
|
+
arrays that consist of integers.
|
|
229
|
+
The conductive area mask marks the non-conductive area, sensor oscillation regime, and fully conductive area.
|
|
230
|
+
The non-conductive area is marked with 0. This is the area in which no electron can tunnel or flow through the
|
|
231
|
+
sensor dot. The sensor oscillation regime is the area in which the barriers are open enough for oscillations to
|
|
232
|
+
occur, as electrons tunnel periodically. This area is marked with 1. In the third area, the conductive area,
|
|
233
|
+
both barriers are fully open and transport occurs as a continuous current rather than through a well-defined
|
|
234
|
+
sensor dot. The fully conductive area is marked with 2.
|
|
235
|
+
The Coulomb peak mask marks the peaks of the Coulomb peak as integers. The wave fronts are marked with values
|
|
236
|
+
higher or equal to one. All maxima belonging to the same Coulomb peak are marked with the same integer.
|
|
237
|
+
Depending on the potential value, the various Coulomb peaks are marked with ascending values.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
volt_limits_g1 (Union[np.ndarray, float, None]): Voltages applied to the first double dot (plunger) gate.
|
|
241
|
+
When a fixed voltage is applied this is a float and when this gate should be swept it is a numpy array
|
|
242
|
+
with the minimum and maximum of the sweep. None can also be passed if no voltage is applied.
|
|
243
|
+
volt_limits_g2 (Union[np.ndarray, float, None]): Voltages applied to the second double dot(plunger) gate.
|
|
244
|
+
When a fixed voltage is applied this is a float and when this gate should be swept it is a numpy array
|
|
245
|
+
with the minimum and maximum of the sweep. None can also be passed if no voltage is applied.
|
|
246
|
+
volt_limits_sensor_g1 (Union[np.ndarray, float, None]): Voltages applied to the first sensor gate.
|
|
247
|
+
When a fixed voltage is applied this is a float and when this gate should be swept it is a numpy array
|
|
248
|
+
with the minimum and maximum of the sweep. None can also be passed if no voltage is applied.
|
|
249
|
+
volt_limits_sensor_g2 (Union[np.ndarray, float, None]): Voltages applied to the second sensor gate.
|
|
250
|
+
When a fixed voltage is applied this is a float and when this gate should be swept it is a numpy array
|
|
251
|
+
with the minimum and maximum of the sweep. None can also be passed if no voltage is applied.
|
|
252
|
+
potential (np.ndarray): Numpy array that contains the potential of the area for which labels should be
|
|
253
|
+
generated. This potential must correspond to the voltages specified for volt_limits_g1,
|
|
254
|
+
volt_limits_g2, volt_limits_sensor_g1 and volt_limits_sensor_g2.
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
(np.ndarray, np.ndarray): Tuple with the two numpy arrays of the two labels of sensor scan.
|
|
258
|
+
The returned tuple looks like: (conductive area mask, coulomb peak mask). Both arrays have the same shape
|
|
259
|
+
as the provided potential.
|
|
260
|
+
"""
|
|
261
|
+
raise NotImplementedError
|