pyvale 2025.7.1__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.
- 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/dic/cpp/dicfourier.cpp +36 -4
- pyvale/dic/cpp/dicinterpolator.cpp +56 -1
- pyvale/dic/cpp/dicmain.cpp +24 -19
- pyvale/dic/cpp/dicoptimizer.cpp +6 -1
- pyvale/dic/cpp/dicscanmethod.cpp +32 -32
- pyvale/dic/cpp/dicsignalhandler.cpp +16 -0
- pyvale/dic/cpp/dicstrain.cpp +7 -3
- pyvale/dic/cpp/dicutil.cpp +79 -23
- pyvale/{dic2d.py → dic/dic2d.py} +51 -29
- pyvale/dic/dic2dconv.py +6 -0
- pyvale/dic/dic2dcpp.cp311-win_amd64.pyd +0 -0
- pyvale/{dicchecks.py → dic/dicchecks.py} +28 -16
- pyvale/dic/dicdataimport.py +370 -0
- pyvale/{dicregionofinterest.py → dic/dicregionofinterest.py} +169 -12
- pyvale/{dicresults.py → dic/dicresults.py} +4 -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-win_amd64.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.1.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/dic2dcpp.cp311-win_amd64.pyd +0 -0
- pyvale/dicdataimport.py +0 -247
- pyvale/simtools.py +0 -67
- pyvale-2025.7.1.dist-info/RECORD +0 -211
- /pyvale/{blendercalibrationdata.py → blender/blendercalibrationdata.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.1.dist-info → pyvale-2025.8.1.dist-info}/WHEEL +0 -0
- {pyvale-2025.7.1.dist-info → pyvale-2025.8.1.dist-info}/licenses/LICENSE +0 -0
- {pyvale-2025.7.1.dist-info → pyvale-2025.8.1.dist-info}/top_level.txt +0 -0
|
@@ -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
|