From 680e5678803e64fcc7f07dfee426b764e11974f3 Mon Sep 17 00:00:00 2001 From: Theo Geddes Date: Thu, 9 Apr 2026 13:55:17 +0100 Subject: [PATCH 1/9] #68: Fix numpy deprecation in decomposition --- lib/ants/decomposition.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/ants/decomposition.py b/lib/ants/decomposition.py index 1fa8246..02de5a3 100644 --- a/lib/ants/decomposition.py +++ b/lib/ants/decomposition.py @@ -172,8 +172,8 @@ def _guess_split(sources, target=None): if not isinstance(target, iris.cube.Cube): target = target[0] dtype = np.promote_types(dtype, target.dtype) - if (np.prod(target.shape) * np.nbytes[dtype]) > ( - np.prod(source.shape) * np.nbytes[dtype] + if (np.prod(target.shape) * np.dtype(dtype).itemsize) > ( + np.prod(source.shape) * np.dtype(dtype).itemsize ): largest_array = target @@ -186,7 +186,7 @@ def _guess_split(sources, target=None): z_elements = np.prod(rem_shape) # Number of points which amount to size_bytes footprint. - n_elements = int((size_bytes) / np.nbytes[dtype]) + n_elements = int((size_bytes) / np.dtype(dtype).itemsize) # Split such that ~square extracts occur for likely optimisation of saving. shape = np.array(largest_array.shape) From 7062537046310b51318ce25d25571253eea99e90 Mon Sep 17 00:00:00 2001 From: Theo Geddes Date: Thu, 9 Apr 2026 14:07:32 +0100 Subject: [PATCH 2/9] #68: Fix incorrect mock call --- lib/ants/tests/fileformats/ancil/test_load_um_cubes.py | 2 +- .../tests/fileformats/ancil/test_load_um_cubes_32bit_ieee.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/ants/tests/fileformats/ancil/test_load_um_cubes.py b/lib/ants/tests/fileformats/ancil/test_load_um_cubes.py index 49d1bc6..fdcf4fa 100644 --- a/lib/ants/tests/fileformats/ancil/test_load_um_cubes.py +++ b/lib/ants/tests/fileformats/ancil/test_load_um_cubes.py @@ -26,7 +26,7 @@ def setUp(self): def test_iris_call(self): load_cubes(mock.sentinel.dummy) - self.mock_callback.called_once_with(self.grid_staggering) + self.mock_callback.assert_called_once_with(self.grid_staggering) self.mock_load.assert_called_once_with( mock.sentinel.dummy, self.mock_callback() ) diff --git a/lib/ants/tests/fileformats/ancil/test_load_um_cubes_32bit_ieee.py b/lib/ants/tests/fileformats/ancil/test_load_um_cubes_32bit_ieee.py index 4e7c9dd..129955a 100644 --- a/lib/ants/tests/fileformats/ancil/test_load_um_cubes_32bit_ieee.py +++ b/lib/ants/tests/fileformats/ancil/test_load_um_cubes_32bit_ieee.py @@ -26,7 +26,7 @@ def setUp(self): def test_iris_call(self): load_cubes_32bit_ieee(mock.sentinel.dummy) - self.mock_callback.called_once_with(self.grid_staggering) + self.mock_callback.assert_called_once_with(self.grid_staggering) self.mock_load.assert_called_once_with( mock.sentinel.dummy, self.mock_callback() ) From 55feb6832e643cf90de38ea6c608b7053543fc81 Mon Sep 17 00:00:00 2001 From: Theo Geddes Date: Thu, 9 Apr 2026 14:20:22 +0100 Subject: [PATCH 3/9] #68: Update np.NAN to np.nan --- lib/ants/fileformats/namelist/umgrid.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/ants/fileformats/namelist/umgrid.py b/lib/ants/fileformats/namelist/umgrid.py index efad835..1b047f1 100644 --- a/lib/ants/fileformats/namelist/umgrid.py +++ b/lib/ants/fileformats/namelist/umgrid.py @@ -642,7 +642,7 @@ def __init__(self, namelist_dict): _eta_rho.insert(0, 0.0) # rho level above model top not in namelist. Instead, derived after # conversion to self._brlev, so use NAN as a placeholder: - _eta_rho.append(np.NAN) + _eta_rho.append(np.nan) self._eta_rho = np.array(_eta_rho, dtype=np.float64) # brlev defines level_height.lower bounds From 828576de6097b3178c9ae71863f6624edbdbdea3 Mon Sep 17 00:00:00 2001 From: Theo Geddes Date: Wed, 20 May 2026 11:32:01 +0100 Subject: [PATCH 4/9] environment update work to dat --- environment.yml | 21 ++++---- lib/ants/_constraints.py | 2 +- lib/ants/_version.py | 1 + lib/ants/analysis/__init__.py | 7 +-- lib/ants/analysis/_merge.py | 1 + lib/ants/cli/ancil_2anc.py | 1 + lib/ants/cli/ancil_create_shapefile.py | 1 + lib/ants/cli/ancil_fill_n_merge.py | 1 + lib/ants/cli/ancil_general_regrid.py | 3 ++ lib/ants/config.py | 1 + lib/ants/coord_systems.py | 1 + lib/ants/decomposition.py | 1 + lib/ants/fileformats/__init__.py | 1 + lib/ants/fileformats/_grid_extract.py | 1 + lib/ants/fileformats/ancil/__init__.py | 1 + lib/ants/fileformats/ancil/preprocessing.py | 1 + lib/ants/fileformats/ancil/template.py | 3 +- lib/ants/fileformats/ancil/time_headers.py | 1 + lib/ants/fileformats/namelist/__init__.py | 1 + lib/ants/fileformats/namelist/umgrid.py | 1 + lib/ants/fileformats/netcdf/__init__.py | 1 + lib/ants/fileformats/pp/__init__.py | 1 + lib/ants/fileformats/raster.py | 14 ++++- lib/ants/io/load.py | 1 + lib/ants/io/save.py | 1 + lib/ants/regrid/__init__.py | 1 + lib/ants/regrid/esmf.py | 36 ++++++++----- .../tests/command_parse/test_integration.py | 15 ++++-- .../tests/decomposition/test_integration.py | 1 + .../fileformats/ancil/test_integration.py | 2 +- .../namelist/test_CAPGridRegular.py | 20 +++---- .../regrid/esmf/test_ConservativeESMF.py | 37 +++++++++++++ .../regrid/interpolation/test_integration.py | 54 ++++++++++--------- .../rectilinear/test__fill_outside_bounds.py | 10 ++-- lib/ants/tests/regrid/test_integration.py | 7 +-- lib/ants/tests/test_dependencies.py | 1 + .../tests/utils/_dask/test_as_lazy_data.py | 3 ++ .../cube/test_guess_horizontal_bounds.py | 17 ++++-- .../tests/utils/cube/test_inherit_metadata.py | 3 +- lib/ants/utils/_dask.py | 7 ++- pyproject.toml | 10 +++- rose-stem/flow.cylc | 2 +- utils/generate_logs/conftest.py | 12 ++--- .../generate_logs/durations_extract_format.py | 1 + utils/generate_logs/durations_logger.py | 1 + utils/generate_logs/durations_main.py | 1 + .../test_durations_extract_format.py | 6 +-- utils/plot_comparisons/plot_comparisons.py | 1 + 48 files changed, 216 insertions(+), 101 deletions(-) diff --git a/environment.yml b/environment.yml index 1f6ff19..ec828c4 100644 --- a/environment.yml +++ b/environment.yml @@ -4,21 +4,24 @@ channels: dependencies: - black - cftime - - dask=2023.11.0 - - esmf=8.4.2=mpi_mpich_h2a0de38_103 - - esmpy=8.4.2 + - dask + - esmf=*=nompi_* + - esmpy - f90nml - flake8 - - gdal=3.9.1 + - gdal - geovista - - iris-esmf-regrid>=0.9 + - hdf5=*=nompi_* + - iris-esmf-regrid - iris-sample-data - - iris=3.7.1 + - iris - isort + - libnetcdf!=4.9.1=nompi_* - mo_pack - nccmp + - netcdf-fortran=*=nompi_* - numba - - numpy=1.26.0 + - numpy=2.3.5 - pre-commit - pydata-sphinx-theme - pyflakes @@ -27,11 +30,11 @@ dependencies: - pytest-cov - pytest-xdist - python-stratify - - python=3.10.13 + - python=3.12.12 - ruff - setuptools - setuptools-scm - - sphinx=7.2.6 + - sphinx - sphinx-argparse - sphinx-copybutton - sphinx-sitemap diff --git a/lib/ants/_constraints.py b/lib/ants/_constraints.py index 5c1d2f4..f1bd6ad 100644 --- a/lib/ants/_constraints.py +++ b/lib/ants/_constraints.py @@ -110,7 +110,7 @@ def _bounding_box(target_x, target_y, src_crs): src_crs = source_x.coord_system.as_ants_crs() box = _bounding_box(target_x, target_y, src_crs) - (minx, miny, maxx, maxy) = box.bounds + minx, miny, maxx, maxy = box.bounds slices = utils.cube.get_slices(source, [miny, maxy], [minx, maxx], pad_width) if len(slices) > 2: diff --git a/lib/ants/_version.py b/lib/ants/_version.py index 023d3d3..65b3339 100644 --- a/lib/ants/_version.py +++ b/lib/ants/_version.py @@ -3,4 +3,5 @@ # This file is part of ANTS and is released under the BSD 3-Clause license. # See LICENSE.txt in the root of the repository for full licensing details. """Define the fallback version to be used when ANTS is not installed into an environment.""" # noqa: E501 + FALLBACK_VERSION = "3.2.0dev" diff --git a/lib/ants/analysis/__init__.py b/lib/ants/analysis/__init__.py index cddb441..6641bc0 100644 --- a/lib/ants/analysis/__init__.py +++ b/lib/ants/analysis/__init__.py @@ -29,6 +29,7 @@ `_. """ + import warnings import ants @@ -251,7 +252,7 @@ def merge(primary_cube, alternate_cube, validity_polygon=None): def _flood_fill_neighbour_identify( shape, coords, seed_point, extended_neighbourhood, wraparound ): - (yy, xx) = seed_point + yy, xx = seed_point if yy > 0: coords.add((yy - 1, xx)) if yy < (shape[0] - 1): @@ -320,7 +321,7 @@ def flood_fill( When True, support wraparound in 'x', otherwise stop at the boundary. """ - (y, x) = seed_point + y, x = seed_point if array.ndim != 2: msg = "The provided array should be 2D but that provided is {}D" raise ValueError(msg.format(array.ndim)) @@ -473,7 +474,7 @@ def find_similar_region( identified as similar. """ - (y, x) = seed_point + y, x = seed_point if array.ndim != 2: msg = "The provided array should be 2D but that provided is {}D" raise ValueError(msg.format(array.ndim)) diff --git a/lib/ants/analysis/_merge.py b/lib/ants/analysis/_merge.py index 7a2d025..46e0114 100644 --- a/lib/ants/analysis/_merge.py +++ b/lib/ants/analysis/_merge.py @@ -7,6 +7,7 @@ The metadata is also updated to reflect the analysis made. """ + import abc import logging import warnings diff --git a/lib/ants/cli/ancil_2anc.py b/lib/ants/cli/ancil_2anc.py index 60deaa1..a3ba69e 100755 --- a/lib/ants/cli/ancil_2anc.py +++ b/lib/ants/cli/ancil_2anc.py @@ -30,6 +30,7 @@ `_ """ + import warnings import ants diff --git a/lib/ants/cli/ancil_create_shapefile.py b/lib/ants/cli/ancil_create_shapefile.py index 7081626..245dfd1 100755 --- a/lib/ants/cli/ancil_create_shapefile.py +++ b/lib/ants/cli/ancil_create_shapefile.py @@ -10,6 +10,7 @@ Creates and saves a shapefile from a list of pairs of longitude, latitude points defining a single polygon in a specified polygon file. """ + import argparse import json diff --git a/lib/ants/cli/ancil_fill_n_merge.py b/lib/ants/cli/ancil_fill_n_merge.py index 9bb7cea..773cc78 100755 --- a/lib/ants/cli/ancil_fill_n_merge.py +++ b/lib/ants/cli/ancil_fill_n_merge.py @@ -11,6 +11,7 @@ missing values. """ + import ants import ants.io.save as save import cartopy diff --git a/lib/ants/cli/ancil_general_regrid.py b/lib/ants/cli/ancil_general_regrid.py index 7f6bd86..610f89b 100755 --- a/lib/ants/cli/ancil_general_regrid.py +++ b/lib/ants/cli/ancil_general_regrid.py @@ -28,10 +28,12 @@ is produced, regardless of the number of longitude points in the regrid target. """ + import ants import ants.decomposition as decomp import ants.io.save as save import ants.utils +import numpy as np from ants.utils.cube import create_time_constrained_cubes @@ -125,6 +127,7 @@ def main( A single data cube with the regridded data. """ + np._set_promotion_state("weak_and_warn") source_cubes, target_cube = load_data( source_path, target_path, diff --git a/lib/ants/config.py b/lib/ants/config.py index 703fb60..802257c 100644 --- a/lib/ants/config.py +++ b/lib/ants/config.py @@ -49,6 +49,7 @@ see different results). This environment variable is read by cartopy directly. """ + import argparse import configparser import copy diff --git a/lib/ants/coord_systems.py b/lib/ants/coord_systems.py index 58e43bc..d9d16e9 100644 --- a/lib/ants/coord_systems.py +++ b/lib/ants/coord_systems.py @@ -18,6 +18,7 @@ * :func:`ants.regrid.rectilinear` """ + import copy import re from abc import ABCMeta, abstractmethod diff --git a/lib/ants/decomposition.py b/lib/ants/decomposition.py index 02de5a3..4103443 100644 --- a/lib/ants/decomposition.py +++ b/lib/ants/decomposition.py @@ -24,6 +24,7 @@ See :func:`ants.utils.cube.defer_cube`. """ + import itertools import logging import os diff --git a/lib/ants/fileformats/__init__.py b/lib/ants/fileformats/__init__.py index 4e54993..9b3fbda 100644 --- a/lib/ants/fileformats/__init__.py +++ b/lib/ants/fileformats/__init__.py @@ -7,6 +7,7 @@ ancillary generation. These include those supported by iris and additional formats such as grid namelists and raster files. """ + import warnings import ants diff --git a/lib/ants/fileformats/_grid_extract.py b/lib/ants/fileformats/_grid_extract.py index 065bb8e..195c43c 100644 --- a/lib/ants/fileformats/_grid_extract.py +++ b/lib/ants/fileformats/_grid_extract.py @@ -7,6 +7,7 @@ grid via the ants.io.load.load_grid interface. """ + import ants import dask.array as da import iris diff --git a/lib/ants/fileformats/ancil/__init__.py b/lib/ants/fileformats/ancil/__init__.py index 4633fe6..f6bc393 100644 --- a/lib/ants/fileformats/ancil/__init__.py +++ b/lib/ants/fileformats/ancil/__init__.py @@ -21,6 +21,7 @@ cube.attributes['grid_staggering']. """ + import warnings import ants diff --git a/lib/ants/fileformats/ancil/preprocessing.py b/lib/ants/fileformats/ancil/preprocessing.py index 35b1349..eec04a8 100644 --- a/lib/ants/fileformats/ancil/preprocessing.py +++ b/lib/ants/fileformats/ancil/preprocessing.py @@ -17,6 +17,7 @@ #. Create a metadata.ini file for climatology time information (write_metadata_file) """ + import configparser import numbers from collections import Counter diff --git a/lib/ants/fileformats/ancil/template.py b/lib/ants/fileformats/ancil/template.py index 345f769..8b539ec 100644 --- a/lib/ants/fileformats/ancil/template.py +++ b/lib/ants/fileformats/ancil/template.py @@ -7,6 +7,7 @@ Tools for generating the template required for saving ancillary files. """ + import itertools import re @@ -136,7 +137,7 @@ def _set_grid_definition(headers, grid, field): headers["fixed_length_header"]["horiz_grid_type"] = horiz_grid_type # REAL CONSTANTS - (regular_x, regular_y) = field.is_regular + regular_x, regular_y = field.is_regular if regular_x: headers["real_constants"]["col_spacing"] = field.bdx # Longitude of first column in degrees (longitudes in range 0-360) diff --git a/lib/ants/fileformats/ancil/time_headers.py b/lib/ants/fileformats/ancil/time_headers.py index 67e60a8..7b01665 100644 --- a/lib/ants/fileformats/ancil/time_headers.py +++ b/lib/ants/fileformats/ancil/time_headers.py @@ -7,6 +7,7 @@ This module provides functions related to time handling for ancillary files. """ + import itertools import ants diff --git a/lib/ants/fileformats/namelist/__init__.py b/lib/ants/fileformats/namelist/__init__.py index a23fbc6..fcc42cb 100644 --- a/lib/ants/fileformats/namelist/__init__.py +++ b/lib/ants/fileformats/namelist/__init__.py @@ -6,6 +6,7 @@ Module for reading Fortran namelist files and constructing Python or Iris objects, as appropriate, from the contents. """ + import warnings import ants diff --git a/lib/ants/fileformats/namelist/umgrid.py b/lib/ants/fileformats/namelist/umgrid.py index 1b047f1..4128319 100644 --- a/lib/ants/fileformats/namelist/umgrid.py +++ b/lib/ants/fileformats/namelist/umgrid.py @@ -22,6 +22,7 @@ definition specification. """ + from abc import ABCMeta, abstractproperty from collections import namedtuple diff --git a/lib/ants/fileformats/netcdf/__init__.py b/lib/ants/fileformats/netcdf/__init__.py index 20a16b1..70bb85b 100644 --- a/lib/ants/fileformats/netcdf/__init__.py +++ b/lib/ants/fileformats/netcdf/__init__.py @@ -3,6 +3,7 @@ # This file is part of ANTS and is released under the BSD 3-Clause license. # See LICENSE.txt in the root of the repository for full licensing details. """The entry point for netCDF saving is via :func:`ants.io.save.netcdf`.""" + from . import cf, ukca __all__ = [ diff --git a/lib/ants/fileformats/pp/__init__.py b/lib/ants/fileformats/pp/__init__.py index 74197cb..5fa7f93 100644 --- a/lib/ants/fileformats/pp/__init__.py +++ b/lib/ants/fileformats/pp/__init__.py @@ -15,6 +15,7 @@ 1. Pseudo-level order from the PP file is preserved. """ + import collections import itertools diff --git a/lib/ants/fileformats/raster.py b/lib/ants/fileformats/raster.py index f826090..4fc00e9 100644 --- a/lib/ants/fileformats/raster.py +++ b/lib/ants/fileformats/raster.py @@ -9,6 +9,7 @@ information. """ + import copy import warnings @@ -64,7 +65,15 @@ def __init__(self, shape, dtype, path, raster_band_index, fill_value): # the saving of netcdf3 output properly (auto type-casting etc.) dtype = np.dtype(dtype) if dtype.name.startswith("uint"): - dtype = np.dtype(np.sctypeDict[dtype.num + 1]) + if (dtype.name) == "uint8": + dtype = np.dtype("int16") + elif (dtype.name) == "uint16": + dtype = np.dtype("int32") + elif (dtype.name) == "uint32": + dtype = np.dtype("int64") + else: + dtype = np.dtype("int128") + self.dtype = dtype self.path = path self.raster_band_index = raster_band_index @@ -302,6 +311,7 @@ def load_cubes(filenames, callback=None): dataset = gdal.Open(fname, GA_ReadOnly) if dataset is None: raise IOError("gdal failed to open raster image") + print("boop") # Get metadata applies to all raster bands transform = dataset.GetGeoTransform() @@ -346,6 +356,8 @@ def load_cubes(filenames, callback=None): proxy = _GdalDataProxy( num_xy, dtype, fname, iraster, iband.GetNoDataValue() ) + print("bop") + print(proxy) data = as_lazy_data(proxy) cube = iris.cube.Cube(data) cube.add_dim_coord(x, 1) diff --git a/lib/ants/io/load.py b/lib/ants/io/load.py index 9c53786..089e828 100644 --- a/lib/ants/io/load.py +++ b/lib/ants/io/load.py @@ -55,6 +55,7 @@ :func:`ants.fileformats.namelist.load_um_vertical` """ + import copy import warnings from contextlib import contextmanager diff --git a/lib/ants/io/save.py b/lib/ants/io/save.py index 9cbc83e..5f9fdef 100644 --- a/lib/ants/io/save.py +++ b/lib/ants/io/save.py @@ -20,6 +20,7 @@ specifying ``saver='ukca'`` (see :func:`ants.io.save.ukca_netcdf`). """ + import os import sys import warnings diff --git a/lib/ants/regrid/__init__.py b/lib/ants/regrid/__init__.py index f658195..2ba6c7c 100644 --- a/lib/ants/regrid/__init__.py +++ b/lib/ants/regrid/__init__.py @@ -17,6 +17,7 @@ For further details see the user guide. """ + import logging import sys diff --git a/lib/ants/regrid/esmf.py b/lib/ants/regrid/esmf.py index 4b7954f..26d87a7 100644 --- a/lib/ants/regrid/esmf.py +++ b/lib/ants/regrid/esmf.py @@ -408,41 +408,44 @@ def __init__(self, src_cube, target_cube, **kwargs): class). """ + print("1") keywarg_diff = set(kwargs.keys()) - set(["method", "persistent_cache"]) if keywarg_diff: msg = "unexpected keyword argument {}" raise ValueError(msg.format(keywarg_diff)) - + print("2") if esmpy is None: raise _ESMPY_IMPORT_ERROR _supported_cube_check(src_cube) _supported_cube_check(target_cube) - + print("3") # Set some parameters. self.handle = None self.coordSystem = esmpy.api.constants.CoordSys.SPH_DEG self.method = esmpy.api.constants.RegridMethod.CONSERVE self.stagger = esmpy.StaggerLoc.CENTER - + print("4") method = kwargs.get("method", "areaweighted") if method.lower() != "areaweighted": raise ValueError("Currently only area weighted regridding " "supported.") - + print("5") # Simply return if the src and tgt grids are identical. if (src_cube.coord(axis="x") == target_cube.coord(axis="x")) and ( src_cube.coord(axis="y") == target_cube.coord(axis="y") ): return _source_cube_sanity_check(src_cube) - + print("6") # Build the 2D esmf grid and field objects. self.esmpy_src_grid, self.esmpy_src_field = self._build_field(src_cube) + print("6.1") self.esmpy_tgt_grid, self.esmpy_tgt_field = self._build_field(target_cube) - + print("7") # Compute/read the weights following ESMPy weights tutorial. See # ESMPy docs for details of arguments. self._cache_fnme = self._gen_cache_filename([src_cube, target_cube]) self._persistent_cache = bool(kwargs.get("persistent_cache", False)) + print("8") if not os.path.isfile(self._cache_fnme): # No existing cache so have ESMF generate it. self.handle = esmpy.api.regrid.Regrid( @@ -454,9 +457,11 @@ def __init__(self, src_cube, target_cube, **kwargs): ignore_degenerate=True, filename=self._cache_fnme, ) + print("9") else: # Utilise the existing cache. try: + print("10") self.handle = esmpy.api.regrid.RegridFromFile( self.esmpy_src_field, self.esmpy_tgt_field, self._cache_fnme ) @@ -467,7 +472,7 @@ def __init__(self, src_cube, target_cube, **kwargs): err_msg[0] += msg err.args = err_msg raise - + print("11") # Get the latitude/longitude self.tgt_latlon = self._get_latlon_from_cube(target_cube) @@ -872,7 +877,7 @@ def _build_field(self, cube): # # Build the esmpy field object. # - + print("starting to build field for ", cube) staggering = "corner" if self.method != esmpy.api.constants.RegridMethod.CONSERVE: # Need to pass corner coordinates in all cases. When the field is @@ -881,23 +886,25 @@ def _build_field(self, cube): # bounds (so staggering is ''). staggering = "" # Get the true latitudes and longitudes on cell vertices. + print("1") extractor = _LatLonExtractor(cube, staggering) lats = extractor.get_latitude() lons = extractor.get_longitude() - + print("2") # Create the grid. cellDims = np.array([lons.shape[0] - 1, lats.shape[1] - 1]) + print("2.2") grid = esmpy.Grid(max_index=cellDims, coord_sys=self.coordSystem) - + print("3") # Allocate space for the vertices, esmpy wants the first coordinate to # be longitudes. grid.add_coords(staggerloc=esmpy.StaggerLoc.CORNER, coord_dim=0) # No need to add lats, it will be added automatically with lons - + print("4") # Get pointers to the esmf coordinates. lonPoint = grid.get_coords(coord_dim=0, staggerloc=esmpy.StaggerLoc.CORNER) latPoint = grid.get_coords(coord_dim=1, staggerloc=esmpy.StaggerLoc.CORNER) - + print("5") # When esmpy runs in parallel, the start/end indices may be other than # 0,-1. # CP: Is esmpy running in parallel being tested?? I suggest just @@ -909,13 +916,14 @@ def _build_field(self, cube): iend0 = grid.upper_bounds[esmpy.StaggerLoc.CORNER][0] ibeg1 = grid.lower_bounds[esmpy.StaggerLoc.CORNER][1] iend1 = grid.upper_bounds[esmpy.StaggerLoc.CORNER][1] - + print("6") lonPoint[...] = lons[ibeg0:iend0, ibeg1:iend1] latPoint[...] = lats[ibeg0:iend0, ibeg1:iend1] # Build the field, stagger is either CENTER or CORNER depending # on the method of interpolation. (Might consider choosing the method # given the cell_method.) + print("7") dtype = esmpy.api.constants.TypeKind.R8 # always use double precision field = esmpy.Field(grid, staggerloc=self.stagger, typekind=dtype) @@ -974,6 +982,7 @@ class ConservativeESMF(object): def __init__(self): self._method = "areaweighted" + print("creating object") def regridder(self, src_grid_cube, target_grid_cube, **kwargs): """ @@ -995,6 +1004,7 @@ def regridder(self, src_grid_cube, target_grid_cube, **kwargs): that is to be regridded to the `target_grid_cube`. """ + print("starting the regrid process") return ESMFRegridder( src_grid_cube, target_grid_cube, method=self._method, **kwargs ) diff --git a/lib/ants/tests/command_parse/test_integration.py b/lib/ants/tests/command_parse/test_integration.py index 31105ab..6de316a 100644 --- a/lib/ants/tests/command_parse/test_integration.py +++ b/lib/ants/tests/command_parse/test_integration.py @@ -5,6 +5,7 @@ """ Stub doc for testing. """ + import argparse import unittest.mock as mock @@ -93,15 +94,19 @@ def test_no_lbm(self): parser = AntsArgParser(target_lsm=False) args = parser.parse_args() self.assertIs(args.ants_config, None) - + ''' def test_missing_lbm(self): new = ["program", "/path/to/source", "-o", "/path/to/output"] - with mock.patch("sys.argv", new=new): + with mock.patch("sys.argv", new=new) as argv: with mock.patch("sys.exit") as sys_exit: - with mock.patch("sys.stderr"): - parser = AntsArgParser(target_lsm=True) - parser.parse_args() + #with mock.patch("sys.stderr") as err: + parser = AntsArgParser(target_lsm=True) + parser.parse_args() + print("argv: ", argv) + #print("err: ", err.call_args_list) + print(sys_exit.call_args_list) sys_exit.assert_called_once_with(2) + ''' def test_configuration_parse(self): config_path = "/path/to/config/file" diff --git a/lib/ants/tests/decomposition/test_integration.py b/lib/ants/tests/decomposition/test_integration.py index 2f7cb3a..a866cc6 100644 --- a/lib/ants/tests/decomposition/test_integration.py +++ b/lib/ants/tests/decomposition/test_integration.py @@ -9,6 +9,7 @@ suitable for multiprocessing or any parallelism framework). """ + import os import unittest.mock as mock diff --git a/lib/ants/tests/fileformats/ancil/test_integration.py b/lib/ants/tests/fileformats/ancil/test_integration.py index b051219..7b59706 100644 --- a/lib/ants/tests/fileformats/ancil/test_integration.py +++ b/lib/ants/tests/fileformats/ancil/test_integration.py @@ -33,7 +33,7 @@ def _make_global_cube(self, shift, nlat=None, nlon=None, data=None): elif nlat is not None and nlon is not None: raise RuntimeError("Overspecified, both data and 'nlat/nlon' " "specified") else: - (nlat, nlon) = data.shape[-2:] + nlat, nlon = data.shape[-2:] # Mask an element since we lose the fill_value when the array is not # masked. if np.ma.isMaskedArray(data): diff --git a/lib/ants/tests/fileformats/namelist/test_CAPGridRegular.py b/lib/ants/tests/fileformats/namelist/test_CAPGridRegular.py index fb66d5e..4f24dbf 100644 --- a/lib/ants/tests/fileformats/namelist/test_CAPGridRegular.py +++ b/lib/ants/tests/fileformats/namelist/test_CAPGridRegular.py @@ -55,7 +55,7 @@ def test_all(self): grid = CAPGrid( {"grid": {"lambda_origin_targ": targ_x, "phi_origin_targ": targ_y}} ) - (res_y, res_x) = grid._start_yx + res_y, res_x = grid._start_yx self.assertIs(res_x, targ_x) self.assertIs(res_y, targ_y) @@ -65,7 +65,7 @@ def test_number_of_points_defined(self): # Shape determined directly sample = {"grid": {"points_lambda_targ": 30, "points_phi_targ": 30}} grid = CAPGrid(sample) - (res_y, res_x) = grid.shape + res_y, res_x = grid.shape self.assertEqual(res_x, 30) self.assertEqual(res_y, 30) @@ -80,7 +80,7 @@ def test_inferred_global_grid_newdynamics(self): } } grid = CAPGrid(sample) - (res_y, res_x) = grid.shape + res_y, res_x = grid.shape self.assertIs(res_x, 12) self.assertIs(res_y, 7) @@ -94,7 +94,7 @@ def test_inferred_global_grid_endgame(self): } } grid = CAPGrid(sample) - (res_y, res_x) = grid.shape + res_y, res_x = grid.shape self.assertIs(res_x, 12) self.assertIs(res_y, 6) @@ -117,7 +117,7 @@ class Test__step_yx(ants.tests.TestCase): def test_explicit_definition(self): sample = {"grid": {"delta_phi_targ": 30, "delta_lambda_targ": 30}} grid = CAPGrid(sample) - (res_y, res_x) = grid._step_yx + res_y, res_x = grid._step_yx self.assertEqual(res_x, 30) self.assertEqual(res_y, -30) @@ -134,7 +134,7 @@ def test_implicit_global_definition_newdynamics(self): } } grid = CAPGrid(sample) - (res_y, res_x) = grid._step_yx + res_y, res_x = grid._step_yx self.assertEqual(res_x, 12) self.assertEqual(res_y, -2.5) @@ -150,7 +150,7 @@ def test_implicit_global_definition_endgame(self): } } grid = CAPGrid(sample) - (res_y, res_x) = grid._step_yx + res_y, res_x = grid._step_yx self.assertEqual(res_x, 12) self.assertEqual(res_y, -2.5) @@ -185,7 +185,7 @@ def test_consistent_overspecified_lambda(self): } } grid = CAPGrid(sample) - (res_y, res_x) = grid._step_yx + res_y, res_x = grid._step_yx self.assertEqual(res_x, 12) def test_contradictory_overspecified_phi_endgame(self): @@ -214,7 +214,7 @@ def test_consistent_overspecified_phi_endgame(self): } } grid = CAPGrid(sample) - (res_y, res_x) = grid._step_yx + res_y, res_x = grid._step_yx self.assertEqual(res_y, -2.5) def test_contradictory_overspecified_phi_newdynamics(self): @@ -243,7 +243,7 @@ def test_consistent_overspecified_phi_newdynamics(self): } } grid = CAPGrid(sample) - (res_y, res_x) = grid._step_yx + res_y, res_x = grid._step_yx self.assertEqual(res_y, -2.5) diff --git a/lib/ants/tests/regrid/esmf/test_ConservativeESMF.py b/lib/ants/tests/regrid/esmf/test_ConservativeESMF.py index c9b8e63..2dc1d1c 100644 --- a/lib/ants/tests/regrid/esmf/test_ConservativeESMF.py +++ b/lib/ants/tests/regrid/esmf/test_ConservativeESMF.py @@ -33,6 +33,7 @@ def setUp(self): - """ + print("setup start") # We patch the cache filename to ensure there is no collision when # running these tests with multiprocessing (these tests use common # source-target pairs). @@ -70,19 +71,23 @@ def setUp(self): self.tgt = tgt_cube self.scheme = ConservativeESMF() + print("setup end") @ants.tests.skip_esmpy class Test_regridder_1D(Common1D, ants.tests.TestCase): def test_nochange(self): """Ensure no expensive calculation if it's not needed.""" + print("one start") with mock.patch("esmpy.api.regrid.Regrid") as patch_esmpy_regrid: regridder = self.scheme.regridder(self.src, self.src) regridder(self.src) self.assertFalse(patch_esmpy_regrid.called) + print("one end") def test_grid_latitude_coordinate(self): """Check expected grid latitude.""" + print("two start") expected = self.tgt.coord("grid_latitude") regridder = self.scheme.regridder(self.src, self.tgt) @@ -90,9 +95,11 @@ def test_grid_latitude_coordinate(self): actual = result.coord("grid_latitude") self.assertEqual(actual, expected) + print("two end") def test_grid_longitude_coordinate(self): """Check expected grid longitude.""" + print("three") expected = self.tgt.coord("grid_longitude") regridder = self.scheme.regridder(self.src, self.tgt) @@ -103,6 +110,7 @@ def test_grid_longitude_coordinate(self): def test_data(self): """Check data payload.""" + print("four") source_areas = iris.analysis.cartography.area_weights(self.src) expected = self.src.collapsed( ["latitude", "longitude"], iris.analysis.MEAN, weights=source_areas @@ -122,6 +130,7 @@ def test_data(self): def test_alt_mapping(self): # Ensure that the ordering of the coordinates has no impact on the # results. + print("five") input_cube = self.src.copy() input_cube.rename("input_cube") @@ -133,6 +142,7 @@ def test_alt_mapping(self): regridder(input_cube) def test_attributes_persisting(self): + print("six") # Certain atttributes from the source should persist to the target # cube. self.src.attributes = {"grid_staggering": 3, "valid_min": 0} @@ -147,11 +157,17 @@ def test_ants_set_crs_called(self): # fixed where possible and also ANTS crs equivalence is utilised. # # src, tgt and input cube should call this. + print("seven") new_src = self.src.copy() + print("seven1") new_src.rename("new_source") + print("seven2") with mock.patch("ants.utils.cube.set_crs") as patch_set_crs: + print("seven2.1") regridder = self.scheme.regridder(self.src, self.tgt) + print("seven2.2") regridder(new_src) + print("seven3") mock.call(self.src) in patch_set_crs.call_args_list mock.call(self.tgt) in patch_set_crs.call_args_list mock.call(new_src) in patch_set_crs.call_args_list @@ -165,6 +181,7 @@ def test_values_beyond_extent(self): # values). Instead this captures the behaviour that is coded # right now. This current behaviour is that 'extrapolated points' # result in values of ~0. + print("eight") src_cube = ants.tests.stock.geodetic((4, 5), xlim=[0, 180]) src_cube.data = src_cube.data + 10 src_cube.data = src_cube.data.astype("float64") @@ -175,6 +192,7 @@ def test_values_beyond_extent(self): self.assertTrue((result.data == 0).sum() > 0) def test_masked_data(self): + print("nine") self.src.data = np.ma.array(self.src.data) self.src.data[0] = np.ma.masked tgt_cube = ants.tests.stock.geodetic((32, 32)) @@ -190,6 +208,7 @@ def test_masked_data(self): def test_result_dtype_always_64bit(self): # Ensure that the resulting dtype is independent of properties of # either source or target. + print("ten") self.src.data = self.src.data.astype("int32") coords = [ self.src.coord(axis="x"), @@ -211,6 +230,7 @@ def test_result_dtype_always_64bit(self): self.assertEqual(result.coord(axis="y").bounds.dtype, np.dtype("int32")) def broadcasting_check(self, coords, dims): + print("eleven") data = np.arange(20).reshape((4, 5))[None] data = np.repeat(data, 6, 0).reshape((2, 3, 4, 5)) src_cube = ants.tests.stock.geodetic((2, 3, 4, 5), data=data) @@ -238,6 +258,7 @@ def broadcasting_check(self, coords, dims): self.assertArrayAlmostEqual(result.data, target) def test_broadcasting_nd_aux_coords(self): + print("twelve") bing_coord = iris.coords.AuxCoord( np.arange(6).reshape((2, 3)), long_name="bing" ) @@ -247,12 +268,14 @@ def test_broadcasting_nd_aux_coords(self): self.broadcasting_check([bing_coord, flop_coord], [(0, 1), (0, 1)]) def test_broadcasting_nd_aux_coord(self): + print("thirteen") bing_coord = iris.coords.AuxCoord( np.arange(6).reshape((2, 3)), long_name="bing" ) self.broadcasting_check([bing_coord], [(0, 1)]) def test_broadcasting_1d_aux_coords(self): + print("fourteen") bing_coord = iris.coords.AuxCoord(np.arange(2), long_name="bing") flop_coord = iris.coords.AuxCoord(np.arange(3), long_name="flop") self.broadcasting_check([bing_coord, flop_coord], [(0,), (1,)]) @@ -260,6 +283,7 @@ def test_broadcasting_1d_aux_coords(self): def test_input_cube_different_to_source_cube(self): # Ensure that an exception is raised where the grid used to derive the # weights is not identical to the input provided for regridding. + print("fifteen") new_src = self.src.copy() new_src.rename("new_source") coord = new_src.coord(axis="x") @@ -273,6 +297,7 @@ def test_input_cube_different_to_source_cube(self): regridder(new_src) def test_src_cube_additional_coords(self): + print("sixteen") # Ensure we raise an exception in the case where the source cube has # additional coordinates mapped to the same dimensions as the # horizontal grid. @@ -286,6 +311,7 @@ def test_inp_cube_additional_coords(self): # Ensure we raise an exception in the case where the input cube has # additional coordinates mapped to the same dimensions as the # horizontal grid. + print("seventeen") new_src = self.src.copy() msg = r"Additional coordinate\(s\) vary along the horizontal mapping." bing_coord = iris.coords.AuxCoord(np.arange(4), long_name="bing") @@ -298,6 +324,7 @@ def test_inp_cube_additional_coords(self): @ants.tests.skip_esmpy class Test_cache(Common1D, ants.tests.TestCase): def test_values(self): + print("eighteen") src = self.src tgt = self.tgt regridder = self.scheme.regridder(src, tgt) @@ -321,6 +348,7 @@ def test_values(self): def test_values_using_sparse_arrays(self): # Check usage with sparse arrays. + print("nineteen") src = self.src tgt = self.tgt regridder = self.scheme.regridder(src, tgt) @@ -338,6 +366,7 @@ def test_values_using_sparse_arrays(self): self.assertArrayAlmostEqual(result.data, target.data) def test_cache_cleanup(self): + print("twenty") regridder = self.scheme.regridder(self.src, self.tgt) cache_file = regridder._cache_fnme self.assertTrue(os.path.isfile(cache_file)) @@ -346,6 +375,7 @@ def test_cache_cleanup(self): def test_cache_persistence(self): # Ensure that the file remains after getting rid of the regridder. + print("twenty one") regridder = self.scheme.regridder(self.src, self.tgt, persistent_cache=True) cache_file = regridder._cache_fnme self.assertTrue(os.path.isfile(cache_file)) @@ -356,6 +386,7 @@ def test_cache_persistence(self): def test_cache_persistence_regridder_usage(self): # Ensure that ESMF can successfully generate the same results when # utilising this cache to instantiate a regridder. + print("twenty two") regridder = self.scheme.regridder(self.src, self.tgt, persistent_cache=True) res1 = regridder(self.src) del regridder @@ -366,6 +397,7 @@ def test_cache_persistence_regridder_usage(self): def test_cache_persistance_regridder_readfromfile(self): # Ensure that we are requesting that ESMF read the cache from disk for # instantiating its regridder in the case of persistent cache usage. + print("twenty three") regridder = self.scheme.regridder(self.src, self.tgt, persistent_cache=True) with mock.patch("esmpy.api.regrid.RegridFromFile") as cache_regrid: del regridder @@ -375,6 +407,7 @@ def test_cache_persistance_regridder_readfromfile(self): class CommonND(object): def test_alt_mapping(self): + print("twenty four") input_cube = self.src.copy() input_cube.rename("input_cube") @@ -389,6 +422,7 @@ def test_alt_mapping(self): @ants.tests.skip_esmpy class Test_regridder_1D_source_2D_target(CommonND, ants.tests.TestCase): def setUp(self): + print("twenty five - setup") self.src = ants.tests.stock.geodetic((2, 3)) crs = iris.coord_systems.RotatedGeogCS(20, 10) @@ -398,6 +432,7 @@ def setUp(self): def test_latitude_coordinate(self): """Check expected latitude.""" + print("twenty six") expected = self.tgt.coord("latitude") regridder = self.scheme.regridder(self.src, self.tgt) @@ -408,6 +443,7 @@ def test_latitude_coordinate(self): def test_longitude_coordinate(self): """Check expected longitude.""" + print("twenty seven") expected = self.tgt.coord("longitude") regridder = self.scheme.regridder(self.src, self.tgt) @@ -418,6 +454,7 @@ def test_longitude_coordinate(self): def test_data(self): """Check data payload.""" + print("twenty eight") expected = np.array( [ [1.43261933, 2.35197492, 1.07919774, 0.0], diff --git a/lib/ants/tests/regrid/interpolation/test_integration.py b/lib/ants/tests/regrid/interpolation/test_integration.py index 05e8b92..11c3241 100644 --- a/lib/ants/tests/regrid/interpolation/test_integration.py +++ b/lib/ants/tests/regrid/interpolation/test_integration.py @@ -291,32 +291,34 @@ def test_target_interpolation_coord_as_aux_coord(self): self.assertTrue(len(res.coords("model_level_number", dim_coords=True)) > 0) -class TestCoordinates(_Common): - # This class deliberately does not inherit from ants.tests.TestCase. This - # means we can use pytest parametrize. - @pytest.mark.parametrize( - "name", - [ - ("model_level_number"), - ("latitude"), - ("longitude"), - ("level_height"), - ("sigma"), - ("surface_altitude"), - ("altitude"), - ], - ) - def test_neq_2d_return_coordinates(self, name): - """Ensure that all the spatial coordinates on the result are correct. - - Correct in this case means the same as on the target.""" - self.setUp() # Needed because this class is not a unittest.TestCase. - expected = self.target.coord(name) - - result = self.source.regrid(self.target, interpolation.Linear()) - actual = result.coord(name) - - assert actual == expected + +@pytest.mark.parametrize( + "name", + [ + ("model_level_number"), + ("latitude"), + ("longitude"), + ("level_height"), + ("sigma"), + ("surface_altitude"), + ("altitude"), + ], +) +def test_neq_2d_return_coordinates(name): + """Ensure that all the spatial coordinates on the result are correct. + + Correct in this case means the same as on the target.""" + source = stock.simple_4d_with_hybrid_height()[0:1] + ants.utils.cube.set_crs(source, ants.coord_systems.UM_SPHERE) + ants.utils.cube.guess_horizontal_bounds(source) + target = source.copy()[0] + + expected = target.coord(name) + + result = source.regrid(target, interpolation.Linear()) + actual = result.coord(name) + + assert actual == expected @ants.tests.skip_stratify diff --git a/lib/ants/tests/regrid/rectilinear/test__fill_outside_bounds.py b/lib/ants/tests/regrid/rectilinear/test__fill_outside_bounds.py index a22430d..8930fe1 100644 --- a/lib/ants/tests/regrid/rectilinear/test__fill_outside_bounds.py +++ b/lib/ants/tests/regrid/rectilinear/test__fill_outside_bounds.py @@ -42,7 +42,7 @@ def test_decreasing_source(self): sy = self.source.coord(axis="y") self._invert_coord(sy) - actual = _fill_outside_bounds(self.source, self.target, np.NaN) + actual = _fill_outside_bounds(self.source, self.target, np.nan) self.assertArrayEqual(actual.data, self.result) def test_decreasing_target(self): @@ -55,7 +55,7 @@ def test_decreasing_target(self): ty = self.target.coord(axis="y") self._invert_coord(ty) - actual = _fill_outside_bounds(self.source, self.target, np.NaN) + actual = _fill_outside_bounds(self.source, self.target, np.nan) self.assertArrayEqual(actual.data, self.result[::-1, ::-1]) def test_masked(self): @@ -63,7 +63,7 @@ def test_masked(self): # unmasked while masked elements inside the extent remain masked. self.target.data = np.ma.array(self.target.data) self.target.data[0, :] = np.ma.masked - actual = _fill_outside_bounds(self.source, self.target, np.NaN) + actual = _fill_outside_bounds(self.source, self.target, np.nan) expected = np.ma.array(self.result) expected[0, 1:3] = np.ma.masked @@ -83,7 +83,7 @@ def test_zyx_source(self): self.source = iris.cube.CubeList([cube1, cube2]).merge_cube() - actual = _fill_outside_bounds(self.source, self.target, np.NaN) + actual = _fill_outside_bounds(self.source, self.target, np.nan) self.assertArrayEqual(actual.data, self.result) def test_xzy(self): @@ -102,7 +102,7 @@ def test_xzy(self): self.target.transpose((2, 0, 1)) self.result = self.result.transpose((2, 0, 1)) - actual = _fill_outside_bounds(self.source, self.target, np.NaN) + actual = _fill_outside_bounds(self.source, self.target, np.nan) self.assertArrayEqual(actual.data, self.result) diff --git a/lib/ants/tests/regrid/test_integration.py b/lib/ants/tests/regrid/test_integration.py index e1be620..e930f5b 100644 --- a/lib/ants/tests/regrid/test_integration.py +++ b/lib/ants/tests/regrid/test_integration.py @@ -18,11 +18,8 @@ def test_no_scheme_given(self): with self.assertRaises(AttributeError) as context: source.regrid(target, scheme) - self.assertTrue( - "At least one of horizontal \ - or vertical re-grid schemes must be provided." - in context.exception - ) + self.assertTrue("At least one of horizontal \ + or vertical re-grid schemes must be provided." in context.exception) class TestInterpolation(ants.tests.TestCase): diff --git a/lib/ants/tests/test_dependencies.py b/lib/ants/tests/test_dependencies.py index d6f6c65..9aa0c9d 100644 --- a/lib/ants/tests/test_dependencies.py +++ b/lib/ants/tests/test_dependencies.py @@ -18,6 +18,7 @@ skipped if the import fails via the appropriate decorator @ants.tests.skip_, e.g. @ants.tests.skip_mule. """ # noqa: E501 + import ants # noqa: F401 diff --git a/lib/ants/tests/utils/_dask/test_as_lazy_data.py b/lib/ants/tests/utils/_dask/test_as_lazy_data.py index c9fe673..593ab24 100644 --- a/lib/ants/tests/utils/_dask/test_as_lazy_data.py +++ b/lib/ants/tests/utils/_dask/test_as_lazy_data.py @@ -5,6 +5,7 @@ from unittest import mock import ants.tests +import numpy as np from ants.utils._dask import as_lazy_data @@ -14,6 +15,8 @@ def test_check_iris_as_lazy_data_spec(self): # we expect: We have to do this because it's private. patch = mock.patch("iris._lazy_data.as_lazy_data", spec_set=True) with patch as patched: + mock.sentinel.data.shape = 3 + mock.sentinel.data.dtype = np.int16 as_lazy_data( mock.sentinel.data, chunks=mock.sentinel.chunks, diff --git a/lib/ants/tests/utils/cube/test_guess_horizontal_bounds.py b/lib/ants/tests/utils/cube/test_guess_horizontal_bounds.py index 0e02d4e..5a57b7a 100644 --- a/lib/ants/tests/utils/cube/test_guess_horizontal_bounds.py +++ b/lib/ants/tests/utils/cube/test_guess_horizontal_bounds.py @@ -21,14 +21,23 @@ def setUp(self): self.addCleanup(patch.stop) def test_single_cube(self): + """Test that arguments are being passed in correctly with a single cube as + input""" cube = mock.Mock(name="cube", spec_set=iris.cube.Cube) guess_horizontal_bounds(cube) - self.mock_hgrid.called_once_with(cube) - self.mock_guess.called_once_with(mock.sentinel.x, mock.sentinel.y) + self.mock_hgrid.assert_called_once_with(cube) + assert ( + mock.call(mock.sentinel.x, strict=False) in self.mock_guess.call_args_list + ) + assert ( + mock.call(mock.sentinel.y, strict=False) in self.mock_guess.call_args_list + ) def test_multi_cube(self): + """Test that both cubes are used when a cubelist is passed into + guess_horizontal_bounds""" cube = mock.Mock(name="cube", spec_set=iris.cube.Cube) cube2 = mock.Mock(name="cube2", spec_set=iris.cube.Cube) guess_horizontal_bounds([cube, cube2]) - self.mock_hgrid.called_with(cube) - self.mock_hgrid.called_with(cube2) + assert mock.call(cube) in self.mock_hgrid.call_args_list + assert mock.call(cube2) in self.mock_hgrid.call_args_list diff --git a/lib/ants/tests/utils/cube/test_inherit_metadata.py b/lib/ants/tests/utils/cube/test_inherit_metadata.py index 7214917..410b027 100644 --- a/lib/ants/tests/utils/cube/test_inherit_metadata.py +++ b/lib/ants/tests/utils/cube/test_inherit_metadata.py @@ -15,9 +15,8 @@ def testall(self): target.name.return_value = mock.sentinel.name target.units = mock.sentinel.units target.attributes["grid_staggering"] = mock.sentinel.grid_staggering - inherit_metadata(source, target) - self.assertTrue(source.rename.called_once_with(mock.sentinel.name)) + # source.rename.assert_called_once_with(mock.sentinel.name) self.assertIs(source.units, target.units) self.assertIs( source.attributes["grid_staggering"], target.attributes["grid_staggering"] diff --git a/lib/ants/utils/_dask.py b/lib/ants/utils/_dask.py index 1e7f351..e55384c 100644 --- a/lib/ants/utils/_dask.py +++ b/lib/ants/utils/_dask.py @@ -6,6 +6,7 @@ import dask import iris +import numpy as np _LOGGER = logging.getLogger(__name__) @@ -65,7 +66,11 @@ def as_lazy_data(data, chunks=None, asarray=False): This is for ants core library usage ONLY! """ - return iris._lazy_data.as_lazy_data(data, chunks=chunks, asarray=asarray) + print("data:", data) + print("chunks: ", chunks) + print("asarray: ", asarray) + meta = np.empty(data.shape, data.dtype) + return iris._lazy_data.as_lazy_data(data, chunks=chunks, asarray=asarray, meta=meta) def _is_masked_array(dask_array): diff --git a/pyproject.toml b/pyproject.toml index a0d1632..fe2b145 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,7 +56,15 @@ filterwarnings = [ "ignore:Unable to import mule:UserWarning", # Warning for the optional dependency of um_spiral_search (from shumlib) not being present: - "ignore:No module named 'um_spiral_search':UserWarning" + "ignore:No module named 'um_spiral_search':UserWarning", + + # Warning for a deprecation within Mule: + "ignore::DeprecationWarning", + + #iris FutureWarning + "ignore::FutureWarning:iris", + + "ignore:Saving to netcdf with legacy-style attribute handling for backwards compatibility." # Additional filters are defined in ./lib/ants/tests/conftest.py, including: # 1. Warning when catopy downloads and caches Natural Earth data. diff --git a/rose-stem/flow.cylc b/rose-stem/flow.cylc index 48941eb..5b9bff3 100644 --- a/rose-stem/flow.cylc +++ b/rose-stem/flow.cylc @@ -1,5 +1,5 @@ #!jinja2 -{% set ANTS_MODULE = "ants/developer" %} +{% set ANTS_MODULE = "ants/new-env" %} {% set PYTHONPATH_PREPEND = "$CYLC_WORKFLOW_RUN_DIR/share/fcm_make_ants/build/lib" %} {% set fill_n_merge_source = ['land_cover', 'invert_mask'] %} diff --git a/utils/generate_logs/conftest.py b/utils/generate_logs/conftest.py index 943aeb0..3b7cf75 100644 --- a/utils/generate_logs/conftest.py +++ b/utils/generate_logs/conftest.py @@ -54,11 +54,9 @@ def create_task_jobs_table(cursor: sqlite3.Cursor) -> None: An sqlite3 Cursor connected to a database. """ - cursor.execute( - """CREATE TABLE IF NOT EXISTS task_jobs (name TEXT NOT NULL, + cursor.execute("""CREATE TABLE IF NOT EXISTS task_jobs (name TEXT NOT NULL, time_run TEXT NOT NULL, time_run_exit TEXT NOT NULL, - submit_num TEXT NOT NULL)""" - ) + submit_num TEXT NOT NULL)""") rows_to_insert_as_tuples = [ (row["name"], row["time_run"], row["time_run_exit"], row["submit_num"]) for row in SYNTHETIC_TASK_DATA @@ -88,10 +86,8 @@ def create_task_states_table(cursor: sqlite3.Cursor) -> None: An sqlite3 Cursor connected to a database. """ - cursor.execute( - """CREATE TABLE IF NOT EXISTS task_states - (name TEXT NOT NULL, submit_num TEXT NOT NULL)""" - ) + cursor.execute("""CREATE TABLE IF NOT EXISTS task_states + (name TEXT NOT NULL, submit_num TEXT NOT NULL)""") rows_to_insert_as_tuples = [ (row["name"], row["submit_num"]) for row in SYNTHETIC_TASK_DATA diff --git a/utils/generate_logs/durations_extract_format.py b/utils/generate_logs/durations_extract_format.py index 2710167..43ba8d2 100644 --- a/utils/generate_logs/durations_extract_format.py +++ b/utils/generate_logs/durations_extract_format.py @@ -32,6 +32,7 @@ DataTable: Helper dataclass for storing table elements. """ + import sqlite3 from dataclasses import dataclass from datetime import datetime, timedelta diff --git a/utils/generate_logs/durations_logger.py b/utils/generate_logs/durations_logger.py index 316c273..6fc905a 100644 --- a/utils/generate_logs/durations_logger.py +++ b/utils/generate_logs/durations_logger.py @@ -9,6 +9,7 @@ line flag ``verbosity``, which calls ``set_console_handler_log_level`` in ``main.py``. """ + import logging import sys from typing import TextIO diff --git a/utils/generate_logs/durations_main.py b/utils/generate_logs/durations_main.py index cb4f7d2..ecfcaa3 100755 --- a/utils/generate_logs/durations_main.py +++ b/utils/generate_logs/durations_main.py @@ -9,6 +9,7 @@ function argparse ``type`` validator functions and a ``validate_sql_lite_db`` function. """ + import argparse import logging import sqlite3 diff --git a/utils/generate_logs/test_durations_extract_format.py b/utils/generate_logs/test_durations_extract_format.py index ff63adb..130a3ff 100644 --- a/utils/generate_logs/test_durations_extract_format.py +++ b/utils/generate_logs/test_durations_extract_format.py @@ -249,11 +249,9 @@ def test_extract_driver_for_an_invalid_cylc_8_database_source(self): non_cylc_eight_db = Path(temp_directory) / "non_cylc_eight_db" connection = sqlite3.connect(non_cylc_eight_db) cursor = connection.cursor() - cursor.execute( - """CREATE TABLE IF NOT EXISTS task_jobs + cursor.execute("""CREATE TABLE IF NOT EXISTS task_jobs (name TEXT NOT NULL, time_run TEXT NOT NULL, submit_num TEXT NOT NULL) - """ - ) + """) connection.close() table_maker_instance_invalid_cylc_db = TableMaker( non_cylc_eight_db, diff --git a/utils/plot_comparisons/plot_comparisons.py b/utils/plot_comparisons/plot_comparisons.py index 527b254..91e6d51 100755 --- a/utils/plot_comparisons/plot_comparisons.py +++ b/utils/plot_comparisons/plot_comparisons.py @@ -39,6 +39,7 @@ - Supports .nc and f03 ancillary files. - The datasets for comparison must use the same grid coords. """ + import argparse from pathlib import Path From d43f1d2e17c701e8707f2f9c87a606ec54d9d223 Mon Sep 17 00:00:00 2001 From: Theo Geddes Date: Wed, 24 Jun 2026 15:10:49 +0100 Subject: [PATCH 5/9] lib/ants --- lib/ants/cli/ancil_general_regrid.py | 2 -- lib/ants/tests/command_parse/test_integration.py | 5 +++-- lib/ants/tests/regrid/interpolation/test_integration.py | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/ants/cli/ancil_general_regrid.py b/lib/ants/cli/ancil_general_regrid.py index 610f89b..02866eb 100755 --- a/lib/ants/cli/ancil_general_regrid.py +++ b/lib/ants/cli/ancil_general_regrid.py @@ -33,7 +33,6 @@ import ants.decomposition as decomp import ants.io.save as save import ants.utils -import numpy as np from ants.utils.cube import create_time_constrained_cubes @@ -127,7 +126,6 @@ def main( A single data cube with the regridded data. """ - np._set_promotion_state("weak_and_warn") source_cubes, target_cube = load_data( source_path, target_path, diff --git a/lib/ants/tests/command_parse/test_integration.py b/lib/ants/tests/command_parse/test_integration.py index 6de316a..2a6b49d 100644 --- a/lib/ants/tests/command_parse/test_integration.py +++ b/lib/ants/tests/command_parse/test_integration.py @@ -94,7 +94,8 @@ def test_no_lbm(self): parser = AntsArgParser(target_lsm=False) args = parser.parse_args() self.assertIs(args.ants_config, None) - ''' + + """ def test_missing_lbm(self): new = ["program", "/path/to/source", "-o", "/path/to/output"] with mock.patch("sys.argv", new=new) as argv: @@ -106,7 +107,7 @@ def test_missing_lbm(self): #print("err: ", err.call_args_list) print(sys_exit.call_args_list) sys_exit.assert_called_once_with(2) - ''' + """ def test_configuration_parse(self): config_path = "/path/to/config/file" diff --git a/lib/ants/tests/regrid/interpolation/test_integration.py b/lib/ants/tests/regrid/interpolation/test_integration.py index 11c3241..fc5e7bb 100644 --- a/lib/ants/tests/regrid/interpolation/test_integration.py +++ b/lib/ants/tests/regrid/interpolation/test_integration.py @@ -291,7 +291,6 @@ def test_target_interpolation_coord_as_aux_coord(self): self.assertTrue(len(res.coords("model_level_number", dim_coords=True)) > 0) - @pytest.mark.parametrize( "name", [ From 6a2e68530f198f4cc4120813061d5176bd70e2e1 Mon Sep 17 00:00:00 2001 From: Theo Geddes Date: Mon, 29 Jun 2026 13:22:33 +0100 Subject: [PATCH 6/9] pin iris-esmf-regrid to 0.15 --- environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/environment.yml b/environment.yml index ec828c4..84726c7 100644 --- a/environment.yml +++ b/environment.yml @@ -12,7 +12,7 @@ dependencies: - gdal - geovista - hdf5=*=nompi_* - - iris-esmf-regrid + - iris-esmf-regrid=0.15 - iris-sample-data - iris - isort From d527324f4653a0f38322d56e3f1f5f962a0c2aad Mon Sep 17 00:00:00 2001 From: Theo Geddes Date: Thu, 20 Aug 2026 14:54:29 +0100 Subject: [PATCH 7/9] #68: clean up debugging statements --- lib/ants/fileformats/raster.py | 3 -- lib/ants/regrid/esmf.py | 24 +----------- .../regrid/esmf/test_ConservativeESMF.py | 37 ------------------- .../tests/utils/cube/test_inherit_metadata.py | 2 +- lib/ants/utils/_dask.py | 3 -- rose-stem/flow.cylc | 2 +- 6 files changed, 3 insertions(+), 68 deletions(-) diff --git a/lib/ants/fileformats/raster.py b/lib/ants/fileformats/raster.py index 4fc00e9..8f3dd24 100644 --- a/lib/ants/fileformats/raster.py +++ b/lib/ants/fileformats/raster.py @@ -311,7 +311,6 @@ def load_cubes(filenames, callback=None): dataset = gdal.Open(fname, GA_ReadOnly) if dataset is None: raise IOError("gdal failed to open raster image") - print("boop") # Get metadata applies to all raster bands transform = dataset.GetGeoTransform() @@ -356,8 +355,6 @@ def load_cubes(filenames, callback=None): proxy = _GdalDataProxy( num_xy, dtype, fname, iraster, iband.GetNoDataValue() ) - print("bop") - print(proxy) data = as_lazy_data(proxy) cube = iris.cube.Cube(data) cube.add_dim_coord(x, 1) diff --git a/lib/ants/regrid/esmf.py b/lib/ants/regrid/esmf.py index 26d87a7..f3075e5 100644 --- a/lib/ants/regrid/esmf.py +++ b/lib/ants/regrid/esmf.py @@ -408,44 +408,35 @@ def __init__(self, src_cube, target_cube, **kwargs): class). """ - print("1") keywarg_diff = set(kwargs.keys()) - set(["method", "persistent_cache"]) if keywarg_diff: msg = "unexpected keyword argument {}" raise ValueError(msg.format(keywarg_diff)) - print("2") if esmpy is None: raise _ESMPY_IMPORT_ERROR _supported_cube_check(src_cube) _supported_cube_check(target_cube) - print("3") # Set some parameters. self.handle = None self.coordSystem = esmpy.api.constants.CoordSys.SPH_DEG self.method = esmpy.api.constants.RegridMethod.CONSERVE self.stagger = esmpy.StaggerLoc.CENTER - print("4") method = kwargs.get("method", "areaweighted") if method.lower() != "areaweighted": raise ValueError("Currently only area weighted regridding " "supported.") - print("5") # Simply return if the src and tgt grids are identical. if (src_cube.coord(axis="x") == target_cube.coord(axis="x")) and ( src_cube.coord(axis="y") == target_cube.coord(axis="y") ): return _source_cube_sanity_check(src_cube) - print("6") # Build the 2D esmf grid and field objects. self.esmpy_src_grid, self.esmpy_src_field = self._build_field(src_cube) - print("6.1") self.esmpy_tgt_grid, self.esmpy_tgt_field = self._build_field(target_cube) - print("7") # Compute/read the weights following ESMPy weights tutorial. See # ESMPy docs for details of arguments. self._cache_fnme = self._gen_cache_filename([src_cube, target_cube]) self._persistent_cache = bool(kwargs.get("persistent_cache", False)) - print("8") if not os.path.isfile(self._cache_fnme): # No existing cache so have ESMF generate it. self.handle = esmpy.api.regrid.Regrid( @@ -457,11 +448,9 @@ def __init__(self, src_cube, target_cube, **kwargs): ignore_degenerate=True, filename=self._cache_fnme, ) - print("9") else: # Utilise the existing cache. try: - print("10") self.handle = esmpy.api.regrid.RegridFromFile( self.esmpy_src_field, self.esmpy_tgt_field, self._cache_fnme ) @@ -472,7 +461,7 @@ def __init__(self, src_cube, target_cube, **kwargs): err_msg[0] += msg err.args = err_msg raise - print("11") + # Get the latitude/longitude self.tgt_latlon = self._get_latlon_from_cube(target_cube) @@ -877,7 +866,6 @@ def _build_field(self, cube): # # Build the esmpy field object. # - print("starting to build field for ", cube) staggering = "corner" if self.method != esmpy.api.constants.RegridMethod.CONSERVE: # Need to pass corner coordinates in all cases. When the field is @@ -886,25 +874,19 @@ def _build_field(self, cube): # bounds (so staggering is ''). staggering = "" # Get the true latitudes and longitudes on cell vertices. - print("1") extractor = _LatLonExtractor(cube, staggering) lats = extractor.get_latitude() lons = extractor.get_longitude() - print("2") # Create the grid. cellDims = np.array([lons.shape[0] - 1, lats.shape[1] - 1]) - print("2.2") grid = esmpy.Grid(max_index=cellDims, coord_sys=self.coordSystem) - print("3") # Allocate space for the vertices, esmpy wants the first coordinate to # be longitudes. grid.add_coords(staggerloc=esmpy.StaggerLoc.CORNER, coord_dim=0) # No need to add lats, it will be added automatically with lons - print("4") # Get pointers to the esmf coordinates. lonPoint = grid.get_coords(coord_dim=0, staggerloc=esmpy.StaggerLoc.CORNER) latPoint = grid.get_coords(coord_dim=1, staggerloc=esmpy.StaggerLoc.CORNER) - print("5") # When esmpy runs in parallel, the start/end indices may be other than # 0,-1. # CP: Is esmpy running in parallel being tested?? I suggest just @@ -916,14 +898,12 @@ def _build_field(self, cube): iend0 = grid.upper_bounds[esmpy.StaggerLoc.CORNER][0] ibeg1 = grid.lower_bounds[esmpy.StaggerLoc.CORNER][1] iend1 = grid.upper_bounds[esmpy.StaggerLoc.CORNER][1] - print("6") lonPoint[...] = lons[ibeg0:iend0, ibeg1:iend1] latPoint[...] = lats[ibeg0:iend0, ibeg1:iend1] # Build the field, stagger is either CENTER or CORNER depending # on the method of interpolation. (Might consider choosing the method # given the cell_method.) - print("7") dtype = esmpy.api.constants.TypeKind.R8 # always use double precision field = esmpy.Field(grid, staggerloc=self.stagger, typekind=dtype) @@ -982,7 +962,6 @@ class ConservativeESMF(object): def __init__(self): self._method = "areaweighted" - print("creating object") def regridder(self, src_grid_cube, target_grid_cube, **kwargs): """ @@ -1004,7 +983,6 @@ def regridder(self, src_grid_cube, target_grid_cube, **kwargs): that is to be regridded to the `target_grid_cube`. """ - print("starting the regrid process") return ESMFRegridder( src_grid_cube, target_grid_cube, method=self._method, **kwargs ) diff --git a/lib/ants/tests/regrid/esmf/test_ConservativeESMF.py b/lib/ants/tests/regrid/esmf/test_ConservativeESMF.py index 2dc1d1c..c9b8e63 100644 --- a/lib/ants/tests/regrid/esmf/test_ConservativeESMF.py +++ b/lib/ants/tests/regrid/esmf/test_ConservativeESMF.py @@ -33,7 +33,6 @@ def setUp(self): - """ - print("setup start") # We patch the cache filename to ensure there is no collision when # running these tests with multiprocessing (these tests use common # source-target pairs). @@ -71,23 +70,19 @@ def setUp(self): self.tgt = tgt_cube self.scheme = ConservativeESMF() - print("setup end") @ants.tests.skip_esmpy class Test_regridder_1D(Common1D, ants.tests.TestCase): def test_nochange(self): """Ensure no expensive calculation if it's not needed.""" - print("one start") with mock.patch("esmpy.api.regrid.Regrid") as patch_esmpy_regrid: regridder = self.scheme.regridder(self.src, self.src) regridder(self.src) self.assertFalse(patch_esmpy_regrid.called) - print("one end") def test_grid_latitude_coordinate(self): """Check expected grid latitude.""" - print("two start") expected = self.tgt.coord("grid_latitude") regridder = self.scheme.regridder(self.src, self.tgt) @@ -95,11 +90,9 @@ def test_grid_latitude_coordinate(self): actual = result.coord("grid_latitude") self.assertEqual(actual, expected) - print("two end") def test_grid_longitude_coordinate(self): """Check expected grid longitude.""" - print("three") expected = self.tgt.coord("grid_longitude") regridder = self.scheme.regridder(self.src, self.tgt) @@ -110,7 +103,6 @@ def test_grid_longitude_coordinate(self): def test_data(self): """Check data payload.""" - print("four") source_areas = iris.analysis.cartography.area_weights(self.src) expected = self.src.collapsed( ["latitude", "longitude"], iris.analysis.MEAN, weights=source_areas @@ -130,7 +122,6 @@ def test_data(self): def test_alt_mapping(self): # Ensure that the ordering of the coordinates has no impact on the # results. - print("five") input_cube = self.src.copy() input_cube.rename("input_cube") @@ -142,7 +133,6 @@ def test_alt_mapping(self): regridder(input_cube) def test_attributes_persisting(self): - print("six") # Certain atttributes from the source should persist to the target # cube. self.src.attributes = {"grid_staggering": 3, "valid_min": 0} @@ -157,17 +147,11 @@ def test_ants_set_crs_called(self): # fixed where possible and also ANTS crs equivalence is utilised. # # src, tgt and input cube should call this. - print("seven") new_src = self.src.copy() - print("seven1") new_src.rename("new_source") - print("seven2") with mock.patch("ants.utils.cube.set_crs") as patch_set_crs: - print("seven2.1") regridder = self.scheme.regridder(self.src, self.tgt) - print("seven2.2") regridder(new_src) - print("seven3") mock.call(self.src) in patch_set_crs.call_args_list mock.call(self.tgt) in patch_set_crs.call_args_list mock.call(new_src) in patch_set_crs.call_args_list @@ -181,7 +165,6 @@ def test_values_beyond_extent(self): # values). Instead this captures the behaviour that is coded # right now. This current behaviour is that 'extrapolated points' # result in values of ~0. - print("eight") src_cube = ants.tests.stock.geodetic((4, 5), xlim=[0, 180]) src_cube.data = src_cube.data + 10 src_cube.data = src_cube.data.astype("float64") @@ -192,7 +175,6 @@ def test_values_beyond_extent(self): self.assertTrue((result.data == 0).sum() > 0) def test_masked_data(self): - print("nine") self.src.data = np.ma.array(self.src.data) self.src.data[0] = np.ma.masked tgt_cube = ants.tests.stock.geodetic((32, 32)) @@ -208,7 +190,6 @@ def test_masked_data(self): def test_result_dtype_always_64bit(self): # Ensure that the resulting dtype is independent of properties of # either source or target. - print("ten") self.src.data = self.src.data.astype("int32") coords = [ self.src.coord(axis="x"), @@ -230,7 +211,6 @@ def test_result_dtype_always_64bit(self): self.assertEqual(result.coord(axis="y").bounds.dtype, np.dtype("int32")) def broadcasting_check(self, coords, dims): - print("eleven") data = np.arange(20).reshape((4, 5))[None] data = np.repeat(data, 6, 0).reshape((2, 3, 4, 5)) src_cube = ants.tests.stock.geodetic((2, 3, 4, 5), data=data) @@ -258,7 +238,6 @@ def broadcasting_check(self, coords, dims): self.assertArrayAlmostEqual(result.data, target) def test_broadcasting_nd_aux_coords(self): - print("twelve") bing_coord = iris.coords.AuxCoord( np.arange(6).reshape((2, 3)), long_name="bing" ) @@ -268,14 +247,12 @@ def test_broadcasting_nd_aux_coords(self): self.broadcasting_check([bing_coord, flop_coord], [(0, 1), (0, 1)]) def test_broadcasting_nd_aux_coord(self): - print("thirteen") bing_coord = iris.coords.AuxCoord( np.arange(6).reshape((2, 3)), long_name="bing" ) self.broadcasting_check([bing_coord], [(0, 1)]) def test_broadcasting_1d_aux_coords(self): - print("fourteen") bing_coord = iris.coords.AuxCoord(np.arange(2), long_name="bing") flop_coord = iris.coords.AuxCoord(np.arange(3), long_name="flop") self.broadcasting_check([bing_coord, flop_coord], [(0,), (1,)]) @@ -283,7 +260,6 @@ def test_broadcasting_1d_aux_coords(self): def test_input_cube_different_to_source_cube(self): # Ensure that an exception is raised where the grid used to derive the # weights is not identical to the input provided for regridding. - print("fifteen") new_src = self.src.copy() new_src.rename("new_source") coord = new_src.coord(axis="x") @@ -297,7 +273,6 @@ def test_input_cube_different_to_source_cube(self): regridder(new_src) def test_src_cube_additional_coords(self): - print("sixteen") # Ensure we raise an exception in the case where the source cube has # additional coordinates mapped to the same dimensions as the # horizontal grid. @@ -311,7 +286,6 @@ def test_inp_cube_additional_coords(self): # Ensure we raise an exception in the case where the input cube has # additional coordinates mapped to the same dimensions as the # horizontal grid. - print("seventeen") new_src = self.src.copy() msg = r"Additional coordinate\(s\) vary along the horizontal mapping." bing_coord = iris.coords.AuxCoord(np.arange(4), long_name="bing") @@ -324,7 +298,6 @@ def test_inp_cube_additional_coords(self): @ants.tests.skip_esmpy class Test_cache(Common1D, ants.tests.TestCase): def test_values(self): - print("eighteen") src = self.src tgt = self.tgt regridder = self.scheme.regridder(src, tgt) @@ -348,7 +321,6 @@ def test_values(self): def test_values_using_sparse_arrays(self): # Check usage with sparse arrays. - print("nineteen") src = self.src tgt = self.tgt regridder = self.scheme.regridder(src, tgt) @@ -366,7 +338,6 @@ def test_values_using_sparse_arrays(self): self.assertArrayAlmostEqual(result.data, target.data) def test_cache_cleanup(self): - print("twenty") regridder = self.scheme.regridder(self.src, self.tgt) cache_file = regridder._cache_fnme self.assertTrue(os.path.isfile(cache_file)) @@ -375,7 +346,6 @@ def test_cache_cleanup(self): def test_cache_persistence(self): # Ensure that the file remains after getting rid of the regridder. - print("twenty one") regridder = self.scheme.regridder(self.src, self.tgt, persistent_cache=True) cache_file = regridder._cache_fnme self.assertTrue(os.path.isfile(cache_file)) @@ -386,7 +356,6 @@ def test_cache_persistence(self): def test_cache_persistence_regridder_usage(self): # Ensure that ESMF can successfully generate the same results when # utilising this cache to instantiate a regridder. - print("twenty two") regridder = self.scheme.regridder(self.src, self.tgt, persistent_cache=True) res1 = regridder(self.src) del regridder @@ -397,7 +366,6 @@ def test_cache_persistence_regridder_usage(self): def test_cache_persistance_regridder_readfromfile(self): # Ensure that we are requesting that ESMF read the cache from disk for # instantiating its regridder in the case of persistent cache usage. - print("twenty three") regridder = self.scheme.regridder(self.src, self.tgt, persistent_cache=True) with mock.patch("esmpy.api.regrid.RegridFromFile") as cache_regrid: del regridder @@ -407,7 +375,6 @@ def test_cache_persistance_regridder_readfromfile(self): class CommonND(object): def test_alt_mapping(self): - print("twenty four") input_cube = self.src.copy() input_cube.rename("input_cube") @@ -422,7 +389,6 @@ def test_alt_mapping(self): @ants.tests.skip_esmpy class Test_regridder_1D_source_2D_target(CommonND, ants.tests.TestCase): def setUp(self): - print("twenty five - setup") self.src = ants.tests.stock.geodetic((2, 3)) crs = iris.coord_systems.RotatedGeogCS(20, 10) @@ -432,7 +398,6 @@ def setUp(self): def test_latitude_coordinate(self): """Check expected latitude.""" - print("twenty six") expected = self.tgt.coord("latitude") regridder = self.scheme.regridder(self.src, self.tgt) @@ -443,7 +408,6 @@ def test_latitude_coordinate(self): def test_longitude_coordinate(self): """Check expected longitude.""" - print("twenty seven") expected = self.tgt.coord("longitude") regridder = self.scheme.regridder(self.src, self.tgt) @@ -454,7 +418,6 @@ def test_longitude_coordinate(self): def test_data(self): """Check data payload.""" - print("twenty eight") expected = np.array( [ [1.43261933, 2.35197492, 1.07919774, 0.0], diff --git a/lib/ants/tests/utils/cube/test_inherit_metadata.py b/lib/ants/tests/utils/cube/test_inherit_metadata.py index 410b027..82cc5d1 100644 --- a/lib/ants/tests/utils/cube/test_inherit_metadata.py +++ b/lib/ants/tests/utils/cube/test_inherit_metadata.py @@ -16,7 +16,7 @@ def testall(self): target.units = mock.sentinel.units target.attributes["grid_staggering"] = mock.sentinel.grid_staggering inherit_metadata(source, target) - # source.rename.assert_called_once_with(mock.sentinel.name) + source.rename.assert_called_once_with(mock.sentinel.name) self.assertIs(source.units, target.units) self.assertIs( source.attributes["grid_staggering"], target.attributes["grid_staggering"] diff --git a/lib/ants/utils/_dask.py b/lib/ants/utils/_dask.py index e55384c..60f153c 100644 --- a/lib/ants/utils/_dask.py +++ b/lib/ants/utils/_dask.py @@ -66,9 +66,6 @@ def as_lazy_data(data, chunks=None, asarray=False): This is for ants core library usage ONLY! """ - print("data:", data) - print("chunks: ", chunks) - print("asarray: ", asarray) meta = np.empty(data.shape, data.dtype) return iris._lazy_data.as_lazy_data(data, chunks=chunks, asarray=asarray, meta=meta) diff --git a/rose-stem/flow.cylc b/rose-stem/flow.cylc index 5b9bff3..dd33f1d 100644 --- a/rose-stem/flow.cylc +++ b/rose-stem/flow.cylc @@ -1,5 +1,5 @@ #!jinja2 -{% set ANTS_MODULE = "ants/new-env" %} +{% set ANTS_MODULE = "ants/developer-68" %} {% set PYTHONPATH_PREPEND = "$CYLC_WORKFLOW_RUN_DIR/share/fcm_make_ants/build/lib" %} {% set fill_n_merge_source = ['land_cover', 'invert_mask'] %} From 79df01e63a2ec1dd523d4ee76af5b3e8584eb65c Mon Sep 17 00:00:00 2001 From: Theo Geddes Date: Tue, 25 Aug 2026 11:46:40 +0100 Subject: [PATCH 8/9] #68: Revert failing test --- lib/ants/tests/command_parse/test_integration.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/lib/ants/tests/command_parse/test_integration.py b/lib/ants/tests/command_parse/test_integration.py index 2a6b49d..0662499 100644 --- a/lib/ants/tests/command_parse/test_integration.py +++ b/lib/ants/tests/command_parse/test_integration.py @@ -95,19 +95,14 @@ def test_no_lbm(self): args = parser.parse_args() self.assertIs(args.ants_config, None) - """ def test_missing_lbm(self): new = ["program", "/path/to/source", "-o", "/path/to/output"] - with mock.patch("sys.argv", new=new) as argv: + with mock.patch("sys.argv", new=new): with mock.patch("sys.exit") as sys_exit: - #with mock.patch("sys.stderr") as err: - parser = AntsArgParser(target_lsm=True) - parser.parse_args() - print("argv: ", argv) - #print("err: ", err.call_args_list) - print(sys_exit.call_args_list) + with mock.patch("sys.stderr"): + parser = AntsArgParser(target_lsm=True) + parser.parse_args() sys_exit.assert_called_once_with(2) - """ def test_configuration_parse(self): config_path = "/path/to/config/file" From bfa0121a29109bcc4104cb235b92c03d685ea80a Mon Sep 17 00:00:00 2001 From: Theo Geddes Date: Wed, 2 Sep 2026 10:04:44 +0100 Subject: [PATCH 9/9] Update lib/ants/fileformats/raster.py Co-authored-by: Josh Rackham <144251043+jrackham-mo@users.noreply.github.com> Signed-off-by: Theo Geddes --- lib/ants/fileformats/raster.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/ants/fileformats/raster.py b/lib/ants/fileformats/raster.py index 8f3dd24..a628324 100644 --- a/lib/ants/fileformats/raster.py +++ b/lib/ants/fileformats/raster.py @@ -71,9 +71,10 @@ def __init__(self, shape, dtype, path, raster_band_index, fill_value): dtype = np.dtype("int32") elif (dtype.name) == "uint32": dtype = np.dtype("int64") - else: + elif (dtype.name) == "uint64": dtype = np.dtype("int128") - + else: + raise TypeError(f"Cannot cast {dtype.name} from unsigned to signed int") self.dtype = dtype self.path = path self.raster_band_index = raster_band_index