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
@@ -0,0 +1,191 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ """
8
+ This module contains function for plotting virtuals sensor trace summary
9
+ statistics and uncertainty bounds over simulated experiments.
10
+ """
11
+
12
+ from typing import Any
13
+ import numpy as np
14
+ import matplotlib.pyplot as plt
15
+ from pyvale.pyvaleexceptions import VisError
16
+ from pyvale.visualopts import (PlotOptsGeneral,
17
+ TraceOptsExperiment,
18
+ EExpVisBounds,
19
+ EExpVisCentre)
20
+ from pyvale.experimentsimulator import ExperimentSimulator
21
+
22
+
23
+ def plot_exp_traces(exp_sim: ExperimentSimulator,
24
+ component: str,
25
+ sens_array_num: int,
26
+ sim_num: int,
27
+ trace_opts: TraceOptsExperiment | None = None,
28
+ plot_opts: PlotOptsGeneral | None = None) -> tuple[Any,Any]:
29
+ """Plots time traces for summary statistics of virtual sensor traces over
30
+ a series of virtual experiments.
31
+
32
+ Parameters
33
+ ----------
34
+ exp_sim : ExperimentSimulator
35
+ Experiment simulation object containing the set of virtual experiment to
36
+ be plotted.
37
+ component : str
38
+ String key for the field component to plot.
39
+ sens_array_num : int
40
+ List index for the sensor array to plot.
41
+ sim_num : int
42
+ Index for the simulation to plot.
43
+ trace_opts : TraceOptsExperiment | None, optional
44
+ Dataclass containing specific options for controlling the plot
45
+ appearance, by default None. If None the default options are used.
46
+ plot_opts : PlotOptsGeneral | None, optional
47
+ Dataclass containing general options for formatting plots and
48
+ visualisations, by default None. If None the default options are used.
49
+
50
+ Returns
51
+ -------
52
+ tuple[Any,Any]
53
+ A tuple containing a handle to the matplotlib figure and axis objects:
54
+ (fig,ax).
55
+
56
+ Raises
57
+ ------
58
+ VisError
59
+ There are no virtual experiments or virtuale experiment stats to plot in
60
+ the ExperimentSimulator object. Call 'run_experiments' and 'calc_stats'.
61
+ """
62
+ if trace_opts is None:
63
+ trace_opts = TraceOptsExperiment()
64
+
65
+ if plot_opts is None:
66
+ plot_opts = PlotOptsGeneral()
67
+
68
+ descriptor = exp_sim._sensor_arrays[sens_array_num].descriptor
69
+ comp_ind = exp_sim._sensor_arrays[sens_array_num].field.get_component_index(component)
70
+ samp_time = exp_sim._sensor_arrays[sens_array_num].get_sample_times()
71
+ num_sens = exp_sim._sensor_arrays[sens_array_num].get_measurement_shape()[0]
72
+
73
+ exp_data = exp_sim._exp_data
74
+ exp_stats = exp_sim._exp_stats
75
+
76
+ if exp_data is None or exp_stats is None:
77
+ raise VisError("Before visualising virtual experiment traces the " \
78
+ "virtual experiments must be run. exp_data or exp_stats is None.")
79
+
80
+ if trace_opts.sensors_to_plot is None:
81
+ sensors_to_plot = range(num_sens)
82
+ else:
83
+ sensors_to_plot = trace_opts.sensors_to_plot
84
+
85
+ #---------------------------------------------------------------------------
86
+ # Figure canvas setup
87
+ fig, ax = plt.subplots(figsize=plot_opts.single_fig_size_landscape,
88
+ layout='constrained')
89
+ fig.set_dpi(plot_opts.resolution)
90
+
91
+ #---------------------------------------------------------------------------
92
+ # Plot all simulated experimental points
93
+ if trace_opts.plot_all_exp_points:
94
+ for ss in sensors_to_plot:
95
+ for ee in range(exp_sim._num_exp_per_sim):
96
+ ax.plot(samp_time,
97
+ exp_data[sens_array_num][sim_num,ee,ss,comp_ind,:],
98
+ "+",
99
+ lw=plot_opts.lw,
100
+ ms=plot_opts.ms,
101
+ color=plot_opts.colors[ss % plot_opts.colors_num])
102
+
103
+ sensor_tags = descriptor.create_sensor_tags(num_sens)
104
+ lines = []
105
+ for ss in sensors_to_plot:
106
+ if trace_opts.centre == EExpVisCentre.MEDIAN:
107
+ trace_centre = exp_stats[sens_array_num].med[sim_num,ss,comp_ind,:]
108
+ else:
109
+ trace_centre = exp_stats[sens_array_num].mean[sim_num,ss,comp_ind,:]
110
+
111
+ line, = ax.plot(samp_time,
112
+ trace_centre,
113
+ trace_opts.exp_centre_line,
114
+ label=sensor_tags[ss],
115
+ lw=plot_opts.lw,
116
+ ms=plot_opts.ms,
117
+ color=plot_opts.colors[ss % plot_opts.colors_num])
118
+ lines.append(line)
119
+
120
+ if trace_opts.fill_between is not None:
121
+ upper = np.zeros_like(exp_stats[sens_array_num].min)
122
+ lower = np.zeros_like(exp_stats[sens_array_num].min)
123
+
124
+ if trace_opts.fill_between == EExpVisBounds.MINMAX:
125
+ upper = trace_opts.fill_scale*exp_stats[sens_array_num].min
126
+ lower = trace_opts.fill_scale*exp_stats[sens_array_num].max
127
+ elif trace_opts.fill_between == EExpVisBounds.QUARTILE:
128
+ upper = trace_opts.fill_scale*exp_stats[sens_array_num].q25
129
+ lower = trace_opts.fill_scale*exp_stats[sens_array_num].q75
130
+ elif trace_opts.fill_between == EExpVisBounds.STD:
131
+ upper = trace_centre + \
132
+ trace_opts.fill_scale*exp_stats[sens_array_num].std
133
+ lower = trace_centre - \
134
+ trace_opts.fill_scale*exp_stats[sens_array_num].std
135
+ elif trace_opts.fill_between == EExpVisBounds.MAD:
136
+ upper = trace_centre + \
137
+ trace_opts.fill_scale*exp_stats[sens_array_num].mad
138
+ lower = trace_centre - \
139
+ trace_opts.fill_scale*exp_stats[sens_array_num].mad
140
+
141
+ ax.fill_between(samp_time,
142
+ upper[sim_num,ss,comp_ind,:],
143
+ lower[sim_num,ss,comp_ind,:],
144
+ color=plot_opts.colors[ss % plot_opts.colors_num],
145
+ alpha=0.2)
146
+
147
+ #---------------------------------------------------------------------------
148
+ # Plot simulation and truth line
149
+ if trace_opts.sim_line is not None:
150
+ sim_time = exp_sim._sensor_arrays[sens_array_num].field.get_time_steps()
151
+ sim_vals = exp_sim._sensor_arrays[sens_array_num].field.sample_field(
152
+ exp_sim._sensor_arrays[sens_array_num].positions)
153
+
154
+ for ss in sensors_to_plot:
155
+ ax.plot(sim_time,
156
+ sim_vals[ss,comp_ind,:],
157
+ trace_opts.sim_line,
158
+ lw=plot_opts.lw,
159
+ ms=plot_opts.ms)
160
+
161
+ if trace_opts.truth_line is not None:
162
+ truth = exp_sim._sensor_arrays[sens_array_num].get_truth()
163
+ for ss in sensors_to_plot:
164
+ ax.plot(samp_time,
165
+ truth[ss,comp_ind,:],
166
+ trace_opts.truth_line,
167
+ lw=plot_opts.lw,
168
+ ms=plot_opts.ms,
169
+ color=plot_opts.colors[ss % plot_opts.colors_num])
170
+
171
+ #---------------------------------------------------------------------------
172
+ # Axis / legend labels and options
173
+ ax.set_xlabel(trace_opts.time_label,
174
+ fontsize=plot_opts.font_ax_size, fontname=plot_opts.font_name)
175
+ ax.set_ylabel(descriptor.create_label(comp_ind),
176
+ fontsize=plot_opts.font_ax_size, fontname=plot_opts.font_name)
177
+
178
+ if trace_opts.time_min_max is None:
179
+ ax.set_xlim((np.min(samp_time),np.max(samp_time))) # type: ignore
180
+ else:
181
+ ax.set_xlim(trace_opts.time_min_max)
182
+
183
+ if trace_opts.legend_loc is not None:
184
+ ax.legend(handles=lines,
185
+ prop={"size":plot_opts.font_leg_size},
186
+ loc=trace_opts.legend_loc)
187
+
188
+ plt.grid(True)
189
+ plt.draw()
190
+
191
+ return (fig,ax)
@@ -1,10 +1,13 @@
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
+ NOTE: this module is a feature under developement.
7
9
  """
10
+
8
11
  import numpy as np
9
12
  import matplotlib.pyplot as plt
10
13
 
@@ -60,12 +63,12 @@ class ImageDefDiags:
60
63
  vector_map = "plasma"
61
64
 
62
65
  if def_mask is not None:
63
- ImageDefDiags.plot_image('Def. Mask',def_mask,image_map)
66
+ ImageDefDiags.plot_speckle_image('Def. Mask',def_mask,image_map)
64
67
 
65
- ImageDefDiags.plot_image('Subpx Def. Image',def_image_subpx,image_map)
66
- ImageDefDiags.plot_image('Def. Image',def_image,image_map)
68
+ ImageDefDiags.plot_speckle_image('Subpx Def. Image',def_image_subpx,image_map)
69
+ ImageDefDiags.plot_speckle_image('Def. Image',def_image,image_map)
67
70
 
68
71
  ext = tuple(np.array([subpx_grid_xm.min(),subpx_grid_xm.max(),
69
72
  subpx_grid_ym.min(),subpx_grid_ym.max()])*10**3)
70
- ImageDefDiags.plot_image_xy('Sub Pixel Disp X',subpx_disp_x,ext,V_CMAP)
71
- ImageDefDiags.plot_image_xy('Sub Pixel Disp Y',subpx_disp_y,ext,V_CMAP)
73
+ ImageDefDiags.plot_image_xy('Sub Pixel Disp X',subpx_disp_x,ext,vector_map)
74
+ ImageDefDiags.plot_image_xy('Sub Pixel Disp Y',subpx_disp_y,ext,vector_map)
@@ -1,17 +1,18 @@
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
+ NOTE: this module is a feature under developement.
7
9
  """
10
+
8
11
  from typing import Any
9
12
  import numpy as np
10
13
  import matplotlib.pyplot as plt
11
- from pyvale.core.camera import CameraBasic2D
12
- from pyvale.core.visualopts import PlotOptsGeneral
13
-
14
- # NOTE: This module is a feature under developement.
14
+ from pyvale.camera import CameraBasic2D
15
+ from pyvale.visualopts import PlotOptsGeneral
15
16
 
16
17
  # TODO: this only works for a 2D camera, maybe this should be deprecated
17
18
  def plot_measurement_image(camera: CameraBasic2D,