pyvale 2025.4.0__py3-none-any.whl → 2025.5.1__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 (153) hide show
  1. pyvale/__init__.py +78 -64
  2. pyvale/analyticmeshgen.py +102 -0
  3. pyvale/{core/analyticsimdatafactory.py → analyticsimdatafactory.py} +44 -16
  4. pyvale/analyticsimdatagenerator.py +323 -0
  5. pyvale/blendercalibrationdata.py +15 -0
  6. pyvale/blenderlightdata.py +26 -0
  7. pyvale/blendermaterialdata.py +15 -0
  8. pyvale/blenderrenderdata.py +30 -0
  9. pyvale/blenderscene.py +488 -0
  10. pyvale/blendertools.py +420 -0
  11. pyvale/{core/camera.py → camera.py} +15 -15
  12. pyvale/{core/cameradata.py → cameradata.py} +27 -22
  13. pyvale/{core/cameradata2d.py → cameradata2d.py} +8 -6
  14. pyvale/camerastereo.py +217 -0
  15. pyvale/{core/cameratools.py → cameratools.py} +220 -26
  16. pyvale/{core/cython → cython}/rastercyth.py +11 -7
  17. pyvale/data/__init__.py +5 -7
  18. pyvale/data/cal_target.tiff +0 -0
  19. pyvale/data/case00_HEX20_out.e +0 -0
  20. pyvale/data/case00_HEX27_out.e +0 -0
  21. pyvale/data/case00_HEX8_out.e +0 -0
  22. pyvale/data/case00_TET10_out.e +0 -0
  23. pyvale/data/case00_TET14_out.e +0 -0
  24. pyvale/data/case00_TET4_out.e +0 -0
  25. pyvale/{core/dataset.py → dataset.py} +91 -16
  26. pyvale/{core/errorcalculator.py → errorcalculator.py} +13 -16
  27. pyvale/{core/errordriftcalc.py → errordriftcalc.py} +14 -14
  28. pyvale/{core/errorintegrator.py → errorintegrator.py} +25 -28
  29. pyvale/{core/errorrand.py → errorrand.py} +39 -46
  30. pyvale/errorsyscalib.py +134 -0
  31. pyvale/{core/errorsysdep.py → errorsysdep.py} +25 -29
  32. pyvale/{core/errorsysfield.py → errorsysfield.py} +59 -52
  33. pyvale/{core/errorsysindep.py → errorsysindep.py} +85 -182
  34. pyvale/examples/__init__.py +5 -7
  35. pyvale/examples/basics/ex1_1_basicscalars_therm2d.py +131 -0
  36. pyvale/examples/basics/ex1_2_sensormodel_therm2d.py +158 -0
  37. pyvale/examples/basics/ex1_3_customsens_therm3d.py +216 -0
  38. pyvale/examples/basics/ex1_4_basicerrors_therm3d.py +153 -0
  39. pyvale/examples/basics/ex1_5_fielderrs_therm3d.py +168 -0
  40. pyvale/examples/basics/ex1_6_caliberrs_therm2d.py +133 -0
  41. pyvale/examples/basics/ex1_7_spatavg_therm2d.py +123 -0
  42. pyvale/examples/basics/ex2_1_basicvectors_disp2d.py +112 -0
  43. pyvale/examples/basics/ex2_2_vectorsens_disp2d.py +111 -0
  44. pyvale/examples/basics/ex2_3_sensangle_disp2d.py +139 -0
  45. pyvale/examples/basics/ex2_4_chainfielderrs_disp2d.py +196 -0
  46. pyvale/examples/basics/ex2_5_vectorfields3d_disp3d.py +109 -0
  47. pyvale/examples/basics/ex3_1_basictensors_strain2d.py +114 -0
  48. pyvale/examples/basics/ex3_2_tensorsens2d_strain2d.py +111 -0
  49. pyvale/examples/basics/ex3_3_tensorsens3d_strain3d.py +182 -0
  50. pyvale/examples/basics/ex4_1_expsim2d_thermmech2d.py +171 -0
  51. pyvale/examples/basics/ex4_2_expsim3d_thermmech3d.py +252 -0
  52. pyvale/examples/{analyticdatagen → genanalyticdata}/ex1_1_scalarvisualisation.py +6 -9
  53. pyvale/examples/{analyticdatagen → genanalyticdata}/ex1_2_scalarcasebuild.py +8 -11
  54. pyvale/examples/{analyticdatagen → genanalyticdata}/ex2_1_analyticsensors.py +9 -12
  55. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +8 -15
  56. pyvale/examples/renderblender/ex1_1_blenderscene.py +121 -0
  57. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +119 -0
  58. pyvale/examples/renderblender/ex2_1_stereoscene.py +128 -0
  59. pyvale/examples/renderblender/ex2_2_stereodeformed.py +131 -0
  60. pyvale/examples/renderblender/ex3_1_blendercalibration.py +120 -0
  61. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastenp.py +6 -7
  62. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_oneframe.py +5 -7
  63. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_static_cypara.py +6 -13
  64. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_static_pypara.py +9 -12
  65. pyvale/examples/{ex1_4_thermal2d.py → visualisation/ex1_1_plot_traces.py} +33 -20
  66. pyvale/examples/{features/ex_animation_tools_3dmonoblock.py → visualisation/ex2_1_animate_sim.py} +37 -31
  67. pyvale/experimentsimulator.py +175 -0
  68. pyvale/{core/field.py → field.py} +6 -14
  69. pyvale/fieldconverter.py +351 -0
  70. pyvale/{core/fieldsampler.py → fieldsampler.py} +9 -10
  71. pyvale/{core/fieldscalar.py → fieldscalar.py} +17 -18
  72. pyvale/{core/fieldtensor.py → fieldtensor.py} +23 -26
  73. pyvale/{core/fieldtransform.py → fieldtransform.py} +9 -5
  74. pyvale/{core/fieldvector.py → fieldvector.py} +14 -16
  75. pyvale/{core/generatorsrandom.py → generatorsrandom.py} +29 -52
  76. pyvale/{core/imagedef2d.py → imagedef2d.py} +11 -8
  77. pyvale/{core/integratorfactory.py → integratorfactory.py} +12 -13
  78. pyvale/{core/integratorquadrature.py → integratorquadrature.py} +57 -32
  79. pyvale/integratorrectangle.py +165 -0
  80. pyvale/{core/integratorspatial.py → integratorspatial.py} +9 -10
  81. pyvale/{core/integratortype.py → integratortype.py} +7 -8
  82. pyvale/output.py +17 -0
  83. pyvale/pyvaleexceptions.py +11 -0
  84. pyvale/{core/raster.py → raster.py} +8 -8
  85. pyvale/{core/rastercy.py → rastercy.py} +11 -10
  86. pyvale/{core/rasternp.py → rasternp.py} +12 -13
  87. pyvale/{core/rendermesh.py → rendermesh.py} +10 -19
  88. pyvale/{core/sensorarray.py → sensorarray.py} +7 -8
  89. pyvale/{core/sensorarrayfactory.py → sensorarrayfactory.py} +64 -78
  90. pyvale/{core/sensorarraypoint.py → sensorarraypoint.py} +39 -41
  91. pyvale/{core/sensordata.py → sensordata.py} +7 -8
  92. pyvale/sensordescriptor.py +213 -0
  93. pyvale/{core/sensortools.py → sensortools.py} +8 -9
  94. pyvale/simcases/case00_HEX20.i +5 -5
  95. pyvale/simcases/case00_HEX27.i +5 -5
  96. pyvale/simcases/case00_HEX8.i +242 -0
  97. pyvale/simcases/case00_TET10.i +2 -2
  98. pyvale/simcases/case00_TET14.i +2 -2
  99. pyvale/simcases/case00_TET4.i +242 -0
  100. pyvale/simcases/run_1case.py +1 -1
  101. pyvale/simtools.py +67 -0
  102. pyvale/visualexpplotter.py +191 -0
  103. pyvale/{core/visualimagedef.py → visualimagedef.py} +13 -10
  104. pyvale/{core/visualimages.py → visualimages.py} +10 -9
  105. pyvale/visualopts.py +493 -0
  106. pyvale/{core/visualsimanimator.py → visualsimanimator.py} +47 -19
  107. pyvale/visualsimsensors.py +318 -0
  108. pyvale/visualtools.py +136 -0
  109. pyvale/visualtraceplotter.py +142 -0
  110. {pyvale-2025.4.0.dist-info → pyvale-2025.5.1.dist-info}/METADATA +17 -14
  111. pyvale-2025.5.1.dist-info/RECORD +172 -0
  112. {pyvale-2025.4.0.dist-info → pyvale-2025.5.1.dist-info}/WHEEL +1 -1
  113. pyvale/core/__init__.py +0 -7
  114. pyvale/core/analyticmeshgen.py +0 -59
  115. pyvale/core/analyticsimdatagenerator.py +0 -160
  116. pyvale/core/cython/rastercyth.c +0 -32267
  117. pyvale/core/experimentsimulator.py +0 -99
  118. pyvale/core/fieldconverter.py +0 -154
  119. pyvale/core/integratorrectangle.py +0 -88
  120. pyvale/core/optimcheckfuncs.py +0 -153
  121. pyvale/core/sensordescriptor.py +0 -101
  122. pyvale/core/visualexpplotter.py +0 -151
  123. pyvale/core/visualopts.py +0 -180
  124. pyvale/core/visualsimplotter.py +0 -182
  125. pyvale/core/visualtools.py +0 -81
  126. pyvale/core/visualtraceplotter.py +0 -256
  127. pyvale/examples/analyticdatagen/__init__.py +0 -7
  128. pyvale/examples/ex1_1_thermal2d.py +0 -89
  129. pyvale/examples/ex1_2_thermal2d.py +0 -111
  130. pyvale/examples/ex1_3_thermal2d.py +0 -113
  131. pyvale/examples/ex1_5_thermal2d.py +0 -105
  132. pyvale/examples/ex2_1_thermal3d .py +0 -87
  133. pyvale/examples/ex2_2_thermal3d.py +0 -51
  134. pyvale/examples/ex2_3_thermal3d.py +0 -109
  135. pyvale/examples/ex3_1_displacement2d.py +0 -47
  136. pyvale/examples/ex3_2_displacement2d.py +0 -79
  137. pyvale/examples/ex3_3_displacement2d.py +0 -104
  138. pyvale/examples/ex3_4_displacement2d.py +0 -105
  139. pyvale/examples/ex4_1_strain2d.py +0 -57
  140. pyvale/examples/ex4_2_strain2d.py +0 -79
  141. pyvale/examples/ex4_3_strain2d.py +0 -100
  142. pyvale/examples/ex5_1_multiphysics2d.py +0 -78
  143. pyvale/examples/ex6_1_multiphysics2d_expsim.py +0 -118
  144. pyvale/examples/ex6_2_multiphysics3d_expsim.py +0 -158
  145. pyvale/examples/features/__init__.py +0 -7
  146. pyvale/examples/features/ex_area_avg.py +0 -89
  147. pyvale/examples/features/ex_calibration_error.py +0 -108
  148. pyvale/examples/features/ex_chain_field_errs.py +0 -141
  149. pyvale/examples/features/ex_field_errs.py +0 -78
  150. pyvale/examples/features/ex_sensor_single_angle_batch.py +0 -110
  151. pyvale-2025.4.0.dist-info/RECORD +0 -157
  152. {pyvale-2025.4.0.dist-info → pyvale-2025.5.1.dist-info}/licenses/LICENSE +0 -0
  153. {pyvale-2025.4.0.dist-info → pyvale-2025.5.1.dist-info}/top_level.txt +0 -0
@@ -1,30 +1,66 @@
1
+ #===============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ #===============================================================================
6
+
1
7
  """
2
- ================================================================================
3
- pyvale: the python validation engine
4
- License: MIT
5
- Copyright (C) 2025 The Computer Aided Validation Team
6
- ================================================================================
8
+ Accesors for data that comes pre-packaged with pyvale for demonstrating its
9
+ functionality. This includes moose simulation outputs as exodus files, input
10
+ files for moose and gmsh for additional simulation cases, and images required
11
+ for testing the image deformation and digital image correlation modules.
7
12
  """
13
+
14
+ from enum import Enum
8
15
  from pathlib import Path
9
16
  from importlib.resources import files
10
17
 
11
18
 
12
19
  SIM_CASE_COUNT = 26
20
+ """Constant describing the number of simulation test case input files for moose
21
+ and gmsh that come packaged with pyvale.
22
+ """
23
+
24
+ class EElemTest(Enum):
25
+ """Enumeration used to specify different 3D element types for extracting
26
+ specific test simulation datasets.
27
+ """
28
+
29
+ TET4 = "TET4"
30
+ """Tetrahedral element, linear with 4 nodes.
31
+ """
32
+
33
+ TET10 = "TET10"
34
+ """Tetrahedral element, quadratic with 10 nodes.
35
+ """
36
+
37
+ TET14 = "TET14"
38
+ """Tetrahedral element, quadratic with 14 nodes.
39
+ """
40
+
41
+ HEX8 = "HEX8"
42
+ """Hexahedral element, linear with 8 nodes.
43
+ """
44
+
45
+ HEX20 = "HEX20"
46
+ """Hexahedral element, quadratic with 20 nodes.
47
+ """
48
+
49
+ HEX27 = "HEX27"
50
+ """Hexahedral element, quadratic with 27 nodes.
51
+ """
52
+
53
+ def __str__(self):
54
+ return self.value
13
55
 
14
56
 
15
57
  class DataSetError(Exception):
16
58
  """Custom error class for file io errors associated with retrieving datasets
17
59
  and files packaged with pyvale.
18
60
  """
19
- pass
20
61
 
21
62
 
22
63
  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
64
  @staticmethod
29
65
  def sim_case_input_file_path(case_num: int) -> Path:
30
66
  """Gets the path to MOOSE input file (*.i) for a particular simulation
@@ -50,7 +86,7 @@ class DataSet:
50
86
  raise DataSetError("Simulation case number must be greater than 0")
51
87
  elif case_num > SIM_CASE_COUNT:
52
88
  raise DataSetError("Simulation case number must be less than " \
53
- + f"{SIM_CASE_COUNT}")
89
+ + f"{SIM_CASE_COUNT}")
54
90
 
55
91
  case_num_str = str(case_num).zfill(2)
56
92
  case_file = f"case{case_num_str}.i"
@@ -85,7 +121,7 @@ class DataSet:
85
121
  raise DataSetError("Simulation case number must be greater than 0")
86
122
  elif case_num > SIM_CASE_COUNT:
87
123
  raise DataSetError("Simulation case number must be less than " \
88
- + f"{SIM_CASE_COUNT}")
124
+ + f"{SIM_CASE_COUNT}")
89
125
 
90
126
  case_num_str = str(case_num).zfill(2)
91
127
  case_file = f"case{case_num_str}.geo"
@@ -236,15 +272,54 @@ class DataSet:
236
272
 
237
273
  @staticmethod
238
274
  def render_mechanical_3d_path() -> Path:
239
- """_summary_
275
+ """Path to a MOOSE simulation output in exodus format. This case is a
276
+ purely mechanical test case in 3D meant for testing image rendering
277
+ algorithms for digital image correlation simulation. The simulation
278
+ consists of a linear elastic thin plate with a hole loaded in tension.
279
+ The simulation uses linear tetrahedral elements for rendering tests.
240
280
 
241
281
  Returns
242
282
  -------
243
283
  Path
244
- _description_
284
+ Path to the exodus (*.e) output file for this simulation case.
245
285
  """
246
286
  return Path(files("pyvale.data").joinpath("case26_out.e"))
247
287
 
248
288
  @staticmethod
249
289
  def render_simple_block_path() -> Path:
250
- return Path(files("pyvale.data").joinpath("case25_out.e"))
290
+ """Path to a MOOSE simulation output in exodus format. This case is a
291
+ a simple rectangular block in 3D loaded in tension. It uses a minimum
292
+ number of elements and is intended purely for testing image rendering
293
+ algorithms. This simulation uses linear tetrahedral elements.
294
+
295
+ Returns
296
+ -------
297
+ Path
298
+ Path to the exodus (*.e) output file for this simulation case.
299
+ """
300
+ return Path(files("pyvale.data").joinpath("case25_out.e"))
301
+
302
+ @staticmethod
303
+ def element_case_path(elem_type: EElemTest) -> Path:
304
+ """Path to a MOOSE simulation output in exodus format. This case is a
305
+ 10mm cube undergoing thermo-mechanical loading solved for the
306
+ temperature displacement and strain fields. This case is solved using a
307
+ variety of tetrahedral and hexahedral elements with linear or quadratic
308
+ shapes functions. These simulation cases are intended for testing
309
+ purposes and contain a minimal number of elements.
310
+
311
+ Parameters
312
+ ----------
313
+ elem_type : EElemTest
314
+ Enumeration specifying the element type for this test case.
315
+
316
+ Returns
317
+ -------
318
+ Path
319
+ Path to the exodus (*.e) output file for this simulation case.
320
+ """
321
+ return Path(files("pyvale.data")
322
+ .joinpath(f"case00_{elem_type.value}_out.e"))
323
+
324
+
325
+
@@ -1,14 +1,13 @@
1
- """
2
- ================================================================================
3
- pyvale: the python validation engine
4
- License: MIT
5
- Copyright (C) 2025 The Computer Aided Validation Team
6
- ================================================================================
7
- """
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
8
7
  import enum
9
8
  from abc import ABC, abstractmethod
10
9
  import numpy as np
11
- from pyvale.core.sensordata import SensorData
10
+ from pyvale.sensordata import SensorData
12
11
 
13
12
 
14
13
  class EErrType(enum.Enum):
@@ -28,14 +27,14 @@ class EErrType(enum.Enum):
28
27
  RANDOM = enum.auto()
29
28
 
30
29
 
31
- class EErrDependence(enum.Enum):
30
+ class EErrDep(enum.Enum):
32
31
  """Enumeration defining error dependence.
33
32
 
34
- EErrDependence.INDEPENDENT:
33
+ EErrDep.INDEPENDENT:
35
34
  Errors are calculated based on the ground truth sensor values
36
35
  interpolated from the input simulation.
37
36
 
38
- EErrDependence.DEPENDENT:
37
+ EErrDep.DEPENDENT:
39
38
  Errors are calculated based on the accumulated sensor reading due
40
39
  to all preceeding errors in the chain.
41
40
  """
@@ -47,6 +46,7 @@ class IErrCalculator(ABC):
47
46
  """Interface (abstract base class) for sensor error calculation allowing for
48
47
  chaining of errors.
49
48
  """
49
+
50
50
  @abstractmethod
51
51
  def get_error_type(self) -> EErrType:
52
52
  """Abstract method for getting the error type.
@@ -56,10 +56,9 @@ class IErrCalculator(ABC):
56
56
  EErrType
57
57
  Enumeration definining RANDOM or SYSTEMATIC error types.
58
58
  """
59
- pass
60
59
 
61
60
  @abstractmethod
62
- def get_error_dep(self) -> EErrDependence:
61
+ def get_error_dep(self) -> EErrDep:
63
62
  """Abstract method for getting the error dependence.
64
63
 
65
64
  Returns
@@ -67,10 +66,9 @@ class IErrCalculator(ABC):
67
66
  EErrDependence
68
67
  Enumeration definining RANDOM or SYSTEMATIC error types.
69
68
  """
70
- pass
71
69
 
72
70
  @abstractmethod
73
- def set_error_dep(self, dependence: EErrDependence) -> None:
71
+ def set_error_dep(self, dependence: EErrDep) -> None:
74
72
  """Abstract method for setting the error dependence.
75
73
 
76
74
  Parameters
@@ -105,7 +103,6 @@ class IErrCalculator(ABC):
105
103
  the error chain. Note that many errors do not modify the sensor data
106
104
  so the sensor data class is passed through this function unchanged.
107
105
  """
108
- pass
109
106
 
110
107
 
111
108
 
@@ -1,10 +1,9 @@
1
- """
2
- ================================================================================
3
- pyvale: the python validation engine
4
- License: MIT
5
- Copyright (C) 2025 The Computer Aided Validation Team
6
- ================================================================================
7
- """
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
8
7
  from abc import ABC, abstractmethod
9
8
  import numpy as np
10
9
 
@@ -33,7 +32,6 @@ class IDriftCalculator(ABC):
33
32
  Array of drift errors having the same shape as the input drift_var
34
33
  array.
35
34
  """
36
- pass
37
35
 
38
36
 
39
37
  class DriftConstant(IDriftCalculator):
@@ -41,9 +39,10 @@ class DriftConstant(IDriftCalculator):
41
39
 
42
40
  Implements the IDriftCalculator interface.
43
41
  """
44
- def __init__(self, offset: float) -> None:
45
- """Initialiser for the `DriftConstant` class.
42
+ __slots__ = ("_offset",)
46
43
 
44
+ def __init__(self, offset: float) -> None:
45
+ """
47
46
  Parameters
48
47
  ----------
49
48
  offset : float
@@ -74,10 +73,10 @@ class DriftLinear(IDriftCalculator):
74
73
 
75
74
  Implements the IDriftCalculator interface.
76
75
  """
76
+ __slots__ = ("_slope","_offset")
77
77
 
78
78
  def __init__(self, slope: float, offset: float = 0.0) -> None:
79
- """Initialiser for the `DriftLinear` class.
80
-
79
+ """
81
80
  Parameters
82
81
  ----------
83
82
  slope : float
@@ -114,9 +113,10 @@ class DriftPolynomial(IDriftCalculator):
114
113
  Implements the IDriftCalculator interface.
115
114
  """
116
115
 
117
- def __init__(self, coeffs: np.ndarray) -> None:
118
- """Initialiser for the `DriftPolynomial` class.
116
+ __slots__ = ("_coeffs",)
119
117
 
118
+ def __init__(self, coeffs: np.ndarray) -> None:
119
+ """
120
120
  Parameters
121
121
  ----------
122
122
  coeffs : np.ndarray
@@ -1,17 +1,16 @@
1
- """
2
- ================================================================================
3
- pyvale: the python validation engine
4
- License: MIT
5
- Copyright (C) 2025 The Computer Aided Validation Team
6
- ================================================================================
7
- """
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
8
7
  import copy
9
8
  from dataclasses import dataclass
10
9
  import numpy as np
11
- from pyvale.core.errorcalculator import (IErrCalculator,
12
- EErrType,
13
- EErrDependence)
14
- from pyvale.core.sensordata import SensorData
10
+ from pyvale.errorcalculator import (IErrCalculator,
11
+ EErrType,
12
+ EErrDep)
13
+ from pyvale.sensordata import SensorData
15
14
 
16
15
 
17
16
  @dataclass(slots=True)
@@ -20,12 +19,9 @@ class ErrIntOpts:
20
19
  errors are calculated and stored in memory for later use.
21
20
  """
22
21
 
23
- force_dependence: bool = False
24
- """Forces all errors to be calculated as dependent if True. Otherwise errors
25
- will use individual dependence set in the errors initialiser. Independent
26
- errors are calculated based on the ground truth whereas dependent errors are
27
- calculated based on the accumulated sensor measurement at that stage in the
28
- error chain.
22
+ force_dependence: EErrDep | None = None
23
+ """Forces all errors to be calculated with the specified dependence. If set
24
+ to None then all errors will use their default/preset dependence.
29
25
 
30
26
  Note that some errors are inherently independent so will not change. For
31
27
  example: `ErrRandNormal` is purely independent whereas `ErrRandNormPercent`
@@ -72,8 +68,7 @@ class ErrIntegrator:
72
68
  sensor_data_initial: SensorData,
73
69
  meas_shape: tuple[int,int,int],
74
70
  err_int_opts: ErrIntOpts | None = None) -> None:
75
- """Initialiser for the `ErrIntegrator` class.
76
-
71
+ """
77
72
  Parameters
78
73
  ----------
79
74
  err_chain : list[IErrCalculator]
@@ -118,7 +113,7 @@ class ErrIntegrator:
118
113
  """Sets the error chain that will be looped over to calculate the sensor
119
114
  measurement errors. If the error integration options are forcing error
120
115
  dependence then all errors in the chain will have their dependence set
121
- to `EErrDependence.DEPENDENT`.
116
+ to the specified value.
122
117
 
123
118
  Parameters
124
119
  ----------
@@ -127,9 +122,9 @@ class ErrIntegrator:
127
122
  """
128
123
  self._err_chain = err_chain
129
124
 
130
- if self._err_int_opts.force_dependence:
125
+ if self._err_int_opts.force_dependence is not None:
131
126
  for ee in self._err_chain:
132
- ee.set_error_dep(EErrDependence.DEPENDENT)
127
+ ee.set_error_dep(self._err_int_opts.force_dependence)
133
128
 
134
129
 
135
130
  def calc_errors_from_chain(self, truth: np.ndarray) -> np.ndarray:
@@ -188,14 +183,15 @@ class ErrIntegrator:
188
183
 
189
184
  for ii,ee in enumerate(self._err_chain):
190
185
 
191
- if ee.get_error_dep() == EErrDependence.DEPENDENT:
186
+ if ee.get_error_dep() == EErrDep.DEPENDENT:
192
187
  (error_array,sens_data) = ee.calc_errs(truth+accumulated_error,
193
188
  self._sens_data_accumulated)
194
- self._sens_data_accumulated = sens_data
189
+
195
190
  else:
196
191
  (error_array,sens_data) = ee.calc_errs(truth,
197
192
  self._sens_data_initial)
198
193
 
194
+ self._sens_data_accumulated = sens_data
199
195
  self._sens_data_by_chain.append(sens_data)
200
196
 
201
197
  if ee.get_error_type() == EErrType.SYSTEMATIC:
@@ -234,10 +230,11 @@ class ErrIntegrator:
234
230
 
235
231
  for ee in self._err_chain:
236
232
 
237
- if ee.get_error_dep() == EErrDependence.DEPENDENT:
238
- (error_array,sens_data) = ee.calc_errs(truth+accumulated_error,
239
- self._sens_data_accumulated)
240
- self._sens_data_accumulated = sens_data
233
+ if ee.get_error_dep() == EErrDep.DEPENDENT:
234
+ (error_array,sens_data) = ee.calc_errs(
235
+ truth+accumulated_error,
236
+ self._sens_data_accumulated
237
+ )
241
238
  else:
242
239
  (error_array,sens_data) = ee.calc_errs(truth,
243
240
  self._sens_data_initial)
@@ -1,19 +1,18 @@
1
- """
2
- ================================================================================
3
- pyvale: the python validation engine
4
- License: MIT
5
- Copyright (C) 2025 The Computer Aided Validation Team
6
- ================================================================================
7
- """
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
8
7
  import numpy as np
9
- from pyvale.core.sensordata import SensorData
10
- from pyvale.core.errorcalculator import (IErrCalculator,
8
+ from pyvale.sensordata import SensorData
9
+ from pyvale.errorcalculator import (IErrCalculator,
11
10
  EErrType,
12
- EErrDependence)
13
- from pyvale.core.generatorsrandom import IGeneratorRandom
11
+ EErrDep)
12
+ from pyvale.generatorsrandom import IGenRandom
14
13
 
15
14
 
16
- class ErrRandUniform(IErrCalculator):
15
+ class ErrRandUnif(IErrCalculator):
17
16
  """Random error calculator based on uniform sampling of an interval
18
17
  specified by its upper and lower bound.
19
18
 
@@ -24,10 +23,9 @@ class ErrRandUniform(IErrCalculator):
24
23
  def __init__(self,
25
24
  low: float,
26
25
  high: float,
27
- err_dep: EErrDependence = EErrDependence.INDEPENDENT,
26
+ err_dep: EErrDep = EErrDep.INDEPENDENT,
28
27
  seed: int | None = None) -> None:
29
- """Initialiser for `ErrRandUniform` class.
30
-
28
+ """
31
29
  Parameters
32
30
  ----------
33
31
  low : float
@@ -55,7 +53,7 @@ class ErrRandUniform(IErrCalculator):
55
53
  self.rng = np.random.default_rng(seed)
56
54
  self.err_dep = err_dep
57
55
 
58
- def get_error_dep(self) -> EErrDependence:
56
+ def get_error_dep(self) -> EErrDep:
59
57
  """Gets the error dependence state for this error calculator. An
60
58
  independent error is calculated based on the input truth values as the
61
59
  error basis. A dependent error is calculated based on the accumulated
@@ -70,7 +68,7 @@ class ErrRandUniform(IErrCalculator):
70
68
  """
71
69
  return self.err_dep
72
70
 
73
- def set_error_dep(self, dependence: EErrDependence) -> None:
71
+ def set_error_dep(self, dependence: EErrDep) -> None:
74
72
  """Sets the error dependence state for this error calculator. An
75
73
  independent error is calculated based on the input truth values as the
76
74
  error basis. A dependent error is calculated based on the accumulated
@@ -139,10 +137,9 @@ class ErrRandUnifPercent(IErrCalculator):
139
137
  def __init__(self,
140
138
  low_percent: float,
141
139
  high_percent: float,
142
- err_dep: EErrDependence = EErrDependence.INDEPENDENT,
140
+ err_dep: EErrDep = EErrDep.INDEPENDENT,
143
141
  seed: int | None = None) -> None:
144
- """Initialiser for the `ErrRandUnifPercent` class.
145
-
142
+ """
146
143
  Parameters
147
144
  ----------
148
145
  low_percent : float
@@ -171,7 +168,7 @@ class ErrRandUnifPercent(IErrCalculator):
171
168
  self.rng = np.random.default_rng(seed)
172
169
  self.err_dep = err_dep
173
170
 
174
- def get_error_dep(self) -> EErrDependence:
171
+ def get_error_dep(self) -> EErrDep:
175
172
  """Gets the error dependence state for this error calculator. An
176
173
  independent error is calculated based on the input truth values as the
177
174
  error basis. A dependent error is calculated based on the accumulated
@@ -184,7 +181,7 @@ class ErrRandUnifPercent(IErrCalculator):
184
181
  """
185
182
  return self.err_dep
186
183
 
187
- def set_error_dep(self, dependence: EErrDependence) -> None:
184
+ def set_error_dep(self, dependence: EErrDep) -> None:
188
185
  """Sets the error dependence state for this error calculator. An
189
186
  independent error is calculated based on the input truth values as the
190
187
  error basis. A dependent error is calculated based on the accumulated
@@ -235,7 +232,7 @@ class ErrRandUnifPercent(IErrCalculator):
235
232
  return (err_basis*norm_rand,sens_data)
236
233
 
237
234
 
238
- class ErrRandNormal(IErrCalculator):
235
+ class ErrRandNorm(IErrCalculator):
239
236
  """Random error calculator based on sampling of a normal (Gaussian)
240
237
  distribution specified using the standard deviation with an assumed zero
241
238
  mean. A non-zero mean is a systematic error and should be specified using
@@ -247,10 +244,9 @@ class ErrRandNormal(IErrCalculator):
247
244
 
248
245
  def __init__(self,
249
246
  std: float,
250
- err_dep: EErrDependence = EErrDependence.INDEPENDENT,
247
+ err_dep: EErrDep = EErrDep.INDEPENDENT,
251
248
  seed: int | None = None) -> None:
252
- """Initialiser for `ErrRandNormal` class.
253
-
249
+ """
254
250
  Parameters
255
251
  ----------
256
252
  std : float
@@ -265,7 +261,7 @@ class ErrRandNormal(IErrCalculator):
265
261
  self.rng = np.random.default_rng(seed)
266
262
  self.err_dep = err_dep
267
263
 
268
- def get_error_dep(self) -> EErrDependence:
264
+ def get_error_dep(self) -> EErrDep:
269
265
  """Gets the error dependence state for this error calculator. An
270
266
  independent error is calculated based on the input truth values as the
271
267
  error basis. A dependent error is calculated based on the accumulated
@@ -280,7 +276,7 @@ class ErrRandNormal(IErrCalculator):
280
276
  """
281
277
  return self.err_dep
282
278
 
283
- def set_error_dep(self, dependence: EErrDependence) -> None:
279
+ def set_error_dep(self, dependence: EErrDep) -> None:
284
280
  """Sets the error dependence state for this error calculator. An
285
281
  independent error is calculated based on the input truth values as the
286
282
  error basis. A dependent error is calculated based on the accumulated
@@ -350,10 +346,9 @@ class ErrRandNormPercent(IErrCalculator):
350
346
 
351
347
  def __init__(self,
352
348
  std_percent: float,
353
- err_dep: EErrDependence = EErrDependence.INDEPENDENT,
349
+ err_dep: EErrDep = EErrDep.INDEPENDENT,
354
350
  seed: int | None = None) -> None:
355
- """Initialiser for `ErrRandNormPercent` class.
356
-
351
+ """
357
352
  Parameters
358
353
  ----------
359
354
  std_percent : float
@@ -369,7 +364,7 @@ class ErrRandNormPercent(IErrCalculator):
369
364
  self._rng = np.random.default_rng(seed)
370
365
  self._err_dep = err_dep
371
366
 
372
- def get_error_dep(self) -> EErrDependence:
367
+ def get_error_dep(self) -> EErrDep:
373
368
  """Gets the error dependence state for this error calculator. An
374
369
  independent error is calculated based on the input truth values as the
375
370
  error basis. A dependent error is calculated based on the accumulated
@@ -382,7 +377,7 @@ class ErrRandNormPercent(IErrCalculator):
382
377
  """
383
378
  return self._err_dep
384
379
 
385
- def set_error_dep(self, dependence: EErrDependence) -> None:
380
+ def set_error_dep(self, dependence: EErrDep) -> None:
386
381
  """Sets the error dependence state for this error calculator. An
387
382
  independent error is calculated based on the input truth values as the
388
383
  error basis. A dependent error is calculated based on the accumulated
@@ -442,10 +437,9 @@ class ErrRandGenerator(IErrCalculator):
442
437
  __slots__ = ("_generator","_err_dep")
443
438
 
444
439
  def __init__(self,
445
- generator: IGeneratorRandom,
446
- err_dep: EErrDependence = EErrDependence.INDEPENDENT) -> None:
447
- """Initiliaser for the `ErrRandGenerator` class.
448
-
440
+ generator: IGenRandom,
441
+ err_dep: EErrDep = EErrDep.INDEPENDENT) -> None:
442
+ """
449
443
  Parameters
450
444
  ----------
451
445
  generator : IGeneratorRandom
@@ -456,7 +450,7 @@ class ErrRandGenerator(IErrCalculator):
456
450
  self._generator = generator
457
451
  self._err_dep = err_dep
458
452
 
459
- def get_error_dep(self) -> EErrDependence:
453
+ def get_error_dep(self) -> EErrDep:
460
454
  """Gets the error dependence state for this error calculator. An
461
455
  independent error is calculated based on the input truth values as the
462
456
  error basis. A dependent error is calculated based on the accumulated
@@ -471,7 +465,7 @@ class ErrRandGenerator(IErrCalculator):
471
465
  """
472
466
  return self._err_dep
473
467
 
474
- def set_error_dep(self, dependence: EErrDependence) -> None:
468
+ def set_error_dep(self, dependence: EErrDep) -> None:
475
469
  """Sets the error dependence state for this error calculator. An
476
470
  independent error is calculated based on the input truth values as the
477
471
  error basis. A dependent error is calculated based on the accumulated
@@ -537,10 +531,9 @@ class ErrRandGenPercent(IErrCalculator):
537
531
  __slots__ = ("_generator","_err_dep")
538
532
 
539
533
  def __init__(self,
540
- generator: IGeneratorRandom,
541
- err_dep: EErrDependence = EErrDependence.INDEPENDENT) -> None:
542
- """Initiliaser for the `ErrRandGenerator` class.
543
-
534
+ generator: IGenRandom,
535
+ err_dep: EErrDep = EErrDep.INDEPENDENT) -> None:
536
+ """
544
537
  Parameters
545
538
  ----------
546
539
  generator : IGeneratorRandom
@@ -551,7 +544,7 @@ class ErrRandGenPercent(IErrCalculator):
551
544
  self._generator = generator
552
545
  self._err_dep = err_dep
553
546
 
554
- def get_error_dep(self) -> EErrDependence:
547
+ def get_error_dep(self) -> EErrDep:
555
548
  """Gets the error dependence state for this error calculator. An
556
549
  independent error is calculated based on the input truth values as the
557
550
  error basis. A dependent error is calculated based on the accumulated
@@ -564,7 +557,7 @@ class ErrRandGenPercent(IErrCalculator):
564
557
  """
565
558
  return self._err_dep
566
559
 
567
- def set_error_dep(self, dependence: EErrDependence) -> None:
560
+ def set_error_dep(self, dependence: EErrDep) -> None:
568
561
  """Sets the error dependence state for this error calculator. An
569
562
  independent error is calculated based on the input truth values as the
570
563
  error basis. A dependent error is calculated based on the accumulated
@@ -609,6 +602,6 @@ class ErrRandGenPercent(IErrCalculator):
609
602
  error array has the same shape as the input error basis.
610
603
  """
611
604
  rand_errs = err_basis \
612
- * self._generator.generate(shape=err_basis.shape)/100
605
+ * self._generator.generate(shape=err_basis.shape)/100.0
613
606
 
614
607
  return (rand_errs,sens_data)