pyvale 2025.4.1__py3-none-any.whl → 2025.5.2__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 (126) hide show
  1. pyvale/__init__.py +18 -3
  2. pyvale/analyticmeshgen.py +1 -0
  3. pyvale/analyticsimdatafactory.py +18 -13
  4. pyvale/analyticsimdatagenerator.py +105 -72
  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/camera.py +6 -5
  12. pyvale/cameradata.py +25 -7
  13. pyvale/cameradata2d.py +6 -4
  14. pyvale/camerastereo.py +217 -0
  15. pyvale/cameratools.py +206 -11
  16. pyvale/cython/rastercyth.py +6 -2
  17. pyvale/data/cal_target.tiff +0 -0
  18. pyvale/dataset.py +73 -14
  19. pyvale/errorcalculator.py +8 -10
  20. pyvale/errordriftcalc.py +10 -9
  21. pyvale/errorintegrator.py +19 -21
  22. pyvale/errorrand.py +33 -39
  23. pyvale/errorsyscalib.py +134 -0
  24. pyvale/errorsysdep.py +19 -22
  25. pyvale/errorsysfield.py +49 -41
  26. pyvale/errorsysindep.py +79 -175
  27. pyvale/examples/basics/ex1_1_basicscalars_therm2d.py +131 -0
  28. pyvale/examples/basics/ex1_2_sensormodel_therm2d.py +158 -0
  29. pyvale/examples/basics/ex1_3_customsens_therm3d.py +216 -0
  30. pyvale/examples/basics/ex1_4_basicerrors_therm3d.py +153 -0
  31. pyvale/examples/basics/ex1_5_fielderrs_therm3d.py +168 -0
  32. pyvale/examples/basics/ex1_6_caliberrs_therm2d.py +133 -0
  33. pyvale/examples/basics/ex1_7_spatavg_therm2d.py +123 -0
  34. pyvale/examples/basics/ex2_1_basicvectors_disp2d.py +112 -0
  35. pyvale/examples/basics/ex2_2_vectorsens_disp2d.py +111 -0
  36. pyvale/examples/basics/ex2_3_sensangle_disp2d.py +139 -0
  37. pyvale/examples/basics/ex2_4_chainfielderrs_disp2d.py +196 -0
  38. pyvale/examples/basics/ex2_5_vectorfields3d_disp3d.py +109 -0
  39. pyvale/examples/basics/ex3_1_basictensors_strain2d.py +114 -0
  40. pyvale/examples/basics/ex3_2_tensorsens2d_strain2d.py +111 -0
  41. pyvale/examples/basics/ex3_3_tensorsens3d_strain3d.py +182 -0
  42. pyvale/examples/basics/ex4_1_expsim2d_thermmech2d.py +171 -0
  43. pyvale/examples/basics/ex4_2_expsim3d_thermmech3d.py +252 -0
  44. pyvale/examples/{analyticdatagen → genanalyticdata}/ex1_1_scalarvisualisation.py +6 -9
  45. pyvale/examples/{analyticdatagen → genanalyticdata}/ex1_2_scalarcasebuild.py +8 -11
  46. pyvale/examples/{analyticdatagen → genanalyticdata}/ex2_1_analyticsensors.py +9 -12
  47. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +8 -15
  48. pyvale/examples/renderblender/ex1_1_blenderscene.py +121 -0
  49. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +119 -0
  50. pyvale/examples/renderblender/ex2_1_stereoscene.py +128 -0
  51. pyvale/examples/renderblender/ex2_2_stereodeformed.py +131 -0
  52. pyvale/examples/renderblender/ex3_1_blendercalibration.py +120 -0
  53. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastenp.py +3 -2
  54. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_oneframe.py +2 -2
  55. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_static_cypara.py +3 -8
  56. pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_static_pypara.py +6 -7
  57. pyvale/examples/{ex1_4_thermal2d.py → visualisation/ex1_1_plot_traces.py} +32 -16
  58. pyvale/examples/{features/ex_animation_tools_3dmonoblock.py → visualisation/ex2_1_animate_sim.py} +37 -31
  59. pyvale/experimentsimulator.py +107 -30
  60. pyvale/field.py +2 -9
  61. pyvale/fieldconverter.py +98 -22
  62. pyvale/fieldsampler.py +2 -2
  63. pyvale/fieldscalar.py +10 -10
  64. pyvale/fieldtensor.py +15 -17
  65. pyvale/fieldtransform.py +7 -2
  66. pyvale/fieldvector.py +6 -7
  67. pyvale/generatorsrandom.py +25 -47
  68. pyvale/imagedef2d.py +6 -2
  69. pyvale/integratorfactory.py +2 -2
  70. pyvale/integratorquadrature.py +50 -24
  71. pyvale/integratorrectangle.py +85 -7
  72. pyvale/integratorspatial.py +4 -4
  73. pyvale/integratortype.py +3 -3
  74. pyvale/output.py +17 -0
  75. pyvale/pyvaleexceptions.py +11 -0
  76. pyvale/raster.py +6 -5
  77. pyvale/rastercy.py +6 -4
  78. pyvale/rasternp.py +6 -4
  79. pyvale/rendermesh.py +6 -2
  80. pyvale/sensorarray.py +2 -2
  81. pyvale/sensorarrayfactory.py +52 -65
  82. pyvale/sensorarraypoint.py +29 -30
  83. pyvale/sensordata.py +2 -2
  84. pyvale/sensordescriptor.py +138 -25
  85. pyvale/sensortools.py +3 -3
  86. pyvale/simtools.py +67 -0
  87. pyvale/visualexpplotter.py +99 -57
  88. pyvale/visualimagedef.py +11 -7
  89. pyvale/visualimages.py +6 -4
  90. pyvale/visualopts.py +372 -58
  91. pyvale/visualsimanimator.py +42 -13
  92. pyvale/visualsimsensors.py +318 -0
  93. pyvale/visualtools.py +69 -13
  94. pyvale/visualtraceplotter.py +52 -165
  95. {pyvale-2025.4.1.dist-info → pyvale-2025.5.2.dist-info}/METADATA +17 -14
  96. pyvale-2025.5.2.dist-info/RECORD +172 -0
  97. {pyvale-2025.4.1.dist-info → pyvale-2025.5.2.dist-info}/WHEEL +1 -1
  98. pyvale/examples/analyticdatagen/__init__.py +0 -5
  99. pyvale/examples/ex1_1_thermal2d.py +0 -86
  100. pyvale/examples/ex1_2_thermal2d.py +0 -108
  101. pyvale/examples/ex1_3_thermal2d.py +0 -110
  102. pyvale/examples/ex1_5_thermal2d.py +0 -102
  103. pyvale/examples/ex2_1_thermal3d .py +0 -84
  104. pyvale/examples/ex2_2_thermal3d.py +0 -51
  105. pyvale/examples/ex2_3_thermal3d.py +0 -106
  106. pyvale/examples/ex3_1_displacement2d.py +0 -44
  107. pyvale/examples/ex3_2_displacement2d.py +0 -76
  108. pyvale/examples/ex3_3_displacement2d.py +0 -101
  109. pyvale/examples/ex3_4_displacement2d.py +0 -102
  110. pyvale/examples/ex4_1_strain2d.py +0 -54
  111. pyvale/examples/ex4_2_strain2d.py +0 -76
  112. pyvale/examples/ex4_3_strain2d.py +0 -97
  113. pyvale/examples/ex5_1_multiphysics2d.py +0 -75
  114. pyvale/examples/ex6_1_multiphysics2d_expsim.py +0 -115
  115. pyvale/examples/ex6_2_multiphysics3d_expsim.py +0 -160
  116. pyvale/examples/features/__init__.py +0 -5
  117. pyvale/examples/features/ex_area_avg.py +0 -89
  118. pyvale/examples/features/ex_calibration_error.py +0 -108
  119. pyvale/examples/features/ex_chain_field_errs.py +0 -141
  120. pyvale/examples/features/ex_field_errs.py +0 -78
  121. pyvale/examples/features/ex_sensor_single_angle_batch.py +0 -110
  122. pyvale/optimcheckfuncs.py +0 -153
  123. pyvale/visualsimplotter.py +0 -182
  124. pyvale-2025.4.1.dist-info/RECORD +0 -163
  125. {pyvale-2025.4.1.dist-info → pyvale-2025.5.2.dist-info}/licenses/LICENSE +0 -0
  126. {pyvale-2025.4.1.dist-info → pyvale-2025.5.2.dist-info}/top_level.txt +0 -0
@@ -1,160 +0,0 @@
1
- # ================================================================================
2
- # pyvale: the python validation engine
3
- # License: MIT
4
- # Copyright (C) 2025 The Computer Aided Validation Team
5
- # ================================================================================
6
-
7
- from pathlib import Path
8
- import numpy as np
9
- import matplotlib.pyplot as plt
10
- import mooseherder as mh
11
- import pyvale as pyv
12
-
13
- def main() -> None:
14
- """pyvale example: 3D thermo-mechanical with thermocouples & strain gauges
15
- ----------------------------------------------------------------------------
16
- """
17
- # Load Simulations as mooseherder.SimData objects
18
- sim_path = pyv.DataSet.thermomechanical_3d_path()
19
- sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
20
-
21
- # Scale to mm to make 3D visualisation scaling easier
22
- sim_data.coords = sim_data.coords*1000.0
23
- pyv.print_dimensions(sim_data)
24
-
25
- sim_list = [sim_data]
26
-
27
- use_sim_time = True
28
- if use_sim_time:
29
- sample_times = None
30
- else:
31
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
32
-
33
- save_figs = False
34
- save_tag = "thermomech3d"
35
- fig_save_path = Path.cwd()/"images"
36
- if not fig_save_path.is_dir():
37
- fig_save_path.mkdir(parents=True, exist_ok=True)
38
-
39
- #---------------------------------------------------------------------------
40
- # Create the thermocouple array
41
- x_lims = (12.5,12.5)
42
- y_lims = (0.0,33.0)
43
- z_lims = (0.0,12.0)
44
- n_sens = (1,4,1)
45
- tc_sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
46
-
47
- tc_sens_data = pyv.SensorData(positions=tc_sens_pos,
48
- sample_times=sample_times)
49
-
50
- tc_field = "temperature"
51
- tc_array = pyv.SensorArrayFactory \
52
- .thermocouples_basic_errs(sim_data,
53
- tc_sens_data,
54
- tc_field,
55
- spat_dims=3,
56
- errs_pc=1.0)
57
-
58
- # Visualise the thermocouple locations:
59
- pv_plot = pyv.plot_point_sensors_on_sim(tc_array,"temperature")
60
- pv_plot.camera_position = [(59.354, 43.428, 69.946),
61
- (-2.858, 13.189, 4.523),
62
- (-0.215, 0.948, -0.233)]
63
- if save_figs:
64
- pv_plot.save_graphic(fig_save_path/(save_tag+"_tc_vis.svg"))
65
- pv_plot.show()
66
-
67
- #---------------------------------------------------------------------------
68
- # Create the strain gauge array
69
- x_lims = (9.4,9.4)
70
- y_lims = (0.0,33.0)
71
- z_lims = (12.0,12.0)
72
- n_sens = (1,4,1)
73
- sg_sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
74
-
75
- sg_sens_data = pyv.SensorData(positions=sg_sens_pos,
76
- sample_times=sample_times)
77
-
78
-
79
- sg_field = "strain"
80
- sg_array = pyv.SensorArrayFactory \
81
- .strain_gauges_basic_errs(sim_data,
82
- sg_sens_data,
83
- sg_field,
84
- spat_dims=3,
85
- errs_pc=1.0)
86
-
87
- # Visualise the strain gauge locations:
88
- pv_plot = pyv.plot_point_sensors_on_sim(sg_array,"strain_yy")
89
- pv_plot.camera_position = [(59.354, 43.428, 69.946),
90
- (-2.858, 13.189, 4.523),
91
- (-0.215, 0.948, -0.233)]
92
- if save_figs:
93
- pv_plot.save_graphic(fig_save_path/(save_tag+"_sg_vis.svg"))
94
- pv_plot.show()
95
-
96
- #---------------------------------------------------------------------------
97
- # Create and run the simulated experiment
98
- sensor_arrays = [tc_array,sg_array]
99
-
100
- exp_sim = pyv.ExperimentSimulator(sim_list,
101
- sensor_arrays,
102
- num_exp_per_sim=100)
103
-
104
- exp_data = exp_sim.run_experiments()
105
- exp_stats = exp_sim.calc_stats()
106
-
107
- #---------------------------------------------------------------------------
108
- print(80*"=")
109
- print("exp_data and exp_stats are lists where the index is the sensor array")
110
- print("position in the list as field components are not consistent dims:")
111
- print(f"{len(exp_data)=}")
112
- print(f"{len(exp_stats)=}")
113
- print()
114
-
115
- print(80*"-")
116
- print("Thermal sensor array @ exp_data[0]")
117
- print(80*"-")
118
- print("shape=(n_sims,n_exps,n_sensors,n_field_comps,n_time_steps)")
119
- print(f"{exp_data[0].shape=}")
120
- print()
121
- print("Stats are calculated over all experiments (axis=1)")
122
- print("shape=(n_sims,n_sensors,n_field_comps,n_time_steps)")
123
- print(f"{exp_stats[0].max.shape=}")
124
- print()
125
- print(80*"-")
126
- print("Mechanical sensor array @ exp_data[1]")
127
- print(80*"-")
128
- print("shape=(n_sims,n_exps,n_sensors,n_field_comps,n_time_steps)")
129
- print(f"{exp_data[1].shape=}")
130
- print()
131
- print("shape=(n_sims,n_sensors,n_field_comps,n_time_steps)")
132
- print(f"{exp_stats[1].max.shape=}")
133
- print(80*"=")
134
-
135
- #---------------------------------------------------------------------------
136
- # Visualise all sensor traces over all experiments
137
- trace_opts = pyv.TraceOptsExperiment(plot_all_exp_points=True)
138
-
139
- (fig,ax) = pyv.plot_exp_traces(exp_sim,
140
- component="temperature",
141
- sens_array_num=0,
142
- sim_num=0,
143
- trace_opts=trace_opts)
144
- if save_figs:
145
- fig.savefig(fig_save_path/(save_tag+"_tc_traces.png"),
146
- dpi=300, format='png', bbox_inches='tight')
147
-
148
- (fig,ax) = pyv.plot_exp_traces(exp_sim,
149
- component="strain_yy",
150
- sens_array_num=1,
151
- sim_num=0,
152
- trace_opts=trace_opts)
153
- if save_figs:
154
- fig.savefig(fig_save_path/(save_tag+"_sg_traces.png"),
155
- dpi=300, format='png', bbox_inches='tight')
156
- plt.show()
157
-
158
-
159
- if __name__ == "__main__":
160
- main()
@@ -1,5 +0,0 @@
1
- #===============================================================================
2
- # pyvale: the python validation engine
3
- # License: MIT
4
- # Copyright (C) 2025 The Computer Aided Validation Team
5
- #===============================================================================
@@ -1,89 +0,0 @@
1
- """
2
- ================================================================================
3
- example: thermocouples on a 2d plate
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- """
10
- import numpy as np
11
- import matplotlib.pyplot as plt
12
- import mooseherder as mh
13
- import pyvale
14
-
15
-
16
- def main() -> None:
17
- """pyvale example: thermocouples on a 2d plate
18
- ----------------------------------------------------------------------------
19
- - Demonstrates area averaging for truth and for systematic errors
20
- """
21
- data_path = pyvale.DataSet.thermal_2d_path()
22
- sim_data = mh.ExodusReader(data_path).read_all_sim_data()
23
- # Scale to mm to make 3D visualisation scaling easier
24
- sim_data.coords = sim_data.coords*1000.0 # type: ignore
25
-
26
- descriptor = pyvale.SensorDescriptorFactory.temperature_descriptor()
27
-
28
- field_key = "temperature"
29
- t_field = pyvale.FieldScalar(sim_data,
30
- field_key=field_key,
31
- spat_dims=2)
32
-
33
- n_sens = (4,1,1)
34
- x_lims = (0.0,100.0)
35
- y_lims = (0.0,50.0)
36
- z_lims = (0.0,0.0)
37
- sens_pos = pyvale.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
38
-
39
- use_sim_time = True
40
- if use_sim_time:
41
- sample_times = None
42
- else:
43
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
44
-
45
- sensor_dims = np.array([10.0,10.0,0])
46
- sensor_data = pyvale.SensorData(positions=sens_pos,
47
- sample_times=sample_times,
48
- spatial_averager=pyvale.EIntSpatialType.QUAD4PT,
49
- spatial_dims=sensor_dims)
50
-
51
- tc_array = pyvale.SensorArrayPoint(sensor_data,
52
- t_field,
53
- descriptor)
54
-
55
- area_avg_err_data = pyvale.ErrFieldData(
56
- spatial_averager=pyvale.EIntSpatialType.RECT1PT,
57
- spatial_dims=sensor_dims
58
- )
59
- err_chain = []
60
- err_chain.append(pyvale.ErrSysField(t_field,
61
- area_avg_err_data))
62
- error_int = pyvale.ErrIntegrator(err_chain,
63
- sensor_data,
64
- tc_array.get_measurement_shape())
65
- tc_array.set_error_integrator(error_int)
66
-
67
- measurements = tc_array.get_measurements()
68
-
69
- print("\n"+80*"-")
70
- print("For a sensor: measurement = truth + sysematic error + random error")
71
- print(f"measurements.shape = {measurements.shape} = "+
72
- "(n_sensors,n_field_components,n_timesteps)\n")
73
- print("The truth, systematic error and random error arrays have the same "+
74
- "shape.")
75
-
76
- print(80*"-")
77
- print("Looking at the last 5 time steps (measurements) of sensor 0:")
78
- pyvale.print_measurements(tc_array,
79
- (0,1),
80
- (0,1),
81
- (0,10))
82
- print(80*"-")
83
-
84
- pyvale.plot_time_traces(tc_array,field_key)
85
- plt.show()
86
-
87
-
88
- if __name__ == "__main__":
89
- main()
@@ -1,108 +0,0 @@
1
- '''
2
- ================================================================================
3
- DEV: calibration check
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- '''
10
- import matplotlib.pyplot as plt
11
- import numpy as np
12
- import mooseherder as mh
13
- import pyvale
14
-
15
-
16
- def assumed_calib(signal: np.ndarray) -> np.ndarray:
17
- return 24.3*signal + 0.616
18
-
19
-
20
- def truth_calib(signal: np.ndarray) -> np.ndarray:
21
- return -0.01897 + 25.41881*signal - 0.42456*signal**2 + 0.04365*signal**3
22
-
23
-
24
- def main() -> None:
25
- """pyvale example: sensor calibration error
26
- Based on K-type thermocouple calibration
27
- """
28
- n_divs = 10000
29
- signal_calib_range = np.array((0,6))
30
- v = np.linspace(signal_calib_range[0],signal_calib_range[1],n_divs)
31
-
32
- temp_truth = -0.01897 + 25.41881*v - 0.42456*v**2 + 0.04365*v**3
33
- temp_assumed = 24.3*v + 0.616
34
- calib_error = temp_assumed - temp_truth
35
- print()
36
- print(80*"-")
37
- print(f"Calibration error over signal:"+\
38
- f" {signal_calib_range[0]} to {signal_calib_range[1]} mV")
39
- print(calib_error)
40
- print(f"Max calib error: {np.max(calib_error)}")
41
- print(f"Min calib error: {np.min(calib_error)}")
42
- print()
43
-
44
- data_path = pyvale.DataSet.thermal_2d_path()
45
- sim_data = mh.ExodusReader(data_path).read_all_sim_data()
46
- # Scale to mm to make 3D visualisation scaling easier
47
- sim_data.coords = sim_data.coords*1000.0
48
-
49
- descriptor = pyvale.SensorDescriptorFactory.temperature_descriptor()
50
-
51
- field_key = 'temperature'
52
- t_field = pyvale.FieldScalar(sim_data,
53
- field_key=field_key,
54
- spat_dims=2)
55
-
56
- n_sens = (4,1,1)
57
- x_lims = (0.0,100.0)
58
- y_lims = (0.0,50.0)
59
- z_lims = (0.0,0.0)
60
- sens_pos = pyvale.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
61
-
62
- use_sim_time = False
63
- if use_sim_time:
64
- sample_times = None
65
- else:
66
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
67
-
68
- sens_data = pyvale.SensorData(positions=sens_pos,
69
- sample_times=sample_times)
70
-
71
- tc_array = pyvale.SensorArrayPoint(sens_data,
72
- t_field,
73
- descriptor)
74
-
75
- cal_err = pyvale.ErrSysCalibration(assumed_calib,
76
- truth_calib,
77
- signal_calib_range,
78
- n_cal_divs=10000)
79
- sys_err_int = pyvale.ErrIntegrator([cal_err],
80
- sens_data,
81
- tc_array.get_measurement_shape())
82
- tc_array.set_error_integrator(sys_err_int)
83
-
84
- measurements = tc_array.get_measurements()
85
-
86
- print('\n'+80*'-')
87
- print('For a sensor: measurement = truth + sysematic error + random error')
88
- print(f'measurements.shape = {measurements.shape} = '+
89
- '(n_sensors,n_field_components,n_timesteps)\n')
90
- print("The truth, systematic error and random error arrays have the same "+
91
- "shape.")
92
-
93
- print(80*'-')
94
- print('Looking at the last 5 time steps (measurements) of sensor 0:')
95
- pyvale.print_measurements(tc_array,
96
- (0,1),
97
- (0,1),
98
- (measurements.shape[2]-5,measurements.shape[2]))
99
- print(80*'-')
100
-
101
- pyvale.plot_time_traces(tc_array,field_key)
102
- plt.show()
103
-
104
-
105
-
106
-
107
- if __name__ == "__main__":
108
- main()
@@ -1,141 +0,0 @@
1
- """
2
- ================================================================================
3
- example: displacement sensors on a 2d plate
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- """
10
- import numpy as np
11
- import matplotlib.pyplot as plt
12
- import mooseherder as mh
13
- import pyvale
14
-
15
- def main() -> None:
16
- data_path = pyvale.DataSet.mechanical_2d_path()
17
- sim_data = mh.ExodusReader(data_path).read_all_sim_data()
18
- # Scale to mm to make 3D visualisation scaling easier
19
- sim_data.coords = sim_data.coords*1000.0 # type: ignore
20
-
21
- descriptor = pyvale.SensorDescriptorFactory.displacement_descriptor()
22
-
23
- spat_dims = 2
24
- field_key = "disp"
25
- components = ("disp_x","disp_y")
26
- disp_field = pyvale.FieldVector(sim_data,field_key,components,spat_dims)
27
-
28
- n_sens = (2,3,1)
29
- x_lims = (0.0,100.0)
30
- y_lims = (0.0,150.0)
31
- z_lims = (0.0,0.0)
32
- sensor_positions = pyvale.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
33
-
34
- use_sim_time = True
35
- if use_sim_time:
36
- sample_times = None
37
- else:
38
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
39
-
40
- sensor_data = pyvale.SensorData(positions=sensor_positions,
41
- sample_times=sample_times)
42
-
43
- disp_sens_array = pyvale.SensorArrayPoint(sensor_data,
44
- disp_field,
45
- descriptor)
46
-
47
- pos_offset = -1.0*np.ones_like(sensor_positions)
48
- pos_offset[:,2] = 0 # in 2d we only have offset in x and y so zero z
49
- pos_error_data = pyvale.ErrFieldData(pos_offset_xyz=pos_offset)
50
-
51
- angle_offset = np.zeros_like(sensor_positions)
52
- angle_offset[:,0] = 1.0 # only rotate about z in 2D
53
- angle_error_data = pyvale.ErrFieldData(ang_offset_zyx=angle_offset)
54
-
55
- time_offset = 2.0*np.ones_like(disp_sens_array.get_sample_times())
56
- time_error_data = pyvale.ErrFieldData(time_offset=time_offset)
57
-
58
- field_errs = []
59
- field_errs.append(pyvale.ErrSysField(disp_field,
60
- time_error_data))
61
- field_errs.append(pyvale.ErrSysField(disp_field,
62
- time_error_data))
63
-
64
- field_errs.append(pyvale.ErrSysField(disp_field,
65
- pos_error_data))
66
- field_errs.append(pyvale.ErrSysField(disp_field,
67
- pos_error_data))
68
-
69
- field_errs.append(pyvale.ErrSysField(disp_field,
70
- angle_error_data))
71
- field_errs.append(pyvale.ErrSysField(disp_field,
72
- angle_error_data))
73
-
74
- err_int_opts = pyvale.ErrIntOpts(force_dependence=True,
75
- store_all_errs=True)
76
- error_int = pyvale.ErrIntegrator(field_errs,
77
- sensor_data,
78
- disp_sens_array.get_measurement_shape(),
79
- err_int_opts)
80
- disp_sens_array.set_error_integrator(error_int)
81
-
82
- measurements = disp_sens_array.calc_measurements()
83
-
84
- sens_data_by_chain = error_int.get_sens_data_by_chain()
85
- if sens_data_by_chain is not None:
86
- for ii,ss in enumerate(sens_data_by_chain):
87
- print(80*"-")
88
- if ss is not None:
89
- print(f"SensorData @ [{ii}]")
90
- print("TIME")
91
- print(ss.sample_times)
92
- print()
93
- print("POSITIONS")
94
- print(ss.positions)
95
- print()
96
- print("ANGLES")
97
- for aa in ss.angles:
98
- print(aa.as_euler("zyx",degrees=True))
99
- print()
100
- print(80*"-")
101
-
102
- print()
103
- print(80*"=")
104
- sens_data_accumulated = error_int.get_sens_data_accumulated()
105
- print("TIME")
106
- print(sens_data_accumulated.sample_times)
107
- print()
108
- print("POSITIONS")
109
- print(sens_data_accumulated.positions)
110
- print()
111
- print("ANGLES")
112
- for aa in sens_data_accumulated.angles:
113
- print(aa.as_euler("zyx",degrees=True))
114
- print()
115
- print(80*"=")
116
-
117
- print(80*"-")
118
- sens_num = 4
119
- print("The last 5 time steps (measurements) of sensor {sens_num}:")
120
- pyvale.print_measurements(disp_sens_array,
121
- (sens_num-1,sens_num),
122
- (0,1),
123
- (measurements.shape[2]-5,measurements.shape[2]))
124
- print(80*"-")
125
-
126
- plot_field = "disp_x"
127
-
128
- if plot_field == "disp_x":
129
- pv_plot = pyvale.plot_point_sensors_on_sim(disp_sens_array,"disp_x")
130
- pv_plot.show()
131
- elif plot_field == "disp_y":
132
- pv_plot = pyvale.plot_point_sensors_on_sim(disp_sens_array,"disp_y")
133
- pv_plot.show()
134
-
135
- pyvale.plot_time_traces(disp_sens_array,"disp_x")
136
- pyvale.plot_time_traces(disp_sens_array,"disp_y")
137
- plt.show()
138
-
139
-
140
- if __name__ == "__main__":
141
- main()
@@ -1,78 +0,0 @@
1
- '''
2
- ================================================================================
3
- Example: thermocouples on a 2d plate
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- '''
10
- import numpy as np
11
- import matplotlib.pyplot as plt
12
- import mooseherder as mh
13
- import pyvale
14
-
15
-
16
- def main() -> None:
17
- """pyvale example: point sensors on a 2D thermal simulation
18
- ----------------------------------------------------------------------------
19
- """
20
- data_path = pyvale.DataSet.thermal_2d_path()
21
- sim_data = mh.ExodusReader(data_path).read_all_sim_data()
22
- field_key = list(sim_data.node_vars.keys())[0] # type: ignore
23
- # Scale to mm to make 3D visualisation scaling easier
24
- sim_data.coords = sim_data.coords*1000.0 # type: ignore
25
-
26
- n_sens = (4,1,1)
27
- x_lims = (0.0,100.0)
28
- y_lims = (0.0,50.0)
29
- z_lims = (0.0,0.0)
30
- sens_pos = pyvale.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
31
-
32
- sample_times = np.linspace(0.0,np.max(sim_data.time),50) # | None
33
-
34
- sensor_data = pyvale.SensorData(positions=sens_pos,
35
- sample_times=sample_times)
36
-
37
- tc_array = pyvale.SensorArrayFactory \
38
- .thermocouples_no_errs(sim_data,
39
- sensor_data,
40
- field_key,
41
- spat_dims=2)
42
-
43
- #---------------------------------------------------------------------------
44
- # Standard independent systematic errors
45
- pos_rand = pyvale.GeneratorNormal(std=1.0) # mm
46
- pos_lock = np.full_like(sensor_data.positions,False,dtype=bool)
47
- pos_lock[:,2] = True
48
- field_err_data = pyvale.ErrFieldData(
49
- pos_rand_xyz=(pos_rand,pos_rand,pos_rand),
50
- pos_lock_xyz=pos_lock
51
- )
52
-
53
- err_chain = []
54
- err_chain.append(pyvale.ErrSysField(tc_array.get_field(),
55
- field_err_data))
56
- err_int = pyvale.ErrIntegrator(err_chain,
57
- sensor_data,
58
- tc_array.get_measurement_shape())
59
- tc_array.set_error_integrator(err_int)
60
-
61
-
62
- #---------------------------------------------------------------------------
63
- measurements = tc_array.calc_measurements()
64
- print(80*'-')
65
- sens_num = 4
66
- print('The last 5 time steps (measurements) of sensor {sens_num}:')
67
- pyvale.print_measurements(tc_array,
68
- (sens_num-1,sens_num),
69
- (0,1),
70
- (measurements.shape[2]-5,measurements.shape[2]))
71
- print(80*'-')
72
-
73
- pyvale.plot_time_traces(tc_array,field_key)
74
- plt.show()
75
-
76
-
77
- if __name__ == '__main__':
78
- main()
@@ -1,110 +0,0 @@
1
- """
2
- ================================================================================
3
- Example: displacement sensors on a 2d plate
4
-
5
- pyvale: the python validation engine
6
- License: MIT
7
- Copyright (C) 2025 The Computer Aided Validation Team
8
- ================================================================================
9
- """
10
- import numpy as np
11
- import matplotlib.pyplot as plt
12
- from scipy.spatial.transform import Rotation
13
- import mooseherder as mh
14
- import pyvale
15
-
16
- def main() -> None:
17
- """pyvale example: single rotation batch processing
18
- ----------------------------------------------------------------------------
19
- - Tests that when only one sensor rotation is provided that
20
- all sensors are assumed to have the same rotation and batch processed.
21
- """
22
- data_path = pyvale.DataSet.mechanical_2d_path()
23
- sim_data = mh.ExodusReader(data_path).read_all_sim_data()
24
- # Scale to mm to make 3D visualisation scaling easier
25
- sim_data.coords = sim_data.coords*1000.0 # type: ignore
26
-
27
- descriptor = pyvale.SensorDescriptorFactory.displacement_descriptor()
28
-
29
- spat_dims = 2
30
- field_key = "disp"
31
- components = ("disp_x","disp_y")
32
- disp_field = pyvale.FieldVector(sim_data,field_key,components,spat_dims)
33
-
34
- #---------------------------------------------------------------------------
35
- n_sens = (2,3,1)
36
- x_lims = (0.0,100.0)
37
- y_lims = (0.0,150.0)
38
- z_lims = (0.0,0.0)
39
- sensor_positions = pyvale.create_sensor_pos_array(n_sens,
40
- x_lims,
41
- y_lims,
42
- z_lims)
43
-
44
- use_sim_time = False
45
- if use_sim_time:
46
- sample_times = None
47
- else:
48
- sample_times = np.linspace(0.0,np.max(sim_data.time),50)
49
-
50
- # Provide only a single rotation for the 6 sensors
51
- sensor_angles = (Rotation.from_euler("zyx", [180, 0, 0], degrees=True),)
52
-
53
- sensor_data_norot = pyvale.SensorData(positions=sensor_positions,
54
- sample_times=sample_times)
55
-
56
-
57
- sensor_data_rot = pyvale.SensorData(positions=sensor_positions,
58
- sample_times=sample_times,
59
- angles=sensor_angles)
60
-
61
- #---------------------------------------------------------------------------
62
- disp_sensors_norot = pyvale.SensorArrayPoint(sensor_data_norot,
63
- disp_field,
64
- descriptor)
65
-
66
-
67
- disp_sensors_rot = pyvale.SensorArrayPoint(sensor_data_rot,
68
- disp_field,
69
- descriptor)
70
-
71
-
72
-
73
- measurements_norot = disp_sensors_norot.calc_measurements()
74
- measurements_rot = disp_sensors_rot.calc_measurements()
75
-
76
- #---------------------------------------------------------------------------
77
- sens_to_print = 1
78
- print(80*"-")
79
- print(f"The last 5 time steps (measurements) of non-rotated sensor {sens_to_print}:")
80
- pyvale.print_measurements(disp_sensors_norot,
81
- (sens_to_print-1,sens_to_print),
82
- (0,1),
83
- (measurements_norot.shape[2]-5,measurements_norot.shape[2]))
84
- print(80*"-")
85
- print(f"The last 5 time steps (measurements) of rotated sensor {sens_to_print}:")
86
- pyvale.print_measurements(disp_sensors_rot,
87
- (sens_to_print-1,sens_to_print),
88
- (0,1),
89
- (measurements_rot.shape[2]-5,measurements_rot.shape[2]))
90
- print(80*"-")
91
-
92
- #---------------------------------------------------------------------------
93
- plot_field = "disp_x"
94
-
95
- if plot_field == "disp_x":
96
- pv_plot = pyvale.plot_point_sensors_on_sim(disp_sensors_rot,"disp_x")
97
- pv_plot.show(cpos="xy")
98
- elif plot_field == "disp_y":
99
- pv_plot = pyvale.plot_point_sensors_on_sim(disp_sensors_rot,"disp_y")
100
- pv_plot.show(cpos="xy")
101
-
102
- (fig,ax) = pyvale.plot_time_traces(disp_sensors_norot,plot_field)
103
- ax.set_title("No rotation")
104
- (fig,ax) = pyvale.plot_time_traces(disp_sensors_rot,plot_field)
105
- ax.set_title("Rotated")
106
- plt.show()
107
-
108
-
109
- if __name__ == "__main__":
110
- main()