From 1045e7d62d4a08aba20f147cf87134d381471f69 Mon Sep 17 00:00:00 2001 From: David Hassell Date: Fri, 12 Jun 2026 14:50:08 +0100 Subject: [PATCH 1/3] dev --- cf/weights.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/cf/weights.py b/cf/weights.py index 3cefd163d3..5d3cbccd0d 100644 --- a/cf/weights.py +++ b/cf/weights.py @@ -1548,9 +1548,17 @@ def cell_measure( ) clm = clm.get_data(_fill_value=False).copy() - if clm_axes != clm_axes0: - iaxes = [clm_axes0.index(axis) for axis in clm_axes] - clm.squeeze(iaxes, inplace=True) + + # Squeeze out size 1 axes + clm.squeeze(inplace=True) + #if clm_axes != clm_axes0: + # # Squeeze out size1 axes + # iaxes = [ + # clm_axes0.index(axis) + # for axis in clm_axes0 + # if axis not in clm_axes + # ] + # clm.squeeze(iaxes, inplace=True) if methods: weights[tuple(clm_axes)] = measure + " cell measure" From ee7093df17e6fce0190ec3ef9eb631f77df33a0c Mon Sep 17 00:00:00 2001 From: David Hassell Date: Fri, 12 Jun 2026 16:48:07 +0100 Subject: [PATCH 2/3] dev --- MANIFEST.in | 2 +- cf/test/cell_measures.nc | Bin 0 -> 35165 bytes cf/test/test_collapse.py | 28 ++++++++++++++++++++++++++++ cf/weights.py | 8 -------- 4 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 cf/test/cell_measures.nc diff --git a/MANIFEST.in b/MANIFEST.in index b8412ba8ca..6b545ff796 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -9,7 +9,7 @@ recursive-exclude cf/data *.rst prune cf/test recursive-include cf/test __init__.py test_*.py recursive-include cf/test cfa_test.sh run_tests.py setup_create_field.py create_test_files*.py individual_tests.sh -recursive-include cf/test test_file.nc test_file[2-4].nc file.nc file[1-9].nc ugrid_global_1.nc ugrid_global_2.nc create_test_files.npz create_test_files_2.npz wgdos_packed.pp extra_data.pp file1.pp *.cdl create_test_files.npz create_test_files_2.npz example_field_0.nc +recursive-include cf/test test_file.nc test_file[2-4].nc file.nc file[1-9].nc ugrid_global_1.nc ugrid_global_2.nc create_test_files.npz create_test_files_2.npz wgdos_packed.pp extra_data.pp file1.pp *.cdl create_test_files.npz create_test_files_2.npz example_field_0.nc cell_measures.nc recursive-include cf/test/example_field_0.zarr[23] * include cf/test/example_field_0.kerchunk prune cf/test/dir diff --git a/cf/test/cell_measures.nc b/cf/test/cell_measures.nc new file mode 100644 index 0000000000000000000000000000000000000000..52ca079dc725a3c8ecc16e4ba8f5a047f0ecf15a GIT binary patch literal 35165 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 literal 0 HcmV?d00001 diff --git a/cf/test/test_collapse.py b/cf/test/test_collapse.py index b3f73f4524..a57ca68879 100644 --- a/cf/test/test_collapse.py +++ b/cf/test/test_collapse.py @@ -37,6 +37,9 @@ def setUp(self): self.filename2 = os.path.join( os.path.dirname(os.path.abspath(__file__)), "test_file2.nc" ) + self.cell_measures = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "cell_measures.nc" + ) def test_Field_collapse_CLIMATOLOGICAL_TIME(self): verbose = False @@ -853,6 +856,31 @@ def test_Field_collapse_HEALPix(self): g1.coordinate_reference("grid_mapping_name:latitude_longitude") ) + def test_Field_cell_measures(self): + """Test collapse weights by area and volume cell measures.""" + f = cf.read(self.cell_measures)[0] + self.assertEqual(f.shape, (1, 5, 5, 5)) + self.assertEqual(f.cell_measure("measure:area").shape, (5, 5)) + self.assertEqual(f.cell_measure("measure:volume").shape, (1, 5, 5, 5)) + + f.collapse("area: mean", weights="area") + f.collapse("volume: mean", weights="volume") + + self.assertEqual(f.weights("area").shape, (5, 5)) + self.assertEqual(f.weights("volume").shape, (5, 5, 5)) + + g = f[..., 0] + + self.assertEqual(g.shape, (1, 5, 5, 1)) + self.assertEqual(g.cell_measure("measure:area").shape, (5, 1)) + self.assertEqual(g.cell_measure("measure:volume").shape, (1, 5, 5, 1)) + + g.collapse("area: mean", weights="area") + g.collapse("volume: mean", weights="volume") + + self.assertEqual(g.weights("area").shape, (5,)) + self.assertEqual(g.weights("volume").shape, (5, 5)) + if __name__ == "__main__": print("Run date:", datetime.datetime.now()) diff --git a/cf/weights.py b/cf/weights.py index 5d3cbccd0d..f9e893cbf0 100644 --- a/cf/weights.py +++ b/cf/weights.py @@ -1551,14 +1551,6 @@ def cell_measure( # Squeeze out size 1 axes clm.squeeze(inplace=True) - #if clm_axes != clm_axes0: - # # Squeeze out size1 axes - # iaxes = [ - # clm_axes0.index(axis) - # for axis in clm_axes0 - # if axis not in clm_axes - # ] - # clm.squeeze(iaxes, inplace=True) if methods: weights[tuple(clm_axes)] = measure + " cell measure" From e7af87c09d170b04b2d6a813e82b8059cbadef7a Mon Sep 17 00:00:00 2001 From: David Hassell Date: Fri, 12 Jun 2026 17:04:39 +0100 Subject: [PATCH 3/3] dev --- Changelog.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.rst b/Changelog.rst index 8129242891..c82e9a02bb 100644 --- a/Changelog.rst +++ b/Changelog.rst @@ -5,6 +5,9 @@ Version NEXTVERSION * Fix bug in `cf.read` that prevented some OPeNDAP URLS being read (https://github.com/NCAS-CMS/cf-python/issues/948) +* Fix bug that caused weighted `cf.collapse` and `cf.weights` to fail + when a cell meausures has a size 1 axis + (https://github.com/NCAS-CMS/cf-python/issues/952) ----