pyvale 2025.7.2__cp311-cp311-win_amd64.whl → 2025.8.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 (176) hide show
  1. pyvale/__init__.py +12 -92
  2. pyvale/blender/__init__.py +23 -0
  3. pyvale/{pyvaleexceptions.py → blender/blenderexceptions.py} +0 -3
  4. pyvale/{blenderlightdata.py → blender/blenderlightdata.py} +3 -3
  5. pyvale/{blendermaterialdata.py → blender/blendermaterialdata.py} +1 -1
  6. pyvale/{blenderrenderdata.py → blender/blenderrenderdata.py} +5 -3
  7. pyvale/{blenderscene.py → blender/blenderscene.py} +33 -30
  8. pyvale/{blendertools.py → blender/blendertools.py} +14 -10
  9. pyvale/dataset/__init__.py +7 -0
  10. pyvale/dataset/dataset.py +443 -0
  11. pyvale/dic/__init__.py +20 -0
  12. pyvale/{dic2d.py → dic/dic2d.py} +31 -36
  13. pyvale/dic/dic2dconv.py +6 -0
  14. pyvale/{dic2dcpp.cp311-win_amd64.pyd → dic/dic2dcpp.cp311-win_amd64.pyd} +0 -0
  15. pyvale/{dicdataimport.py → dic/dicdataimport.py} +8 -8
  16. pyvale/{dicregionofinterest.py → dic/dicregionofinterest.py} +1 -1
  17. pyvale/{dicresults.py → dic/dicresults.py} +1 -1
  18. pyvale/{dicstrain.py → dic/dicstrain.py} +9 -9
  19. pyvale/examples/basics/{ex1_1_basicscalars_therm2d.py → ex1a_basicscalars_therm2d.py} +12 -9
  20. pyvale/examples/basics/{ex1_2_sensormodel_therm2d.py → ex1b_sensormodel_therm2d.py} +17 -14
  21. pyvale/examples/basics/{ex1_3_customsens_therm3d.py → ex1c_customsens_therm3d.py} +27 -24
  22. pyvale/examples/basics/{ex1_4_basicerrors_therm3d.py → ex1d_basicerrors_therm3d.py} +32 -29
  23. pyvale/examples/basics/{ex1_5_fielderrs_therm3d.py → ex1e_fielderrs_therm3d.py} +19 -15
  24. pyvale/examples/basics/{ex1_6_caliberrs_therm2d.py → ex1f_caliberrs_therm2d.py} +20 -16
  25. pyvale/examples/basics/{ex1_7_spatavg_therm2d.py → ex1g_spatavg_therm2d.py} +19 -16
  26. pyvale/examples/basics/{ex2_1_basicvectors_disp2d.py → ex2a_basicvectors_disp2d.py} +13 -10
  27. pyvale/examples/basics/{ex2_2_vectorsens_disp2d.py → ex2b_vectorsens_disp2d.py} +19 -15
  28. pyvale/examples/basics/{ex2_3_sensangle_disp2d.py → ex2c_sensangle_disp2d.py} +21 -18
  29. pyvale/examples/basics/{ex2_4_chainfielderrs_disp2d.py → ex2d_chainfielderrs_disp2d.py} +31 -29
  30. pyvale/examples/basics/{ex2_5_vectorfields3d_disp3d.py → ex2e_vectorfields3d_disp3d.py} +21 -18
  31. pyvale/examples/basics/{ex3_1_basictensors_strain2d.py → ex3a_basictensors_strain2d.py} +16 -14
  32. pyvale/examples/basics/{ex3_2_tensorsens2d_strain2d.py → ex3b_tensorsens2d_strain2d.py} +17 -14
  33. pyvale/examples/basics/{ex3_3_tensorsens3d_strain3d.py → ex3c_tensorsens3d_strain3d.py} +25 -22
  34. pyvale/examples/basics/{ex4_1_expsim2d_thermmech2d.py → ex4a_expsim2d_thermmech2d.py} +17 -14
  35. pyvale/examples/basics/{ex4_2_expsim3d_thermmech3d.py → ex4b_expsim3d_thermmech3d.py} +37 -34
  36. pyvale/examples/basics/ex5_nomesh.py +24 -0
  37. pyvale/examples/dic/ex1_2_blenderdeformed.py +174 -0
  38. pyvale/examples/dic/ex1_region_of_interest.py +6 -3
  39. pyvale/examples/dic/ex2_plate_with_hole.py +21 -18
  40. pyvale/examples/dic/ex3_plate_with_hole_strain.py +8 -6
  41. pyvale/examples/dic/ex4_dic_blender.py +17 -15
  42. pyvale/examples/dic/ex5_dic_challenge.py +19 -14
  43. pyvale/examples/genanalyticdata/ex1_1_scalarvisualisation.py +16 -10
  44. pyvale/examples/genanalyticdata/ex1_2_scalarcasebuild.py +3 -3
  45. pyvale/examples/genanalyticdata/ex2_1_analyticsensors.py +29 -23
  46. pyvale/examples/genanalyticdata/ex2_2_analyticsensors_nomesh.py +67 -0
  47. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +12 -9
  48. pyvale/examples/mooseherder/ex0_create_moose_config.py +65 -0
  49. pyvale/examples/mooseherder/ex1a_modify_moose_input.py +71 -0
  50. pyvale/examples/mooseherder/ex1b_modify_gmsh_input.py +69 -0
  51. pyvale/examples/mooseherder/ex2a_run_moose_once.py +80 -0
  52. pyvale/examples/mooseherder/ex2b_run_gmsh_once.py +64 -0
  53. pyvale/examples/mooseherder/ex2c_run_both_once.py +114 -0
  54. pyvale/examples/mooseherder/ex3_run_moose_seq_para.py +157 -0
  55. pyvale/examples/mooseherder/ex4_run_gmsh-moose_seq_para.py +176 -0
  56. pyvale/examples/mooseherder/ex5_run_moose_paramulti.py +136 -0
  57. pyvale/examples/mooseherder/ex6_read_moose_exodus.py +163 -0
  58. pyvale/examples/mooseherder/ex7a_read_moose_herd_results.py +153 -0
  59. pyvale/examples/mooseherder/ex7b_read_multi_herd_results.py +116 -0
  60. pyvale/examples/mooseherder/ex7c_read_multi_gmshmoose_results.py +127 -0
  61. pyvale/examples/mooseherder/ex7d_readconfig_multi_gmshmoose_results.py +143 -0
  62. pyvale/examples/mooseherder/ex8_read_existing_sweep_output.py +72 -0
  63. pyvale/examples/renderblender/ex1_1_blenderscene.py +24 -20
  64. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +22 -18
  65. pyvale/examples/renderblender/ex2_1_stereoscene.py +36 -29
  66. pyvale/examples/renderblender/ex2_2_stereodeformed.py +26 -20
  67. pyvale/examples/renderblender/ex3_1_blendercalibration.py +24 -17
  68. pyvale/examples/renderrasterisation/ex_rastenp.py +14 -12
  69. pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +14 -15
  70. pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +13 -11
  71. pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +13 -11
  72. pyvale/mooseherder/__init__.py +32 -0
  73. pyvale/mooseherder/directorymanager.py +416 -0
  74. pyvale/mooseherder/exodusreader.py +763 -0
  75. pyvale/mooseherder/gmshrunner.py +163 -0
  76. pyvale/mooseherder/inputmodifier.py +236 -0
  77. pyvale/mooseherder/mooseconfig.py +226 -0
  78. pyvale/mooseherder/mooseherd.py +527 -0
  79. pyvale/mooseherder/mooserunner.py +303 -0
  80. pyvale/mooseherder/outputreader.py +22 -0
  81. pyvale/mooseherder/simdata.py +92 -0
  82. pyvale/mooseherder/simrunner.py +31 -0
  83. pyvale/mooseherder/sweepreader.py +356 -0
  84. pyvale/mooseherder/sweeptools.py +76 -0
  85. pyvale/sensorsim/__init__.py +82 -0
  86. pyvale/{camera.py → sensorsim/camera.py} +7 -7
  87. pyvale/{camerasensor.py → sensorsim/camerasensor.py} +7 -7
  88. pyvale/{camerastereo.py → sensorsim/camerastereo.py} +2 -2
  89. pyvale/{cameratools.py → sensorsim/cameratools.py} +4 -4
  90. pyvale/{cython → sensorsim/cython}/rastercyth.c +596 -596
  91. pyvale/{cython → sensorsim/cython}/rastercyth.cp311-win_amd64.pyd +0 -0
  92. pyvale/{cython → sensorsim/cython}/rastercyth.py +16 -17
  93. pyvale/{errorcalculator.py → sensorsim/errorcalculator.py} +1 -1
  94. pyvale/{errorintegrator.py → sensorsim/errorintegrator.py} +2 -2
  95. pyvale/{errorrand.py → sensorsim/errorrand.py} +4 -4
  96. pyvale/{errorsyscalib.py → sensorsim/errorsyscalib.py} +2 -2
  97. pyvale/{errorsysdep.py → sensorsim/errorsysdep.py} +2 -2
  98. pyvale/{errorsysfield.py → sensorsim/errorsysfield.py} +8 -8
  99. pyvale/{errorsysindep.py → sensorsim/errorsysindep.py} +3 -3
  100. pyvale/sensorsim/exceptions.py +8 -0
  101. pyvale/{experimentsimulator.py → sensorsim/experimentsimulator.py} +23 -3
  102. pyvale/{field.py → sensorsim/field.py} +1 -1
  103. pyvale/{fieldconverter.py → sensorsim/fieldconverter.py} +72 -19
  104. pyvale/sensorsim/fieldinterp.py +37 -0
  105. pyvale/sensorsim/fieldinterpmesh.py +124 -0
  106. pyvale/sensorsim/fieldinterppoints.py +55 -0
  107. pyvale/{fieldsampler.py → sensorsim/fieldsampler.py} +4 -4
  108. pyvale/{fieldscalar.py → sensorsim/fieldscalar.py} +28 -24
  109. pyvale/{fieldtensor.py → sensorsim/fieldtensor.py} +33 -31
  110. pyvale/{fieldvector.py → sensorsim/fieldvector.py} +33 -31
  111. pyvale/{imagedef2d.py → sensorsim/imagedef2d.py} +9 -5
  112. pyvale/{integratorfactory.py → sensorsim/integratorfactory.py} +6 -6
  113. pyvale/{integratorquadrature.py → sensorsim/integratorquadrature.py} +3 -3
  114. pyvale/{integratorrectangle.py → sensorsim/integratorrectangle.py} +3 -3
  115. pyvale/{integratorspatial.py → sensorsim/integratorspatial.py} +1 -1
  116. pyvale/{rastercy.py → sensorsim/rastercy.py} +5 -5
  117. pyvale/{rasternp.py → sensorsim/rasternp.py} +9 -9
  118. pyvale/{rasteropts.py → sensorsim/rasteropts.py} +1 -1
  119. pyvale/{renderer.py → sensorsim/renderer.py} +1 -1
  120. pyvale/{rendermesh.py → sensorsim/rendermesh.py} +5 -5
  121. pyvale/{renderscene.py → sensorsim/renderscene.py} +2 -2
  122. pyvale/{sensorarray.py → sensorsim/sensorarray.py} +1 -1
  123. pyvale/{sensorarrayfactory.py → sensorsim/sensorarrayfactory.py} +12 -12
  124. pyvale/{sensorarraypoint.py → sensorsim/sensorarraypoint.py} +10 -8
  125. pyvale/{sensordata.py → sensorsim/sensordata.py} +1 -1
  126. pyvale/{sensortools.py → sensorsim/sensortools.py} +2 -20
  127. pyvale/sensorsim/simtools.py +174 -0
  128. pyvale/{visualexpplotter.py → sensorsim/visualexpplotter.py} +3 -3
  129. pyvale/{visualimages.py → sensorsim/visualimages.py} +2 -2
  130. pyvale/{visualsimanimator.py → sensorsim/visualsimanimator.py} +4 -4
  131. pyvale/{visualsimplotter.py → sensorsim/visualsimplotter.py} +5 -5
  132. pyvale/{visualsimsensors.py → sensorsim/visualsimsensors.py} +12 -12
  133. pyvale/{visualtools.py → sensorsim/visualtools.py} +1 -1
  134. pyvale/{visualtraceplotter.py → sensorsim/visualtraceplotter.py} +2 -2
  135. pyvale/simcases/case17.geo +3 -0
  136. pyvale/simcases/case17.i +4 -4
  137. pyvale/simcases/run_1case.py +1 -9
  138. pyvale/simcases/run_all_cases.py +1 -1
  139. pyvale/simcases/run_build_case.py +1 -1
  140. pyvale/simcases/run_example_cases.py +1 -1
  141. pyvale/verif/__init__.py +12 -0
  142. pyvale/{analyticsimdatafactory.py → verif/analyticsimdatafactory.py} +2 -2
  143. pyvale/{analyticsimdatagenerator.py → verif/analyticsimdatagenerator.py} +2 -2
  144. pyvale/verif/psens.py +125 -0
  145. pyvale/verif/psensconst.py +18 -0
  146. pyvale/verif/psensmech.py +227 -0
  147. pyvale/verif/psensmultiphys.py +187 -0
  148. pyvale/verif/psensscalar.py +347 -0
  149. pyvale/verif/psenstensor.py +123 -0
  150. pyvale/verif/psensvector.py +116 -0
  151. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/METADATA +6 -7
  152. pyvale-2025.8.1.dist-info/RECORD +260 -0
  153. pyvale/dataset.py +0 -415
  154. pyvale/simtools.py +0 -67
  155. pyvale-2025.7.2.dist-info/RECORD +0 -212
  156. /pyvale/{blendercalibrationdata.py → blender/blendercalibrationdata.py} +0 -0
  157. /pyvale/{dicchecks.py → dic/dicchecks.py} +0 -0
  158. /pyvale/{dicspecklegenerator.py → dic/dicspecklegenerator.py} +0 -0
  159. /pyvale/{dicspecklequality.py → dic/dicspecklequality.py} +0 -0
  160. /pyvale/{dicstrainresults.py → dic/dicstrainresults.py} +0 -0
  161. /pyvale/{cameradata.py → sensorsim/cameradata.py} +0 -0
  162. /pyvale/{cameradata2d.py → sensorsim/cameradata2d.py} +0 -0
  163. /pyvale/{errordriftcalc.py → sensorsim/errordriftcalc.py} +0 -0
  164. /pyvale/{fieldtransform.py → sensorsim/fieldtransform.py} +0 -0
  165. /pyvale/{generatorsrandom.py → sensorsim/generatorsrandom.py} +0 -0
  166. /pyvale/{imagetools.py → sensorsim/imagetools.py} +0 -0
  167. /pyvale/{integratortype.py → sensorsim/integratortype.py} +0 -0
  168. /pyvale/{output.py → sensorsim/output.py} +0 -0
  169. /pyvale/{raster.py → sensorsim/raster.py} +0 -0
  170. /pyvale/{sensordescriptor.py → sensorsim/sensordescriptor.py} +0 -0
  171. /pyvale/{visualimagedef.py → sensorsim/visualimagedef.py} +0 -0
  172. /pyvale/{visualopts.py → sensorsim/visualopts.py} +0 -0
  173. /pyvale/{analyticmeshgen.py → verif/analyticmeshgen.py} +0 -0
  174. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/WHEEL +0 -0
  175. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/licenses/LICENSE +0 -0
  176. {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/top_level.txt +0 -0
@@ -8,15 +8,17 @@ import time
8
8
  import numpy as np
9
9
  from scipy.spatial.transform import Rotation
10
10
  import matplotlib.pyplot as plt
11
- import mooseherder as mh
12
- import pyvale as pyv
13
11
  import imagebenchmarks as ib
14
12
 
13
+ # Pyvale imports
14
+ import pyvale.sensorsim as sens
15
+ import pyvale.mooseherder as mh
16
+
15
17
  def main() -> None:
16
18
  print()
17
19
  print(80*"=")
18
20
  print("RASTER CYTHON FILE (should be *.so on Linux):")
19
- print(pyv.rastercyth.__file__)
21
+ print(sens.rastercyth.__file__)
20
22
  print(80*"=")
21
23
  print()
22
24
 
@@ -26,14 +28,14 @@ def main() -> None:
26
28
  # replaced with a path to your own simulation file
27
29
  #sim_path = Path.home()/"pyvale"/"src"/"pyvale"/"simcases"/"case26_out.e"
28
30
 
29
- sim_path = pyv.DataSet.render_simple_block_path()
30
- #sim_path = pyv.DataSet.render_mechanical_3d_path()
31
+ sim_path = sens.DataSet.render_simple_block_path()
32
+ #sim_path = sens.DataSet.render_mechanical_3d_path()
31
33
  sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
32
34
 
33
35
  disp_comps = ("disp_x","disp_y","disp_z")
34
36
 
35
37
  # Scale m -> mm
36
- sim_data = pyv.scale_length_units(1000.0,sim_data,disp_comps)
38
+ sim_data = sens.scale_length_units(1000.0,sim_data,disp_comps)
37
39
 
38
40
  print()
39
41
  print(f"{np.max(np.abs(sim_data.node_vars['disp_x']))=}")
@@ -42,15 +44,12 @@ def main() -> None:
42
44
  print()
43
45
 
44
46
  # Extracts the surface mesh from a full 3d simulation for rendering
45
- render_mesh = pyv.create_render_mesh(sim_data,
47
+ render_mesh = sens.create_render_mesh(sim_data,
46
48
  ("disp_y","disp_x","disp_z"),
47
49
  sim_spat_dim=3,
48
50
  field_disp_keys=disp_comps)
49
51
 
50
52
 
51
-
52
-
53
-
54
53
  pixel_num = np.array((960,1280),dtype=np.int32)
55
54
  pixel_size = np.array((5.3e-3,5.3e-3),dtype=np.float64)
56
55
  focal_leng: float = 50.0
@@ -58,7 +57,7 @@ def main() -> None:
58
57
  fov_scale_factor: float = 1.1
59
58
 
60
59
  (roi_pos_world,
61
- cam_pos_world) = pyv.CameraTools.pos_fill_frame(
60
+ cam_pos_world) = sens.CameraTools.pos_fill_frame(
62
61
  coords_world=render_mesh.coords,
63
62
  pixel_num=pixel_num,
64
63
  pixel_size=pixel_size,
@@ -67,7 +66,7 @@ def main() -> None:
67
66
  frame_fill=fov_scale_factor,
68
67
  )
69
68
 
70
- cam_data = pyv.CameraData(
69
+ cam_data = sens.CameraData(
71
70
  pixels_num=pixel_num,
72
71
  pixels_size=pixel_size,
73
72
  pos_world=cam_pos_world,
@@ -144,7 +143,7 @@ def main() -> None:
144
143
 
145
144
  (image_buffer,
146
145
  depth_buffer,
147
- elems_in_image) = pyv.rastercyth.raster_static_frame(
146
+ elems_in_image) = sens.rastercyth.raster_static_frame(
148
147
  render_mesh.coords,
149
148
  render_mesh.connectivity,
150
149
  fields_render,
@@ -164,7 +163,7 @@ def main() -> None:
164
163
 
165
164
  #===========================================================================
166
165
  # PLOTTING
167
- plot_on = False
166
+ plot_on = True
168
167
  plot_field = 0
169
168
 
170
169
  # depth_to_plot = np.copy(np.asarray(depth_buffer[:,:,plot_frame]))
@@ -173,7 +172,7 @@ def main() -> None:
173
172
  # image_to_plot[depth_buffer[:,:,plot_frame] > 10*cam_data.image_dist] = np.nan
174
173
 
175
174
  if plot_on:
176
- plot_opts = pyv.PlotOptsGeneral()
175
+ plot_opts = sens.PlotOptsGeneral()
177
176
 
178
177
 
179
178
  (fig, ax) = plt.subplots(figsize=plot_opts.single_fig_size_square,
@@ -9,26 +9,28 @@ import time
9
9
  import numpy as np
10
10
  from scipy.spatial.transform import Rotation
11
11
  import matplotlib.pyplot as plt
12
- import mooseherder as mh
13
- import pyvale as pyv
12
+
13
+ # Pyvale imports
14
+ import pyvale.sensorsim as sens
15
+ import pyvale.mooseherder as mh
14
16
 
15
17
  def main() -> None:
16
18
  print()
17
19
  print(80*"=")
18
20
  print("RASTER CYTHON FILE (should be *.so on Linux):")
19
- print(pyv.rastercyth.__file__)
21
+ print(sens.rastercyth.__file__)
20
22
  print(80*"=")
21
23
  print()
22
24
 
23
- sim_path = pyv.DataSet.render_mechanical_3d_path()
24
- #sim_path = pyv.DataSet.render_simple_block_path()
25
+ sim_path = sens.DataSet.render_mechanical_3d_path()
26
+ #sim_path = sens.DataSet.render_simple_block_path()
25
27
  #sim_path = Path.home()/"pyvale"/"src"/"pyvale"/"simcases"/"case26_out.e"
26
28
  sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
27
29
 
28
30
  disp_comps = ("disp_x","disp_y","disp_z")
29
31
 
30
32
  # Scale m -> mm
31
- sim_data = pyv.scale_length_units(1000.0,sim_data,disp_comps)
33
+ sim_data = sens.scale_length_units(1000.0,sim_data,disp_comps)
32
34
 
33
35
  print()
34
36
  print(f"{np.max(np.abs(sim_data.node_vars['disp_x']))=}")
@@ -37,7 +39,7 @@ def main() -> None:
37
39
  print()
38
40
 
39
41
  # Extracts the surface mesh from a full 3d simulation for rendering
40
- render_mesh = pyv.create_render_mesh(sim_data,
42
+ render_mesh = sens.create_render_mesh(sim_data,
41
43
  ("disp_y","disp_x"),
42
44
  sim_spat_dim=3,
43
45
  field_disp_keys=disp_comps)
@@ -66,7 +68,7 @@ def main() -> None:
66
68
  fov_scale_factor: float = 1.1
67
69
 
68
70
  (roi_pos_world,
69
- cam_pos_world) = pyv.CameraTools.pos_fill_frame(
71
+ cam_pos_world) = sens.CameraTools.pos_fill_frame(
70
72
  coords_world=render_mesh.coords,
71
73
  pixel_num=pixel_num,
72
74
  pixel_size=pixel_size,
@@ -75,7 +77,7 @@ def main() -> None:
75
77
  frame_fill=fov_scale_factor,
76
78
  )
77
79
 
78
- cam_data = pyv.CameraData(
80
+ cam_data = sens.CameraData(
79
81
  pixels_num=pixel_num,
80
82
  pixels_size=pixel_size,
81
83
  pos_world=cam_pos_world,
@@ -120,7 +122,7 @@ def main() -> None:
120
122
 
121
123
  (image_buffer,
122
124
  depth_buffer,
123
- elems_in_image) = pyv.rastercyth.raster_static_mesh(
125
+ elems_in_image) = sens.rastercyth.raster_static_mesh(
124
126
  render_mesh,
125
127
  cam_data,
126
128
  0)
@@ -149,7 +151,7 @@ def main() -> None:
149
151
  # image_to_plot[depth_buffer[:,:,plot_frame] > 10*cam_data.image_dist] = np.nan
150
152
 
151
153
  if plot_on:
152
- plot_opts = pyv.PlotOptsGeneral()
154
+ plot_opts = sens.PlotOptsGeneral()
153
155
 
154
156
  for ff in plot_frames:
155
157
  (fig, ax) = plt.subplots(figsize=plot_opts.single_fig_size_square,
@@ -8,29 +8,31 @@ import time
8
8
  import numpy as np
9
9
  from scipy.spatial.transform import Rotation
10
10
  import matplotlib.pyplot as plt
11
- import mooseherder as mh
12
- import pyvale as pyv
11
+
12
+ # Pyvale imports
13
+ import pyvale.sensorsim as sens
14
+ import pyvale.mooseherder as mh
13
15
 
14
16
 
15
17
  def main() -> None:
16
18
  print()
17
19
  print(80*"=")
18
20
  print("RASTER CYTHON FILE (should be *.so on Linux):")
19
- print(pyv.rastercyth.__file__)
21
+ print(sens.rastercyth.__file__)
20
22
  print(80*"=")
21
23
  print()
22
24
 
23
25
  # This a path to an exodus *.e output file from MOOSE, this can be
24
26
  # replaced with a path to your own simulation file
25
- sim_path = pyv.DataSet.render_mechanical_3d_path()
26
- #sim_path = pyv.DataSet.render_simple_block_path()
27
+ sim_path = sens.DataSet.render_mechanical_3d_path()
28
+ #sim_path = sens.DataSet.render_simple_block_path()
27
29
  #sim_path = Path.home()/"pyvale"/"src"/"pyvale"/"simcases"/"case26_out.e"
28
30
  sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
29
31
 
30
32
  disp_comps = ("disp_x","disp_y","disp_z")
31
33
 
32
34
  # Scale m -> mm
33
- sim_data = pyv.scale_length_units(1000.0,sim_data,disp_comps)
35
+ sim_data = sens.scale_length_units(1000.0,sim_data,disp_comps)
34
36
 
35
37
  print()
36
38
  print(f"{np.max(np.abs(sim_data.node_vars['disp_x']))=}")
@@ -39,7 +41,7 @@ def main() -> None:
39
41
  print()
40
42
 
41
43
  # Extracts the surface mesh from a full 3d simulation for rendering
42
- render_mesh = pyv.create_render_mesh(sim_data,
44
+ render_mesh = sens.create_render_mesh(sim_data,
43
45
  ("disp_y","disp_x"),
44
46
  sim_spat_dim=3,
45
47
  field_disp_keys=disp_comps)
@@ -68,7 +70,7 @@ def main() -> None:
68
70
  fov_scale_factor: float = 1.1
69
71
 
70
72
  (roi_pos_world,
71
- cam_pos_world) = pyv.CameraTools.pos_fill_frame(
73
+ cam_pos_world) = sens.CameraTools.pos_fill_frame(
72
74
  coords_world=render_mesh.coords,
73
75
  pixel_num=pixel_num,
74
76
  pixel_size=pixel_size,
@@ -77,7 +79,7 @@ def main() -> None:
77
79
  frame_fill=fov_scale_factor,
78
80
  )
79
81
 
80
- cam_data = pyv.CameraData(
82
+ cam_data = sens.CameraData(
81
83
  pixels_num=pixel_num,
82
84
  pixels_size=pixel_size,
83
85
  pos_world=cam_pos_world,
@@ -122,7 +124,7 @@ def main() -> None:
122
124
 
123
125
  (image_buffer,
124
126
  depth_buffer,
125
- elems_in_images) = pyv.RasterCY.raster_static_mesh(cam_data,
127
+ elems_in_images) = sens.RasterCY.raster_static_mesh(cam_data,
126
128
  render_mesh,
127
129
  16)
128
130
 
@@ -150,7 +152,7 @@ def main() -> None:
150
152
  # image_to_plot[depth_buffer[:,:,plot_frame] > 10*cam_data.image_dist] = np.nan
151
153
 
152
154
  if plot_on:
153
- plot_opts = pyv.PlotOptsGeneral()
155
+ plot_opts = sens.PlotOptsGeneral()
154
156
 
155
157
  for ff in plot_frames:
156
158
  (fig, ax) = plt.subplots(figsize=plot_opts.single_fig_size_square,
@@ -0,0 +1,32 @@
1
+ #===============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ #===============================================================================
6
+
7
+ from .inputmodifier import InputModifier
8
+ from .simrunner import SimRunner
9
+ from .mooserunner import MooseRunner
10
+ from .gmshrunner import GmshRunner
11
+ from .exodusreader import ExodusReader
12
+ from .mooseherd import MooseHerd
13
+ from .directorymanager import DirectoryManager
14
+ from .sweepreader import SweepReader
15
+ from .simdata import SimData
16
+ from .simdata import SimReadConfig
17
+ from .mooseconfig import MooseConfig
18
+ from .sweeptools import sweep_param_grid
19
+
20
+
21
+ __all__ = ["InputModifier",
22
+ "SimRunner",
23
+ "MooseRunner",
24
+ "GmshRunner",
25
+ "ExodusReader",
26
+ "mooseherd",
27
+ "DirectoryManager",
28
+ "SweepReader",
29
+ "SimData",
30
+ "SimReadConfig",
31
+ "MooseConfig",
32
+ "sweep_param_grid"]
@@ -0,0 +1,416 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ import os
8
+ import shutil
9
+ import json
10
+ from pathlib import Path
11
+
12
+ class DirectoryManager:
13
+ """Manages directories for running simulations in parallel with the
14
+ mooseherd.
15
+
16
+ Parameters
17
+ ----------
18
+
19
+ Returns
20
+ -------
21
+
22
+ """
23
+ def __init__(self, n_dirs: int = 1) -> None:
24
+ """__init__
25
+
26
+ Args:
27
+ n_dirs (int, optional): number of directories to be created.
28
+ Defaults to 1.
29
+ """
30
+ self._n_dirs = n_dirs
31
+ self._sub_dir = 'sim-workdir'
32
+ self._base_dir = Path().cwd()
33
+ self._run_dirs = self._set_run_dirs()
34
+ self._output_paths = list([])
35
+ self._output_key_tag = 'output-key'
36
+ self._sweep_var_tag = 'sweep-vars'
37
+
38
+
39
+ def _set_run_dirs(self) -> list[Path]:
40
+ """_set_run_dirs: helper function that populates the list of
41
+ directories that will be created by the manager. Uses the base directory
42
+ at the start of the path and then creates numbered sub-directory paths
43
+ based on the sub directory name and number of directories specified.
44
+
45
+ Parameters
46
+ ----------
47
+
48
+ Returns
49
+ -------
50
+ list[Path]
51
+
52
+
53
+ """
54
+ run_dirs = list([])
55
+ for nn in range(self._n_dirs): # type: ignore
56
+ run_dirs.append(self._base_dir / (self._sub_dir + '-' + str(nn+1)))
57
+
58
+ return run_dirs
59
+
60
+
61
+ def set_sub_dir_name(self, sub_dir_name: str) -> None:
62
+ """set_sub_dir_name: used to set the string used at the start of the
63
+ created sub-directores. default on creation is 'sim-workdir'. Populates
64
+ the list of run directories using the new sub directory name.
65
+
66
+ Parameters
67
+ ----------
68
+ sub_dir_name : str
69
+ string to be used to name the created
70
+ sub-directories within the base directory.
71
+ sub_dir_name: str :
72
+
73
+
74
+ Returns
75
+ -------
76
+
77
+ """
78
+ self._sub_dir = sub_dir_name
79
+ self._run_dirs = self._set_run_dirs()
80
+
81
+
82
+ def set_base_dir(self, base_dir: Path, clear_old_dirs = False) -> None:
83
+ """set_base_dir: sets the base directory to create sub-directors for
84
+ running the simulations. The base directory must exist.
85
+
86
+ Parameters
87
+ ----------
88
+ base_dir : Path
89
+ directory in which the new working directories will
90
+ be created.
91
+ clear_old_dirs : bool
92
+ deletes previous directories in
93
+ the base directory and their contents if they exist. Defaults
94
+ to False.
95
+
96
+ Returns
97
+ -------
98
+
99
+ Raises
100
+ ------
101
+ FileExistsError
102
+ the selected base directory does no exist.
103
+
104
+ """
105
+ if not base_dir.is_dir():
106
+ raise FileExistsError("Specified base directory does not exist.")
107
+
108
+ if clear_old_dirs:
109
+ self.clear_dirs()
110
+
111
+ self._base_dir = base_dir
112
+ self._run_dirs = self._set_run_dirs()
113
+
114
+
115
+ def get_output_key_tag(self) -> str:
116
+ """get_output_key_tag: returns the string used to name the output
117
+ key files that map the simulation outputs to the various directories
118
+ that are being managed.
119
+
120
+ Parameters
121
+ ----------
122
+
123
+ Returns
124
+ -------
125
+ str
126
+ common string used to name the output key json files.
127
+
128
+ """
129
+ return self._output_key_tag
130
+
131
+
132
+ def get_sweep_var_tag(self) -> str:
133
+ """get_sweep_var_tag: returns ths string used to name the sweep
134
+ variable json file that contains a copy of the dictionary the user
135
+ provided as part of the parameter sweep.
136
+
137
+ Parameters
138
+ ----------
139
+
140
+ Returns
141
+ -------
142
+ str
143
+ common string used to name the sweep variable json files.
144
+
145
+ """
146
+ return self._sweep_var_tag
147
+
148
+
149
+ def create_dirs(self) -> list[Path]:
150
+ """Creates the specified number of directories based on
151
+ the sub_dir name within the base directory.
152
+
153
+ Parameters
154
+ ----------
155
+
156
+ Returns
157
+ -------
158
+ list[Path]
159
+ list of paths to the directories to create.
160
+
161
+ """
162
+ for rr in self._run_dirs:
163
+ if not rr.is_dir():
164
+ rr.mkdir()
165
+
166
+ return self._run_dirs
167
+
168
+
169
+ def clear_dirs(self) -> None:
170
+ """Deletes all working directories in the base directory
171
+ that have the corresponding sub-directory name and their contents.
172
+ """
173
+ all_dirs = os.listdir(self._base_dir)
174
+ for dd in all_dirs:
175
+ if os.path.isdir(self._base_dir / dd):
176
+ if self._sub_dir in dd:
177
+ shutil.rmtree(self._base_dir / dd)
178
+
179
+ def reset_dirs(self) -> list[Path]:
180
+ """Helper function that first clears the working directories if they
181
+ exist and then creates new working directories ready for a simulation
182
+ sweep.
183
+
184
+ Returns
185
+ -------
186
+ list[Path]
187
+ List of paths to the created working directories
188
+ """
189
+ self.clear_dirs()
190
+ return self.create_dirs()
191
+
192
+ def get_all_run_dirs(self) -> list[Path]:
193
+ """Returns the list of paths to all the directories
194
+ that can be used to run simulations.
195
+
196
+ Parameters
197
+ ----------
198
+
199
+ Returns
200
+ -------
201
+ list[Path]
202
+ paths to all created directories.
203
+
204
+ """
205
+ return self._run_dirs
206
+
207
+
208
+ def get_run_dir(self, dir_num: int) -> Path:
209
+ """get_run_dir: returns the path to the run directory based on the
210
+ input directory number. The directory number can be greater than the
211
+ number of managed directories in the run_dirs list in this case the
212
+ directory number will wrap and point at an existing run directory
213
+ allowing multiple simulations to be run in the same directory.
214
+
215
+ Parameters
216
+ ----------
217
+ dir_num : int
218
+ number of the directory path to be retrieved. Can be
219
+ greater than the specified number of directories and will wrap
220
+ appropriately
221
+
222
+
223
+ Returns
224
+ -------
225
+ Path
226
+ path to the directory
227
+
228
+ """
229
+ if dir_num < 0:
230
+ dir_num = 0
231
+ elif dir_num >= self._n_dirs:
232
+ dir_num = dir_num % self._n_dirs
233
+
234
+ return self._run_dirs[dir_num]
235
+
236
+
237
+ def set_output_paths(self, output_paths: list[list[Path | None]]) -> None:
238
+ """set_output_paths: sets the list of lists to the simulation output
239
+ based on herder input.
240
+
241
+ Parameters
242
+ ----------
243
+ output_paths : list[list[Path | None]]
244
+ paths to all outputs from the
245
+ variable sweep. Outer list is the variable combination run
246
+ inner list is based on the order the simulations were called.
247
+
248
+
249
+ Returns
250
+ -------
251
+
252
+ """
253
+ self._output_paths = output_paths
254
+
255
+
256
+ def get_output_paths(self) -> list[list[Path | None]]:
257
+ """get_output_paths: returns the list of lists to the simulation output
258
+ files.
259
+
260
+ Parameters
261
+ ----------
262
+
263
+ Returns
264
+ -------
265
+ list[list[Path | None]]
266
+ paths to all outputs from the variable sweep.
267
+ Outer list is the variable combination run inner list is based
268
+ on the order the simulations were called.
269
+
270
+ """
271
+ return self._output_paths
272
+
273
+
274
+ def get_output_key_file(self, sweep_iter: int = 1) -> Path:
275
+ """get_output_key_file: gets the path to the output key file created
276
+ during the variable sweep mapping directories to given combinations
277
+ of variables that were run.
278
+
279
+ Parameters
280
+ ----------
281
+ sweep_iter : int
282
+ number corresponding to the sweep iteration to
283
+ retrieve. Defaults to 1.
284
+
285
+ Returns
286
+ -------
287
+ Path
288
+ path to the output key file that maps output paths to the
289
+ combinations of variables in the sweep.
290
+
291
+ """
292
+ return self._run_dirs[0] / f'{self._output_key_tag}-{sweep_iter:d}.json'
293
+
294
+
295
+ def write_output_key(self, sweep_iter: int) -> None:
296
+ """write_output_key: converts the output paths to strings and saves
297
+ them in json format.
298
+
299
+ Parameters
300
+ ----------
301
+ sweep_iter : int
302
+ number corresponing to the sweep iteration to
303
+ write. The sweep iteration is used to number the output key
304
+ files.
305
+
306
+ Returns
307
+ -------
308
+
309
+ """
310
+ str_output = output_paths_to_str(self._output_paths)
311
+
312
+ with open(self.get_output_key_file(sweep_iter), "w", encoding='utf-8') as okf:
313
+ json.dump(str_output, okf, indent=4)
314
+
315
+
316
+ def get_sweep_var_file(self, sweep_iter: int = 1) -> Path:
317
+ """get_sweep_var_file: path to the json file which contains the
318
+ dictionary of variables that were analysed at the given sweep iteration
319
+
320
+ Parameters
321
+ ----------
322
+ sweep_iter : int
323
+ Sweep iteration (call number to herd
324
+ run_para). Defaults to 1.
325
+
326
+ Returns
327
+ -------
328
+ Path
329
+ path to the json sweep variable file.
330
+
331
+ """
332
+ return self._run_dirs[0] / f'{self._sweep_var_tag}-{sweep_iter:d}.json'
333
+
334
+
335
+ def write_sweep_vars(self,
336
+ sweep_vars: list[list[dict | None]],
337
+ sweep_iter: int = 1) -> None:
338
+ """write_sweep_vars: writes the sweep variable dictionary to a json
339
+ file to log the variables used for each simulation.
340
+
341
+ Parameters
342
+ ----------
343
+ sweep_vars : list[list[dict | None]]
344
+ sweep variables as passed to the herd to run.
345
+ sweep_iter : int
346
+ iteration number for number of calls to the
347
+ herd. Defaults to 1.
348
+
349
+ Returns
350
+ -------
351
+
352
+ """
353
+ with open(self.get_sweep_var_file(sweep_iter), "w", encoding='utf-8') as okf:
354
+ json.dump(sweep_vars, okf, indent=4)
355
+
356
+
357
+
358
+ def output_paths_to_str(output_files: list[list[Path | None]]
359
+ ) -> list[list[str | None]]:
360
+ """output_paths_to_str: helper function for converting the output paths
361
+ to strings to allow them to be saved as json.
362
+
363
+ Parameters
364
+ ----------
365
+ output_files : list[list[Path | None]]
366
+
367
+
368
+ Returns
369
+ -------
370
+ list[list[str]]
371
+ as input with Path converted to str
372
+
373
+ """
374
+ str_output = list([])
375
+ for sim_iter in output_files:
376
+ iter_output = list([])
377
+ for output_path in sim_iter:
378
+ if output_path is None:
379
+ iter_output.append(None)
380
+ else:
381
+ iter_output.append(str(output_path))
382
+
383
+ str_output.append(iter_output)
384
+
385
+ return str_output
386
+
387
+
388
+ def output_str_to_paths(output_files: list[list[str | None]]
389
+ ) -> list[list[Path | None]]:
390
+ """output_str_to_paths: helper function to convert strings read from output
391
+ key json to paths.
392
+
393
+ Parameters
394
+ ----------
395
+ output_files : list[list[str]]
396
+ output file list of path strings as in the output key file.
397
+
398
+ Returns
399
+ -------
400
+ list[list[Path]]
401
+ as input with str converted to Path.
402
+
403
+ """
404
+ str_output = list([])
405
+
406
+ for sim_iter in output_files:
407
+ iter_output = list([])
408
+ for output_path in sim_iter:
409
+ if output_path is None:
410
+ iter_output.append(None)
411
+ else:
412
+ iter_output.append(Path(output_path))
413
+
414
+ str_output.append(iter_output)
415
+
416
+ return str_output