Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* The former function "iris.analysis.coord_comparison" has been removed.
50 changes: 43 additions & 7 deletions lib/iris/analysis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@
"SUM",
"VARIANCE",
"WPERCENTILE",
"coord_comparison",
"Aggregator",
"WeightedAggregator",
"clear_phenomenon_identity",
Expand Down Expand Up @@ -186,16 +185,53 @@ def matches_any(self, predicate):
return any(self.matches(predicate))


def coord_comparison(*cubes, object_get=None):
def _dimensional_metadata_comparison(*cubes, object_get=None):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pp-mo Awesome! 👍

My only suggestion here, before we commit to this, is questioning the name of this private function (all 30+ characters of it).

I'm just making the explicit point that it can be anything that we want - it's private. I'm all for meaningful, appropriate names, rather than those that are cryptic, abstract or obfuscated, but now is probably the time to suggest shorter alternatives? It is a bit of a mouthful, right? 😮

Any suggestions? Can I start the bun-fight with simply _metadata_compare?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bjlittle questioning the name of this private function

We just missed the boat on this.

I get the point, but I couldn't think of anything more concise and still clear.
Probably the term DimensionalMetadata is at fault here, also being a bit of a mouthful.

I guess we could have _dm_comparison.
Do you want to propose a post-fix in separate issue ?

Copy link
Member

@bjlittle bjlittle Nov 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pp-mo @stephenworsley No worries. Naming a thing is the hardest part, strangely.

I recently asked @lbdreyer for an alternative name to _DimensionalMetadata.... but we came up blank 😕

This isn't a high priority, by any means, just wanted to raise it as an obvious point to consider. We can stick with what we've got, and change at a later date in a follow-up PR, if we have an epiphany 💡 with agreement

"""
Convenience function to help compare coordinates on one or more cubes
by their metadata.
Convenience function to help compare coordinates, cell-measures or
ancillary-variables, on one or more cubes, by their metadata.

Return a dictionary where the key represents the statement,
.. Note::

Up to Iris 2.x, this _used_ to be the public API method
"iris.analysis.coord_comparison".
It has since been generalised, and made private.
However, the cube elements handled are still mostly referred to as 'coords' /
'coordinates' throughout, for simplicity : In fact, they will all be either
`iris.coords.Coord`, `iris.coords.CellMeasure` or
`iris.coords.AncillaryVariable`, the cube element type being controlled by the
'object_get' keyword.

Args:

* cubes (iterable of `iris.cube.Cube`):
a set of cubes whose coordinates, cell-measures or ancillary-variables are to
be compared.

Kwargs:

* object_get (callable(cube) or None):
If not None, this must be a cube method returning a list of all cube elements
of the required type, i.e. one of `iris.cube.Cube.coords`,
`iris.cube.Cube.cell_measures`, or `iris.cube.Cube.ancillary_variables`.
If not specified, defaults to `iris.cube.Cube.coords`

Returns:

result (dict mapping string: list of _CoordGroup):
A dictionary whose keys are match categories and values are groups of
coordinates, cell-measures or ancillary-variables.

The values of the returned dictionary are lists of _CoordGroup representing
grouped coordinates. Each _CoordGroup contains all the input 'cubes', and a
matching list of the coord within each cube that matches some specific CoordDefn
(or maybe None).

The keys of the returned dictionary are strings naming 'categories' : Each
represents a statement,
"Given these cubes list the coordinates which,
when grouped by metadata, are/have..."

Keys:
Returned Keys:

* grouped_coords
A list of coordinate groups of all the coordinates grouped together
Expand Down Expand Up @@ -236,7 +272,7 @@ def coord_comparison(*cubes, object_get=None):

Example usage::

result = coord_comparison(cube1, cube2)
result = _dimensional_metadata_comparison(cube1, cube2)
print('All equal coordinates: ', result['equal'])

"""
Expand Down
2 changes: 1 addition & 1 deletion lib/iris/analysis/calculus.py
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ def curl(i_cube, j_cube, k_cube=None):
cubes = filter(None, [i_cube, j_cube, k_cube])

# get the names of all coords binned into useful comparison groups
coord_comparison = iris.analysis.coord_comparison(*cubes)
coord_comparison = iris.analysis._dimensional_metadata_comparison(*cubes)

bad_coords = coord_comparison["ungroupable_and_dimensioned"]
if bad_coords:
Expand Down
16 changes: 12 additions & 4 deletions lib/iris/analysis/maths.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ def intersection_of_cubes(cube, other_cube):
if coord.ndim != 1:
raise iris.exceptions.CoordinateMultiDimError(coord)

coord_comp = iris.analysis.coord_comparison(cube, other_cube)
coord_comp = iris.analysis._dimensional_metadata_comparison(
cube, other_cube
)

if coord_comp["ungroupable_and_dimensioned"]:
raise ValueError(
Expand Down Expand Up @@ -338,7 +340,9 @@ def _add_subtract_common(
if isinstance(other, iris.cube.Cube):
# get a coordinate comparison of this cube and the cube to do the
# operation with
coord_comp = iris.analysis.coord_comparison(cube, other)
coord_comp = iris.analysis._dimensional_metadata_comparison(
cube, other
)

bad_coord_grps = (
coord_comp["ungroupable_and_dimensioned"]
Expand Down Expand Up @@ -413,7 +417,9 @@ def multiply(cube, other, dim=None, in_place=False):
if isinstance(other, iris.cube.Cube):
# get a coordinate comparison of this cube and the cube to do the
# operation with
coord_comp = iris.analysis.coord_comparison(cube, other)
coord_comp = iris.analysis._dimensional_metadata_comparison(
cube, other
)
bad_coord_grps = (
coord_comp["ungroupable_and_dimensioned"]
+ coord_comp["resamplable"]
Expand Down Expand Up @@ -512,7 +518,9 @@ def divide(cube, other, dim=None, in_place=False):
if isinstance(other, iris.cube.Cube):
# get a coordinate comparison of this cube and the cube to do the
# operation with
coord_comp = iris.analysis.coord_comparison(cube, other)
coord_comp = iris.analysis._dimensional_metadata_comparison(
cube, other
)
bad_coord_grps = (
coord_comp["ungroupable_and_dimensioned"]
+ coord_comp["resamplable"]
Expand Down
20 changes: 11 additions & 9 deletions lib/iris/cube.py
Original file line number Diff line number Diff line change
Expand Up @@ -3567,31 +3567,33 @@ def __eq__(self, other):

# having checked the metadata, now check the coordinates
if result:
coord_comparison = iris.analysis.coord_comparison(self, other)
coord_compares = iris.analysis._dimensional_metadata_comparison(
self, other
)
# if there are any coordinates which are not equal
result = not (
coord_comparison["not_equal"]
or coord_comparison["non_equal_data_dimension"]
coord_compares["not_equal"]
or coord_compares["non_equal_data_dimension"]
)

if result:
coord_comparison = iris.analysis.coord_comparison(
cm_compares = iris.analysis._dimensional_metadata_comparison(
self, other, object_get=Cube.cell_measures,
)
# if there are any cell measures which are not equal
result = not (
coord_comparison["not_equal"]
or coord_comparison["non_equal_data_dimension"]
cm_compares["not_equal"]
or cm_compares["non_equal_data_dimension"]
)

if result:
coord_comparison = iris.analysis.coord_comparison(
av_compares = iris.analysis._dimensional_metadata_comparison(
self, other, object_get=Cube.ancillary_variables,
)
# if there are any ancillary variables which are not equal
result = not (
coord_comparison["not_equal"]
or coord_comparison["non_equal_data_dimension"]
av_compares["not_equal"]
or av_compares["non_equal_data_dimension"]
)

# Having checked everything else, check approximate data equality.
Expand Down
2 changes: 1 addition & 1 deletion lib/iris/tests/test_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def test_coord_comparison(self):
cube5.add_dim_coord(lon, 0)
cube5.add_dim_coord(lat, 1)

coord_comparison = iris.analysis.coord_comparison
coord_comparison = iris.analysis._dimensional_metadata_comparison

self.assertComparisonDict(
coord_comparison(cube1, cube1),
Expand Down
2 changes: 1 addition & 1 deletion lib/iris/tests/test_cdm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1207,7 +1207,7 @@ def test_fancy_indexing_bool_array(self):

class TestCubeCollapsed(tests.IrisTest):
def partial_compare(self, dual, single):
result = iris.analysis.coord_comparison(dual, single)
result = iris.analysis._dimensional_metadata_comparison(dual, single)
self.assertEqual(len(result["not_equal"]), 0)
self.assertEqual(
dual.name(),
Expand Down