jarvisplot 1.3.6__tar.gz → 1.3.7__tar.gz
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.
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/JarvisPLOT.egg-info/PKG-INFO +1 -1
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/PKG-INFO +1 -1
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/adapters_rect.py +42 -16
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/interp_natural_neighbor_exact.py +4 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/layer_runtime.py +1 -1
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/pyproject.toml +1 -1
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/tests/test_interp_natural_neighbor.py +2 -1
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/tests/test_jpcontour_methods.py +124 -7
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/JarvisPLOT.egg-info/SOURCES.txt +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/JarvisPLOT.egg-info/dependency_links.txt +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/JarvisPLOT.egg-info/entry_points.txt +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/JarvisPLOT.egg-info/requires.txt +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/JarvisPLOT.egg-info/top_level.txt +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/README.md +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/__init__.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/adapters_ternary.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/cards/std_axes_adapter_config.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/colorbar_runtime.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/config_runtime.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/data_pipelines.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/figure.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/helper.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/interp_natural_neighbor.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/layout_runtime.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/method_registry.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/preprocessor.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/preprocessor_runtime.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/profile_runtime.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/Figure/style_runtime.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/__init__.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cache_store.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/a4paper/1x1/ternary.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/a4paper/2x1/rect.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/a4paper/2x1/rect5x1.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/a4paper/2x1/rect_cmap.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/a4paper/2x1/ternary.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/a4paper/2x1/ternary_cmap.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/a4paper/4x1/rect.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/a4paper/4x1/rect_cmap.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/a4paper/4x1/ternary.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/a4paper/4x1/ternary_cmap.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/args.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/colors/colormaps.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/default/output.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/gambit/1x1/ternary.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/gambit/2x1/rect_cmap.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/gambit/2x1/ternary.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/gambit/2x1/ternary_cmap.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/icons/JarvisHEP.png +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/icons/gambit.png +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/icons/gambit_small.png +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cards/style_preference.json +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/cli.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/client.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/config.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/core.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/core_assets.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/core_runtime.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/data_loader.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/data_loader_hdf5.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/data_loader_runtime.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/data_loader_summary.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/inner_func.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/memtrace.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/utils/__init__.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/utils/cmaps.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/utils/dataframes.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/utils/expression.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/utils/interpolator.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/jarvisplot/utils/pathing.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/setup.cfg +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/tests/test_data_loader_contracts.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/tests/test_docs_status_labels.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/tests/test_figure_contracts.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/tests/test_interpolator_contracts.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/tests/test_parse_data_metadata.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/tests/test_pathing_contracts.py +0 -0
- {jarvisplot-1.3.6 → jarvisplot-1.3.7}/tests/test_template_json.py +0 -0
|
@@ -14,6 +14,8 @@ from .helper import _auto_clip, _mask_by_extend, voronoi_finite_polygons_2d, _cl
|
|
|
14
14
|
from .profile_runtime import grid_profile_mesh
|
|
15
15
|
from .interp_natural_neighbor import resolve_backend
|
|
16
16
|
|
|
17
|
+
DEFAULT_JP_SAMPLE_GRID = 500
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
# —— Basic Adapter: Forward to the underlying Axes, merge default parameters, perform automatic clipping ——
|
|
19
21
|
|
|
@@ -207,7 +209,7 @@ class StdAxesAdapter:
|
|
|
207
209
|
x,
|
|
208
210
|
y,
|
|
209
211
|
*,
|
|
210
|
-
bin: int =
|
|
212
|
+
bin: int = DEFAULT_JP_SAMPLE_GRID,
|
|
211
213
|
nx: Optional[int] = None,
|
|
212
214
|
ny: Optional[int] = None,
|
|
213
215
|
xlim=None,
|
|
@@ -218,8 +220,8 @@ class StdAxesAdapter:
|
|
|
218
220
|
if x.shape[0] != y.shape[0]:
|
|
219
221
|
raise ValueError("x and y must have the same length")
|
|
220
222
|
|
|
221
|
-
nx_eff = self._coerce_positive_int(nx if nx is not None else bin,
|
|
222
|
-
ny_eff = self._coerce_positive_int(ny if ny is not None else bin,
|
|
223
|
+
nx_eff = self._coerce_positive_int(nx if nx is not None else bin, DEFAULT_JP_SAMPLE_GRID)
|
|
224
|
+
ny_eff = self._coerce_positive_int(ny if ny is not None else bin, DEFAULT_JP_SAMPLE_GRID)
|
|
223
225
|
x_norm = self._normalize_jpfield_axis("x", x, bounds=xlim)
|
|
224
226
|
y_norm = self._normalize_jpfield_axis("y", y, bounds=ylim)
|
|
225
227
|
xq = np.linspace(0.0, 1.0, nx_eff)
|
|
@@ -234,7 +236,7 @@ class StdAxesAdapter:
|
|
|
234
236
|
z,
|
|
235
237
|
*,
|
|
236
238
|
interp_method: str = "natural_neighbor",
|
|
237
|
-
bin: int =
|
|
239
|
+
bin: int = DEFAULT_JP_SAMPLE_GRID,
|
|
238
240
|
nx: Optional[int] = None,
|
|
239
241
|
ny: Optional[int] = None,
|
|
240
242
|
xlim=None,
|
|
@@ -279,7 +281,7 @@ class StdAxesAdapter:
|
|
|
279
281
|
x,
|
|
280
282
|
y,
|
|
281
283
|
*,
|
|
282
|
-
bin: int =
|
|
284
|
+
bin: int = DEFAULT_JP_SAMPLE_GRID,
|
|
283
285
|
nx: Optional[int] = None,
|
|
284
286
|
ny: Optional[int] = None,
|
|
285
287
|
xlim=None,
|
|
@@ -301,8 +303,8 @@ class StdAxesAdapter:
|
|
|
301
303
|
except Exception:
|
|
302
304
|
ylim = None
|
|
303
305
|
|
|
304
|
-
nx_eff = self._coerce_positive_int(nx if nx is not None else bin,
|
|
305
|
-
ny_eff = self._coerce_positive_int(ny if ny is not None else bin,
|
|
306
|
+
nx_eff = self._coerce_positive_int(nx if nx is not None else bin, DEFAULT_JP_SAMPLE_GRID)
|
|
307
|
+
ny_eff = self._coerce_positive_int(ny if ny is not None else bin, DEFAULT_JP_SAMPLE_GRID)
|
|
306
308
|
xq = self._resolve_jpcontour_axis("x", x, npts=nx_eff, bounds=xlim)
|
|
307
309
|
yq = self._resolve_jpcontour_axis("y", y, npts=ny_eff, bounds=ylim)
|
|
308
310
|
return np.meshgrid(xq, yq)
|
|
@@ -314,7 +316,7 @@ class StdAxesAdapter:
|
|
|
314
316
|
z,
|
|
315
317
|
*,
|
|
316
318
|
interp_method: str = "natural_neighbor",
|
|
317
|
-
bin: int =
|
|
319
|
+
bin: int = DEFAULT_JP_SAMPLE_GRID,
|
|
318
320
|
nx: Optional[int] = None,
|
|
319
321
|
ny: Optional[int] = None,
|
|
320
322
|
xlim=None,
|
|
@@ -323,13 +325,19 @@ class StdAxesAdapter:
|
|
|
323
325
|
diagnostics: bool = False,
|
|
324
326
|
backend_options: Optional[dict[str, Any]] = None,
|
|
325
327
|
):
|
|
328
|
+
"""Interpolate scattered data on an axes-fraction grid for contour rendering.
|
|
329
|
+
|
|
330
|
+
This keeps jpcontour/jpcontourf aligned with jpfield: coordinates are
|
|
331
|
+
normalized into the current Axes frame before interpolation, then the
|
|
332
|
+
contour artist is drawn with transform=ax.transAxes.
|
|
333
|
+
"""
|
|
326
334
|
x = np.asarray(x, dtype=float).reshape(-1)
|
|
327
335
|
y = np.asarray(y, dtype=float).reshape(-1)
|
|
328
336
|
z = np.asarray(z, dtype=float).reshape(-1)
|
|
329
337
|
if x.shape[0] != y.shape[0] or x.shape[0] != z.shape[0]:
|
|
330
338
|
raise ValueError("x, y, and z must have the same length")
|
|
331
339
|
|
|
332
|
-
X, Y = self.
|
|
340
|
+
X, Y, x_norm, y_norm = self._build_jpfield_grid(
|
|
333
341
|
x,
|
|
334
342
|
y,
|
|
335
343
|
bin=bin,
|
|
@@ -345,8 +353,8 @@ class StdAxesAdapter:
|
|
|
345
353
|
f"Unsupported jpcontour interpolation backend: {interp_method!r}"
|
|
346
354
|
) from exc
|
|
347
355
|
Z = backend(
|
|
348
|
-
|
|
349
|
-
|
|
356
|
+
x_norm,
|
|
357
|
+
y_norm,
|
|
350
358
|
z,
|
|
351
359
|
X,
|
|
352
360
|
Y,
|
|
@@ -489,7 +497,7 @@ class StdAxesAdapter:
|
|
|
489
497
|
z,
|
|
490
498
|
*args,
|
|
491
499
|
interp_method: str = "natural_neighbor",
|
|
492
|
-
bin: int =
|
|
500
|
+
bin: int = DEFAULT_JP_SAMPLE_GRID,
|
|
493
501
|
nx: Optional[int] = None,
|
|
494
502
|
ny: Optional[int] = None,
|
|
495
503
|
xlim=None,
|
|
@@ -499,7 +507,9 @@ class StdAxesAdapter:
|
|
|
499
507
|
backend_options: Optional[dict[str, Any]] = None,
|
|
500
508
|
**kwargs,
|
|
501
509
|
):
|
|
510
|
+
"""Scattered-data contour plot rendered in axes-fraction coordinates."""
|
|
502
511
|
kw = self._merge("contour", kwargs)
|
|
512
|
+
kw.pop("transform", None)
|
|
503
513
|
X, Y, Z = self._interpolate_jpcontour_grid(
|
|
504
514
|
x,
|
|
505
515
|
y,
|
|
@@ -514,7 +524,14 @@ class StdAxesAdapter:
|
|
|
514
524
|
diagnostics=diagnostics,
|
|
515
525
|
backend_options=backend_options,
|
|
516
526
|
)
|
|
517
|
-
artists = self.ax.contour(
|
|
527
|
+
artists = self.ax.contour(
|
|
528
|
+
X,
|
|
529
|
+
Y,
|
|
530
|
+
np.ma.masked_invalid(Z),
|
|
531
|
+
*args,
|
|
532
|
+
transform=self.ax.transAxes,
|
|
533
|
+
**kw,
|
|
534
|
+
)
|
|
518
535
|
return _auto_clip(artists, self.ax, self._clip_path)
|
|
519
536
|
|
|
520
537
|
def jpcontourf(
|
|
@@ -524,7 +541,7 @@ class StdAxesAdapter:
|
|
|
524
541
|
z,
|
|
525
542
|
*args,
|
|
526
543
|
interp_method: str = "natural_neighbor",
|
|
527
|
-
bin: int =
|
|
544
|
+
bin: int = DEFAULT_JP_SAMPLE_GRID,
|
|
528
545
|
nx: Optional[int] = None,
|
|
529
546
|
ny: Optional[int] = None,
|
|
530
547
|
xlim=None,
|
|
@@ -534,7 +551,9 @@ class StdAxesAdapter:
|
|
|
534
551
|
backend_options: Optional[dict[str, Any]] = None,
|
|
535
552
|
**kwargs,
|
|
536
553
|
):
|
|
554
|
+
"""Filled scattered-data contour plot rendered in axes-fraction coordinates."""
|
|
537
555
|
kw = self._merge("contourf", kwargs)
|
|
556
|
+
kw.pop("transform", None)
|
|
538
557
|
X, Y, Z = self._interpolate_jpcontour_grid(
|
|
539
558
|
x,
|
|
540
559
|
y,
|
|
@@ -549,7 +568,14 @@ class StdAxesAdapter:
|
|
|
549
568
|
diagnostics=diagnostics,
|
|
550
569
|
backend_options=backend_options,
|
|
551
570
|
)
|
|
552
|
-
artists = self.ax.contourf(
|
|
571
|
+
artists = self.ax.contourf(
|
|
572
|
+
X,
|
|
573
|
+
Y,
|
|
574
|
+
np.ma.masked_invalid(Z),
|
|
575
|
+
*args,
|
|
576
|
+
transform=self.ax.transAxes,
|
|
577
|
+
**kw,
|
|
578
|
+
)
|
|
553
579
|
return _auto_clip(artists, self.ax, self._clip_path)
|
|
554
580
|
|
|
555
581
|
def jpfield(
|
|
@@ -559,7 +585,7 @@ class StdAxesAdapter:
|
|
|
559
585
|
z,
|
|
560
586
|
*args,
|
|
561
587
|
interp_method: str = "natural_neighbor",
|
|
562
|
-
bin: int =
|
|
588
|
+
bin: int = DEFAULT_JP_SAMPLE_GRID,
|
|
563
589
|
nx: Optional[int] = None,
|
|
564
590
|
ny: Optional[int] = None,
|
|
565
591
|
xlim=None,
|
|
@@ -534,6 +534,8 @@ class NaturalNeighborExactInterpolator:
|
|
|
534
534
|
self._hull_polygon = None
|
|
535
535
|
self.diagnostics.degenerate_input = True
|
|
536
536
|
_warn("natural_neighbor: convex hull is degenerate")
|
|
537
|
+
self.diagnostics.interpolator_ready = False
|
|
538
|
+
return
|
|
537
539
|
else:
|
|
538
540
|
self._hull_polygon = None
|
|
539
541
|
self.diagnostics.degenerate_input = True
|
|
@@ -541,6 +543,8 @@ class NaturalNeighborExactInterpolator:
|
|
|
541
543
|
self._hull_polygon = None
|
|
542
544
|
self.diagnostics.degenerate_input = True
|
|
543
545
|
_warn(f"natural_neighbor: convex hull construction failed: {exc}")
|
|
546
|
+
self.diagnostics.interpolator_ready = False
|
|
547
|
+
return
|
|
544
548
|
|
|
545
549
|
try:
|
|
546
550
|
if coords.shape[0] >= 3:
|
|
@@ -48,7 +48,7 @@ def _coerce_positive_int(value, default: int) -> int:
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
def _resolve_interp_grid_size(interp_cfg: dict | None, x_size: int, y_size: int) -> tuple[int, int]:
|
|
51
|
-
default_n =
|
|
51
|
+
default_n = 500
|
|
52
52
|
if not isinstance(interp_cfg, dict):
|
|
53
53
|
return default_n, default_n
|
|
54
54
|
|
|
@@ -186,7 +186,8 @@ def test_exact_backend_returns_nan_for_collinear_input():
|
|
|
186
186
|
X = np.array([[1.0]])
|
|
187
187
|
Y = np.array([[0.0]])
|
|
188
188
|
|
|
189
|
-
|
|
189
|
+
with pytest.warns(RuntimeWarning):
|
|
190
|
+
Z = natural_neighbor_exact_interpolate(x, y, z, X, Y)
|
|
190
191
|
|
|
191
192
|
assert np.isnan(Z[0, 0])
|
|
192
193
|
diag = natural_neighbor_exact_interpolate.last_diagnostics
|
|
@@ -86,6 +86,47 @@ def test_jpfield_returns_quadmesh():
|
|
|
86
86
|
plt.close(fig)
|
|
87
87
|
|
|
88
88
|
|
|
89
|
+
@pytest.mark.parametrize(
|
|
90
|
+
"method_name, mpl_name",
|
|
91
|
+
[("jpcontour", "contour"), ("jpcontourf", "contourf"), ("jpfield", "pcolormesh")],
|
|
92
|
+
)
|
|
93
|
+
def test_default_jp_sample_grid_is_500_when_bin_is_omitted(monkeypatch, method_name, mpl_name):
|
|
94
|
+
fig, ax = plt.subplots()
|
|
95
|
+
adapter = StdAxesAdapter(ax)
|
|
96
|
+
|
|
97
|
+
backend_calls = {}
|
|
98
|
+
|
|
99
|
+
def fake_backend(
|
|
100
|
+
x,
|
|
101
|
+
y,
|
|
102
|
+
z,
|
|
103
|
+
X,
|
|
104
|
+
Y,
|
|
105
|
+
*,
|
|
106
|
+
nan_policy="strict",
|
|
107
|
+
diagnostics=False,
|
|
108
|
+
backend_options=None,
|
|
109
|
+
):
|
|
110
|
+
backend_calls["grid_shape"] = X.shape
|
|
111
|
+
return np.asarray(X + Y, dtype=float)
|
|
112
|
+
|
|
113
|
+
monkeypatch.setattr(adapters_rect_mod, "resolve_backend", lambda name: fake_backend)
|
|
114
|
+
monkeypatch.setattr(adapter.ax, mpl_name, lambda *args, **kwargs: SimpleNamespace(tag=method_name))
|
|
115
|
+
|
|
116
|
+
x = np.array([0.0, 1.0, 0.0, 1.0])
|
|
117
|
+
y = np.array([0.0, 0.0, 1.0, 1.0])
|
|
118
|
+
z = np.array([0.0, 1.0, 1.0, 2.0])
|
|
119
|
+
|
|
120
|
+
if method_name == "jpfield":
|
|
121
|
+
out = getattr(adapter, method_name)(x, y, z, cmap="viridis")
|
|
122
|
+
else:
|
|
123
|
+
out = getattr(adapter, method_name)(x, y, z, levels=3, cmap="viridis")
|
|
124
|
+
|
|
125
|
+
assert out.tag == method_name
|
|
126
|
+
assert backend_calls["grid_shape"] == (500, 500)
|
|
127
|
+
plt.close(fig)
|
|
128
|
+
|
|
129
|
+
|
|
89
130
|
@pytest.mark.parametrize("method_name", ["jpcontour", "jpcontourf"])
|
|
90
131
|
def test_render_layer_dispatches_jpcontour_methods_with_scattered_inputs(monkeypatch, method_name):
|
|
91
132
|
df = pd.DataFrame(
|
|
@@ -163,6 +204,8 @@ def test_jpcontour_strips_interp_kwargs_and_preserves_masked_nan_grid(monkeypatc
|
|
|
163
204
|
diagnostics=False,
|
|
164
205
|
backend_options=None,
|
|
165
206
|
):
|
|
207
|
+
backend_calls["x"] = np.asarray(x, dtype=float)
|
|
208
|
+
backend_calls["y"] = np.asarray(y, dtype=float)
|
|
166
209
|
backend_calls["nan_policy"] = nan_policy
|
|
167
210
|
backend_calls["diagnostics"] = diagnostics
|
|
168
211
|
backend_calls["backend_options"] = backend_options
|
|
@@ -184,8 +227,8 @@ def test_jpcontour_strips_interp_kwargs_and_preserves_masked_nan_grid(monkeypatc
|
|
|
184
227
|
|
|
185
228
|
monkeypatch.setattr(adapter.ax, mpl_name, recorder)
|
|
186
229
|
|
|
187
|
-
x = np.array([0.0, 1.0,
|
|
188
|
-
y = np.array([0.0, 0.
|
|
230
|
+
x = np.array([0.0, 1.0, 2.0, 2.0])
|
|
231
|
+
y = np.array([0.0, 0.5, 1.5, 2.0])
|
|
189
232
|
z = np.array([0.0, 1.0, 1.0, 2.0])
|
|
190
233
|
|
|
191
234
|
out = getattr(adapter, method_name)(
|
|
@@ -199,8 +242,8 @@ def test_jpcontour_strips_interp_kwargs_and_preserves_masked_nan_grid(monkeypatc
|
|
|
199
242
|
bin=6,
|
|
200
243
|
nx=4,
|
|
201
244
|
ny=5,
|
|
202
|
-
xlim=(
|
|
203
|
-
ylim=(
|
|
245
|
+
xlim=(0.0, 2.0),
|
|
246
|
+
ylim=(0.0, 2.0),
|
|
204
247
|
nan_policy="strict",
|
|
205
248
|
diagnostics=True,
|
|
206
249
|
backend_options={"vertex_tol": 1.0e-6},
|
|
@@ -211,10 +254,15 @@ def test_jpcontour_strips_interp_kwargs_and_preserves_masked_nan_grid(monkeypatc
|
|
|
211
254
|
assert backend_calls["diagnostics"] is True
|
|
212
255
|
assert backend_calls["backend_options"] == {"vertex_tol": 1.0e-6}
|
|
213
256
|
assert backend_calls["grid_shape"] == (5, 4)
|
|
214
|
-
assert backend_calls["x_range"] == (
|
|
215
|
-
assert backend_calls["y_range"] == (
|
|
257
|
+
assert backend_calls["x_range"] == (0.0, 1.0)
|
|
258
|
+
assert backend_calls["y_range"] == (0.0, 1.0)
|
|
259
|
+
np.testing.assert_allclose(backend_calls["x"], np.array([0.0, 0.5, 1.0, 1.0]))
|
|
260
|
+
np.testing.assert_allclose(backend_calls["y"], np.array([0.0, 0.25, 0.75, 1.0]))
|
|
216
261
|
|
|
217
|
-
assert mpl_calls["kwargs"]
|
|
262
|
+
assert mpl_calls["kwargs"]["levels"] == 3
|
|
263
|
+
assert mpl_calls["kwargs"]["colors"] == "k"
|
|
264
|
+
assert mpl_calls["kwargs"]["linewidths"] == 2.0
|
|
265
|
+
assert mpl_calls["kwargs"]["transform"] is adapter.ax.transAxes
|
|
218
266
|
z_arg = mpl_calls["args"][2]
|
|
219
267
|
assert np.ma.isMaskedArray(z_arg)
|
|
220
268
|
mask = np.ma.getmaskarray(z_arg)
|
|
@@ -224,6 +272,73 @@ def test_jpcontour_strips_interp_kwargs_and_preserves_masked_nan_grid(monkeypatc
|
|
|
224
272
|
plt.close(fig)
|
|
225
273
|
|
|
226
274
|
|
|
275
|
+
def test_render_layer_contourf_defaults_to_500_grid_when_interp_bin_missing(monkeypatch):
|
|
276
|
+
df = pd.DataFrame(
|
|
277
|
+
{
|
|
278
|
+
"x": [0.0, 1.0, 0.0, 1.0],
|
|
279
|
+
"y": [0.0, 0.0, 1.0, 1.0],
|
|
280
|
+
"z": [0.0, 1.0, 1.0, 2.0],
|
|
281
|
+
}
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
fig = SimpleNamespace(
|
|
285
|
+
logger=SimpleNamespace(debug=lambda *args, **kwargs: None, warning=lambda *args, **kwargs: None),
|
|
286
|
+
style={"contourf": {"interp": {"method": "natural_neighbor"}, "levels": 3}},
|
|
287
|
+
_ensure_pandas_data=lambda data, reason="render": data,
|
|
288
|
+
_eval_series=lambda data, spec: np.asarray(data[spec["expr"]]),
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
ax = SimpleNamespace(
|
|
292
|
+
_type="rect",
|
|
293
|
+
get_xscale=lambda: "linear",
|
|
294
|
+
get_yscale=lambda: "linear",
|
|
295
|
+
get_xlim=lambda: (0.0, 1.0),
|
|
296
|
+
get_ylim=lambda: (0.0, 1.0),
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
backend_calls = {}
|
|
300
|
+
|
|
301
|
+
def fake_backend(
|
|
302
|
+
x,
|
|
303
|
+
y,
|
|
304
|
+
z,
|
|
305
|
+
X,
|
|
306
|
+
Y,
|
|
307
|
+
*,
|
|
308
|
+
nan_policy="strict",
|
|
309
|
+
diagnostics=False,
|
|
310
|
+
backend_options=None,
|
|
311
|
+
):
|
|
312
|
+
backend_calls["grid_shape"] = X.shape
|
|
313
|
+
return X + Y
|
|
314
|
+
|
|
315
|
+
method_calls = {}
|
|
316
|
+
|
|
317
|
+
def dummy_method(*args, **kwargs):
|
|
318
|
+
method_calls["kwargs"] = dict(kwargs)
|
|
319
|
+
return "ok"
|
|
320
|
+
|
|
321
|
+
monkeypatch.setattr(layer_runtime_mod, "resolve_backend", lambda name: fake_backend)
|
|
322
|
+
monkeypatch.setattr(layer_runtime_mod, "resolve_callable", lambda *args, **kwargs: (dummy_method, None))
|
|
323
|
+
monkeypatch.setattr(layer_runtime_mod, "collect_and_attach_colorbar", lambda *args, **kwargs: args[1])
|
|
324
|
+
|
|
325
|
+
out = layer_runtime_mod.render_layer(
|
|
326
|
+
fig,
|
|
327
|
+
ax,
|
|
328
|
+
{
|
|
329
|
+
"name": "contourf-layer",
|
|
330
|
+
"method": "contourf",
|
|
331
|
+
"data": df,
|
|
332
|
+
"coor": {"x": {"expr": "x"}, "y": {"expr": "y"}, "z": {"expr": "z"}},
|
|
333
|
+
"style": {},
|
|
334
|
+
},
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
assert out == "ok"
|
|
338
|
+
assert backend_calls["grid_shape"] == (500, 500)
|
|
339
|
+
assert method_calls["kwargs"]["levels"] == 3
|
|
340
|
+
|
|
341
|
+
|
|
227
342
|
def test_jpfield_strips_interp_kwargs_and_preserves_masked_nan_grid(monkeypatch):
|
|
228
343
|
fig, ax = plt.subplots()
|
|
229
344
|
adapter = StdAxesAdapter(ax)
|
|
@@ -457,6 +572,7 @@ def test_ternary_jpcontourf_accepts_left_right_bottom(monkeypatch):
|
|
|
457
572
|
np.testing.assert_allclose(backend_calls["y"], expected_y)
|
|
458
573
|
np.testing.assert_allclose(backend_calls["z"], z)
|
|
459
574
|
assert mpl_calls["kwargs"]["levels"] == 4
|
|
575
|
+
assert mpl_calls["kwargs"]["transform"] is adapter.ax.transAxes
|
|
460
576
|
plt.close(fig)
|
|
461
577
|
|
|
462
578
|
|
|
@@ -626,4 +742,5 @@ def test_jpcontour_strips_interpolation_kwargs_from_mpl_call(monkeypatch):
|
|
|
626
742
|
assert "ylim" not in mpl_calls["kwargs"]
|
|
627
743
|
assert "nan_policy" not in mpl_calls["kwargs"]
|
|
628
744
|
assert "backend_options" not in mpl_calls["kwargs"]
|
|
745
|
+
assert mpl_calls["kwargs"]["transform"] is adapter.ax.transAxes
|
|
629
746
|
plt.close(fig)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|