pyvale 2025.5.3__cp311-cp311-win32.whl → 2025.7.1__cp311-cp311-win32.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pyvale might be problematic. Click here for more details.
- pyvale/__init__.py +12 -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/DIC_Challenge_Star_Noise_Def.tiff +0 -0
- pyvale/data/DIC_Challenge_Star_Noise_Ref.tiff +0 -0
- 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.1.dist-info}/METADATA +11 -57
- {pyvale-2025.5.3.dist-info → pyvale-2025.7.1.dist-info}/RECORD +93 -56
- {pyvale-2025.5.3.dist-info → pyvale-2025.7.1.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.1.dist-info}/licenses/LICENSE +0 -0
- {pyvale-2025.5.3.dist-info → pyvale-2025.7.1.dist-info}/top_level.txt +0 -0
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
# ==============================================================================
|
|
6
6
|
|
|
7
7
|
"""
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
Basics: Pyvale point sensor simulation
|
|
9
|
+
================================================================================
|
|
10
|
+
|
|
11
|
+
In this example we introduce the basic features of `pyvale` for point sensor
|
|
11
12
|
simulation. We demonstrate quick sensor array construction with defaults using
|
|
12
|
-
the pyvale sensor array factory. Finally we run a sensor simulation and display
|
|
13
|
+
the `pyvale` sensor array factory. Finally we run a sensor simulation and display
|
|
13
14
|
the output.
|
|
14
15
|
|
|
15
16
|
Test case: Scalar field point sensors (thermocouples) on a 2D thermal simulation
|
|
@@ -20,112 +21,122 @@ import matplotlib.pyplot as plt
|
|
|
20
21
|
import mooseherder as mh
|
|
21
22
|
import pyvale as pyv
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
24
|
+
#%%
|
|
25
|
+
# Here we load a pre-generated MOOSE finite element simulation dataset that
|
|
26
|
+
# comes packaged with pyvale. The simulation is a 2D rectangular plate with
|
|
27
|
+
# a bi-directional temperature gradient. You can replace this with the path
|
|
28
|
+
# to your own MOOSE simulation with exodus output (*.e). Note that the
|
|
29
|
+
# field_key must match the name of your variable in your MOOSE simulation.
|
|
30
|
+
# We use `mooseherder` to load the exodus file into a `SimData` object.
|
|
31
|
+
data_path = pyv.DataSet.thermal_2d_path()
|
|
32
|
+
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
33
|
+
|
|
34
|
+
#%%
|
|
35
|
+
# Scale to mm to make 3D visualisation scaling easier as pyvista scales
|
|
36
|
+
# everything to unity
|
|
37
|
+
sim_data = pyv.scale_length_units(scale=1000.0,
|
|
38
|
+
sim_data=sim_data,
|
|
39
|
+
disp_comps=None)
|
|
40
|
+
|
|
41
|
+
#%%
|
|
42
|
+
# We now use a helper function to create a grid of sensor locations but we
|
|
43
|
+
# could have also manually built the numpy array of sensor locations which
|
|
44
|
+
# has the shape=(num_sensors,coord[x,y,z]).
|
|
45
|
+
n_sens = (3,2,1)
|
|
46
|
+
x_lims = (0.0,100.0)
|
|
47
|
+
y_lims = (0.0,50.0)
|
|
48
|
+
z_lims = (0.0,0.0)
|
|
49
|
+
sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
50
|
+
|
|
51
|
+
#%%
|
|
52
|
+
# This dataclass contains the parameters to build our sensor array. We can
|
|
53
|
+
# also customise the output frequency, the sensor area and the sensor
|
|
54
|
+
# orientation. For now we will use the defaults which assumes an ideal point
|
|
55
|
+
# sensor sampling at the simulation time steps.
|
|
56
|
+
sens_data = pyv.SensorData(positions=sens_pos)
|
|
57
|
+
|
|
58
|
+
#%%
|
|
59
|
+
# Now that we have our sensor locations we can use the sensor factory to
|
|
60
|
+
# build a basic thermocouple array with some useful defaults. In later
|
|
61
|
+
# examples we will see how to customise sensor parameters and errors.
|
|
62
|
+
# This basic thermocouple array includes a 1% systematic and random error.
|
|
63
|
+
# If you want to remove the simulated errors and just interpolate at the
|
|
64
|
+
# sensor locations then user `.thermocouples_no_errs()`.
|
|
65
|
+
field_key: str = "temperature"
|
|
66
|
+
tc_array = pyv.SensorArrayFactory \
|
|
67
|
+
.thermocouples_basic_errs(sim_data,
|
|
68
|
+
sens_data,
|
|
69
|
+
elem_dims=2,
|
|
70
|
+
field_name=field_key)
|
|
71
|
+
|
|
72
|
+
#%%
|
|
73
|
+
# We have built our sensor array so now we can call `calc_measurements()` to
|
|
74
|
+
# generate simulated sensor traces.
|
|
75
|
+
measurements = tc_array.calc_measurements()
|
|
76
|
+
print(f"\nMeasurements for last sensor:\n{measurements[-1,0,:]}\n")
|
|
77
|
+
|
|
78
|
+
#%%
|
|
79
|
+
# We can now visualise the sensor locations on the simulation mesh and the
|
|
80
|
+
# simulated sensor traces using pyvale's visualisation tools which use
|
|
81
|
+
# pyvista for meshes and matplotlib for sensor traces. pyvale will return
|
|
82
|
+
# plot and axes objects to the user allowing additional customisation using
|
|
83
|
+
# pyvista and matplotlib. This also means that we need to call `.show()`
|
|
84
|
+
# ourselves to display the figure as pyvale does not do this for us.
|
|
85
|
+
#
|
|
86
|
+
# If we are going to save figures we need to make sure the path exists. Here
|
|
87
|
+
# we create a default output path based on your current working directory.
|
|
88
|
+
output_path = Path.cwd() / "pyvale-output"
|
|
89
|
+
if not output_path.is_dir():
|
|
90
|
+
output_path.mkdir(parents=True, exist_ok=True)
|
|
91
|
+
|
|
92
|
+
#%%
|
|
93
|
+
# This creates a pyvista visualisation of the sensor locations on the
|
|
94
|
+
# simulation mesh. The plot will can be shown in interactive mode by calling
|
|
95
|
+
# `pv_plot.show()`.
|
|
96
|
+
pv_plot = pyv.plot_point_sensors_on_sim(tc_array,field_key)
|
|
97
|
+
|
|
98
|
+
#%%
|
|
99
|
+
# We determined manually by moving camera in interative mode and then
|
|
100
|
+
# printing camera position to console after window close, as below.
|
|
101
|
+
pv_plot.camera_position = [(-7.547, 59.753, 134.52),
|
|
102
|
+
(41.916, 25.303, 9.297),
|
|
103
|
+
(0.0810, 0.969, -0.234)]
|
|
104
|
+
|
|
105
|
+
#%%
|
|
106
|
+
# This allows us to save a vector graphic and raster graphic showing the
|
|
107
|
+
# sensor locations on the simulation mesh
|
|
108
|
+
save_render = output_path / "basics_ex1_1_sensorlocs.svg"
|
|
109
|
+
pv_plot.save_graphic(save_render) # only for .svg .eps .ps .pdf .tex
|
|
110
|
+
pv_plot.screenshot(save_render.with_suffix(".png"))
|
|
111
|
+
|
|
112
|
+
#%%
|
|
113
|
+
# We can also show the simulation and sensor locations in interative mode
|
|
114
|
+
# by calling `.show()`
|
|
115
|
+
pv_plot.show()
|
|
116
|
+
|
|
117
|
+
print(80*"-")
|
|
118
|
+
print("Camera position after interactive view:")
|
|
119
|
+
print(pv_plot.camera_position)
|
|
120
|
+
print(80*"-"+"\n")
|
|
121
|
+
|
|
122
|
+
#%%
|
|
123
|
+
# This plots the time traces for all of our sensors. The solid line shows
|
|
124
|
+
# the 'truth' interpolated from the simulation and the dashed line with
|
|
125
|
+
# markers shows the simulated sensor traces. In later examples we will see
|
|
126
|
+
# how to configure this plot but for now we note we that we are returned a
|
|
127
|
+
# matplotlib figure and axes object which allows for further customisation.
|
|
128
|
+
(fig,ax) = pyv.plot_time_traces(tc_array,field_key)
|
|
129
|
+
|
|
130
|
+
#%%
|
|
131
|
+
# We can also save the sensor trace plot as a vector and raster graphic
|
|
132
|
+
save_traces = output_path/"basics_ex1_1_sensortraces.png"
|
|
133
|
+
fig.savefig(save_traces, dpi=300, bbox_inches="tight")
|
|
134
|
+
fig.savefig(save_traces.with_suffix(".svg"), dpi=300, bbox_inches="tight")
|
|
135
|
+
|
|
136
|
+
#%%
|
|
137
|
+
# The trace plot can also be shown in interactive mode using `plt.show()`
|
|
138
|
+
plt.show()
|
|
139
|
+
|
|
140
|
+
#%%
|
|
141
|
+
# That is it for this example. In the next one we will look at the `pyvale`
|
|
142
|
+
# simulated measurement model.
|
|
@@ -5,10 +5,11 @@
|
|
|
5
5
|
# ==============================================================================
|
|
6
6
|
|
|
7
7
|
"""
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
Basics: Sensor model & `get_measurements()` vs `calc_measurements()`
|
|
9
|
+
================================================================================
|
|
10
|
+
|
|
11
|
+
In this example we explain the `pyvale` virtual sensor measurement model. For a
|
|
12
|
+
virtual sensor in `pyvale` a measurement is defined as measurement = truth +
|
|
12
13
|
systematic error + random error. Sources of systematic errors include: spatial/
|
|
13
14
|
temporal averaging, uncertainty in position / sampling time / orientation,
|
|
14
15
|
digitisation, saturation, and calibration. Sources of random error are generally
|
|
@@ -19,10 +20,10 @@ However, systematic errors cannot easily be accounted for without a forward
|
|
|
19
20
|
model of the source of the error. Characterising the contribution of systematic
|
|
20
21
|
errors to the total measurement error is a key application of `pyvale`.
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
A sensor array has two key methods: `get_measurements()` and `calc_measurements`
|
|
24
|
+
. Calling `get_measurements()` retrieves the results for the current simulated
|
|
25
|
+
experiment whereas calling `calc_measurements()` will generate a new simulated
|
|
26
|
+
experiment by sampling / calculating the systematic and random errors.
|
|
26
27
|
|
|
27
28
|
Test case: Scalar field point sensors (thermocouples) on a 2D thermal simulation
|
|
28
29
|
"""
|
|
@@ -32,127 +33,118 @@ import mooseherder as mh
|
|
|
32
33
|
import pyvale as pyv
|
|
33
34
|
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
(fig,ax) = pyv.plot_time_traces(tc_array,field_key)
|
|
151
|
-
ax.set_title("Exp 3: called calc_measurements()")
|
|
152
|
-
|
|
153
|
-
print(80*"-")
|
|
154
|
-
|
|
155
|
-
plt.show()
|
|
156
|
-
|
|
157
|
-
if __name__ == "__main__":
|
|
158
|
-
main()
|
|
36
|
+
#%%
|
|
37
|
+
# The first part of this example is the similar to basics example 1.1, so
|
|
38
|
+
# feel free to skip to after the first call to `calc_measurements()`.
|
|
39
|
+
#
|
|
40
|
+
# Here we load a pre-generated MOOSE finite element simulation dataset that
|
|
41
|
+
# comes packaged with pyvale. The simulation is a 2D rectangular plate with
|
|
42
|
+
# a bi-directional temperature gradient.
|
|
43
|
+
data_path = pyv.DataSet.thermal_2d_path()
|
|
44
|
+
sim_data = mh.ExodusReader(data_path).read_all_sim_data()
|
|
45
|
+
field_key: str = "temperature"
|
|
46
|
+
|
|
47
|
+
#%%
|
|
48
|
+
# Scale to mm to make 3D visualisation scaling easier as pyvista scales
|
|
49
|
+
# everything to unity
|
|
50
|
+
sim_data = pyv.scale_length_units(scale=1000.0,
|
|
51
|
+
sim_data=sim_data,
|
|
52
|
+
disp_comps=None)
|
|
53
|
+
|
|
54
|
+
#%%
|
|
55
|
+
# We now use a helper function to create a grid of sensor locations but we
|
|
56
|
+
# could have also manually built the numpy array of sensor locations which
|
|
57
|
+
# has the shape=(num_sensors,coord[x,y,z]).
|
|
58
|
+
n_sens = (4,1,1)
|
|
59
|
+
x_lims = (0.0,100.0)
|
|
60
|
+
y_lims = (0.0,50.0)
|
|
61
|
+
z_lims = (0.0,0.0)
|
|
62
|
+
sens_pos = pyv.create_sensor_pos_array(n_sens,x_lims,y_lims,z_lims)
|
|
63
|
+
|
|
64
|
+
#%%
|
|
65
|
+
# This dataclass contains the parameters to build our sensor array. We can
|
|
66
|
+
# also customise the output frequency, the sensor area and the sensor
|
|
67
|
+
# orientation. For now we will use the defaults which assumes an ideal point
|
|
68
|
+
# sensor sampling at the simulation time steps.
|
|
69
|
+
sens_data = pyv.SensorData(positions=sens_pos)
|
|
70
|
+
|
|
71
|
+
#%%
|
|
72
|
+
# Now that we have our sensor locations we can use the sensor factory to
|
|
73
|
+
# build a basic thermocouple array with some useful defaults. In later
|
|
74
|
+
# examples we will see how to customise sensor parameters and errors.
|
|
75
|
+
# This basic thermocouple array includes a 5% systematic and random error -
|
|
76
|
+
# We are specifically using exaggerated errors here for visualisation.
|
|
77
|
+
tc_array = pyv.SensorArrayFactory \
|
|
78
|
+
.thermocouples_basic_errs(sim_data,
|
|
79
|
+
sens_data,
|
|
80
|
+
elem_dims=2,
|
|
81
|
+
field_name=field_key,
|
|
82
|
+
errs_pc=5.0)
|
|
83
|
+
|
|
84
|
+
#%%
|
|
85
|
+
# We have built our sensor array so now we can call `calc_measurements()` to
|
|
86
|
+
# generate simulated sensor traces.
|
|
87
|
+
measurements = tc_array.calc_measurements()
|
|
88
|
+
|
|
89
|
+
#%%
|
|
90
|
+
# From here we are going to experiment with repeated calls to
|
|
91
|
+
# `calc_measurements()` and `get_measurements()` for our sensor array. We
|
|
92
|
+
# will print the results to the console as well as plotting time traces of
|
|
93
|
+
# the simulated sensor output. All further explanations are in the print
|
|
94
|
+
# statements below.
|
|
95
|
+
|
|
96
|
+
print("\n"+80*"-")
|
|
97
|
+
print("For a sensor array: "
|
|
98
|
+
+ "measurement = truth + sysematic error + random error")
|
|
99
|
+
print(f"\nmeasurements.shape = {measurements.shape} = "
|
|
100
|
+
+ "(n_sensors,n_field_components,n_timesteps)\n")
|
|
101
|
+
print("Here we have a scalar temperature field so only 1 field component.")
|
|
102
|
+
print("The truth, systematic error and random error arrays all have the "+
|
|
103
|
+
"same shape.")
|
|
104
|
+
|
|
105
|
+
sens_print = 0
|
|
106
|
+
comp_print = 0
|
|
107
|
+
time_last = 5
|
|
108
|
+
time_print = slice(measurements.shape[2]-time_last,measurements.shape[2])
|
|
109
|
+
|
|
110
|
+
print(80*"-")
|
|
111
|
+
print(f"Looking at the last {time_last} virtual measurements for sensor"
|
|
112
|
+
+f" {sens_print}:")
|
|
113
|
+
|
|
114
|
+
pyv.print_measurements(tc_array,sens_print,comp_print,time_print)
|
|
115
|
+
|
|
116
|
+
print(80*"-")
|
|
117
|
+
print("If we call the `calc_measurements()` method then the errors are "
|
|
118
|
+
+ "re-calculated.")
|
|
119
|
+
measurements = tc_array.calc_measurements()
|
|
120
|
+
|
|
121
|
+
pyv.print_measurements(tc_array,sens_print,comp_print,time_print)
|
|
122
|
+
|
|
123
|
+
(fig,ax) = pyv.plot_time_traces(tc_array,field_key)
|
|
124
|
+
ax.set_title("Exp 1: called calc_measurements()")
|
|
125
|
+
|
|
126
|
+
print(80*"-")
|
|
127
|
+
print("If we call the `get_measurements()` method then the errors are the "
|
|
128
|
+
+ "same:")
|
|
129
|
+
measurements = tc_array.get_measurements()
|
|
130
|
+
|
|
131
|
+
pyv.print_measurements(tc_array,sens_print,comp_print,time_print)
|
|
132
|
+
|
|
133
|
+
(fig,ax) = pyv.plot_time_traces(tc_array,field_key)
|
|
134
|
+
ax.set_title("Exp 2: called get_measurements()")
|
|
135
|
+
|
|
136
|
+
print(80*"-")
|
|
137
|
+
print("If we call the `calc_measurements()` method again we generate / "
|
|
138
|
+
"sample new errors:")
|
|
139
|
+
measurements = tc_array.calc_measurements()
|
|
140
|
+
|
|
141
|
+
pyv.print_measurements(tc_array,sens_print,comp_print,time_print)
|
|
142
|
+
|
|
143
|
+
(fig,ax) = pyv.plot_time_traces(tc_array,field_key)
|
|
144
|
+
ax.set_title("Exp 3: called calc_measurements()")
|
|
145
|
+
|
|
146
|
+
print(80*"-")
|
|
147
|
+
|
|
148
|
+
plt.show()
|
|
149
|
+
|
|
150
|
+
|