pyvale 2025.5.3__cp311-cp311-win_amd64.whl → 2025.7.1__cp311-cp311-win_amd64.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/__init__.py +12 -0
  2. pyvale/blendercalibrationdata.py +3 -1
  3. pyvale/blenderscene.py +7 -5
  4. pyvale/blendertools.py +27 -5
  5. pyvale/camera.py +1 -0
  6. pyvale/cameradata.py +3 -0
  7. pyvale/camerasensor.py +147 -0
  8. pyvale/camerastereo.py +4 -4
  9. pyvale/cameratools.py +23 -61
  10. pyvale/cython/rastercyth.c +1657 -1352
  11. pyvale/cython/rastercyth.cp311-win_amd64.pyd +0 -0
  12. pyvale/cython/rastercyth.py +71 -26
  13. pyvale/data/DIC_Challenge_Star_Noise_Def.tiff +0 -0
  14. pyvale/data/DIC_Challenge_Star_Noise_Ref.tiff +0 -0
  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.cp311-win_amd64.pyd +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.1.dist-info}/METADATA +11 -57
  90. {pyvale-2025.5.3.dist-info → pyvale-2025.7.1.dist-info}/RECORD +93 -56
  91. {pyvale-2025.5.3.dist-info → pyvale-2025.7.1.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.1.dist-info}/licenses/LICENSE +0 -0
  95. {pyvale-2025.5.3.dist-info → pyvale-2025.7.1.dist-info}/top_level.txt +0 -0
@@ -4,117 +4,172 @@
4
4
  # Copyright (C) 2025 The Computer Aided Validation Team
5
5
  # ==============================================================================
6
6
 
7
+ """
8
+ Blender example: Rendering calibration images
9
+ ---------------------------------------------
10
+
11
+ This example takes you through how to render calibration images for a given DIC
12
+ setup.
13
+ """
7
14
  import numpy as np
8
15
  from scipy.spatial.transform import Rotation
9
16
  from pathlib import Path
10
17
  import pyvale
11
18
 
12
- def main() -> None:
13
- #NOTE: All lengths are to be specified in mm
14
-
15
- # Set the save path
16
- # --------------------------------------------------------------------------
17
- # All the files saved will be saved to a subfolder within this specified
18
- # base directory.
19
- # This base directory can be specified by:
20
- base_dir = Path("./")
21
- # If no base directory is specified, it will be set as your home directory
22
-
23
- # Creating the scene
24
- # --------------------------------------------------------------------------
25
- scene = pyvale.BlenderScene()
26
-
27
- # Add the calibration target
28
- # A rectangular calibration target of the specified size is added to the scene
29
- target = scene.add_cal_target(target_size=np.array([150, 100, 10]))
30
-
31
- # Add the camera
32
- cam_data_0 = pyvale.CameraData(pixels_num=np.array([1540, 1040]),
33
- pixels_size=np.array([0.00345, 0.00345]),
34
- pos_world=np.array([0, 0, 400]),
35
- rot_world=Rotation.from_euler("xyz", [0, 0, 0]),
36
- roi_cent_world=(0, 0, 0),
37
- focal_length=15.0)
38
- # Set this to "symmetric" to get a symmetric stereo system or set this to
39
- # "faceon" to get a face-on stereo system
40
- stereo_setup = "faceon"
41
- if stereo_setup == "symmetric":
42
- stereo_system = pyvale.CameraTools.symmetric_stereo_cameras(
43
- cam_data_0=cam_data_0,
44
- stereo_angle=15.0)
45
- if stereo_setup == "faceon":
46
- stereo_system = pyvale.CameraTools.faceon_stereo_cameras(
47
- cam_data_0=cam_data_0,
48
- stereo_angle=15.0)
49
-
50
- scene.add_stereo_system(stereo_system)
51
-
52
- # Generate calibration file
53
- stereo_system.save_calibration(base_dir)
54
-
55
- # Add the light
56
- light_data = pyvale.BlenderLightData(type=pyvale.BlenderLightType.POINT,
57
- pos_world=(0, 0, 200),
58
- rot_world=Rotation.from_euler("xyz",
59
- [0, 0, 0]),
60
- energy=1)
61
- light = scene.add_light(light_data)
62
- # The light can be moved and rotated:
63
- light.location = (0, 0, 210)
64
- light.rotation_euler = (0, 0, 0) # NOTE: The default is an XYZ Euler angle
65
-
66
- # Apply the calibration target pattern
67
- material_data = pyvale.BlenderMaterialData()
68
- speckle_path = Path.cwd() / "src/pyvale/data/cal_target.tiff"
69
- mm_px_resolution = pyvale.CameraTools.calculate_mm_px_resolution(cam_data_0)
70
- scene.add_speckle(part=target,
71
- speckle_path=speckle_path,
72
- mat_data=material_data,
73
- mm_px_resolution=mm_px_resolution,
74
- cal=True)
75
- # NOTE: The `cal` flag has to be set to True in order to scale the
76
- # calibration target pattern correctly
77
-
78
- # Rendering calibration images
79
- # --------------------------------------------------------------------------
80
- save_dir = Path.cwd() / "blenderimages"
81
- save_name = "cal"
82
- render_data = pyvale.RenderData(cam_data=(stereo_system.cam_data_0,
83
- stereo_system.cam_data_1),
84
- base_dir=base_dir)
85
- # NOTE: The number of threads used to render the images is set within
86
- # RenderData, it is defaulted to 4 threads
87
-
88
- # The desired limits for the calibration target movement are to be set within
89
- # the CalibrationData dataclass
90
- calibration_data = pyvale.CalibrationData(angle_lims=(-10, 10),
91
- angle_step=5,
92
- plunge_lims=(-5, 5),
93
- plunge_step=5)
94
-
95
- # The number of calibration images that will be rendered can be calculated
96
- number_calibration_images = pyvale.BlenderTools.number_calibration_images(calibration_data)
97
- print()
98
- print(80*"-")
99
- print("Number of calibration images to be rendered:", number_calibration_images)
100
- print(80*"-")
101
-
102
- # The calibration images can then be rendered
103
- pyvale.BlenderTools.render_calibration_images(render_data,
104
- calibration_data,
105
- target)
106
-
107
- print()
108
- print(80*"-")
109
- print("Save directory of the images:", (render_data.base_dir / "calimages"))
110
- print(80*"-")
111
- print()
112
-
113
- # Save Blender file
114
- # --------------------------------------------------------------------------
115
- # The file that will be saved is a Blender project file. This can be opened
116
- # with the Blender GUI to view the scene.
117
- pyvale.BlenderTools.save_blender_file(base_dir)
118
-
119
- if __name__ == "__main__":
120
- main()
19
+ # %%
20
+ # Firstly, a save path must be set.
21
+ # In order to do this a base path must be set. Then all the generated files will
22
+ # be saved to a subfolder within this specified base directory
23
+ # (e.g. blenderimages).
24
+ # If no base directory is specified, it will be set as your home directory.
25
+
26
+ base_dir = Path.cwd()
27
+
28
+ # %%
29
+ # Creating the scene
30
+ # ^^^^^^^^^^^^^^^^^^
31
+ # In order to create a DIC setup in Blender, first a scene must be created.
32
+ # A scene is initialised using the `BlenderScene` class. All the subsequent
33
+ # objects and actions necessary are then methods of this class.
34
+ scene = pyvale.BlenderScene()
35
+
36
+ # %%
37
+ # The next thing to add to the scene is the calibration target.
38
+ # This is done by specifing the size of calibration target to add to the scene
39
+ # by passing in an array of (width, height, depth).
40
+ # The calibration target being simulated here is 12 x 9 with 10 mm spacing.
41
+
42
+ target = scene.add_cal_target(target_size=np.array([150, 100, 10]))
43
+
44
+ # %%
45
+ # The cameras can then be initialised. A stereo camera system is defined by a
46
+ # `CameraStereo` object, which contains the intrinsic parameters of both cameras
47
+ # as well as the extrinsic parameters between them.
48
+ # There are two ways to initialise a `CameraStereo` object.
49
+ # One way is to specify the camera parameters separately for each camera, create
50
+ # a `CameraStereo` object, and then add the stereo system using the
51
+ # `add_stereo_system` method.
52
+ # The other method is to use a convenience function, as shown below.
53
+ # This requires you to first initialise one camera. Then you can choose between
54
+ # either a face-on or symmetric stereo system. Then, either of the
55
+ # `symmetric_stereo_cameras` or `faceon_stereo_cameras` functions can be used to
56
+ # initialise a `CameraStereo` object. The only input required to these functions
57
+ # are the camera parameters for the first camera, and the desired stereo angle
58
+ # between the two. The cameras can then be added to the Blender scene using the
59
+ # `add_stereo_system` method.
60
+ cam_data_0 = pyvale.CameraData(pixels_num=np.array([1540, 1040]),
61
+ pixels_size=np.array([0.00345, 0.00345]),
62
+ pos_world=np.array([0, 0, 400]),
63
+ rot_world=Rotation.from_euler("xyz", [0, 0, 0]),
64
+ roi_cent_world=(0, 0, 0),
65
+ focal_length=15.0)
66
+ # Set this to "symmetric" to get a symmetric stereo system or set this to
67
+ # "faceon" to get a face-on stereo system
68
+ stereo_setup = "faceon"
69
+ if stereo_setup == "symmetric":
70
+ stereo_system = pyvale.CameraTools.symmetric_stereo_cameras(
71
+ cam_data_0=cam_data_0,
72
+ stereo_angle=15.0)
73
+ if stereo_setup == "faceon":
74
+ stereo_system = pyvale.CameraTools.faceon_stereo_cameras(
75
+ cam_data_0=cam_data_0,
76
+ stereo_angle=15.0)
77
+ scene.add_stereo_system(stereo_system)
78
+
79
+ # %%
80
+ # Since this scene contains a stereo DIC system, a calibration file will be
81
+ # required to run the images through a DIC engine.
82
+ # A calibration file can be generated directly from the `CameraStereo` object.
83
+ # The calibration file will be saved in `YAML` format. However, if you wish to
84
+ # use MatchID to process the images, `save_calibration_mid` can be used instead
85
+ # to save the calibration in a format readable by MatchID.
86
+ # The calibration file will be saved to a sub-directory of the base directory
87
+ # called "calibration".
88
+ # This calibration file with "perfect" parameters can be used as a comparitive
89
+ # benchmark to the calibration gained from running the calibration files through
90
+ # a DIC engine.
91
+ stereo_system.save_calibration(base_dir)
92
+
93
+ # %%
94
+ # A light can the be added to the scene.
95
+ # Blender offers different light types: Point, Sun, Spot and Area.
96
+ # The light can also be moved and rotated like the camera.
97
+
98
+ light_data = pyvale.BlenderLightData(type=pyvale.BlenderLightType.POINT,
99
+ pos_world=(0, 0, 200),
100
+ rot_world=Rotation.from_euler("xyz",
101
+ [0, 0, 0]),
102
+ energy=1)
103
+ light = scene.add_light(light_data)
104
+ light.location = (0, 0, 210)
105
+ light.rotation_euler = (0, 0, 0) # NOTE: The default is an XYZ Euler angle
106
+
107
+ # %%
108
+ # The calibration target pattern can then be added to the calibration target
109
+ # object.
110
+ # This is added in the same way that a speckle pattern is added to a sample.
111
+ # However, it is important to set the `cal` flag to True, as this means that the
112
+ # calibration target pattern will not be scaled in the same way as a speckle
113
+ # pattern.
114
+
115
+ material_data = pyvale.BlenderMaterialData()
116
+ speckle_path = Path.cwd() / "src/pyvale/data/cal_target.tiff"
117
+ mm_px_resolution = pyvale.CameraTools.calculate_mm_px_resolution(cam_data_0)
118
+ scene.add_speckle(part=target,
119
+ speckle_path=speckle_path,
120
+ mat_data=material_data,
121
+ mm_px_resolution=mm_px_resolution,
122
+ cal=True)
123
+
124
+ # %%
125
+ # Rendering a set of images
126
+ # ^^^^^^^^^^^^^^^^^^^^^^^^^
127
+ # Once all the objects have been added to the scene, a set of images can be
128
+ # rendered.Firstly, all the rendering parameters must be set, including
129
+ # parameters such as the number of threads to use.
130
+
131
+ render_data = pyvale.RenderData(cam_data=(stereo_system.cam_data_0,
132
+ stereo_system.cam_data_1),
133
+ base_dir=base_dir)
134
+
135
+ # %%
136
+ # The parameters for the calibration target's movement can then be set. This is
137
+ # done by setting the minimum and maximum angle and plunge limits, as well as
138
+ # the step value that they should be increased by. The x and y limit of the
139
+ # calibration target's movement (from the origin) can also be set if you wish to
140
+ # perform a calibration for a constrained optical setup. If these limits are not
141
+ # passed in they will be initialised from the FOV to cover the whole FOV of the
142
+ # cameras.
143
+
144
+ calibration_data = pyvale.CalibrationData(angle_lims=(-10, 10),
145
+ angle_step=5,
146
+ plunge_lims=(-5, 5),
147
+ plunge_step=5)
148
+
149
+ # %%
150
+ # It is then possible to check the number of calibration images that will be
151
+ # rendered before rendering them. The only input that is needed is the
152
+ # `calibration_data` specified above.
153
+
154
+ number_calibration_images = pyvale.BlenderTools.number_calibration_images(calibration_data)
155
+ print("Number of calibration images to be rendered:", number_calibration_images)
156
+
157
+ # %%
158
+ # The calibration images can then be rendered. This function will move the
159
+ # calibration target according to movement limits set above, and will also move
160
+ # the target rigidly across the FOV of the camera, in order to characterise the
161
+ # entire FOV of the cameras.
162
+ pyvale.BlenderTools.render_calibration_images(render_data,
163
+ calibration_data,
164
+ target)
165
+
166
+ # %%
167
+ # The rendered images will be saved to this filepath:
168
+
169
+ print("Save directory of the images:", (render_data.base_dir / "calimages"))
170
+
171
+ # %%
172
+ # There is also the option to save the scene as a Blender project file.
173
+ # This file can be opened with the Blender GUI to view the scene.
174
+
175
+ pyvale.BlenderTools.save_blender_file(base_dir)
@@ -5,6 +5,7 @@
5
5
  # ==============================================================================
6
6
 
7
7
  from pathlib import Path
8
+ import copy
8
9
  import time
9
10
  import numpy as np
10
11
  from scipy.spatial.transform import Rotation
@@ -27,21 +28,20 @@ import pyvale as pyv
27
28
 
28
29
 
29
30
  def main() -> None:
30
- """pyvale example: rasterisation field renderer
31
+ """Basics rasterisation field renderer
31
32
  ----------------------------------------------------------------------------
32
- - TODO
33
33
  """
34
34
  # This a path to an exodus *.e output file from MOOSE, this can be
35
35
  # replaced with a path to your own simulation file
36
- #sim_path = Path.home()/"pyvale"/"src"/"pyvale"/"simcases"/"case21_out.e"
37
- sim_path = pyv.DataSet.render_mechanical_3d_path()
36
+ sim_path = Path.home()/"pyvale"/"src"/"pyvale"/"simcases"/"case21_out.e"
37
+ #sim_path = pyv.DataSet.render_mechanical_3d_path()
38
38
 
39
39
  disp_comps = ("disp_x","disp_y","disp_z")
40
40
 
41
41
  sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
42
42
 
43
43
  # Scale m -> mm
44
- sim_data = pyv.scale_length_units(sim_data,disp_comps,1000.0)
44
+ sim_data = pyv.scale_length_units(1000.0,sim_data,disp_comps)
45
45
 
46
46
  # Extracts the surface mesh from a full 3d simulation for rendering
47
47
  render_mesh = pyv.create_render_mesh(sim_data,
@@ -49,6 +49,18 @@ def main() -> None:
49
49
  sim_spat_dim=3,
50
50
  field_disp_keys=disp_comps)
51
51
 
52
+ #===========================================================================
53
+ # render_mesh.fields_render = render_mesh.fields_render[:,-2:-1,:]
54
+ # render_mesh.fields_disp = render_mesh.fields_disp[:,-2:-1,:]
55
+ # render_mesh.fields_disp = None
56
+ #===========================================================================
57
+
58
+ meshes = [render_mesh,copy.deepcopy(render_mesh)]
59
+ meshes[1].set_pos(np.array((0.0,12.5,0.0)))
60
+ meshes[1].set_rot(Rotation.from_euler("zyx",(0.0, 0.0, 0.0),degrees=True))
61
+ meshes[1].fields_disp = None
62
+ coords_all = pyv.get_all_coords_world(meshes)
63
+
52
64
  print()
53
65
  print(80*"-")
54
66
  print("MESH DATA:")
@@ -66,16 +78,15 @@ def main() -> None:
66
78
  print(80*"-")
67
79
  print()
68
80
 
69
-
70
81
  pixel_num = np.array((960,1280))
71
82
  pixel_size = np.array((5.3e-3,5.3e-3))
72
83
  focal_leng: float = 50
73
- cam_rot = Rotation.from_euler("zyx",(0.0,-30.0,-10.0),degrees=True)
74
- fov_scale_factor: float = 1.1
84
+ cam_rot = Rotation.from_euler("zyx",(0.0, 0.0, -30.0),degrees=True)
85
+ fov_scale_factor: float = 1.0
75
86
 
76
87
  (roi_pos_world,
77
- cam_pos_world) = pyv.CameraTools.pos_fill_frame_from_rotation(
78
- coords_world=render_mesh.coords,
88
+ cam_pos_world) = pyv.CameraTools.pos_fill_frame(
89
+ coords_world=coords_all,
79
90
  pixel_num=pixel_num,
80
91
  pixel_size=pixel_size,
81
92
  focal_leng=focal_leng,
@@ -103,51 +114,79 @@ def main() -> None:
103
114
  print("World to camera matrix:")
104
115
  print(cam_data.world_to_cam_mat)
105
116
  print(80*"-")
106
- print()
117
+
118
+ scene = pyv.RenderScene([cam_data,cam_data],meshes)
119
+
120
+ frames_per_camera = (scene.meshes[0].fields_render.shape[1]
121
+ *scene.meshes[0].fields_render.shape[2])
122
+ frames_total = frames_per_camera*len(scene.cameras)
107
123
 
108
124
  print(80*"-")
109
- total_frames = render_mesh.fields_render.shape[1]*render_mesh.fields_render.shape[2]
110
- print(f"Time steps to render: {render_mesh.fields_render.shape[1]}")
111
- print(f"Fields to render: {render_mesh.fields_render.shape[2]}")
112
- print(f"Total frames to render: {total_frames}")
125
+ print("RENDER SCENE:")
126
+ print(f"Cameras #: {len(scene.cameras)}")
127
+ print(f"Meshes #: {len(scene.meshes)}")
128
+ print()
129
+ print(f"Time steps: {scene.meshes[0].fields_render.shape[1]}")
130
+ print(f"Field #: {scene.meshes[0].fields_render.shape[2]}")
131
+ print()
132
+ print(f"Frames per camera: {frames_per_camera}")
133
+ print(f"Frames total: {frames_total}")
113
134
  print(80*"-")
114
135
 
136
+
137
+ #===========================================================================
115
138
  print()
116
139
  print(80*"=")
117
- print("RASTER LOOP START")
140
+ print("IN MEM: Raster Loop start")
118
141
 
119
- #save_path = Path.cwd()/"example_output"
120
- save_path = None
121
- static_mesh = False
142
+ raster_opts = pyv.RasterOpts(parallel=8)
143
+ renderer = pyv.RasterNumpy(raster_opts)
122
144
 
123
145
  time_start_loop = time.perf_counter()
124
- if static_mesh:
125
- images = pyv.RasterNP.raster_static_mesh(
126
- cam_data,render_mesh,save_path,threads_num=8
127
- )
128
- else:
129
- time_start_loop = time.perf_counter()
130
- images = pyv.RasterNP.raster_deformed_mesh(
131
- cam_data,render_mesh,save_path,parallel=8
132
- )
146
+
147
+ images = renderer.render_all(scene)
133
148
 
134
149
  time_end_loop = time.perf_counter()
135
- render_time = time_end_loop - time_start_loop
150
+ time_inmem = time_end_loop - time_start_loop
151
+
152
+ print(f"{images[0].shape=}")
153
+ print(f"{images[1].shape=}")
154
+ print("IN MEM: Raster Loop End")
155
+ print(80*"=")
136
156
 
137
157
 
138
- print("RASTER LOOP END")
139
158
  print(80*"=")
159
+ print("TO DISK: Raster Loop start")
160
+ save_path = Path.cwd()/"pyvale-output"
161
+ if not save_path.is_dir():
162
+ save_path.mkdir(parents=True, exist_ok=True)
163
+
164
+ time_start_loop = time.perf_counter()
165
+
166
+ renderer.render_all_to_disk(scene,save_path)
167
+
168
+ time_end_loop = time.perf_counter()
169
+ time_to_disk = time_end_loop - time_start_loop
170
+
171
+ print("TO DISK: Raster Loop End")
172
+ print(80*"=")
173
+
174
+
140
175
  print("PERFORMANCE")
141
- print(f"Total frames = {total_frames}")
142
- print(f"Total render time = {render_time:.4f} seconds")
143
- print(f"Time per frame = {(render_time/total_frames):.4f} seconds")
176
+ print(f"Total frames = {frames_total}")
177
+ print(f"IN MEM: Total render time = {time_inmem:.4f} s")
178
+ print(f"IN MEM: Time per frame = {(time_inmem/frames_total):.4f} s")
179
+ print(f"TO DISK: Total render time = {time_to_disk:.4f} s")
180
+ print(f"TO DISK: Time per frame = {(time_to_disk/frames_total):.4f} s")
144
181
  print(80*"=")
145
182
 
183
+
146
184
  plot_on = True
147
185
  if plot_on:
148
- (fig,ax) = pyv.plot_field_image(images[:,:,-1,0],
186
+ (fig,ax) = pyv.plot_field_image(images[1][:,:,-1,0],
149
187
  title_str="Disp. y, [mm]")
150
- plt.show()
188
+
189
+ plt.show()
151
190
 
152
191
  if __name__ == "__main__":
153
192
  main()
@@ -13,10 +13,6 @@ import pyvale as pyv
13
13
  import imagebenchmarks as ib
14
14
 
15
15
  def main() -> None:
16
- """pyvale example: rasterisation field renderer
17
- ----------------------------------------------------------------------------
18
- - TODO
19
- """
20
16
  print()
21
17
  print(80*"=")
22
18
  print("RASTER CYTHON FILE (should be *.so on Linux):")
@@ -24,23 +20,20 @@ def main() -> None:
24
20
  print(80*"=")
25
21
  print()
26
22
 
27
- return
28
-
29
- benchmark = True
23
+ benchmark = False
30
24
  if not benchmark:
31
-
32
25
  # This a path to an exodus *.e output file from MOOSE, this can be
33
26
  # replaced with a path to your own simulation file
34
27
  #sim_path = Path.home()/"pyvale"/"src"/"pyvale"/"simcases"/"case26_out.e"
35
28
 
36
29
  sim_path = pyv.DataSet.render_simple_block_path()
37
- sim_path = pyv.DataSet.render_mechanical_3d_path()
30
+ #sim_path = pyv.DataSet.render_mechanical_3d_path()
38
31
  sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
39
32
 
40
33
  disp_comps = ("disp_x","disp_y","disp_z")
41
34
 
42
35
  # Scale m -> mm
43
- sim_data = pyv.scale_length_units(sim_data,disp_comps,1000.0)
36
+ sim_data = pyv.scale_length_units(1000.0,sim_data,disp_comps)
44
37
 
45
38
  print()
46
39
  print(f"{np.max(np.abs(sim_data.node_vars['disp_x']))=}")
@@ -65,7 +58,7 @@ def main() -> None:
65
58
  fov_scale_factor: float = 1.1
66
59
 
67
60
  (roi_pos_world,
68
- cam_pos_world) = pyv.CameraTools.pos_fill_frame_from_rotation(
61
+ cam_pos_world) = pyv.CameraTools.pos_fill_frame(
69
62
  coords_world=render_mesh.coords,
70
63
  pixel_num=pixel_num,
71
64
  pixel_size=pixel_size,
@@ -151,7 +144,7 @@ def main() -> None:
151
144
 
152
145
  (image_buffer,
153
146
  depth_buffer,
154
- elems_in_image) = pyv.rastercyth.raster_frame(
147
+ elems_in_image) = pyv.rastercyth.raster_static_frame(
155
148
  render_mesh.coords,
156
149
  render_mesh.connectivity,
157
150
  fields_render,
@@ -171,7 +164,7 @@ def main() -> None:
171
164
 
172
165
  #===========================================================================
173
166
  # PLOTTING
174
- plot_on = True
167
+ plot_on = False
175
168
  plot_field = 0
176
169
 
177
170
  # depth_to_plot = np.copy(np.asarray(depth_buffer[:,:,plot_frame]))
@@ -28,7 +28,7 @@ def main() -> None:
28
28
  disp_comps = ("disp_x","disp_y","disp_z")
29
29
 
30
30
  # Scale m -> mm
31
- sim_data = pyv.scale_length_units(sim_data,disp_comps,1000.0)
31
+ sim_data = pyv.scale_length_units(1000.0,sim_data,disp_comps)
32
32
 
33
33
  print()
34
34
  print(f"{np.max(np.abs(sim_data.node_vars['disp_x']))=}")
@@ -66,7 +66,7 @@ def main() -> None:
66
66
  fov_scale_factor: float = 1.1
67
67
 
68
68
  (roi_pos_world,
69
- cam_pos_world) = pyv.CameraTools.pos_fill_frame_from_rotation(
69
+ cam_pos_world) = pyv.CameraTools.pos_fill_frame(
70
70
  coords_world=render_mesh.coords,
71
71
  pixel_num=pixel_num,
72
72
  pixel_size=pixel_size,
@@ -4,8 +4,6 @@
4
4
  # Copyright (C) 2025 The Computer Aided Validation Team
5
5
  # ==============================================================================
6
6
 
7
-
8
-
9
7
  import time
10
8
  import numpy as np
11
9
  from scipy.spatial.transform import Rotation
@@ -32,7 +30,7 @@ def main() -> None:
32
30
  disp_comps = ("disp_x","disp_y","disp_z")
33
31
 
34
32
  # Scale m -> mm
35
- sim_data = pyv.scale_length_units(sim_data,disp_comps,1000.0)
33
+ sim_data = pyv.scale_length_units(1000.0,sim_data,disp_comps)
36
34
 
37
35
  print()
38
36
  print(f"{np.max(np.abs(sim_data.node_vars['disp_x']))=}")
@@ -70,7 +68,7 @@ def main() -> None:
70
68
  fov_scale_factor: float = 1.1
71
69
 
72
70
  (roi_pos_world,
73
- cam_pos_world) = pyv.CameraTools.pos_fill_frame_from_rotation(
71
+ cam_pos_world) = pyv.CameraTools.pos_fill_frame(
74
72
  coords_world=render_mesh.coords,
75
73
  pixel_num=pixel_num,
76
74
  pixel_size=pixel_size,
pyvale/imagedef2d.py CHANGED
@@ -20,6 +20,7 @@ from scipy import ndimage
20
20
  from pyvale.rasternp import edge_function, RasterNP
21
21
  from pyvale.cameradata2d import CameraData2D
22
22
  from pyvale.cameratools import CameraTools
23
+ from pyvale.imagetools import ImageTools
23
24
 
24
25
 
25
26
  @dataclass(slots=True)
@@ -436,9 +437,9 @@ class ImageDef2D:
436
437
  print_on=print_on)
437
438
 
438
439
  save_file = id_opts.save_path / str(f'{id_opts.save_tag}_'+
439
- f'{CameraTools.image_num_str(im_num=ff,width=4)}'+
440
+ f'{ImageTools.get_num_str(im_num=ff,width=4)}'+
440
441
  '.tiff')
441
- CameraTools.save_image(save_file,def_image,cam_data.bits)
442
+ ImageTools.save_tiff(save_file,def_image,cam_data.bits)
442
443
 
443
444
  if print_on:
444
445
  tocf = time.perf_counter()