Skip to content

Commit 28dfd25

Browse files
committed
Also convert attribute units
1 parent 7fd73e8 commit 28dfd25

File tree

5 files changed

+52
-4
lines changed

5 files changed

+52
-4
lines changed

docs/src/whatsnew/latest.rst

+3-2
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,9 @@ This document explains the changes made to Iris for this release
4242
💣 Incompatible Changes
4343
=======================
4444

45-
#. N/A
46-
45+
#. `@bouweandela`_ changed the ``convert_units`` method on cubes and coordinates
46+
so it also converts the values of the attributes ``"actual_range"``,
47+
``"valid_max"``, ``"valid_min"``, and ``"valid_range"``. (:pull:`6416`)
4748

4849
🚀 Performance Enhancements
4950
===========================

lib/iris/coords.py

+3
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,9 @@ def pointwise_convert(values):
747747
else:
748748
new_bounds = self.units.convert(self.bounds, unit)
749749
self.bounds = new_bounds
750+
for key in "actual_range", "valid_max", "valid_min", "valid_range":
751+
if key in self.attributes:
752+
self.attributes[key] = self.units.convert(self.attributes[key], unit)
750753
self.units = unit
751754

752755
def is_compatible(self, other, ignore=None):

lib/iris/cube.py

+5
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,11 @@ def convert_units(self, unit: str | Unit) -> None:
14781478
else:
14791479
new_data = self.units.convert(self.data, unit)
14801480
self.data = new_data
1481+
for key in "actual_range", "valid_max", "valid_min", "valid_range":
1482+
if key in self.attributes.locals:
1483+
self.attributes.locals[key] = self.units.convert(
1484+
self.attributes.locals[key], unit
1485+
)
14811486
self.units = unit
14821487

14831488
def add_cell_method(self, cell_method: CellMethod) -> None:

lib/iris/tests/unit/coords/test_Coord.py

+22-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
from iris.coords import AuxCoord, Coord, DimCoord
2424
from iris.cube import Cube
2525
from iris.exceptions import UnitConversionError
26+
from iris.tests import _shared_utils
2627
from iris.tests.unit.coords import CoordTestMixin
2728
from iris.warnings import IrisVagueMetadataWarning
2829

@@ -1177,16 +1178,35 @@ def test_coord_3d(self):
11771178
coord._sanity_check_bounds()
11781179

11791180

1180-
class Test_convert_units(tests.IrisTest):
1181+
class Test_convert_units:
11811182
def test_convert_unknown_units(self):
11821183
coord = iris.coords.AuxCoord(1, units="unknown")
11831184
emsg = (
11841185
"Cannot convert from unknown units. "
11851186
'The "units" attribute may be set directly.'
11861187
)
1187-
with self.assertRaisesRegex(UnitConversionError, emsg):
1188+
with pytest.raises(UnitConversionError, match=emsg):
11881189
coord.convert_units("degrees")
11891190

1191+
@pytest.mark.parametrize(
1192+
"attribute",
1193+
[
1194+
"valid_min",
1195+
"valid_max",
1196+
"valid_range",
1197+
"actual_range",
1198+
],
1199+
)
1200+
def test_convert_attributes(self, attribute):
1201+
coord = iris.coords.AuxCoord(1, units="m")
1202+
value = np.array([0, 10]) if attribute.endswith("range") else 0
1203+
coord.attributes[attribute] = value
1204+
coord.convert_units("ft")
1205+
converted_value = cf_units.Unit("m").convert(value, "ft")
1206+
_shared_utils.assert_array_all_close(
1207+
coord.attributes[attribute], converted_value
1208+
)
1209+
11901210

11911211
class Test___str__(tests.IrisTest):
11921212
def test_short_time_interval(self):

lib/iris/tests/unit/cube/test_Cube.py

+19
Original file line numberDiff line numberDiff line change
@@ -3024,6 +3024,25 @@ def test_unit_multiply(self):
30243024
cube.data
30253025
_client.close()
30263026

3027+
@pytest.mark.parametrize(
3028+
"attribute",
3029+
[
3030+
"valid_min",
3031+
"valid_max",
3032+
"valid_range",
3033+
"actual_range",
3034+
],
3035+
)
3036+
def test_convert_attributes(self, attribute):
3037+
cube = iris.cube.Cube(1, units="degrees_C")
3038+
value = np.array([0, 10]) if attribute.endswith("range") else 0
3039+
cube.attributes.locals[attribute] = value
3040+
cube.convert_units("K")
3041+
converted_value = Unit("degrees_C").convert(value, "K")
3042+
_shared_utils.assert_array_all_close(
3043+
cube.attributes.locals[attribute], converted_value
3044+
)
3045+
30273046

30283047
class Test__eq__data:
30293048
"""Partial cube equality testing, for data type only."""

0 commit comments

Comments
 (0)