pyvale 2025.5.3__cp311-cp311-macosx_14_0_arm64.whl → 2025.7.0__cp311-cp311-macosx_14_0_arm64.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 (95) hide show
  1. pyvale/.dylibs/libomp.dylib +0 -0
  2. pyvale/.dylibs/libunwind.1.0.dylib +0 -0
  3. pyvale/__init__.py +12 -0
  4. pyvale/blendercalibrationdata.py +3 -1
  5. pyvale/blenderscene.py +7 -5
  6. pyvale/blendertools.py +27 -5
  7. pyvale/camera.py +1 -0
  8. pyvale/cameradata.py +3 -0
  9. pyvale/camerasensor.py +147 -0
  10. pyvale/camerastereo.py +4 -4
  11. pyvale/cameratools.py +23 -61
  12. pyvale/cython/rastercyth.c +1657 -1352
  13. pyvale/cython/rastercyth.cpython-311-darwin.so +0 -0
  14. pyvale/cython/rastercyth.py +71 -26
  15. pyvale/data/plate_hole_def0000.tiff +0 -0
  16. pyvale/data/plate_hole_def0001.tiff +0 -0
  17. pyvale/data/plate_hole_ref0000.tiff +0 -0
  18. pyvale/data/plate_rigid_def0000.tiff +0 -0
  19. pyvale/data/plate_rigid_def0001.tiff +0 -0
  20. pyvale/data/plate_rigid_ref0000.tiff +0 -0
  21. pyvale/dataset.py +96 -6
  22. pyvale/dic/cpp/dicbruteforce.cpp +370 -0
  23. pyvale/dic/cpp/dicfourier.cpp +648 -0
  24. pyvale/dic/cpp/dicinterpolator.cpp +559 -0
  25. pyvale/dic/cpp/dicmain.cpp +215 -0
  26. pyvale/dic/cpp/dicoptimizer.cpp +675 -0
  27. pyvale/dic/cpp/dicrg.cpp +137 -0
  28. pyvale/dic/cpp/dicscanmethod.cpp +677 -0
  29. pyvale/dic/cpp/dicsmooth.cpp +138 -0
  30. pyvale/dic/cpp/dicstrain.cpp +383 -0
  31. pyvale/dic/cpp/dicutil.cpp +563 -0
  32. pyvale/dic2d.py +164 -0
  33. pyvale/dic2dcpp.cpython-311-darwin.so +0 -0
  34. pyvale/dicchecks.py +476 -0
  35. pyvale/dicdataimport.py +247 -0
  36. pyvale/dicregionofinterest.py +887 -0
  37. pyvale/dicresults.py +55 -0
  38. pyvale/dicspecklegenerator.py +238 -0
  39. pyvale/dicspecklequality.py +305 -0
  40. pyvale/dicstrain.py +387 -0
  41. pyvale/dicstrainresults.py +37 -0
  42. pyvale/errorintegrator.py +10 -8
  43. pyvale/examples/basics/ex1_1_basicscalars_therm2d.py +124 -113
  44. pyvale/examples/basics/ex1_2_sensormodel_therm2d.py +124 -132
  45. pyvale/examples/basics/ex1_3_customsens_therm3d.py +199 -195
  46. pyvale/examples/basics/ex1_4_basicerrors_therm3d.py +125 -121
  47. pyvale/examples/basics/ex1_5_fielderrs_therm3d.py +145 -141
  48. pyvale/examples/basics/ex1_6_caliberrs_therm2d.py +96 -101
  49. pyvale/examples/basics/ex1_7_spatavg_therm2d.py +109 -105
  50. pyvale/examples/basics/ex2_1_basicvectors_disp2d.py +92 -91
  51. pyvale/examples/basics/ex2_2_vectorsens_disp2d.py +96 -90
  52. pyvale/examples/basics/ex2_3_sensangle_disp2d.py +88 -89
  53. pyvale/examples/basics/ex2_4_chainfielderrs_disp2d.py +172 -171
  54. pyvale/examples/basics/ex2_5_vectorfields3d_disp3d.py +88 -86
  55. pyvale/examples/basics/ex3_1_basictensors_strain2d.py +90 -90
  56. pyvale/examples/basics/ex3_2_tensorsens2d_strain2d.py +93 -91
  57. pyvale/examples/basics/ex3_3_tensorsens3d_strain3d.py +172 -160
  58. pyvale/examples/basics/ex4_1_expsim2d_thermmech2d.py +154 -148
  59. pyvale/examples/basics/ex4_2_expsim3d_thermmech3d.py +249 -231
  60. pyvale/examples/dic/ex1_region_of_interest.py +98 -0
  61. pyvale/examples/dic/ex2_plate_with_hole.py +149 -0
  62. pyvale/examples/dic/ex3_plate_with_hole_strain.py +93 -0
  63. pyvale/examples/dic/ex4_dic_blender.py +95 -0
  64. pyvale/examples/dic/ex5_dic_challenge.py +102 -0
  65. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +4 -2
  66. pyvale/examples/renderblender/ex1_1_blenderscene.py +152 -105
  67. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +151 -100
  68. pyvale/examples/renderblender/ex2_1_stereoscene.py +183 -116
  69. pyvale/examples/renderblender/ex2_2_stereodeformed.py +185 -112
  70. pyvale/examples/renderblender/ex3_1_blendercalibration.py +164 -109
  71. pyvale/examples/renderrasterisation/ex_rastenp.py +74 -35
  72. pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +6 -13
  73. pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +2 -2
  74. pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +2 -4
  75. pyvale/imagedef2d.py +3 -2
  76. pyvale/imagetools.py +137 -0
  77. pyvale/rastercy.py +34 -4
  78. pyvale/rasternp.py +300 -276
  79. pyvale/rasteropts.py +58 -0
  80. pyvale/renderer.py +47 -0
  81. pyvale/rendermesh.py +52 -62
  82. pyvale/renderscene.py +51 -0
  83. pyvale/sensorarrayfactory.py +2 -2
  84. pyvale/sensortools.py +19 -35
  85. pyvale/simcases/case21.i +1 -1
  86. pyvale/simcases/run_1case.py +8 -0
  87. pyvale/simtools.py +2 -2
  88. pyvale/visualsimplotter.py +180 -0
  89. {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/METADATA +11 -57
  90. {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/RECORD +93 -57
  91. {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/WHEEL +1 -1
  92. pyvale/examples/visualisation/ex1_1_plot_traces.py +0 -102
  93. pyvale/examples/visualisation/ex2_1_animate_sim.py +0 -89
  94. {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/licenses/LICENSE +0 -0
  95. {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/top_level.txt +0 -0
@@ -4,118 +4,165 @@
4
4
  # Copyright (C) 2025 The Computer Aided Validation Team
5
5
  # ==============================================================================
6
6
 
7
+ """
8
+ Blender example: Creating a scene with 2D DIC
9
+ ---------------------------------------------
10
+
11
+ This example takes you through creating a scene and adding all the necessary
12
+ objects required to represent a 2D DIC setup (camera, lighting and sample).
13
+ This example will then show you how to render a single image of this scene.
14
+
15
+ Test case: mechanical analysis of a plate with a hole loaded in tension.
16
+ """
17
+
7
18
  import numpy as np
8
19
  from scipy.spatial.transform import Rotation
9
20
  from pathlib import Path
10
21
  import pyvale
11
22
  import mooseherder as mh
12
23
 
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
+ # %%
25
+ # Here we load in a pre-generated MOOSE finite element simulation dataset that
26
+ # comes packaged with pyvale. The simulation is purely mechanical test case in
27
+ # 3D of a plate with a hole loaded in tension. A mentioned in previous examples,
28
+ # this path can be replaced with your own MOOSE simulation output in exodus
29
+ # format (*.e). `mooseherder` is then used to convert the simulation output
30
+ # into a `SimData` object.
31
+
32
+ data_path = pyvale.DataSet.render_mechanical_3d_path()
33
+ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
34
+
35
+ # %%
36
+
37
+ # This is then scaled to mm, as all lengths in Blender are to be set in mm.
38
+ # The `SimData` object is then converted into a `RenderMeshData` object, as
39
+ # this skins the mesh ready to be imported into Blender.
40
+ # The `disp_comps` are the expected direction of displacement. Since this is a
41
+ # 3D deformation test case, displacement is expected in the x, y and z directions.
42
+ disp_comps = ("disp_x","disp_y", "disp_z")
43
+ sim_data = pyvale.scale_length_units(scale=1000.0,
44
+ sim_data=sim_data,
45
+ disp_comps=disp_comps)
46
+
47
+ render_mesh = pyvale.create_render_mesh(sim_data,
24
48
  ("disp_y","disp_x"),
25
49
  sim_spat_dim=3,
26
50
  field_disp_keys=disp_comps)
27
51
 
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()
52
+ # %%
53
+ # Firstly, a save path must be set.
54
+ # In order to do this a base path must be set. Then all the generated files will
55
+ # be saved to a subfolder within this specified base directory
56
+ # (e.g. blenderimages).
57
+ # If no base directory is specified, it will be set as your home directory.
58
+
59
+ base_dir = Path.cwd()
60
+
61
+ # %%
62
+ # Creating the scene
63
+ # ^^^^^^^^^^^^^^^^^^
64
+ # In order to create a DIC setup in Blender, first a scene must be created.
65
+ # A scene is a holding space for all of your objects (e.g. camera(s), light(s)
66
+ # and sample(s)).
67
+ # A scene is initialised using the `BlenderScene` class. All the subsequent
68
+ # objects and actions necessary are then methods of this class.
69
+
70
+ scene = pyvale.BlenderScene()
71
+
72
+ # %%
73
+ # The next thing that can be added to the scene is a sample.
74
+ # This is done by passing in the `RenderMeshData` object.
75
+ # It should be noted that the mesh will be centred on the origin to allow for
76
+ # the cameras to be centred on the mesh.
77
+ # Once the part is added to the Blender scene, it can be both moved and rotated.
78
+
79
+ part = scene.add_part(render_mesh, sim_spat_dim=3)
80
+ # Set the part location
81
+ part_location = np.array([0, 0, 0])
82
+ pyvale.BlenderTools.move_blender_obj(part=part, pos_world=part_location)
83
+ # Set part rotation
84
+ part_rotation = Rotation.from_euler("xyz", [0, 0, 0], degrees=True)
85
+ pyvale.BlenderTools.rotate_blender_obj(part=part, rot_world=part_rotation)
86
+
87
+ # %%
88
+ # A camera can then be added to the scene.
89
+ # To initialise a camera, the camera parameters must be specified using the
90
+ # `CameraData` dataclass. Note that all lengths / distances inputted are in mm.
91
+ # This camera can then be added to the Blender scene.
92
+ # The camera can also be moved and rotated.
93
+
94
+ cam_data = pyvale.CameraData(pixels_num=np.array([1540, 1040]),
95
+ pixels_size=np.array([0.00345, 0.00345]),
96
+ pos_world=(0, 0, 400),
97
+ rot_world=Rotation.from_euler("xyz", [0, 0, 0]),
98
+ roi_cent_world=(0, 0, 0),
99
+ focal_length=15.0)
100
+ camera = scene.add_camera(cam_data)
101
+ camera.location = (0, 0, 410)
102
+ camera.rotation_euler = (0, 0, 0) # NOTE: The default is an XYZ Euler angle
103
+
104
+ # %%
105
+ # A light can the be added to the scene.
106
+ # Blender offers different light types: Point, Sun, Spot and Area.
107
+ # The light can also be moved and rotated like the camera.
108
+
109
+ light_data = pyvale.BlenderLightData(type=pyvale.BlenderLightType.POINT,
110
+ pos_world=(0, 0, 400),
111
+ rot_world=Rotation.from_euler("xyz",
112
+ [0, 0, 0]),
113
+ energy=1)
114
+ light = scene.add_light(light_data)
115
+ light.location = (0, 0, 410)
116
+ light.rotation_euler = (0, 0, 0)
117
+
118
+ # %%
119
+ # A speckle pattern can then be applied to the sample.
120
+ # Firstly, the material properties of the sample must be specified, but these
121
+ # will all be defaulted if no inputs are provided.
122
+ #The speckle pattern can then be specified by providing a path to an image file
123
+ # with the pattern.
124
+ # The mm/px resolution of the camera must also be specified in order to
125
+ # correctly scale the speckle pattern.
126
+ # It should be noted that for a bigger camera or sample you may need to generate
127
+ # a larger speckle pattern.
128
+
129
+ material_data = pyvale.BlenderMaterialData()
130
+ speckle_path = pyvale.DataSet.dic_pattern_5mpx_path()
131
+
132
+ mm_px_resolution = pyvale.CameraTools.calculate_mm_px_resolution(cam_data)
133
+ scene.add_speckle(part=part,
134
+ speckle_path=speckle_path,
135
+ mat_data=material_data,
136
+ mm_px_resolution=mm_px_resolution)
137
+
138
+ # %%
139
+ # Rendering an image
140
+ # ^^^^^^^^^^^^^^^^^^
141
+ # Once all the objects have been added to the scene, an image can be rendered.
142
+ # Firstly, all the rendering parameters must be set, including parameters such as
143
+ # the number of threads to use.
144
+
145
+ render_data = pyvale.RenderData(cam_data=cam_data,
146
+ base_dir=base_dir,
147
+ threads=8)
148
+
149
+ # %%
150
+ # A single image of the scene can then be rendered.
151
+ # If `stage_image` is set to True, the image will be saved to disk, converted to
152
+ # an array, deleted and the image array will be returned. This is due to the
153
+ # fact that an image cannot be saved directly as an array through Blender.
154
+
155
+ scene.render_single_image(stage_image=False,
156
+ render_data=render_data)
157
+
158
+ # %%
159
+ # The rendered image will be saved to this filepath:
160
+
161
+ print("Save directory of the image:", (render_data.base_dir / "blenderimages"))
162
+
163
+ # %%
164
+ # There is also the option to save the scene as a Blender project file.
165
+ # This file can be opened with the Blender GUI to view the scene.
166
+
167
+ pyvale.BlenderTools.save_blender_file(base_dir)
168
+
@@ -4,116 +4,167 @@
4
4
  # Copyright (C) 2025 The Computer Aided Validation Team
5
5
  # ==============================================================================
6
6
 
7
+ """
8
+ Blender example: Deforming a sample with 2D DIC
9
+ ===============================================
10
+
11
+ This example follows a similar workflow to the previous Blender example.
12
+ In this example, defomation is applied to sample, and images are rendered at
13
+ each timestep.
14
+
15
+ Test case: mechanical analysis of a plate with a hole loaded in tension.
16
+ """
17
+
7
18
  import numpy as np
8
19
  from scipy.spatial.transform import Rotation
9
20
  from pathlib import Path
10
21
  import pyvale
11
22
  import mooseherder as mh
12
23
 
13
- def main() -> None:
14
- data_path = pyvale.DataSet.render_mechanical_3d_path()
15
- sim_data = mh.ExodusReader(data_path).read_all_sim_data()
24
+ # %%
25
+ # The simulation results are loaded in here in the same way as the previous
26
+ # example. As mentioned this `data_path` can be replaced with your own MOOSE
27
+ # simulation output in exodus format (*.e).
28
+
29
+ data_path = pyvale.DataSet.render_mechanical_3d_path()
30
+ sim_data = mh.ExodusReader(data_path).read_all_sim_data()
16
31
 
17
- disp_comps = ("disp_x","disp_y", "disp_z")
32
+ # %%
33
+ # This is then scaled to mm, as all lengths in Blender are to be set in mm.
34
+ # The `SimData` object is then converted into a `RenderMeshData` object, as
35
+ # this skins the mesh ready to be imported into Blender.
36
+ # The `disp_comps` are the expected direction of displacement. Since this is a
37
+ # 3D deformation test case, displacement is expected in the x, y and z directions.
18
38
 
19
- # Scale m -> mm
20
- sim_data = pyvale.scale_length_units(sim_data,disp_comps,1000.0)
39
+ disp_comps = ("disp_x","disp_y", "disp_z")
40
+ sim_data = pyvale.scale_length_units(scale=1000.0,
41
+ sim_data=sim_data,
42
+ disp_comps=disp_comps)
21
43
 
22
- render_mesh = pyvale.create_render_mesh(sim_data,
44
+ render_mesh = pyvale.create_render_mesh(sim_data,
23
45
  ("disp_y","disp_x"),
24
46
  sim_spat_dim=3,
25
47
  field_disp_keys=disp_comps)
26
48
 
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()
49
+ # %%
50
+ # Firstly, a save path must be set.
51
+ # In order to do this a base path must be set. Then all the generated files will
52
+ # be saved to a subfolder within this specified base directory
53
+ # (e.g. blenderimages).
54
+ # If no base directory is specified, it will be set as your home directory.
55
+
56
+ base_dir = Path.cwd()
57
+
58
+ # %%
59
+ # Creating the scene
60
+ # ^^^^^^^^^^^^^^^^^^
61
+ # In order to create a DIC setup in Blender, first a scene must be created.
62
+ # A scene is initialised using the `BlenderScene` class. All the subsequent
63
+ # objects and actions necessary are then methods of this class.
64
+
65
+ scene = pyvale.BlenderScene()
66
+
67
+ # %%
68
+ # The next thing that can be added to the scene is a sample.
69
+ # This is done by passing in the `RenderMeshData` object.
70
+ # It should be noted that the mesh will be centred on the origin to allow for
71
+ # the cameras to be centred on the mesh.
72
+ # Once the part is added to the Blender scene, it can be both moved and rotated.
73
+
74
+
75
+ part = scene.add_part(render_mesh, sim_spat_dim=3)
76
+ # Set the part location
77
+ part_location = np.array([0, 0, 0])
78
+ pyvale.BlenderTools.move_blender_obj(part=part, pos_world=part_location)
79
+ part_rotation = Rotation.from_euler("xyz", [0, 0, 0], degrees=True)
80
+ pyvale.BlenderTools.rotate_blender_obj(part=part, rot_world=part_rotation)
81
+
82
+ # %%
83
+ # A camera can then be added to the scene.
84
+ # To initialise a camera, the camera parameters must be specified using the
85
+ # `CameraData` dataclass. Note that all lengths / distances inputted are in mm.
86
+ # This camera can then be added to the Blender scene.
87
+ # The camera can also be moved and rotated.
88
+
89
+ cam_data = pyvale.CameraData(pixels_num=np.array([1540, 1040]),
90
+ pixels_size=np.array([0.00345, 0.00345]),
91
+ pos_world=(0, 0, 400),
92
+ rot_world=Rotation.from_euler("xyz", [0, 0, 0]),
93
+ roi_cent_world=(0, 0, 0),
94
+ focal_length=15.0)
95
+ camera = scene.add_camera(cam_data)
96
+ camera.location = (0, 0, 410)
97
+ camera.rotation_euler = (0, 0, 0) # NOTE: The default is an XYZ Euler angle
98
+
99
+ # %%
100
+ # A light can the be added to the scene.
101
+ # Blender offers different light types: Point, Sun, Spot and Area.
102
+ # The light can also be moved and rotated like the camera.
103
+
104
+ light_data = pyvale.BlenderLightData(type=pyvale.BlenderLightType.POINT,
105
+ pos_world=(0, 0, 400),
106
+ rot_world=Rotation.from_euler("xyz",
107
+ [0, 0, 0]),
108
+ energy=1)
109
+ light = scene.add_light(light_data)
110
+ light.location = (0, 0, 410)
111
+ light.rotation_euler = (0, 0, 0)
112
+
113
+ # %%
114
+ # A speckle pattern can then be applied to the sample.
115
+ # Firstly, the material properties of the sample must be specified, but these
116
+ # will all be defaulted if no inputs are provided.
117
+ #The speckle pattern can then be specified by providing a path to an image file
118
+ # with the pattern.
119
+ # The mm/px resolution of the camera must also be specified in order to
120
+ # correctly scale the speckle pattern.
121
+ # It should be noted that for a bigger camera or sample you may need to generate
122
+ # a larger speckle pattern.
123
+
124
+ material_data = pyvale.BlenderMaterialData()
125
+ speckle_path = pyvale.DataSet.dic_pattern_5mpx_path()
126
+ mm_px_resolution = pyvale.CameraTools.calculate_mm_px_resolution(cam_data)
127
+ scene.add_speckle(part=part,
128
+ speckle_path=speckle_path,
129
+ mat_data=material_data,
130
+ mm_px_resolution=mm_px_resolution)
131
+
132
+ # %%
133
+ # Deforming the sample and rendering images
134
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
135
+ # Once all the objects have been added to the scene, the sample can be deformed,
136
+ # and images can be rendered.
137
+ # Firstly, all the rendering parameters must be set, including parameters such as
138
+ # the number of threads to use.
139
+
140
+ render_data = pyvale.RenderData(cam_data=cam_data,
141
+ base_dir=base_dir,
142
+ threads=8)
143
+
144
+ # %%
145
+ # A series of deformed images can then be rendered.
146
+ # This is done by passing in rendering parameters, as well as the
147
+ # `RenderMeshData` object, the part(sample) and the spatial dimension of the
148
+ # simulation.
149
+ # This will automatically deform the sample, and render subsequent images at
150
+ # each deformation timestep.
151
+ # If `stage_image` is set to True, the image will be saved to disk, converted to
152
+ # an array, deleted and the image array will be returned. This is due to the
153
+ # fact that an image cannot be saved directly as an array through Blender.
154
+
155
+ scene.render_deformed_images(render_mesh,
156
+ sim_spat_dim=3,
157
+ render_data=render_data,
158
+ part=part,
159
+ stage_image=False)
160
+
161
+ # %%
162
+ # The rendered image will be saved to this filepath:
163
+
164
+ print("Save directory of the image:", (render_data.base_dir / "blenderimages"))
165
+
166
+ # %%
167
+ # There is also the option to save the scene as a Blender project file.
168
+ # This file can be opened with the Blender GUI to view the scene.
169
+
170
+ pyvale.BlenderTools.save_blender_file(base_dir)