Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge from main into develop #48

Merged
merged 3 commits into from
Dec 9, 2024
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
16 changes: 16 additions & 0 deletions docs/gridspec.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,19 @@ Example:
{"grid": "H512", "ordering": "ring"}
{"grid": "H512"}
ORCA grid
------------------------------------------

The ``grid`` format is::

eORCAXXX_subtype

The ``subtype`` must be "T", "U", "V" or "W".

Example:

.. code-block::
{"grid": "eORCA025_T"}
1 change: 1 addition & 0 deletions docs/inventory/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ The pages below contain all the **source and target gridspec** combinations for
healpix_ring
healpix_nested
regular_ll
orca
9 changes: 9 additions & 0 deletions docs/inventory/orca.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.. _orca_inventory:

orca
==============

.. note::
Currently, only the ``linear`` and ``nearest-neighbour`` interpolation methods are supported for ORCA grids.

.. module-output:: generate_inventory_rst orca "ORCA"
8 changes: 8 additions & 0 deletions docs/release_notes/version_0.3_updates.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
Version 0.3 Updates
/////////////////////////

Version 0.3.5
===============

Fixes
++++++++++++++++
- added support for ORCA input grids in :func:`interpolate`. See the :ref:`ORCA inventory <orca_inventory>` for the list of available ORCA source grids.


Version 0.3.4
===============

Expand Down
4 changes: 2 additions & 2 deletions src/earthkit/regrid/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ def load(self, path):
)

for name, entry in index["matrix"].items():
# it is possible that the inventory is already updated with new
# a gridspecs type, but a given earthkit-regrid version is not
# it is possible that the inventory is already updated with a new
# gridspecs type, but a given earthkit-regrid version is not
# yet supporting it. In this case loading the index should not crash.
try:
in_gs = GridSpec.from_dict(entry["input"])
Expand Down
18 changes: 17 additions & 1 deletion src/earthkit/regrid/gridspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

HEALPIX_PATTERN = re.compile(r"[Hh]\d+")
RGG_PATTERN = re.compile(r"[OoNn]\d+")

ORCA_PATTERN = re.compile(r"eORCA\d+_[TUVW]")

# NOTE: this is a temporary code until the full gridspec
# implementation is available via earthkit-geo.
Expand Down Expand Up @@ -424,8 +424,24 @@ def type_match(grid):
return False


class NamedGridSpec(GridSpec):
@staticmethod
def type_match(grid):
return isinstance(grid, str)


class OrcaGridSpec(GridSpec):
@staticmethod
def type_match(grid):
if isinstance(grid, str):
return ORCA_PATTERN.match(grid)
return False


GRIDSPEC_TYPES = {
"regular_ll": LLGridSpec,
"reduced_gg": ReducedGGGridSpec,
"healpix": HealpixGridSpec,
"orca": OrcaGridSpec,
# "_named": NamedGridSpec,
}
5 changes: 5 additions & 0 deletions src/earthkit/regrid/utils/matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ def healpix(entry):
return d


def orca(entry):
d = {"grid": entry["unstructuredGridType"] + "_" + entry["unstructuredGridSubtype"]}
return d


def make_sha(d):
m = hashlib.sha256()
m.update(json.dumps(d, sort_keys=True).encode("utf-8"))
Expand Down
27 changes: 27 additions & 0 deletions tests/data/local/db/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,33 @@
"version": 16,
"method": "grid-box-average"
}
},
"df20c8b83afc369370e615d3380482d384cedf033af66d3962b40292c83cbb9f": {
"input": {
"grid": "eORCA025_T",
"shape": [
1740494
],
"global": 1
},
"output": {
"grid": "O96",
"shape": [
40320
],
"area": [
89.2842,
0,
-89.2842,
359.1
],
"global": 1
},
"interpolation": {
"engine": "mir",
"version": 16,
"method": "linear"
}
}
}
}
3 changes: 3 additions & 0 deletions tests/test_gridspec.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
({"grid": "H128"}, {"grid": [1, 1]}),
({"grid": "H128", "ordering": "ring"}, {"grid": [1, 1]}),
({"grid": (5, 5)}, {"grid": (10, 10)}),
({"grid": "eORCA025_T"}, {"grid": "O96"}),
],
)
def test_gridspec_ok(gs_in, gs_out):
Expand Down Expand Up @@ -117,6 +118,8 @@ def test_gridspec_ok(gs_in, gs_out):
({"grid": "N32", "shape": 6599680}, {"grid": [10, 10]}, None),
({"grid": "N32", "area": [90, 0, -90, 359.999]}, {"grid": [10, 10]}, None),
({"grid": "N32", "area": [90, -0.1, -90, 360]}, {"grid": [10, 10]}, None),
({"grid": "ORCA025_T"}, {"grid": "O96"}, ValueError),
({"grid": "eORCA025_U"}, {"grid": "O96"}, None),
],
)
def test_gridspec_bad(gs_in, gs_out, err):
Expand Down
27 changes: 25 additions & 2 deletions tests/test_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ def test_local_index():
index_path = DB.index_file_path()
with open(index_path, "r") as f:
d = json.load(f)
assert len(d["matrix"]) == 16
assert len(d["matrix"]) == 17

assert len(DB) == 15
assert len(DB) == 16

# r = DB.find_entry({"grid": [5, 5]}, {"grid": [10, 10]}, method)
# assert r
Expand All @@ -63,6 +63,9 @@ def test_local_index():
r = DB.find_entry({"grid": "O64"}, {"grid": [10, 10]}, method)
assert r is None

r = DB.find_entry({"grid": "eORCA025_T"}, {"grid": "O96"}, method)
assert r


@pytest.mark.parametrize("method", METHODS)
def test_local_ll_to_ll(method):
Expand Down Expand Up @@ -136,6 +139,23 @@ def test_local_healpix_nested_to_ll(method):
assert np.allclose(v_res.flatten(), v_ref)


# TODO: implement this test
# @pytest.mark.parametrize("method", ["linear", "nearest-neighbour"])
# def test_local_orca_to_ll(method):
# v_in = np.load(file_in_testdir("in_eorca025_t.npz"))["arr_0"]
# v_ref = np.load(file_in_testdir(f"out_eorca025_t_10x10_{method}.npz"))["arr_0"]
# v_res = interpolate(
# v_in,
# {"grid": "eORCA025_T"},
# {"grid": [10, 10]},
# matrix_source=DB_PATH,
# method=method,
# )

# assert v_res.shape == (19, 36)
# assert np.allclose(v_res.flatten(), v_ref)


@pytest.mark.parametrize(
"gs_in, gs_out",
[
Expand Down Expand Up @@ -181,6 +201,7 @@ def test_local_healpix_nested_to_ll(method):
),
({"grid": "H4"}, {"grid": [10, 10]}),
({"grid": "H4", "ordering": "ring"}, {"grid": [10, 10]}),
({"grid": "eORCA025_T"}, {"grid": "O96"}),
],
)
def test_local_gridspec_ok(gs_in, gs_out):
Expand Down Expand Up @@ -217,6 +238,8 @@ def test_local_gridspec_ok(gs_in, gs_out):
({"grid": "N32", "area": [90, 0, -90, 359.999]}, {"grid": [10, 10]}, None),
({"grid": "N32", "area": [90, -0.1, -90, 360]}, {"grid": [10, 10]}, None),
({"grid": "H4", "ordering": "any"}, {"grid": [10, 10]}, ValueError),
({"grid": "ORCA025_T"}, {"grid": "O96"}, ValueError),
({"grid": "eORCA025_U"}, {"grid": "O96"}, None),
],
)
def test_local_gridspec_bad(gs_in, gs_out, err):
Expand Down
9 changes: 4 additions & 5 deletions tools/manage/build_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,15 +94,14 @@
]
}

in_grids = {
"N_rgg": [256],
}
in_grids = {"orca": ["eORCA025_T"]}

out_grids = {
"O_rgg": [400],
# "O_rgg": [96],
"N_rgg": [320],
}

build_root_dir = "_build_20241123"
build_root_dir = "_build_20241208"
build_dir = os.path.join(build_root_dir, "db")

# extra = [["0.25x0.25", "N320"], ["O1280", "N320"], ["5x5", "10x10"]]
Expand Down
19 changes: 10 additions & 9 deletions tools/manage/test_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@
This script generates and runs tests for newly built (partial) matrix inventory.
"""

build_root_dir = "_build_20241021"
build_root_dir = "_build_20241208"
db_dir = os.path.join(build_root_dir, "db")
index_file = os.path.join(build_root_dir, "index", "index.json")
test_dir = os.path.join(build_root_dir, "test")

# methods = ["linear", "nearest-neighbour"]
# build_matrix_dirs = ["matrices_linear", "matrices_nn"]
methods = ["linear", "nearest-neighbour"]
build_matrix_dirs = ["matrices_linear", "matrices_nn"]

methods = ["grid-box-average"]
build_matrix_dirs = ["matrices_grid-box-average"]
# methods = ["grid-box-average"]
# build_matrix_dirs = ["matrices_grid-box-average"]


def build_test_dir():
Expand All @@ -49,6 +49,7 @@ def build_test_dir():
count = 0
for m_dir in build_matrix_dirs:
m_dir = os.path.join(db_dir, m_dir)
print(f"Looking for matrices in {m_dir}")
for d in glob.glob(m_dir + "/*"):
if os.path.isdir(d):
print(f"Linking {d}")
Expand All @@ -71,15 +72,15 @@ def build_test_dir():
build_test_dir()

# TODO: make the tests automatic
gs_in = {"grid": "N256"}
gs_out = {"grid": "O400"}
gs_in = {"grid": "eORCA025_T"}
gs_out = {"grid": "O96"}
cnt = 0
for method in methods:
v = np.ones(348528)
v = np.ones(1740494)
r = earthkit.regrid.interpolate(
v, gs_in, gs_out, matrix_source=test_dir, method=method
)
assert len(r) == 654400
assert len(r) == 40320
cnt += 1

print(f"Tests passed: {cnt}")
6 changes: 5 additions & 1 deletion tools/utils/grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ def make_H_nested(g):
return f"H{g}_nested"


def make_other(g):
return f"{g}"


makers = {
k: globals()[f"make_{k}"] for k in ["ll", "O_rgg", "N_rgg", "H_ring", "H_nested"]
}
Expand All @@ -36,7 +40,7 @@ def make_H_nested(g):
def make_grid_id(grids):
r = []
for k, v in grids.items():
m = makers[k]
m = makers.get(k, make_other)
for x in v:
r.append(m(x))
return r
Loading