Skip to content
Open
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
74 changes: 74 additions & 0 deletions src/anemoi/transform/filters/difference.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# (C) Copyright 2024 Anemoi contributors.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
# (C) Copyright 2024 Anemoi contributors.
# (C) Copyright 2026- Anemoi contributors.

#
# This software is licensed under the terms of the Apache Licence Version 2.0
# which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
#
# In applying this licence, ECMWF does not waive the privileges and immunities
# granted to it by virtue of its status as an intergovernmental organisation
# nor does it submit to any jurisdiction.


from typing import Literal

import earthkit.data as ekd

from anemoi.transform.filters import filter_registry
from anemoi.transform.filters.matching import MatchingFieldsFilter
from anemoi.transform.filters.matching import matching


@filter_registry.register("difference")
class DifferenceFilter(MatchingFieldsFilter):
"""A filter to compute a simple difference between two variables.

This filter converts two fields X and Y to a field representing the difference between the two (X - Y).

"""

@matching(select="param", forward=("x", "y"), backward=("diff",))
def __init__(
self,
*,
x: str,
y: str,
diff: str,
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if it's worth having an abs: bool = False argument as well (which optionally takes the absolute value of the difference)? I can imagine that there may cases where the absolute difference is useful (and prevents people having to think about which is X and which is Y)

return_inputs: Literal["all", "none"] | list[str] = "all",
) -> None:
"""Initialize the Diff filter.

Parameters
----------
x : str
Name of the first variable.
y : str
Name of the second variable.
diff : str
Name of the difference variable.
"""

self.x = x
self.y = y
self.diff = diff
self.return_inputs = return_inputs

def forward_transform(self, x: ekd.Field, y: ekd.Field) -> ekd.Field:
"""Compute the difference between two fields (X - Y).

Parameters
----------
x : ekd.Field
The first variable.
y : ekd.Field
The second variable.

Returns
-------
ekd.Field
The difference field.
"""

diff = x.to_numpy() - y.to_numpy()
yield self.new_field_from_numpy(diff, template=x, param=self.diff)

def backward(self, diff: ekd.FieldList) -> ekd.FieldList:
raise NotImplementedError("Difference filter is not reversible")
Loading