Skip to content

Commit

Permalink
fix merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhassell committed Feb 29, 2024
2 parents 136ba10 + d63b11b commit 1022a78
Show file tree
Hide file tree
Showing 22 changed files with 215 additions and 32 deletions.
6 changes: 4 additions & 2 deletions Changelog.rst
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
version 3.17.0
version 3.16.1
--------------

**2024-??-??**
**2024-03-01**

* Allow DSG tractories with identical `trajectory_id` values to be
aggregated (https://github.com/NCAS-CMS/cf-python/issues/723)
* New methods: `cf.Field.pad_missing` and `cf.Data.pad_missing`
(https://github.com/NCAS-CMS/cf-python/issues/717)
* Fix occasional bug when calculating UGRID cell areas when
Expand Down
2 changes: 1 addition & 1 deletion DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
sphinx-copybutton==0.5.1
sphinx-toggleprompt==0.2.0
sphinxcontrib-spelling==4.3.0
serializinghtml-serializinghtml==1.1.5
sphinxcontrib.serializinghtml==1.1.5
sphinx==2.4.5
* The `.py` files to generate recipes are stored in `docs/source/recipes/`.
Expand Down
4 changes: 2 additions & 2 deletions cf/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@
"""

__Conventions__ = "CF-1.11"
__date__ = "2023-12-06"
__version__ = "3.16.0"
__date__ = "2023-03-01"
__version__ = "3.16.1"

_requires = (
"numpy",
Expand Down
98 changes: 94 additions & 4 deletions cf/aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"add_offset",
"calendar",
"cell_methods",
"featureType",
"_FillValue",
"flag_masks",
"flag_meanings",
Expand Down Expand Up @@ -210,6 +211,7 @@ class _Meta:
(
"Type",
"Identity",
"featureType",
"Units",
"Cell_methods",
"Data",
Expand Down Expand Up @@ -389,6 +391,10 @@ def __init__(
if field_identity:
self.identity = f.get_property(field_identity, None)

# Set the DSG featureType
featureType = f.get_property("featureType", None)
self.featureType = featureType

construct_axes = f.constructs.data_axes()

# ------------------------------------------------------------
Expand Down Expand Up @@ -502,6 +508,7 @@ def __init__(
"identity": dim_identity,
"key": dim_coord_key,
"units": units,
"cf_role": None,
"hasdata": dim_coord.has_data(),
"hasbounds": hasbounds,
"coordrefs": self.find_coordrefs(axis),
Expand Down Expand Up @@ -539,11 +546,18 @@ def __init__(
aux_coord, aux_identity, relaxed_units=relaxed_units
)

# Set the cf_role for DSGs
if not featureType:
cf_role = None
else:
cf_role = aux_coord.get_property("cf_role", None)

info_aux.append(
{
"identity": aux_identity,
"key": key,
"units": units,
"cf_role": cf_role,
"hasdata": aux_coord.has_data(),
"hasbounds": aux_coord.has_bounds(),
"coordrefs": self.find_coordrefs(key),
Expand Down Expand Up @@ -586,12 +600,14 @@ def __init__(

return

identity = f"ncvar%{identity}"
size = domain_axis.get_size()

axis_identities = {
"ids": "identity",
"keys": "key",
"units": "units",
"cf_role": "cf_role",
"hasdata": "hasdata",
"hasbounds": "hasbounds",
"coordrefs": "coordrefs",
Expand Down Expand Up @@ -1773,6 +1789,9 @@ def structural_signature(self):
Cell_methods = self.cell_methods
Data = self.has_field_data

# DSG FeatureType
featureType = self.featureType

# Properties
Properties = self.properties

Expand Down Expand Up @@ -1812,6 +1831,7 @@ def structural_signature(self):
]
),
),
("cf_role", axis[identity]["cf_role"]),
("hasdata", axis[identity]["hasdata"]),
("hasbounds", axis[identity]["hasbounds"]),
("coordrefs", axis[identity]["coordrefs"]),
Expand Down Expand Up @@ -1918,6 +1938,7 @@ def structural_signature(self):
self.signature = self._structural_signature(
Type=Type,
Identity=Identity,
featureType=featureType,
Units=Units,
Cell_methods=Cell_methods,
Data=Data,
Expand Down Expand Up @@ -4147,6 +4168,15 @@ def _hash_values(m):

hash0 = hash1

# If 'count' is 0 then all of the 1-d coordinates have the
# same values across fields. However, for a DSG featureType
# axis we can still aggregate it, because it's OK to aggregate
# featureTypes with the timeseries_id, profile_id, or
# trajectory_id.
if not count and dsg_feature_type_axis(m0, axis):
a_identity = axis
count = 1

if count == 1:
# --------------------------------------------------------
# Exactly one axis has different 1-d coordinate values
Expand Down Expand Up @@ -4248,10 +4278,22 @@ def _hash_values(m):
# aggregate anything in this entire group.
# --------------------------------------------------------
if info:
meta[
0
].message = (
"Some fields have identical sets of 1-d coordinates."
coord_ids = []
for k, v in m0.axis.items():
coord_ids.extend([repr(i) for i in v["ids"]])

if len(coord_ids) > 1:
coord_ids = (
f"{', '.join(coord_ids[:-1])} and {coord_ids[-1]}"
)
elif coord_ids:
coord_ids = coord_ids[0]
else:
coord_ids = ""

meta[0].message = (
f"Some fields have identical sets of 1-d {coord_ids} "
"coordinates."
)

return ()
Expand Down Expand Up @@ -4839,6 +4881,19 @@ def _aggregate_2_fields(


def f_identity(meta):
"""Return the field identity for logging strings.
:Parameters:
meta: `_Meta`
The `_Meta` instance containing the field.
:Returns:
`str`
The identity.
"""
identity = meta.identity
f_identity = meta.field.identity()
if f_identity == identity:
Expand All @@ -4847,3 +4902,38 @@ def f_identity(meta):
identity = f"{meta.identity!r} ({f_identity})"

return identity


def dsg_feature_type_axis(meta, axis):
"""True if the given axis is a DSG featureType axis.
A DSG featureType axis has no dimension coordinates and at least
one 1-d auxiliary coordinate with a ``cf-role`` property.
:Parameters:
meta: `_Meta`
The `_Meta` instance
axis: `str`
One of the axes in ``meta.axis_ids``.
:Returns:
`bool`
`True` if the given axis is a DSG featureType axis.
"""
if not meta.featureType:
# The field/domain is not a DSG
return False

coords = meta.axis[axis]
if coords["dim_coord_index"] is not None:
# The axis has dimension coordinates
return False

# Return True if one of the 1-d auxiliary coordinates has a
# cf_role property
cf_role = coords["cf_role"]
return cf_role.count(None) != len(cf_role)
26 changes: 13 additions & 13 deletions cf/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -2385,27 +2385,27 @@ def cell_area(
constructs are considered for cell area
creation. Otherwise they are ignored.

.. versionadded:: 3.17.0
.. versionadded:: 3.16.1

coordinates: `bool`, optional
If True, the default, then coordinate constructs are
considered for cell area creation. Otherwise they are
ignored.

.. versionadded:: 3.17.0
.. versionadded:: 3.16.1

methods: `bool`, optional
If True, then return a dictionary describing the method
used to create the cell areas instead of the default,
a field construct.

.. versionadded:: 3.17.0
.. versionadded:: 3.16.1

return_cell_measure: `bool`, optional
If True, then return a cell measure construct instead
of the default, a field construct.

.. versionadded:: 3.17.0
.. versionadded:: 3.16.1

insert: deprecated at version 3.0.0

Expand Down Expand Up @@ -3507,15 +3507,15 @@ def weights(
``'volume'``. If False then cell measure constructs
are ignored for these *weights*.

.. versionadded:: 3.17.0
.. versionadded:: 3.16.1

coordinates: `bool`, optional
If True, the default, then coordinate constructs are
considered for weights creation for *weights* of
`True` or ``'area'``. If False then coordinate
constructs are ignored for these *weights*.

.. versionadded:: 3.17.0
.. versionadded:: 3.16.1

kwargs: deprecated at version 3.0.0.

Expand Down Expand Up @@ -8719,7 +8719,7 @@ def insert_dimension(
metadata constructs that don't already include it. By
default, metadata constructs are not changed.

.. versionadded:: 3.17.0
.. versionadded:: 3.16.1

{{inplace: `bool`, optional}}

Expand Down Expand Up @@ -11960,7 +11960,7 @@ def pad_missing(self, axis, pad_width=None, to_size=None, inplace=False):
The field's data and all metadata constructs that span the
axis are padded.

.. versionadded:: 3.17.0
.. versionadded:: 3.16.1

:Parameters:

Expand All @@ -11978,13 +11978,13 @@ def pad_missing(self, axis, pad_width=None, to_size=None, inplace=False):

{{inplace: `bool`, optional}}

:Returns:
:Returns:

`Field` or `None`
The padded field construct, or `None` if the operation
was in-place.
`Field` or `None`
The padded field construct, or `None` if the operation
was in-place.

**Examples*
**Examples**

>>> f = cf.example_field(6)
>>> print(f)
Expand Down
6 changes: 6 additions & 0 deletions cf/regrid/regrid.py
Original file line number Diff line number Diff line change
Expand Up @@ -1707,6 +1707,12 @@ def create_esmpy_mesh(grid, mask=None):
node_count = node_ids.size
node_owners = np.zeros(node_count)

# Make sure that node IDs are >= 1, as needed by newer versions of
# esmpy
min_id = node_ids.min()
if min_id < 1:
node_ids += min_id + 1

# Add nodes. This must be done before `add_elements`.
esmpy_mesh.add_nodes(
node_count=node_count,
Expand Down
15 changes: 15 additions & 0 deletions cf/test/test_aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,21 @@ def test_aggregate_ugrid(self):
d += 0.1
self.assertEqual(len(cf.aggregate([f, g])), 2)

def test_aggregate_trajectory(self):
"""Test DSG trajectory aggregation"""
# Test that aggregation occurs when the tractory_id axes have
# identical 1-d auxiliary coordinates
f = cf.example_field(11)
g = cf.aggregate([f, f], relaxed_identities=True)
self.assertEqual(len(g), 1)

g = g[0]
self.assertTrue(
g.subspace(**{"cf_role=trajectory_id": [0]}).equals(
g.subspace(**{"cf_role=trajectory_id": [1]})
)
)


if __name__ == "__main__":
print("Run date:", datetime.datetime.now())
Expand Down
1 change: 1 addition & 0 deletions docs/source/class/cf.AuxiliaryCoordinate.rst
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ Data
:template: method.rst

~cf.AuxiliaryCoordinate.halo
~cf.AuxiliaryCoordinate.pad_missing

.. rubric:: *Data array mask*

Expand Down
11 changes: 10 additions & 1 deletion docs/source/class/cf.Bounds.rst
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,16 @@ Data
~cf.Bounds.swapaxes
~cf.Bounds.transpose

.. rubric:: *Expanding the data*

.. autosummary::
:nosignatures:
:toctree: ../method/
:template: method.rst

~cf.Bounds.halo
~cf.Bounds.pad_missing

.. rubric:: *Data array mask*

.. autosummary::
Expand Down Expand Up @@ -205,7 +215,6 @@ Data
:template: method.rst

~cf.Bounds.__setitem__
~cf.Bounds.halo
~cf.Bounds.masked_invalid
~cf.Bounds.subspace
~cf.Bounds.where
Expand Down
Loading

0 comments on commit 1022a78

Please sign in to comment.