pyvale 2025.7.2__cp311-cp311-win32.whl → 2025.8.1__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.
- pyvale/__init__.py +12 -92
- pyvale/blender/__init__.py +23 -0
- pyvale/{pyvaleexceptions.py → blender/blenderexceptions.py} +0 -3
- pyvale/{blenderlightdata.py → blender/blenderlightdata.py} +3 -3
- pyvale/{blendermaterialdata.py → blender/blendermaterialdata.py} +1 -1
- pyvale/{blenderrenderdata.py → blender/blenderrenderdata.py} +5 -3
- pyvale/{blenderscene.py → blender/blenderscene.py} +33 -30
- pyvale/{blendertools.py → blender/blendertools.py} +14 -10
- pyvale/dataset/__init__.py +7 -0
- pyvale/dataset/dataset.py +443 -0
- pyvale/dic/__init__.py +20 -0
- pyvale/{dic2d.py → dic/dic2d.py} +31 -36
- pyvale/dic/dic2dconv.py +6 -0
- pyvale/{dic2dcpp.cp311-win32.pyd → dic/dic2dcpp.cp311-win32.pyd} +0 -0
- pyvale/{dicdataimport.py → dic/dicdataimport.py} +8 -8
- pyvale/{dicregionofinterest.py → dic/dicregionofinterest.py} +1 -1
- pyvale/{dicresults.py → dic/dicresults.py} +1 -1
- pyvale/{dicstrain.py → dic/dicstrain.py} +9 -9
- pyvale/examples/basics/{ex1_1_basicscalars_therm2d.py → ex1a_basicscalars_therm2d.py} +12 -9
- pyvale/examples/basics/{ex1_2_sensormodel_therm2d.py → ex1b_sensormodel_therm2d.py} +17 -14
- pyvale/examples/basics/{ex1_3_customsens_therm3d.py → ex1c_customsens_therm3d.py} +27 -24
- pyvale/examples/basics/{ex1_4_basicerrors_therm3d.py → ex1d_basicerrors_therm3d.py} +32 -29
- pyvale/examples/basics/{ex1_5_fielderrs_therm3d.py → ex1e_fielderrs_therm3d.py} +19 -15
- pyvale/examples/basics/{ex1_6_caliberrs_therm2d.py → ex1f_caliberrs_therm2d.py} +20 -16
- pyvale/examples/basics/{ex1_7_spatavg_therm2d.py → ex1g_spatavg_therm2d.py} +19 -16
- pyvale/examples/basics/{ex2_1_basicvectors_disp2d.py → ex2a_basicvectors_disp2d.py} +13 -10
- pyvale/examples/basics/{ex2_2_vectorsens_disp2d.py → ex2b_vectorsens_disp2d.py} +19 -15
- pyvale/examples/basics/{ex2_3_sensangle_disp2d.py → ex2c_sensangle_disp2d.py} +21 -18
- pyvale/examples/basics/{ex2_4_chainfielderrs_disp2d.py → ex2d_chainfielderrs_disp2d.py} +31 -29
- pyvale/examples/basics/{ex2_5_vectorfields3d_disp3d.py → ex2e_vectorfields3d_disp3d.py} +21 -18
- pyvale/examples/basics/{ex3_1_basictensors_strain2d.py → ex3a_basictensors_strain2d.py} +16 -14
- pyvale/examples/basics/{ex3_2_tensorsens2d_strain2d.py → ex3b_tensorsens2d_strain2d.py} +17 -14
- pyvale/examples/basics/{ex3_3_tensorsens3d_strain3d.py → ex3c_tensorsens3d_strain3d.py} +25 -22
- pyvale/examples/basics/{ex4_1_expsim2d_thermmech2d.py → ex4a_expsim2d_thermmech2d.py} +17 -14
- pyvale/examples/basics/{ex4_2_expsim3d_thermmech3d.py → ex4b_expsim3d_thermmech3d.py} +37 -34
- pyvale/examples/basics/ex5_nomesh.py +24 -0
- pyvale/examples/dic/ex1_2_blenderdeformed.py +174 -0
- pyvale/examples/dic/ex1_region_of_interest.py +6 -3
- pyvale/examples/dic/ex2_plate_with_hole.py +21 -18
- pyvale/examples/dic/ex3_plate_with_hole_strain.py +8 -6
- pyvale/examples/dic/ex4_dic_blender.py +17 -15
- pyvale/examples/dic/ex5_dic_challenge.py +19 -14
- pyvale/examples/genanalyticdata/ex1_1_scalarvisualisation.py +16 -10
- pyvale/examples/genanalyticdata/ex1_2_scalarcasebuild.py +3 -3
- pyvale/examples/genanalyticdata/ex2_1_analyticsensors.py +29 -23
- pyvale/examples/genanalyticdata/ex2_2_analyticsensors_nomesh.py +67 -0
- pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +12 -9
- pyvale/examples/mooseherder/ex0_create_moose_config.py +65 -0
- pyvale/examples/mooseherder/ex1a_modify_moose_input.py +71 -0
- pyvale/examples/mooseherder/ex1b_modify_gmsh_input.py +69 -0
- pyvale/examples/mooseherder/ex2a_run_moose_once.py +80 -0
- pyvale/examples/mooseherder/ex2b_run_gmsh_once.py +64 -0
- pyvale/examples/mooseherder/ex2c_run_both_once.py +114 -0
- pyvale/examples/mooseherder/ex3_run_moose_seq_para.py +157 -0
- pyvale/examples/mooseherder/ex4_run_gmsh-moose_seq_para.py +176 -0
- pyvale/examples/mooseherder/ex5_run_moose_paramulti.py +136 -0
- pyvale/examples/mooseherder/ex6_read_moose_exodus.py +163 -0
- pyvale/examples/mooseherder/ex7a_read_moose_herd_results.py +153 -0
- pyvale/examples/mooseherder/ex7b_read_multi_herd_results.py +116 -0
- pyvale/examples/mooseherder/ex7c_read_multi_gmshmoose_results.py +127 -0
- pyvale/examples/mooseherder/ex7d_readconfig_multi_gmshmoose_results.py +143 -0
- pyvale/examples/mooseherder/ex8_read_existing_sweep_output.py +72 -0
- pyvale/examples/renderblender/ex1_1_blenderscene.py +24 -20
- pyvale/examples/renderblender/ex1_2_blenderdeformed.py +22 -18
- pyvale/examples/renderblender/ex2_1_stereoscene.py +36 -29
- pyvale/examples/renderblender/ex2_2_stereodeformed.py +26 -20
- pyvale/examples/renderblender/ex3_1_blendercalibration.py +24 -17
- pyvale/examples/renderrasterisation/ex_rastenp.py +14 -12
- pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +14 -15
- pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +13 -11
- pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +13 -11
- pyvale/mooseherder/__init__.py +32 -0
- pyvale/mooseherder/directorymanager.py +416 -0
- pyvale/mooseherder/exodusreader.py +763 -0
- pyvale/mooseherder/gmshrunner.py +163 -0
- pyvale/mooseherder/inputmodifier.py +236 -0
- pyvale/mooseherder/mooseconfig.py +226 -0
- pyvale/mooseherder/mooseherd.py +527 -0
- pyvale/mooseherder/mooserunner.py +303 -0
- pyvale/mooseherder/outputreader.py +22 -0
- pyvale/mooseherder/simdata.py +92 -0
- pyvale/mooseherder/simrunner.py +31 -0
- pyvale/mooseherder/sweepreader.py +356 -0
- pyvale/mooseherder/sweeptools.py +76 -0
- pyvale/sensorsim/__init__.py +82 -0
- pyvale/{camera.py → sensorsim/camera.py} +7 -7
- pyvale/{camerasensor.py → sensorsim/camerasensor.py} +7 -7
- pyvale/{camerastereo.py → sensorsim/camerastereo.py} +2 -2
- pyvale/{cameratools.py → sensorsim/cameratools.py} +4 -4
- pyvale/{cython → sensorsim/cython}/rastercyth.c +596 -596
- pyvale/{cython → sensorsim/cython}/rastercyth.cp311-win32.pyd +0 -0
- pyvale/{cython → sensorsim/cython}/rastercyth.py +16 -17
- pyvale/{errorcalculator.py → sensorsim/errorcalculator.py} +1 -1
- pyvale/{errorintegrator.py → sensorsim/errorintegrator.py} +2 -2
- pyvale/{errorrand.py → sensorsim/errorrand.py} +4 -4
- pyvale/{errorsyscalib.py → sensorsim/errorsyscalib.py} +2 -2
- pyvale/{errorsysdep.py → sensorsim/errorsysdep.py} +2 -2
- pyvale/{errorsysfield.py → sensorsim/errorsysfield.py} +8 -8
- pyvale/{errorsysindep.py → sensorsim/errorsysindep.py} +3 -3
- pyvale/sensorsim/exceptions.py +8 -0
- pyvale/{experimentsimulator.py → sensorsim/experimentsimulator.py} +23 -3
- pyvale/{field.py → sensorsim/field.py} +1 -1
- pyvale/{fieldconverter.py → sensorsim/fieldconverter.py} +72 -19
- pyvale/sensorsim/fieldinterp.py +37 -0
- pyvale/sensorsim/fieldinterpmesh.py +124 -0
- pyvale/sensorsim/fieldinterppoints.py +55 -0
- pyvale/{fieldsampler.py → sensorsim/fieldsampler.py} +4 -4
- pyvale/{fieldscalar.py → sensorsim/fieldscalar.py} +28 -24
- pyvale/{fieldtensor.py → sensorsim/fieldtensor.py} +33 -31
- pyvale/{fieldvector.py → sensorsim/fieldvector.py} +33 -31
- pyvale/{imagedef2d.py → sensorsim/imagedef2d.py} +9 -5
- pyvale/{integratorfactory.py → sensorsim/integratorfactory.py} +6 -6
- pyvale/{integratorquadrature.py → sensorsim/integratorquadrature.py} +3 -3
- pyvale/{integratorrectangle.py → sensorsim/integratorrectangle.py} +3 -3
- pyvale/{integratorspatial.py → sensorsim/integratorspatial.py} +1 -1
- pyvale/{rastercy.py → sensorsim/rastercy.py} +5 -5
- pyvale/{rasternp.py → sensorsim/rasternp.py} +9 -9
- pyvale/{rasteropts.py → sensorsim/rasteropts.py} +1 -1
- pyvale/{renderer.py → sensorsim/renderer.py} +1 -1
- pyvale/{rendermesh.py → sensorsim/rendermesh.py} +5 -5
- pyvale/{renderscene.py → sensorsim/renderscene.py} +2 -2
- pyvale/{sensorarray.py → sensorsim/sensorarray.py} +1 -1
- pyvale/{sensorarrayfactory.py → sensorsim/sensorarrayfactory.py} +12 -12
- pyvale/{sensorarraypoint.py → sensorsim/sensorarraypoint.py} +10 -8
- pyvale/{sensordata.py → sensorsim/sensordata.py} +1 -1
- pyvale/{sensortools.py → sensorsim/sensortools.py} +2 -20
- pyvale/sensorsim/simtools.py +174 -0
- pyvale/{visualexpplotter.py → sensorsim/visualexpplotter.py} +3 -3
- pyvale/{visualimages.py → sensorsim/visualimages.py} +2 -2
- pyvale/{visualsimanimator.py → sensorsim/visualsimanimator.py} +4 -4
- pyvale/{visualsimplotter.py → sensorsim/visualsimplotter.py} +5 -5
- pyvale/{visualsimsensors.py → sensorsim/visualsimsensors.py} +12 -12
- pyvale/{visualtools.py → sensorsim/visualtools.py} +1 -1
- pyvale/{visualtraceplotter.py → sensorsim/visualtraceplotter.py} +2 -2
- pyvale/simcases/case17.geo +3 -0
- pyvale/simcases/case17.i +4 -4
- pyvale/simcases/run_1case.py +1 -9
- pyvale/simcases/run_all_cases.py +1 -1
- pyvale/simcases/run_build_case.py +1 -1
- pyvale/simcases/run_example_cases.py +1 -1
- pyvale/verif/__init__.py +12 -0
- pyvale/{analyticsimdatafactory.py → verif/analyticsimdatafactory.py} +2 -2
- pyvale/{analyticsimdatagenerator.py → verif/analyticsimdatagenerator.py} +2 -2
- pyvale/verif/psens.py +125 -0
- pyvale/verif/psensconst.py +18 -0
- pyvale/verif/psensmech.py +227 -0
- pyvale/verif/psensmultiphys.py +187 -0
- pyvale/verif/psensscalar.py +347 -0
- pyvale/verif/psenstensor.py +123 -0
- pyvale/verif/psensvector.py +116 -0
- {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/METADATA +6 -7
- pyvale-2025.8.1.dist-info/RECORD +260 -0
- pyvale/dataset.py +0 -415
- pyvale/simtools.py +0 -67
- pyvale-2025.7.2.dist-info/RECORD +0 -212
- /pyvale/{blendercalibrationdata.py → blender/blendercalibrationdata.py} +0 -0
- /pyvale/{dicchecks.py → dic/dicchecks.py} +0 -0
- /pyvale/{dicspecklegenerator.py → dic/dicspecklegenerator.py} +0 -0
- /pyvale/{dicspecklequality.py → dic/dicspecklequality.py} +0 -0
- /pyvale/{dicstrainresults.py → dic/dicstrainresults.py} +0 -0
- /pyvale/{cameradata.py → sensorsim/cameradata.py} +0 -0
- /pyvale/{cameradata2d.py → sensorsim/cameradata2d.py} +0 -0
- /pyvale/{errordriftcalc.py → sensorsim/errordriftcalc.py} +0 -0
- /pyvale/{fieldtransform.py → sensorsim/fieldtransform.py} +0 -0
- /pyvale/{generatorsrandom.py → sensorsim/generatorsrandom.py} +0 -0
- /pyvale/{imagetools.py → sensorsim/imagetools.py} +0 -0
- /pyvale/{integratortype.py → sensorsim/integratortype.py} +0 -0
- /pyvale/{output.py → sensorsim/output.py} +0 -0
- /pyvale/{raster.py → sensorsim/raster.py} +0 -0
- /pyvale/{sensordescriptor.py → sensorsim/sensordescriptor.py} +0 -0
- /pyvale/{visualimagedef.py → sensorsim/visualimagedef.py} +0 -0
- /pyvale/{visualopts.py → sensorsim/visualopts.py} +0 -0
- /pyvale/{analyticmeshgen.py → verif/analyticmeshgen.py} +0 -0
- {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/WHEEL +0 -0
- {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/licenses/LICENSE +0 -0
- {pyvale-2025.7.2.dist-info → pyvale-2025.8.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# pyvale: the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
# ==============================================================================
|
|
6
|
+
import os
|
|
7
|
+
import json
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from multiprocessing.pool import Pool
|
|
10
|
+
from pyvale.mooseherder.directorymanager import DirectoryManager
|
|
11
|
+
import pyvale.mooseherder.directorymanager as dm
|
|
12
|
+
from pyvale.mooseherder.exodusreader import ExodusReader
|
|
13
|
+
from pyvale.mooseherder.simdata import SimData, SimReadConfig
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class SweepReader:
|
|
17
|
+
"""Used to read the output from one or more calls to mooseherd.run_para().
|
|
18
|
+
has configurable options for reading in the variable sweep in parallel.
|
|
19
|
+
"""
|
|
20
|
+
def __init__(self,
|
|
21
|
+
dir_manager: DirectoryManager,
|
|
22
|
+
num_para_read: int = 1) -> None:
|
|
23
|
+
"""Construct the sweep reader with a directory manager and
|
|
24
|
+
the number of simulations to read in parallel.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
dir_manager : DirectoryManager
|
|
29
|
+
The directory manager as used by the mooseherd that ran the
|
|
30
|
+
simulation sweep.
|
|
31
|
+
num_para_read : int, optional
|
|
32
|
+
Number of simulation to read in parallel. Defaults to 1.
|
|
33
|
+
"""
|
|
34
|
+
self._dir_manager = dir_manager
|
|
35
|
+
self._output_files = list([])
|
|
36
|
+
self._n_para_read = num_para_read
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def read_output_file_key(self, sweep_iter: int) -> list[list[Path | None]]:
|
|
40
|
+
"""read_output_key: reads the output key json file produced by running
|
|
41
|
+
the variable sweep. The output key file maps which simulation were run
|
|
42
|
+
in a given sub directory.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
sweep_iter : int
|
|
47
|
+
sweep iteration to read. This is the number that
|
|
48
|
+
is appended to the output key file e.g. output-key-2.json for
|
|
49
|
+
the 2nd call to run_seq/para in the mooseherd.
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
list[list[Path]]
|
|
55
|
+
paths to the outputs from the variable sweep the
|
|
56
|
+
outer list is the simulation iteration and the inner list is
|
|
57
|
+
the position in the simulation chain.
|
|
58
|
+
|
|
59
|
+
"""
|
|
60
|
+
output_key = self._dir_manager.get_output_key_file(sweep_iter)
|
|
61
|
+
if not output_key.is_file():
|
|
62
|
+
raise FileNotFoundError(f'Output key file for sweep iteration {sweep_iter} not found at path: {output_key}')
|
|
63
|
+
|
|
64
|
+
with open(output_key, 'r', encoding='utf-8') as okf:
|
|
65
|
+
output_files = json.load(okf)
|
|
66
|
+
|
|
67
|
+
return dm.output_str_to_paths(output_files)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def read_all_output_file_keys(self) -> list[list[Path | None]]:
|
|
71
|
+
"""read_all_output_keys: as read_output_keys() but finds all output key
|
|
72
|
+
files in the first sub-directory and reads them.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
|
|
77
|
+
Returns
|
|
78
|
+
-------
|
|
79
|
+
list[list[Path]]
|
|
80
|
+
paths to the outputs from the variable sweep the
|
|
81
|
+
outer list is the simulation iteration and the inner list is
|
|
82
|
+
the position in the simulation chain.
|
|
83
|
+
|
|
84
|
+
Raises
|
|
85
|
+
------
|
|
86
|
+
FileNotFoundError
|
|
87
|
+
No output key files found in the first sub-
|
|
88
|
+
directory.
|
|
89
|
+
|
|
90
|
+
"""
|
|
91
|
+
output_paths = self._find_files_by_str(self._dir_manager.get_output_key_tag(),
|
|
92
|
+
self._dir_manager.get_run_dir(0))
|
|
93
|
+
|
|
94
|
+
if len(output_paths) == 0:
|
|
95
|
+
raise FileNotFoundError("No output key json files found.")
|
|
96
|
+
|
|
97
|
+
output_files = list([])
|
|
98
|
+
for output_path in output_paths:
|
|
99
|
+
sweep_iter = output_path.name.split('.')[0].split('-')[-1]
|
|
100
|
+
output_files = output_files + self.read_output_file_key(int(sweep_iter))
|
|
101
|
+
|
|
102
|
+
self._output_files = output_files
|
|
103
|
+
return self._output_files
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def read_sweep_var_file(self, sweep_iter: int = 1
|
|
107
|
+
) -> list[list[dict | None]]:
|
|
108
|
+
"""read_sweep_var_file: reads the file containing the sweep variable
|
|
109
|
+
dictionary for a given sweep iteration and returns it.
|
|
110
|
+
|
|
111
|
+
Parameters
|
|
112
|
+
----------
|
|
113
|
+
sweep_iter : int
|
|
114
|
+
The sweep iteration (i.e. the call
|
|
115
|
+
number to mooseher.run_seq/para) Defaults to 1.
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
list[list[dict | None]]
|
|
120
|
+
The sweep variables as passed to mooseherd
|
|
121
|
+
.run_seq/para.
|
|
122
|
+
|
|
123
|
+
Raises
|
|
124
|
+
------
|
|
125
|
+
FileNotFoundError
|
|
126
|
+
Sweep file not found.
|
|
127
|
+
|
|
128
|
+
"""
|
|
129
|
+
sweep_var_file = self._dir_manager.get_sweep_var_file(sweep_iter)
|
|
130
|
+
if not sweep_var_file.is_file():
|
|
131
|
+
raise FileNotFoundError(
|
|
132
|
+
f'Sweep variable file for sweep iteration {sweep_iter}'+
|
|
133
|
+
f'not found at path: {sweep_var_file}')
|
|
134
|
+
|
|
135
|
+
with open(sweep_var_file, 'r', encoding='utf-8') as svf:
|
|
136
|
+
sweep_vars = json.load(svf)
|
|
137
|
+
|
|
138
|
+
return sweep_vars
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def read_all_sweep_var_files(self) -> list[list[dict | None]]:
|
|
142
|
+
"""read_all_sweep_var_files: as read sweep variables but finds all
|
|
143
|
+
sweep variables in the first sub-directory and reads them.
|
|
144
|
+
|
|
145
|
+
Parameters
|
|
146
|
+
----------
|
|
147
|
+
|
|
148
|
+
Returns
|
|
149
|
+
-------
|
|
150
|
+
list[list[dict | None]]
|
|
151
|
+
The sweep variables as passed to mooseherd
|
|
152
|
+
.run_seq/para. Additional sweep iterations are appended to the
|
|
153
|
+
end of the list.
|
|
154
|
+
|
|
155
|
+
Raises
|
|
156
|
+
------
|
|
157
|
+
FileNotFoundError
|
|
158
|
+
No sweep variable files found.
|
|
159
|
+
|
|
160
|
+
"""
|
|
161
|
+
sweep_var_paths = self._find_files_by_str(self._dir_manager.get_sweep_var_tag(),
|
|
162
|
+
self._dir_manager.get_run_dir(0))
|
|
163
|
+
|
|
164
|
+
if len(sweep_var_paths) == 0:
|
|
165
|
+
raise FileNotFoundError("No sweep variable json files found.")
|
|
166
|
+
|
|
167
|
+
sweep_vars = list([])
|
|
168
|
+
for ii,_ in enumerate(sweep_var_paths):
|
|
169
|
+
sweep_vars = sweep_vars + self.read_sweep_var_file(ii+1)
|
|
170
|
+
|
|
171
|
+
return sweep_vars
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _find_files_by_str(self, search_str: str, search_path: Path
|
|
175
|
+
) -> list[Path]:
|
|
176
|
+
"""_find_files_by_str: helper function for finding output key and sweep
|
|
177
|
+
variable files based on a specific string.
|
|
178
|
+
|
|
179
|
+
Parameters
|
|
180
|
+
----------
|
|
181
|
+
search_str : str
|
|
182
|
+
the string to find in the file name.
|
|
183
|
+
search_path : Path
|
|
184
|
+
the path to the directory to search for files
|
|
185
|
+
containing the specified string.
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
Returns
|
|
189
|
+
-------
|
|
190
|
+
list[Path]
|
|
191
|
+
list of paths to the files found with the string.
|
|
192
|
+
|
|
193
|
+
"""
|
|
194
|
+
found_files = list([])
|
|
195
|
+
|
|
196
|
+
all_files = os.listdir(search_path)
|
|
197
|
+
|
|
198
|
+
for ff in all_files:
|
|
199
|
+
if search_str in ff:
|
|
200
|
+
found_files.append(Path(ff))
|
|
201
|
+
|
|
202
|
+
found_files.sort()
|
|
203
|
+
|
|
204
|
+
return found_files
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def get_output_files(self) -> list[list[Path | None]]:
|
|
208
|
+
"""get_output_files
|
|
209
|
+
|
|
210
|
+
Parameters
|
|
211
|
+
----------
|
|
212
|
+
|
|
213
|
+
Returns
|
|
214
|
+
-------
|
|
215
|
+
list[list[Path]]
|
|
216
|
+
returns the paths to the output files as read
|
|
217
|
+
from the output key files.
|
|
218
|
+
|
|
219
|
+
"""
|
|
220
|
+
return self._output_files
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def read_results_once(self,
|
|
224
|
+
output_files: list[Path | None],
|
|
225
|
+
read_config: SimReadConfig | None = None
|
|
226
|
+
) -> list[SimData | None]:
|
|
227
|
+
"""read_results_once: reads a specific simulation at the specified
|
|
228
|
+
path based on the specified read configuration. If the read
|
|
229
|
+
configuration is None then read everything.
|
|
230
|
+
|
|
231
|
+
Parameters
|
|
232
|
+
----------
|
|
233
|
+
output_file : list[Path | None] :
|
|
234
|
+
Path to the file to read
|
|
235
|
+
read_config : SimReadConfig | None
|
|
236
|
+
class to specify the data to read
|
|
237
|
+
|
|
238
|
+
Returns
|
|
239
|
+
-------
|
|
240
|
+
list[SimData | None]
|
|
241
|
+
list of data classes holding the simulation
|
|
242
|
+
data for each simulation in the chain. Will be None for a pre-
|
|
243
|
+
processor like Gmsh that has not output.
|
|
244
|
+
|
|
245
|
+
"""
|
|
246
|
+
data_list = list([])
|
|
247
|
+
|
|
248
|
+
for ff in output_files:
|
|
249
|
+
if ff is None:
|
|
250
|
+
data_list.append(None)
|
|
251
|
+
else:
|
|
252
|
+
#TODO: replace with output reader ABC
|
|
253
|
+
reader = ExodusReader(ff)
|
|
254
|
+
if read_config is None:
|
|
255
|
+
data_list.append(reader.read_all_sim_data())
|
|
256
|
+
else:
|
|
257
|
+
data_list.append(reader.read_sim_data(read_config))
|
|
258
|
+
|
|
259
|
+
return data_list
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def read_sequential(self,
|
|
263
|
+
sweep_iter: int | None = None,
|
|
264
|
+
read_config: SimReadConfig | None = None
|
|
265
|
+
) -> list[list[SimData]]:
|
|
266
|
+
"""read_results_sequential: reads the variable sweep results
|
|
267
|
+
sequentially. Can read a specific iteration with a specific read config
|
|
268
|
+
but defaults to reading everything found in the simulation directories.
|
|
269
|
+
|
|
270
|
+
Parameters
|
|
271
|
+
----------
|
|
272
|
+
sweep_iter : int | None
|
|
273
|
+
sweep iteration number to read.
|
|
274
|
+
Reads the output key file for this iteration. Defaults to None.
|
|
275
|
+
read_config : SimReadConfig | None
|
|
276
|
+
object for specifying
|
|
277
|
+
which variables are to be extracted from the output. Defaults
|
|
278
|
+
to None.
|
|
279
|
+
|
|
280
|
+
Returns
|
|
281
|
+
-------
|
|
282
|
+
list[list[SimData]]
|
|
283
|
+
list of lists of SimData objects containing the
|
|
284
|
+
simulation results corresponding to each combination of
|
|
285
|
+
variables.
|
|
286
|
+
|
|
287
|
+
"""
|
|
288
|
+
self._start_read_output_keys(sweep_iter)
|
|
289
|
+
|
|
290
|
+
sweep_results = list([])
|
|
291
|
+
for ii,ff in enumerate(self._output_files):
|
|
292
|
+
sweep_results.append(self.read_results_once(ff,read_config))
|
|
293
|
+
|
|
294
|
+
return sweep_results
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def read_results_para(self,
|
|
298
|
+
sweep_iter: int | None = None,
|
|
299
|
+
read_config: SimReadConfig | None = None
|
|
300
|
+
) -> list[list[SimData]]:
|
|
301
|
+
"""read_results_para: reads the variable sweep results in parallel
|
|
302
|
+
Can read a specific iteration with a specific read config but defaults
|
|
303
|
+
to reading everything found in the simulation directories.
|
|
304
|
+
|
|
305
|
+
Parameters
|
|
306
|
+
----------
|
|
307
|
+
sweep_iter : int | None
|
|
308
|
+
sweep iteration number to read.
|
|
309
|
+
Reads the output key file for this iteration. Defaults to None.
|
|
310
|
+
read_config : SimReadConfig | None
|
|
311
|
+
object for specifying
|
|
312
|
+
which variables are to be extracted from the output. Defaults
|
|
313
|
+
to None.
|
|
314
|
+
|
|
315
|
+
Returns
|
|
316
|
+
-------
|
|
317
|
+
list[list[SimData]]
|
|
318
|
+
list of lists of SimData objects containing the
|
|
319
|
+
simulation results corresponding to each combination of
|
|
320
|
+
variables.
|
|
321
|
+
|
|
322
|
+
"""
|
|
323
|
+
self._start_read_output_keys(sweep_iter)
|
|
324
|
+
|
|
325
|
+
with Pool(self._n_para_read) as pool:
|
|
326
|
+
processes = list([])
|
|
327
|
+
for ff in self._output_files:
|
|
328
|
+
processes.append(pool.apply_async(
|
|
329
|
+
self.read_results_once, args=(ff,read_config)))
|
|
330
|
+
|
|
331
|
+
sweep_results = [pp.get() for pp in processes]
|
|
332
|
+
|
|
333
|
+
return sweep_results
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def _start_read_output_keys(self, sweep_iter: int | None):
|
|
337
|
+
"""_start_read: helper function to read the output keys for a specific
|
|
338
|
+
simulation iteration prior to reading the simulation outputs.
|
|
339
|
+
|
|
340
|
+
Parameters
|
|
341
|
+
----------
|
|
342
|
+
sweep_iter : int | None
|
|
343
|
+
sweep iteration number to read. If None
|
|
344
|
+
read all of the output keys.
|
|
345
|
+
|
|
346
|
+
Returns
|
|
347
|
+
-------
|
|
348
|
+
|
|
349
|
+
"""
|
|
350
|
+
if self._output_files == '':
|
|
351
|
+
self._output_files = self.read_output_file_key(sweep_iter=1)
|
|
352
|
+
|
|
353
|
+
if sweep_iter is None:
|
|
354
|
+
self.read_all_output_file_keys()
|
|
355
|
+
|
|
356
|
+
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# pyvale: the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
# ==============================================================================
|
|
6
|
+
from typing import Any
|
|
7
|
+
import itertools
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _single_sim_param_grid(in_params: dict[str,list[Any]] | None
|
|
11
|
+
) -> list[dict[str,Any]] | None:
|
|
12
|
+
"""Private helper function that unpacks the list inside each dictionary key
|
|
13
|
+
to find every possible unique combination of variables within each list.
|
|
14
|
+
This gives a list of dictionaries where the dictionary values are single
|
|
15
|
+
values not lists.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
in_params : dict[str,list[Any]] | None
|
|
20
|
+
Dictionary of lists keyed by the simulation variable name with lists
|
|
21
|
+
containing the parameters the will form the grid of combinations.
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
list[dict[str,Any]] | None
|
|
26
|
+
The list of unique dictionaries that have single values not lists.
|
|
27
|
+
"""
|
|
28
|
+
if in_params is None:
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
param_keys = in_params.keys()
|
|
32
|
+
param_vals = in_params.values()
|
|
33
|
+
param_combs = itertools.product(*param_vals)
|
|
34
|
+
|
|
35
|
+
params = []
|
|
36
|
+
for cc in param_combs:
|
|
37
|
+
this_params = dict(zip(param_keys,cc))
|
|
38
|
+
params.append(this_params)
|
|
39
|
+
|
|
40
|
+
return params
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def sweep_param_grid(in_params: list[dict[str,list[Any]] | None]
|
|
44
|
+
) -> list[list[dict[str,Any] | None]]:
|
|
45
|
+
"""Helper function for generating grid parameter sweeps for all possible
|
|
46
|
+
combinations of modified variables in the simulation chain.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
in_params : list[dict[str,list[Any]] | None]
|
|
51
|
+
List of the same length as the simulation input modifier/runner list
|
|
52
|
+
where each dictionary corresponds to the variables that will be modified
|
|
53
|
+
for the corresponding simulation tool. The variables should be keyed by
|
|
54
|
+
their string identigfier in the simulation input file and the list
|
|
55
|
+
should contain all unique values of the variables to analyse.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
list[list[dict[str,Any] | None]]
|
|
60
|
+
The outer list is for each unique parameter combination. The inner list
|
|
61
|
+
position corresponds to the simulation input modifier/runner position in
|
|
62
|
+
the simulation chain. The dictionary is then keyed by the variable name
|
|
63
|
+
in the corresponding input file and the unique value the variable takes
|
|
64
|
+
for this combination of parameters.
|
|
65
|
+
"""
|
|
66
|
+
param_grids = []
|
|
67
|
+
for pp in in_params:
|
|
68
|
+
this_params = _single_sim_param_grid(pp)
|
|
69
|
+
|
|
70
|
+
if this_params is None:
|
|
71
|
+
param_grids.append([None])
|
|
72
|
+
else:
|
|
73
|
+
param_grids.append(this_params)
|
|
74
|
+
|
|
75
|
+
sweep_params = [list(pp) for pp in itertools.product(*param_grids)]
|
|
76
|
+
return sweep_params
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# . the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
# ==============================================================================
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
The python validation engine (`.) is your virtual engineering laboratory:
|
|
9
|
+
An all-in-one package for sensor simulation, sensor uncertainty quantification,
|
|
10
|
+
sensor placement optimisation and simulation calibration/validation. Used to
|
|
11
|
+
simulate experimental data from an input multi-physics simulation by explicitly
|
|
12
|
+
modelling sensors with realistic uncertainties. Useful for experimental design,
|
|
13
|
+
sensor placement optimisation, testing simulation validation metrics and
|
|
14
|
+
virtually testing digital shadows/twins.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# NOTE: this simplifies and decouples how the user calls .from the
|
|
18
|
+
# underlying project structure: the user should be able to use '.'
|
|
19
|
+
# and access everything in one layer without multiple import dots
|
|
20
|
+
|
|
21
|
+
from .field import *
|
|
22
|
+
from .fieldscalar import *
|
|
23
|
+
from .fieldvector import *
|
|
24
|
+
from .fieldtensor import *
|
|
25
|
+
from .fieldconverter import *
|
|
26
|
+
from .fieldtransform import *
|
|
27
|
+
from .fieldinterp import *
|
|
28
|
+
from .fieldinterpmesh import *
|
|
29
|
+
from .fieldinterppoints import*
|
|
30
|
+
|
|
31
|
+
from .integratorspatial import *
|
|
32
|
+
from .integratorquadrature import *
|
|
33
|
+
from .integratorrectangle import *
|
|
34
|
+
from .integratorfactory import *
|
|
35
|
+
|
|
36
|
+
from .sensordescriptor import *
|
|
37
|
+
from .sensortools import *
|
|
38
|
+
from .sensorarray import *
|
|
39
|
+
from .sensorarrayfactory import *
|
|
40
|
+
from .sensorarraypoint import *
|
|
41
|
+
from .sensordata import *
|
|
42
|
+
|
|
43
|
+
from .camera import *
|
|
44
|
+
from .cameradata import *
|
|
45
|
+
from .cameradata2d import *
|
|
46
|
+
from .cameratools import *
|
|
47
|
+
from .camerastereo import *
|
|
48
|
+
|
|
49
|
+
from .rastercy import *
|
|
50
|
+
|
|
51
|
+
from .renderscene import *
|
|
52
|
+
from .rendermesh import *
|
|
53
|
+
from .rasternp import *
|
|
54
|
+
|
|
55
|
+
from .imagedef2d import *
|
|
56
|
+
|
|
57
|
+
from .errorintegrator import *
|
|
58
|
+
from .errorrand import *
|
|
59
|
+
from .errorsysindep import *
|
|
60
|
+
from .errorsysdep import *
|
|
61
|
+
from .errorsysfield import *
|
|
62
|
+
from .errorsyscalib import *
|
|
63
|
+
from .errordriftcalc import *
|
|
64
|
+
|
|
65
|
+
from .generatorsrandom import *
|
|
66
|
+
|
|
67
|
+
from .visualopts import *
|
|
68
|
+
from .visualtools import *
|
|
69
|
+
from .visualsimsensors import *
|
|
70
|
+
from .visualsimanimator import *
|
|
71
|
+
from .visualexpplotter import *
|
|
72
|
+
from .visualtraceplotter import *
|
|
73
|
+
from .visualimages import *
|
|
74
|
+
from .visualimagedef import *
|
|
75
|
+
|
|
76
|
+
from .simtools import *
|
|
77
|
+
|
|
78
|
+
from .experimentsimulator import *
|
|
79
|
+
from .output import *
|
|
80
|
+
from .exceptions import *
|
|
81
|
+
|
|
82
|
+
|
|
@@ -9,13 +9,13 @@ NOTE: This module is a feature under developement.
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
import numpy as np
|
|
12
|
-
from pyvale.field import IField
|
|
13
|
-
from pyvale.sensorarray import ISensorArray
|
|
14
|
-
from pyvale.errorintegrator import ErrIntegrator
|
|
15
|
-
from pyvale.sensordescriptor import SensorDescriptor
|
|
16
|
-
from pyvale.fieldsampler import sample_field_with_sensor_data
|
|
17
|
-
from pyvale.cameradata2d import CameraData2D
|
|
18
|
-
from pyvale.cameratools import CameraTools
|
|
12
|
+
from pyvale.sensorsim.field import IField
|
|
13
|
+
from pyvale.sensorsim.sensorarray import ISensorArray
|
|
14
|
+
from pyvale.sensorsim.errorintegrator import ErrIntegrator
|
|
15
|
+
from pyvale.sensorsim.sensordescriptor import SensorDescriptor
|
|
16
|
+
from pyvale.sensorsim.fieldsampler import sample_field_with_sensor_data
|
|
17
|
+
from pyvale.sensorsim.cameradata2d import CameraData2D
|
|
18
|
+
from pyvale.sensorsim.cameratools import CameraTools
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
@@ -9,13 +9,13 @@ NOTE: This module is a feature under developement.
|
|
|
9
9
|
"""
|
|
10
10
|
|
|
11
11
|
import numpy as np
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
16
|
-
from
|
|
17
|
-
from
|
|
18
|
-
from
|
|
12
|
+
from pyavle.sensorsim.field import IField
|
|
13
|
+
from pyavle.sensorsim.sensorarray import ISensorArray
|
|
14
|
+
from pyavle.sensorsim.errorintegrator import ErrIntegrator
|
|
15
|
+
from pyavle.sensorsim.sensordescriptor import SensorDescriptor
|
|
16
|
+
from pyavle.sensorsim.fieldsampler import sample_field_with_sensor_data
|
|
17
|
+
from pyavle.sensorsim.cameradata2d import CameraData2D
|
|
18
|
+
from pyavle.sensorsim.cameratools import CameraTools
|
|
19
19
|
|
|
20
20
|
|
|
21
21
|
|
|
@@ -13,8 +13,8 @@ from pathlib import Path
|
|
|
13
13
|
import numpy as np
|
|
14
14
|
import yaml
|
|
15
15
|
from scipy.spatial.transform import Rotation
|
|
16
|
-
from pyvale.cameradata import CameraData
|
|
17
|
-
from pyvale.
|
|
16
|
+
from pyvale.sensorsim.cameradata import CameraData
|
|
17
|
+
from pyvale.blender.blenderexceptions import BlenderError
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class CameraStereo:
|
|
@@ -16,10 +16,10 @@ import copy
|
|
|
16
16
|
from scipy.spatial.transform import Rotation
|
|
17
17
|
import matplotlib.image as mplim
|
|
18
18
|
from PIL import Image
|
|
19
|
-
from pyvale.cameradata2d import CameraData2D
|
|
20
|
-
from pyvale.sensordata import SensorData
|
|
21
|
-
from pyvale.cameradata import CameraData
|
|
22
|
-
from pyvale.camerastereo import CameraStereo
|
|
19
|
+
from pyvale.sensorsim.cameradata2d import CameraData2D
|
|
20
|
+
from pyvale.sensorsim.sensordata import SensorData
|
|
21
|
+
from pyvale.sensorsim.cameradata import CameraData
|
|
22
|
+
from pyvale.sensorsim.camerastereo import CameraStereo
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class CameraTools:
|