pyvale 2025.4.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.

Potentially problematic release.


This version of pyvale might be problematic. Click here for more details.

Files changed (157) hide show
  1. pyvale/__init__.py +75 -0
  2. pyvale/core/__init__.py +7 -0
  3. pyvale/core/analyticmeshgen.py +59 -0
  4. pyvale/core/analyticsimdatafactory.py +63 -0
  5. pyvale/core/analyticsimdatagenerator.py +160 -0
  6. pyvale/core/camera.py +146 -0
  7. pyvale/core/cameradata.py +64 -0
  8. pyvale/core/cameradata2d.py +82 -0
  9. pyvale/core/cameratools.py +328 -0
  10. pyvale/core/cython/rastercyth.c +32267 -0
  11. pyvale/core/cython/rastercyth.py +636 -0
  12. pyvale/core/dataset.py +250 -0
  13. pyvale/core/errorcalculator.py +112 -0
  14. pyvale/core/errordriftcalc.py +146 -0
  15. pyvale/core/errorintegrator.py +339 -0
  16. pyvale/core/errorrand.py +614 -0
  17. pyvale/core/errorsysdep.py +331 -0
  18. pyvale/core/errorsysfield.py +407 -0
  19. pyvale/core/errorsysindep.py +905 -0
  20. pyvale/core/experimentsimulator.py +99 -0
  21. pyvale/core/field.py +136 -0
  22. pyvale/core/fieldconverter.py +154 -0
  23. pyvale/core/fieldsampler.py +112 -0
  24. pyvale/core/fieldscalar.py +167 -0
  25. pyvale/core/fieldtensor.py +221 -0
  26. pyvale/core/fieldtransform.py +384 -0
  27. pyvale/core/fieldvector.py +215 -0
  28. pyvale/core/generatorsrandom.py +528 -0
  29. pyvale/core/imagedef2d.py +566 -0
  30. pyvale/core/integratorfactory.py +241 -0
  31. pyvale/core/integratorquadrature.py +192 -0
  32. pyvale/core/integratorrectangle.py +88 -0
  33. pyvale/core/integratorspatial.py +90 -0
  34. pyvale/core/integratortype.py +44 -0
  35. pyvale/core/optimcheckfuncs.py +153 -0
  36. pyvale/core/raster.py +31 -0
  37. pyvale/core/rastercy.py +76 -0
  38. pyvale/core/rasternp.py +604 -0
  39. pyvale/core/rendermesh.py +156 -0
  40. pyvale/core/sensorarray.py +179 -0
  41. pyvale/core/sensorarrayfactory.py +210 -0
  42. pyvale/core/sensorarraypoint.py +280 -0
  43. pyvale/core/sensordata.py +72 -0
  44. pyvale/core/sensordescriptor.py +101 -0
  45. pyvale/core/sensortools.py +143 -0
  46. pyvale/core/visualexpplotter.py +151 -0
  47. pyvale/core/visualimagedef.py +71 -0
  48. pyvale/core/visualimages.py +75 -0
  49. pyvale/core/visualopts.py +180 -0
  50. pyvale/core/visualsimanimator.py +83 -0
  51. pyvale/core/visualsimplotter.py +182 -0
  52. pyvale/core/visualtools.py +81 -0
  53. pyvale/core/visualtraceplotter.py +256 -0
  54. pyvale/data/__init__.py +7 -0
  55. pyvale/data/case13_out.e +0 -0
  56. pyvale/data/case16_out.e +0 -0
  57. pyvale/data/case17_out.e +0 -0
  58. pyvale/data/case18_1_out.e +0 -0
  59. pyvale/data/case18_2_out.e +0 -0
  60. pyvale/data/case18_3_out.e +0 -0
  61. pyvale/data/case25_out.e +0 -0
  62. pyvale/data/case26_out.e +0 -0
  63. pyvale/data/optspeckle_2464x2056px_spec5px_8bit_gblur1px.tiff +0 -0
  64. pyvale/examples/__init__.py +7 -0
  65. pyvale/examples/analyticdatagen/__init__.py +7 -0
  66. pyvale/examples/analyticdatagen/ex1_1_scalarvisualisation.py +38 -0
  67. pyvale/examples/analyticdatagen/ex1_2_scalarcasebuild.py +46 -0
  68. pyvale/examples/analyticdatagen/ex2_1_analyticsensors.py +83 -0
  69. pyvale/examples/ex1_1_thermal2d.py +89 -0
  70. pyvale/examples/ex1_2_thermal2d.py +111 -0
  71. pyvale/examples/ex1_3_thermal2d.py +113 -0
  72. pyvale/examples/ex1_4_thermal2d.py +89 -0
  73. pyvale/examples/ex1_5_thermal2d.py +105 -0
  74. pyvale/examples/ex2_1_thermal3d .py +87 -0
  75. pyvale/examples/ex2_2_thermal3d.py +51 -0
  76. pyvale/examples/ex2_3_thermal3d.py +109 -0
  77. pyvale/examples/ex3_1_displacement2d.py +47 -0
  78. pyvale/examples/ex3_2_displacement2d.py +79 -0
  79. pyvale/examples/ex3_3_displacement2d.py +104 -0
  80. pyvale/examples/ex3_4_displacement2d.py +105 -0
  81. pyvale/examples/ex4_1_strain2d.py +57 -0
  82. pyvale/examples/ex4_2_strain2d.py +79 -0
  83. pyvale/examples/ex4_3_strain2d.py +100 -0
  84. pyvale/examples/ex5_1_multiphysics2d.py +78 -0
  85. pyvale/examples/ex6_1_multiphysics2d_expsim.py +118 -0
  86. pyvale/examples/ex6_2_multiphysics3d_expsim.py +158 -0
  87. pyvale/examples/features/__init__.py +7 -0
  88. pyvale/examples/features/ex_animation_tools_3dmonoblock.py +83 -0
  89. pyvale/examples/features/ex_area_avg.py +89 -0
  90. pyvale/examples/features/ex_calibration_error.py +108 -0
  91. pyvale/examples/features/ex_chain_field_errs.py +141 -0
  92. pyvale/examples/features/ex_field_errs.py +78 -0
  93. pyvale/examples/features/ex_sensor_single_angle_batch.py +110 -0
  94. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +86 -0
  95. pyvale/examples/rasterisation/ex_rastenp.py +154 -0
  96. pyvale/examples/rasterisation/ex_rastercyth_oneframe.py +220 -0
  97. pyvale/examples/rasterisation/ex_rastercyth_static_cypara.py +194 -0
  98. pyvale/examples/rasterisation/ex_rastercyth_static_pypara.py +193 -0
  99. pyvale/simcases/case00_HEX20.i +242 -0
  100. pyvale/simcases/case00_HEX27.i +242 -0
  101. pyvale/simcases/case00_TET10.i +242 -0
  102. pyvale/simcases/case00_TET14.i +242 -0
  103. pyvale/simcases/case01.i +101 -0
  104. pyvale/simcases/case02.i +156 -0
  105. pyvale/simcases/case03.i +136 -0
  106. pyvale/simcases/case04.i +181 -0
  107. pyvale/simcases/case05.i +234 -0
  108. pyvale/simcases/case06.i +305 -0
  109. pyvale/simcases/case07.geo +135 -0
  110. pyvale/simcases/case07.i +87 -0
  111. pyvale/simcases/case08.geo +144 -0
  112. pyvale/simcases/case08.i +153 -0
  113. pyvale/simcases/case09.geo +204 -0
  114. pyvale/simcases/case09.i +87 -0
  115. pyvale/simcases/case10.geo +204 -0
  116. pyvale/simcases/case10.i +257 -0
  117. pyvale/simcases/case11.geo +337 -0
  118. pyvale/simcases/case11.i +147 -0
  119. pyvale/simcases/case12.geo +388 -0
  120. pyvale/simcases/case12.i +329 -0
  121. pyvale/simcases/case13.i +140 -0
  122. pyvale/simcases/case14.i +159 -0
  123. pyvale/simcases/case15.geo +337 -0
  124. pyvale/simcases/case15.i +150 -0
  125. pyvale/simcases/case16.geo +391 -0
  126. pyvale/simcases/case16.i +357 -0
  127. pyvale/simcases/case17.geo +135 -0
  128. pyvale/simcases/case17.i +144 -0
  129. pyvale/simcases/case18.i +254 -0
  130. pyvale/simcases/case18_1.i +254 -0
  131. pyvale/simcases/case18_2.i +254 -0
  132. pyvale/simcases/case18_3.i +254 -0
  133. pyvale/simcases/case19.geo +252 -0
  134. pyvale/simcases/case19.i +99 -0
  135. pyvale/simcases/case20.geo +252 -0
  136. pyvale/simcases/case20.i +250 -0
  137. pyvale/simcases/case21.geo +74 -0
  138. pyvale/simcases/case21.i +155 -0
  139. pyvale/simcases/case22.geo +82 -0
  140. pyvale/simcases/case22.i +140 -0
  141. pyvale/simcases/case23.geo +164 -0
  142. pyvale/simcases/case23.i +140 -0
  143. pyvale/simcases/case24.geo +79 -0
  144. pyvale/simcases/case24.i +123 -0
  145. pyvale/simcases/case25.geo +82 -0
  146. pyvale/simcases/case25.i +140 -0
  147. pyvale/simcases/case26.geo +166 -0
  148. pyvale/simcases/case26.i +140 -0
  149. pyvale/simcases/run_1case.py +61 -0
  150. pyvale/simcases/run_all_cases.py +69 -0
  151. pyvale/simcases/run_build_case.py +64 -0
  152. pyvale/simcases/run_example_cases.py +69 -0
  153. pyvale-2025.4.0.dist-info/METADATA +140 -0
  154. pyvale-2025.4.0.dist-info/RECORD +157 -0
  155. pyvale-2025.4.0.dist-info/WHEEL +5 -0
  156. pyvale-2025.4.0.dist-info/licenses/LICENSE +21 -0
  157. pyvale-2025.4.0.dist-info/top_level.txt +1 -0
pyvale/core/dataset.py ADDED
@@ -0,0 +1,250 @@
1
+ """
2
+ ================================================================================
3
+ pyvale: the python validation engine
4
+ License: MIT
5
+ Copyright (C) 2025 The Computer Aided Validation Team
6
+ ================================================================================
7
+ """
8
+ from pathlib import Path
9
+ from importlib.resources import files
10
+
11
+
12
+ SIM_CASE_COUNT = 26
13
+
14
+
15
+ class DataSetError(Exception):
16
+ """Custom error class for file io errors associated with retrieving datasets
17
+ and files packaged with pyvale.
18
+ """
19
+ pass
20
+
21
+
22
+ class DataSet:
23
+ """A static namespace class for handling datasets packaged with pyvale.
24
+ Contains a series of static methods returning a Path object to each data
25
+ file that is packaged with pyvale.
26
+ """
27
+
28
+ @staticmethod
29
+ def sim_case_input_file_path(case_num: int) -> Path:
30
+ """Gets the path to MOOSE input file (*.i) for a particular simulation
31
+ case.
32
+
33
+ Parameters
34
+ ----------
35
+ case_num : int
36
+ Integer defining the case number to be retrieved. Must be greater
37
+ than 0 and less than the number of simulation cases.
38
+
39
+ Returns
40
+ -------
41
+ Path
42
+ Path object to the MOOSE *.i file for the selected simulation case.
43
+
44
+ Raises
45
+ ------
46
+ DataSetError
47
+ Raised if an invalid simulation case number is specified.
48
+ """
49
+ if case_num <= 0:
50
+ raise DataSetError("Simulation case number must be greater than 0")
51
+ elif case_num > SIM_CASE_COUNT:
52
+ raise DataSetError("Simulation case number must be less than " \
53
+ + f"{SIM_CASE_COUNT}")
54
+
55
+ case_num_str = str(case_num).zfill(2)
56
+ case_file = f"case{case_num_str}.i"
57
+ return Path(files("pyvale.simcases").joinpath(case_file))
58
+
59
+
60
+ @staticmethod
61
+ def sim_case_gmsh_file_path(case_num: int) -> Path | None:
62
+ """Gets the path to Gmsh input file (*.geo) for a particular simulation
63
+ case. Note that not all simulation cases use Gmsh for geometry and mesh
64
+ generation. If the specified simulation case does not have an associated
65
+ Gmsh *.geo file. In this case 'None' is returned
66
+
67
+ Parameters
68
+ ----------
69
+ case_num : int
70
+ Integer defining the case number to be retrieved. Must be greater
71
+ than 0 and less than the number of simulation cases.
72
+
73
+ Returns
74
+ -------
75
+ Path | None
76
+ Path object to the Gmsh *.geo file for the selected simulation case.
77
+ Returns None if there is no *.geo for this simulation case.
78
+
79
+ Raises
80
+ ------
81
+ DataSetError
82
+ Raised if an invalid simulation case number is specified.
83
+ """
84
+ if case_num <= 0:
85
+ raise DataSetError("Simulation case number must be greater than 0")
86
+ elif case_num > SIM_CASE_COUNT:
87
+ raise DataSetError("Simulation case number must be less than " \
88
+ + f"{SIM_CASE_COUNT}")
89
+
90
+ case_num_str = str(case_num).zfill(2)
91
+ case_file = f"case{case_num_str}.geo"
92
+ case_path = Path(files("pyvale.simcases").joinpath(case_file))
93
+
94
+ if case_path.is_file():
95
+ return case_path
96
+
97
+ return None
98
+
99
+
100
+ @staticmethod
101
+ def dic_pattern_5mpx_path() -> Path:
102
+ """Path to a 5 mega-pixel speckle pattern image (2464 x 2056 pixels)
103
+ with 8 bit resolution stored as a *.tiff. Speckles are sampled by
104
+ 5 pixels. A gaussian blur has been applied to the image to remove sharp
105
+ transitions from black to white.
106
+
107
+ Path
108
+ Path to the *.tiff file containing the speckle pattern.
109
+ """
110
+ return Path(files("pyvale.data")
111
+ .joinpath("optspeckle_2464x2056px_spec5px_8bit_gblur1px.tiff"))
112
+
113
+ @staticmethod
114
+ def thermal_2d_path() -> Path:
115
+ """Path to a MOOSE simulation output in exodus format. This case is a
116
+ thermal problem solving for a scalar temperature field. The geometry is
117
+ a 2D plate (in x,y) with a heat flux applied on one edge and a heat
118
+ transfer coefficient applied on the opposite edge inducing a temperature
119
+ gradient along the x axis of the plate.
120
+
121
+ The simulation parameters can be found in the corresponding MOOSE input
122
+ file: case13.i which can be retrieved using `sim_ca_summary_
123
+
124
+ Parameters
125
+ ----------
126
+ Exception : _type_
127
+ _description_se_input_file_path`
128
+ in this class.
129
+
130
+ Returns
131
+ -------
132
+ Path
133
+ Path to the exodus (*.e) output file for this simulation case.
134
+ """
135
+ return Path(files("pyvale.data").joinpath("case13_out.e"))
136
+
137
+ @staticmethod
138
+ def thermal_3d_path() -> Path:
139
+ """Path to a MOOSE simulation output in exodus format. This case is a 3D
140
+ thermal problem solving for a scalar temperature field. The model is a
141
+ divertor armour monoblock composed of a tungsten block bonded to a
142
+ copper-chromium-zirconium pipe with a pure copper interlayer. A heat
143
+ flux is applied to the top surface of the block and a heat transfer
144
+ coefficient for cooling water is applied to the inner surface of the
145
+ pipe inducing a temperature gradient from the top of the block to the
146
+ pipe.
147
+
148
+ The simulation parameters can be found in the corresponding MOOSE input
149
+ file: case16.i which can be retrieved using `sim_case_input_file_path`
150
+ in this class. Note that this case uses a Gmsh *.geo file for geometry
151
+ and mesh creation.
152
+
153
+ Returns
154
+ -------
155
+ Path
156
+ Path to the exodus (*.e) output file for this simulation case.
157
+ """
158
+ return Path(files("pyvale.data").joinpath("case16_out.e"))
159
+
160
+ @staticmethod
161
+ def mechanical_2d_path() -> Path:
162
+ """Path to a MOOSE simulation output in exodus format. This case is a 2D
163
+ plate with a hole in the center with the bottom edge fixed and a
164
+ displacement applied to the top edge. This is a mechanical problem and
165
+ solves for the displacement vector field and the tensorial strain field.
166
+
167
+ The simulation parameters can be found in the corresponding MOOSE input
168
+ file: case17.i which can be retrieved using `sim_case_input_file_path`
169
+ in this class. Note that this case uses a Gmsh *.geo file for geometry
170
+ and mesh creation.
171
+
172
+ Returns
173
+ -------
174
+ Path
175
+ Path to the exodus (*.e) output file for this simulation case.
176
+ """
177
+ return Path(files("pyvale.data").joinpath("case17_out.e"))
178
+
179
+ @staticmethod
180
+ def thermomechanical_2d_path() -> Path:
181
+ """Path to a MOOSE simulation output in exodus format. This case is a
182
+ thermo-mechanical analysis of a 2D plate with a heat flux applied on one
183
+ edge and a heat transfer coefficient applied on the opposing edge. The
184
+ mechanical deformation results from thermal expansion due to the imposed
185
+ temperature gradient. This model is solved for the scalar temperature
186
+ field, vector displacement and tensor strain field.
187
+
188
+ Returns
189
+ -------
190
+ Path
191
+ Path to the exodus (*.e) output file for this simulation case.
192
+ """
193
+ return Path(files("pyvale.data").joinpath("case18_1_out.e"))
194
+
195
+ @staticmethod
196
+ def thermomechanical_3d_path() -> Path:
197
+ """Path to a MOOSE simulation output in exodus format. This case is a
198
+ thermo-mechanical analysis of a 3D monoblock divertor armour with a heat
199
+ flux applied on the top surface and a heat transfer coefficient applied
200
+ on the inner surface of the pipe. The mechanical deformation results
201
+ from thermal expansion due to the imposed temperature gradient.
202
+ This model is solved for the scalar temperature field, vector
203
+ displacement and tensor strain field.
204
+
205
+ Returns
206
+ -------
207
+ Path
208
+ Path to the exodus (*.e) output file for this simulation case.
209
+ """
210
+ return Path(files("pyvale.data").joinpath("case16_out.e"))
211
+
212
+ @staticmethod
213
+ def thermomechanical_2d_experiment_paths() -> list[Path]:
214
+ """Path to a MOOSE simulation output in exodus format. This case is a
215
+ thermo-mechanical analysis of a 2D plate with a heat flux applied on one
216
+ edge and a heat transfer coefficient applied on the opposing edge. The
217
+ mechanical deformation results from thermal expansion due to the imposed
218
+ temperature gradient. This model is solved for the scalar temperature
219
+ field, vector temperature and tensor strain field.
220
+
221
+ Here we analyse 3 separate experiments where the thermal conductivity of
222
+ the material is perturbed from the nominal case by +/-10%.
223
+
224
+ The simulation parameters can be found in the corresponding MOOSE input
225
+ file: case18.i which can be retrieved using `sim_case_input_file_path`
226
+ in this class.
227
+
228
+ Returns
229
+ -------
230
+ Path
231
+ Path to the exodus (*.e) output file for this simulation case.
232
+ """
233
+ return [Path(files("pyvale.data").joinpath("case18_1_out.e")),
234
+ Path(files("pyvale.data").joinpath("case18_2_out.e")),
235
+ Path(files("pyvale.data").joinpath("case18_3_out.e"))]
236
+
237
+ @staticmethod
238
+ def render_mechanical_3d_path() -> Path:
239
+ """_summary_
240
+
241
+ Returns
242
+ -------
243
+ Path
244
+ _description_
245
+ """
246
+ return Path(files("pyvale.data").joinpath("case26_out.e"))
247
+
248
+ @staticmethod
249
+ def render_simple_block_path() -> Path:
250
+ return Path(files("pyvale.data").joinpath("case25_out.e"))
@@ -0,0 +1,112 @@
1
+ """
2
+ ================================================================================
3
+ pyvale: the python validation engine
4
+ License: MIT
5
+ Copyright (C) 2025 The Computer Aided Validation Team
6
+ ================================================================================
7
+ """
8
+ import enum
9
+ from abc import ABC, abstractmethod
10
+ import numpy as np
11
+ from pyvale.core.sensordata import SensorData
12
+
13
+
14
+ class EErrType(enum.Enum):
15
+ """Enumeration defining the error type for separation of error types for
16
+ later analysis.
17
+
18
+ EErrType.SYSTEMATIC:
19
+ Also known as an epistemic error and is due to a lack of
20
+ knowledge. Common examples include spatial or temporal averaging,
21
+ digitisation / round off error and calibration errors.
22
+
23
+ EErrType.RANDOM:
24
+ Also known as aleatory error and is generally a result of sensor
25
+ noise.
26
+ """
27
+ SYSTEMATIC = enum.auto()
28
+ RANDOM = enum.auto()
29
+
30
+
31
+ class EErrDependence(enum.Enum):
32
+ """Enumeration defining error dependence.
33
+
34
+ EErrDependence.INDEPENDENT:
35
+ Errors are calculated based on the ground truth sensor values
36
+ interpolated from the input simulation.
37
+
38
+ EErrDependence.DEPENDENT:
39
+ Errors are calculated based on the accumulated sensor reading due
40
+ to all preceeding errors in the chain.
41
+ """
42
+ INDEPENDENT = enum.auto()
43
+ DEPENDENT = enum.auto()
44
+
45
+
46
+ class IErrCalculator(ABC):
47
+ """Interface (abstract base class) for sensor error calculation allowing for
48
+ chaining of errors.
49
+ """
50
+ @abstractmethod
51
+ def get_error_type(self) -> EErrType:
52
+ """Abstract method for getting the error type.
53
+
54
+ Returns
55
+ -------
56
+ EErrType
57
+ Enumeration definining RANDOM or SYSTEMATIC error types.
58
+ """
59
+ pass
60
+
61
+ @abstractmethod
62
+ def get_error_dep(self) -> EErrDependence:
63
+ """Abstract method for getting the error dependence.
64
+
65
+ Returns
66
+ -------
67
+ EErrDependence
68
+ Enumeration definining RANDOM or SYSTEMATIC error types.
69
+ """
70
+ pass
71
+
72
+ @abstractmethod
73
+ def set_error_dep(self, dependence: EErrDependence) -> None:
74
+ """Abstract method for setting the error dependence.
75
+
76
+ Parameters
77
+ ----------
78
+ dependence : EErrDependence
79
+ Enumeration definining RANDOM or SYSTEMATIC error types.
80
+ """
81
+
82
+ @abstractmethod
83
+ def calc_errs(self,
84
+ err_basis: np.ndarray,
85
+ sens_data: SensorData,
86
+ ) -> tuple[np.ndarray, SensorData]:
87
+ """Abstract method that calculates the error array based on the input
88
+ err_basis array. The output error array will be the same shape as the
89
+ input err_basis array.
90
+
91
+ Parameters
92
+ ----------
93
+ err_basis : np.ndarray
94
+ Used as the base array for calculating the returned error
95
+ sens_data : SensorData
96
+ Sensor data object holding the current sensor state before applying
97
+ this error calculation.
98
+
99
+ Returns
100
+ -------
101
+ tuple[np.ndarray, SensorData]
102
+ Tuple containing the error array from this calculator and a
103
+ SensorData object with the current accumulated sensor state starting
104
+ from the nominal state up to and including this error calculator in
105
+ the error chain. Note that many errors do not modify the sensor data
106
+ so the sensor data class is passed through this function unchanged.
107
+ """
108
+ pass
109
+
110
+
111
+
112
+
@@ -0,0 +1,146 @@
1
+ """
2
+ ================================================================================
3
+ pyvale: the python validation engine
4
+ License: MIT
5
+ Copyright (C) 2025 The Computer Aided Validation Team
6
+ ================================================================================
7
+ """
8
+ from abc import ABC, abstractmethod
9
+ import numpy as np
10
+
11
+
12
+ class IDriftCalculator(ABC):
13
+ """Interface (abstract base class) for applying a function to cause a sensor
14
+ array measurement to drift (normally over time). The initialiser for the
15
+ concrete implementation of this class specifies the function parameters and
16
+ a unified method is provided to calculate the drift based on the input.
17
+ """
18
+
19
+ @abstractmethod
20
+ def calc_drift(self, drift_var: np.ndarray) -> np.ndarray:
21
+ """Abstract method. Used to calculate the drift function based on the
22
+ input drift variable (useually the time steps).
23
+
24
+ Parameters
25
+ ----------
26
+ drift_var : np.ndarray
27
+ Array of values (normally time steps) that are used to calculate the
28
+ drift errors.
29
+
30
+ Returns
31
+ -------
32
+ np.ndarray
33
+ Array of drift errors having the same shape as the input drift_var
34
+ array.
35
+ """
36
+ pass
37
+
38
+
39
+ class DriftConstant(IDriftCalculator):
40
+ """Class for applying a constant drift error over time.
41
+
42
+ Implements the IDriftCalculator interface.
43
+ """
44
+ def __init__(self, offset: float) -> None:
45
+ """Initialiser for the `DriftConstant` class.
46
+
47
+ Parameters
48
+ ----------
49
+ offset : float
50
+ Constant drift offset.
51
+ """
52
+ self._offset = offset
53
+
54
+ def calc_drift(self, drift_var: np.ndarray) -> np.ndarray:
55
+ """Calculates the drift errors based on the input drift variable array.
56
+
57
+ Parameters
58
+ ----------
59
+ drift_var : np.ndarray
60
+ Array of values (normally time steps) that are used to calculate the
61
+ drift errors.
62
+
63
+ Returns
64
+ -------
65
+ np.ndarray
66
+ Array of drift errors having the same shape as the input drift_var
67
+ array.
68
+ """
69
+ return self._offset*np.ones_like(drift_var)
70
+
71
+
72
+ class DriftLinear(IDriftCalculator):
73
+ """Class for applying a linear drift error over time.
74
+
75
+ Implements the IDriftCalculator interface.
76
+ """
77
+
78
+ def __init__(self, slope: float, offset: float = 0.0) -> None:
79
+ """Initialiser for the `DriftLinear` class.
80
+
81
+ Parameters
82
+ ----------
83
+ slope : float
84
+ Slope of the drift error function.
85
+ offset : float, optional
86
+ Offset (intercept) of the drift error function, by default 0.0.
87
+ """
88
+ self._slope = slope
89
+ self._offset = offset
90
+
91
+ def calc_drift(self, drift_var: np.ndarray) -> np.ndarray:
92
+ """Calculates the drift errors based on the input drift variable array.
93
+
94
+ Parameters
95
+ ----------
96
+ drift_var : np.ndarray
97
+ Array of values (normally time steps) that are used to calculate the
98
+ drift errors.
99
+
100
+ Returns
101
+ -------
102
+ np.ndarray
103
+ Array of drift errors having the same shape as the input drift_var
104
+ array.
105
+ """
106
+ return self._slope*drift_var + self._offset
107
+
108
+
109
+ class DriftPolynomial(IDriftCalculator):
110
+ """Class for applying a polynomial drift error over time. The coefficients
111
+ of the polynomial are specified with a numpy array from constant term to
112
+ highest power.
113
+
114
+ Implements the IDriftCalculator interface.
115
+ """
116
+
117
+ def __init__(self, coeffs: np.ndarray) -> None:
118
+ """Initialiser for the `DriftPolynomial` class.
119
+
120
+ Parameters
121
+ ----------
122
+ coeffs : np.ndarray
123
+ Array of polynomial coefficients from constant to highest power.
124
+ """
125
+ self._coeffs = coeffs
126
+
127
+ def calc_drift(self, drift_var: np.ndarray) -> np.ndarray:
128
+ """Calculates the drift errors based on the input drift variable array.
129
+
130
+ Parameters
131
+ ----------
132
+ drift_var : np.ndarray
133
+ Array of values (normally time steps) that are used to calculate the
134
+ drift errors.
135
+
136
+ Returns
137
+ -------
138
+ np.ndarray
139
+ Array of drift errors having the same shape as the input drift_var
140
+ array.
141
+ """
142
+ poly = np.zeros_like(drift_var)
143
+ for ii,cc in enumerate(self._coeffs):
144
+ poly += cc*drift_var**ii
145
+
146
+ return poly