pyvale 2025.5.3__cp311-cp311-win32.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 (174) hide show
  1. pyvale/__init__.py +89 -0
  2. pyvale/analyticmeshgen.py +102 -0
  3. pyvale/analyticsimdatafactory.py +91 -0
  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/camera.py +146 -0
  12. pyvale/cameradata.py +69 -0
  13. pyvale/cameradata2d.py +84 -0
  14. pyvale/camerastereo.py +217 -0
  15. pyvale/cameratools.py +522 -0
  16. pyvale/cython/rastercyth.c +32211 -0
  17. pyvale/cython/rastercyth.cp311-win32.pyd +0 -0
  18. pyvale/cython/rastercyth.py +640 -0
  19. pyvale/data/__init__.py +5 -0
  20. pyvale/data/cal_target.tiff +0 -0
  21. pyvale/data/case00_HEX20_out.e +0 -0
  22. pyvale/data/case00_HEX27_out.e +0 -0
  23. pyvale/data/case00_HEX8_out.e +0 -0
  24. pyvale/data/case00_TET10_out.e +0 -0
  25. pyvale/data/case00_TET14_out.e +0 -0
  26. pyvale/data/case00_TET4_out.e +0 -0
  27. pyvale/data/case13_out.e +0 -0
  28. pyvale/data/case16_out.e +0 -0
  29. pyvale/data/case17_out.e +0 -0
  30. pyvale/data/case18_1_out.e +0 -0
  31. pyvale/data/case18_2_out.e +0 -0
  32. pyvale/data/case18_3_out.e +0 -0
  33. pyvale/data/case25_out.e +0 -0
  34. pyvale/data/case26_out.e +0 -0
  35. pyvale/data/optspeckle_2464x2056px_spec5px_8bit_gblur1px.tiff +0 -0
  36. pyvale/dataset.py +325 -0
  37. pyvale/errorcalculator.py +109 -0
  38. pyvale/errordriftcalc.py +146 -0
  39. pyvale/errorintegrator.py +336 -0
  40. pyvale/errorrand.py +607 -0
  41. pyvale/errorsyscalib.py +134 -0
  42. pyvale/errorsysdep.py +327 -0
  43. pyvale/errorsysfield.py +414 -0
  44. pyvale/errorsysindep.py +808 -0
  45. pyvale/examples/__init__.py +5 -0
  46. pyvale/examples/basics/ex1_1_basicscalars_therm2d.py +131 -0
  47. pyvale/examples/basics/ex1_2_sensormodel_therm2d.py +158 -0
  48. pyvale/examples/basics/ex1_3_customsens_therm3d.py +216 -0
  49. pyvale/examples/basics/ex1_4_basicerrors_therm3d.py +153 -0
  50. pyvale/examples/basics/ex1_5_fielderrs_therm3d.py +168 -0
  51. pyvale/examples/basics/ex1_6_caliberrs_therm2d.py +133 -0
  52. pyvale/examples/basics/ex1_7_spatavg_therm2d.py +123 -0
  53. pyvale/examples/basics/ex2_1_basicvectors_disp2d.py +112 -0
  54. pyvale/examples/basics/ex2_2_vectorsens_disp2d.py +111 -0
  55. pyvale/examples/basics/ex2_3_sensangle_disp2d.py +139 -0
  56. pyvale/examples/basics/ex2_4_chainfielderrs_disp2d.py +196 -0
  57. pyvale/examples/basics/ex2_5_vectorfields3d_disp3d.py +109 -0
  58. pyvale/examples/basics/ex3_1_basictensors_strain2d.py +114 -0
  59. pyvale/examples/basics/ex3_2_tensorsens2d_strain2d.py +111 -0
  60. pyvale/examples/basics/ex3_3_tensorsens3d_strain3d.py +182 -0
  61. pyvale/examples/basics/ex4_1_expsim2d_thermmech2d.py +171 -0
  62. pyvale/examples/basics/ex4_2_expsim3d_thermmech3d.py +252 -0
  63. pyvale/examples/genanalyticdata/ex1_1_scalarvisualisation.py +35 -0
  64. pyvale/examples/genanalyticdata/ex1_2_scalarcasebuild.py +43 -0
  65. pyvale/examples/genanalyticdata/ex2_1_analyticsensors.py +80 -0
  66. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +79 -0
  67. pyvale/examples/renderblender/ex1_1_blenderscene.py +121 -0
  68. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +119 -0
  69. pyvale/examples/renderblender/ex2_1_stereoscene.py +128 -0
  70. pyvale/examples/renderblender/ex2_2_stereodeformed.py +131 -0
  71. pyvale/examples/renderblender/ex3_1_blendercalibration.py +120 -0
  72. pyvale/examples/renderrasterisation/ex_rastenp.py +153 -0
  73. pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +218 -0
  74. pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +187 -0
  75. pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +190 -0
  76. pyvale/examples/visualisation/ex1_1_plot_traces.py +102 -0
  77. pyvale/examples/visualisation/ex2_1_animate_sim.py +89 -0
  78. pyvale/experimentsimulator.py +175 -0
  79. pyvale/field.py +128 -0
  80. pyvale/fieldconverter.py +351 -0
  81. pyvale/fieldsampler.py +111 -0
  82. pyvale/fieldscalar.py +166 -0
  83. pyvale/fieldtensor.py +218 -0
  84. pyvale/fieldtransform.py +388 -0
  85. pyvale/fieldvector.py +213 -0
  86. pyvale/generatorsrandom.py +505 -0
  87. pyvale/imagedef2d.py +569 -0
  88. pyvale/integratorfactory.py +240 -0
  89. pyvale/integratorquadrature.py +217 -0
  90. pyvale/integratorrectangle.py +165 -0
  91. pyvale/integratorspatial.py +89 -0
  92. pyvale/integratortype.py +43 -0
  93. pyvale/output.py +17 -0
  94. pyvale/pyvaleexceptions.py +11 -0
  95. pyvale/raster.py +31 -0
  96. pyvale/rastercy.py +77 -0
  97. pyvale/rasternp.py +603 -0
  98. pyvale/rendermesh.py +147 -0
  99. pyvale/sensorarray.py +178 -0
  100. pyvale/sensorarrayfactory.py +196 -0
  101. pyvale/sensorarraypoint.py +278 -0
  102. pyvale/sensordata.py +71 -0
  103. pyvale/sensordescriptor.py +213 -0
  104. pyvale/sensortools.py +142 -0
  105. pyvale/simcases/case00_HEX20.i +242 -0
  106. pyvale/simcases/case00_HEX27.i +242 -0
  107. pyvale/simcases/case00_HEX8.i +242 -0
  108. pyvale/simcases/case00_TET10.i +242 -0
  109. pyvale/simcases/case00_TET14.i +242 -0
  110. pyvale/simcases/case00_TET4.i +242 -0
  111. pyvale/simcases/case01.i +101 -0
  112. pyvale/simcases/case02.i +156 -0
  113. pyvale/simcases/case03.i +136 -0
  114. pyvale/simcases/case04.i +181 -0
  115. pyvale/simcases/case05.i +234 -0
  116. pyvale/simcases/case06.i +305 -0
  117. pyvale/simcases/case07.geo +135 -0
  118. pyvale/simcases/case07.i +87 -0
  119. pyvale/simcases/case08.geo +144 -0
  120. pyvale/simcases/case08.i +153 -0
  121. pyvale/simcases/case09.geo +204 -0
  122. pyvale/simcases/case09.i +87 -0
  123. pyvale/simcases/case10.geo +204 -0
  124. pyvale/simcases/case10.i +257 -0
  125. pyvale/simcases/case11.geo +337 -0
  126. pyvale/simcases/case11.i +147 -0
  127. pyvale/simcases/case12.geo +388 -0
  128. pyvale/simcases/case12.i +329 -0
  129. pyvale/simcases/case13.i +140 -0
  130. pyvale/simcases/case14.i +159 -0
  131. pyvale/simcases/case15.geo +337 -0
  132. pyvale/simcases/case15.i +150 -0
  133. pyvale/simcases/case16.geo +391 -0
  134. pyvale/simcases/case16.i +357 -0
  135. pyvale/simcases/case17.geo +135 -0
  136. pyvale/simcases/case17.i +144 -0
  137. pyvale/simcases/case18.i +254 -0
  138. pyvale/simcases/case18_1.i +254 -0
  139. pyvale/simcases/case18_2.i +254 -0
  140. pyvale/simcases/case18_3.i +254 -0
  141. pyvale/simcases/case19.geo +252 -0
  142. pyvale/simcases/case19.i +99 -0
  143. pyvale/simcases/case20.geo +252 -0
  144. pyvale/simcases/case20.i +250 -0
  145. pyvale/simcases/case21.geo +74 -0
  146. pyvale/simcases/case21.i +155 -0
  147. pyvale/simcases/case22.geo +82 -0
  148. pyvale/simcases/case22.i +140 -0
  149. pyvale/simcases/case23.geo +164 -0
  150. pyvale/simcases/case23.i +140 -0
  151. pyvale/simcases/case24.geo +79 -0
  152. pyvale/simcases/case24.i +123 -0
  153. pyvale/simcases/case25.geo +82 -0
  154. pyvale/simcases/case25.i +140 -0
  155. pyvale/simcases/case26.geo +166 -0
  156. pyvale/simcases/case26.i +140 -0
  157. pyvale/simcases/run_1case.py +61 -0
  158. pyvale/simcases/run_all_cases.py +69 -0
  159. pyvale/simcases/run_build_case.py +64 -0
  160. pyvale/simcases/run_example_cases.py +69 -0
  161. pyvale/simtools.py +67 -0
  162. pyvale/visualexpplotter.py +191 -0
  163. pyvale/visualimagedef.py +74 -0
  164. pyvale/visualimages.py +76 -0
  165. pyvale/visualopts.py +493 -0
  166. pyvale/visualsimanimator.py +111 -0
  167. pyvale/visualsimsensors.py +318 -0
  168. pyvale/visualtools.py +136 -0
  169. pyvale/visualtraceplotter.py +142 -0
  170. pyvale-2025.5.3.dist-info/METADATA +144 -0
  171. pyvale-2025.5.3.dist-info/RECORD +174 -0
  172. pyvale-2025.5.3.dist-info/WHEEL +5 -0
  173. pyvale-2025.5.3.dist-info/licenses/LICENSE +21 -0
  174. pyvale-2025.5.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,80 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ import matplotlib.pyplot as plt
8
+ import numpy as np
9
+ import pyvale
10
+
11
+ def main() -> None:
12
+ (sim_data,_) = pyvale.AnalyticCaseFactory.scalar_linear_2d()
13
+
14
+ descriptor = pyvale.SensorDescriptorFactory.temperature_descriptor()
15
+
16
+ field_key = 'scalar'
17
+ t_field = pyvale.FieldScalar(sim_data,
18
+ field_key=field_key,
19
+ elem_dims=2)
20
+
21
+ n_sens = (4,1,1)
22
+ x_lims = (0.0,10.0)
23
+ y_lims = (0.0,7.5)
24
+ z_lims = (0.0,0.0)
25
+ sens_pos = pyvale.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
26
+
27
+ use_sim_time = False
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
+ sensor_data = pyvale.SensorData(positions=sens_pos,
34
+ sample_times=sample_times)
35
+
36
+ tc_array = pyvale.SensorArrayPoint(sensor_data,
37
+ t_field,
38
+ descriptor)
39
+
40
+ errors_on = {'indep_sys': True,
41
+ 'rand': True,
42
+ 'dep_sys': True}
43
+
44
+ error_chain = []
45
+ if errors_on['indep_sys']:
46
+ error_chain.append(pyvale.ErrSysOffset(offset=-5.0))
47
+ error_chain.append(pyvale.ErrSysUnif(low=-5.0,
48
+ high=5.0))
49
+ gen_norm = pyvale.GenNormal(std=1.0)
50
+
51
+ if errors_on['rand']:
52
+ error_chain.append(pyvale.ErrRandNormPercent(std_percent=1.0))
53
+ error_chain.append(pyvale.ErrRandUnifPercent(low_percent=-1.0,
54
+ high_percent=1.0))
55
+
56
+ if errors_on['dep_sys']:
57
+ error_chain.append(pyvale.ErrSysDigitisation(bits_per_unit=2**8/100))
58
+ error_chain.append(pyvale.ErrSysSaturation(meas_min=0.0,meas_max=300.0))
59
+
60
+ if len(error_chain) > 0:
61
+ error_integrator = pyvale.ErrIntegrator(error_chain,
62
+ sensor_data,
63
+ tc_array.get_measurement_shape())
64
+ tc_array.set_error_integrator(error_integrator)
65
+
66
+ measurements = tc_array.get_measurements()
67
+
68
+ pyvale.print_measurements(tc_array,
69
+ (0,1), # Sensor 1
70
+ (0,1), # Component 1: scalar field = 1 component
71
+ (measurements.shape[2]-5,measurements.shape[2]))
72
+
73
+ (fig,_) = pyvale.plot_time_traces(tc_array,field_key)
74
+ plt.show()
75
+
76
+ pv_plot = pyvale.plot_point_sensors_on_sim(tc_array,field_key)
77
+ pv_plot.show(cpos="xy")
78
+
79
+ if __name__ == '__main__':
80
+ main()
@@ -0,0 +1,79 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+
8
+ from pathlib import Path
9
+ import numpy as np
10
+ import mooseherder as mh
11
+ import pyvale as pyv
12
+
13
+
14
+ def main() -> None:
15
+ sim_path = pyv.DataSet.mechanical_2d_path()
16
+ sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
17
+
18
+ image_path = pyv.DataSet.dic_pattern_5mpx_path()
19
+ image_speckle = pyv.CameraTools.load_image(image_path)
20
+
21
+ save_path = Path.cwd()/"exampleoutput"
22
+
23
+ coords = sim_data.coords
24
+ connectivity = (sim_data.connect["connect1"]-1).T # Beware 0 indexing here
25
+ disp_x = sim_data.node_vars["disp_x"][:,:]
26
+ disp_y = sim_data.node_vars["disp_y"][:,:]
27
+
28
+ print()
29
+ print(80*"-")
30
+ print(f"{coords.shape=}")
31
+ print(f"{connectivity.shape=}")
32
+ print(f"{disp_x.shape=}")
33
+ print(f"{disp_y.shape=}")
34
+ print(80*"-")
35
+
36
+
37
+ cam_data = pyv.CameraData2D(pixels_count=np.array((1040,1540)),
38
+ leng_per_px=0.1e-3,
39
+ bits=8,
40
+ roi_cent_world=np.mean(coords,axis=0),
41
+ subsample=3)
42
+ id_opts = pyv.ImageDefOpts(save_path=save_path,
43
+ crop_on=True,
44
+ add_static_ref=True)
45
+
46
+
47
+
48
+ (upsampled_image,
49
+ image_mask,
50
+ image_input,
51
+ disp_x,
52
+ disp_y) = pyv.ImageDef2D.preprocess(cam_data,
53
+ image_speckle,
54
+ coords,
55
+ connectivity,
56
+ disp_x,
57
+ disp_y,
58
+ id_opts,
59
+ print_on=True)
60
+
61
+ ff = -1
62
+ disp = np.array((disp_x[:,ff],disp_y[:,ff])).T
63
+ print(f"{disp.shape=}")
64
+
65
+
66
+ pyv.ImageDef2D.deform_images_to_disk(cam_data,
67
+ upsampled_image,
68
+ coords,
69
+ connectivity,
70
+ disp_x,
71
+ disp_y,
72
+ image_mask,
73
+ id_opts,
74
+ print_on=True)
75
+
76
+
77
+ if __name__ == "__main__":
78
+ main()
79
+
@@ -0,0 +1,121 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ import numpy as np
8
+ from scipy.spatial.transform import Rotation
9
+ from pathlib import Path
10
+ import pyvale
11
+ import mooseherder as mh
12
+
13
+ def main() -> None:
14
+ data_path = pyvale.DataSet.render_mechanical_3d_path()
15
+ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
16
+
17
+ disp_comps = ("disp_x","disp_y", "disp_z")
18
+
19
+ # Scale m -> mm
20
+ # NOTE: All lengths are to be specified in mm
21
+ sim_data = pyvale.scale_length_units(sim_data,disp_comps,1000.0)
22
+
23
+ render_mesh = pyvale.create_render_mesh(sim_data,
24
+ ("disp_y","disp_x"),
25
+ sim_spat_dim=3,
26
+ field_disp_keys=disp_comps)
27
+
28
+ # Set the save path
29
+ # --------------------------------------------------------------------------
30
+ # All the files saved will be saved to a subfolder within this specified
31
+ # base directory.
32
+ # This base directory can be specified by:
33
+ base_dir = Path.cwd()
34
+ # If no base directory is specified, it will be set as your home directory
35
+
36
+
37
+ # Creating the scene
38
+ # --------------------------------------------------------------------------
39
+ scene = pyvale.BlenderScene()
40
+
41
+
42
+ # It should be noted that the mesh will be centred to allow for the cameras
43
+ # to be centred on the mesh.
44
+ part = scene.add_part(render_mesh, sim_spat_dim=3)
45
+ # Set the part location
46
+ part_location = np.array([0, 0, 0])
47
+ pyvale.BlenderTools.move_blender_obj(part=part, pos_world=part_location)
48
+ # Set part rotation
49
+ part_rotation = Rotation.from_euler("xyz", [0, 0, 0])
50
+ pyvale.BlenderTools.rotate_blender_obj(part=part, rot_world=part_rotation)
51
+
52
+ # Add the camera
53
+ cam_data = pyvale.CameraData(pixels_num=np.array([1540, 1040]),
54
+ pixels_size=np.array([0.00345, 0.00345]),
55
+ pos_world=(0, 0, 400),
56
+ rot_world=Rotation.from_euler("xyz", [0, 0, 0]),
57
+ roi_cent_world=(0, 0, 0),
58
+ focal_length=15.0)
59
+ camera = scene.add_camera(cam_data)
60
+
61
+ # The camera can be moved and rotated this:
62
+ camera.location = (0, 0, 410)
63
+ camera.rotation_euler = (0, 0, 0) # NOTE: The default is an XYZ Euler angle
64
+
65
+
66
+ # Add the light
67
+ light_data = pyvale.BlenderLightData(type=pyvale.BlenderLightType.POINT,
68
+ pos_world=(0, 0, 400),
69
+ rot_world=Rotation.from_euler("xyz",
70
+ [0, 0, 0]),
71
+ energy=1)
72
+ light = scene.add_light(light_data)
73
+
74
+ # The light can also be moved and rotated:
75
+ light.location = (0, 0, 410)
76
+ light.rotation_euler = (0, 0, 0)
77
+
78
+ # Apply the speckle pattern
79
+ material_data = pyvale.BlenderMaterialData()
80
+ speckle_path = pyvale.DataSet.dic_pattern_5mpx_path()
81
+ # NOTE: If you wish to use a bigger camera, you will need to generate a
82
+ # bigger speckle pattern generator
83
+
84
+ mm_px_resolution = pyvale.CameraTools.calculate_mm_px_resolution(cam_data)
85
+ scene.add_speckle(part=part,
86
+ speckle_path=speckle_path,
87
+ mat_data=material_data,
88
+ mm_px_resolution=mm_px_resolution)
89
+
90
+ # Rendering image
91
+ # --------------------------------------------------------------------------
92
+ # Set this to True to render image of the current scene
93
+ render_opts = True
94
+ if render_opts:
95
+ # NOTE: If no save directory is specified, this is where the images will
96
+ # be saved
97
+ render_data = pyvale.RenderData(cam_data=cam_data,
98
+ base_dir=base_dir,
99
+ threads=8)
100
+ # NOTE: The number of threads used to render the images is set within
101
+ # RenderData, it is defaulted to 4 threads
102
+
103
+ scene.render_single_image(stage_image=False,
104
+ render_data=render_data)
105
+ # NOTE: If bounce_image is set to True, the image will be saved to disk,
106
+ # converted to an array, deleted and the image array will be returned.
107
+
108
+ print()
109
+ print(80*"-")
110
+ print("Save directory of the image:", (render_data.base_dir / "blenderimages"))
111
+ print(80*"-")
112
+ print()
113
+
114
+ # Save Blender file
115
+ # --------------------------------------------------------------------------
116
+ # The file that will be saved is a Blender project file. This can be opened
117
+ # with the Blender GUI to view the scene.
118
+ pyvale.BlenderTools.save_blender_file(base_dir)
119
+
120
+ if __name__ == "__main__":
121
+ main()
@@ -0,0 +1,119 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ import numpy as np
8
+ from scipy.spatial.transform import Rotation
9
+ from pathlib import Path
10
+ import pyvale
11
+ import mooseherder as mh
12
+
13
+ def main() -> None:
14
+ data_path = pyvale.DataSet.render_mechanical_3d_path()
15
+ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
16
+
17
+ disp_comps = ("disp_x","disp_y", "disp_z")
18
+
19
+ # Scale m -> mm
20
+ sim_data = pyvale.scale_length_units(sim_data,disp_comps,1000.0)
21
+
22
+ render_mesh = pyvale.create_render_mesh(sim_data,
23
+ ("disp_y","disp_x"),
24
+ sim_spat_dim=3,
25
+ field_disp_keys=disp_comps)
26
+
27
+ # Set the save path
28
+ # --------------------------------------------------------------------------
29
+ # All the files saved will be saved to a subfolder within this specified
30
+ # base directory.
31
+ # This base directory can be specified by:
32
+ base_dir = Path.cwd()
33
+ # If no base directory is specified, it will be set as your home directory
34
+
35
+ # Creating the scene
36
+ # --------------------------------------------------------------------------
37
+ scene = pyvale.BlenderScene()
38
+
39
+ # It should be noted that the mesh will be centred to allow for the cameras
40
+ # to be centred on the mesh.
41
+ part = scene.add_part(render_mesh, sim_spat_dim=3)
42
+ # Set the part location
43
+ part_location = np.array([0, 0, 0])
44
+ pyvale.BlenderTools.move_blender_obj(part=part, pos_world=part_location)
45
+ # Set part rotation
46
+ part_rotation = Rotation.from_euler("xyz", [0, 0, 0])
47
+ pyvale.BlenderTools.rotate_blender_obj(part=part, rot_world=part_rotation)
48
+
49
+ # Add the camera
50
+ cam_data = pyvale.CameraData(pixels_num=np.array([1540, 1040]),
51
+ pixels_size=np.array([0.00345, 0.00345]),
52
+ pos_world=(0, 0, 400),
53
+ rot_world=Rotation.from_euler("xyz", [0, 0, 0]),
54
+ roi_cent_world=(0, 0, 0),
55
+ focal_length=15.0)
56
+ camera = scene.add_camera(cam_data)
57
+
58
+ # The camera can be moved and rotated this:
59
+ camera.location = (0, 0, 410)
60
+ camera.rotation_euler = (0, 0, 0) # NOTE: The default is an XYZ Euler angle
61
+
62
+ # Add the light
63
+ light_data = pyvale.BlenderLightData(type=pyvale.BlenderLightType.POINT,
64
+ pos_world=(0, 0, 400),
65
+ rot_world=Rotation.from_euler("xyz",
66
+ [0, 0, 0]),
67
+ energy=1)
68
+ light = scene.add_light(light_data)
69
+
70
+ # The light can also be moved and rotated:
71
+ light.location = (0, 0, 410)
72
+ light.rotation_euler = (0, 0, 0)
73
+
74
+ # Apply the speckle pattern
75
+ material_data = pyvale.BlenderMaterialData()
76
+ speckle_path = pyvale.DataSet.dic_pattern_5mpx_path()
77
+ # NOTE: If you wish to use a bigger camera, you will need to generate a
78
+ # bigger speckle pattern generator
79
+ mm_px_resolution = pyvale.CameraTools.calculate_mm_px_resolution(cam_data)
80
+ scene.add_speckle(part=part,
81
+ speckle_path=speckle_path,
82
+ mat_data=material_data,
83
+ mm_px_resolution=mm_px_resolution)
84
+
85
+ # Deform and render images
86
+ # --------------------------------------------------------------------------
87
+ # Set this to True to render image of the deforming part
88
+ render_opts = True
89
+ if render_opts:
90
+ # NOTE: If no save directory is specified, this is where the images will
91
+ # be saved
92
+ render_data = pyvale.RenderData(cam_data=cam_data,
93
+ base_dir=base_dir,
94
+ threads=8)
95
+ # NOTE: The number of threads used to render the images is set within
96
+ # RenderData, it is defaulted to 4 threads
97
+
98
+ scene.render_deformed_images(render_mesh,
99
+ sim_spat_dim=3,
100
+ render_data=render_data,
101
+ part=part,
102
+ stage_image=False)
103
+ # NOTE: If bounce_image is set to True, the image will be saved to disk,
104
+ # converted to an array, deleted and the image array will be returned.
105
+
106
+ print()
107
+ print(80*"-")
108
+ print("Save directory of the image:", render_data.base_dir)
109
+ print(80*"-")
110
+ print()
111
+
112
+ # Save Blender file
113
+ # --------------------------------------------------------------------------
114
+ # The file that will be saved is a Blender project file. This can be opened
115
+ # with the Blender GUI to view the scene.
116
+ pyvale.BlenderTools.save_blender_file(base_dir)
117
+
118
+ if __name__ == "__main__":
119
+ main()
@@ -0,0 +1,128 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ import numpy as np
8
+ from scipy.spatial.transform import Rotation
9
+ from pathlib import Path
10
+ import pyvale
11
+ import mooseherder as mh
12
+
13
+ def main() -> None:
14
+ data_path = pyvale.DataSet.render_mechanical_3d_path()
15
+ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
16
+
17
+ disp_comps = ("disp_x","disp_y", "disp_z")
18
+
19
+ # Scale m -> mm
20
+ # NOTE: All lengths are to be specified in mm
21
+ sim_data = pyvale.scale_length_units(sim_data,disp_comps,1000.0)
22
+
23
+ render_mesh = pyvale.create_render_mesh(sim_data,
24
+ ("disp_y","disp_x"),
25
+ sim_spat_dim=3,
26
+ field_disp_keys=disp_comps)
27
+
28
+ # Set the save path
29
+ # --------------------------------------------------------------------------
30
+ # All the files saved will be saved to a subfolder within this specified
31
+ # base directory.
32
+ # This base directory can be specified by:
33
+ base_dir = Path.cwd()
34
+ # If no base directory is specified, it will be set as your home directory
35
+
36
+ # Creating the scene
37
+ # --------------------------------------------------------------------------
38
+ scene = pyvale.BlenderScene()
39
+
40
+ part = scene.add_part(render_mesh, sim_spat_dim=3)
41
+ # Set the part location
42
+ part_location = np.array([0, 0, 0])
43
+ pyvale.BlenderTools.move_blender_obj(part=part, pos_world=part_location)
44
+ # Set part rotation
45
+ part_rotation = Rotation.from_euler("xyz", [0, 0, 0])
46
+ pyvale.BlenderTools.rotate_blender_obj(part=part, rot_world=part_rotation)
47
+
48
+ # Add the stereo camera system
49
+ cam_data_0 = pyvale.CameraData(pixels_num=np.array([1540, 1040]),
50
+ pixels_size=np.array([0.00345, 0.00345]),
51
+ pos_world=np.array([0, 0, 400]),
52
+ rot_world=Rotation.from_euler("xyz", [0, 0, 0]),
53
+ roi_cent_world=(0, 0, 0),
54
+ focal_length=15.0)
55
+ # Set this to "symmetric" to get a symmetric stereo system or set this to
56
+ # "faceon" to get a face-on stereo system
57
+ stereo_setup = "faceon"
58
+ if stereo_setup == "symmetric":
59
+ stereo_system = pyvale.CameraTools.symmetric_stereo_cameras(
60
+ cam_data_0=cam_data_0,
61
+ stereo_angle=15.0)
62
+ if stereo_setup == "faceon":
63
+ stereo_system = pyvale.CameraTools.faceon_stereo_cameras(
64
+ cam_data_0=cam_data_0,
65
+ stereo_angle=15.0)
66
+
67
+ cam0, cam1 = scene.add_stereo_system(stereo_system)
68
+
69
+ # Generate calibration file
70
+ stereo_system.save_calibration(base_dir)
71
+
72
+ # Add the light
73
+ light_data = pyvale.BlenderLightData(type=pyvale.BlenderLightType.POINT,
74
+ pos_world=(0, 0, 400),
75
+ rot_world=Rotation.from_euler("xyz",
76
+ [0, 0, 0]),
77
+ energy=1)
78
+ light = scene.add_light(light_data)
79
+
80
+ # The light can also be moved and rotated:
81
+ light.location = (0, 0, 410)
82
+ light.rotation_euler = (0, 0, 0) # NOTE: The default is an XYZ Euler angle
83
+
84
+ # Apply the speckle pattern
85
+ material_data = pyvale.BlenderMaterialData()
86
+ speckle_path = pyvale.DataSet.dic_pattern_5mpx_path()
87
+ # NOTE: If you wish to use a bigger camera, you will need to generate a
88
+ # bigger speckle pattern generator
89
+
90
+ mm_px_resolution = pyvale.CameraTools.calculate_mm_px_resolution(cam_data_0)
91
+ scene.add_speckle(part=part,
92
+ speckle_path=speckle_path,
93
+ mat_data=material_data,
94
+ mm_px_resolution=mm_px_resolution)
95
+
96
+ # Rendering image
97
+ # --------------------------------------------------------------------------
98
+ # Set this to True to render image of the current scene
99
+ render_opts = True
100
+ if render_opts:
101
+ # NOTE: If no save directory is specified, this is where the images will
102
+ # be saved
103
+ render_data = pyvale.RenderData(cam_data=(stereo_system.cam_data_0,
104
+ stereo_system.cam_data_1),
105
+ base_dir=base_dir,
106
+ threads=8)
107
+ # NOTE: The number of threads used to render the images is set within
108
+ # RenderData, it is defaulted to 4 threads
109
+
110
+ scene.render_single_image(stage_image=False,
111
+ render_data=render_data)
112
+ # NOTE: If bounce_image is set to True, the image will be saved to disk,
113
+ # converted to an array, deleted and the image array will be returned.
114
+
115
+ print()
116
+ print(80*"-")
117
+ print("Save directory of the image:", (render_data.base_dir / "blenderimages"))
118
+ print(80*"-")
119
+ print()
120
+
121
+ # Save Blender file
122
+ # --------------------------------------------------------------------------
123
+ # The file that will be saved is a Blender project file. This can be opened
124
+ # with the Blender GUI to view the scene.
125
+ pyvale.BlenderTools.save_blender_file(base_dir=base_dir)
126
+
127
+ if __name__ == "__main__":
128
+ main()
@@ -0,0 +1,131 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ import numpy as np
8
+ from scipy.spatial.transform import Rotation
9
+ from pathlib import Path
10
+ import pyvale
11
+ import mooseherder as mh
12
+
13
+ def main() -> None:
14
+ data_path = pyvale.DataSet.render_mechanical_3d_path()
15
+ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
16
+
17
+ disp_comps = ("disp_x","disp_y", "disp_z")
18
+
19
+ # Scale m -> mm
20
+ # NOTE: All lengths are to be specified in mm
21
+ sim_data = pyvale.scale_length_units(sim_data,disp_comps,1000.0)
22
+
23
+ render_mesh = pyvale.create_render_mesh(sim_data,
24
+ ("disp_y","disp_x"),
25
+ sim_spat_dim=3,
26
+ field_disp_keys=disp_comps)
27
+
28
+ # Set the save path
29
+ # --------------------------------------------------------------------------
30
+ # All the files saved will be saved to a subfolder within this specified
31
+ # base directory.
32
+ # This base directory can be specified by:
33
+ base_dir = Path.cwd()
34
+ # If no base directory is specified, it will be set as your home directory
35
+
36
+ # Creating the scene
37
+ # --------------------------------------------------------------------------
38
+ scene = pyvale.BlenderScene()
39
+
40
+ part = scene.add_part(render_mesh, sim_spat_dim=3)
41
+ # Set the part location
42
+ part_location = np.array([0, 0, 0])
43
+ pyvale.BlenderTools.move_blender_obj(part=part, pos_world=part_location)
44
+ # Set part rotation
45
+ part_rotation = Rotation.from_euler("xyz", [0, 0, 0])
46
+ pyvale.BlenderTools.rotate_blender_obj(part=part, rot_world=part_rotation)
47
+
48
+ # Add the stereo camera system
49
+ cam_data_0 = pyvale.CameraData(pixels_num=np.array([1540, 1040]),
50
+ pixels_size=np.array([0.00345, 0.00345]),
51
+ pos_world=np.array([0, 0, 400]),
52
+ rot_world=Rotation.from_euler("xyz", [0, 0, 0]),
53
+ roi_cent_world=(0, 0, 0),
54
+ focal_length=15.0)
55
+ # Set this to "symmetric" to get a symmetric stereo system or set this to
56
+ # "faceon" to get a face-on stereo system
57
+ stereo_setup = "faceon"
58
+ if stereo_setup == "symmetric":
59
+ stereo_system = pyvale.CameraTools.symmetric_stereo_cameras(
60
+ cam_data_0=cam_data_0,
61
+ stereo_angle=15.0)
62
+ if stereo_setup == "faceon":
63
+ stereo_system = pyvale.CameraTools.faceon_stereo_cameras(
64
+ cam_data_0=cam_data_0,
65
+ stereo_angle=15.0)
66
+
67
+ cam0, cam1 = scene.add_stereo_system(stereo_system)
68
+
69
+ # Generate calibration file
70
+ stereo_system.save_calibration(base_dir)
71
+
72
+ # Add the light
73
+ light_data = pyvale.BlenderLightData(type=pyvale.BlenderLightType.POINT,
74
+ pos_world=(0, 0, 400),
75
+ rot_world=Rotation.from_euler("xyz",
76
+ [0, 0, 0]),
77
+ energy=1)
78
+ light = scene.add_light(light_data)
79
+
80
+ # The light can also be moved and rotated:
81
+ light.location = (0, 0, 410)
82
+ light.rotation_euler = (0, 0, 0) # NOTE: The default is an XYZ Euler angle
83
+
84
+ # Apply the speckle pattern
85
+ material_data = pyvale.BlenderMaterialData()
86
+ speckle_path = pyvale.DataSet.dic_pattern_5mpx_path()
87
+ # NOTE: If you wish to use a bigger camera, you will need to generate a
88
+ # bigger speckle pattern generator
89
+
90
+ mm_px_resolution = pyvale.CameraTools.calculate_mm_px_resolution(cam_data_0)
91
+ scene.add_speckle(part=part,
92
+ speckle_path=speckle_path,
93
+ mat_data=material_data,
94
+ mm_px_resolution=mm_px_resolution)
95
+
96
+ # Deform and render images
97
+ # --------------------------------------------------------------------------
98
+ # Set this to True to render image of the deforming part
99
+ render_opts = True
100
+ if render_opts:
101
+ # NOTE: If no save directory is specified, this is where the images will
102
+ # be saved
103
+ render_data = pyvale.RenderData(cam_data=(stereo_system.cam_data_0,
104
+ stereo_system.cam_data_1),
105
+ base_dir=base_dir,
106
+ threads=8)
107
+ # NOTE: The number of threads used to render the images is set within
108
+ # RenderData, it is defaulted to 4 threads
109
+
110
+ scene.render_deformed_images(render_mesh=render_mesh,
111
+ sim_spat_dim=3,
112
+ render_data=render_data,
113
+ part=part,
114
+ stage_image=False)
115
+ # NOTE: If bounce_image is set to True, the image will be saved to disk,
116
+ # converted to an array, deleted and the image array will be returned.
117
+
118
+ print()
119
+ print(80*"-")
120
+ print("Save directory of the image:", (render_data.base_dir / "blenderimages"))
121
+ print(80*"-")
122
+ print()
123
+
124
+ # Save Blender file
125
+ # --------------------------------------------------------------------------
126
+ # The file that will be saved is a Blender project file. This can be opened
127
+ # with the Blender GUI to view the scene.
128
+ pyvale.BlenderTools.save_blender_file(base_dir)
129
+
130
+ if __name__ == "__main__":
131
+ main()