Skip to content

Commit 4cb8129

Browse files
authored
Merge pull request #14 from hdrake/bounded-regions
Bounded regions
2 parents 84f7156 + 0559c04 commit 4cb8129

12 files changed

Lines changed: 776 additions & 215 deletions

examples/1_thickness_budget.ipynb

Lines changed: 31 additions & 13 deletions
Large diffs are not rendered by default.

examples/2_advective_heat_convergence.ipynb

Lines changed: 78 additions & 46 deletions
Large diffs are not rendered by default.

examples/3_Arctic_heat_CM4p25.ipynb

Lines changed: 26 additions & 27 deletions
Large diffs are not rendered by default.

examples/4_bounded_by_named_sections.ipynb

Lines changed: 463 additions & 0 deletions
Large diffs are not rendered by default.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ dependencies = [
1818
"geopandas",
1919
"regionmask",
2020
"contourpy",
21-
"sectionate @ git+https://github.com/MOM6-community/sectionate.git@master"
21+
"sectionate @ git+https://github.com/hdrake/sectionate.git@master"
2222
]
2323

2424
[project.urls]

regionate/boundaries.py

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def grid_boundaries_from_mask(grid, mask):
1818
1919
RETURNS
2020
-------
21-
i_list, j_list, lons_list, lats_list
21+
i_c_list, j_c_list, lons_c_list, lats_c_list
2222
"""
2323

2424
symmetric = check_symmetric(grid)
@@ -31,33 +31,33 @@ def grid_boundaries_from_mask(grid, mask):
3131
)
3232
.create_contour(0.5)
3333
)
34-
i_list = []
35-
j_list = []
36-
lons_list = []
37-
lats_list = []
34+
i_c_list = []
35+
j_c_list = []
36+
lons_c_list = []
37+
lats_c_list = []
3838
for c in contours:
39-
i, j = c[:-1,0], c[:-1,1]
39+
i_c, j_c = c[:-1,0], c[:-1,1]
4040

41-
i_new, j_new = i.copy(), j.copy()
41+
i_c_new, j_c_new = i_c.copy(), j_c.copy()
4242

43-
i_inc = np.roll(i, -1)-i
44-
j_inc = np.roll(j, -1)-j
43+
i_inc = np.roll(i_c, -1)-i_c
44+
j_inc = np.roll(j_c, -1)-j_c
4545

46-
i_new[(i%1)==0.0] = (i - (i_inc<0))[(i%1)==0.0] + symmetric
47-
j_new[(j%1)==0.0] = (j - (j_inc<0))[(j%1)==0.0] + symmetric
48-
i_new[(i%1)==0.5] = np.floor(i[(i%1)==0.5]) + symmetric
49-
j_new[(j%1)==0.5] = np.floor(j[(j%1)==0.5]) + symmetric
46+
i_c_new[(i_c%1)==0.0] = (i_c - (i_inc<0))[(i_c%1)==0.0] + symmetric
47+
j_c_new[(j_c%1)==0.0] = (j_c - (j_inc<0))[(j_c%1)==0.0] + symmetric
48+
i_c_new[(i_c%1)==0.5] = np.floor(i_c[(i_c%1)==0.5]) + symmetric
49+
j_c_new[(j_c%1)==0.5] = np.floor(j_c[(j_c%1)==0.5]) + symmetric
5050

51-
i_new, j_new = loop(i_new).astype(np.int64), loop(j_new).astype(np.int64)
51+
i_c_new, j_c_new = loop(i_c_new).astype(np.int64), loop(j_c_new).astype(np.int64)
5252

53-
i_list.append(i_new)
54-
j_list.append(j_new)
53+
i_c_list.append(i_c_new)
54+
j_c_list.append(j_c_new)
5555

5656
idx = {
57-
"xq":xr.DataArray(i_new, dims=("pt",)),
58-
"yq":xr.DataArray(j_new, dims=("pt",))
57+
"xq":xr.DataArray(i_c_new, dims=("pt",)),
58+
"yq":xr.DataArray(j_c_new, dims=("pt",))
5959
}
60-
lons_list.append(grid._ds["geolon_c"].isel(idx).values[:-1])
61-
lats_list.append(grid._ds["geolat_c"].isel(idx).values[:-1])
60+
lons_c_list.append(grid._ds["geolon_c"].isel(idx).values[:-1])
61+
lats_c_list.append(grid._ds["geolat_c"].isel(idx).values[:-1])
6262

63-
return i_list, j_list, lons_list, lats_list
63+
return i_c_list, j_c_list, lons_c_list, lats_c_list

regionate/grid_conform.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ def get_region_boundary_grid_indices(lons, lats, grid):
1818
1919
RETURNS
2020
-------
21-
(i, j, lons_c, lats_c, lons_uv, lats_uv)
21+
(i_c, j_c, lons_c, lats_c, lons_uv, lats_uv)
2222
23-
i : "X"-axis grid indices of corner points
24-
j : "Y"-axis grid indices of corner points
23+
i_c : "X"-axis grid indices of corner points
24+
j_c : "Y"-axis grid indices of corner points
2525
lons_c : longitudes of corner points
2626
lats_c : latitudes of corner points
2727
lons_uv : longitudes of (u,v) velocity faces
@@ -30,21 +30,15 @@ def get_region_boundary_grid_indices(lons, lats, grid):
3030
if (lons[0], lats[0]) != (lons[-1], lats[-1]):
3131
lons, lats = loop(lons), loop(lats)
3232

33-
i, j, lons_c, lats_c = sec.grid_section(
33+
i_c, j_c, lons_c, lats_c = sec.grid_section(
3434
grid,
3535
lons,
3636
lats,
3737
topology="MOM-tripolar"
3838
)
39-
40-
uvindices = sec.uvindices_from_qindices(grid, i, j)
41-
42-
lons_uv, lats_uv = sec.uvcoords_from_uvindices(
43-
grid,
44-
uvindices
45-
)
39+
lons_uv, lats_uv = sec.uvcoords_from_qindices(grid, i_c, j_c)
4640

47-
return (i, j, lons_c[:-1], lats_c[:-1], lons_uv, lats_uv)
41+
return (i_c, j_c, lons_c, lats_c, lons_uv, lats_uv)
4842

4943
def mask_from_grid_boundaries(
5044
lons_c,

regionate/overlaps.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33

44
def find_indices_of_overlaps(r1, r2, closeness_threshold=5.e3, face_indices=False):
55
overlaps = haversine(
6-
r1.lons[:, np.newaxis], r1.lats[:, np.newaxis],
7-
r2.lons[np.newaxis, :], r2.lats[np.newaxis, :]
6+
r1.lons_c[:, np.newaxis], r1.lats_c[:, np.newaxis],
7+
r2.lons_c[np.newaxis, :], r2.lats_c[np.newaxis, :]
88
) < closeness_threshold
99

10-
r1_oidx = consecutive_lists( np.where(np.any(overlaps, axis=1))[0], mod=r1.lons.size)
11-
r2_oidx = consecutive_lists( np.where(np.any(overlaps, axis=0))[0], mod=r2.lons.size)
10+
r1_oidx = consecutive_lists( np.where(np.any(overlaps, axis=1))[0], mod=r1.lons_c.size)
11+
r2_oidx = consecutive_lists( np.where(np.any(overlaps, axis=0))[0], mod=r2.lons_c.size)
1212

1313
if face_indices:
1414
r1_oidx = [l[:-1] for l in r1_oidx]
@@ -23,8 +23,8 @@ def group_overlaps(overlaps, r1, r2, closeness_threshold=5.e3):
2323
for o1 in overlaps[r1.name]:
2424
if np.any(o1) and np.any(o2):
2525
if np.any(haversine(
26-
r1.lons[o1, np.newaxis], r1.lats[o1, np.newaxis],
27-
r2.lons[np.newaxis, o2], r2.lats[np.newaxis, o2]
26+
r1.lons_c[o1, np.newaxis], r1.lats_c[o1, np.newaxis],
27+
r2.lons_c[np.newaxis, o2], r2.lats_c[np.newaxis, o2]
2828
) < closeness_threshold):
2929
grouped_overlaps[r1.name][group_num] = o1
3030
grouped_overlaps[r2.name][group_num] = o2
@@ -42,21 +42,21 @@ def align_boundaries_with_overlap_sections(regions, remove_gaps=True):
4242
)
4343

4444
def roll_boundary_to_align_with_overlap(r, oidx, remove_gaps=True):
45-
roll_idx = -consecutive_lists(oidx[0], mod=r.lons.size)[0][0]
46-
new_oidx = {onum: np.mod(np.array(o) + roll_idx, r.lons.size) for (onum, o) in oidx.items()}
45+
roll_idx = -consecutive_lists(oidx[0], mod=r.lons_c.size)[0][0]
46+
new_oidx = {onum: np.mod(np.array(o) + roll_idx, r.lons_c.size) for (onum, o) in oidx.items()}
4747

48-
r.lons = np.roll(r.lons, roll_idx)
49-
r.lats = np.roll(r.lats, roll_idx)
48+
r.lons_c = np.roll(r.lons_c, roll_idx)
49+
r.lats_c = np.roll(r.lats_c, roll_idx)
5050

5151
if remove_gaps:
5252
for onum, o in new_oidx.items():
5353
gaps = np.array([i for i in range(np.min(o), np.max(o)+1) if i not in o])
5454
if any(gaps):
55-
r.lons[gaps] = np.nan
56-
r.lats[gaps] = np.nan
55+
r.lons_c[gaps] = np.nan
56+
r.lats_c[gaps] = np.nan
5757

58-
nan_idx = np.isnan(r.lons) | np.isnan(r.lats)
59-
r.lons = r.lons[~nan_idx]
60-
r.lats = r.lats[~nan_idx]
58+
nan_idx = np.isnan(r.lons_c) | np.isnan(r.lats_c)
59+
r.lons_c = r.lons_c[~nan_idx]
60+
r.lats_c = r.lats_c[~nan_idx]
6161

6262
return r

0 commit comments

Comments
 (0)