geopyv-dev 0.1.0__cp38-cp38-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- geopyv_dev/__init__.py +14 -0
- geopyv_dev/_geopyv_dev.cp38-win_amd64.pyd +0 -0
- geopyv_dev/plots.py +339 -0
- geopyv_dev/wrappers.py +57 -0
- geopyv_dev-0.1.0.dist-info/METADATA +20 -0
- geopyv_dev-0.1.0.dist-info/RECORD +9 -0
- geopyv_dev-0.1.0.dist-info/WHEEL +4 -0
- geopyv_dev-0.1.0.dist-info/licenses/LICENSE +674 -0
- geopyv_dev-0.1.0.dist-info/sboms/geopyv-dev-python.cyclonedx.json +5660 -0
geopyv_dev/__init__.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from ._geopyv_dev import *
|
|
2
|
+
from .plots import (
|
|
3
|
+
inspect_subset,
|
|
4
|
+
inspect_mesh,
|
|
5
|
+
inspect_sequence,
|
|
6
|
+
inspect_particle,
|
|
7
|
+
inspect_field,
|
|
8
|
+
convergence_subset,
|
|
9
|
+
convergence_mesh,
|
|
10
|
+
convergence_sequence,
|
|
11
|
+
contour_mesh,
|
|
12
|
+
contour_field,
|
|
13
|
+
)
|
|
14
|
+
from .wrappers import SubsetWrapper, MeshWrapper, ParticleWrapper, FieldWrapper
|
|
Binary file
|
geopyv_dev/plots.py
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import matplotlib.pyplot as plt
|
|
3
|
+
import matplotlib.tri as tri
|
|
4
|
+
from scipy.spatial import Delaunay
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def _imshow_or_blank(ax, img_path, **kwargs):
|
|
8
|
+
"""Helper: show image from path, or blank background if path is None."""
|
|
9
|
+
kwargs.setdefault("cmap", "gist_gray")
|
|
10
|
+
if img_path is not None:
|
|
11
|
+
import cv2
|
|
12
|
+
img = cv2.imread(img_path, cv2.IMREAD_COLOR)
|
|
13
|
+
img_gs = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY).astype(float)
|
|
14
|
+
ax.imshow(img_gs, **kwargs)
|
|
15
|
+
else:
|
|
16
|
+
blank = np.zeros((50, 50), dtype=float)
|
|
17
|
+
ax.imshow(blank, **kwargs)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _show_save_close(fig, show, block, save):
|
|
21
|
+
if save:
|
|
22
|
+
plt.savefig(save, dpi=600)
|
|
23
|
+
if show:
|
|
24
|
+
plt.show(block=block)
|
|
25
|
+
else:
|
|
26
|
+
plt.close(fig)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def inspect_subset(subset, show=True, block=True, save=False, **kwargs):
|
|
30
|
+
coord = subset.coord
|
|
31
|
+
f_coords = np.asarray(subset.f_coords)
|
|
32
|
+
f = np.asarray(subset.f)
|
|
33
|
+
sssig = subset.sssig
|
|
34
|
+
sigma_intensity = subset.sigma_intensity
|
|
35
|
+
|
|
36
|
+
f_img_path = getattr(subset, 'f_img_path', None)
|
|
37
|
+
template_size = getattr(subset, 'template_size', None)
|
|
38
|
+
if template_size is None:
|
|
39
|
+
template_size = int(np.ceil(np.sqrt(len(f) / np.pi)))
|
|
40
|
+
|
|
41
|
+
# Build display image
|
|
42
|
+
if f_img_path is not None:
|
|
43
|
+
import cv2
|
|
44
|
+
img = cv2.imread(f_img_path, cv2.IMREAD_COLOR)
|
|
45
|
+
img_gs = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY).astype(float)
|
|
46
|
+
x, y = coord
|
|
47
|
+
r = template_size
|
|
48
|
+
x0, x1 = max(0, int(round(x)) - r), min(img_gs.shape[1], int(round(x)) + r + 1)
|
|
49
|
+
y0, y1 = max(0, int(round(y)) - r), min(img_gs.shape[0], int(round(y)) + r + 1)
|
|
50
|
+
display = img_gs[y0:y1, x0:x1]
|
|
51
|
+
else:
|
|
52
|
+
xi = f_coords[:, 0]
|
|
53
|
+
yi = f_coords[:, 1]
|
|
54
|
+
x_min = int(np.floor(xi.min()))
|
|
55
|
+
y_min = int(np.floor(yi.min()))
|
|
56
|
+
x_max = int(np.ceil(xi.max()))
|
|
57
|
+
y_max = int(np.ceil(yi.max()))
|
|
58
|
+
h = y_max - y_min + 1
|
|
59
|
+
w = x_max - x_min + 1
|
|
60
|
+
display = np.full((h, w), float(np.mean(f)))
|
|
61
|
+
for k in range(len(f)):
|
|
62
|
+
ix = int(round(float(xi[k]))) - x_min
|
|
63
|
+
iy = int(round(float(yi[k]))) - y_min
|
|
64
|
+
if 0 <= iy < h and 0 <= ix < w:
|
|
65
|
+
display[iy, ix] = float(f[k])
|
|
66
|
+
|
|
67
|
+
imshow_kwargs = {"cmap": "gist_gray"}
|
|
68
|
+
imshow_kwargs.update(kwargs)
|
|
69
|
+
|
|
70
|
+
fig, ax = plt.subplots()
|
|
71
|
+
ax.imshow(display, **imshow_kwargs)
|
|
72
|
+
ax.text(0.5, -0.05,
|
|
73
|
+
f"Size: {template_size} px; \u03c3_s = {sigma_intensity:.2f}; SSSIG = {sssig:.2E}",
|
|
74
|
+
transform=ax.transAxes, ha="center")
|
|
75
|
+
ax.set_axis_off()
|
|
76
|
+
plt.tight_layout()
|
|
77
|
+
_show_save_close(fig, show, block, save)
|
|
78
|
+
return fig, ax
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def inspect_mesh(mesh, subset_idx=None, show_areas=False, show=True, block=True, save=False, **kwargs):
|
|
82
|
+
nodes = np.asarray(mesh.nodes)
|
|
83
|
+
elements = np.asarray(mesh.elements)
|
|
84
|
+
f_img_path = getattr(mesh, 'f_img_path', None)
|
|
85
|
+
|
|
86
|
+
fig, ax = plt.subplots()
|
|
87
|
+
|
|
88
|
+
imshow_kwargs = {"cmap": "gist_gray"}
|
|
89
|
+
imshow_kwargs.update(kwargs)
|
|
90
|
+
_imshow_or_blank(ax, f_img_path, **imshow_kwargs)
|
|
91
|
+
|
|
92
|
+
# Element edges
|
|
93
|
+
n_corner = 3
|
|
94
|
+
for elem in elements:
|
|
95
|
+
corners = nodes[elem[:n_corner]]
|
|
96
|
+
for i in range(n_corner):
|
|
97
|
+
j = (i + 1) % n_corner
|
|
98
|
+
ax.plot([corners[i, 0], corners[j, 0]], [corners[i, 1], corners[j, 1]],
|
|
99
|
+
'b-', linewidth=0.5)
|
|
100
|
+
|
|
101
|
+
# Element index annotations
|
|
102
|
+
for i, elem in enumerate(elements):
|
|
103
|
+
cx = nodes[elem[:3], 0].mean()
|
|
104
|
+
cy = nodes[elem[:3], 1].mean()
|
|
105
|
+
ax.text(cx, cy, str(i), ha='center', va='center', color='red', fontsize=8)
|
|
106
|
+
|
|
107
|
+
if show_areas:
|
|
108
|
+
from matplotlib.patches import Circle as MplCircle
|
|
109
|
+
radius = 10
|
|
110
|
+
for nd in nodes:
|
|
111
|
+
ax.add_patch(MplCircle((nd[0], nd[1]), radius, alpha=0.2, color='blue'))
|
|
112
|
+
|
|
113
|
+
plt.tight_layout()
|
|
114
|
+
_show_save_close(fig, show, block, save)
|
|
115
|
+
return fig, ax
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def inspect_sequence(sequence, mesh_idx=None, subset_idx=None, show=True, block=True, save=False, **kwargs):
|
|
119
|
+
if mesh_idx is None:
|
|
120
|
+
raise ValueError("mesh_idx is required")
|
|
121
|
+
mesh = sequence.mesh_solutions[mesh_idx]
|
|
122
|
+
return inspect_mesh(mesh, subset_idx=subset_idx, show=show, block=block, save=save, **kwargs)
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def inspect_particle(particle, show=True, block=True, save=False, **kwargs):
|
|
126
|
+
coords = np.asarray(particle.coordinates)
|
|
127
|
+
initial = coords[0]
|
|
128
|
+
img_path = getattr(particle, 'image_0_path', None)
|
|
129
|
+
|
|
130
|
+
fig, ax = plt.subplots()
|
|
131
|
+
_imshow_or_blank(ax, img_path)
|
|
132
|
+
ax.scatter([initial[0]], [initial[1]], marker='x', color='red', s=100, zorder=10, **kwargs)
|
|
133
|
+
plt.tight_layout()
|
|
134
|
+
_show_save_close(fig, show, block, save)
|
|
135
|
+
return fig, ax
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def inspect_field(field, particle_idx=None, show=True, block=True, save=False, **kwargs):
|
|
139
|
+
coords = np.asarray(field.coordinates)
|
|
140
|
+
img_path = getattr(field, 'image_0_path', None)
|
|
141
|
+
|
|
142
|
+
fig, ax = plt.subplots()
|
|
143
|
+
_imshow_or_blank(ax, img_path)
|
|
144
|
+
ax.scatter(coords[:, 0], coords[:, 1], **kwargs)
|
|
145
|
+
if particle_idx is not None:
|
|
146
|
+
ax.scatter([coords[particle_idx, 0]], [coords[particle_idx, 1]],
|
|
147
|
+
color='red', s=100, zorder=10)
|
|
148
|
+
plt.tight_layout()
|
|
149
|
+
_show_save_close(fig, show, block, save)
|
|
150
|
+
return fig, ax
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def convergence_subset(subset, show=True, block=True, save=False, **kwargs):
|
|
154
|
+
solve_result = getattr(subset, 'solve_result', None)
|
|
155
|
+
if solve_result is None:
|
|
156
|
+
raise ValueError("Subset has not been solved.")
|
|
157
|
+
history = solve_result["history"]
|
|
158
|
+
max_norm = solve_result.get("max_norm", 1e-3)
|
|
159
|
+
max_iterations = solve_result.get("max_iterations", 50)
|
|
160
|
+
|
|
161
|
+
iters = [h[0] for h in history]
|
|
162
|
+
norms = [h[1] for h in history]
|
|
163
|
+
znccs = [h[2] for h in history]
|
|
164
|
+
|
|
165
|
+
fig, ax = plt.subplots(2, 1, sharex=True)
|
|
166
|
+
ax[0].semilogy(iters, norms, marker="o", **kwargs)
|
|
167
|
+
ax[0].semilogy([min(iters), max(iters)], [max_norm, max_norm], "--r")
|
|
168
|
+
ax[0].set_ylabel(r"$\Delta$ Norm (-)")
|
|
169
|
+
ax[1].plot(iters, znccs, marker="o", **kwargs)
|
|
170
|
+
ax[1].plot([min(iters), max(iters)], [0.75, 0.75], "--r")
|
|
171
|
+
ax[1].set_ylabel(r"$C_{ZNCC}$ (-)")
|
|
172
|
+
ax[1].set_xlabel("Iteration (-)")
|
|
173
|
+
plt.tight_layout()
|
|
174
|
+
_show_save_close(fig, show, block, save)
|
|
175
|
+
return fig, np.array(ax)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def convergence_mesh(mesh, quantity, show=True, block=True, save=False, **kwargs):
|
|
179
|
+
valid = {"C_ZNCC", "iterations", "norm"}
|
|
180
|
+
if quantity not in valid:
|
|
181
|
+
raise ValueError(f"quantity must be one of {sorted(valid)!r}, got {quantity!r}")
|
|
182
|
+
|
|
183
|
+
if quantity == "C_ZNCC":
|
|
184
|
+
data = np.asarray(mesh.c_zncc)
|
|
185
|
+
xlabel = r"$C_{ZNCC}$ (-)"
|
|
186
|
+
elif quantity == "iterations":
|
|
187
|
+
data = np.asarray(mesh.iterations, dtype=float)
|
|
188
|
+
xlabel = "Iterations (-)"
|
|
189
|
+
else:
|
|
190
|
+
data = np.asarray(mesh.norms)
|
|
191
|
+
xlabel = r"$\Delta$ Norm (-)"
|
|
192
|
+
|
|
193
|
+
fig, ax = plt.subplots()
|
|
194
|
+
ax.hist(data, **kwargs)
|
|
195
|
+
ax.set_xlabel(xlabel)
|
|
196
|
+
ax.set_ylabel("Count (-)")
|
|
197
|
+
plt.tight_layout()
|
|
198
|
+
_show_save_close(fig, show, block, save)
|
|
199
|
+
return fig, ax
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def convergence_sequence(sequence, mesh_idx=None, subset_idx=None, quantity="C_ZNCC",
|
|
203
|
+
show=True, block=True, save=False, **kwargs):
|
|
204
|
+
if mesh_idx is not None:
|
|
205
|
+
mesh = sequence.mesh_solutions[mesh_idx]
|
|
206
|
+
return convergence_mesh(mesh, quantity, show=show, block=block, save=save, **kwargs)
|
|
207
|
+
else:
|
|
208
|
+
all_data = np.concatenate([np.asarray(m.c_zncc) for m in sequence.mesh_solutions])
|
|
209
|
+
fig, ax = plt.subplots()
|
|
210
|
+
ax.hist(all_data, **kwargs)
|
|
211
|
+
ax.set_xlabel(r"$C_{ZNCC}$ (-)")
|
|
212
|
+
ax.set_ylabel("Count (-)")
|
|
213
|
+
plt.tight_layout()
|
|
214
|
+
_show_save_close(fig, show, block, save)
|
|
215
|
+
return fig, ax
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def contour_mesh(mesh, quantity, show=True, block=True, save=False, **kwargs):
|
|
219
|
+
valid = {"C_ZNCC", "iterations", "norm", "u", "v", "R"}
|
|
220
|
+
if quantity not in valid:
|
|
221
|
+
raise ValueError(f"quantity must be one of {sorted(valid)!r}, got {quantity!r}")
|
|
222
|
+
|
|
223
|
+
nodes = np.asarray(mesh.nodes)
|
|
224
|
+
elements = np.asarray(mesh.elements)
|
|
225
|
+
displacements = np.asarray(mesh.displacements)
|
|
226
|
+
|
|
227
|
+
labels = {
|
|
228
|
+
"C_ZNCC": r"$C_{ZNCC}$ (-)",
|
|
229
|
+
"iterations": "Iterations (-)",
|
|
230
|
+
"norm": r"$\Delta$ Norm (-)",
|
|
231
|
+
"u": "u (px)",
|
|
232
|
+
"v": "v (px)",
|
|
233
|
+
"R": "R (px)",
|
|
234
|
+
}
|
|
235
|
+
if quantity == "C_ZNCC":
|
|
236
|
+
values = np.asarray(mesh.c_zncc)
|
|
237
|
+
elif quantity == "iterations":
|
|
238
|
+
values = np.asarray(mesh.iterations, dtype=float)
|
|
239
|
+
elif quantity == "norm":
|
|
240
|
+
values = np.asarray(mesh.norms)
|
|
241
|
+
elif quantity == "u":
|
|
242
|
+
values = displacements[:, 0]
|
|
243
|
+
elif quantity == "v":
|
|
244
|
+
values = displacements[:, 1]
|
|
245
|
+
elif quantity == "R":
|
|
246
|
+
values = np.sqrt(displacements[:, 0]**2 + displacements[:, 1]**2)
|
|
247
|
+
|
|
248
|
+
fig, ax = plt.subplots()
|
|
249
|
+
f_img_path = getattr(mesh, 'f_img_path', None)
|
|
250
|
+
_imshow_or_blank(ax, f_img_path)
|
|
251
|
+
|
|
252
|
+
tri_obj = tri.Triangulation(nodes[:, 0], nodes[:, 1], elements[:, :3])
|
|
253
|
+
cf = ax.tricontourf(tri_obj, values, **kwargs)
|
|
254
|
+
cbar = fig.colorbar(cf, ax=ax)
|
|
255
|
+
cbar.set_label(labels[quantity])
|
|
256
|
+
|
|
257
|
+
plt.tight_layout()
|
|
258
|
+
_show_save_close(fig, show, block, save)
|
|
259
|
+
return fig, ax
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def contour_field(field, quantity, window=None, dt=None, absolute=False,
|
|
263
|
+
show=True, block=True, save=False, **kwargs):
|
|
264
|
+
valid = {"u", "v", "R", "ep_xx", "ep_yy", "ep_xy", "ep_vol"}
|
|
265
|
+
if quantity not in valid:
|
|
266
|
+
raise ValueError(f"quantity must be one of {sorted(valid)!r}, got {quantity!r}")
|
|
267
|
+
|
|
268
|
+
particles = field.particles
|
|
269
|
+
n = len(particles)
|
|
270
|
+
coords = np.array([[p.coordinates[0, 0], p.coordinates[0, 1]] for p in particles])
|
|
271
|
+
|
|
272
|
+
strain_col = {"ep_xx": 0, "ep_yy": 1, "ep_xy": 2}
|
|
273
|
+
|
|
274
|
+
# Build window slice
|
|
275
|
+
if window is not None:
|
|
276
|
+
if isinstance(window, (list, tuple)) and len(window) == 2:
|
|
277
|
+
w = slice(window[0], window[1])
|
|
278
|
+
else:
|
|
279
|
+
w = window
|
|
280
|
+
else:
|
|
281
|
+
w = slice(None)
|
|
282
|
+
|
|
283
|
+
values = np.zeros(n)
|
|
284
|
+
for i, p in enumerate(particles):
|
|
285
|
+
warps = np.asarray(p.warps) # (inc_no, warp_len)
|
|
286
|
+
vol_strains = np.asarray(p.vol_strains)
|
|
287
|
+
strains = np.asarray(p.strains) # (inc_no, 6)
|
|
288
|
+
|
|
289
|
+
if quantity == "u":
|
|
290
|
+
v = warps[w, 0]
|
|
291
|
+
elif quantity == "v":
|
|
292
|
+
v = warps[w, 1]
|
|
293
|
+
elif quantity == "R":
|
|
294
|
+
v = np.sqrt(warps[w, 0]**2 + warps[w, 1]**2)
|
|
295
|
+
elif quantity in strain_col:
|
|
296
|
+
v = strains[w, strain_col[quantity]]
|
|
297
|
+
elif quantity == "ep_vol":
|
|
298
|
+
v = vol_strains[w]
|
|
299
|
+
|
|
300
|
+
v = np.atleast_1d(v)
|
|
301
|
+
if dt is None:
|
|
302
|
+
if absolute:
|
|
303
|
+
values[i] = float(np.sum(np.abs(np.diff(v)))) if len(v) > 1 else 0.0
|
|
304
|
+
else:
|
|
305
|
+
values[i] = float(v[-1] - v[0]) if len(v) > 1 else float(v[-1])
|
|
306
|
+
else:
|
|
307
|
+
if len(v) > 1:
|
|
308
|
+
values[i] = float((v[-1] - v[0]) / (len(v) * dt))
|
|
309
|
+
else:
|
|
310
|
+
values[i] = 0.0
|
|
311
|
+
|
|
312
|
+
# Delaunay triangulation
|
|
313
|
+
if n >= 3:
|
|
314
|
+
delaunay = Delaunay(coords)
|
|
315
|
+
triangles = delaunay.simplices
|
|
316
|
+
else:
|
|
317
|
+
triangles = None
|
|
318
|
+
|
|
319
|
+
fig, ax = plt.subplots()
|
|
320
|
+
img_path = getattr(field, 'image_0_path', None)
|
|
321
|
+
_imshow_or_blank(ax, img_path)
|
|
322
|
+
|
|
323
|
+
if triangles is not None and len(triangles) > 0:
|
|
324
|
+
mpl_tri = tri.Triangulation(coords[:, 0], coords[:, 1], triangles)
|
|
325
|
+
cf = ax.tricontourf(mpl_tri, values, **kwargs)
|
|
326
|
+
else:
|
|
327
|
+
cf = ax.scatter(coords[:, 0], coords[:, 1], c=values, **kwargs)
|
|
328
|
+
|
|
329
|
+
if dt is None:
|
|
330
|
+
label = f"{quantity}" + (" (abs)" if absolute else "")
|
|
331
|
+
else:
|
|
332
|
+
label = f"{quantity} /s"
|
|
333
|
+
|
|
334
|
+
cbar = fig.colorbar(cf, ax=ax)
|
|
335
|
+
cbar.set_label(label)
|
|
336
|
+
|
|
337
|
+
plt.tight_layout()
|
|
338
|
+
_show_save_close(fig, show, block, save)
|
|
339
|
+
return fig, ax
|
geopyv_dev/wrappers.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from geopyv_dev import plots
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SubsetWrapper:
|
|
5
|
+
def __init__(self, inner):
|
|
6
|
+
self._inner = inner
|
|
7
|
+
|
|
8
|
+
def __getattr__(self, name):
|
|
9
|
+
return getattr(self._inner, name)
|
|
10
|
+
|
|
11
|
+
def inspect(self, **kwargs):
|
|
12
|
+
return plots.inspect_subset(self._inner, **kwargs)
|
|
13
|
+
|
|
14
|
+
def convergence(self, **kwargs):
|
|
15
|
+
return plots.convergence_subset(self._inner, **kwargs)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MeshWrapper:
|
|
19
|
+
def __init__(self, inner):
|
|
20
|
+
self._inner = inner
|
|
21
|
+
|
|
22
|
+
def __getattr__(self, name):
|
|
23
|
+
return getattr(self._inner, name)
|
|
24
|
+
|
|
25
|
+
def inspect(self, **kwargs):
|
|
26
|
+
return plots.inspect_mesh(self._inner, **kwargs)
|
|
27
|
+
|
|
28
|
+
def convergence(self, quantity="C_ZNCC", **kwargs):
|
|
29
|
+
return plots.convergence_mesh(self._inner, quantity, **kwargs)
|
|
30
|
+
|
|
31
|
+
def contour(self, quantity, **kwargs):
|
|
32
|
+
return plots.contour_mesh(self._inner, quantity, **kwargs)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class ParticleWrapper:
|
|
36
|
+
def __init__(self, inner):
|
|
37
|
+
self._inner = inner
|
|
38
|
+
|
|
39
|
+
def __getattr__(self, name):
|
|
40
|
+
return getattr(self._inner, name)
|
|
41
|
+
|
|
42
|
+
def inspect(self, **kwargs):
|
|
43
|
+
return plots.inspect_particle(self._inner, **kwargs)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class FieldWrapper:
|
|
47
|
+
def __init__(self, inner):
|
|
48
|
+
self._inner = inner
|
|
49
|
+
|
|
50
|
+
def __getattr__(self, name):
|
|
51
|
+
return getattr(self._inner, name)
|
|
52
|
+
|
|
53
|
+
def inspect(self, **kwargs):
|
|
54
|
+
return plots.inspect_field(self._inner, **kwargs)
|
|
55
|
+
|
|
56
|
+
def contour(self, quantity, **kwargs):
|
|
57
|
+
return plots.contour_field(self._inner, quantity, **kwargs)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: geopyv_dev
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Classifier: Programming Language :: Python :: 3
|
|
5
|
+
Classifier: Programming Language :: Rust
|
|
6
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
7
|
+
Classifier: Operating System :: OS Independent
|
|
8
|
+
Classifier: Topic :: Scientific/Engineering
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Summary: A PIV/DIC analysis package for geotechnics.
|
|
11
|
+
Author-email: Sam Stanier <sas229@cam.ac.uk>, Jonathan Smith <jdks2@cam.ac.uk>
|
|
12
|
+
License: GPL-3.0-or-later
|
|
13
|
+
Requires-Python: >=3.8
|
|
14
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
15
|
+
Project-URL: Bug Tracker, https://github.com/jdks2/geopyv-dev/issues
|
|
16
|
+
Project-URL: Homepage, https://github.com/jdks2/geopyv-dev
|
|
17
|
+
|
|
18
|
+
# geopyv-dev
|
|
19
|
+
PIV/DIC package for geotechnics. Under active development.
|
|
20
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
geopyv_dev/__init__.py,sha256=zZ22CcRbt9vlLjmdfOQPTnTAvl0TCVpD6H0rhfSJcN4,354
|
|
2
|
+
geopyv_dev/_geopyv_dev.cp38-win_amd64.pyd,sha256=cgoqS2c_8nX5A9AuxwXce4p0G7uKwZ-JKqLZw5lX4wQ,4067328
|
|
3
|
+
geopyv_dev/plots.py,sha256=TIxO5gr5AzZyjl_qYNyk3pw9du8uKuPpNHWPDo5aVJA,11989
|
|
4
|
+
geopyv_dev/wrappers.py,sha256=u3vsgrDd3Hc8MffLn8oKGdnBUlYEzNGqCgN92Vl9KhQ,1540
|
|
5
|
+
geopyv_dev-0.1.0.dist-info/METADATA,sha256=VDAfBzOUQv3DGwJ1JnMwUAoj2Hyi_Ve4c3yq2ecNuE8,786
|
|
6
|
+
geopyv_dev-0.1.0.dist-info/WHEEL,sha256=xEd7qBFYXQhAn8rGBXan7kyVqAXkLdOy69TzrWTPQxg,95
|
|
7
|
+
geopyv_dev-0.1.0.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
|
|
8
|
+
geopyv_dev-0.1.0.dist-info/sboms/geopyv-dev-python.cyclonedx.json,sha256=KcnEKLERYkoKZBCC6CqRYaDtRtmuRo92uNhNKZNwfC4,178931
|
|
9
|
+
geopyv_dev-0.1.0.dist-info/RECORD,,
|