pyvale 2025.7.1__cp311-cp311-macosx_14_0_arm64.whl → 2025.8.1__cp311-cp311-macosx_14_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyvale might be problematic. Click here for more details.
- 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.cpython-311-darwin.so +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.cpython-311-darwin.so +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 +262 -0
- pyvale/dataset.py +0 -415
- pyvale/dic2dcpp.cpython-311-darwin.so +0 -0
- pyvale/dicdataimport.py +0 -247
- pyvale/simtools.py +0 -67
- pyvale-2025.7.1.dist-info/RECORD +0 -213
- /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
|
@@ -23,8 +23,11 @@ Test case: thermo-mechanical analysis of a 2D plate with a temperature gradient.
|
|
|
23
23
|
|
|
24
24
|
import numpy as np
|
|
25
25
|
import matplotlib.pyplot as plt
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
|
|
27
|
+
# Pyvale imports
|
|
28
|
+
import pyvale.mooseherder as mh
|
|
29
|
+
import pyvale.sensorsim as sens
|
|
30
|
+
import pyvale.dataset as dataset
|
|
28
31
|
|
|
29
32
|
#%%
|
|
30
33
|
# Here we get a list of paths to a set of 3 simulations in this case the
|
|
@@ -32,7 +35,7 @@ import pyvale as pyv
|
|
|
32
35
|
# coefficient on the other. The mechanical deformation is a result of
|
|
33
36
|
# thermal expansion. The 3 simulation cases cover a nominal thermal
|
|
34
37
|
# and a perturbation of +/-10%.
|
|
35
|
-
data_paths =
|
|
38
|
+
data_paths = dataset.thermomechanical_2d_experiment_paths()
|
|
36
39
|
elem_dims: int = 2
|
|
37
40
|
|
|
38
41
|
#%%
|
|
@@ -43,7 +46,7 @@ disp_comps = ("disp_x","disp_y")
|
|
|
43
46
|
sim_list = []
|
|
44
47
|
for pp in data_paths:
|
|
45
48
|
sim_data = mh.ExodusReader(pp).read_all_sim_data()
|
|
46
|
-
sim_data =
|
|
49
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
47
50
|
sim_data=sim_data,
|
|
48
51
|
disp_comps=disp_comps)
|
|
49
52
|
sim_list.append(sim_data)
|
|
@@ -60,10 +63,10 @@ n_sens = (4,1,1)
|
|
|
60
63
|
x_lims = (0.0,100.0)
|
|
61
64
|
y_lims = (0.0,50.0)
|
|
62
65
|
z_lims = (0.0,0.0)
|
|
63
|
-
tc_sens_pos =
|
|
66
|
+
tc_sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
64
67
|
|
|
65
|
-
tc_sens_data =
|
|
66
|
-
|
|
68
|
+
tc_sens_data = sens.SensorData(positions=tc_sens_pos,
|
|
69
|
+
sample_times=sample_times)
|
|
67
70
|
|
|
68
71
|
#%%
|
|
69
72
|
# We use the sensor array factory to give us thermocouples with basic 2%
|
|
@@ -72,7 +75,7 @@ tc_sens_data = pyv.SensorData(positions=tc_sens_pos,
|
|
|
72
75
|
# we run our experiment the field object that relies on this will switch the
|
|
73
76
|
# sim data for the required simulation in our list.
|
|
74
77
|
tc_field_name = "temperature"
|
|
75
|
-
tc_array =
|
|
78
|
+
tc_array = sens.SensorArrayFactory \
|
|
76
79
|
.thermocouples_basic_errs(sim_list[0],
|
|
77
80
|
tc_sens_data,
|
|
78
81
|
elem_dims=elem_dims,
|
|
@@ -82,8 +85,8 @@ tc_array = pyv.SensorArrayFactory \
|
|
|
82
85
|
#%%
|
|
83
86
|
# We place 3 strain gauges along the direction of the temperature gradient.
|
|
84
87
|
n_sens = (3,1,1)
|
|
85
|
-
sg_sens_pos =
|
|
86
|
-
sg_sens_data =
|
|
88
|
+
sg_sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
89
|
+
sg_sens_data = sens.SensorData(positions=sg_sens_pos,
|
|
87
90
|
sample_times=sample_times)
|
|
88
91
|
|
|
89
92
|
#%%
|
|
@@ -91,7 +94,7 @@ sg_sens_data = pyv.SensorData(positions=sg_sens_pos,
|
|
|
91
94
|
sg_field_name = "strain"
|
|
92
95
|
sg_norm_comps = ("strain_xx","strain_yy")
|
|
93
96
|
sg_dev_comps = ("strain_xy",)
|
|
94
|
-
sg_array =
|
|
97
|
+
sg_array = sens.SensorArrayFactory \
|
|
95
98
|
.strain_gauges_basic_errs(sim_list[0],
|
|
96
99
|
sg_sens_data,
|
|
97
100
|
elem_dims=elem_dims,
|
|
@@ -106,7 +109,7 @@ sg_array = pyv.SensorArrayFactory \
|
|
|
106
109
|
# use this to create an experiment simulator while specifying how many
|
|
107
110
|
# simulate experiments we want to run per simulation and sensor array.
|
|
108
111
|
sensor_arrays = [tc_array,sg_array]
|
|
109
|
-
exp_sim =
|
|
112
|
+
exp_sim = sens.ExperimentSimulator(sim_list,
|
|
110
113
|
sensor_arrays,
|
|
111
114
|
num_exp_per_sim=1000)
|
|
112
115
|
|
|
@@ -163,12 +166,12 @@ print(80*"=")
|
|
|
163
166
|
# deviation. In the next example we will see how to control these plots.
|
|
164
167
|
# For now we will plot the temperature traces for the first simulation and
|
|
165
168
|
# the strain traces for the third simulation in our list of SimData objects.
|
|
166
|
-
(fig,ax) =
|
|
169
|
+
(fig,ax) = sens.plot_exp_traces(exp_sim,
|
|
167
170
|
component="temperature",
|
|
168
171
|
sens_array_num=0,
|
|
169
172
|
sim_num=0)
|
|
170
173
|
|
|
171
|
-
(fig,ax) =
|
|
174
|
+
(fig,ax) = sens.plot_exp_traces(exp_sim,
|
|
172
175
|
component="strain_yy",
|
|
173
176
|
sens_array_num=1,
|
|
174
177
|
sim_num=2)
|
|
@@ -20,14 +20,17 @@ Test case: thermo-mechanical analysis of a divertor heatsink in 3D
|
|
|
20
20
|
from pathlib import Path
|
|
21
21
|
import numpy as np
|
|
22
22
|
import matplotlib.pyplot as plt
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
# Pyvale imports
|
|
25
|
+
import pyvale.mooseherder as mh
|
|
26
|
+
import pyvale.sensorsim as sens
|
|
27
|
+
import pyvale.dataset as dataset
|
|
25
28
|
|
|
26
29
|
#%%
|
|
27
30
|
# First we get the path to simulation output file and then read the
|
|
28
31
|
# simulation into a `SimData` object. In this case our simulation is a
|
|
29
32
|
# thermomechanical model of a divertor heatsink.
|
|
30
|
-
sim_path =
|
|
33
|
+
sim_path = dataset.thermomechanical_3d_path()
|
|
31
34
|
sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
|
|
32
35
|
elem_dims: int = 3
|
|
33
36
|
|
|
@@ -35,7 +38,7 @@ elem_dims: int = 3
|
|
|
35
38
|
# We scale our length and displacement units to mm to help with
|
|
36
39
|
# visualisation.
|
|
37
40
|
disp_comps = ("disp_x","disp_y","disp_z")
|
|
38
|
-
sim_data =
|
|
41
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
39
42
|
sim_data=sim_data,
|
|
40
43
|
disp_comps=disp_comps)
|
|
41
44
|
|
|
@@ -59,15 +62,15 @@ x_lims = (12.5,12.5)
|
|
|
59
62
|
y_lims = (0.0,33.0)
|
|
60
63
|
z_lims = (0.0,12.0)
|
|
61
64
|
n_sens = (1,4,1)
|
|
62
|
-
tc_sens_pos =
|
|
65
|
+
tc_sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
63
66
|
|
|
64
|
-
tc_sens_data =
|
|
67
|
+
tc_sens_data = sens.SensorData(positions=tc_sens_pos,
|
|
65
68
|
sample_times=sample_times)
|
|
66
69
|
#%%
|
|
67
70
|
# We use the sensor array factory to create our thermocouple array with no
|
|
68
71
|
# errors.
|
|
69
72
|
tc_field_name = "temperature"
|
|
70
|
-
tc_array =
|
|
73
|
+
tc_array = sens.SensorArrayFactory \
|
|
71
74
|
.thermocouples_no_errs(sim_data,
|
|
72
75
|
tc_sens_data,
|
|
73
76
|
elem_dims=elem_dims,
|
|
@@ -76,30 +79,30 @@ tc_array = pyv.SensorArrayFactory \
|
|
|
76
79
|
# Now we build our error chain starting with some basic errors on the order
|
|
77
80
|
# of 1 degree.
|
|
78
81
|
tc_err_chain = []
|
|
79
|
-
tc_err_chain.append(
|
|
80
|
-
tc_err_chain.append(
|
|
82
|
+
tc_err_chain.append(sens.ErrSysUnif(low=1.0,high=1.0))
|
|
83
|
+
tc_err_chain.append(sens.ErrRandNorm(std=1.0))
|
|
81
84
|
|
|
82
85
|
#%%
|
|
83
86
|
# Now we add positioning error for our thermocouples.
|
|
84
87
|
tc_pos_uncert = 0.1 # units = mm
|
|
85
|
-
tc_pos_rand = (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
tc_pos_rand = (sens.GenNormal(std=tc_pos_uncert),
|
|
89
|
+
sens.GenNormal(std=tc_pos_uncert),
|
|
90
|
+
sens.GenNormal(std=tc_pos_uncert))
|
|
88
91
|
|
|
89
92
|
#%%
|
|
90
93
|
# We block translation in x so the thermocouples stay attached.
|
|
91
94
|
tc_pos_lock = np.full(tc_sens_pos.shape,False,dtype=bool)
|
|
92
95
|
tc_pos_lock[:,0] = True
|
|
93
96
|
|
|
94
|
-
tc_field_err_data =
|
|
97
|
+
tc_field_err_data = sens.ErrFieldData(pos_rand_xyz=tc_pos_rand,
|
|
95
98
|
pos_lock_xyz=tc_pos_lock)
|
|
96
|
-
tc_err_chain.append(
|
|
99
|
+
tc_err_chain.append(sens.ErrSysField(tc_array.get_field(),
|
|
97
100
|
|
|
98
101
|
tc_field_err_data))
|
|
99
102
|
#%%
|
|
100
103
|
# We have finished our error chain so we can build our error integrator and
|
|
101
104
|
# attach it to our thermocouple array.
|
|
102
|
-
tc_error_int =
|
|
105
|
+
tc_error_int = sens.ErrIntegrator(tc_err_chain,
|
|
103
106
|
tc_sens_data,
|
|
104
107
|
tc_array.get_measurement_shape())
|
|
105
108
|
tc_array.set_error_integrator(tc_error_int)
|
|
@@ -107,7 +110,7 @@ tc_array.set_error_integrator(tc_error_int)
|
|
|
107
110
|
#%%
|
|
108
111
|
# We visualise our thermcouple locations on our mesh to make sure they are
|
|
109
112
|
# in the correct positions.
|
|
110
|
-
pv_plot =
|
|
113
|
+
pv_plot = sens.plot_point_sensors_on_sim(tc_array,"temperature")
|
|
111
114
|
pv_plot.camera_position = [(59.354, 43.428, 69.946),
|
|
112
115
|
(-2.858, 13.189, 4.523),
|
|
113
116
|
(-0.215, 0.948, -0.233)]
|
|
@@ -127,9 +130,9 @@ x_lims = (9.4,9.4)
|
|
|
127
130
|
y_lims = (0.0,33.0)
|
|
128
131
|
z_lims = (12.0,12.0)
|
|
129
132
|
n_sens = (1,4,1)
|
|
130
|
-
sg_sens_pos =
|
|
133
|
+
sg_sens_pos = sens.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
131
134
|
|
|
132
|
-
sg_sens_data =
|
|
135
|
+
sg_sens_data = sens.SensorData(positions=sg_sens_pos,
|
|
133
136
|
sample_times=sample_times)
|
|
134
137
|
|
|
135
138
|
#%%
|
|
@@ -138,7 +141,7 @@ sg_sens_data = pyv.SensorData(positions=sg_sens_pos,
|
|
|
138
141
|
sg_field_name = "strain"
|
|
139
142
|
sg_norm_comps = ("strain_xx","strain_yy","strain_zz")
|
|
140
143
|
sg_dev_comps = ("strain_xy","strain_yz","strain_xz")
|
|
141
|
-
sg_array =
|
|
144
|
+
sg_array = sens.SensorArrayFactory \
|
|
142
145
|
.strain_gauges_no_errs(sim_data,
|
|
143
146
|
sg_sens_data,
|
|
144
147
|
elem_dims=elem_dims,
|
|
@@ -150,30 +153,30 @@ sg_array = pyv.SensorArrayFactory \
|
|
|
150
153
|
# Now we build our error chain starting with some basic errors on the order
|
|
151
154
|
# of 1 percent.
|
|
152
155
|
sg_err_chain = []
|
|
153
|
-
sg_err_chain.append(
|
|
154
|
-
sg_err_chain.append(
|
|
156
|
+
sg_err_chain.append(sens.ErrSysUnifPercent(low_percent=1.0,high_percent=1.0))
|
|
157
|
+
sg_err_chain.append(sens.ErrRandNormPercent(std_percent=1.0))
|
|
155
158
|
|
|
156
159
|
#%%
|
|
157
160
|
# We are going to add +/-2 degree rotation uncertainty to our strain gauges.
|
|
158
161
|
angle_uncert = 2.0
|
|
159
|
-
angle_rand_zyx = (
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
angle_rand_zyx = (sens.GenUniform(low=-angle_uncert,high=angle_uncert), # units = deg
|
|
163
|
+
sens.GenUniform(low=-angle_uncert,high=angle_uncert),
|
|
164
|
+
sens.GenUniform(low=-angle_uncert,high=angle_uncert))
|
|
162
165
|
|
|
163
166
|
#%%
|
|
164
167
|
# We only allow rotation on the face the strain gauges are on
|
|
165
168
|
angle_lock = np.full(sg_sens_pos.shape,True,dtype=bool)
|
|
166
169
|
angle_lock[:,0] = False # Allow rotation about z
|
|
167
170
|
|
|
168
|
-
sg_field_err_data =
|
|
171
|
+
sg_field_err_data = sens.ErrFieldData(ang_rand_zyx=angle_rand_zyx,
|
|
169
172
|
ang_lock_zyx=angle_lock)
|
|
170
|
-
sg_err_chain.append(
|
|
173
|
+
sg_err_chain.append(sens.ErrSysField(sg_array.get_field(),
|
|
171
174
|
sg_field_err_data))
|
|
172
175
|
|
|
173
176
|
#%%
|
|
174
177
|
# We have finished our error chain so we can build our error integrator and
|
|
175
178
|
# attach it to our thermocouple array.
|
|
176
|
-
sg_error_int =
|
|
179
|
+
sg_error_int = sens.ErrIntegrator(sg_err_chain,
|
|
177
180
|
sg_sens_data,
|
|
178
181
|
sg_array.get_measurement_shape())
|
|
179
182
|
sg_array.set_error_integrator(sg_error_int)
|
|
@@ -181,7 +184,7 @@ sg_array.set_error_integrator(sg_error_int)
|
|
|
181
184
|
#%%
|
|
182
185
|
# Now we visualise the strain gauge locations to make sure they are where
|
|
183
186
|
# we expect them to be.
|
|
184
|
-
pv_plot =
|
|
187
|
+
pv_plot = sens.plot_point_sensors_on_sim(sg_array,"strain_yy")
|
|
185
188
|
pv_plot.camera_position = [(59.354, 43.428, 69.946),
|
|
186
189
|
(-2.858, 13.189, 4.523),
|
|
187
190
|
(-0.215, 0.948, -0.233)]
|
|
@@ -200,7 +203,7 @@ pv_plot.show()
|
|
|
200
203
|
# all points on the graph.
|
|
201
204
|
sim_list = [sim_data,]
|
|
202
205
|
sensor_arrays = [tc_array,sg_array]
|
|
203
|
-
exp_sim =
|
|
206
|
+
exp_sim = sens.ExperimentSimulator(sim_list,
|
|
204
207
|
sensor_arrays,
|
|
205
208
|
num_exp_per_sim=100)
|
|
206
209
|
|
|
@@ -246,11 +249,11 @@ print(80*"=")
|
|
|
246
249
|
# the median as the centre line and to fill between the min and max values.
|
|
247
250
|
# Note that the default here is to plot the mean and fill between 3 times
|
|
248
251
|
# the standard deviation.
|
|
249
|
-
trace_opts =
|
|
250
|
-
centre=
|
|
251
|
-
fill_between=
|
|
252
|
+
trace_opts = sens.TraceOptsExperiment(plot_all_exp_points=True,
|
|
253
|
+
centre=sens.EExpVisCentre.MEDIAN,
|
|
254
|
+
fill_between=sens.EExpVisBounds.MINMAX)
|
|
252
255
|
|
|
253
|
-
(fig,ax) =
|
|
256
|
+
(fig,ax) = sens.plot_exp_traces(exp_sim,
|
|
254
257
|
component="temperature",
|
|
255
258
|
sens_array_num=0,
|
|
256
259
|
sim_num=0,
|
|
@@ -259,7 +262,7 @@ if save_figs:
|
|
|
259
262
|
fig.savefig(fig_save_path/(save_tag+"_tc_traces.png"),
|
|
260
263
|
dpi=300, format='png', bbox_inches='tight')
|
|
261
264
|
|
|
262
|
-
(fig,ax) =
|
|
265
|
+
(fig,ax) = sens.plot_exp_traces(exp_sim,
|
|
263
266
|
component="strain_yy",
|
|
264
267
|
sens_array_num=1,
|
|
265
268
|
sim_num=0,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# pyvale: the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
# ==============================================================================
|
|
6
|
+
|
|
7
|
+
"""Basics: No mesh
|
|
8
|
+
================================================================================
|
|
9
|
+
|
|
10
|
+
TODO
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import numpy as np
|
|
14
|
+
import pyvale as pyv
|
|
15
|
+
|
|
16
|
+
# Build an analytic mesh in 2D and create a bi-linear field on the mesh
|
|
17
|
+
|
|
18
|
+
# Run normal pyvale to see output of a sensor array
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# pyvale: the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
# ==============================================================================
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
Deforming a sample with 2D DIC
|
|
9
|
+
===============================================
|
|
10
|
+
|
|
11
|
+
This example follows a similar workflow to the previous Blender example.
|
|
12
|
+
In this example, defomation is applied to sample, and images are rendered at
|
|
13
|
+
each timestep.
|
|
14
|
+
|
|
15
|
+
Test case: mechanical analysis of a plate with a hole loaded in tension.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import numpy as np
|
|
19
|
+
from scipy.spatial.transform import Rotation
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
# Pyvale imports
|
|
23
|
+
import pyvale.sensorsim as sens
|
|
24
|
+
import pyvale.dataset as dataset
|
|
25
|
+
import pyvale.blender as blender
|
|
26
|
+
import pyvale.mooseherder as mh
|
|
27
|
+
|
|
28
|
+
# %%
|
|
29
|
+
# The simulation results are loaded in here in the same way as the previous
|
|
30
|
+
# example. As mentioned this `data_path` can be replaced with your own MOOSE
|
|
31
|
+
# simulation output in exodus format (*.e).
|
|
32
|
+
|
|
33
|
+
data_path = dataset.render_mechanical_3d_path()
|
|
34
|
+
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
35
|
+
|
|
36
|
+
# %%
|
|
37
|
+
# This is then scaled to mm, as all lengths in Blender are to be set in mm.
|
|
38
|
+
# The `SimData` object is then converted into a `RenderMeshData` object, as
|
|
39
|
+
# this skins the mesh ready to be imported into Blender.
|
|
40
|
+
# The `disp_comps` are the expected direction of displacement. Since this is a
|
|
41
|
+
# 3D deformation test case, displacement is expected in the x, y and z directions.
|
|
42
|
+
|
|
43
|
+
disp_comps = ("disp_x","disp_y", "disp_z")
|
|
44
|
+
sim_data = sens.scale_length_units(scale=1000.0,
|
|
45
|
+
sim_data=sim_data,
|
|
46
|
+
disp_comps=disp_comps)
|
|
47
|
+
|
|
48
|
+
render_mesh = sens.create_render_mesh(sim_data,
|
|
49
|
+
("disp_y","disp_x"),
|
|
50
|
+
sim_spat_dim=3,
|
|
51
|
+
field_disp_keys=disp_comps)
|
|
52
|
+
|
|
53
|
+
# %%
|
|
54
|
+
# Firstly, a save path must be set.
|
|
55
|
+
# In order to do this a base path must be set. Then all the generated files will
|
|
56
|
+
# be saved to a subfolder within this specified base directory
|
|
57
|
+
# (e.g. blenderimages).
|
|
58
|
+
# If no base directory is specified, it will be set as your home directory.
|
|
59
|
+
|
|
60
|
+
base_dir = Path.cwd()
|
|
61
|
+
|
|
62
|
+
# %%
|
|
63
|
+
# Creating the scene
|
|
64
|
+
# ^^^^^^^^^^^^^^^^^^
|
|
65
|
+
# In order to create a DIC setup in Blender, first a scene must be created.
|
|
66
|
+
# A scene is initialised using the `BlenderScene` class. All the subsequent
|
|
67
|
+
# objects and actions necessary are then methods of this class.
|
|
68
|
+
|
|
69
|
+
scene = blender.Scene()
|
|
70
|
+
|
|
71
|
+
# %%
|
|
72
|
+
# The next thing that can be added to the scene is a sample.
|
|
73
|
+
# This is done by passing in the `RenderMeshData` object.
|
|
74
|
+
# It should be noted that the mesh will be centred on the origin to allow for
|
|
75
|
+
# the cameras to be centred on the mesh.
|
|
76
|
+
# Once the part is added to the Blender scene, it can be both moved and rotated.
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
part = scene.add_part(render_mesh, sim_spat_dim=3)
|
|
80
|
+
# Set the part location
|
|
81
|
+
part_location = np.array([0, 0, 0])
|
|
82
|
+
blender.Tools.move_blender_obj(part=part, pos_world=part_location)
|
|
83
|
+
part_rotation = Rotation.from_euler("xyz", [0, 0, 0], degrees=True)
|
|
84
|
+
blender.Tools.rotate_blender_obj(part=part, rot_world=part_rotation)
|
|
85
|
+
|
|
86
|
+
# %%
|
|
87
|
+
# A camera can then be added to the scene.
|
|
88
|
+
# To initialise a camera, the camera parameters must be specified using the
|
|
89
|
+
# `CameraData` dataclass. Note that all lengths / distances inputted are in mm.
|
|
90
|
+
# This camera can then be added to the Blender scene.
|
|
91
|
+
# The camera can also be moved and rotated.
|
|
92
|
+
|
|
93
|
+
cam_data = sens.CameraData(pixels_num=np.array([1540, 1040]),
|
|
94
|
+
pixels_size=np.array([0.00345, 0.00345]),
|
|
95
|
+
pos_world=(0, 0, 400),
|
|
96
|
+
rot_world=Rotation.from_euler("xyz", [0, 0, 0]),
|
|
97
|
+
roi_cent_world=(0, 0, 0),
|
|
98
|
+
focal_length=15.0)
|
|
99
|
+
camera = scene.add_camera(cam_data)
|
|
100
|
+
camera.location = (0, 0, 410)
|
|
101
|
+
camera.rotation_euler = (0, 0, 0) # NOTE: The default is an XYZ Euler angle
|
|
102
|
+
|
|
103
|
+
# %%
|
|
104
|
+
# A light can the be added to the scene.
|
|
105
|
+
# Blender offers different light types: Point, Sun, Spot and Area.
|
|
106
|
+
# The light can also be moved and rotated like the camera.
|
|
107
|
+
|
|
108
|
+
light_data = blender.LightData(type=blender.LightType.POINT,
|
|
109
|
+
pos_world=(0, 0, 400),
|
|
110
|
+
rot_world=Rotation.from_euler("xyz",
|
|
111
|
+
[0, 0, 0]),
|
|
112
|
+
energy=1)
|
|
113
|
+
light = scene.add_light(light_data)
|
|
114
|
+
light.location = (0, 0, 410)
|
|
115
|
+
light.rotation_euler = (0, 0, 0)
|
|
116
|
+
|
|
117
|
+
# %%
|
|
118
|
+
# A speckle pattern can then be applied to the sample.
|
|
119
|
+
# Firstly, the material properties of the sample must be specified, but these
|
|
120
|
+
# will all be defaulted if no inputs are provided.
|
|
121
|
+
#The speckle pattern can then be specified by providing a path to an image file
|
|
122
|
+
# with the pattern.
|
|
123
|
+
# The mm/px resolution of the camera must also be specified in order to
|
|
124
|
+
# correctly scale the speckle pattern.
|
|
125
|
+
# It should be noted that for a bigger camera or sample you may need to generate
|
|
126
|
+
# a larger speckle pattern.
|
|
127
|
+
|
|
128
|
+
material_data = blender.MaterialData()
|
|
129
|
+
speckle_path = dataset.dic_pattern_5mpx_path()
|
|
130
|
+
mm_px_resolution = sens.CameraTools.calculate_mm_px_resolution(cam_data)
|
|
131
|
+
scene.add_speckle(part=part,
|
|
132
|
+
speckle_path=speckle_path,
|
|
133
|
+
mat_data=material_data,
|
|
134
|
+
mm_px_resolution=mm_px_resolution)
|
|
135
|
+
|
|
136
|
+
# %%
|
|
137
|
+
# Deforming the sample and rendering images
|
|
138
|
+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
139
|
+
# Once all the objects have been added to the scene, the sample can be deformed,
|
|
140
|
+
# and images can be rendered.
|
|
141
|
+
# Firstly, all the rendering parameters must be set, including parameters such as
|
|
142
|
+
# the number of threads to use.
|
|
143
|
+
|
|
144
|
+
render_data = blender.RenderData(cam_data=cam_data,
|
|
145
|
+
base_dir=base_dir,
|
|
146
|
+
threads=8)
|
|
147
|
+
|
|
148
|
+
# %%
|
|
149
|
+
# A series of deformed images can then be rendered.
|
|
150
|
+
# This is done by passing in rendering parameters, as well as the
|
|
151
|
+
# `RenderMeshData` object, the part(sample) and the spatial dimension of the
|
|
152
|
+
# simulation.
|
|
153
|
+
# This will automatically deform the sample, and render subsequent images at
|
|
154
|
+
# each deformation timestep.
|
|
155
|
+
# If `stage_image` is set to True, the image will be saved to disk, converted to
|
|
156
|
+
# an array, deleted and the image array will be returned. This is due to the
|
|
157
|
+
# fact that an image cannot be saved directly as an array through Blender.
|
|
158
|
+
|
|
159
|
+
scene.render_deformed_images(render_mesh,
|
|
160
|
+
sim_spat_dim=3,
|
|
161
|
+
render_data=render_data,
|
|
162
|
+
part=part,
|
|
163
|
+
stage_image=False)
|
|
164
|
+
|
|
165
|
+
# %%
|
|
166
|
+
# The rendered image will be saved to this filepath:
|
|
167
|
+
|
|
168
|
+
print("Save directory of the image:", (render_data.base_dir / "blenderimages"))
|
|
169
|
+
|
|
170
|
+
# %%
|
|
171
|
+
# There is also the option to save the scene as a Blender project file.
|
|
172
|
+
# This file can be opened with the Blender GUI to view the scene.
|
|
173
|
+
|
|
174
|
+
blender.Tools.save_blender_file(base_dir)
|
|
@@ -15,14 +15,17 @@ This example looks at the current core functionality of the Region of Interest
|
|
|
15
15
|
"""
|
|
16
16
|
|
|
17
17
|
from pathlib import Path
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
# pyvale modules
|
|
20
|
+
import pyvale.dataset as dataset
|
|
21
|
+
import pyvale.dic as dic
|
|
19
22
|
|
|
20
23
|
# %%
|
|
21
24
|
# We'll begin by selecting our Region of Interest (ROI) using the interactive selection tool.
|
|
22
25
|
# First, we create an instance of the ROI class. We pass a reference image to it, which is
|
|
23
26
|
# displayed as the underlay during ROI selection.
|
|
24
|
-
ref_img =
|
|
25
|
-
roi =
|
|
27
|
+
ref_img = dataset.dic_plate_with_hole_ref()
|
|
28
|
+
roi = dic.RegionOfInterest(ref_image=ref_img)
|
|
26
29
|
roi.interactive_selection(subset_size=31)
|
|
27
30
|
|
|
28
31
|
# create a directory for the the different outputs
|
|
@@ -16,7 +16,10 @@ allowing for comparison to analytically known values.
|
|
|
16
16
|
|
|
17
17
|
import matplotlib.pyplot as plt
|
|
18
18
|
from pathlib import Path
|
|
19
|
-
|
|
19
|
+
|
|
20
|
+
# pyvale modules
|
|
21
|
+
import pyvale.dataset as dataset
|
|
22
|
+
import pyvale.dic as dic
|
|
20
23
|
|
|
21
24
|
# %%
|
|
22
25
|
# We'll start by defining some variables that will be reused throughout the example:
|
|
@@ -29,8 +32,8 @@ import pyvale
|
|
|
29
32
|
# The images used here are included in the `data <https://github.com/Computer-Aided-Validation-Laboratory/pyvale/tree/main/src/pyvale/data>`_ folder.
|
|
30
33
|
# We've provided helper functions to load them regardless of your installation path.
|
|
31
34
|
subset_size = 31
|
|
32
|
-
ref_img =
|
|
33
|
-
def_img =
|
|
35
|
+
ref_img = dataset.dic_plate_with_hole_ref()
|
|
36
|
+
def_img = dataset.dic_plate_with_hole_def()
|
|
34
37
|
|
|
35
38
|
# create a directory for the the different outputs
|
|
36
39
|
output_path = Path.cwd() / "pyvale-output"
|
|
@@ -42,7 +45,7 @@ if not output_path.is_dir():
|
|
|
42
45
|
# Create an instance of the ROI class and pass the reference image
|
|
43
46
|
# as input. This image will be shown as the underlay during any ROI selection or
|
|
44
47
|
# visualization.
|
|
45
|
-
roi =
|
|
48
|
+
roi = dic.RegionOfInterest(ref_img)
|
|
46
49
|
roi.interactive_selection(subset_size)
|
|
47
50
|
|
|
48
51
|
# %%
|
|
@@ -77,22 +80,22 @@ roi.read_array(filename=roi_file, binary=False)
|
|
|
77
80
|
# At present, the DIC engine doesn't return any results to the user, instead the results are saved to disk.
|
|
78
81
|
# You can customize the filename, location, format, and delimiter using
|
|
79
82
|
# the options options `output_basepath`, `output_prefix`, `output_delimiter`, and `output_binary`.
|
|
80
|
-
# More info on these options can be found in the documentation for :func:`
|
|
83
|
+
# More info on these options can be found in the documentation for :func:`dic.two_dimensional`.
|
|
81
84
|
# By default, the results will be saved with the prefix `dic_results_` followed
|
|
82
85
|
# by the original filename. The file extension will be replaced will either ".csv" or "dic2d"
|
|
83
86
|
# depending on whether the results are being saved in human-readable or binary format.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
87
|
+
dic.two_dimensional(reference=ref_img,
|
|
88
|
+
deformed=def_img,
|
|
89
|
+
roi_mask=roi.mask,
|
|
90
|
+
seed=roi.seed,
|
|
91
|
+
subset_size=subset_size,
|
|
92
|
+
subset_step=10,
|
|
93
|
+
shape_function="AFFINE",
|
|
94
|
+
max_displacement=10,
|
|
95
|
+
correlation_criteria="ZNSSD",
|
|
96
|
+
output_basepath=output_path,
|
|
97
|
+
output_delimiter=",",
|
|
98
|
+
output_prefix="dic_results_")
|
|
96
99
|
|
|
97
100
|
# %%
|
|
98
101
|
# If you saved the results in a human-readable format, you can use any tool
|
|
@@ -104,7 +107,7 @@ pyvale.dic_2d(reference=ref_img,
|
|
|
104
107
|
# The returned object is an instance of :class:`pyvale.DICResults`. If the results
|
|
105
108
|
# were saved in binary format or with a custom delimiter, be sure to specify those parameters.
|
|
106
109
|
dic_files = output_path / "dic_results_*.csv"
|
|
107
|
-
dicdata =
|
|
110
|
+
dicdata = dic.data_import(data=dic_files, delimiter=",", binary=False)
|
|
108
111
|
|
|
109
112
|
# %%
|
|
110
113
|
# As an example, here's a simple visualization of the displacement (u, v) and
|
|
@@ -17,7 +17,9 @@ be used for strain calculations.
|
|
|
17
17
|
|
|
18
18
|
import matplotlib.pyplot as plt
|
|
19
19
|
from pathlib import Path
|
|
20
|
-
|
|
20
|
+
|
|
21
|
+
# pyvale modules
|
|
22
|
+
import pyvale.dic as dic
|
|
21
23
|
|
|
22
24
|
# %%
|
|
23
25
|
# We'll start by importing the DIC data from the previous example.
|
|
@@ -46,8 +48,8 @@ input_data = output_path / "dic_results_*.csv"
|
|
|
46
48
|
# The output will always include the window coordinates and the full deformation
|
|
47
49
|
# gradient tensor. If you also specify a `strain_formulation`, the corresponding
|
|
48
50
|
# 2D strain tensor will be included in the output.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
+
dic.strain_two_dimensional(data=input_data, window_size=5, window_element=4,
|
|
52
|
+
output_basepath=output_path)
|
|
51
53
|
|
|
52
54
|
# %%
|
|
53
55
|
# Once the strain calculation is complete, you can import the results using
|
|
@@ -55,9 +57,9 @@ pyvale.strain_2d(data=input_data, window_size=5, window_element=4,
|
|
|
55
57
|
#
|
|
56
58
|
# Be sure to specify the delimiter, format (binary or not), and layout.
|
|
57
59
|
strain_output = output_path / "strain_dic_results_*.csv"
|
|
58
|
-
straindata =
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
straindata = dic.strain_data_import(data=strain_output,
|
|
61
|
+
binary=False, delimiter=",",
|
|
62
|
+
layout="matrix")
|
|
61
63
|
|
|
62
64
|
# %%
|
|
63
65
|
# Here's a simple example of how to visualize the deformation gradient components
|