Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate the function esmvalcore.var_name_constraint #1592

Merged
merged 1 commit into from
May 19, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/api/esmvalcore.iris_helpers.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Iris helper functions
=====================

.. automodule:: esmvalcore.iris_helpers
1 change: 1 addition & 0 deletions doc/api/esmvalcore.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ library. This section documents the public API of ESMValCore.
esmvalcore.cmor
esmvalcore.esgf
esmvalcore.exceptions
esmvalcore.iris_helpers
esmvalcore.preprocessor
esmvalcore.api
2 changes: 2 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,8 @@

# Configuration for intersphinx
intersphinx_mapping = {
'cf_units': ('https://cf-units.readthedocs.io/en/latest/', None),
'cftime': ('https://unidata.github.io/cftime/', None),
'esmvalcore':
(f'https://docs.esmvaltool.org/projects/esmvalcore/en/{rtd_version}/',
None),
Expand Down
7 changes: 3 additions & 4 deletions esmvalcore/cmor/_fixes/shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@
import iris
import pandas as pd
from cf_units import Unit
from iris import NameConstraint
from scipy.interpolate import interp1d

from esmvalcore.iris_helpers import var_name_constraint

logger = logging.getLogger(__name__)


Expand All @@ -36,7 +35,7 @@ def add_aux_coords_from_cubes(cube, cubes, coord_dict):
it.
"""
for (coord_name, coord_dims) in coord_dict.items():
coord_cube = cubes.extract(var_name_constraint(coord_name))
coord_cube = cubes.extract(NameConstraint(var_name=coord_name))
if len(coord_cube) != 1:
raise ValueError(
f"Expected exactly one coordinate cube '{coord_name}' in "
Expand Down Expand Up @@ -247,7 +246,7 @@ def get_bounds_cube(cubes, coord_var_name):
"""
for bounds in ('bnds', 'bounds'):
bound_var = f'{coord_var_name}_{bounds}'
cube = cubes.extract(var_name_constraint(bound_var))
cube = cubes.extract(NameConstraint(var_name=bound_var))
if len(cube) == 1:
return cube[0]
if len(cube) > 1:
Expand Down
41 changes: 36 additions & 5 deletions esmvalcore/iris_helpers.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
"""Auxiliary functions for :mod:`iris`."""
import iris
import warnings

import numpy as np
from iris import NameConstraint

from esmvalcore.exceptions import ESMValCoreDeprecationWarning


def date2num(date, unit, dtype=np.float64):
"""Convert datetime object into numeric value with requested dtype.

This is a custom version of :func:`cf_units.Unit.date2num` that
This is a custom version of :meth:`cf_units.Unit.date2num` that
guarantees the correct dtype for the return value.

Arguments
Expand All @@ -18,7 +22,7 @@ def date2num(date, unit, dtype=np.float64):
Returns
-------
:class:`numpy.ndarray` of type `dtype`
the return value of `unit.date2num` with the requested dtype
The return value of ``unit.date2num`` with the requested dtype.
"""
num = unit.date2num(date)
try:
Expand All @@ -28,5 +32,32 @@ def date2num(date, unit, dtype=np.float64):


def var_name_constraint(var_name):
""":mod:`iris.Constraint` using `var_name` of a :mod:`iris.cube.Cube`."""
return iris.Constraint(cube_func=lambda c: c.var_name == var_name)
""":class:`iris.Constraint` using ``var_name``.

Warning
-------
.. deprecated:: 2.6.0
This function has been deprecated in ESMValCore version 2.6.0 and is
scheduled for removal in version 2.8.0. Please use the function
:class:`iris.NameConstraint` with the argument ``var_name`` instead:
this is an exact replacement.

Parameters
----------
var_name: str
``var_name`` used for the constraint.

Returns
-------
iris.Constraint
Constraint.

"""
deprecation_msg = (
"The function ``var_name_constraint`` has been deprecated in "
"ESMValCore version 2.6.0 and is scheduled for removal in version "
"2.8.0. Please use the function ``iris.NameConstraint`` with the "
"argument ``var_name`` instead: this is an exact replacement."
)
warnings.warn(deprecation_msg, ESMValCoreDeprecationWarning)
return NameConstraint(var_name=var_name)
5 changes: 2 additions & 3 deletions esmvalcore/preprocessor/_derive/_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@

import iris
import numpy as np
from iris import NameConstraint
from scipy import constants

from esmvalcore.iris_helpers import var_name_constraint

logger = logging.getLogger(__name__)


def cloud_area_fraction(cubes, tau_constraint, plev_constraint):
"""Calculate cloud area fraction for different parameters."""
clisccp_cube = cubes.extract_cube(var_name_constraint('clisccp'))
clisccp_cube = cubes.extract_cube(NameConstraint(var_name='clisccp'))
new_cube = clisccp_cube
new_cube = new_cube.extract(tau_constraint & plev_constraint)
coord_names = [
Expand Down
7 changes: 3 additions & 4 deletions esmvalcore/preprocessor/_derive/alb.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
- crez_ba

"""

from esmvalcore.iris_helpers import var_name_constraint
from iris import NameConstraint

from ._baseclass import DerivedVariableBase

Expand All @@ -29,8 +28,8 @@ def required(project):
@staticmethod
def calculate(cubes):
"""Compute surface albedo."""
rsdscs_cube = cubes.extract_cube(var_name_constraint('rsdscs'))
rsuscs_cube = cubes.extract_cube(var_name_constraint('rsuscs'))
rsdscs_cube = cubes.extract_cube(NameConstraint(var_name='rsdscs'))
rsuscs_cube = cubes.extract_cube(NameConstraint(var_name='rsuscs'))

rsnscs_cube = rsuscs_cube / rsdscs_cube

Expand Down
8 changes: 4 additions & 4 deletions esmvalcore/preprocessor/_derive/lvp.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

"""

from esmvalcore.iris_helpers import var_name_constraint
from iris import NameConstraint

from ._baseclass import DerivedVariableBase

Expand All @@ -32,9 +32,9 @@ def required(project):
@staticmethod
def calculate(cubes):
"""Compute Latent Heat Release from Precipitation."""
hfls_cube = cubes.extract_cube(var_name_constraint('hfls'))
pr_cube = cubes.extract_cube(var_name_constraint('pr'))
evspsbl_cube = cubes.extract_cube(var_name_constraint('evspsbl'))
hfls_cube = cubes.extract_cube(NameConstraint(var_name='hfls'))
pr_cube = cubes.extract_cube(NameConstraint(var_name='pr'))
evspsbl_cube = cubes.extract_cube(NameConstraint(var_name='evspsbl'))

lvp_cube = hfls_cube * (pr_cube / evspsbl_cube)

Expand Down
6 changes: 3 additions & 3 deletions esmvalcore/preprocessor/_derive/lwp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import logging

from esmvalcore.iris_helpers import var_name_constraint
from iris import NameConstraint

from ._baseclass import DerivedVariableBase

Expand Down Expand Up @@ -37,8 +37,8 @@ def calculate(cubes):
"""
# CMIP5 and CMIP6 names are slightly different, so use
# variable name instead to extract cubes
clwvi_cube = cubes.extract_cube(var_name_constraint('clwvi'))
clivi_cube = cubes.extract_cube(var_name_constraint('clivi'))
clwvi_cube = cubes.extract_cube(NameConstraint(var_name='clwvi'))
clivi_cube = cubes.extract_cube(NameConstraint(var_name='clivi'))

# CMIP5 and CMIP6 have different global attributes that we use
# to determine model name and project name:
Expand Down
5 changes: 2 additions & 3 deletions esmvalcore/preprocessor/_derive/sm.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import cf_units
import numpy as np

from esmvalcore.iris_helpers import var_name_constraint
from iris import NameConstraint

from ._baseclass import DerivedVariableBase

Expand All @@ -28,7 +27,7 @@ def calculate(cubes):
20 deg C).

"""
mrsos_cube = cubes.extract_cube(var_name_constraint('mrsos'))
mrsos_cube = cubes.extract_cube(NameConstraint(var_name='mrsos'))

depth = mrsos_cube.coord('depth').bounds.astype(np.float32)
layer_thickness = depth[..., 1] - depth[..., 0]
Expand Down
13 changes: 6 additions & 7 deletions esmvalcore/preprocessor/_derive/vegfrac.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

import dask.array as da
import iris
from esmvalcore.iris_helpers import var_name_constraint
from iris import NameConstraint

from .._regrid import regrid

from ._baseclass import DerivedVariableBase


Expand All @@ -25,11 +24,11 @@ def required(project):
@staticmethod
def calculate(cubes):
"""Compute vegetation fraction from bare soil fraction."""
baresoilfrac_cube = cubes.extract_cube(var_name_constraint(
'baresoilFrac'))
residualfrac_cube = cubes.extract_cube(var_name_constraint(
'residualFrac'))
sftlf_cube = cubes.extract_cube(var_name_constraint('sftlf'))
baresoilfrac_cube = cubes.extract_cube(NameConstraint(
var_name='baresoilFrac'))
residualfrac_cube = cubes.extract_cube(NameConstraint(
var_name='residualFrac'))
sftlf_cube = cubes.extract_cube(NameConstraint(var_name='sftlf'))

# Add time dimension to sftlf
target_shape_sftlf = (baresoilfrac_cube.shape[0], *sftlf_cube.shape)
Expand Down
10 changes: 5 additions & 5 deletions tests/integration/cmor/_fixes/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import numpy as np
import pytest
from cf_units import Unit
from iris import NameConstraint

from esmvalcore.cmor._fixes.common import (
ClFixHybridHeightCoord,
Expand All @@ -11,7 +12,6 @@
SiconcFixScalarCoord,
)
from esmvalcore.cmor.table import get_var_info
from esmvalcore.iris_helpers import var_name_constraint

AIR_PRESSURE_POINTS = np.array([[[[1.0, 1.0, 1.0, 1.0],
[1.0, 1.0, 1.0, 1.0],
Expand Down Expand Up @@ -57,7 +57,7 @@ def hybrid_pressure_coord_fix_metadata(nc_path, short_name, fix):
assert 'b_bnds' in var_names

# Raw cube
cube = cubes.extract_cube(var_name_constraint(short_name))
cube = cubes.extract_cube(NameConstraint(var_name=short_name))
air_pressure_coord = cube.coord('air_pressure')
assert air_pressure_coord.points is not None
assert air_pressure_coord.bounds is None
Expand All @@ -70,7 +70,7 @@ def hybrid_pressure_coord_fix_metadata(nc_path, short_name, fix):
# Apply fix
fixed_cubes = fix.fix_metadata(cubes)
assert len(fixed_cubes) == 1
fixed_cube = fixed_cubes.extract_cube(var_name_constraint(short_name))
fixed_cube = fixed_cubes.extract_cube(NameConstraint(var_name=short_name))
fixed_air_pressure_coord = fixed_cube.coord('air_pressure')
assert fixed_air_pressure_coord.points is not None
assert fixed_air_pressure_coord.bounds is not None
Expand Down Expand Up @@ -134,7 +134,7 @@ def hybrid_height_coord_fix_metadata(nc_path, short_name, fix):
assert 'b_bnds' in var_names

# Raw cube
cube = cubes.extract_cube(var_name_constraint(short_name))
cube = cubes.extract_cube(NameConstraint(var_name=short_name))
height_coord = cube.coord('altitude')
assert height_coord.points is not None
assert height_coord.bounds is not None
Expand All @@ -146,7 +146,7 @@ def hybrid_height_coord_fix_metadata(nc_path, short_name, fix):
# Apply fix
fixed_cubes = fix.fix_metadata(cubes)
assert len(fixed_cubes) == 1
fixed_cube = fixed_cubes.extract_cube(var_name_constraint(short_name))
fixed_cube = fixed_cubes.extract_cube(NameConstraint(var_name=short_name))
fixed_height_coord = fixed_cube.coord('altitude')
assert fixed_height_coord.points is not None
assert fixed_height_coord.bounds is not None
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/cmor/_fixes/test_shared.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import numpy as np
import pytest
from cf_units import Unit
from iris import NameConstraint

from esmvalcore.cmor._fixes.shared import (
add_altitude_from_plev,
Expand All @@ -23,7 +24,6 @@
get_pressure_to_altitude_func,
round_coordinates,
)
from esmvalcore.iris_helpers import var_name_constraint


@pytest.mark.sequential
Expand Down Expand Up @@ -92,7 +92,7 @@ def test_add_aux_coords_from_cubes(coord_dict, output):
assert cube.coord_dims(coord) == coord_dims
points = np.full(coord.shape, 0.0)
assert coord.points == points
assert not cubes.extract(var_name_constraint(coord_name))
assert not cubes.extract(NameConstraint(var_name=coord_name))
assert len(cubes) == 5 - len(coord_dict)
return
with pytest.raises(ValueError) as err:
Expand Down
23 changes: 17 additions & 6 deletions tests/unit/test_iris_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import pytest
from cf_units import Unit

from esmvalcore.exceptions import ESMValCoreDeprecationWarning
from esmvalcore.iris_helpers import date2num, var_name_constraint


Expand Down Expand Up @@ -38,20 +39,30 @@ def test_date2num_scalar(date, dtype, expected, units):

def test_var_name_constraint(cubes):
"""Test :func:`esmvalcore.iris_helpers.var_name_constraint`."""
out_cubes = cubes.extract(var_name_constraint('a'))
with pytest.warns(ESMValCoreDeprecationWarning):
out_cubes = cubes.extract(var_name_constraint('a'))
assert out_cubes == iris.cube.CubeList([
iris.cube.Cube(0.0, var_name='a', long_name='a'),
iris.cube.Cube(0.0, var_name='a', long_name='b'),
])
out_cubes = cubes.extract(var_name_constraint('b'))

with pytest.warns(ESMValCoreDeprecationWarning):
out_cubes = cubes.extract(var_name_constraint('b'))
assert out_cubes == iris.cube.CubeList([])
out_cubes = cubes.extract(var_name_constraint('c'))

with pytest.warns(ESMValCoreDeprecationWarning):
out_cubes = cubes.extract(var_name_constraint('c'))
assert out_cubes == iris.cube.CubeList([
iris.cube.Cube(0.0, var_name='c', long_name='d'),
])

with pytest.raises(iris.exceptions.ConstraintMismatchError):
cubes.extract_cube(var_name_constraint('a'))
with pytest.warns(ESMValCoreDeprecationWarning):
cubes.extract_cube(var_name_constraint('a'))
with pytest.raises(iris.exceptions.ConstraintMismatchError):
cubes.extract_cube(var_name_constraint('b'))
out_cube = cubes.extract_cube(var_name_constraint('c'))
with pytest.warns(ESMValCoreDeprecationWarning):
cubes.extract_cube(var_name_constraint('b'))

with pytest.warns(ESMValCoreDeprecationWarning):
out_cube = cubes.extract_cube(var_name_constraint('c'))
assert out_cube == iris.cube.Cube(0.0, var_name='c', long_name='d')