Skip to content

Commit 2435ae9

Browse files
committed
improve diagnostic for filter and detection
1 parent d96823c commit 2435ae9

File tree

5 files changed

+90
-21
lines changed

5 files changed

+90
-21
lines changed

examples/02_eddy_identification/pet_eddy_detection.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ def update_axes(ax, mappable=None):
4040
update_axes(ax, m)
4141

4242
# %%
43+
# Get u/v
44+
# -------
4345
# U/V are deduced from ADT, this algortihm are not usable around equator (~+- 2°)
4446
g.add_uv("adt")
4547
ax = start_axes("U/V deduce from ADT (m)")
@@ -50,14 +52,18 @@ def update_axes(ax, mappable=None):
5052
update_axes(ax, m)
5153

5254
# %%
55+
# Pre-processings
56+
# ---------------
5357
# Apply high filter to remove long scale to highlight mesoscale
54-
g.bessel_high_filter("adt", 500, order=2)
55-
ax = start_axes("ADT (m) filtered (500km, order 2)")
58+
g.bessel_high_filter("adt", 500)
59+
ax = start_axes("ADT (m) filtered (500km)")
5660
m = g.display(ax, "adt", vmin=-0.15, vmax=0.15)
5761
update_axes(ax, m)
5862

5963
# %%
60-
#  Run identification with slice of 2 mm
64+
# Identification
65+
# --------------
66+
# run identification with slice of 2 mm
6167
date = datetime(2016, 5, 15)
6268
a, c = g.eddy_identification("adt", "u", "v", date, 0.002)
6369

@@ -93,6 +99,8 @@ def update_axes(ax, mappable=None):
9399
update_axes(ax)
94100

95101
# %%
102+
# Output
103+
# ------
96104
# Display detected eddies, dashed lines represent effective contour
97105
# and solid lines represent contour of maximum of speed. See figure 1 of https://doi.org/10.1175/JTECH-D-14-00019.1
98106

examples/02_eddy_identification/pet_filter_and_detection.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from matplotlib import pyplot as plt
88
from py_eddy_tracker.dataset.grid import RegularGridDataset
99
from py_eddy_tracker import data
10+
from py_eddy_tracker.generic import reverse_index
1011
from numpy import arange
1112

1213

@@ -35,7 +36,7 @@ def update_axes(ax, mappable=None):
3536
g.add_uv("adt")
3637
g.copy("adt", "adt_high")
3738
wavelength = 400
38-
g.bessel_high_filter("adt_high", wavelength, order=3)
39+
g.bessel_high_filter("adt_high", wavelength)
3940
date = datetime(2016, 5, 15)
4041

4142
# %%
@@ -60,7 +61,6 @@ def update_axes(ax, mappable=None):
6061
fig = plt.figure(figsize=(12, 5))
6162
ax_a = plt.subplot(121, xlabel="amplitdue(cm)")
6263
ax_r = plt.subplot(122, xlabel="speed radius (km)")
63-
ax_a.grid(), ax_r.grid()
6464
ax_a.hist(
6565
merge_f["amplitude"] * 100,
6666
bins=arange(0.0005, 100, 1),
@@ -86,15 +86,39 @@ def update_axes(ax, mappable=None):
8686
i, j, c = merge_f.match(merge_r)
8787
m = c > 0.1
8888
i_, j_ = i[m], j[m]
89+
90+
91+
# %%
92+
# where is lonely eddies
93+
kwargs_f = dict(lw=1.5, label="Lonely eddy from filtered grid", ref=-10, color="k")
94+
kwargs_r = dict(lw=1.5, label="Lonely eddy from raw grid", ref=-10, color="r")
95+
ax = start_axes("Eddies with no match, over filtered ADT")
96+
mappable = g.display(ax, "adt_high", vmin=-0.15, vmax=0.15)
97+
merge_f.index(reverse_index(i_, len(merge_f))).display(ax, **kwargs_f)
98+
merge_r.index(reverse_index(j_, len(merge_r))).display(ax, **kwargs_r)
99+
ax.legend()
100+
update_axes(ax, mappable)
101+
102+
ax = start_axes("Eddies with no match, over filtered ADT (zoom)")
103+
ax.set_xlim(25, 36), ax.set_ylim(31, 35.25)
104+
mappable = g.display(ax, "adt_high", vmin=-0.15, vmax=0.15)
105+
u, v = g.grid("u").T, g.grid("v").T
106+
ax.quiver(g.x_c, g.y_c, u, v, scale=10, pivot="mid", color="gray")
107+
merge_f.index(reverse_index(i_, len(merge_f))).display(ax, **kwargs_f)
108+
merge_r.index(reverse_index(j_, len(merge_r))).display(ax, **kwargs_r)
109+
ax.legend()
110+
update_axes(ax, mappable)
111+
112+
# %%
89113
fig = plt.figure(figsize=(12, 12))
90-
fig.suptitle(f"Scatter plot of speed_radius(km) ({m.sum()} matches)")
114+
fig.suptitle(f"Scatter plot ({m.sum()} matches)")
91115

92116
for i, (label, field, factor, stop) in enumerate(
93-
zip(
94-
("speed radius (km)", "outter radius (km)", "amplitude (cm)"),
95-
("radius_s", "radius_e", "amplitude"),
96-
(0.001, 0.001, 100),
97-
(80, 120, 25),
117+
(
118+
("speed radius (km)", "radius_s", 0.001, 80),
119+
("outter radius (km)", "radius_e", 0.001, 120),
120+
("amplitude (cm)", "amplitude", 100, 25),
121+
("speed max (cm/s)", "speed_average", 100, 25),
98122
)
99123
):
100124
ax = fig.add_subplot(

notebooks/python_module/02_eddy_identification/pet_eddy_detection.ipynb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@
6262
"cell_type": "markdown",
6363
"metadata": {},
6464
"source": [
65-
"U/V are deduced from ADT, this algortihm are not usable around equator (~+- 2\u00b0)\n\n"
65+
"Get u/v\n-------\nU/V are deduced from ADT, this algortihm are not usable around equator (~+- 2\u00b0)\n\n"
6666
]
6767
},
6868
{
@@ -80,7 +80,7 @@
8080
"cell_type": "markdown",
8181
"metadata": {},
8282
"source": [
83-
"Apply high filter to remove long scale to highlight mesoscale\n\n"
83+
"Pre-processings\n---------------\nApply high filter to remove long scale to highlight mesoscale\n\n"
8484
]
8585
},
8686
{
@@ -91,14 +91,14 @@
9191
},
9292
"outputs": [],
9393
"source": [
94-
"g.bessel_high_filter(\"adt\", 500, order=2)\nax = start_axes(\"ADT (m) filtered (500km, order 2)\")\nm = g.display(ax, \"adt\", vmin=-0.15, vmax=0.15)\nupdate_axes(ax, m)"
94+
"g.bessel_high_filter(\"adt\", 500)\nax = start_axes(\"ADT (m) filtered (500km)\")\nm = g.display(ax, \"adt\", vmin=-0.15, vmax=0.15)\nupdate_axes(ax, m)"
9595
]
9696
},
9797
{
9898
"cell_type": "markdown",
9999
"metadata": {},
100100
"source": [
101-
"Run identification with slice of 2 mm\n\n"
101+
"Identification\n--------------\nrun identification with slice of 2 mm\n\n"
102102
]
103103
},
104104
{
@@ -188,7 +188,7 @@
188188
"cell_type": "markdown",
189189
"metadata": {},
190190
"source": [
191-
"Display detected eddies, dashed lines represent effective contour\nand solid lines represent contour of maximum of speed. See figure 1 of https://doi.org/10.1175/JTECH-D-14-00019.1\n\n"
191+
"Output\n------\nDisplay detected eddies, dashed lines represent effective contour\nand solid lines represent contour of maximum of speed. See figure 1 of https://doi.org/10.1175/JTECH-D-14-00019.1\n\n"
192192
]
193193
},
194194
{

notebooks/python_module/02_eddy_identification/pet_filter_and_detection.ipynb

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
},
2727
"outputs": [],
2828
"source": [
29-
"from datetime import datetime\nfrom matplotlib import pyplot as plt\nfrom py_eddy_tracker.dataset.grid import RegularGridDataset\nfrom py_eddy_tracker import data\nfrom numpy import arange"
29+
"from datetime import datetime\nfrom matplotlib import pyplot as plt\nfrom py_eddy_tracker.dataset.grid import RegularGridDataset\nfrom py_eddy_tracker import data\nfrom py_eddy_tracker.generic import reverse_index\nfrom numpy import arange"
3030
]
3131
},
3232
{
@@ -55,7 +55,7 @@
5555
},
5656
"outputs": [],
5757
"source": [
58-
"g = RegularGridDataset(\n data.get_path(\"dt_med_allsat_phy_l4_20160515_20190101.nc\"), \"longitude\", \"latitude\",\n)\ng.add_uv(\"adt\")\ng.copy(\"adt\", \"adt_high\")\nwavelength = 400\ng.bessel_high_filter(\"adt_high\", wavelength, order=3)\ndate = datetime(2016, 5, 15)"
58+
"g = RegularGridDataset(\n data.get_path(\"dt_med_allsat_phy_l4_20160515_20190101.nc\"), \"longitude\", \"latitude\",\n)\ng.add_uv(\"adt\")\ng.copy(\"adt\", \"adt_high\")\nwavelength = 400\ng.bessel_high_filter(\"adt_high\", wavelength)\ndate = datetime(2016, 5, 15)"
5959
]
6060
},
6161
{
@@ -109,7 +109,7 @@
109109
},
110110
"outputs": [],
111111
"source": [
112-
"fig = plt.figure(figsize=(12, 5))\nax_a = plt.subplot(121, xlabel=\"amplitdue(cm)\")\nax_r = plt.subplot(122, xlabel=\"speed radius (km)\")\nax_a.grid(), ax_r.grid()\nax_a.hist(\n merge_f[\"amplitude\"] * 100,\n bins=arange(0.0005, 100, 1),\n label=\"Eddy from filtered grid\",\n histtype=\"step\",\n)\nax_a.hist(\n merge_r[\"amplitude\"] * 100,\n bins=arange(0.0005, 100, 1),\n label=\"Eddy from raw grid\",\n histtype=\"step\",\n)\nax_a.set_xlim(0, 10)\nax_r.hist(merge_f[\"radius_s\"] / 1000.0, bins=arange(0, 300, 5), histtype=\"step\")\nax_r.hist(merge_r[\"radius_s\"] / 1000.0, bins=arange(0, 300, 5), histtype=\"step\")\nax_r.set_xlim(0, 100)\nax_a.legend()"
112+
"fig = plt.figure(figsize=(12, 5))\nax_a = plt.subplot(121, xlabel=\"amplitdue(cm)\")\nax_r = plt.subplot(122, xlabel=\"speed radius (km)\")\nax_a.hist(\n merge_f[\"amplitude\"] * 100,\n bins=arange(0.0005, 100, 1),\n label=\"Eddy from filtered grid\",\n histtype=\"step\",\n)\nax_a.hist(\n merge_r[\"amplitude\"] * 100,\n bins=arange(0.0005, 100, 1),\n label=\"Eddy from raw grid\",\n histtype=\"step\",\n)\nax_a.set_xlim(0, 10)\nax_r.hist(merge_f[\"radius_s\"] / 1000.0, bins=arange(0, 300, 5), histtype=\"step\")\nax_r.hist(merge_r[\"radius_s\"] / 1000.0, bins=arange(0, 300, 5), histtype=\"step\")\nax_r.set_xlim(0, 100)\nax_a.legend()"
113113
]
114114
},
115115
{
@@ -127,7 +127,36 @@
127127
},
128128
"outputs": [],
129129
"source": [
130-
"i, j, c = merge_f.match(merge_r)\nm = c > 0.1\ni_, j_ = i[m], j[m]\nfig = plt.figure(figsize=(12, 12))\nfig.suptitle(f\"Scatter plot of speed_radius(km) ({m.sum()} matches)\")\n\nfor i, (label, field, factor, stop) in enumerate(\n zip(\n (\"speed radius (km)\", \"outter radius (km)\", \"amplitude (cm)\"),\n (\"radius_s\", \"radius_e\", \"amplitude\"),\n (0.001, 0.001, 100),\n (80, 120, 25),\n )\n):\n ax = fig.add_subplot(\n 2, 2, i + 1, xlabel=\"filtered grid\", ylabel=\"raw grid\", title=label\n )\n ax.plot(merge_f[field][i_] * factor, merge_r[field][j_] * factor, \".\")\n ax.set_aspect(\"equal\"), ax.grid()\n ax.plot((0, 1000), (0, 1000), \"r\")\n ax.set_xlim(0, stop), ax.set_ylim(0, stop)"
130+
"i, j, c = merge_f.match(merge_r)\nm = c > 0.1\ni_, j_ = i[m], j[m]"
131+
]
132+
},
133+
{
134+
"cell_type": "markdown",
135+
"metadata": {},
136+
"source": [
137+
"where is lonely eddies\n\n"
138+
]
139+
},
140+
{
141+
"cell_type": "code",
142+
"execution_count": null,
143+
"metadata": {
144+
"collapsed": false
145+
},
146+
"outputs": [],
147+
"source": [
148+
"kwargs_f = dict(lw=1.5, label=\"Lonely eddy from filtered grid\", ref=-10, color=\"k\")\nkwargs_r = dict(lw=1.5, label=\"Lonely eddy from raw grid\", ref=-10, color=\"r\")\nax = start_axes(\"Eddies with no match, over filtered ADT\")\nmappable = g.display(ax, \"adt_high\", vmin=-0.15, vmax=0.15)\nmerge_f.index(reverse_index(i_, len(merge_f))).display(ax, **kwargs_f)\nmerge_r.index(reverse_index(j_, len(merge_r))).display(ax, **kwargs_r)\nax.legend()\nupdate_axes(ax, mappable)\n\nax = start_axes(\"Eddies with no match, over filtered ADT (zoom)\")\nax.set_xlim(25, 36), ax.set_ylim(31, 35.25)\nmappable = g.display(ax, \"adt_high\", vmin=-0.15, vmax=0.15)\nu, v = g.grid(\"u\").T, g.grid(\"v\").T\nax.quiver(g.x_c, g.y_c, u, v, scale=10, pivot=\"mid\", color=\"gray\")\nmerge_f.index(reverse_index(i_, len(merge_f))).display(ax, **kwargs_f)\nmerge_r.index(reverse_index(j_, len(merge_r))).display(ax, **kwargs_r)\nax.legend()\nupdate_axes(ax, mappable)"
149+
]
150+
},
151+
{
152+
"cell_type": "code",
153+
"execution_count": null,
154+
"metadata": {
155+
"collapsed": false
156+
},
157+
"outputs": [],
158+
"source": [
159+
"fig = plt.figure(figsize=(12, 12))\nfig.suptitle(f\"Scatter plot ({m.sum()} matches)\")\n\nfor i, (label, field, factor, stop) in enumerate(\n (\n (\"speed radius (km)\", \"radius_s\", 0.001, 80),\n (\"outter radius (km)\", \"radius_e\", 0.001, 120),\n (\"amplitude (cm)\", \"amplitude\", 100, 25),\n (\"speed max (cm/s)\", \"speed_average\", 100, 25),\n )\n):\n ax = fig.add_subplot(\n 2, 2, i + 1, xlabel=\"filtered grid\", ylabel=\"raw grid\", title=label\n )\n ax.plot(merge_f[field][i_] * factor, merge_r[field][j_] * factor, \".\")\n ax.set_aspect(\"equal\"), ax.grid()\n ax.plot((0, 1000), (0, 1000), \"r\")\n ax.set_xlim(0, stop), ax.set_ylim(0, stop)"
131160
]
132161
}
133162
],

src/py_eddy_tracker/generic.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,18 @@
3737
where,
3838
isnan,
3939
)
40-
from numba import njit, prange
40+
from numba import njit, prange, types as numba_types
4141
from numpy.linalg import lstsq
4242

4343

44+
@njit(cache=True)
45+
def reverse_index(index, nb):
46+
m = ones(nb, dtype=numba_types.bool_)
47+
for i in index:
48+
m[i] = False
49+
return where(m)[0]
50+
51+
4452
@njit(cache=True, fastmath=True, parallel=False)
4553
def distance_grid(lon0, lat0, lon1, lat1):
4654
"""

0 commit comments

Comments
 (0)