pyvale 2025.5.3__cp311-cp311-win32.whl → 2025.7.0__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 -0
- pyvale/blendercalibrationdata.py +3 -1
- pyvale/blenderscene.py +7 -5
- pyvale/blendertools.py +27 -5
- pyvale/camera.py +1 -0
- pyvale/cameradata.py +3 -0
- pyvale/camerasensor.py +147 -0
- pyvale/camerastereo.py +4 -4
- pyvale/cameratools.py +23 -61
- pyvale/cython/rastercyth.c +1657 -1352
- pyvale/cython/rastercyth.cp311-win32.pyd +0 -0
- pyvale/cython/rastercyth.py +71 -26
- pyvale/data/plate_hole_def0000.tiff +0 -0
- pyvale/data/plate_hole_def0001.tiff +0 -0
- pyvale/data/plate_hole_ref0000.tiff +0 -0
- pyvale/data/plate_rigid_def0000.tiff +0 -0
- pyvale/data/plate_rigid_def0001.tiff +0 -0
- pyvale/data/plate_rigid_ref0000.tiff +0 -0
- pyvale/dataset.py +96 -6
- pyvale/dic/cpp/dicbruteforce.cpp +370 -0
- pyvale/dic/cpp/dicfourier.cpp +648 -0
- pyvale/dic/cpp/dicinterpolator.cpp +559 -0
- pyvale/dic/cpp/dicmain.cpp +215 -0
- pyvale/dic/cpp/dicoptimizer.cpp +675 -0
- pyvale/dic/cpp/dicrg.cpp +137 -0
- pyvale/dic/cpp/dicscanmethod.cpp +677 -0
- pyvale/dic/cpp/dicsmooth.cpp +138 -0
- pyvale/dic/cpp/dicstrain.cpp +383 -0
- pyvale/dic/cpp/dicutil.cpp +563 -0
- pyvale/dic2d.py +164 -0
- pyvale/dic2dcpp.cp311-win32.pyd +0 -0
- pyvale/dicchecks.py +476 -0
- pyvale/dicdataimport.py +247 -0
- pyvale/dicregionofinterest.py +887 -0
- pyvale/dicresults.py +55 -0
- pyvale/dicspecklegenerator.py +238 -0
- pyvale/dicspecklequality.py +305 -0
- pyvale/dicstrain.py +387 -0
- pyvale/dicstrainresults.py +37 -0
- pyvale/errorintegrator.py +10 -8
- pyvale/examples/basics/ex1_1_basicscalars_therm2d.py +124 -113
- pyvale/examples/basics/ex1_2_sensormodel_therm2d.py +124 -132
- pyvale/examples/basics/ex1_3_customsens_therm3d.py +199 -195
- pyvale/examples/basics/ex1_4_basicerrors_therm3d.py +125 -121
- pyvale/examples/basics/ex1_5_fielderrs_therm3d.py +145 -141
- pyvale/examples/basics/ex1_6_caliberrs_therm2d.py +96 -101
- pyvale/examples/basics/ex1_7_spatavg_therm2d.py +109 -105
- pyvale/examples/basics/ex2_1_basicvectors_disp2d.py +92 -91
- pyvale/examples/basics/ex2_2_vectorsens_disp2d.py +96 -90
- pyvale/examples/basics/ex2_3_sensangle_disp2d.py +88 -89
- pyvale/examples/basics/ex2_4_chainfielderrs_disp2d.py +172 -171
- pyvale/examples/basics/ex2_5_vectorfields3d_disp3d.py +88 -86
- pyvale/examples/basics/ex3_1_basictensors_strain2d.py +90 -90
- pyvale/examples/basics/ex3_2_tensorsens2d_strain2d.py +93 -91
- pyvale/examples/basics/ex3_3_tensorsens3d_strain3d.py +172 -160
- pyvale/examples/basics/ex4_1_expsim2d_thermmech2d.py +154 -148
- pyvale/examples/basics/ex4_2_expsim3d_thermmech3d.py +249 -231
- pyvale/examples/dic/ex1_region_of_interest.py +98 -0
- pyvale/examples/dic/ex2_plate_with_hole.py +149 -0
- pyvale/examples/dic/ex3_plate_with_hole_strain.py +93 -0
- pyvale/examples/dic/ex4_dic_blender.py +95 -0
- pyvale/examples/dic/ex5_dic_challenge.py +102 -0
- pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +4 -2
- pyvale/examples/renderblender/ex1_1_blenderscene.py +152 -105
- pyvale/examples/renderblender/ex1_2_blenderdeformed.py +151 -100
- pyvale/examples/renderblender/ex2_1_stereoscene.py +183 -116
- pyvale/examples/renderblender/ex2_2_stereodeformed.py +185 -112
- pyvale/examples/renderblender/ex3_1_blendercalibration.py +164 -109
- pyvale/examples/renderrasterisation/ex_rastenp.py +74 -35
- pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +6 -13
- pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +2 -2
- pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +2 -4
- pyvale/imagedef2d.py +3 -2
- pyvale/imagetools.py +137 -0
- pyvale/rastercy.py +34 -4
- pyvale/rasternp.py +300 -276
- pyvale/rasteropts.py +58 -0
- pyvale/renderer.py +47 -0
- pyvale/rendermesh.py +52 -62
- pyvale/renderscene.py +51 -0
- pyvale/sensorarrayfactory.py +2 -2
- pyvale/sensortools.py +19 -35
- pyvale/simcases/case21.i +1 -1
- pyvale/simcases/run_1case.py +8 -0
- pyvale/simtools.py +2 -2
- pyvale/visualsimplotter.py +180 -0
- {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/METADATA +11 -57
- {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/RECORD +91 -56
- {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/WHEEL +1 -1
- pyvale/examples/visualisation/ex1_1_plot_traces.py +0 -102
- pyvale/examples/visualisation/ex2_1_animate_sim.py +0 -89
- {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/licenses/LICENSE +0 -0
- {pyvale-2025.5.3.dist-info → pyvale-2025.7.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
#================================================================================
|
|
2
|
+
#Example: thermocouples on a 2d plate
|
|
3
|
+
#
|
|
4
|
+
#pyvale: the python validation engine
|
|
5
|
+
#License: MIT
|
|
6
|
+
#Copyright (C) 2024 The Computer Aided Validation Team
|
|
7
|
+
#================================================================================
|
|
8
|
+
"""
|
|
9
|
+
2D Plate with a Hole
|
|
10
|
+
---------------------
|
|
11
|
+
|
|
12
|
+
This example walks through setting up a DIC and strain calculation for the
|
|
13
|
+
classic "plate with a hole" problem. The images used are synthetically generated,
|
|
14
|
+
allowing for comparison to analytically known values.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
import matplotlib.pyplot as plt
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
import pyvale
|
|
20
|
+
|
|
21
|
+
# %%
|
|
22
|
+
# We'll start by defining some variables that will be reused throughout the example:
|
|
23
|
+
# the reference image, deformed image(s), and the subset size.
|
|
24
|
+
#
|
|
25
|
+
# If you're working with a series of deformed images, it's a good idea to place
|
|
26
|
+
# them in a separate folder or ensure they follow a consistent naming convention.
|
|
27
|
+
# In such cases, the wildcard operator `*` can be used to select multiple files.
|
|
28
|
+
#
|
|
29
|
+
# The images used here are included in the `data <https://github.com/Computer-Aided-Validation-Laboratory/pyvale/tree/main/src/pyvale/data>`_ folder.
|
|
30
|
+
# We've provided helper functions to load them regardless of your installation path.
|
|
31
|
+
subset_size = 31
|
|
32
|
+
ref_img = pyvale.DataSet.dic_plate_with_hole_ref()
|
|
33
|
+
def_img = pyvale.DataSet.dic_plate_with_hole_def()
|
|
34
|
+
|
|
35
|
+
# create a directory for the the different outputs
|
|
36
|
+
output_path = Path.cwd() / "pyvale-output"
|
|
37
|
+
if not output_path.is_dir():
|
|
38
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
39
|
+
|
|
40
|
+
# %%
|
|
41
|
+
# Next, we’ll select our Region of Interest (ROI) using the interactive tool.
|
|
42
|
+
# Create an instance of the ROI class and pass the reference image
|
|
43
|
+
# as input. This image will be shown as the underlay during any ROI selection or
|
|
44
|
+
# visualization.
|
|
45
|
+
roi = pyvale.DICRegionOfInterest(ref_img)
|
|
46
|
+
roi.interactive_selection(subset_size)
|
|
47
|
+
|
|
48
|
+
# %%
|
|
49
|
+
# Once you've closed the ROI interactive window, a mask and seed location coordinates
|
|
50
|
+
# will be generated. These are needed for the DIC engine.
|
|
51
|
+
#
|
|
52
|
+
# If you intend to reuse this ROI, it's a good idea to save it. For large images,
|
|
53
|
+
# setting `binary=True` is recommended to reduce file size and write time.
|
|
54
|
+
roi_file = output_path / "roi.dat"
|
|
55
|
+
roi.save_array(filename=roi_file, binary=False)
|
|
56
|
+
|
|
57
|
+
# %%
|
|
58
|
+
# To load a previously saved ROI for future use, use the `read_array` method.
|
|
59
|
+
# Make sure the filename and format (binary or human-readable) match what was saved.
|
|
60
|
+
roi.read_array(filename=roi_file, binary=False)
|
|
61
|
+
|
|
62
|
+
# %%
|
|
63
|
+
# Now we can run the 2D DIC engine using :func:`pyvale.dic_2d`.
|
|
64
|
+
#
|
|
65
|
+
# This function accepts many optional arguments — consult the documentation for full details.
|
|
66
|
+
# At a minimum, you’ll need to specify:
|
|
67
|
+
#
|
|
68
|
+
# - Reference image
|
|
69
|
+
# - Deformed image(s)
|
|
70
|
+
# - ROI mask
|
|
71
|
+
# - Seed coordinates (If using a Reliability Guided approach)
|
|
72
|
+
# - Subset size
|
|
73
|
+
#
|
|
74
|
+
# By default, the engine uses an affine shape function with the Zero Normalised
|
|
75
|
+
# Sum of Squared Differences (ZNSSD) correlation criterion.
|
|
76
|
+
#
|
|
77
|
+
# At present, the DIC engine doesn't return any results to the user, instead the results are saved to disk.
|
|
78
|
+
# You can customize the filename, location, format, and delimiter using
|
|
79
|
+
# 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:`pyvale.dic_2d`.
|
|
81
|
+
# By default, the results will be saved with the prefix `dic_results_` followed
|
|
82
|
+
# by the original filename. The file extension will be replaced will either ".csv" or "dic2d"
|
|
83
|
+
# depending on whether the results are being saved in human-readable or binary format.
|
|
84
|
+
pyvale.dic_2d(reference=ref_img,
|
|
85
|
+
deformed=def_img,
|
|
86
|
+
roi_mask=roi.mask,
|
|
87
|
+
seed=roi.seed,
|
|
88
|
+
subset_size=subset_size,
|
|
89
|
+
subset_step=10,
|
|
90
|
+
shape_function="AFFINE",
|
|
91
|
+
max_displacement=10,
|
|
92
|
+
correlation_criteria="ZNSSD",
|
|
93
|
+
output_basepath=output_path,
|
|
94
|
+
output_delimiter=",",
|
|
95
|
+
output_prefix="dic_results_")
|
|
96
|
+
|
|
97
|
+
# %%
|
|
98
|
+
# If you saved the results in a human-readable format, you can use any tool
|
|
99
|
+
# (e.g., Excel, Python, MATLAB) for post-processing.
|
|
100
|
+
#
|
|
101
|
+
# For convenience, we provide a utility function to import results back into Python
|
|
102
|
+
# for analysis and visualization: :func:`pyvale.dic_data_import`.
|
|
103
|
+
#
|
|
104
|
+
# The returned object is an instance of :class:`pyvale.DICResults`. If the results
|
|
105
|
+
# were saved in binary format or with a custom delimiter, be sure to specify those parameters.
|
|
106
|
+
dic_files = output_path / "dic_results_*.csv"
|
|
107
|
+
dicdata = pyvale.dic_data_import(data=dic_files, delimiter=",", binary=False)
|
|
108
|
+
|
|
109
|
+
# %%
|
|
110
|
+
# As an example, here's a simple visualization of the displacement (u, v) and
|
|
111
|
+
# correlation cost for the two deformed images using matplotlib. You'll need to
|
|
112
|
+
# ensure you have `matplotlib.pyplot` installed and imported.
|
|
113
|
+
fig, axes = plt.subplots(2, 3, figsize=(15, 5))
|
|
114
|
+
axes = axes.flatten()
|
|
115
|
+
|
|
116
|
+
# First deformation image
|
|
117
|
+
im1 = axes[0].pcolor(dicdata.ss_x, dicdata.ss_y, dicdata.u[0])
|
|
118
|
+
im2 = axes[1].pcolor(dicdata.ss_x, dicdata.ss_y, dicdata.v[0])
|
|
119
|
+
im3 = axes[2].pcolor(dicdata.ss_x, dicdata.ss_y, dicdata.cost[0])
|
|
120
|
+
|
|
121
|
+
# Second deformation image
|
|
122
|
+
im4 = axes[3].pcolor(dicdata.ss_x, dicdata.ss_y, dicdata.u[1])
|
|
123
|
+
im5 = axes[4].pcolor(dicdata.ss_x, dicdata.ss_y, dicdata.v[1])
|
|
124
|
+
im6 = axes[5].pcolor(dicdata.ss_x, dicdata.ss_y, dicdata.cost[1])
|
|
125
|
+
|
|
126
|
+
# Titles
|
|
127
|
+
axes[0].set_title('u component (def0000.tiff)')
|
|
128
|
+
axes[1].set_title('v component (def0000.tiff)')
|
|
129
|
+
axes[2].set_title('cost (def0000.tiff)')
|
|
130
|
+
axes[3].set_title('u component (def0001.tiff)')
|
|
131
|
+
axes[4].set_title('v component (def0001.tiff)')
|
|
132
|
+
axes[5].set_title('cost (def0001.tiff)')
|
|
133
|
+
|
|
134
|
+
# Colorbars
|
|
135
|
+
fig.colorbar(im1, ax=axes[0])
|
|
136
|
+
fig.colorbar(im2, ax=axes[1])
|
|
137
|
+
fig.colorbar(im3, ax=axes[2])
|
|
138
|
+
fig.colorbar(im4, ax=axes[3])
|
|
139
|
+
fig.colorbar(im5, ax=axes[4])
|
|
140
|
+
fig.colorbar(im6, ax=axes[5])
|
|
141
|
+
|
|
142
|
+
plt.tight_layout()
|
|
143
|
+
plt.show()
|
|
144
|
+
|
|
145
|
+
# %%
|
|
146
|
+
# .. image:: ../../../../_static/plate_with_hole.png
|
|
147
|
+
# :alt: Displacement and cost values
|
|
148
|
+
# :width: 800px
|
|
149
|
+
# :align: center
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# ================================================================================
|
|
2
|
+
# Example: DIC Challenge 2.0 Comparison
|
|
3
|
+
#
|
|
4
|
+
# pyvale: the python validation engine
|
|
5
|
+
# License: MIT
|
|
6
|
+
# Copyright (C) 2024 The Computer Aided Validation Team
|
|
7
|
+
# ================================================================================
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
Strain and Deformation Gradient Calculations
|
|
11
|
+
---------------------------------------------
|
|
12
|
+
|
|
13
|
+
This example follows on from the previous one. It assumes that the DIC results
|
|
14
|
+
have already been generated in the current working directory and are ready to
|
|
15
|
+
be used for strain calculations.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
import matplotlib.pyplot as plt
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
import pyvale
|
|
21
|
+
|
|
22
|
+
# %%
|
|
23
|
+
# We'll start by importing the DIC data from the previous example.
|
|
24
|
+
|
|
25
|
+
# create a directory for the the different outputs
|
|
26
|
+
output_path = Path.cwd() / "pyvale-output"
|
|
27
|
+
if not output_path.is_dir():
|
|
28
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
29
|
+
|
|
30
|
+
# specify where our input data is
|
|
31
|
+
input_data = output_path / "dic_results_*.csv"
|
|
32
|
+
|
|
33
|
+
# %%
|
|
34
|
+
# You can calculate strain directly from the DIC results.
|
|
35
|
+
# It's not necessary to load the data beforehand — you can simply pass the
|
|
36
|
+
# filename (or pattern) to the `data` argument. If you used a custom delimiter
|
|
37
|
+
# or saved in binary format, make sure to specify those as well.
|
|
38
|
+
|
|
39
|
+
# %%
|
|
40
|
+
# At a minimum, you need to specify the strain window size and the element type
|
|
41
|
+
# used within the window. The valid options for `window_element` are:
|
|
42
|
+
#
|
|
43
|
+
# - `4` for bilinear
|
|
44
|
+
# - `9` for biquadratic
|
|
45
|
+
#
|
|
46
|
+
# The output will always include the window coordinates and the full deformation
|
|
47
|
+
# gradient tensor. If you also specify a `strain_formulation`, the corresponding
|
|
48
|
+
# 2D strain tensor will be included in the output.
|
|
49
|
+
pyvale.strain_2d(data=input_data, window_size=5, window_element=4,
|
|
50
|
+
output_basepath=output_path)
|
|
51
|
+
|
|
52
|
+
# %%
|
|
53
|
+
# Once the strain calculation is complete, you can import the results using
|
|
54
|
+
# :func:`pyvale.strain_data_import`.
|
|
55
|
+
#
|
|
56
|
+
# Be sure to specify the delimiter, format (binary or not), and layout.
|
|
57
|
+
strain_output = output_path / "strain_dic_results_*.csv"
|
|
58
|
+
straindata = pyvale.strain_data_import(data=strain_output,
|
|
59
|
+
binary=False, delimiter=",",
|
|
60
|
+
layout="matrix")
|
|
61
|
+
|
|
62
|
+
# %%
|
|
63
|
+
# Here's a simple example of how to visualize the deformation gradient components
|
|
64
|
+
# for the first deformation step using matplotlib.
|
|
65
|
+
fig, axes = plt.subplots(2, 2, figsize=(15, 5))
|
|
66
|
+
axes = axes.flatten()
|
|
67
|
+
fig.suptitle('Deformation Gradient for ' + straindata.filenames[0])
|
|
68
|
+
|
|
69
|
+
im1 = axes[0].pcolor(straindata.window_x, straindata.window_y, straindata.def_grad[0, :, :, 0, 0])
|
|
70
|
+
im2 = axes[1].pcolor(straindata.window_x, straindata.window_y, straindata.def_grad[0, :, :, 0, 1])
|
|
71
|
+
im3 = axes[2].pcolor(straindata.window_x, straindata.window_y, straindata.def_grad[0, :, :, 1, 0])
|
|
72
|
+
im4 = axes[3].pcolor(straindata.window_x, straindata.window_y, straindata.def_grad[0, :, :, 1, 1])
|
|
73
|
+
|
|
74
|
+
# titles
|
|
75
|
+
axes[0].set_title('deformation gradient xx')
|
|
76
|
+
axes[1].set_title('deformation gradient xy')
|
|
77
|
+
axes[2].set_title('deformation gradient yx')
|
|
78
|
+
axes[3].set_title('deformation gradient yy')
|
|
79
|
+
|
|
80
|
+
# Colorbars
|
|
81
|
+
fig.colorbar(im1, ax=axes[0])
|
|
82
|
+
fig.colorbar(im2, ax=axes[1])
|
|
83
|
+
fig.colorbar(im3, ax=axes[2])
|
|
84
|
+
fig.colorbar(im4, ax=axes[3])
|
|
85
|
+
|
|
86
|
+
plt.tight_layout()
|
|
87
|
+
plt.show()
|
|
88
|
+
|
|
89
|
+
# %%
|
|
90
|
+
# .. image:: ../../../../_static/plate_with_hole_def_grad.png
|
|
91
|
+
# :alt: Displacement and cost values
|
|
92
|
+
# :width: 800px
|
|
93
|
+
# :align: center
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#================================================================================
|
|
2
|
+
#Example: DIC with images generated by blender
|
|
3
|
+
#
|
|
4
|
+
#pyvale: the python validation engine
|
|
5
|
+
#License: MIT
|
|
6
|
+
#Copyright (C) 2024 The Computer Aided Validation Team
|
|
7
|
+
#================================================================================
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
DIC with images generated from a virtual blender experiment
|
|
11
|
+
---------------------------------------------
|
|
12
|
+
|
|
13
|
+
This example looks at taking the virtual experiments conducted using the blender
|
|
14
|
+
module and taking it one step further and performing a DIC calculation on the
|
|
15
|
+
simulated data. For this to work, you'll need to complete the `2D image
|
|
16
|
+
deformation example <https://computer-aided-validation-laboratory.github.io/pyvale/examples/renderblender/ex1_2_blenderdeformed.html>`_ using the blender module first.
|
|
17
|
+
|
|
18
|
+
**We'd recommend downloading both examples (links can be
|
|
19
|
+
found at the bottom of each example) and placing them within the same folder on
|
|
20
|
+
your device. That way the relative file paths below will not need to be
|
|
21
|
+
changed.**
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import matplotlib.pyplot as plt
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
import numpy as np
|
|
27
|
+
import pyvale
|
|
28
|
+
import os
|
|
29
|
+
|
|
30
|
+
#subset size
|
|
31
|
+
subset_size = 21
|
|
32
|
+
|
|
33
|
+
# rename the reference image so that that we can distinguish between reference
|
|
34
|
+
# and deformed images
|
|
35
|
+
if os.path.exists("./blenderimages/blenderimage_0.tiff"):
|
|
36
|
+
os.rename("./blenderimages/blenderimage_0.tiff",
|
|
37
|
+
"./blenderimages/reference.tiff")
|
|
38
|
+
|
|
39
|
+
ref_img = "./blenderimages/reference.tiff"
|
|
40
|
+
def_img = "./blenderimages/blenderimage_*.tiff"
|
|
41
|
+
|
|
42
|
+
# Interactive ROI selection
|
|
43
|
+
roi = pyvale.DICRegionOfInterest(ref_img)
|
|
44
|
+
roi.interactive_selection(subset_size)
|
|
45
|
+
|
|
46
|
+
#output_path
|
|
47
|
+
output_path = Path.cwd() / "pyvale-output"
|
|
48
|
+
if not output_path.is_dir():
|
|
49
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
50
|
+
|
|
51
|
+
# DIC Calculation
|
|
52
|
+
pyvale.dic_2d(reference=ref_img,
|
|
53
|
+
deformed=def_img,
|
|
54
|
+
roi_mask=roi.mask,
|
|
55
|
+
seed=roi.seed,
|
|
56
|
+
subset_size=subset_size,
|
|
57
|
+
subset_step=10,
|
|
58
|
+
shape_function="AFFINE",
|
|
59
|
+
max_displacement=20,
|
|
60
|
+
correlation_criteria="ZNSSD",
|
|
61
|
+
output_basepath=output_path,
|
|
62
|
+
output_prefix="blender_dic_")
|
|
63
|
+
|
|
64
|
+
# Import the Results
|
|
65
|
+
data_path = output_path / "blender_dic_*.csv"
|
|
66
|
+
dicdata = pyvale.dic_data_import(data=data_path, delimiter=",",
|
|
67
|
+
layout='matrix', binary=False)
|
|
68
|
+
|
|
69
|
+
# %%
|
|
70
|
+
# As an example we can plot the v-component of displacement for each of the
|
|
71
|
+
# eight deformation images
|
|
72
|
+
|
|
73
|
+
# Setup plot
|
|
74
|
+
fig, axes = plt.subplots(2, 4, figsize=(15, 5))
|
|
75
|
+
axes = axes.flatten()
|
|
76
|
+
|
|
77
|
+
# Compute global min and max for consistent color scaling
|
|
78
|
+
vmin = np.nanmin(dicdata.v)
|
|
79
|
+
vmax = np.nanmax(dicdata.v)
|
|
80
|
+
print(vmin,vmax)
|
|
81
|
+
|
|
82
|
+
# loop over images and add to subplots
|
|
83
|
+
for i in range(len(dicdata.filenames)):
|
|
84
|
+
im = axes[i].pcolor(dicdata.ss_x, dicdata.ss_y, dicdata.v[i], vmin=vmin, vmax=vmax)
|
|
85
|
+
axes[i].set_title(dicdata.filenames[i])
|
|
86
|
+
fig.colorbar(im, ax=axes[i])
|
|
87
|
+
|
|
88
|
+
plt.tight_layout()
|
|
89
|
+
plt.show()
|
|
90
|
+
|
|
91
|
+
# %%
|
|
92
|
+
# .. image:: ../../../../_static/dic_blender_plot.png
|
|
93
|
+
# :alt: DIC Comparison with ground truth
|
|
94
|
+
# :width: 800px
|
|
95
|
+
# :align: center
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# ================================================================================
|
|
2
|
+
# Example: DIC Challenge 2.0 Comparison
|
|
3
|
+
#
|
|
4
|
+
# pyvale: the python validation engine
|
|
5
|
+
# License: MIT
|
|
6
|
+
# Copyright (C) 2024 The Computer Aided Validation Team
|
|
7
|
+
# ================================================================================
|
|
8
|
+
|
|
9
|
+
"""
|
|
10
|
+
Comparison to the 2.0 2D DIC Challenge
|
|
11
|
+
---------------------------------------------
|
|
12
|
+
|
|
13
|
+
The DIC challenge provides a framework for comparison and validation of existing
|
|
14
|
+
DIC Codes. More information can be found at `https://idics.org/challenge/
|
|
15
|
+
<https://idics.org/challenge/>`_. In this example we look at a comparison to a
|
|
16
|
+
image generated with ±0.5 pixel sinusoidal vertical displacement amplitude “star”
|
|
17
|
+
pattern with varying spatial frequency. More information on the image creation
|
|
18
|
+
can be found in the `original paper
|
|
19
|
+
<https://link.springer.com/article/10.1007/s11340-021-00806-6>`_. In this
|
|
20
|
+
example we'll look at the convergence to the peak vertical discplacement value
|
|
21
|
+
of 0.5 pixels along a particular correlation direction.
|
|
22
|
+
|
|
23
|
+
As always, we'll start with importing the required libraries:
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
import matplotlib.pyplot as plt
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
import pyvale
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# %%
|
|
32
|
+
# There's a pair of DIC challenge images that come as part of the Pyvale install. We can preload them with:
|
|
33
|
+
ref_pattern = pyvale.DataSet.dic_challenge_ref()
|
|
34
|
+
def_pattern = pyvale.DataSet.dic_challenge_def()
|
|
35
|
+
subset_size = 17
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# %%
|
|
39
|
+
# we need to select our region of interest. For this example, we are only
|
|
40
|
+
# interested in the subsets along the mid horizontal line.
|
|
41
|
+
# We can use :func:`roi.rect_boundary` to exclude a large border region so we
|
|
42
|
+
# only correlate along the horizontal at the midpoint for our selected subset
|
|
43
|
+
# size
|
|
44
|
+
roi = pyvale.DICRegionOfInterest(ref_image=ref_pattern)
|
|
45
|
+
subset_radius = subset_size // 2
|
|
46
|
+
roi.rect_boundary(left=50,right=50,top=250-subset_radius,bottom=250-subset_radius)
|
|
47
|
+
roi.show_image()
|
|
48
|
+
|
|
49
|
+
# create a directory for the the different outputs
|
|
50
|
+
output_path = Path.cwd() / "pyvale-output"
|
|
51
|
+
if not output_path.is_dir():
|
|
52
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
53
|
+
|
|
54
|
+
# %%
|
|
55
|
+
# .. image:: ../../../../_static/dic_challenge_roi.png
|
|
56
|
+
# :alt: Selected roi
|
|
57
|
+
# :width: 800px
|
|
58
|
+
# :align: center
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# %%
|
|
62
|
+
# To perform the correlation we need to select a seed point. Ideally, this is
|
|
63
|
+
# somewhere in the region where the displacements are small with low noise.
|
|
64
|
+
# Here we'll select it to be [3500,250], which is close to the right hand
|
|
65
|
+
# boundary where the spatial frequency is lower. The results will be saved in
|
|
66
|
+
# the current working directory with a filename prefix of subset_size_19_*.txt
|
|
67
|
+
# If you are feeling adventorous you could investigate the effect of varying the
|
|
68
|
+
# subset size by placing the above and below sections in a loop.
|
|
69
|
+
pyvale.dic_2d(reference=ref_pattern,
|
|
70
|
+
deformed=def_pattern,
|
|
71
|
+
roi_mask=roi.mask,
|
|
72
|
+
subset_size=subset_size,
|
|
73
|
+
subset_step=1,
|
|
74
|
+
seed=[3500,250],
|
|
75
|
+
max_displacement=10,
|
|
76
|
+
output_basepath=output_path)
|
|
77
|
+
|
|
78
|
+
# %%
|
|
79
|
+
# We can import the results in the standard way
|
|
80
|
+
data_path = output_path / "dic_results_DIC_Challenge*.csv"
|
|
81
|
+
dicdata = pyvale.dic_data_import(data=data_path, layout='column',
|
|
82
|
+
binary=False, delimiter=",")
|
|
83
|
+
|
|
84
|
+
# &&
|
|
85
|
+
# Finally a simple plot of the calculated displacements at y=2500. This could be
|
|
86
|
+
# extended and compared to other DIC engines used in the 2.0 DIC challenge. A
|
|
87
|
+
# link to the dataset can be found under '2D-DIC Challenge 2.0' can be found
|
|
88
|
+
# at `https://idics.org/challenge/ <https://idics.org/challenge/>`_
|
|
89
|
+
plt.figure()
|
|
90
|
+
plt.xlabel("subset x location [px]")
|
|
91
|
+
plt.ylabel("Displacement [px]")
|
|
92
|
+
plt.grid(True)
|
|
93
|
+
plt.axhline(y=0.5, color='red', linestyle='--', linewidth=4)
|
|
94
|
+
plt.plot(dicdata.ss_x, dicdata.v[0,:])
|
|
95
|
+
plt.tight_layout()
|
|
96
|
+
plt.show()
|
|
97
|
+
|
|
98
|
+
# %%
|
|
99
|
+
# .. image:: ../../../../_static/dic_challenge_plot.png
|
|
100
|
+
# :alt: DIC Comparison with ground truth
|
|
101
|
+
# :width: 600px
|
|
102
|
+
# :align: center
|
|
@@ -16,9 +16,11 @@ def main() -> None:
|
|
|
16
16
|
sim_data = mh.ExodusReader(sim_path).read_all_sim_data()
|
|
17
17
|
|
|
18
18
|
image_path = pyv.DataSet.dic_pattern_5mpx_path()
|
|
19
|
-
image_speckle = pyv.
|
|
19
|
+
image_speckle = pyv.ImageTools.load_image_greyscale(image_path)
|
|
20
20
|
|
|
21
|
-
save_path = Path.cwd()/"
|
|
21
|
+
save_path = Path.cwd()/"pyvale-output"
|
|
22
|
+
if not save_path.is_dir():
|
|
23
|
+
save_path.mkdir(parents=True, exist_ok=True)
|
|
22
24
|
|
|
23
25
|
coords = sim_data.coords
|
|
24
26
|
connectivity = (sim_data.connect["connect1"]-1).T # Beware 0 indexing here
|