Skip to content

Commit 7e1c311

Browse files
rajeejaerogluorhan
andauthored
Fix ICON Reader (#1430)
* o Fix ICON Reader added to _icon_to_ugrid_dims * Fix cross section coords handling and further fix ICON reader dim parser * test: add icon cross_section test case --------- Co-authored-by: Orhan Eroglu <[email protected]> Co-authored-by: erogluorhan <[email protected]>
1 parent ee9228d commit 7e1c311

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

test/io/test_icon.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,17 @@ def test_read_icon_grid(gridpath):
88
def test_read_icon_dataset(gridpath):
99
grid_path = gridpath("icon", "R02B04", "icon_grid_0010_R02B04_G.nc")
1010
uxds = ux.open_dataset(grid_path, grid_path)
11+
12+
def test_icon_cross_section(gridpath):
13+
grid_path = gridpath("icon", "R02B04", "icon_grid_0010_R02B04_G.nc")
14+
uxds = ux.open_dataset(grid_path, grid_path)
15+
16+
# Test cross_section with cell_area variable
17+
result = uxds.cell_area.cross_section(start=(0, -90), end=(0, 90))
18+
assert result is not None
19+
assert len(result) == 100 # 100 steps by default
20+
assert result.dims == ('steps',)
21+
assert all(result.coords['lon'] == 0.0) # Constant longitude
22+
assert result.coords['lat'].min() == -90.0
23+
assert result.coords['lat'].max() == 90.0
24+
assert result.attrs['units'] == 'steradian'

uxarray/cross_sections/dataarray_accessor.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,11 @@ def __call__(
132132
data = np.moveaxis(filled, -1, dim_axis)
133133

134134
# Build coords dict: keep everything except 'n_face'
135-
coords = {d: self.uxda.coords[d] for d in self.uxda.coords if d != "n_face"}
135+
coords = {
136+
name: self.uxda.coords[name]
137+
for name in self.uxda.coords
138+
if name != "n_face" and "n_face" not in self.uxda.coords[name].dims
139+
}
136140
# index along the arc
137141
coords[new_dim] = np.arange(steps)
138142

uxarray/io/_icon.py

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,66 @@
55

66

77
def _icon_to_ugrid_dims(in_ds):
8-
source_dims_dict = {"vertex": "n_node", "edge": "n_edge", "cell": "n_face"}
9-
return source_dims_dict
8+
"""Parse ICON dimension names and map them to UGRID conventions."""
9+
source_dims_dict = {}
10+
11+
# Coordinate-driven mappings
12+
if "vlat" in in_ds:
13+
source_dims_dict[in_ds["vlat"].dims[0]] = ugrid.NODE_DIM
14+
if "vlon" in in_ds:
15+
source_dims_dict[in_ds["vlon"].dims[0]] = ugrid.NODE_DIM
16+
17+
if "elat" in in_ds:
18+
source_dims_dict[in_ds["elat"].dims[0]] = ugrid.EDGE_DIM
19+
if "elon" in in_ds:
20+
source_dims_dict[in_ds["elon"].dims[0]] = ugrid.EDGE_DIM
21+
22+
if "clat" in in_ds:
23+
source_dims_dict[in_ds["clat"].dims[0]] = ugrid.FACE_DIM
24+
if "clon" in in_ds:
25+
source_dims_dict[in_ds["clon"].dims[0]] = ugrid.FACE_DIM
26+
27+
# Connectivity-driven mappings
28+
if "vertex_of_cell" in in_ds:
29+
n_max_face_nodes_dim, face_dim = in_ds["vertex_of_cell"].dims
30+
source_dims_dict.setdefault(face_dim, ugrid.FACE_DIM)
31+
source_dims_dict.setdefault(n_max_face_nodes_dim, ugrid.N_MAX_FACE_NODES_DIM)
32+
33+
if "edge_of_cell" in in_ds:
34+
n_max_face_edges_dim, face_dim = in_ds["edge_of_cell"].dims
35+
source_dims_dict.setdefault(face_dim, ugrid.FACE_DIM)
36+
source_dims_dict.setdefault(
37+
n_max_face_edges_dim, ugrid.FACE_EDGE_CONNECTIVITY_DIMS[1]
38+
)
39+
40+
if "neighbor_cell_index" in in_ds:
41+
n_max_face_faces_dim, face_dim = in_ds["neighbor_cell_index"].dims
42+
source_dims_dict.setdefault(face_dim, ugrid.FACE_DIM)
43+
source_dims_dict.setdefault(
44+
n_max_face_faces_dim, ugrid.FACE_FACE_CONNECTIVITY_DIMS[1]
45+
)
46+
47+
if "adjacent_cell_of_edge" in in_ds:
48+
two_dim, edge_dim = in_ds["adjacent_cell_of_edge"].dims
49+
source_dims_dict.setdefault(edge_dim, ugrid.EDGE_DIM)
50+
source_dims_dict.setdefault(two_dim, ugrid.EDGE_FACE_CONNECTIVITY_DIMS[1])
51+
52+
if "edge_vertices" in in_ds:
53+
two_dim, edge_dim = in_ds["edge_vertices"].dims
54+
source_dims_dict.setdefault(edge_dim, ugrid.EDGE_DIM)
55+
source_dims_dict.setdefault(two_dim, ugrid.EDGE_NODE_CONNECTIVITY_DIMS[1])
56+
57+
# Fall back to common ICON dimension names if they were not detected above
58+
for dim, ugrid_dim in {
59+
"vertex": ugrid.NODE_DIM,
60+
"edge": ugrid.EDGE_DIM,
61+
"cell": ugrid.FACE_DIM,
62+
}.items():
63+
if dim in in_ds.dims:
64+
source_dims_dict.setdefault(dim, ugrid_dim)
65+
66+
# Keep only dims that actually exist on the dataset
67+
return {dim: name for dim, name in source_dims_dict.items() if dim in in_ds.dims}
1068

1169

1270
def _primal_to_ugrid(in_ds, out_ds):

0 commit comments

Comments
 (0)