From ffa0215a03d1dff7473f717a17dae459014d1420 Mon Sep 17 00:00:00 2001 From: omiralles Date: Mon, 18 Nov 2024 14:00:06 +0100 Subject: [PATCH 1/4] Fix voronoi issue for empty list management --- src/anemoi/graphs/nodes/attributes.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/anemoi/graphs/nodes/attributes.py b/src/anemoi/graphs/nodes/attributes.py index 1498e6d..5f64668 100644 --- a/src/anemoi/graphs/nodes/attributes.py +++ b/src/anemoi/graphs/nodes/attributes.py @@ -144,13 +144,24 @@ def get_raw_values(self, nodes: NodeStorage, **kwargs) -> np.ndarray: latitudes, longitudes = nodes.x[:, 0], nodes.x[:, 1] points = latlon_rad_to_cartesian((np.asarray(latitudes), np.asarray(longitudes))) sv = SphericalVoronoi(points, self.radius, self.centre) + # SphericalVoronoi expects C int type + if sv._simplices.dtype != np.int32: + sv._simplices = sv._simplices.astype(np.int32) + # np.asarray([]) is dtype float 64 + # the code expects intp (e.g. int64) + mask = np.array([bool(i) for i in sv.regions]) + sv.regions = [l for l in sv.regions if l] + # compute the area weight without empty regions area_weights = sv.calculate_areas() + # add them back with zero weight + result = np.zeros(points.shape[0]) + result[mask] = area_weights LOGGER.debug( "There are %d of weights, which (unscaled) add up a total weight of %.2f.", - len(area_weights), - np.array(area_weights).sum(), + len(result), + np.array(result).sum(), ) - return area_weights + return result class BooleanBaseNodeAttribute(BaseNodeAttribute, ABC): From b21d137b5df35f25105df86beadb8f994abdf118 Mon Sep 17 00:00:00 2001 From: omiralles Date: Thu, 21 Nov 2024 10:47:43 +0100 Subject: [PATCH 2/4] Remove unnecessary code and add fill_value --- src/anemoi/graphs/nodes/attributes.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/anemoi/graphs/nodes/attributes.py b/src/anemoi/graphs/nodes/attributes.py index 5f64668..a003cb5 100644 --- a/src/anemoi/graphs/nodes/attributes.py +++ b/src/anemoi/graphs/nodes/attributes.py @@ -106,6 +106,8 @@ class AreaWeights(BaseNodeAttribute): Radius of the sphere. centre : np.ndarray Centre of the sphere. + fill_value : float + Value to fill the empty regions. Methods ------- @@ -118,11 +120,13 @@ def __init__( norm: str | None = None, radius: float = 1.0, centre: np.ndarray = np.array([0, 0, 0]), + fill_value: float = 0.0, dtype: str = "float32", ) -> None: super().__init__(norm, dtype) self.radius = radius self.centre = centre + self.fill_value = fill_value def get_raw_values(self, nodes: NodeStorage, **kwargs) -> np.ndarray: """Compute the area associated to each node. @@ -144,17 +148,14 @@ def get_raw_values(self, nodes: NodeStorage, **kwargs) -> np.ndarray: latitudes, longitudes = nodes.x[:, 0], nodes.x[:, 1] points = latlon_rad_to_cartesian((np.asarray(latitudes), np.asarray(longitudes))) sv = SphericalVoronoi(points, self.radius, self.centre) - # SphericalVoronoi expects C int type - if sv._simplices.dtype != np.int32: - sv._simplices = sv._simplices.astype(np.int32) # np.asarray([]) is dtype float 64 # the code expects intp (e.g. int64) mask = np.array([bool(i) for i in sv.regions]) - sv.regions = [l for l in sv.regions if l] + sv.regions = [region for region in sv.regions if region] # compute the area weight without empty regions area_weights = sv.calculate_areas() # add them back with zero weight - result = np.zeros(points.shape[0]) + result = np.ones(points.shape[0]) * self.fill_value result[mask] = area_weights LOGGER.debug( "There are %d of weights, which (unscaled) add up a total weight of %.2f.", From 6f5cdc8735673b9af44df7e8c8dcc2b4bb08177d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 21 Nov 2024 09:51:12 +0000 Subject: [PATCH 3/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/anemoi/graphs/nodes/attributes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/anemoi/graphs/nodes/attributes.py b/src/anemoi/graphs/nodes/attributes.py index a003cb5..32fc717 100644 --- a/src/anemoi/graphs/nodes/attributes.py +++ b/src/anemoi/graphs/nodes/attributes.py @@ -106,7 +106,7 @@ class AreaWeights(BaseNodeAttribute): Radius of the sphere. centre : np.ndarray Centre of the sphere. - fill_value : float + fill_value : float Value to fill the empty regions. Methods From a39d6bf2ab75b3a515fe56e23e9002b9daecbab3 Mon Sep 17 00:00:00 2001 From: omiralles Date: Thu, 21 Nov 2024 11:25:26 +0100 Subject: [PATCH 4/4] Update changelog, remove comments --- CHANGELOG.md | 1 + src/anemoi/graphs/nodes/attributes.py | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7743f30..16b9282 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ Keep it human-readable, your future self will thank you! - Added `CutOutMask` class to create a mask for a cutout. (#68) - Added `MissingZarrVariable` and `NotMissingZarrVariable` classes to create a mask for missing zarr variables. (#68) - feat: Add CONTRIBUTORS.md file. (#72) +- Fixed issue when computing area weights with scipy.Voronoi. (#79) ### Changed diff --git a/src/anemoi/graphs/nodes/attributes.py b/src/anemoi/graphs/nodes/attributes.py index 32fc717..4a7ad10 100644 --- a/src/anemoi/graphs/nodes/attributes.py +++ b/src/anemoi/graphs/nodes/attributes.py @@ -148,8 +148,6 @@ def get_raw_values(self, nodes: NodeStorage, **kwargs) -> np.ndarray: latitudes, longitudes = nodes.x[:, 0], nodes.x[:, 1] points = latlon_rad_to_cartesian((np.asarray(latitudes), np.asarray(longitudes))) sv = SphericalVoronoi(points, self.radius, self.centre) - # np.asarray([]) is dtype float 64 - # the code expects intp (e.g. int64) mask = np.array([bool(i) for i in sv.regions]) sv.regions = [region for region in sv.regions if region] # compute the area weight without empty regions