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.
Files changed (42) hide show
  1. simcats/__init__.py +4 -3
  2. simcats/_default_configs.py +129 -13
  3. simcats/_simulation.py +451 -69
  4. simcats/config_samplers/_GaAs_v1_random_variations_v3_config_sampler.py +1059 -0
  5. simcats/config_samplers/__init__.py +9 -0
  6. simcats/distortions/_distortion_interfaces.py +1 -1
  7. simcats/distortions/_dot_jumps.py +8 -6
  8. simcats/distortions/_random_telegraph_noise.py +4 -4
  9. simcats/distortions/_transition_blurring.py +5 -5
  10. simcats/distortions/_white_noise.py +2 -2
  11. simcats/ideal_csd/geometric/_generate_lead_transition_mask.py +3 -3
  12. simcats/ideal_csd/geometric/_get_electron_occupation.py +5 -5
  13. simcats/ideal_csd/geometric/_ideal_csd_geometric.py +5 -5
  14. simcats/ideal_csd/geometric/_ideal_csd_geometric_class.py +9 -9
  15. simcats/ideal_csd/geometric/_tct_bezier.py +5 -5
  16. simcats/sensor/__init__.py +10 -6
  17. simcats/sensor/{_generic_sensor.py → _sensor_generic.py} +1 -1
  18. simcats/sensor/_sensor_interface.py +164 -11
  19. simcats/sensor/_sensor_rise_glf.py +229 -0
  20. simcats/sensor/_sensor_scan_sensor_generic.py +929 -0
  21. simcats/sensor/barrier_function/__init__.py +9 -0
  22. simcats/sensor/barrier_function/_barrier_function_glf.py +280 -0
  23. simcats/sensor/barrier_function/_barrier_function_interface.py +43 -0
  24. simcats/sensor/barrier_function/_barrier_function_multi_glf.py +157 -0
  25. simcats/sensor/deformation/__init__.py +9 -0
  26. simcats/sensor/deformation/_sensor_peak_deformation_circle.py +109 -0
  27. simcats/sensor/deformation/_sensor_peak_deformation_interface.py +65 -0
  28. simcats/sensor/deformation/_sensor_peak_deformation_linear.py +77 -0
  29. simcats/support_functions/__init__.py +11 -3
  30. simcats/support_functions/_generalized_logistic_function.py +146 -0
  31. simcats/support_functions/_linear_algebra.py +171 -0
  32. simcats/support_functions/_parameter_sampling.py +108 -19
  33. simcats/support_functions/_pixel_volt_transformation.py +24 -0
  34. simcats/support_functions/_reset_offset_mu_sens.py +43 -0
  35. {simcats-1.1.0.dist-info → simcats-2.0.0.dist-info}/METADATA +93 -29
  36. simcats-2.0.0.dist-info/RECORD +53 -0
  37. {simcats-1.1.0.dist-info → simcats-2.0.0.dist-info}/WHEEL +1 -1
  38. simcats-1.1.0.dist-info/RECORD +0 -37
  39. /simcats/sensor/{_gaussian_sensor_peak.py → _sensor_peak_gaussian.py} +0 -0
  40. /simcats/sensor/{_lorentzian_sensor_peak.py → _sensor_peak_lorentzian.py} +0 -0
  41. {simcats-1.1.0.dist-info → simcats-2.0.0.dist-info/licenses}/LICENSE +0 -0
  42. {simcats-1.1.0.dist-info → simcats-2.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,9 @@
1
+ """
2
+ SimCATS subpackage of the sensor package containing all functionalities related to barrier functions.
3
+ """
4
+
5
+ from simcats.sensor.barrier_function._barrier_function_interface import BarrierFunctionInterface
6
+ from simcats.sensor.barrier_function._barrier_function_glf import BarrierFunctionGLF
7
+ from simcats.sensor.barrier_function._barrier_function_multi_glf import BarrierFunctionMultiGLF
8
+
9
+ __all__ = ['BarrierFunctionInterface', 'BarrierFunctionGLF', 'BarrierFunctionMultiGLF']
@@ -0,0 +1,280 @@
1
+ """This module contains a class that models the conductivity of a barrier using the generalized logistic function (GLF).
2
+
3
+ @author: b.papajewski
4
+ """
5
+
6
+ from typing import Union
7
+
8
+ import numpy as np
9
+
10
+ from simcats.sensor.barrier_function import BarrierFunctionInterface
11
+ from simcats.support_functions import glf, inverse_glf
12
+
13
+ __all__ = []
14
+
15
+
16
+ class BarrierFunctionGLF(BarrierFunctionInterface):
17
+ """Implementation of the BarrierFunctionInterface that models a conductivity off of a barrier using a generalized logistic function (GLF).
18
+
19
+ For further information see: https://en.wikipedia.org/wiki/Generalised_logistic_function
20
+ """
21
+
22
+ def __init__(self, pinch_off_percentage: float, fully_conductive_percentage: float, asymptote_left: float,
23
+ asymptote_right: float, growth_rate: float, asymmetry: float, shape_factor: float,
24
+ denominator_offset: float = 1, offset: float = 0):
25
+ """
26
+ Initializes an object of the class to represent the barrier function using the generalized logistic function.
27
+ For further information see: https://en.wikipedia.org/wiki/Generalised_logistic_function
28
+
29
+ Args:
30
+ pinch_off_percentage (float): Percentage of the GLF height before which the barrier response is
31
+ considered non-conductive. The height is defined as the absolute difference between the two asymptotes.
32
+ fully_conductive_percentage (float): Percentage of the GLF height after which the barrier response is
33
+ considered fully conductive. The height is defined as the absolute difference between the two
34
+ asymptotes.
35
+ asymptote_left (float): Originally called A. This parameter is the left horizontal asymptote of the
36
+ function. Any rational number can be used as the left asymptote. This parameter may take any rational
37
+ number.
38
+ asymptote_right (float): Originally called K. Specifies the right horizontal asymptote of the function
39
+ when denominator_offset=1. If asymptote_left=0 and denominator_offset=1 then this parameter is also
40
+ called the carrying capacity. This parameter may take any rational number.
41
+ growth_rate (float): Originally called B. The growth rate of the function. The value must be a float and can
42
+ be any rational number. Be careful with negative values, because the function is mirrored on a vertical
43
+ straight line for these. This line passes through the point where the potential equals `offset`.
44
+ asymmetry (float): Originally called nu. This parameter introduces skew and affects symmetry. It also
45
+ affects near which asymptote maximum growth occurs. The value of asymmetry must be a rational number
46
+ greater than zero. \n
47
+ - `asymmetry > 1`: the curve rises more gradually before the midpoint and more sharply after. \n
48
+ - `asymmetry < 1`: the curve rises quickly early on and levels off more slowly.
49
+ shape_factor (float): Originally called Q. is related to the value Y(0) and adjusts the curve's value at the
50
+ y-intercept. Thereby it changes the shape of the function without changing the asymptotes. The shape
51
+ factor can be any rational number.
52
+ denominator_offset (float): Originally called C. A constant added to the denominator inside the power.
53
+ Controls the initial level of the denominator.This parameter must be a rational number. It typically
54
+ takes a value of 1. Otherwise, the upper asymptote is \n
55
+ asymptote_left + (asymptote_right-asymptote_left)/(denominator_offset^(1/asymmetry)).
56
+ offset (float): Potential offset that shifts the GLF starting from the zero point. If the offset is
57
+ positive, the function is shifted to the right and if it is negative, it is shifted to the left. Default
58
+ is 0.
59
+ """
60
+ self.pinch_off_percentage = pinch_off_percentage
61
+ self.fully_conductive_percentage = fully_conductive_percentage
62
+ self.asymptote_left = asymptote_left
63
+ self.asymptote_right = asymptote_right
64
+ self.growth_rate = growth_rate
65
+ self.asymmetry = asymmetry
66
+ self.shape_factor = shape_factor
67
+ self.denominator_offset = denominator_offset
68
+ self.offset = offset
69
+
70
+ def get_value(self, potential: Union[float, np.ndarray]) -> float:
71
+ """Returns the value of the barrier function for a given potential.
72
+
73
+ Args:
74
+ potential (Union[float, np.ndarray]): Potential for which the conductance of the barrier function is to be
75
+ calculated.
76
+
77
+ Returns:
78
+ Union[float, np.ndarray]: Value of the barrier function for a given potential.
79
+ """
80
+ return glf(potential=potential, asymptote_left=self.asymptote_left, asymptote_right=self.asymptote_right,
81
+ growth_rate=self.growth_rate, asymmetry=self.asymmetry, shape_factor=self.shape_factor,
82
+ denominator_offset=self.denominator_offset, offset=self.offset)
83
+
84
+ @property
85
+ def pinch_off(self) -> float:
86
+ """Potential value of the pinch off."""
87
+ return inverse_glf(
88
+ value=np.abs(self.asymptote_right - self.asymptote_left) * self.pinch_off_percentage + np.min(
89
+ [self.asymptote_left, self.asymptote_right]),
90
+ asymptote_left=self.asymptote_left,
91
+ asymptote_right=self.asymptote_right,
92
+ growth_rate=self.growth_rate,
93
+ asymmetry=self.asymmetry,
94
+ shape_factor=self.shape_factor,
95
+ denominator_offset=self.denominator_offset,
96
+ offset=self.offset
97
+ )
98
+
99
+ @property
100
+ def pinch_off_percentage(self) -> float:
101
+ """Percentage of the GLF height before which the barrier response is considered non-conductive. The height is
102
+ defined as the absolute difference between the two asymptotes."""
103
+ return self.__pinch_off_percentage
104
+
105
+ @pinch_off_percentage.setter
106
+ def pinch_off_percentage(self, pinch_off_percentage: float) -> None:
107
+ """Updates the pinch of percentage.
108
+
109
+ Args:
110
+ pinch_off_percentage (float): Potential value of the pinch off
111
+ """
112
+ self.__pinch_off_percentage = pinch_off_percentage
113
+
114
+ @property
115
+ def fully_conductive(self) -> float:
116
+ """Potential value of the point from which on the barrier vanishes and becomes fully conductive."""
117
+ return inverse_glf(
118
+ value=np.abs(self.asymptote_right - self.asymptote_left) * self.fully_conductive_percentage + np.min(
119
+ [self.asymptote_left, self.asymptote_right]),
120
+ asymptote_left=self.asymptote_left,
121
+ asymptote_right=self.asymptote_right,
122
+ growth_rate=self.growth_rate,
123
+ asymmetry=self.asymmetry,
124
+ shape_factor=self.shape_factor,
125
+ denominator_offset=self.denominator_offset,
126
+ offset=self.offset
127
+ )
128
+
129
+ @property
130
+ def fully_conductive_percentage(self) -> float:
131
+ """Percentage of the GLF height after which the barrier response is considered fully conductive. The height is
132
+ defined as the absolute difference between the two asymptotes."""
133
+ return self.__fully_conductive_percentage
134
+
135
+ @fully_conductive_percentage.setter
136
+ def fully_conductive_percentage(self, fully_conductive_percentage: float) -> None:
137
+ """Updates the fully conductive percentage.
138
+
139
+ Args:
140
+ fully_conductive_percentage (float): Potential value of the fully conductive point.
141
+ """
142
+ self.__fully_conductive_percentage = fully_conductive_percentage
143
+
144
+ @property
145
+ def asymptote_left(self):
146
+ """Originally called A. This parameter is the left horizontal asymptote of the function. Any rational number can
147
+ be used as the left asymptote. This parameter may take any rational number.
148
+ """
149
+ return self.__asymptote_left
150
+
151
+ @asymptote_left.setter
152
+ def asymptote_left(self, asymptote_left: float) -> None:
153
+ """Updates the left horizontal asymptote of the GLF.
154
+
155
+ Args:
156
+ asymptote_left (float): Left horizontal asymptote of the GLF. The value must be a float and can be any
157
+ rational number.
158
+ """
159
+ self.__asymptote_left = asymptote_left
160
+
161
+ @property
162
+ def asymptote_right(self):
163
+ """Originally called K. Specifies the right horizontal asymptote of the function when denominator_offset=1. If
164
+ asymptote_left=0 and denominator_offset=1 then this parameter is also called the carrying capacity. This
165
+ parameter may take any rational number.
166
+ """
167
+ return self.__asymptote_right
168
+
169
+ @asymptote_right.setter
170
+ def asymptote_right(self, asymptote_right: float) -> None:
171
+ """Updates the right horizontal asymptote of the GLF.
172
+
173
+ Args:
174
+ asymptote_right (float): Right horizontal asymptote of the GLF. The value must be a float and can be any
175
+ rational number.
176
+ """
177
+ self.__asymptote_right = asymptote_right
178
+
179
+ @property
180
+ def growth_rate(self):
181
+ """Originally called B. The growth rate of the function. The value must be a float and can´be any rational
182
+ number. Be careful with negative values, because the function is mirrored on a vertical straight line for these.
183
+ This line passes through the point where the potential equals `offset`.
184
+ """
185
+ return self.__growth_rate
186
+
187
+ @growth_rate.setter
188
+ def growth_rate(self, growth_rate: float) -> None:
189
+ """Updates the growth rate of the GLF.
190
+
191
+ Args:
192
+ growth_rate (float): Growth rate of the GLF. The value must be a float and can be any rational number.
193
+ """
194
+ self.__growth_rate = growth_rate
195
+
196
+ @property
197
+ def asymmetry(self):
198
+ """Originally called nu. This parameter introduces skew and affects symmetry. It also affects near which
199
+ asymptote maximum growth occurs. The value of asymmetry must be a rational number greater than zero. \n
200
+ - If `asymmetry > 1`: the curve rises more gradually before the midpoint and more sharply after. \n
201
+ - If `asymmetry < 1`: the curve rises quickly early on and levels off more slowly.
202
+ """
203
+ return self.__asymmetry
204
+
205
+ @asymmetry.setter
206
+ def asymmetry(self, asymmetry: float) -> None:
207
+ """Updates asymmetry, which affects near which asymptote maximum growth occurs. The value of asymmetry must be
208
+ a rational number greater than zero.
209
+
210
+ Args:
211
+ asymmetry (float): Asymmetry of the GLF. The value must be a float and can be any rational number greater
212
+ than zero.
213
+ """
214
+ if asymmetry <= 0:
215
+ raise ValueError(f"asymmetry should be positive, but was {asymmetry}")
216
+ self.__asymmetry = asymmetry
217
+
218
+ @property
219
+ def shape_factor(self):
220
+ """Originally called Q. is related to the value Y(0) and adjusts the curve’s value at the y-intercept. Thereby
221
+ it changes the shape of the function without changing the asymptotes. The shape factor can be any rational
222
+ number."""
223
+ return self.__shape_factor
224
+
225
+ @shape_factor.setter
226
+ def shape_factor(self, shape_factor: float) -> None:
227
+ """Updates shape_factor, which is related the value Y(0). The value can be any rational number.
228
+
229
+ Args:
230
+ shape_factor (float): Shape factor of the GLF. The value must be a float and can be any rational number.
231
+ """
232
+ self.__shape_factor = shape_factor
233
+
234
+ @property
235
+ def denominator_offset(self) -> float:
236
+ """Originally called C. A constant added to the denominator inside the power. Controls the initial level of the
237
+ denominator.This parameter must be a rational number. It typically takes a value of 1. Otherwise, the upper
238
+ asymptote is \n
239
+ asymptote_left + (asymptote_right-asymptote_left)/(denominator_offset^(1/asymmetry)).
240
+ """
241
+ return self.__denominator_offset
242
+
243
+ @denominator_offset.setter
244
+ def denominator_offset(self, denominator_offset: float) -> None:
245
+ """Originally called C. A constant added to the denominator inside the power. Controls the initial level of the
246
+ denominator.This parameter must be a rational number. It typically takes a value of 1. Otherwise, the upper
247
+ asymptote is \n
248
+ asymptote_left + (asymptote_right-asymptote_left)/(denominator_offset^(1/asymmetry)).
249
+
250
+ Args:
251
+ denominator_offset (float): Denominator offset of the GLF. The value must be a float and can be any rational
252
+ number.
253
+ """
254
+ self.__denominator_offset = denominator_offset
255
+
256
+ @property
257
+ def offset(self) -> float:
258
+ """Attribute that shifts the GLF starting from the zero point. If the offset is positive, the function is
259
+ shifted to the right and if it is negative, it is shifted to the left. Default is 0.
260
+ """
261
+ return self.__offset
262
+
263
+ @offset.setter
264
+ def offset(self, offset: float) -> None:
265
+ """Updates the potential offset of the GLF. This value shifts the GLF in relation to the zero point.
266
+
267
+ Args:
268
+ offset (float): Potential offset of the GLF. The value must be a float and can be any rational number.
269
+ """
270
+ self.__offset = offset
271
+
272
+ def __repr__(self):
273
+ return (
274
+ self.__class__.__name__
275
+ + f"(pinch_off_percentage={self.pinch_off_percentage}, "
276
+ f"fully_conductive_percentage={self.fully_conductive_percentage}, "
277
+ f"asymptote_left={self.asymptote_left}, asymptote_right={self.asymptote_right}, "
278
+ f"growth_rate={self.growth_rate}, asymmetry={self.asymmetry}, shape_factor={self.shape_factor}, "
279
+ f"denominator_offset={self.denominator_offset}, offset={self.offset})"
280
+ )
@@ -0,0 +1,43 @@
1
+ """This module contains an interface that models the conductivity of a sensor dot barrier.
2
+
3
+ @author: b.papajewski
4
+ """
5
+
6
+ __all__ = []
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import Union
10
+
11
+ import numpy as np
12
+
13
+
14
+ class BarrierFunctionInterface(ABC):
15
+ """
16
+ Interface that models the conductivity (similar to a pinch-off measurement) of a barrier.
17
+ """
18
+
19
+ @abstractmethod
20
+ def get_value(self, potential: Union[float, np.ndarray]) -> float:
21
+ """
22
+ Returns the value of the barrier function for a given potential.
23
+
24
+ Args:
25
+ potential (Union[float, np.ndarray]): Potential for which the conductance of the barrier function is to be
26
+ calculated.
27
+
28
+ Returns:
29
+ Union[float, np.ndarray]: Value of the barrier function for a given potential.
30
+ """
31
+ raise NotImplementedError
32
+
33
+ @property
34
+ @abstractmethod
35
+ def pinch_off(self) -> float:
36
+ """Potential value of the pinch off."""
37
+ raise NotImplementedError
38
+
39
+ @property
40
+ @abstractmethod
41
+ def fully_conductive(self) -> float:
42
+ """Potential value of the point from which on the barrier vanishes and becomes fully conductive."""
43
+ raise NotImplementedError
@@ -0,0 +1,157 @@
1
+ """This module contains a class that models the conductivity of a barrier using multiple generalized logistic functions (GLFs).
2
+
3
+ @author: b.papajewski
4
+ """
5
+
6
+ from typing import Union, Tuple
7
+
8
+ import numpy as np
9
+
10
+ from simcats.sensor.barrier_function import BarrierFunctionInterface
11
+ from simcats.support_functions import multi_glf
12
+
13
+ __all__ = []
14
+
15
+
16
+ class BarrierFunctionMultiGLF(BarrierFunctionInterface):
17
+ """
18
+ Implementation of the BarrierFunctionInterface that models a conductivity off of a barrier using a combination of
19
+ multiple generalized logistic functions (GLFs).
20
+ For further information see: https://en.wikipedia.org/wiki/Generalised_logistic_function
21
+ """
22
+
23
+ def __init__(self, pinch_off: float, fully_conductive: float, *params: float):
24
+ """Initializes an object of the class to represent the barrier function using several generalized logistic functions.
25
+
26
+ For further information see: https://en.wikipedia.org/wiki/Generalised_logistic_function
27
+
28
+ The number of GLFs is specified by the number of parameters. To do this, the parameter count must be
29
+ divisible by seven and a GLF is added for every seven other parameters.
30
+
31
+ Each GLF has the following parameters: \n
32
+ - asymptote_left (float): Originally called A. This parameter is the left horizontal asymptote of the function.
33
+ Any rational number can be used as the left asymptote.
34
+ - asymptote_right (float): Originally called K. Specifies the right horizontal asymptote of the function when
35
+ denominator_offset=1. If asymptote_left=0 and denominator_offset=1 then this parameter is also called the
36
+ carrying capacity. This parameter may take any rational number.
37
+ - growth_rate (float): Originally called B. The growth rate of the function. The value must be a float and can
38
+ be any rational number. Be careful with negative values, because the function is mirrored on a vertical
39
+ straight line for these. This line passes through the point where the potential equals `offset`.
40
+ - asymmetry (float): Originally called nu. This parameter introduces skew and affects symmetry. It also affects
41
+ near which asymptote maximum growth occurs. The value of asymmetry must be a rational number greater than
42
+ zero. \n
43
+ - If `asymmetry > 1`: the curve rises more gradually before the midpoint and more sharply after. \n
44
+ - If `asymmetry < 1`: the curve rises quickly early on and levels off more slowly.
45
+ - shape_factor (float): Originally called Q. is related to the value Y(0) and adjusts the curve’s value at the
46
+ y-intercept. Thereby it changes the shape of the function without changing the asymptotes. The shape
47
+ factor can be any rational number.
48
+ - denominator_offset (float): Originally called C. A constant added to the denominator inside the power.
49
+ Controls the initial level of the denominator.This parameter must be a rational number. It typically takes a
50
+ value of 1. Otherwise, the upper asymptote is \n
51
+ asymptote_left + (asymptote_right - asymptote_left) / (denominator_offset^(1 / asymmetry)).
52
+ - offset (float): Potential offset, that shifts the function starting from the zero point. If the offset is
53
+ positive, the function is shifted to the right and if it is negative, it is shifted to the left.
54
+
55
+ Args:
56
+ pinch_off (float): Potential at which the pinch-off of the barrier is located.
57
+ fully_conductive (float): Potential of the point from which on the barrier function is fully conductive.
58
+ *params: Additional positional arguments representing the GLF parameters. The number of additional
59
+ parameters must be divisible by seven and determines the number of GLFs that are used for the Multi-GLF.
60
+ All parameters consist of sequential groups of seven floats that each represent a single GLF. All
61
+ individual parameters are described above and are in the same order as they are described.
62
+ """
63
+ self.pinch_off = pinch_off
64
+ self.fully_conductive = fully_conductive
65
+ self.params = params
66
+
67
+ def get_value(self, potential: Union[float, np.ndarray]) -> float:
68
+ """Returns the value of the barrier function for a given potential.
69
+
70
+ Args:
71
+ potential (Union[float, np.ndarray]): Potential for which the conductance of the barrier function is to be
72
+ calculated.
73
+
74
+ Returns:
75
+ Union[float, np.ndarray]: Value of the barrier function for a given potential.
76
+ """
77
+ return multi_glf(potential, *self.__params)
78
+
79
+ @property
80
+ def pinch_off(self) -> float:
81
+ """Potential value of the pinch off."""
82
+ return self.__pinch_off
83
+
84
+ @pinch_off.setter
85
+ def pinch_off(self, pinch_off: float) -> None:
86
+ """Updates the potential value of the pinch off.
87
+
88
+ Args:
89
+ pinch_off (float): Potential value of the pinch off
90
+ """
91
+ self.__pinch_off = pinch_off
92
+
93
+ @property
94
+ def fully_conductive(self) -> float:
95
+ """Potential value of the point from which on the barrier vanishes and becomes fully conductive."""
96
+ return self.__fully_conductive
97
+
98
+ @fully_conductive.setter
99
+ def fully_conductive(self, fully_conductive: float) -> None:
100
+ """Updates the fully conductive point, the potential value at which the barrier vanishes.
101
+
102
+ Args:
103
+ fully_conductive (float): Potential value of the fully conductive point.
104
+ """
105
+ self.__fully_conductive = fully_conductive
106
+
107
+ @property
108
+ def params(self) -> Tuple[float]:
109
+ """Parameters of the multiple GLFs.
110
+ The number of GLFs is specified by the number of parameters. To do this, the parameter count must be divisible
111
+ by seven and a GLF is added for every seven other parameters.
112
+
113
+ Each GLF has the following parameters: \n
114
+ - asymptote_left (float): Originally called A. This parameter is the left horizontal asymptote of the function.
115
+ Any rational number can be used as the left asymptote.
116
+ - asymptote_right (float): Originally called K. Specifies the right horizontal asymptote of the function when
117
+ denominator_offset=1. If asymptote_left=0 and denominator_offset=1 then this parameter is also called the
118
+ carrying capacity. This parameter may take any rational number.
119
+ - growth_rate (float): Originally called B. The growth rate of the function. The value must be a float and can
120
+ be any rational number. Be careful with negative values, because the function is mirrored on a vertical
121
+ straight line for these. This line passes through the point where the potential equals `offset`.
122
+ - asymmetry (float): Originally called nu. This parameter introduces skew and affects symmetry. It also affects
123
+ near which asymptote maximum growth occurs. The value of asymmetry must be a rational number greater than
124
+ zero. \n
125
+ - If `asymmetry > 1`: the curve rises more gradually before the midpoint and more sharply after. \n
126
+ - If `asymmetry < 1`: the curve rises quickly early on and levels off more slowly.
127
+ - shape_factor (float): Originally called Q. is related to the value Y(0) and adjusts the curve’s value at the
128
+ y-intercept. Thereby it changes the shape of the function without changing the asymptotes. The shape factor can
129
+ be any rational number.
130
+ - denominator_offset (float): Originally called C. A constant added to the denominator inside the power.
131
+ Controls the initial level of the denominator. This parameter must be a rational number. It typically takes a
132
+ value of 1. Otherwise, the upper asymptote is \n
133
+ asymptote_left + (asymptote_right - asymptote_left) / (denominator_offset^(1 / asymmetry)).
134
+ - offset (float): Potential offset, that shifts the function starting from the zero point. If the offset is
135
+ positive, the function is shifted to the right and if it is negative, it is shifted to the left.
136
+
137
+ Returns:
138
+ The parameters of the multiple GLFs as described above.
139
+ """
140
+ return self.__params
141
+
142
+ @params.setter
143
+ def params(self, params: Tuple[float]) -> None:
144
+ """Updates the parameter list of a multi GLF. A more detailed description of every parameter can be found above.
145
+
146
+ Args:
147
+ params (Tuple[float]): Parameters of the multiple GLFs as described above.
148
+ """
149
+ if len(params) % 7 != 0:
150
+ raise ValueError("The parameter list must be divisible by 7")
151
+ self.__params = params
152
+
153
+ def __repr__(self):
154
+ return (
155
+ self.__class__.__name__
156
+ + f"(pinch_off={self.pinch_off}, fully_conductive={self.fully_conductive}, *params={self.__params}"
157
+ )
@@ -0,0 +1,9 @@
1
+ """
2
+ SimCATS subpackage of the sensor package containing all functionalities related to sensor peak deformations.
3
+ """
4
+
5
+ from simcats.sensor.deformation._sensor_peak_deformation_interface import SensorPeakDeformationInterface
6
+ from simcats.sensor.deformation._sensor_peak_deformation_circle import SensorPeakDeformationCircle
7
+ from simcats.sensor.deformation._sensor_peak_deformation_linear import SensorPeakDeformationLinear
8
+
9
+ __all__ = ['SensorPeakDeformationInterface', 'SensorPeakDeformationCircle', 'SensorPeakDeformationLinear']
@@ -0,0 +1,109 @@
1
+ """This module contains the class for simulating a circular deformation of sensor peaks in a scan.
2
+
3
+ @author: b.papajewski
4
+ """
5
+ from typing import Union
6
+
7
+ import numpy as np
8
+
9
+ from simcats.sensor.deformation import SensorPeakDeformationInterface
10
+
11
+ __all__ = []
12
+
13
+
14
+ class SensorPeakDeformationCircle(SensorPeakDeformationInterface):
15
+ """Circular deformation implementation of the SensorPeakDeformationInterface."""
16
+
17
+ def __init__(self, radius: float) -> None:
18
+ """Initialization of an object of the class CircleSensorPeakDeformation.
19
+ This kind of deformation uses a single circle for the deformation of a sensor peak.
20
+
21
+ Args:
22
+ radius (float): Radius of the circle that is used for the deformation. The radius can the positive or
23
+ negative. If the radius is positive the center of the circle is below mu0 and if it is negative the
24
+ center is above mu0.
25
+ """
26
+ super().__init__()
27
+
28
+ self.__radius = radius
29
+
30
+ @property
31
+ def radius(self) -> float:
32
+ """Returns the radius used for this deformation.
33
+ Radius is specified in potential values.
34
+ The radius can the positive or negative. If the radius is positive the center of the circle is below mu0 and if
35
+ it is negative the center is above mu0.
36
+
37
+ Returns:
38
+ float: Radius of the circular deformation. The wavefront is deformed according to this circle.
39
+ """
40
+ return self.__radius
41
+
42
+ @radius.setter
43
+ def radius(self, radius: float) -> None:
44
+ """Sets the radius of the circular deformation.
45
+ Radius is specified in potential values.
46
+ The radius can the positive or negative. If the radius is positive the center of the circle is below mu0 and if
47
+ it is negative the center is above mu0.
48
+
49
+ Args:
50
+ radius (float): Radius of the circular deformation. The wavefront is deformed according to this circle.
51
+ """
52
+ self.__radius = radius
53
+
54
+ def calc_mu(self, dist: Union[float, np.ndarray], mu0: float) -> Union[float, np.ndarray]:
55
+ """
56
+ Method that calculates the deformed potential value for mu0 of a sensor peak that is moved based on the
57
+ distance (dist) to a middle line, from which the deformation originates, using a circle. The middle line follows
58
+ the direction of the sensor peaks (i.e., the sensor dot potential) and is perpendicular to the wavefronts
59
+ defined by the peaks.
60
+
61
+ The center of the circle is either above or below the sensor peak and lies on the middle line. However, it is
62
+ chosen so that the mu0 value lies on the edge of the circle. To determine the deformation, one of the points of
63
+ the circle with the given distance to the middle line is used. The deformed mu0 value is the potential value of
64
+ the point whose potential value is closest to the original mu0 value. If there is no point of the circle that
65
+ has the given distance (dist) to the middle line, the potential of the point of the circle with the greatest
66
+ distance to the middle straight line is used.
67
+
68
+ Args:
69
+ dist (Union[float, np.ndarray]): Distance from the middle line, from which the deformation originates. If a
70
+ point is above the middle line the distance is positive and if it is below, the distance is negative.
71
+ The parameter can either be a np.ndarray that contains multiple distances or a single distance as a
72
+ float.
73
+ mu0 (float): Potential offset for calculation of the deformed potential. Usually this should be the
74
+ potential offset of the sensor peak, that should be deformed.
75
+
76
+ Returns:
77
+ Union[float, np.ndarray]: Deformed potential value mu0 of a sensor peak. The same type as the type of
78
+ `dist` is returned.
79
+ """
80
+ # Here only positive distances are used as the deformation with a single circle is symmetrical
81
+ dist = np.abs(dist)
82
+ # Conversion of the raidus from potential values to voltage values
83
+ radius_volt = self.__radius / np.linalg.norm(self.sensor.alpha_sensor_gate[0])
84
+
85
+ radius_abs = np.abs(radius_volt)
86
+ sign_radius = np.sign(self.__radius)
87
+
88
+ # Prevents division by zero if radius_abs is zero
89
+ with np.errstate(divide='ignore', invalid='ignore'):
90
+ angle = np.arcsin(np.clip(dist / radius_abs, -1, 1))
91
+ cos_angle = np.cos(angle)
92
+
93
+ # Calculation of both possible points of the circle that have the distance dist to the middle line
94
+ temp1 = mu0 - (radius_abs - cos_angle * radius_abs) * sign_radius
95
+ temp2 = mu0 - radius_volt * np.sign(radius_volt)
96
+
97
+ # Selection of the result that is closer to the output mu0
98
+ result = np.where(dist <= radius_abs, temp1, temp2)
99
+
100
+ # If the result is an array with only one element, you can convert it to a scalar
101
+ if np.isscalar(dist):
102
+ return result.item()
103
+ else:
104
+ return result
105
+
106
+ def __repr__(self):
107
+ return (
108
+ self.__class__.__name__ + f"(radius={self.radius})"
109
+ )