Skip to content

Commit 1d02032

Browse files
committed
Fix skipped tests for Python 3.14
1 parent 1bbfa0c commit 1d02032

8 files changed

Lines changed: 158 additions & 126 deletions

openpiv/PIV_3D_plotting.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ def scatter_3D(a, cmap="jet", sca_args=None, control="color", size=60):
7171
sm = matplotlib.cm.ScalarMappable(cmap=cmap, norm=norm)
7272
sm.set_array([])
7373
# different option
74-
cm = matplotlib.cm.get_cmap(cmap)
74+
cm = matplotlib.colormaps.get_cmap(cmap)
7575
colors = cm(norm(a)).reshape(a.shape[0] * a.shape[1] * a.shape[2], 4) #
7676
# plotting
7777
nan_filter = ~np.isnan(a.flatten())
@@ -83,7 +83,7 @@ def scatter_3D(a, cmap="jet", sca_args=None, control="color", size=60):
8383
s=size,
8484
**scatter_args
8585
)
86-
plt.colorbar(sm)
86+
fig.colorbar(sm, ax=ax)
8787

8888
if control == "alpha":
8989
# untested #
@@ -92,8 +92,12 @@ def scatter_3D(a, cmap="jet", sca_args=None, control="color", size=60):
9292
plt.show()
9393

9494
if control == "size":
95-
sizes = (a - a.min()) * size / a.ptp()
96-
ax.scatter(x, y, z, a, s=sizes, **scatter_args)
95+
value_range = np.ptp(a)
96+
if value_range == 0:
97+
sizes = np.full(a.shape, size, dtype=float)
98+
else:
99+
sizes = (a - a.min()) * size / value_range
100+
ax.scatter(x, y, z, c=a.flatten(), s=sizes.flatten(), **scatter_args)
97101
ax_scale = plt.axes([0.88, 0.1, 0.05, 0.7])
98102
# ax_scale.set_ylim((0.1,1.2))
99103
nm = 5
@@ -172,12 +176,13 @@ def plot_3D_alpha(data):
172176
z[:, :, 1::2] += 0.95
173177

174178
fig = plt.figure()
175-
ax = fig.gca(projection="3d")
179+
ax = fig.add_subplot(projection="3d")
176180
ax.voxels(x, y, z, fill, facecolors=col_exp, edgecolors=col_exp)
177181
ax.set_xlabel("x")
178182
ax.set_ylabel("y")
179183
ax.set_zlabel("z")
180184
plt.show()
185+
return fig
181186

182187

183188
def quiver_3D(
@@ -332,11 +337,11 @@ def quiver_3D(
332337

333338
# plotting
334339
fig = plt.figure()
335-
ax = fig.gca(projection="3d", rasterized=True)
340+
ax = fig.add_subplot(projection="3d", rasterized=True)
336341
ax.quiver(
337342
xf, yf, zf, vf * scale, uf * scale, wf * scale, colors=colors, **quiver_args
338343
)
339-
plt.colorbar(sm)
344+
fig.colorbar(sm, ax=ax)
340345

341346
ax.set_xlim(ax_dims[0])
342347
ax.set_ylim(ax_dims[1])
@@ -348,8 +353,9 @@ def quiver_3D(
348353
ax.set_xlabel("x")
349354
ax.set_ylabel("y")
350355
ax.set_zlabel("z")
351-
ax.w_xaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
352-
ax.w_yaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
353-
ax.w_zaxis.set_pane_color((0.2, 0.2, 0.2, 1.0))
356+
for axis in (ax.xaxis, ax.yaxis, ax.zaxis):
357+
pane = getattr(axis, "pane", None)
358+
if pane is not None:
359+
pane.set_facecolor((0.2, 0.2, 0.2, 1.0))
354360

355361
return fig

openpiv/filters.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -174,22 +174,21 @@ def replace_outliers(
174174
# regardless the grid_mask (which is a user-provided masked region)
175175

176176

177-
# Only create masked array if needed
178-
if isinstance(u, np.ma.MaskedArray):
179-
grid_mask = u.mask.copy()
180-
else:
181-
u = np.ma.masked_array(u, mask=np.ma.nomask)
182-
grid_mask = np.ma.nomask
183-
184-
u[flags] = np.nan
185-
v[flags] = np.nan
177+
has_mask = isinstance(u, np.ma.MaskedArray)
178+
grid_mask = np.ma.getmaskarray(u).copy() if has_mask else np.ma.nomask
179+
180+
u_data = np.array(np.ma.getdata(u), copy=True)
181+
v_data = np.array(np.ma.getdata(v), copy=True)
182+
183+
u_data[flags] = np.nan
184+
v_data[flags] = np.nan
186185

187186
uf = replace_nans(
188-
u, method=method, max_iter=max_iter, tol=tol,
187+
u_data, method=method, max_iter=max_iter, tol=tol,
189188
kernel_size=kernel_size
190189
)
191190
vf = replace_nans(
192-
v, method=method, max_iter=max_iter, tol=tol,
191+
v_data, method=method, max_iter=max_iter, tol=tol,
193192
kernel_size=kernel_size
194193
)
195194

@@ -198,9 +197,10 @@ def replace_outliers(
198197
vf = np.ma.masked_array(vf, mask=grid_mask)
199198

200199
if isinstance(w, np.ndarray):
201-
w[flags] = np.nan
200+
w_data = np.array(np.ma.getdata(w), copy=True)
201+
w_data[flags] = np.nan
202202
wf = replace_nans(
203-
w, method=method, max_iter=max_iter, tol=tol,
203+
w_data, method=method, max_iter=max_iter, tol=tol,
204204
kernel_size=kernel_size
205205
)
206206
wf = np.ma.masked_array(wf, mask=grid_mask)

openpiv/test/test_PIV_3D_plotting.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
import os
44
import numpy as np
55
import pytest
6+
import matplotlib
7+
8+
matplotlib.use("Agg")
9+
610
import matplotlib.pyplot as plt
711
from mpl_toolkits.mplot3d import Axes3D
812
from matplotlib.testing.compare import compare_images
@@ -15,9 +19,7 @@
1519
quiver_3D
1620
)
1721

18-
# Skip all tests that require displaying plots if running in a headless environment
19-
# or if there are compatibility issues with the current matplotlib version
20-
SKIP_PLOT_TESTS = True
22+
SKIP_PLOT_TESTS = False
2123

2224
# Create a temporary directory for test images
2325
@pytest.fixture
@@ -91,7 +93,6 @@ def test_explode():
9193
assert np.all(result_4d[::2, ::2, ::2, :] == 1)
9294
assert np.all(result_4d[1::2, ::2, ::2, :] == 0)
9395

94-
@pytest.mark.skipif(SKIP_PLOT_TESTS, reason="Skipping plot tests due to compatibility issues")
9596
def test_scatter_3D():
9697
"""Test scatter_3D function with color control"""
9798
# Create a simple 3D array
@@ -119,7 +120,6 @@ def test_scatter_3D():
119120
# Clean up
120121
plt.close(fig)
121122

122-
@pytest.mark.skipif(SKIP_PLOT_TESTS, reason="Skipping plot tests due to compatibility issues")
123123
def test_scatter_3D_size_control():
124124
"""Test scatter_3D function with size control"""
125125
# Create a simple 3D array
@@ -144,7 +144,6 @@ def test_scatter_3D_size_control():
144144
# Clean up
145145
plt.close(fig)
146146

147-
@pytest.mark.skipif(SKIP_PLOT_TESTS, reason="Skipping plot tests due to compatibility issues")
148147
def test_quiver_3D():
149148
"""Test quiver_3D function"""
150149
# Create simple vector field
@@ -174,7 +173,6 @@ def test_quiver_3D():
174173
# Clean up
175174
plt.close(fig)
176175

177-
@pytest.mark.skipif(SKIP_PLOT_TESTS, reason="Skipping plot tests due to compatibility issues")
178176
def test_quiver_3D_with_coordinates():
179177
"""Test quiver_3D function with custom coordinates"""
180178
# Create simple vector field
@@ -207,7 +205,6 @@ def test_quiver_3D_with_coordinates():
207205
# Clean up
208206
plt.close(fig)
209207

210-
@pytest.mark.skipif(SKIP_PLOT_TESTS, reason="Skipping plot tests due to compatibility issues")
211208
def test_quiver_3D_with_filter():
212209
"""Test quiver_3D function with filtering"""
213210
# Create vector field with multiple vectors
@@ -222,9 +219,18 @@ def test_quiver_3D_with_filter():
222219
# Clean up
223220
plt.close(fig)
224221

225-
# Skip test_plot_3D_alpha for now as it's more complex and requires more setup
226-
@pytest.mark.skip(reason="Complex test requiring more setup")
227222
def test_plot_3D_alpha():
228223
"""Test plot_3D_alpha function"""
229-
# This would require more complex setup and validation
230-
pass
224+
data = np.zeros((3, 3, 3), dtype=float)
225+
data[1, 1, 1] = 1.0
226+
227+
fig = plot_3D_alpha(data)
228+
229+
assert isinstance(fig, plt.Figure)
230+
ax = fig.axes[0]
231+
assert isinstance(ax, Axes3D)
232+
assert ax.get_xlabel() == "x"
233+
assert ax.get_ylabel() == "y"
234+
assert ax.get_zlabel() == "z"
235+
236+
plt.close(fig)

openpiv/test/test_performance.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,14 @@ def test_replace_outliers_performance():
9090
u = np.random.randn(50, 50) * 10
9191
v = np.random.randn(50, 50) * 10
9292
flags = np.random.rand(50, 50) > 0.95 # 5% outliers
93+
94+
# Warm up the compiled/scipy-backed path before timing.
95+
filters.replace_outliers(u, v, flags, method='localmean', max_iter=3)
9396

9497
# Test with regular arrays
95-
start = time.time()
98+
start = time.perf_counter()
9699
uf, vf = filters.replace_outliers(u, v, flags, method='localmean', max_iter=3)
97-
elapsed = time.time() - start
100+
elapsed = time.perf_counter() - start
98101

99102
assert uf.shape == u.shape
100103
assert vf.shape == v.shape

openpiv/test/test_tools_background.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ def create_test_images(num_images=3, size=(20, 20)):
3838
return image_files
3939

4040

41-
@pytest.mark.skip(reason="Requires fixing mark_background function")
4241
def test_mark_background():
4342
"""Test mark_background function"""
4443
try:
@@ -112,7 +111,6 @@ def test_mark_background2():
112111
os.unlink(output_file)
113112

114113

115-
@pytest.mark.skip(reason="Requires fixing find_reflexions function")
116114
def test_find_reflexions():
117115
"""Test find_reflexions function"""
118116
try:
@@ -149,7 +147,6 @@ def test_find_reflexions():
149147
os.unlink(output_file)
150148

151149

152-
@pytest.mark.skip(reason="Requires fixing find_boundaries function")
153150
def test_find_boundaries():
154151
"""Test find_boundaries function"""
155152
try:

openpiv/test/test_tools_image_processing.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,25 @@ def test_imsave_tiff_format():
205205
os.unlink(tmp.name)
206206

207207

208-
@pytest.mark.skip(reason="Requires creating a 16-bit TIFF file")
209208
def test_convert_16bits_tif():
210209
"""Test convert_16bits_tif function"""
211-
# This test would require creating a 16-bit TIFF file
212-
# For now, we'll skip it and implement it later
213-
pass
210+
img = np.zeros((10, 10), dtype=np.uint16)
211+
img[2:8, 2:8] = np.iinfo(np.uint16).max
212+
213+
with tempfile.NamedTemporaryFile(suffix='.tif', delete=False) as source:
214+
Image.fromarray(img).save(source.name, format='TIFF')
215+
216+
with tempfile.NamedTemporaryFile(suffix='.png', delete=False) as destination:
217+
output_name = destination.name
218+
219+
try:
220+
convert_16bits_tif(source.name, output_name)
221+
222+
read_img = imread(output_name)
223+
224+
assert read_img.shape == (10, 10)
225+
assert np.all(read_img[2:8, 2:8] == 255)
226+
assert np.all(read_img[0:2, 0:2] == 0)
227+
finally:
228+
os.unlink(source.name)
229+
os.unlink(output_name)

openpiv/test/test_tools_vector_field.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@ def test_display_vector_field_from_arrays(show_invalid):
205205

206206

207207
@pytest.mark.parametrize("method", ["standard", "random"])
208-
@pytest.mark.skip(reason="Requires interactive matplotlib backend")
209208
def test_display_windows_sampling(method):
210209
"""Test display_windows_sampling function"""
211210
# Create test data

0 commit comments

Comments
 (0)