pyvale 2025.4.1__py3-none-any.whl → 2025.5.1__py3-none-any.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 +18 -3
- pyvale/analyticmeshgen.py +1 -0
- pyvale/analyticsimdatafactory.py +18 -13
- pyvale/analyticsimdatagenerator.py +105 -72
- pyvale/blendercalibrationdata.py +15 -0
- pyvale/blenderlightdata.py +26 -0
- pyvale/blendermaterialdata.py +15 -0
- pyvale/blenderrenderdata.py +30 -0
- pyvale/blenderscene.py +488 -0
- pyvale/blendertools.py +420 -0
- pyvale/camera.py +6 -5
- pyvale/cameradata.py +25 -7
- pyvale/cameradata2d.py +6 -4
- pyvale/camerastereo.py +217 -0
- pyvale/cameratools.py +206 -11
- pyvale/cython/rastercyth.py +6 -2
- pyvale/data/cal_target.tiff +0 -0
- pyvale/dataset.py +73 -14
- pyvale/errorcalculator.py +8 -10
- pyvale/errordriftcalc.py +10 -9
- pyvale/errorintegrator.py +19 -21
- pyvale/errorrand.py +33 -39
- pyvale/errorsyscalib.py +134 -0
- pyvale/errorsysdep.py +19 -22
- pyvale/errorsysfield.py +49 -41
- pyvale/errorsysindep.py +79 -175
- pyvale/examples/basics/ex1_1_basicscalars_therm2d.py +131 -0
- pyvale/examples/basics/ex1_2_sensormodel_therm2d.py +158 -0
- pyvale/examples/basics/ex1_3_customsens_therm3d.py +216 -0
- pyvale/examples/basics/ex1_4_basicerrors_therm3d.py +153 -0
- pyvale/examples/basics/ex1_5_fielderrs_therm3d.py +168 -0
- pyvale/examples/basics/ex1_6_caliberrs_therm2d.py +133 -0
- pyvale/examples/basics/ex1_7_spatavg_therm2d.py +123 -0
- pyvale/examples/basics/ex2_1_basicvectors_disp2d.py +112 -0
- pyvale/examples/basics/ex2_2_vectorsens_disp2d.py +111 -0
- pyvale/examples/basics/ex2_3_sensangle_disp2d.py +139 -0
- pyvale/examples/basics/ex2_4_chainfielderrs_disp2d.py +196 -0
- pyvale/examples/basics/ex2_5_vectorfields3d_disp3d.py +109 -0
- pyvale/examples/basics/ex3_1_basictensors_strain2d.py +114 -0
- pyvale/examples/basics/ex3_2_tensorsens2d_strain2d.py +111 -0
- pyvale/examples/basics/ex3_3_tensorsens3d_strain3d.py +182 -0
- pyvale/examples/basics/ex4_1_expsim2d_thermmech2d.py +171 -0
- pyvale/examples/basics/ex4_2_expsim3d_thermmech3d.py +252 -0
- pyvale/examples/{analyticdatagen → genanalyticdata}/ex1_1_scalarvisualisation.py +6 -9
- pyvale/examples/{analyticdatagen → genanalyticdata}/ex1_2_scalarcasebuild.py +8 -11
- pyvale/examples/{analyticdatagen → genanalyticdata}/ex2_1_analyticsensors.py +9 -12
- pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +8 -15
- pyvale/examples/renderblender/ex1_1_blenderscene.py +121 -0
- pyvale/examples/renderblender/ex1_2_blenderdeformed.py +119 -0
- pyvale/examples/renderblender/ex2_1_stereoscene.py +128 -0
- pyvale/examples/renderblender/ex2_2_stereodeformed.py +131 -0
- pyvale/examples/renderblender/ex3_1_blendercalibration.py +120 -0
- pyvale/examples/{rasterisation → renderrasterisation}/ex_rastenp.py +3 -2
- pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_oneframe.py +2 -2
- pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_static_cypara.py +3 -8
- pyvale/examples/{rasterisation → renderrasterisation}/ex_rastercyth_static_pypara.py +6 -7
- pyvale/examples/{ex1_4_thermal2d.py → visualisation/ex1_1_plot_traces.py} +32 -16
- pyvale/examples/{features/ex_animation_tools_3dmonoblock.py → visualisation/ex2_1_animate_sim.py} +37 -31
- pyvale/experimentsimulator.py +107 -30
- pyvale/field.py +2 -9
- pyvale/fieldconverter.py +98 -22
- pyvale/fieldsampler.py +2 -2
- pyvale/fieldscalar.py +10 -10
- pyvale/fieldtensor.py +15 -17
- pyvale/fieldtransform.py +7 -2
- pyvale/fieldvector.py +6 -7
- pyvale/generatorsrandom.py +25 -47
- pyvale/imagedef2d.py +6 -2
- pyvale/integratorfactory.py +2 -2
- pyvale/integratorquadrature.py +50 -24
- pyvale/integratorrectangle.py +85 -7
- pyvale/integratorspatial.py +4 -4
- pyvale/integratortype.py +3 -3
- pyvale/output.py +17 -0
- pyvale/pyvaleexceptions.py +11 -0
- pyvale/raster.py +6 -5
- pyvale/rastercy.py +6 -4
- pyvale/rasternp.py +6 -4
- pyvale/rendermesh.py +6 -2
- pyvale/sensorarray.py +2 -2
- pyvale/sensorarrayfactory.py +52 -65
- pyvale/sensorarraypoint.py +29 -30
- pyvale/sensordata.py +2 -2
- pyvale/sensordescriptor.py +138 -25
- pyvale/sensortools.py +3 -3
- pyvale/simtools.py +67 -0
- pyvale/visualexpplotter.py +99 -57
- pyvale/visualimagedef.py +11 -7
- pyvale/visualimages.py +6 -4
- pyvale/visualopts.py +372 -58
- pyvale/visualsimanimator.py +42 -13
- pyvale/visualsimsensors.py +318 -0
- pyvale/visualtools.py +69 -13
- pyvale/visualtraceplotter.py +52 -165
- {pyvale-2025.4.1.dist-info → pyvale-2025.5.1.dist-info}/METADATA +17 -14
- pyvale-2025.5.1.dist-info/RECORD +172 -0
- {pyvale-2025.4.1.dist-info → pyvale-2025.5.1.dist-info}/WHEEL +1 -1
- pyvale/examples/analyticdatagen/__init__.py +0 -5
- pyvale/examples/ex1_1_thermal2d.py +0 -86
- pyvale/examples/ex1_2_thermal2d.py +0 -108
- pyvale/examples/ex1_3_thermal2d.py +0 -110
- pyvale/examples/ex1_5_thermal2d.py +0 -102
- pyvale/examples/ex2_1_thermal3d .py +0 -84
- pyvale/examples/ex2_2_thermal3d.py +0 -51
- pyvale/examples/ex2_3_thermal3d.py +0 -106
- pyvale/examples/ex3_1_displacement2d.py +0 -44
- pyvale/examples/ex3_2_displacement2d.py +0 -76
- pyvale/examples/ex3_3_displacement2d.py +0 -101
- pyvale/examples/ex3_4_displacement2d.py +0 -102
- pyvale/examples/ex4_1_strain2d.py +0 -54
- pyvale/examples/ex4_2_strain2d.py +0 -76
- pyvale/examples/ex4_3_strain2d.py +0 -97
- pyvale/examples/ex5_1_multiphysics2d.py +0 -75
- pyvale/examples/ex6_1_multiphysics2d_expsim.py +0 -115
- pyvale/examples/ex6_2_multiphysics3d_expsim.py +0 -160
- pyvale/examples/features/__init__.py +0 -5
- pyvale/examples/features/ex_area_avg.py +0 -89
- pyvale/examples/features/ex_calibration_error.py +0 -108
- pyvale/examples/features/ex_chain_field_errs.py +0 -141
- pyvale/examples/features/ex_field_errs.py +0 -78
- pyvale/examples/features/ex_sensor_single_angle_batch.py +0 -110
- pyvale/optimcheckfuncs.py +0 -153
- pyvale/visualsimplotter.py +0 -182
- pyvale-2025.4.1.dist-info/RECORD +0 -163
- {pyvale-2025.4.1.dist-info → pyvale-2025.5.1.dist-info}/licenses/LICENSE +0 -0
- {pyvale-2025.4.1.dist-info → pyvale-2025.5.1.dist-info}/top_level.txt +0 -0
pyvale/simtools.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# pyvale: the python validation engine
|
|
3
|
+
# License: MIT
|
|
4
|
+
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
+
# ==============================================================================
|
|
6
|
+
import numpy as np
|
|
7
|
+
from pyvale.rendermesh import RenderMeshData
|
|
8
|
+
|
|
9
|
+
class SimTools:
|
|
10
|
+
"""Namespace for tools required for analysing simulation results.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def centre_mesh_nodes(nodes: np.ndarray, spat_dim: int) -> np.ndarray:
|
|
15
|
+
"""A method to centre the nodes of a mesh around the origin.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
nodes : np.ndarray
|
|
20
|
+
An array containing the node locations of the mesh.
|
|
21
|
+
spat_dim : int
|
|
22
|
+
The spatial dimension of the mesh.
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
np.ndarray
|
|
27
|
+
An array containing the mesh node locations, but centred around
|
|
28
|
+
the origin.
|
|
29
|
+
"""
|
|
30
|
+
max = np.max(nodes, axis=0)
|
|
31
|
+
min = np.min(nodes, axis=0)
|
|
32
|
+
middle = max - ((max - min) / 2)
|
|
33
|
+
if spat_dim == 3:
|
|
34
|
+
middle[2] = 0
|
|
35
|
+
centred = np.subtract(nodes, middle)
|
|
36
|
+
return centred
|
|
37
|
+
|
|
38
|
+
@staticmethod
|
|
39
|
+
def get_deformed_nodes(timestep: int,
|
|
40
|
+
render_mesh: RenderMeshData) -> np.ndarray | None:
|
|
41
|
+
"""A method to obtain the deformed locations of all the nodes at a given
|
|
42
|
+
timestep.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
timestep : int
|
|
47
|
+
The timestep at which to find the deformed nodes.
|
|
48
|
+
render_mesh: RenderMeshData
|
|
49
|
+
A dataclass containing the skinned mesh and simulation results.
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
np.ndarray | None
|
|
54
|
+
An array containing the deformed values of all the components at
|
|
55
|
+
each node location. Returns None if there are no deformation values.
|
|
56
|
+
"""
|
|
57
|
+
if render_mesh.fields_disp is None:
|
|
58
|
+
return None
|
|
59
|
+
|
|
60
|
+
added_disp = render_mesh.fields_disp[:, timestep]
|
|
61
|
+
if added_disp.shape[1] == 2:
|
|
62
|
+
added_disp = np.hstack((added_disp,np.zeros([added_disp.shape[0],1])))
|
|
63
|
+
coords = np.delete(render_mesh.coords, 3, axis=1)
|
|
64
|
+
deformed_nodes = coords + added_disp
|
|
65
|
+
return deformed_nodes
|
|
66
|
+
|
|
67
|
+
|
pyvale/visualexpplotter.py
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ==============================================================================
|
|
2
2
|
# pyvale: the python validation engine
|
|
3
3
|
# License: MIT
|
|
4
4
|
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
-
#
|
|
5
|
+
# ==============================================================================
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
This module contains function for plotting virtuals sensor trace summary
|
|
9
|
+
statistics and uncertainty bounds over simulated experiments.
|
|
10
|
+
"""
|
|
6
11
|
|
|
7
12
|
from typing import Any
|
|
8
13
|
import numpy as np
|
|
9
14
|
import matplotlib.pyplot as plt
|
|
15
|
+
from pyvale.pyvaleexceptions import VisError
|
|
10
16
|
from pyvale.visualopts import (PlotOptsGeneral,
|
|
11
|
-
|
|
17
|
+
TraceOptsExperiment,
|
|
18
|
+
EExpVisBounds,
|
|
19
|
+
EExpVisCentre)
|
|
12
20
|
from pyvale.experimentsimulator import ExperimentSimulator
|
|
13
21
|
|
|
14
|
-
#TODO: Docstrings
|
|
15
22
|
|
|
16
23
|
def plot_exp_traces(exp_sim: ExperimentSimulator,
|
|
17
24
|
component: str,
|
|
@@ -19,20 +26,56 @@ def plot_exp_traces(exp_sim: ExperimentSimulator,
|
|
|
19
26
|
sim_num: int,
|
|
20
27
|
trace_opts: TraceOptsExperiment | None = None,
|
|
21
28
|
plot_opts: PlotOptsGeneral | None = None) -> tuple[Any,Any]:
|
|
22
|
-
|
|
29
|
+
"""Plots time traces for summary statistics of virtual sensor traces over
|
|
30
|
+
a series of virtual experiments.
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
----------
|
|
34
|
+
exp_sim : ExperimentSimulator
|
|
35
|
+
Experiment simulation object containing the set of virtual experiment to
|
|
36
|
+
be plotted.
|
|
37
|
+
component : str
|
|
38
|
+
String key for the field component to plot.
|
|
39
|
+
sens_array_num : int
|
|
40
|
+
List index for the sensor array to plot.
|
|
41
|
+
sim_num : int
|
|
42
|
+
Index for the simulation to plot.
|
|
43
|
+
trace_opts : TraceOptsExperiment | None, optional
|
|
44
|
+
Dataclass containing specific options for controlling the plot
|
|
45
|
+
appearance, by default None. If None the default options are used.
|
|
46
|
+
plot_opts : PlotOptsGeneral | None, optional
|
|
47
|
+
Dataclass containing general options for formatting plots and
|
|
48
|
+
visualisations, by default None. If None the default options are used.
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
tuple[Any,Any]
|
|
53
|
+
A tuple containing a handle to the matplotlib figure and axis objects:
|
|
54
|
+
(fig,ax).
|
|
55
|
+
|
|
56
|
+
Raises
|
|
57
|
+
------
|
|
58
|
+
VisError
|
|
59
|
+
There are no virtual experiments or virtuale experiment stats to plot in
|
|
60
|
+
the ExperimentSimulator object. Call 'run_experiments' and 'calc_stats'.
|
|
61
|
+
"""
|
|
23
62
|
if trace_opts is None:
|
|
24
63
|
trace_opts = TraceOptsExperiment()
|
|
25
64
|
|
|
26
65
|
if plot_opts is None:
|
|
27
66
|
plot_opts = PlotOptsGeneral()
|
|
28
67
|
|
|
29
|
-
descriptor = exp_sim.
|
|
30
|
-
comp_ind = exp_sim.
|
|
31
|
-
samp_time = exp_sim.
|
|
32
|
-
num_sens = exp_sim.
|
|
68
|
+
descriptor = exp_sim._sensor_arrays[sens_array_num].descriptor
|
|
69
|
+
comp_ind = exp_sim._sensor_arrays[sens_array_num].field.get_component_index(component)
|
|
70
|
+
samp_time = exp_sim._sensor_arrays[sens_array_num].get_sample_times()
|
|
71
|
+
num_sens = exp_sim._sensor_arrays[sens_array_num].get_measurement_shape()[0]
|
|
33
72
|
|
|
34
|
-
exp_data = exp_sim.
|
|
35
|
-
exp_stats = exp_sim.
|
|
73
|
+
exp_data = exp_sim._exp_data
|
|
74
|
+
exp_stats = exp_sim._exp_stats
|
|
75
|
+
|
|
76
|
+
if exp_data is None or exp_stats is None:
|
|
77
|
+
raise VisError("Before visualising virtual experiment traces the " \
|
|
78
|
+
"virtual experiments must be run. exp_data or exp_stats is None.")
|
|
36
79
|
|
|
37
80
|
if trace_opts.sensors_to_plot is None:
|
|
38
81
|
sensors_to_plot = range(num_sens)
|
|
@@ -41,7 +84,7 @@ def plot_exp_traces(exp_sim: ExperimentSimulator,
|
|
|
41
84
|
|
|
42
85
|
#---------------------------------------------------------------------------
|
|
43
86
|
# Figure canvas setup
|
|
44
|
-
fig, ax = plt.subplots(figsize=plot_opts.
|
|
87
|
+
fig, ax = plt.subplots(figsize=plot_opts.single_fig_size_landscape,
|
|
45
88
|
layout='constrained')
|
|
46
89
|
fig.set_dpi(plot_opts.resolution)
|
|
47
90
|
|
|
@@ -49,66 +92,64 @@ def plot_exp_traces(exp_sim: ExperimentSimulator,
|
|
|
49
92
|
# Plot all simulated experimental points
|
|
50
93
|
if trace_opts.plot_all_exp_points:
|
|
51
94
|
for ss in sensors_to_plot:
|
|
52
|
-
for ee in range(exp_sim.
|
|
95
|
+
for ee in range(exp_sim._num_exp_per_sim):
|
|
53
96
|
ax.plot(samp_time,
|
|
54
97
|
exp_data[sens_array_num][sim_num,ee,ss,comp_ind,:],
|
|
55
98
|
"+",
|
|
56
99
|
lw=plot_opts.lw,
|
|
57
100
|
ms=plot_opts.ms,
|
|
58
|
-
color=plot_opts.colors[ss % plot_opts.
|
|
101
|
+
color=plot_opts.colors[ss % plot_opts.colors_num])
|
|
59
102
|
|
|
103
|
+
sensor_tags = descriptor.create_sensor_tags(num_sens)
|
|
104
|
+
lines = []
|
|
60
105
|
for ss in sensors_to_plot:
|
|
61
|
-
if trace_opts.centre ==
|
|
62
|
-
|
|
63
|
-
exp_stats[sens_array_num].median[sim_num,ss,comp_ind,:],
|
|
64
|
-
trace_opts.exp_mean_line,
|
|
65
|
-
lw=plot_opts.lw,
|
|
66
|
-
ms=plot_opts.ms,
|
|
67
|
-
color=plot_opts.colors[ss % plot_opts.n_colors])
|
|
106
|
+
if trace_opts.centre == EExpVisCentre.MEDIAN:
|
|
107
|
+
trace_centre = exp_stats[sens_array_num].med[sim_num,ss,comp_ind,:]
|
|
68
108
|
else:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
109
|
+
trace_centre = exp_stats[sens_array_num].mean[sim_num,ss,comp_ind,:]
|
|
110
|
+
|
|
111
|
+
line, = ax.plot(samp_time,
|
|
112
|
+
trace_centre,
|
|
113
|
+
trace_opts.exp_centre_line,
|
|
114
|
+
label=sensor_tags[ss],
|
|
115
|
+
lw=plot_opts.lw,
|
|
116
|
+
ms=plot_opts.ms,
|
|
117
|
+
color=plot_opts.colors[ss % plot_opts.colors_num])
|
|
118
|
+
lines.append(line)
|
|
119
|
+
|
|
120
|
+
if trace_opts.fill_between is not None:
|
|
77
121
|
upper = np.zeros_like(exp_stats[sens_array_num].min)
|
|
78
122
|
lower = np.zeros_like(exp_stats[sens_array_num].min)
|
|
79
123
|
|
|
80
|
-
if trace_opts.fill_between ==
|
|
81
|
-
upper = exp_stats[sens_array_num].min
|
|
82
|
-
lower = exp_stats[sens_array_num].max
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
3*exp_stats[sens_array_num].std
|
|
97
|
-
lower = exp_stats[sens_array_num].mean - \
|
|
98
|
-
3*exp_stats[sens_array_num].std
|
|
124
|
+
if trace_opts.fill_between == EExpVisBounds.MINMAX:
|
|
125
|
+
upper = trace_opts.fill_scale*exp_stats[sens_array_num].min
|
|
126
|
+
lower = trace_opts.fill_scale*exp_stats[sens_array_num].max
|
|
127
|
+
elif trace_opts.fill_between == EExpVisBounds.QUARTILE:
|
|
128
|
+
upper = trace_opts.fill_scale*exp_stats[sens_array_num].q25
|
|
129
|
+
lower = trace_opts.fill_scale*exp_stats[sens_array_num].q75
|
|
130
|
+
elif trace_opts.fill_between == EExpVisBounds.STD:
|
|
131
|
+
upper = trace_centre + \
|
|
132
|
+
trace_opts.fill_scale*exp_stats[sens_array_num].std
|
|
133
|
+
lower = trace_centre - \
|
|
134
|
+
trace_opts.fill_scale*exp_stats[sens_array_num].std
|
|
135
|
+
elif trace_opts.fill_between == EExpVisBounds.MAD:
|
|
136
|
+
upper = trace_centre + \
|
|
137
|
+
trace_opts.fill_scale*exp_stats[sens_array_num].mad
|
|
138
|
+
lower = trace_centre - \
|
|
139
|
+
trace_opts.fill_scale*exp_stats[sens_array_num].mad
|
|
99
140
|
|
|
100
141
|
ax.fill_between(samp_time,
|
|
101
142
|
upper[sim_num,ss,comp_ind,:],
|
|
102
143
|
lower[sim_num,ss,comp_ind,:],
|
|
103
|
-
color=plot_opts.colors[ss % plot_opts.
|
|
144
|
+
color=plot_opts.colors[ss % plot_opts.colors_num],
|
|
104
145
|
alpha=0.2)
|
|
105
146
|
|
|
106
147
|
#---------------------------------------------------------------------------
|
|
107
148
|
# Plot simulation and truth line
|
|
108
149
|
if trace_opts.sim_line is not None:
|
|
109
|
-
sim_time = exp_sim.
|
|
110
|
-
sim_vals = exp_sim.
|
|
111
|
-
exp_sim.
|
|
150
|
+
sim_time = exp_sim._sensor_arrays[sens_array_num].field.get_time_steps()
|
|
151
|
+
sim_vals = exp_sim._sensor_arrays[sens_array_num].field.sample_field(
|
|
152
|
+
exp_sim._sensor_arrays[sens_array_num].positions)
|
|
112
153
|
|
|
113
154
|
for ss in sensors_to_plot:
|
|
114
155
|
ax.plot(sim_time,
|
|
@@ -118,14 +159,14 @@ def plot_exp_traces(exp_sim: ExperimentSimulator,
|
|
|
118
159
|
ms=plot_opts.ms)
|
|
119
160
|
|
|
120
161
|
if trace_opts.truth_line is not None:
|
|
121
|
-
truth = exp_sim.
|
|
162
|
+
truth = exp_sim._sensor_arrays[sens_array_num].get_truth()
|
|
122
163
|
for ss in sensors_to_plot:
|
|
123
164
|
ax.plot(samp_time,
|
|
124
165
|
truth[ss,comp_ind,:],
|
|
125
166
|
trace_opts.truth_line,
|
|
126
167
|
lw=plot_opts.lw,
|
|
127
168
|
ms=plot_opts.ms,
|
|
128
|
-
color=plot_opts.colors[ss % plot_opts.
|
|
169
|
+
color=plot_opts.colors[ss % plot_opts.colors_num])
|
|
129
170
|
|
|
130
171
|
#---------------------------------------------------------------------------
|
|
131
172
|
# Axis / legend labels and options
|
|
@@ -139,9 +180,10 @@ def plot_exp_traces(exp_sim: ExperimentSimulator,
|
|
|
139
180
|
else:
|
|
140
181
|
ax.set_xlim(trace_opts.time_min_max)
|
|
141
182
|
|
|
142
|
-
trace_opts.
|
|
143
|
-
|
|
144
|
-
|
|
183
|
+
if trace_opts.legend_loc is not None:
|
|
184
|
+
ax.legend(handles=lines,
|
|
185
|
+
prop={"size":plot_opts.font_leg_size},
|
|
186
|
+
loc=trace_opts.legend_loc)
|
|
145
187
|
|
|
146
188
|
plt.grid(True)
|
|
147
189
|
plt.draw()
|
pyvale/visualimagedef.py
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ==============================================================================
|
|
2
2
|
# pyvale: the python validation engine
|
|
3
3
|
# License: MIT
|
|
4
4
|
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
-
#
|
|
5
|
+
# ==============================================================================
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
NOTE: this module is a feature under developement.
|
|
9
|
+
"""
|
|
6
10
|
|
|
7
11
|
import numpy as np
|
|
8
12
|
import matplotlib.pyplot as plt
|
|
@@ -59,12 +63,12 @@ class ImageDefDiags:
|
|
|
59
63
|
vector_map = "plasma"
|
|
60
64
|
|
|
61
65
|
if def_mask is not None:
|
|
62
|
-
ImageDefDiags.
|
|
66
|
+
ImageDefDiags.plot_speckle_image('Def. Mask',def_mask,image_map)
|
|
63
67
|
|
|
64
|
-
ImageDefDiags.
|
|
65
|
-
ImageDefDiags.
|
|
68
|
+
ImageDefDiags.plot_speckle_image('Subpx Def. Image',def_image_subpx,image_map)
|
|
69
|
+
ImageDefDiags.plot_speckle_image('Def. Image',def_image,image_map)
|
|
66
70
|
|
|
67
71
|
ext = tuple(np.array([subpx_grid_xm.min(),subpx_grid_xm.max(),
|
|
68
72
|
subpx_grid_ym.min(),subpx_grid_ym.max()])*10**3)
|
|
69
|
-
ImageDefDiags.plot_image_xy('Sub Pixel Disp X',subpx_disp_x,ext,
|
|
70
|
-
ImageDefDiags.plot_image_xy('Sub Pixel Disp Y',subpx_disp_y,ext,
|
|
73
|
+
ImageDefDiags.plot_image_xy('Sub Pixel Disp X',subpx_disp_x,ext,vector_map)
|
|
74
|
+
ImageDefDiags.plot_image_xy('Sub Pixel Disp Y',subpx_disp_y,ext,vector_map)
|
pyvale/visualimages.py
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ==============================================================================
|
|
2
2
|
# pyvale: the python validation engine
|
|
3
3
|
# License: MIT
|
|
4
4
|
# Copyright (C) 2025 The Computer Aided Validation Team
|
|
5
|
-
#
|
|
5
|
+
# ==============================================================================
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
NOTE: this module is a feature under developement.
|
|
9
|
+
"""
|
|
6
10
|
|
|
7
11
|
from typing import Any
|
|
8
12
|
import numpy as np
|
|
@@ -10,8 +14,6 @@ import matplotlib.pyplot as plt
|
|
|
10
14
|
from pyvale.camera import CameraBasic2D
|
|
11
15
|
from pyvale.visualopts import PlotOptsGeneral
|
|
12
16
|
|
|
13
|
-
# NOTE: This module is a feature under developement.
|
|
14
|
-
|
|
15
17
|
# TODO: this only works for a 2D camera, maybe this should be deprecated
|
|
16
18
|
def plot_measurement_image(camera: CameraBasic2D,
|
|
17
19
|
component: str,
|