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
@@ -0,0 +1,614 @@
1
+ """
2
+ ================================================================================
3
+ pyvale: the python validation engine
4
+ License: MIT
5
+ Copyright (C) 2025 The Computer Aided Validation Team
6
+ ================================================================================
7
+ """
8
+ import numpy as np
9
+ from pyvale.core.sensordata import SensorData
10
+ from pyvale.core.errorcalculator import (IErrCalculator,
11
+ EErrType,
12
+ EErrDependence)
13
+ from pyvale.core.generatorsrandom import IGeneratorRandom
14
+
15
+
16
+ class ErrRandUniform(IErrCalculator):
17
+ """Random error calculator based on uniform sampling of an interval
18
+ specified by its upper and lower bound.
19
+
20
+ Implements the `IErrCalculator` interface.
21
+ """
22
+ __slots__ = ("low","high","rng","err_dep")
23
+
24
+ def __init__(self,
25
+ low: float,
26
+ high: float,
27
+ err_dep: EErrDependence = EErrDependence.INDEPENDENT,
28
+ seed: int | None = None) -> None:
29
+ """Initialiser for `ErrRandUniform` class.
30
+
31
+ Parameters
32
+ ----------
33
+ low : float
34
+ Lower bound of the uniform random generator.
35
+ high : float
36
+ Upper bound of the uniform random generator.
37
+ err_dep : EErrDependence, optional
38
+ Error calculation dependence, by default EErrDependence.INDEPENDENT.
39
+ seed : int | None, optional
40
+ Optional seed for the random generator to allow for replicable
41
+ behaviour, by default None.
42
+
43
+ Raises
44
+ ------
45
+ ValueError
46
+ Raised if the user specified a lower bound that is higher than the
47
+ upper bound.
48
+ """
49
+
50
+ if low > high:
51
+ raise ValueError("The upper bound must be higher than the lower "
52
+ + "bound for this error.")
53
+ self.low = low
54
+ self.high = high
55
+ self.rng = np.random.default_rng(seed)
56
+ self.err_dep = err_dep
57
+
58
+ def get_error_dep(self) -> EErrDependence:
59
+ """Gets the error dependence state for this error calculator. An
60
+ independent error is calculated based on the input truth values as the
61
+ error basis. A dependent error is calculated based on the accumulated
62
+ sensor reading from all preceeding errors in the chain.
63
+
64
+ For this class errors are calculated independently regardless.
65
+
66
+ Returns
67
+ -------
68
+ EErrDependence
69
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
70
+ """
71
+ return self.err_dep
72
+
73
+ def set_error_dep(self, dependence: EErrDependence) -> None:
74
+ """Sets the error dependence state for this error calculator. An
75
+ independent error is calculated based on the input truth values as the
76
+ error basis. A dependent error is calculated based on the accumulated
77
+ sensor reading from all preceeding errors in the chain.
78
+
79
+ For this class errors are calculated independently regardless.
80
+
81
+ Parameters
82
+ ----------
83
+ dependence : EErrDependence
84
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
85
+ """
86
+ self.err_dep = dependence
87
+
88
+ def get_error_type(self) -> EErrType:
89
+ """Gets the error type.
90
+
91
+ Returns
92
+ -------
93
+ EErrType
94
+ Enumeration definining RANDOM or SYSTEMATIC error types.
95
+ """
96
+ return EErrType.RANDOM
97
+
98
+ def calc_errs(self,
99
+ err_basis: np.ndarray,
100
+ sens_data: SensorData,
101
+ ) -> tuple[np.ndarray, SensorData]:
102
+ """Calculates the error array based on the size of the input.
103
+
104
+ Parameters
105
+ ----------
106
+ err_basis : np.ndarray
107
+ Array of values with the same dimensions as the sensor measurement
108
+ matrix.
109
+ sens_data : SensorData
110
+ The accumulated sensor state data for all errors prior to this one.
111
+
112
+ Returns
113
+ -------
114
+ tuple[np.ndarray, SensorData]
115
+ Tuple containing the calculated error array and pass through of the
116
+ sensor data object as it is not modified by this class. The returned
117
+ error array has the same shape as the input error basis.
118
+ """
119
+ rand_errs = self.rng.uniform(low=self.low,
120
+ high=self.high,
121
+ size=err_basis.shape)
122
+
123
+ return (rand_errs,sens_data)
124
+
125
+
126
+ class ErrRandUnifPercent(IErrCalculator):
127
+ """Random error calculator based on a percentage error based on sampling
128
+ from a uniform probability distribution specified by its upper and lower
129
+ bound (in percent).
130
+
131
+ The percentage error is calculated based on the ground truth if the error
132
+ dependence is `INDEPENDENT` or based on the accumulated sensor measurement
133
+ if the dependence is `DEPENDENT`.
134
+
135
+ Implements the `IErrCalculator` interface.
136
+ """
137
+ __slots__ = ("low","high","rng","err_dep")
138
+
139
+ def __init__(self,
140
+ low_percent: float,
141
+ high_percent: float,
142
+ err_dep: EErrDependence = EErrDependence.INDEPENDENT,
143
+ seed: int | None = None) -> None:
144
+ """Initialiser for the `ErrRandUnifPercent` class.
145
+
146
+ Parameters
147
+ ----------
148
+ low_percent : float
149
+ Lower percentage bound of the uniform random generator.
150
+ high_percent : float
151
+ Upper percentage bound of the uniform random generator.
152
+ err_dep : EErrDependence, optional
153
+ Error calculation dependence, by default EErrDependence.INDEPENDENT.
154
+ seed : int | None, optional
155
+ Optional seed for the random generator to allow for replicable
156
+ behaviour, by default None.
157
+
158
+ Raises
159
+ ------
160
+ ValueError
161
+ Raised if the user specified a lower bound that is higher than the
162
+ upper bound.
163
+ """
164
+
165
+ if low_percent > high_percent:
166
+ raise ValueError("The upper percentage bound must be higher than "
167
+ + "the lower percentage bound for this error.")
168
+
169
+ self.low = low_percent/100
170
+ self.high = high_percent/100
171
+ self.rng = np.random.default_rng(seed)
172
+ self.err_dep = err_dep
173
+
174
+ def get_error_dep(self) -> EErrDependence:
175
+ """Gets the error dependence state for this error calculator. An
176
+ independent error is calculated based on the input truth values as the
177
+ error basis. A dependent error is calculated based on the accumulated
178
+ sensor reading from all preceeding errors in the chain.
179
+
180
+ Returns
181
+ -------
182
+ EErrDependence
183
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
184
+ """
185
+ return self.err_dep
186
+
187
+ def set_error_dep(self, dependence: EErrDependence) -> None:
188
+ """Sets the error dependence state for this error calculator. An
189
+ independent error is calculated based on the input truth values as the
190
+ error basis. A dependent error is calculated based on the accumulated
191
+ sensor reading from all preceeding errors in the chain.
192
+
193
+ Parameters
194
+ ----------
195
+ dependence : EErrDependence
196
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
197
+ """
198
+ self.err_dep = dependence
199
+
200
+ def get_error_type(self) -> EErrType:
201
+ """Gets the error type.
202
+
203
+ Returns
204
+ -------
205
+ EErrType
206
+ Enumeration definining RANDOM or SYSTEMATIC error types.
207
+ """
208
+ return EErrType.RANDOM
209
+
210
+ def calc_errs(self,
211
+ err_basis: np.ndarray,
212
+ sens_data: SensorData,
213
+ ) -> tuple[np.ndarray, SensorData]:
214
+ """Calculates the error array based on the size of the input.
215
+
216
+ Parameters
217
+ ----------
218
+ err_basis : np.ndarray
219
+ Array of values with the same dimensions as the sensor measurement
220
+ matrix.
221
+ sens_data : SensorData
222
+ The accumulated sensor state data for all errors prior to this one.
223
+
224
+ Returns
225
+ -------
226
+ tuple[np.ndarray, SensorData]
227
+ Tuple containing the calculated error array and pass through of the
228
+ sensor data object as it is not modified by this class. The returned
229
+ error array has the same shape as the input error basis.
230
+ """
231
+ norm_rand = self.rng.uniform(low=self.low,
232
+ high=self.high,
233
+ size=err_basis.shape)
234
+
235
+ return (err_basis*norm_rand,sens_data)
236
+
237
+
238
+ class ErrRandNormal(IErrCalculator):
239
+ """Random error calculator based on sampling of a normal (Gaussian)
240
+ distribution specified using the standard deviation with an assumed zero
241
+ mean. A non-zero mean is a systematic error and should be specified using
242
+ `ErrSysOffset`.
243
+
244
+ Implements the `IErrCalculator` interface.
245
+ """
246
+ __slots__ = ("std","rng","err_dep")
247
+
248
+ def __init__(self,
249
+ std: float,
250
+ err_dep: EErrDependence = EErrDependence.INDEPENDENT,
251
+ seed: int | None = None) -> None:
252
+ """Initialiser for `ErrRandNormal` class.
253
+
254
+ Parameters
255
+ ----------
256
+ std : float
257
+ Standard deviation of the normal distribution to sample from.
258
+ err_dep : EErrDependence, optional
259
+ Error calculation dependence, by default EErrDependence.INDEPENDENT.
260
+ seed : int | None, optional
261
+ Optional seed for the random generator to allow for replicable
262
+ behaviour, by default None.
263
+ """
264
+ self.std = np.abs(std)
265
+ self.rng = np.random.default_rng(seed)
266
+ self.err_dep = err_dep
267
+
268
+ def get_error_dep(self) -> EErrDependence:
269
+ """Gets the error dependence state for this error calculator. An
270
+ independent error is calculated based on the input truth values as the
271
+ error basis. A dependent error is calculated based on the accumulated
272
+ sensor reading from all preceeding errors in the chain.
273
+
274
+ For this class errors are calculated independently regardless.
275
+
276
+ Returns
277
+ -------
278
+ EErrDependence
279
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
280
+ """
281
+ return self.err_dep
282
+
283
+ def set_error_dep(self, dependence: EErrDependence) -> None:
284
+ """Sets the error dependence state for this error calculator. An
285
+ independent error is calculated based on the input truth values as the
286
+ error basis. A dependent error is calculated based on the accumulated
287
+ sensor reading from all preceeding errors in the chain.
288
+
289
+ For this class errors are calculated independently regardless.
290
+
291
+ Parameters
292
+ ----------
293
+ dependence : EErrDependence
294
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
295
+ """
296
+ self.err_dep = dependence
297
+
298
+ def get_error_type(self) -> EErrType:
299
+ """Gets the error type.
300
+
301
+ Returns
302
+ -------
303
+ EErrType
304
+ Enumeration definining RANDOM or SYSTEMATIC error types.
305
+ """
306
+ return EErrType.RANDOM
307
+
308
+ def calc_errs(self,
309
+ err_basis: np.ndarray,
310
+ sens_data: SensorData,
311
+ ) -> tuple[np.ndarray, SensorData]:
312
+ """Calculates the error array based on the size of the input.
313
+
314
+ Parameters
315
+ ----------
316
+ err_basis : np.ndarray
317
+ Array of values with the same dimensions as the sensor measurement
318
+ matrix.
319
+ sens_data : SensorData
320
+ The accumulated sensor state data for all errors prior to this one.
321
+
322
+ Returns
323
+ -------
324
+ tuple[np.ndarray, SensorData]
325
+ Tuple containing the calculated error array and pass through of the
326
+ sensor data object as it is not modified by this class. The returned
327
+ error array has the same shape as the input error basis.
328
+ """
329
+ rand_errs = self.rng.normal(loc=0.0,
330
+ scale=self.std,
331
+ size=err_basis.shape)
332
+
333
+ return (rand_errs,sens_data)
334
+
335
+
336
+ class ErrRandNormPercent(IErrCalculator):
337
+ """Sensor random error calculator based on sampling of a normal (Gaussian)
338
+ distribution specified using the standard deviation with an assumed zero
339
+ mean. This error is calculated as a percentage of the input error basis.
340
+ Note that a non-zero mean is a systematic error and should be specified
341
+ using `ErrSysOffset`.
342
+
343
+ The percentage error is calculated based on the ground truth if the error
344
+ dependence is `INDEPENDENT` or based on the accumulated sensor measurement
345
+ if the dependence is `DEPENDENT`.
346
+
347
+ Implements the `IErrCalculator` interface.
348
+ """
349
+ __slots__ = ("_std","_rng","_err_dep")
350
+
351
+ def __init__(self,
352
+ std_percent: float,
353
+ err_dep: EErrDependence = EErrDependence.INDEPENDENT,
354
+ seed: int | None = None) -> None:
355
+ """Initialiser for `ErrRandNormPercent` class.
356
+
357
+ Parameters
358
+ ----------
359
+ std_percent : float
360
+ Standard deviation of the normal distribution to sample as a
361
+ percentage.
362
+ err_dep : EErrDependence, optional
363
+ Error calculation dependence, by default EErrDependence.INDEPENDENT.
364
+ seed : int | None, optional
365
+ Optional seed for the random generator to allow for replicable
366
+ behaviour, by default None.
367
+ """
368
+ self._std = np.abs(std_percent)/100
369
+ self._rng = np.random.default_rng(seed)
370
+ self._err_dep = err_dep
371
+
372
+ def get_error_dep(self) -> EErrDependence:
373
+ """Gets the error dependence state for this error calculator. An
374
+ independent error is calculated based on the input truth values as the
375
+ error basis. A dependent error is calculated based on the accumulated
376
+ sensor reading from all preceeding errors in the chain.
377
+
378
+ Returns
379
+ -------
380
+ EErrDependence
381
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
382
+ """
383
+ return self._err_dep
384
+
385
+ def set_error_dep(self, dependence: EErrDependence) -> None:
386
+ """Sets the error dependence state for this error calculator. An
387
+ independent error is calculated based on the input truth values as the
388
+ error basis. A dependent error is calculated based on the accumulated
389
+ sensor reading from all preceeding errors in the chain.
390
+
391
+ Parameters
392
+ ----------
393
+ dependence : EErrDependence
394
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
395
+ """
396
+ self._err_dep = dependence
397
+
398
+ def get_error_type(self) -> EErrType:
399
+ """Gets the error type.
400
+
401
+ Returns
402
+ -------
403
+ EErrType
404
+ Enumeration definining RANDOM or SYSTEMATIC error types.
405
+ """
406
+ return EErrType.RANDOM
407
+
408
+ def calc_errs(self,
409
+ err_basis: np.ndarray,
410
+ sens_data: SensorData,
411
+ ) -> tuple[np.ndarray, SensorData]:
412
+ """Calculates the error array based on the size of the input.
413
+
414
+ Parameters
415
+ ----------
416
+ err_basis : np.ndarray
417
+ Array of values with the same dimensions as the sensor measurement
418
+ matrix.
419
+ sens_data : SensorData
420
+ The accumulated sensor state data for all errors prior to this one.
421
+
422
+ Returns
423
+ -------
424
+ tuple[np.ndarray, SensorData]
425
+ Tuple containing the calculated error array and pass through of the
426
+ sensor data object as it is not modified by this class. The returned
427
+ error array has the same shape as the input error basis.
428
+ """
429
+ norm_rand = self._rng.normal(loc=0.0,
430
+ scale=1.0,
431
+ size=err_basis.shape)
432
+
433
+ return (err_basis*self._std*norm_rand,sens_data)
434
+
435
+
436
+ class ErrRandGenerator(IErrCalculator):
437
+ """Sensor random error calculator based on sampling a user specified random
438
+ number generator implementing the `IGeneratorRandom` interface.
439
+
440
+ Implements the `IErrCalculator` interface.
441
+ """
442
+ __slots__ = ("_generator","_err_dep")
443
+
444
+ def __init__(self,
445
+ generator: IGeneratorRandom,
446
+ err_dep: EErrDependence = EErrDependence.INDEPENDENT) -> None:
447
+ """Initiliaser for the `ErrRandGenerator` class.
448
+
449
+ Parameters
450
+ ----------
451
+ generator : IGeneratorRandom
452
+ Interface for a user specified random number generator.
453
+ err_dep : EErrDependence, optional
454
+ Error calculation dependence, by default EErrDependence.INDEPENDENT.
455
+ """
456
+ self._generator = generator
457
+ self._err_dep = err_dep
458
+
459
+ def get_error_dep(self) -> EErrDependence:
460
+ """Gets the error dependence state for this error calculator. An
461
+ independent error is calculated based on the input truth values as the
462
+ error basis. A dependent error is calculated based on the accumulated
463
+ sensor reading from all preceeding errors in the chain.
464
+
465
+ For this class errors are calculated independently regardless.
466
+
467
+ Returns
468
+ -------
469
+ EErrDependence
470
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
471
+ """
472
+ return self._err_dep
473
+
474
+ def set_error_dep(self, dependence: EErrDependence) -> None:
475
+ """Sets the error dependence state for this error calculator. An
476
+ independent error is calculated based on the input truth values as the
477
+ error basis. A dependent error is calculated based on the accumulated
478
+ sensor reading from all preceeding errors in the chain.
479
+
480
+ For this class errors are calculated independently regardless.
481
+
482
+ Parameters
483
+ ----------
484
+ dependence : EErrDependence
485
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
486
+ """
487
+ self._err_dep = dependence
488
+
489
+ def get_error_type(self) -> EErrType:
490
+ """Gets the error type.
491
+
492
+ Returns
493
+ -------
494
+ EErrType
495
+ Enumeration definining RANDOM or SYSTEMATIC error types.
496
+ """
497
+ return EErrType.RANDOM
498
+
499
+ def calc_errs(self,
500
+ err_basis: np.ndarray,
501
+ sens_data: SensorData,
502
+ ) -> tuple[np.ndarray, SensorData]:
503
+ """Calculates the error array based on the size of the input.
504
+
505
+ Parameters
506
+ ----------
507
+ err_basis : np.ndarray
508
+ Array of values with the same dimensions as the sensor measurement
509
+ matrix.
510
+ sens_data : SensorData
511
+ The accumulated sensor state data for all errors prior to this one.
512
+
513
+ Returns
514
+ -------
515
+ tuple[np.ndarray, SensorData]
516
+ Tuple containing the calculated error array and pass through of the
517
+ sensor data object as it is not modified by this class. The returned
518
+ error array has the same shape as the input error basis.
519
+ """
520
+ rand_errs = self._generator.generate(shape=err_basis.shape)
521
+
522
+ return (rand_errs,sens_data)
523
+
524
+
525
+ class ErrRandGenPercent(IErrCalculator):
526
+ """Random error calculator based on sampling a user specified random
527
+ number generator implementing the `IGeneratorRandom` interface. This class
528
+ assumes the random generator is for a percentage error based on the input
529
+ error basis and therefore it supports error dependence.
530
+
531
+ The percentage error is calculated based on the ground truth if the error
532
+ dependence is `INDEPENDENT` or based on the accumulated sensor measurement
533
+ if the dependence is `DEPENDENT`.
534
+
535
+ Implements the `IErrCalculator` interface.
536
+ """
537
+ __slots__ = ("_generator","_err_dep")
538
+
539
+ def __init__(self,
540
+ generator: IGeneratorRandom,
541
+ err_dep: EErrDependence = EErrDependence.INDEPENDENT) -> None:
542
+ """Initiliaser for the `ErrRandGenerator` class.
543
+
544
+ Parameters
545
+ ----------
546
+ generator : IGeneratorRandom
547
+ Interface for a user specified random number generator.
548
+ err_dep : EErrDependence, optional
549
+ Error calculation dependence, by default EErrDependence.INDEPENDENT.
550
+ """
551
+ self._generator = generator
552
+ self._err_dep = err_dep
553
+
554
+ def get_error_dep(self) -> EErrDependence:
555
+ """Gets the error dependence state for this error calculator. An
556
+ independent error is calculated based on the input truth values as the
557
+ error basis. A dependent error is calculated based on the accumulated
558
+ sensor reading from all preceeding errors in the chain.
559
+
560
+ Returns
561
+ -------
562
+ EErrDependence
563
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
564
+ """
565
+ return self._err_dep
566
+
567
+ def set_error_dep(self, dependence: EErrDependence) -> None:
568
+ """Sets the error dependence state for this error calculator. An
569
+ independent error is calculated based on the input truth values as the
570
+ error basis. A dependent error is calculated based on the accumulated
571
+ sensor reading from all preceeding errors in the chain.
572
+
573
+ Parameters
574
+ ----------
575
+ dependence : EErrDependence
576
+ Enumeration defining INDEPENDENT or DEPENDENT behaviour.
577
+ """
578
+ self._err_dep = dependence
579
+
580
+ def get_error_type(self) -> EErrType:
581
+ """Gets the error type.
582
+
583
+ Returns
584
+ -------
585
+ EErrType
586
+ Enumeration definining RANDOM or SYSTEMATIC error types.
587
+ """
588
+ return EErrType.RANDOM
589
+
590
+ def calc_errs(self,
591
+ err_basis: np.ndarray,
592
+ sens_data: SensorData,
593
+ ) -> tuple[np.ndarray, SensorData]:
594
+ """Calculates the error array based on the size of the input.
595
+
596
+ Parameters
597
+ ----------
598
+ err_basis : np.ndarray
599
+ Array of values with the same dimensions as the sensor measurement
600
+ matrix.
601
+ sens_data : SensorData
602
+ The accumulated sensor state data for all errors prior to this one.
603
+
604
+ Returns
605
+ -------
606
+ tuple[np.ndarray, SensorData]
607
+ Tuple containing the calculated error array and pass through of the
608
+ sensor data object as it is not modified by this class. The returned
609
+ error array has the same shape as the input error basis.
610
+ """
611
+ rand_errs = err_basis \
612
+ * self._generator.generate(shape=err_basis.shape)/100
613
+
614
+ return (rand_errs,sens_data)