diff --git a/CHANGELOG.md b/CHANGELOG.md index a0c25e70..3ee7c95b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,12 +14,13 @@ of being developed elsewhere. ----- -### Version `3.5.X`, first released 2026-10-09 +### Version `3.5.X`, first released XXXXXX #### Version `3.5.1`, released 2026-??-?? * Update code to prevent deprecation-related warnings (https://github.com/NCAS-CMS/cf-plot/issues/72) +* Prevent striped artefacts on curvilinear longitude/latitude grids such as NEMO. #### Version `3.5.0`, released 2026-10-09 diff --git a/cfplot/blockfill.py b/cfplot/blockfill.py index 846bcada..1270d7f6 100644 --- a/cfplot/blockfill.py +++ b/cfplot/blockfill.py @@ -108,9 +108,11 @@ def _bfill( colarr[pts] = np.size(levels) - 2 if isinstance(field, np.ma.MaskedArray): - pts = np.ma.where(field.mask) - if np.size(pts) > 0: - colarr[pts] = -1 + # np.ma.where on a scalar False mask raises on newer NumPy. + # Use a normalized boolean mask array instead. + mask = np.ma.getmaskarray(field) + if np.any(mask): + colarr[mask] = -1 norm = matplotlib.colors.BoundaryNorm(levels, cmap.N) diff --git a/cfplot/contour.py b/cfplot/contour.py index f4266017..10f156c1 100644 --- a/cfplot/contour.py +++ b/cfplot/contour.py @@ -682,7 +682,7 @@ def render_filled( runtime.image = runtime.mymap.contourf( lons, lats, - self.data.field * self.data.fmult, + _mask_curvilinear_contour_seams(self.data) * self.data.fmult, self.data.levels, extend=scale.levels_extend, cmap=cmap, @@ -792,10 +792,11 @@ def render_lines( runtime = plotvars.runtime dec = plotvars.decoration + field = _mask_curvilinear_contour_seams(self.data) * self.data.fmult cs = runtime.mymap.contour( self.data.x, self.data.y, - self.data.field * self.data.fmult, + field, self.data.levels, colors=colors, linewidths=linewidths, @@ -825,7 +826,7 @@ def render_lines( cs0 = runtime.mymap.contour( self.data.x, self.data.y, - self.data.field * self.data.fmult, + field, [-1e-32, 0], colors=colors, linewidths=zero_thick, @@ -1697,6 +1698,70 @@ def _window_irregular_map_data( return field_irregular, lons_irregular, lats_irregular +def _is_curvilinear_map_grid(data: ContourData) -> bool: + """Return True for map plots using 2D lon/lat coordinates. + + Curvilinear grids (for example NEMO/ORCA ocean meshes) are prone to + severe contourf/contour artefacts. These are better rendered through + blockfill/pcolormesh. + """ + if data.ptype != 1 or data.x is None or data.y is None: + return False + if np.ndim(data.field) != 2: + return False + return np.ndim(data.x) == 2 and np.ndim(data.y) == 2 + + +def _mask_curvilinear_contour_seams(data: ContourData) -> np.ndarray: + """Exclude vertices adjoining longitude jumps from structured contours.""" + if not _is_curvilinear_map_grid(data): + return data.field + + mask = np.ma.getmaskarray(data.field).copy() + for axis in (0, 1): + jumps = np.abs(np.diff(data.x, axis=axis)) > 180.0 + before = [slice(None), slice(None)] + after = before.copy() + before[axis] = slice(None, -1) + after[axis] = slice(1, None) + # Mask both ends so corner masking cannot retain a seam-crossing + # triangle and interpolate a contour across the whole map. + mask[tuple(before)] |= jumps + mask[tuple(after)] |= jumps + + return np.ma.array(data.field, mask=mask) + + +def _resolve_curvilinear_render_defaults( + *, + data: ContourData, + kwargs: dict[str, Any], + fill: bool, + lines: bool, + blockfill: bool, + blockfill_fast: bool | None, +) -> tuple[bool, bool, bool, bool | None]: + """Adjust renderer defaults for curvilinear lon/lat map grids. + + Returns the possibly updated (fill, lines, blockfill, blockfill_fast) + tuple. + """ + if not _is_curvilinear_map_grid(data): + return fill, lines, blockfill, blockfill_fast + + # Use robust defaults for 2D map grids unless the caller explicitly + # requested alternative behavior. + if "blockfill" not in kwargs: + blockfill = True + fill = False + if blockfill and blockfill_fast is None: + blockfill_fast = True + if "lines" not in kwargs: + lines = False + + return fill, lines, blockfill, blockfill_fast + + def _render_with_new_xy( f: Any, x: Any, y: Any, kwargs: dict[str, Any] ) -> bool: @@ -1776,6 +1841,7 @@ def _render_with_new_xy( fill = kwargs.get("fill", global_fill) lines = kwargs.get("lines", global_lines) blockfill = kwargs.get("blockfill", global_blockfill) + blockfill_fast = kwargs.get("blockfill_fast", None) line_labels = kwargs.get("line_labels", True) zero_thick = kwargs.get("zero_thick", False) colors = kwargs.get("colors", "k") @@ -1787,6 +1853,17 @@ def _render_with_new_xy( if blockfill: fill = False + fill, lines, blockfill, blockfill_fast = ( + _resolve_curvilinear_render_defaults( + data=data, + kwargs=kwargs, + fill=fill, + lines=lines, + blockfill=blockfill, + blockfill_fast=blockfill_fast, + ) + ) + colorbar = kwargs.get("colorbar", True) if not fill and not blockfill: colorbar = False @@ -2171,7 +2248,7 @@ def _render_with_new_xy( ) if blockfill: renderer.render_blockfill( - fast=kwargs.get("blockfill_fast", None), alpha=alpha, zorder=zorder + fast=blockfill_fast, alpha=alpha, zorder=zorder ) if lines: renderer.render_lines( @@ -2350,7 +2427,11 @@ def con(f=None, x=None, y=None, **kwargs): | 6 = rotated pole | negative_linestyle='solid' - set to one of 'solid', 'dashed' | zero_thick=False - add a thick zero contour line. Set to 3 for example. - | blockfill=False - set to True for a blockfill plot + | blockfill=False - set to True for a blockfill plot. For 2D lon/lat + | grids, defaults to fast blockfill without lines. + | Explicit False selects contours; vertices adjoining + | longitude wrap jumps are excluded to avoid stripes, + | leaving a narrow gap at the seam. | colorbar_title=colbar_title - title for the colour bar | colorbar=True - add a colour bar if a filled contour plot | colorbar_label_skip=None - skip colour bar labels. Set to 2 to skip diff --git a/docs/source/examples/example_1.rst b/docs/source/examples/example_1.rst index d0600d87..146a6e10 100644 --- a/docs/source/examples/example_1.rst +++ b/docs/source/examples/example_1.rst @@ -14,4 +14,4 @@ Example 1: Basic contour plot in default projection cfp.con(f.subspace(time=15)) -.. figure:: /../../tests/reference-example-images/ref_fig_1.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_1.png diff --git a/docs/source/examples/example_10.rst b/docs/source/examples/example_10.rst index 63d61fe5..87586a29 100644 --- a/docs/source/examples/example_10.rst +++ b/docs/source/examples/example_10.rst @@ -14,4 +14,4 @@ Example 10: Latitude-time Hovmöller plot cfp.con(f.subspace(longitude=0), lines=0) -.. figure:: /../../tests/reference-example-images/ref_fig_10.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_10.png diff --git a/docs/source/examples/example_11.rst b/docs/source/examples/example_11.rst index b6b387cb..a93c4f75 100644 --- a/docs/source/examples/example_11.rst +++ b/docs/source/examples/example_11.rst @@ -18,4 +18,4 @@ Example 11: Latitude-time subset view Hovmöller plot cfp.con(f.subspace(longitude=0), lines=0) -.. figure:: /../../tests/reference-example-images/ref_fig_11.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_11.png diff --git a/docs/source/examples/example_12.rst b/docs/source/examples/example_12.rst index 3d8997c9..ec1b2049 100644 --- a/docs/source/examples/example_12.rst +++ b/docs/source/examples/example_12.rst @@ -14,4 +14,4 @@ Example 12: Longitude-time Hovmöller plot cfp.con(f.subspace(latitude=0), lines=0) -.. figure:: /../../tests/reference-example-images/ref_fig_12.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_12.png diff --git a/docs/source/examples/example_13.rst b/docs/source/examples/example_13.rst index d2409c9d..55371e54 100644 --- a/docs/source/examples/example_13.rst +++ b/docs/source/examples/example_13.rst @@ -18,4 +18,4 @@ Example 13: Basic vector plot cfp.vect(u=u, v=v, key_length=10, scale=100, stride=5) -.. figure:: /../../tests/reference-example-images/ref_fig_13.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_13.png diff --git a/docs/source/examples/example_14.rst b/docs/source/examples/example_14.rst index 8025a452..865dca79 100644 --- a/docs/source/examples/example_14.rst +++ b/docs/source/examples/example_14.rst @@ -26,4 +26,4 @@ Example 14: Vector plot overlaid on a contour map cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_14.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_14.png diff --git a/docs/source/examples/example_15.rst b/docs/source/examples/example_15.rst index e00cbf84..6da06aac 100644 --- a/docs/source/examples/example_15.rst +++ b/docs/source/examples/example_15.rst @@ -37,4 +37,4 @@ Example 15: Polar projection vector plot cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_15.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_15.png diff --git a/docs/source/examples/example_16a.rst b/docs/source/examples/example_16a.rst index 55661137..5b7a5e58 100644 --- a/docs/source/examples/example_16a.rst +++ b/docs/source/examples/example_16a.rst @@ -29,4 +29,4 @@ Example 16a: Zonal vector plot ) -.. figure:: /../../tests/reference-example-images/ref_fig_16a.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_16a.png diff --git a/docs/source/examples/example_16b.rst b/docs/source/examples/example_16b.rst index ce5d92ef..2323e042 100644 --- a/docs/source/examples/example_16b.rst +++ b/docs/source/examples/example_16b.rst @@ -21,4 +21,4 @@ Example 16b: Basic stream plot cfp.stream(u=u, v=v, density=2) -.. figure:: /../../tests/reference-example-images/ref_fig_16b.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_16b.png diff --git a/docs/source/examples/example_16c.rst b/docs/source/examples/example_16c.rst index ef1dcf11..f76c43ee 100644 --- a/docs/source/examples/example_16c.rst +++ b/docs/source/examples/example_16c.rst @@ -34,4 +34,4 @@ Example 16c: Stream plot in a colour scale ) cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_16c.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_16c.png diff --git a/docs/source/examples/example_17.rst b/docs/source/examples/example_17.rst index b3513df2..b10811e4 100644 --- a/docs/source/examples/example_17.rst +++ b/docs/source/examples/example_17.rst @@ -22,4 +22,4 @@ Example 17: Basic stipple plot cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_17.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_17.png diff --git a/docs/source/examples/example_18.rst b/docs/source/examples/example_18.rst index 274bd933..66802eac 100644 --- a/docs/source/examples/example_18.rst +++ b/docs/source/examples/example_18.rst @@ -19,4 +19,4 @@ Example 18: Polar stipple plot cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_18.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_18.png diff --git a/docs/source/examples/example_19a.rst b/docs/source/examples/example_19a.rst index 1cabefb8..6f46b760 100644 --- a/docs/source/examples/example_19a.rst +++ b/docs/source/examples/example_19a.rst @@ -29,4 +29,4 @@ Example 19a: Multiple plots cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_19a.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_19a.png diff --git a/docs/source/examples/example_19b.rst b/docs/source/examples/example_19b.rst index 730a2a73..55d5e3df 100644 --- a/docs/source/examples/example_19b.rst +++ b/docs/source/examples/example_19b.rst @@ -25,4 +25,4 @@ Example 19b: Multiple plots with user-specified plot positions cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_19b.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_19b.png diff --git a/docs/source/examples/example_19c.rst b/docs/source/examples/example_19c.rst index 650e1424..e7599af8 100644 --- a/docs/source/examples/example_19c.rst +++ b/docs/source/examples/example_19c.rst @@ -39,4 +39,4 @@ Example 19c: Accomodating more than one colour bar cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_19c.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_19c.png diff --git a/docs/source/examples/example_2.rst b/docs/source/examples/example_2.rst index 3f166095..a1e1aa31 100644 --- a/docs/source/examples/example_2.rst +++ b/docs/source/examples/example_2.rst @@ -13,4 +13,4 @@ Example 2: Basic blockfill plot in default projection cfp.con(f.subspace(time=15), blockfill=True, lines=False) -.. figure:: /../../tests/reference-example-images/ref_fig_2.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_2.png diff --git a/docs/source/examples/example_20.rst b/docs/source/examples/example_20.rst index 5edf0808..8f937246 100644 --- a/docs/source/examples/example_20.rst +++ b/docs/source/examples/example_20.rst @@ -15,4 +15,4 @@ Example 20: Case where user-defined axis labels are required cfp.con(f.subspace[9]) -.. figure:: /../../tests/reference-example-images/ref_fig_20.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_20.png diff --git a/docs/source/examples/example_21a.rst b/docs/source/examples/example_21a.rst index 6f4a6dc6..ed26cbcb 100644 --- a/docs/source/examples/example_21a.rst +++ b/docs/source/examples/example_21a.rst @@ -21,4 +21,4 @@ Example 21a: User-defined axes ) -.. figure:: /../../tests/reference-example-images/ref_fig_21a.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_21a.png diff --git a/docs/source/examples/example_21b.rst b/docs/source/examples/example_21b.rst index 25f348d1..615eb0ea 100644 --- a/docs/source/examples/example_21b.rst +++ b/docs/source/examples/example_21b.rst @@ -14,4 +14,4 @@ Example 21b: Plot of rotated pole data cfp.con(f) -.. figure:: /../../tests/reference-example-images/ref_fig_21b.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_21b.png diff --git a/docs/source/examples/example_22.rst b/docs/source/examples/example_22.rst index 23d9592a..3ee27771 100644 --- a/docs/source/examples/example_22.rst +++ b/docs/source/examples/example_22.rst @@ -16,4 +16,4 @@ Example 22: Plot of rotated pole data on its native grid cfp.con(f) -.. figure:: /../../tests/reference-example-images/ref_fig_22.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_22.png diff --git a/docs/source/examples/example_23a.rst b/docs/source/examples/example_23a.rst index d843943d..ead289d6 100644 --- a/docs/source/examples/example_23a.rst +++ b/docs/source/examples/example_23a.rst @@ -30,4 +30,4 @@ Example 23a: Rotated pole plot from data which is not CF Compliant cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_23a.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_23a.png diff --git a/docs/source/examples/example_23b.rst b/docs/source/examples/example_23b.rst index 764dcc0c..166ac7b8 100644 --- a/docs/source/examples/example_23b.rst +++ b/docs/source/examples/example_23b.rst @@ -23,4 +23,4 @@ Example 23b: Overlaying vectors over a rotated pole data plot cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_23b.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_23b.png diff --git a/docs/source/examples/example_24a.rst b/docs/source/examples/example_24a.rst index fbd4f0ee..bf2b3600 100644 --- a/docs/source/examples/example_24a.rst +++ b/docs/source/examples/example_24a.rst @@ -28,4 +28,4 @@ Example 24a: UGRID blockfill plot with LFRic cubed sphere mesh output ) -.. figure:: /../../tests/reference-example-images/ref_fig_24a.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_24a.png diff --git a/docs/source/examples/example_24b.rst b/docs/source/examples/example_24b.rst index fe4d574e..f5d24396 100644 --- a/docs/source/examples/example_24b.rst +++ b/docs/source/examples/example_24b.rst @@ -30,4 +30,4 @@ Example 24b: UGRID plot in the polar stereographic projection view ) -.. figure:: /../../tests/reference-example-images/ref_fig_24b.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_24b.png diff --git a/docs/source/examples/example_24c.rst b/docs/source/examples/example_24c.rst index 8dd0bb6e..c023ab69 100644 --- a/docs/source/examples/example_24c.rst +++ b/docs/source/examples/example_24c.rst @@ -17,4 +17,4 @@ Example 24c: UGRID contour plot with LFRic cubed sphere mesh output cfp.con(g, lines=False) -.. figure:: /../../tests/reference-example-images/ref_fig_24c.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_24c.png diff --git a/docs/source/examples/example_25.rst b/docs/source/examples/example_25.rst index 98642692..90cf834f 100644 --- a/docs/source/examples/example_25.rst +++ b/docs/source/examples/example_25.rst @@ -26,4 +26,4 @@ Example 25: UGRID contour plot with ORCA 2 output cfp.con(f=temp.array, x=lons.array, y=lats.array, ptype=1) -.. figure:: /../../tests/reference-example-images/ref_fig_25.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_25.png diff --git a/docs/source/examples/example_26a.rst b/docs/source/examples/example_26a.rst index 102f4e95..46a938c9 100644 --- a/docs/source/examples/example_26a.rst +++ b/docs/source/examples/example_26a.rst @@ -29,4 +29,4 @@ Example 26a: Contour plot based on discrete feature values ) -.. figure:: /../../tests/reference-example-images/ref_fig_26a.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_26a.png diff --git a/docs/source/examples/example_26b.rst b/docs/source/examples/example_26b.rst index 1ca8aecc..23929da7 100644 --- a/docs/source/examples/example_26b.rst +++ b/docs/source/examples/example_26b.rst @@ -43,4 +43,4 @@ Example 26b: Contour plot from discrete feature values with labelling cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_26b.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_26b.png diff --git a/docs/source/examples/example_27.rst b/docs/source/examples/example_27.rst index 5f1f8bef..970d322b 100644 --- a/docs/source/examples/example_27.rst +++ b/docs/source/examples/example_27.rst @@ -22,4 +22,4 @@ Example 27: Basic line plot cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_27.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_27.png diff --git a/docs/source/examples/example_28.rst b/docs/source/examples/example_28.rst index ec7695f6..a700cfa9 100644 --- a/docs/source/examples/example_28.rst +++ b/docs/source/examples/example_28.rst @@ -58,4 +58,4 @@ Example 28: Line plot with a legend cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_28.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_28.png diff --git a/docs/source/examples/example_29.rst b/docs/source/examples/example_29.rst index 54164029..7bfbd599 100644 --- a/docs/source/examples/example_29.rst +++ b/docs/source/examples/example_29.rst @@ -22,4 +22,4 @@ Example 29: Time series line plot ) -.. figure:: /../../tests/reference-example-images/ref_fig_29.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_29.png diff --git a/docs/source/examples/example_3.rst b/docs/source/examples/example_3.rst index ead1d5f2..4b232ebf 100644 --- a/docs/source/examples/example_3.rst +++ b/docs/source/examples/example_3.rst @@ -17,4 +17,4 @@ Example 3: Contour plot with altered map limits and levels cfp.con(f.subspace(time=15)) -.. figure:: /../../tests/reference-example-images/ref_fig_3.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_3.png diff --git a/docs/source/examples/example_30.rst b/docs/source/examples/example_30.rst index 4dc0fd95..caa76705 100644 --- a/docs/source/examples/example_30.rst +++ b/docs/source/examples/example_30.rst @@ -31,4 +31,4 @@ Example 30: Line plot with two x axes cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_30.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_30.png diff --git a/docs/source/examples/example_31.rst b/docs/source/examples/example_31.rst index d55f6c35..96c8ef3b 100644 --- a/docs/source/examples/example_31.rst +++ b/docs/source/examples/example_31.rst @@ -15,4 +15,4 @@ Example 31: UKCP projection cfp.con(f, lines=False) -.. figure:: /../../tests/reference-example-images/ref_fig_31.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_31.png diff --git a/docs/source/examples/example_32.rst b/docs/source/examples/example_32.rst index 26ad8a20..9dcf2066 100644 --- a/docs/source/examples/example_32.rst +++ b/docs/source/examples/example_32.rst @@ -23,4 +23,4 @@ Example 32: UKCP projection with blockfill ) -.. figure:: /../../tests/reference-example-images/ref_fig_32.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_32.png diff --git a/docs/source/examples/example_33.rst b/docs/source/examples/example_33.rst index 36d932a0..4cd84732 100644 --- a/docs/source/examples/example_33.rst +++ b/docs/source/examples/example_33.rst @@ -20,4 +20,4 @@ Example 33: OSGB and EuroPP projections cfp.gclose() -.. figure:: /../../tests/reference-example-images/ref_fig_33.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_33.png diff --git a/docs/source/examples/example_34.rst b/docs/source/examples/example_34.rst index 577690fe..808f7166 100644 --- a/docs/source/examples/example_34.rst +++ b/docs/source/examples/example_34.rst @@ -15,4 +15,4 @@ Example 34: Cropping the Lambert Conformal Conic (LCC) projection cfp.con(f.subspace(time=15)) -.. figure:: /../../tests/reference-example-images/ref_fig_34.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_34.png diff --git a/docs/source/examples/example_35.rst b/docs/source/examples/example_35.rst index dd64d5af..33cc427d 100644 --- a/docs/source/examples/example_35.rst +++ b/docs/source/examples/example_35.rst @@ -14,4 +14,4 @@ Example 35: Mollweide projection cfp.con(f.subspace(time=15)) -.. figure:: /../../tests/reference-example-images/ref_fig_35.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_35.png diff --git a/docs/source/examples/example_36.rst b/docs/source/examples/example_36.rst index 1f2176e9..7ff85186 100644 --- a/docs/source/examples/example_36.rst +++ b/docs/source/examples/example_36.rst @@ -14,4 +14,4 @@ Example 36: Mercator projection cfp.con(f.subspace(time=15)) -.. figure:: /../../tests/reference-example-images/ref_fig_36.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_36.png diff --git a/docs/source/examples/example_37.rst b/docs/source/examples/example_37.rst index 156c31bd..55fa5f5e 100644 --- a/docs/source/examples/example_37.rst +++ b/docs/source/examples/example_37.rst @@ -14,4 +14,4 @@ Example 37: Orthographic projection cfp.con(f.subspace(time=15)) -.. figure:: /../../tests/reference-example-images/ref_fig_37.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_37.png diff --git a/docs/source/examples/example_38.rst b/docs/source/examples/example_38.rst index 36c6353e..100c59d0 100644 --- a/docs/source/examples/example_38.rst +++ b/docs/source/examples/example_38.rst @@ -14,4 +14,4 @@ Example 38: Robinson projection cfp.con(f.subspace(time=15)) -.. figure:: /../../tests/reference-example-images/ref_fig_38.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_38.png diff --git a/docs/source/examples/example_39.rst b/docs/source/examples/example_39.rst index ff18b206..11398441 100644 --- a/docs/source/examples/example_39.rst +++ b/docs/source/examples/example_39.rst @@ -12,4 +12,4 @@ Example 39: Basic track plotting cfp.traj(f) -.. figure:: /../../tests/reference-example-images/ref_fig_39.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_39.png diff --git a/docs/source/examples/example_39b.rst b/docs/source/examples/example_39b.rst index 8c2d3224..d5070c3c 100644 --- a/docs/source/examples/example_39b.rst +++ b/docs/source/examples/example_39b.rst @@ -15,4 +15,4 @@ Example 39b: plotting a single (1D) DSG trajectory cfp.traj(f) -.. figure:: /../../tests/reference-example-images/ref_fig_39b.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_39b.png diff --git a/docs/source/examples/example_4.rst b/docs/source/examples/example_4.rst index e3e96229..4a752df9 100644 --- a/docs/source/examples/example_4.rst +++ b/docs/source/examples/example_4.rst @@ -16,4 +16,4 @@ Example 4: North Pole polar stereographic projection contour plot cfp.con(f.subspace(pressure=500)) -.. figure:: /../../tests/reference-example-images/ref_fig_4.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_4.png diff --git a/docs/source/examples/example_40.rst b/docs/source/examples/example_40.rst index 8be4aefd..614c868c 100644 --- a/docs/source/examples/example_40.rst +++ b/docs/source/examples/example_40.rst @@ -15,4 +15,4 @@ Example 40: Tracks in the polar stereographic projection cfp.traj(f) -.. figure:: /../../tests/reference-example-images/ref_fig_40.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_40.png diff --git a/docs/source/examples/example_41.rst b/docs/source/examples/example_41.rst index 97e70e64..ef7459b6 100644 --- a/docs/source/examples/example_41.rst +++ b/docs/source/examples/example_41.rst @@ -14,4 +14,4 @@ Example 41: Feature propagation over Europe cfp.traj(f, vector=True, markersize=0.0, fc="b", ec="b") -.. figure:: /../../tests/reference-example-images/ref_fig_41.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_41.png diff --git a/docs/source/examples/example_42a.rst b/docs/source/examples/example_42a.rst index d6c3e9f3..a69affc6 100644 --- a/docs/source/examples/example_42a.rst +++ b/docs/source/examples/example_42a.rst @@ -26,4 +26,4 @@ Example 42a: Tracks with labelled data points ) -.. figure:: /../../tests/reference-example-images/ref_fig_42a.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_42a.png diff --git a/docs/source/examples/example_42b.rst b/docs/source/examples/example_42b.rst index b11ae6e4..818a7ed8 100644 --- a/docs/source/examples/example_42b.rst +++ b/docs/source/examples/example_42b.rst @@ -25,4 +25,4 @@ Example 42b: Tracks displayed in a colour scale ) -.. figure:: /../../tests/reference-example-images/ref_fig_42b.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_42b.png diff --git a/docs/source/examples/example_5.rst b/docs/source/examples/example_5.rst index 8675a43c..4256884e 100644 --- a/docs/source/examples/example_5.rst +++ b/docs/source/examples/example_5.rst @@ -17,4 +17,4 @@ Example 5: South Pole polar projection contour plot with bounding latitude cfp.con(f.subspace(pressure=500)) -.. figure:: /../../tests/reference-example-images/ref_fig_5.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_5.png diff --git a/docs/source/examples/example_6.rst b/docs/source/examples/example_6.rst index 7e7402cc..492d8c5b 100644 --- a/docs/source/examples/example_6.rst +++ b/docs/source/examples/example_6.rst @@ -14,4 +14,4 @@ Example 6: Latitude-pressure plot at set longitude cfp.con(f.subspace(longitude=0)) -.. figure:: /../../tests/reference-example-images/ref_fig_6.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_6.png diff --git a/docs/source/examples/example_7.rst b/docs/source/examples/example_7.rst index 58dbe486..a8f9e113 100644 --- a/docs/source/examples/example_7.rst +++ b/docs/source/examples/example_7.rst @@ -14,4 +14,4 @@ Example 7: Latitude-pressure plot over zonal mean cfp.con(f.collapse("mean", "longitude")) -.. figure:: /../../tests/reference-example-images/ref_fig_7.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_7.png diff --git a/docs/source/examples/example_8.rst b/docs/source/examples/example_8.rst index aaa80fee..cb63ed25 100644 --- a/docs/source/examples/example_8.rst +++ b/docs/source/examples/example_8.rst @@ -14,4 +14,4 @@ Example 8: Latitude against log of pressure over longitude zonal mean cfp.con(f.collapse("mean", "longitude"), ylog=1) -.. figure:: /../../tests/reference-example-images/ref_fig_8.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_8.png diff --git a/docs/source/examples/example_9.rst b/docs/source/examples/example_9.rst index d450a519..f1e3e51f 100644 --- a/docs/source/examples/example_9.rst +++ b/docs/source/examples/example_9.rst @@ -14,4 +14,4 @@ Example 9: Longitude-pressure plot over latitude mean cfp.con(f.collapse("mean", "latitude")) -.. figure:: /../../tests/reference-example-images/ref_fig_9.png +.. figure:: /../../tests/v350-controlled-env-ref-images/ref_fig_9.png diff --git a/docs/source/gallery_of_examples.rst b/docs/source/gallery_of_examples.rst index 67b285ae..467c1bd4 100644 --- a/docs/source/gallery_of_examples.rst +++ b/docs/source/gallery_of_examples.rst @@ -40,77 +40,77 @@ by clicking through to the category pages. :gutter: 1 .. grid-item-card:: Contour plots - :img-top: /../../tests/reference-example-images/ref_fig_1.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_1.png :link: cylindrical.html#example-1-basic-contour-plot-in-default-projection :text-align: center .. grid-item-card:: Blockfill plots - :img-top: /../../tests/reference-example-images/ref_fig_2.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_2.png :link: cylindrical.html#example-2-basic-blockfill-plot-in-default-projection :text-align: center .. grid-item-card:: Vector plots - :img-top: /../../tests/reference-example-images/ref_fig_13.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_13.png :link: vectors.html#example-13-basic-vector-plot :text-align: center .. grid-item-card:: Stream plots - :img-top: /../../tests/reference-example-images/ref_fig_16c.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_16c.png :link: vectors.html#example-16c-stream-plot-in-a-colour-scale :text-align: center .. grid-item-card:: Stipple plots - :img-top: /../../tests/reference-example-images/ref_fig_17.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_17.png :link: stipple_plots.html#example-17-basic-stipple-plot :text-align: center .. grid-item-card:: Trajectories - :img-top: /../../tests/reference-example-images/ref_fig_42b.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_42b.png :link: trajectories.html#example-42b-tracks-displayed-in-a-colour-scale :text-align: center .. grid-item-card:: Hovmöller plots - :img-top: /../../tests/reference-example-images/ref_fig_11.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_11.png :link: hovmuller.html#example-11-latitude-time-subset-view-hovmoller-plot :text-align: center .. grid-item-card:: Vertical (pressure or height) plots - :img-top: /../../tests/reference-example-images/ref_fig_8.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_8.png :link: pressure.html#example-8-latitude-against-log-of-pressure-over-longitude-zonal-mean :text-align: center .. grid-item-card:: Lineplots - :img-top: /../../tests/reference-example-images/ref_fig_27.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_27.png :link: graphs.html#example-27-basic-line-plot :text-align: center .. grid-item-card:: Support for multiple projections - :img-top: /../../tests/reference-example-images/ref_fig_34.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_34.png :link: projections.html#example-34-cropping-the-lambert-conformal-conic-lcc-projection :text-align: center .. grid-item-card:: Polar projection views - :img-top: /../../tests/reference-example-images/ref_fig_40.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_40.png :link: trajectories.html#example-40-tracks-in-the-polar-stereographic-projection :text-align: center .. grid-item-card:: Unstructured grids (UGRID) support - :img-top: /../../tests/reference-example-images/ref_fig_24a.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_24a.png :link: unstructured.html#example-24a-ugrid-blockfill-plot-with-lfric-cubed-sphere-mesh-output :text-align: center .. grid-item-card:: Rotated pole support - :img-top: /../../tests/reference-example-images/ref_fig_22.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_22.png :link: rotated_pole.html#example-22-plot-of-rotated-pole-data-on-its-native-grid :text-align: center .. grid-item-card:: Multiple plots on one figure - :img-top: /../../tests/reference-example-images/ref_fig_19b.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_19b.png :link: multiple_plots.html#example-19b-multiple-plots-with-user-specified-plot-positions :text-align: center .. grid-item-card:: Flexible customisation e.g. user-defined axes - :img-top: /../../tests/reference-example-images/ref_fig_21a.png + :img-top: /../../tests/v350-controlled-env-ref-images/ref_fig_21a.png :link: user_defined.html#example-21a-user-defined-axes :text-align: center diff --git a/tests/data/nemo_eg260916.nc b/tests/data/nemo_eg260916.nc new file mode 100644 index 00000000..87cee8b4 Binary files /dev/null and b/tests/data/nemo_eg260916.nc differ diff --git a/tests/data/qrparm.c48.orog.nc b/tests/data/qrparm.c48.orog.nc new file mode 100644 index 00000000..f9e80283 Binary files /dev/null and b/tests/data/qrparm.c48.orog.nc differ diff --git a/tests/integration/test_contour_plot_examples.py b/tests/integration/test_contour_plot_examples.py index a44c78f1..426eebd0 100644 --- a/tests/integration/test_contour_plot_examples.py +++ b/tests/integration/test_contour_plot_examples.py @@ -684,6 +684,22 @@ def test_example_37b_orthographic_full_globe(): _assert_reference_match("37b") +@pytest.mark.integration +def test_example_nemo_1(): + """Test plotting of data on a NEMO grid.""" + data_file = Path(__file__).parent.parent / "data" / "nemo_eg260916.nc" + if not data_file.exists(): + pytest.skip(f"Missing test data: {data_file}") + + fl = cf.read(str(data_file)) + f = fl[0].squeeze() + + _configure_example_output("nemo1") + cfp.con(f) + + _assert_reference_match("nemo1") + + @pytest.mark.integration def test_example_numpy_arrays(): """Test contour with raw numpy arrays.""" diff --git a/tests/reference-example-images/ref_fig_1.png b/tests/reference-example-images/ref_fig_1.png deleted file mode 100644 index 68e348ab..00000000 Binary files a/tests/reference-example-images/ref_fig_1.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_10.png b/tests/reference-example-images/ref_fig_10.png deleted file mode 100644 index bbf751e9..00000000 Binary files a/tests/reference-example-images/ref_fig_10.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_11.png b/tests/reference-example-images/ref_fig_11.png deleted file mode 100644 index ca713f5d..00000000 Binary files a/tests/reference-example-images/ref_fig_11.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_12.png b/tests/reference-example-images/ref_fig_12.png deleted file mode 100644 index f5fec399..00000000 Binary files a/tests/reference-example-images/ref_fig_12.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_13.png b/tests/reference-example-images/ref_fig_13.png deleted file mode 100644 index 2882858c..00000000 Binary files a/tests/reference-example-images/ref_fig_13.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_14.png b/tests/reference-example-images/ref_fig_14.png deleted file mode 100644 index 21358563..00000000 Binary files a/tests/reference-example-images/ref_fig_14.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_15.png b/tests/reference-example-images/ref_fig_15.png deleted file mode 100644 index 70b52eb5..00000000 Binary files a/tests/reference-example-images/ref_fig_15.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_16.png b/tests/reference-example-images/ref_fig_16.png deleted file mode 100644 index 8b98456e..00000000 Binary files a/tests/reference-example-images/ref_fig_16.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_16a.png b/tests/reference-example-images/ref_fig_16a.png deleted file mode 100644 index cfb1f888..00000000 Binary files a/tests/reference-example-images/ref_fig_16a.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_16b.png b/tests/reference-example-images/ref_fig_16b.png deleted file mode 100644 index 2f8f0365..00000000 Binary files a/tests/reference-example-images/ref_fig_16b.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_16c.png b/tests/reference-example-images/ref_fig_16c.png deleted file mode 100644 index 52f7ce71..00000000 Binary files a/tests/reference-example-images/ref_fig_16c.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_17.png b/tests/reference-example-images/ref_fig_17.png deleted file mode 100644 index 67895ee6..00000000 Binary files a/tests/reference-example-images/ref_fig_17.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_18.png b/tests/reference-example-images/ref_fig_18.png deleted file mode 100644 index 2bff7aca..00000000 Binary files a/tests/reference-example-images/ref_fig_18.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_19.png b/tests/reference-example-images/ref_fig_19.png deleted file mode 100644 index 1c0ae852..00000000 Binary files a/tests/reference-example-images/ref_fig_19.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_19a.png b/tests/reference-example-images/ref_fig_19a.png deleted file mode 100644 index b1c6d379..00000000 Binary files a/tests/reference-example-images/ref_fig_19a.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_19b.png b/tests/reference-example-images/ref_fig_19b.png deleted file mode 100644 index dbe64522..00000000 Binary files a/tests/reference-example-images/ref_fig_19b.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_19c.png b/tests/reference-example-images/ref_fig_19c.png deleted file mode 100644 index 35004105..00000000 Binary files a/tests/reference-example-images/ref_fig_19c.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_2.png b/tests/reference-example-images/ref_fig_2.png deleted file mode 100644 index a0649fca..00000000 Binary files a/tests/reference-example-images/ref_fig_2.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_20.png b/tests/reference-example-images/ref_fig_20.png deleted file mode 100644 index ae25fc26..00000000 Binary files a/tests/reference-example-images/ref_fig_20.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_21.png b/tests/reference-example-images/ref_fig_21.png deleted file mode 100644 index 9ba8db23..00000000 Binary files a/tests/reference-example-images/ref_fig_21.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_21a.png b/tests/reference-example-images/ref_fig_21a.png deleted file mode 100644 index bc94f7ed..00000000 Binary files a/tests/reference-example-images/ref_fig_21a.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_21b.png b/tests/reference-example-images/ref_fig_21b.png deleted file mode 100644 index aad23554..00000000 Binary files a/tests/reference-example-images/ref_fig_21b.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_21other.png b/tests/reference-example-images/ref_fig_21other.png deleted file mode 100644 index 156e1ee4..00000000 Binary files a/tests/reference-example-images/ref_fig_21other.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_22.png b/tests/reference-example-images/ref_fig_22.png deleted file mode 100644 index 64838f37..00000000 Binary files a/tests/reference-example-images/ref_fig_22.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_23.png b/tests/reference-example-images/ref_fig_23.png deleted file mode 100644 index ba4a66e1..00000000 Binary files a/tests/reference-example-images/ref_fig_23.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_23a.png b/tests/reference-example-images/ref_fig_23a.png deleted file mode 100644 index 16d49f56..00000000 Binary files a/tests/reference-example-images/ref_fig_23a.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_23b.png b/tests/reference-example-images/ref_fig_23b.png deleted file mode 100644 index b6bf701f..00000000 Binary files a/tests/reference-example-images/ref_fig_23b.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_23other.png b/tests/reference-example-images/ref_fig_23other.png deleted file mode 100644 index 3439b9d3..00000000 Binary files a/tests/reference-example-images/ref_fig_23other.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_24a.png b/tests/reference-example-images/ref_fig_24a.png deleted file mode 100644 index fc2ffb5c..00000000 Binary files a/tests/reference-example-images/ref_fig_24a.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_24b.png b/tests/reference-example-images/ref_fig_24b.png deleted file mode 100644 index dabd7abc..00000000 Binary files a/tests/reference-example-images/ref_fig_24b.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_24c.png b/tests/reference-example-images/ref_fig_24c.png deleted file mode 100644 index 7d1f5121..00000000 Binary files a/tests/reference-example-images/ref_fig_24c.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_25.png b/tests/reference-example-images/ref_fig_25.png deleted file mode 100644 index d42a1c61..00000000 Binary files a/tests/reference-example-images/ref_fig_25.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_26a.png b/tests/reference-example-images/ref_fig_26a.png deleted file mode 100644 index 2ca18216..00000000 Binary files a/tests/reference-example-images/ref_fig_26a.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_26b.png b/tests/reference-example-images/ref_fig_26b.png deleted file mode 100644 index 0944ca65..00000000 Binary files a/tests/reference-example-images/ref_fig_26b.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_27.png b/tests/reference-example-images/ref_fig_27.png deleted file mode 100644 index c241de96..00000000 Binary files a/tests/reference-example-images/ref_fig_27.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_28.png b/tests/reference-example-images/ref_fig_28.png deleted file mode 100644 index 05c66f23..00000000 Binary files a/tests/reference-example-images/ref_fig_28.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_29.png b/tests/reference-example-images/ref_fig_29.png deleted file mode 100644 index c94a3d97..00000000 Binary files a/tests/reference-example-images/ref_fig_29.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_3.png b/tests/reference-example-images/ref_fig_3.png deleted file mode 100644 index cba75c0b..00000000 Binary files a/tests/reference-example-images/ref_fig_3.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_30.png b/tests/reference-example-images/ref_fig_30.png deleted file mode 100644 index 8047d703..00000000 Binary files a/tests/reference-example-images/ref_fig_30.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_31.png b/tests/reference-example-images/ref_fig_31.png deleted file mode 100644 index b6c07409..00000000 Binary files a/tests/reference-example-images/ref_fig_31.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_32.png b/tests/reference-example-images/ref_fig_32.png deleted file mode 100644 index b7189e51..00000000 Binary files a/tests/reference-example-images/ref_fig_32.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_33.png b/tests/reference-example-images/ref_fig_33.png deleted file mode 100644 index 2fbf197a..00000000 Binary files a/tests/reference-example-images/ref_fig_33.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_34.png b/tests/reference-example-images/ref_fig_34.png deleted file mode 100644 index e769d12d..00000000 Binary files a/tests/reference-example-images/ref_fig_34.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_35.png b/tests/reference-example-images/ref_fig_35.png deleted file mode 100644 index 463ce585..00000000 Binary files a/tests/reference-example-images/ref_fig_35.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_36.png b/tests/reference-example-images/ref_fig_36.png deleted file mode 100644 index 1fd1cc08..00000000 Binary files a/tests/reference-example-images/ref_fig_36.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_37.png b/tests/reference-example-images/ref_fig_37.png deleted file mode 100644 index 67013f4c..00000000 Binary files a/tests/reference-example-images/ref_fig_37.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_37b.png b/tests/reference-example-images/ref_fig_37b.png deleted file mode 100644 index d504d3e8..00000000 Binary files a/tests/reference-example-images/ref_fig_37b.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_38.png b/tests/reference-example-images/ref_fig_38.png deleted file mode 100644 index f7f119fb..00000000 Binary files a/tests/reference-example-images/ref_fig_38.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_39.png b/tests/reference-example-images/ref_fig_39.png deleted file mode 100644 index 7dbd4fdc..00000000 Binary files a/tests/reference-example-images/ref_fig_39.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_39b.png b/tests/reference-example-images/ref_fig_39b.png deleted file mode 100644 index c6fe88dd..00000000 Binary files a/tests/reference-example-images/ref_fig_39b.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_4.png b/tests/reference-example-images/ref_fig_4.png deleted file mode 100644 index 7eed4f80..00000000 Binary files a/tests/reference-example-images/ref_fig_4.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_40.png b/tests/reference-example-images/ref_fig_40.png deleted file mode 100644 index 7b5257bb..00000000 Binary files a/tests/reference-example-images/ref_fig_40.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_41.png b/tests/reference-example-images/ref_fig_41.png deleted file mode 100644 index 20d2038c..00000000 Binary files a/tests/reference-example-images/ref_fig_41.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_42a.png b/tests/reference-example-images/ref_fig_42a.png deleted file mode 100644 index 844151bc..00000000 Binary files a/tests/reference-example-images/ref_fig_42a.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_42b.png b/tests/reference-example-images/ref_fig_42b.png deleted file mode 100644 index 52f045d2..00000000 Binary files a/tests/reference-example-images/ref_fig_42b.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_5.png b/tests/reference-example-images/ref_fig_5.png deleted file mode 100644 index 20ca10a5..00000000 Binary files a/tests/reference-example-images/ref_fig_5.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_6.png b/tests/reference-example-images/ref_fig_6.png deleted file mode 100644 index 0ff34ee4..00000000 Binary files a/tests/reference-example-images/ref_fig_6.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_7.png b/tests/reference-example-images/ref_fig_7.png deleted file mode 100644 index dabc0b3c..00000000 Binary files a/tests/reference-example-images/ref_fig_7.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_8.png b/tests/reference-example-images/ref_fig_8.png deleted file mode 100644 index b9751764..00000000 Binary files a/tests/reference-example-images/ref_fig_8.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_9.png b/tests/reference-example-images/ref_fig_9.png deleted file mode 100644 index e157b63c..00000000 Binary files a/tests/reference-example-images/ref_fig_9.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_canari_1.png b/tests/reference-example-images/ref_fig_canari_1.png deleted file mode 100644 index af5dbade..00000000 Binary files a/tests/reference-example-images/ref_fig_canari_1.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_npstere_da193.png b/tests/reference-example-images/ref_fig_npstere_da193.png deleted file mode 100644 index 90607496..00000000 Binary files a/tests/reference-example-images/ref_fig_npstere_da193.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_numpy.png b/tests/reference-example-images/ref_fig_numpy.png deleted file mode 100644 index 010840c3..00000000 Binary files a/tests/reference-example-images/ref_fig_numpy.png and /dev/null differ diff --git a/tests/reference-example-images/ref_fig_seaice_ortho_bbox.png b/tests/reference-example-images/ref_fig_seaice_ortho_bbox.png deleted file mode 100644 index bf71c9c8..00000000 Binary files a/tests/reference-example-images/ref_fig_seaice_ortho_bbox.png and /dev/null differ diff --git a/tests/unit/test_contour_boundary.py b/tests/unit/test_contour_boundary.py index 55172961..c82c1863 100644 --- a/tests/unit/test_contour_boundary.py +++ b/tests/unit/test_contour_boundary.py @@ -1,5 +1,9 @@ import inspect +from pathlib import Path +from types import SimpleNamespace +import cf +import contourpy import numpy as np import pytest @@ -88,3 +92,188 @@ def test_blockfill_signature_does_not_advertise_lonlat(): params = inspect.signature(blockfill._bfill).parameters assert "lonlat" not in params + + +def test_curvilinear_defaults_enable_fast_blockfill_and_disable_lines(): + data = contour.ContourData( + field=np.ones((3, 4)), + x=np.ones((3, 4)), + y=np.ones((3, 4)), + ptype=1, + ) + + fill, lines, blockfill, blockfill_fast = contour._resolve_curvilinear_render_defaults( + data=data, + kwargs={}, + fill=True, + lines=True, + blockfill=False, + blockfill_fast=None, + ) + + assert fill is False + assert lines is False + assert blockfill is True + assert blockfill_fast is True + + +def test_curvilinear_defaults_respect_explicit_user_choices(): + data = contour.ContourData( + field=np.ones((3, 4)), + x=np.ones((3, 4)), + y=np.ones((3, 4)), + ptype=1, + ) + + fill, lines, blockfill, blockfill_fast = contour._resolve_curvilinear_render_defaults( + data=data, + kwargs={"blockfill": False, "lines": True}, + fill=True, + lines=True, + blockfill=False, + blockfill_fast=None, + ) + + assert fill is True + assert lines is True + assert blockfill is False + assert blockfill_fast is None + + +@pytest.mark.parametrize("axis", [0, 1]) +def test_curvilinear_contours_mask_both_sides_of_seam(axis): + x = np.tile([178.0, 179.0, -179.0, -178.0], (4, 1)) + if axis == 0: + x = x.T + field = np.ma.array(np.ones((4, 4)), mask=False) + field.mask[0, 0] = True + data = contour.ContourData( + field=field, x=x, y=np.ones((4, 4)), ptype=1 + ) + + result = contour._mask_curvilinear_contour_seams(data) + + expected = np.zeros((4, 4), dtype=bool) + if axis == 0: + expected[1:3, :] = True + else: + expected[:, 1:3] = True + expected[0, 0] = True + np.testing.assert_array_equal(result.mask, expected) + np.testing.assert_array_equal(result.data, field.data) + assert np.ma.count_masked(field) == 1 + + +@pytest.mark.parametrize("curvilinear", [False, True]) +def test_contour_seam_mask_preserves_continuous_grids(curvilinear): + field = np.arange(12.0).reshape(3, 4) + x, y = np.arange(4.0), np.arange(3.0) + if curvilinear: + x, y = np.meshgrid(x, y) + data = contour.ContourData(field=field, x=x, y=y, ptype=1) + + result = contour._mask_curvilinear_contour_seams(data) + + np.testing.assert_array_equal(result, field) + assert np.ma.count_masked(result) == 0 + + +def test_map_renderers_use_seam_mask_for_fill_lines_and_zero(monkeypatch): + calls = [] + + def record(x, y, field, levels, **kwargs): + calls.append(field) + return SimpleNamespace() + + monkeypatch.setattr( + contour.plotvars.runtime, + "mymap", + SimpleNamespace(contourf=record, contour=record), + ) + data = contour.ContourData( + field=np.ones((3, 4)), + x=np.tile([178.0, 179.0, -179.0, -178.0], (3, 1)), + y=np.tile(np.arange(3.0)[:, None], (1, 4)), + ptype=1, + levels=np.array([-1.0, 0.0, 1.0]), + fmult=2, + ) + renderer = contour.MapContourRenderer( + layout=None, + data=data, + colour_scale=SimpleNamespace(get_cmap=lambda: None), + ) + + renderer.render_filled(alpha=1, zorder=1, transform_first=False) + renderer.render_lines( + colors="k", + linewidths=None, + linestyles=None, + line_labels=False, + zero_thick=3, + ) + + assert len(calls) == 3 + for field in calls: + np.testing.assert_array_equal(field.mask[:, 1:3], True) + np.testing.assert_array_equal(field.compressed(), 2.0) + assert np.ma.count_masked(data.field) == 0 + + +def test_map_blockfill_does_not_apply_contour_seam_mask(monkeypatch): + calls = [] + monkeypatch.setattr( + contour, "_bfill", lambda **kwargs: calls.append(kwargs["f"]) + ) + data = contour.ContourData( + field=np.ones((3, 4)), + x=np.tile([178.0, 179.0, -179.0, -178.0], (3, 1)), + y=np.ones((3, 4)), + ptype=1, + levels=np.array([0.0, 1.0]), + ) + renderer = contour.MapContourRenderer( + layout=None, data=data, colour_scale=None + ) + + renderer.render_blockfill(fast=True, alpha=1, zorder=1) + + assert len(calls) == 1 + assert np.ma.count_masked(calls[0]) == 0 + np.testing.assert_array_equal(calls[0], data.field) + + +@pytest.mark.parametrize("filled", [False, True]) +def test_nemo_contours_do_not_interpolate_across_longitude_seam(filled): + path = Path(__file__).parents[1] / "data" / "nemo_eg260916.nc" + data = contour.ContourData.from_cf_field(cf.read(str(path))[0], None) + field = contour._mask_curvilinear_contour_seams(data) + levels = np.array([0.5, 1.5, 2.5, 3.5]) * 1e-4 + + def longest_edge(values): + generator = contourpy.contour_generator( + x=data.x, y=data.y, z=values, corner_mask=True + ) + if filled: + paths = [] + for lower, upper in zip(levels[:-1], levels[1:]): + vertices, offsets = generator.filled(lower, upper) + for points, boundaries in zip(vertices, offsets): + paths.extend( + points[start:end] + for start, end in zip( + boundaries[:-1], boundaries[1:] + ) + ) + else: + paths = [ + path for level in levels for path in generator.lines(level) + ] + return max( + np.max(np.abs(np.diff(path[:, 0]))) + for path in paths + if len(path) > 1 + ) + + assert longest_edge(data.field) > 300.0 + assert longest_edge(field) < 180.0 diff --git a/tests/v350-controlled-env-ref-images/ref_fig_nemo1.png b/tests/v350-controlled-env-ref-images/ref_fig_nemo1.png new file mode 100644 index 00000000..536826b1 Binary files /dev/null and b/tests/v350-controlled-env-ref-images/ref_fig_nemo1.png differ