Skip to content

Commit 581a637

Browse files
Change segment color in video and add comments (AntSimi#50)
- add scatter and event_map, change marker for event - Add documentation in examples
1 parent ab226ce commit 581a637

File tree

6 files changed

+106
-27
lines changed

6 files changed

+106
-27
lines changed

examples/16_network/pet_atlas.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""
2-
Network analyse
3-
===============
2+
Network Analysis
3+
================
44
"""
55
from matplotlib import pyplot as plt
66
from numpy import ma
@@ -21,7 +21,7 @@
2121

2222

2323
# %%
24-
# Function
24+
# Functions
2525
def start_axes(title):
2626
fig = plt.figure(figsize=(13, 5))
2727
ax = fig.add_axes([0.03, 0.03, 0.90, 0.94], projection="full_axes")
@@ -41,6 +41,7 @@ def update_axes(ax, mappable=None):
4141
# %%
4242
# All
4343
# ---
44+
# Display the % of time each pixel (1/10°) is within an anticyclonic network
4445
ax = start_axes("")
4546
g_all = n.grid_count(bins)
4647
m = g_all.display(ax, **kw_time, vmin=0, vmax=75)
@@ -49,12 +50,16 @@ def update_axes(ax, mappable=None):
4950
# %%
5051
# Network longer than 10 days
5152
# ---------------------------
53+
# Display the % of time each pixel (1/10°) is within an anticyclonic network
54+
# which total lifetime in longer than 10 days
5255
ax = start_axes("")
5356
n10 = n.longer_than(10)
5457
g_10 = n10.grid_count(bins)
5558
m = g_10.display(ax, **kw_time, vmin=0, vmax=75)
5659
update_axes(ax, m).set_label("Pixel used in % of time")
5760

61+
# Display the ratio between the short and total presence.
62+
# Red = mostly short networks
5863
ax = start_axes("")
5964
m = g_10.display(
6065
ax,
@@ -67,12 +72,17 @@ def update_axes(ax, mappable=None):
6772
# %%
6873
# Network longer than 20 days
6974
# ---------------------------
75+
# Display the % of time each pixel (1/10°) is within an anticyclonic network
76+
# which total lifetime in longer than 20 days
7077
ax = start_axes("")
7178
n20 = n.longer_than(20)
7279
g_20 = n20.grid_count(bins)
7380
m = g_20.display(ax, **kw_time, vmin=0, vmax=75)
7481
update_axes(ax, m).set_label("Pixel used in % of time")
7582

83+
# %%
84+
# Display the ratio between the short and total presence.
85+
# Red = mostly short networks
7686
ax = start_axes("")
7787
m = g_20.display(
7888
ax,
@@ -82,6 +92,11 @@ def update_axes(ax, mappable=None):
8292
name=g_20.vars["count"] * 100.0 / g_all.vars["count"]
8393
)
8494
update_axes(ax, m).set_label("Pixel used in % all atlas")
95+
96+
# %%
97+
# Display the ratio between the short and total presence.
98+
# Red = mostly short networks
99+
# Networks shorter than 365 days are masked
85100
ax = start_axes("")
86101
m = g_20.display(
87102
ax,
@@ -93,6 +108,11 @@ def update_axes(ax, mappable=None):
93108
)
94109
)
95110
update_axes(ax, m).set_label("Pixel used in % all atlas")
111+
# %%
112+
# Display the ratio between the short and total presence.
113+
# Red = mostly short networks
114+
# Networks longer than 365 days are masked
115+
# -> Coastal areas are mostly populated by short networks
96116
ax = start_axes("")
97117
m = g_20.display(
98118
ax,
@@ -110,11 +130,13 @@ def update_axes(ax, mappable=None):
110130
# %%
111131
# All merging
112132
# -----------
133+
# Display the occurence of merging events
113134
ax = start_axes("")
114135
g_all_merging = n.merging_event().grid_count(bins)
115136
m = g_all_merging.display(ax, **kw_time, vmin=0, vmax=0.2)
116137
update_axes(ax, m).set_label("Pixel used in % of time")
117138
# %%
139+
# Ratio merging events / eddy presence
118140
ax = start_axes("")
119141
m = g_all_merging.display(
120142
ax,
@@ -126,8 +148,8 @@ def update_axes(ax, mappable=None):
126148
update_axes(ax, m).set_label("Pixel used in % all atlas")
127149

128150
# %%
129-
# Merging in network longer than 10 days
130-
# --------------------------------------
151+
# Merging in networks longer than 10 days
152+
# ---------------------------------------
131153
ax = start_axes("")
132154
g_10_merging = n10.merging_event().grid_count(bins)
133155
m = g_10_merging.display(ax, **kw_time, vmin=0, vmax=0.2)

examples/16_network/pet_ioannou_2017_case.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,18 @@
44
Figure 10 from https://doi.org/10.1002/2017JC013158
55
66
"""
7+
8+
# %%
9+
# We want to find the Ierapetra Eddy described above in the networks
10+
11+
# %%
712
from datetime import datetime, timedelta
813

914
import numpy as np
1015
from matplotlib import pyplot as plt
1116
from matplotlib.animation import FuncAnimation
1217
from matplotlib.ticker import FuncFormatter
18+
from matplotlib import colors
1319

1420
import py_eddy_tracker.gui
1521
from py_eddy_tracker.appli.gui import Anim
@@ -62,6 +68,8 @@ def update_axes(ax, mappable=None):
6268

6369

6470
# %%
71+
# We know the position and the time of a specific eddy
72+
# `n.extract_with_mask` give us the corresponding network
6573
n = NetworkObservations.load_file(
6674
"med/Anticyclonic_seg.nc"
6775
)
@@ -77,13 +85,15 @@ def update_axes(ax, mappable=None):
7785
print(ioannou_case.infos())
7886

7987
# %%
88+
# It seems that this network is huge! Our case is in purple...
8089
ax = start_axes()
8190
ioannou_case.plot(ax)
8291
update_axes(ax)
8392

8493
# %%
8594
# Full Timeline
8695
# -------------
96+
# The network span for many years... How to cut the interesting part?
8797
fig = plt.figure(figsize=(15, 5))
8898
ax = fig.add_axes([0.04, 0.05, 0.92, 0.92])
8999
ax.xaxis.set_major_formatter(formatter), ax.grid()
@@ -93,6 +103,7 @@ def update_axes(ax, mappable=None):
93103
# %%
94104
# Sub network and new numbering
95105
# -----------------------------
106+
# Here we chose to keep only the order 3 segments relatives to our chosen eddy
96107
i = np.where(
97108
(ioannou_case.lat > 33)
98109
* (ioannou_case.lat < 34)
@@ -107,10 +118,14 @@ def update_axes(ax, mappable=None):
107118
# %%
108119
# Anim
109120
# ----
121+
# Quick movie to see better!
122+
cmap = colors.ListedColormap(
123+
list(close_to_i3.COLORS), name="from_list", N=close_to_i3.segment.max()
124+
)
110125
a = Anim(
111126
close_to_i3,
112127
figsize=(12, 4),
113-
cmap="Spectral_r",
128+
cmap=cmap,
114129
nb_step=7,
115130
dpi=55,
116131
field_color="segment",
@@ -136,8 +151,8 @@ def update_axes(ax, mappable=None):
136151
update_axes(ax)
137152

138153
# %%
139-
# Local Timeline
140-
# --------------
154+
# Latitude Timeline
155+
# -----------------
141156
ax = timeline_axes(f"Close segments ({close_to_i3.infos()})")
142157
n_copy = close_to_i3.copy()
143158
n_copy.median_filter(15, "time", "latitude")
@@ -146,6 +161,7 @@ def update_axes(ax, mappable=None):
146161
# %%
147162
# Local radius timeline
148163
# ---------------------
164+
# Effective (bold) and Speed (thin) Radius together
149165
n_copy.median_filter(2, "time", "radius_e")
150166
n_copy.median_filter(2, "time", "radius_s")
151167
for b0, b1 in [
@@ -167,14 +183,16 @@ def update_axes(ax, mappable=None):
167183
)
168184

169185
# %%
170-
# Parameter timeline
171-
# ------------------
186+
# Parameters timeline
187+
# -------------------
188+
# Effective Radius
172189
kw = dict(s=35, cmap=plt.get_cmap("Spectral_r", 8), zorder=10)
173190
ax = timeline_axes()
174191
m = close_to_i3.scatter_timeline(ax, "radius_e", factor=1e-3, vmin=20, vmax=100, **kw)
175192
cb = update_axes(ax, m["scatter"])
176193
cb.set_label("Effective radius (km)")
177194
# %%
195+
# Shape error
178196
ax = timeline_axes()
179197
m = close_to_i3.scatter_timeline(ax, "shape_error_e", vmin=14, vmax=70, **kw)
180198
cb = update_axes(ax, m["scatter"])

examples/16_network/pet_relative.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,20 @@
1919
e.lon[:] = (e.lon + 180) % 360 - 180
2020
e.contour_lon_e[:] = ((e.contour_lon_e.T - e.lon + 180) % 360 - 180 + e.lon).T
2121
e.contour_lon_s[:] = ((e.contour_lon_s.T - e.lon + 180) % 360 - 180 + e.lon).T
22-
##############
22+
# %%
23+
# Do segmentation
24+
# ---------------
25+
# Segmentation based on maximum overlap, temporal window for candidates = 5 days
2326
n = NetworkObservations.from_split_network(e, e.split_network(intern=False, window=5))
2427

2528
# %%
2629
# Timeline
2730
# --------
2831

2932
# %%
30-
# Display timeline
33+
# Display timeline with events
34+
# A segment generated by a splitting is marked with a star
35+
# A segment merging in another is marked with an exagon
3136
fig = plt.figure(figsize=(15, 5))
3237
ax = fig.add_axes([0.04, 0.04, 0.92, 0.92])
3338
_ = n.display_timeline(ax)
@@ -39,27 +44,34 @@
3944
_ = n.display_timeline(ax, event=False)
4045

4146
# %%
42-
# Timeline by latitude mean
47+
# Timeline by mean latitude
4348
# -------------------------
49+
# Display timeline with the mean latitude of the segments in yaxis
4450
fig = plt.figure(figsize=(15, 5))
4551
ax = fig.add_axes([0.04, 0.04, 0.92, 0.92])
52+
ax.set_ylabel("Latitude")
4653
_ = n.display_timeline(ax, field="latitude")
4754

4855
# %%
49-
# Timeline by radius mean
56+
# Timeline by mean Effective Radius
5057
# -----------------------
58+
# The factor argument is applied on the chosen field
5159
fig = plt.figure(figsize=(15, 5))
5260
ax = fig.add_axes([0.04, 0.04, 0.92, 0.92])
53-
_ = n.display_timeline(ax, field="radius_e")
61+
ax.set_ylabel("Effective Radius (km)")
62+
_ = n.display_timeline(ax, field="radius_e", factor=1e-3)
5463

5564
# %%
5665
# Timeline by latitude
5766
# --------------------
67+
# Use `method="all"` to display the consecutive values of the field
5868
fig = plt.figure(figsize=(15, 5))
5969
ax = fig.add_axes([0.04, 0.05, 0.92, 0.92])
70+
ax.set_ylabel("Latitude")
6071
_ = n.display_timeline(ax, field="lat", method="all")
6172

6273
# %%
74+
# You can filter the data, here with a time window of 15 days
6375
fig = plt.figure(figsize=(15, 5))
6476
ax = fig.add_axes([0.04, 0.05, 0.92, 0.92])
6577
n_copy = n.copy()
@@ -69,6 +81,8 @@
6981
# %%
7082
# Parameters timeline
7183
# -------------------
84+
# Scatter is usefull to display the parameters' temporal evolution
85+
# Effective Radius and Amplitude
7286
kw = dict(s=25, cmap="Spectral_r", zorder=10)
7387
fig = plt.figure(figsize=(15, 8))
7488
ax = fig.add_axes([0.04, 0.54, 0.90, 0.44])
@@ -86,6 +100,7 @@
86100
cb.set_label("Amplitude (cm)")
87101

88102
# %%
103+
# Speed
89104
fig = plt.figure(figsize=(15, 5))
90105
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88])
91106
m = n.scatter_timeline(ax, "speed_average", factor=100, vmin=0, vmax=40, **kw)
@@ -95,6 +110,7 @@
95110
cb.set_label("Maximum speed (cm/s)")
96111

97112
# %%
113+
# Speed Radius
98114
fig = plt.figure(figsize=(15, 5))
99115
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88])
100116
m = n.scatter_timeline(ax, "radius_s", factor=1e-3, vmin=20, vmax=100, **kw)
@@ -106,7 +122,10 @@
106122
# %%
107123
# Remove dead branch
108124
# ------------------
109-
# Remove all tiny segment with less than N obs which didn't join two segments
125+
# Remove all tiny segments with less than N obs which didn't join two segments
126+
#
127+
# .. warning::
128+
# Must be explore, no solution to solve all the case
110129

111130
n_clean = n.remove_dead_end(nobs=10)
112131
fig = plt.figure(figsize=(15, 8))
@@ -120,6 +139,7 @@
120139
# %%
121140
# Keep close relative
122141
# -------------------
142+
# When you want to investigate one particular observation and select only the closest segments
123143
# First choose an observation in the network
124144
fig = plt.figure(figsize=(15, 5))
125145
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88])
@@ -130,6 +150,7 @@
130150
_ = ax.plot(*obs_args, **obs_kw)
131151

132152
# %%
153+
# Colors show the relative order of the segment with regards to the chosen one
133154
fig = plt.figure(figsize=(15, 5))
134155
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88])
135156
m = n.scatter_timeline(
@@ -141,18 +162,21 @@
141162
)
142163
cb.set_label("Relative order")
143164
# %%
165+
# You want to keep only the segments at the order 1
144166
fig = plt.figure(figsize=(15, 5))
145167
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88])
146168
close_to_i1 = n.relative(i, order=1)
147169
ax.set_title(f"Close segments ({close_to_i1.infos()})")
148170
_ = close_to_i1.display_timeline(ax)
149171
# %%
172+
# You want to keep the segments until order 2
150173
fig = plt.figure(figsize=(15, 5))
151174
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88])
152175
close_to_i2 = n.relative(i, order=2)
153176
ax.set_title(f"Close segments ({close_to_i2.infos()})")
154177
_ = close_to_i2.display_timeline(ax)
155178
# %%
179+
# You want to keep the segments until order 3
156180
fig = plt.figure(figsize=(15, 5))
157181
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88])
158182
close_to_i3 = n.relative(i, order=3)
@@ -162,6 +186,7 @@
162186
# %%
163187
# Display track on map
164188
# --------------------
189+
# Only a map can be tricky to understand, with a timeline it's easier!
165190
fig = plt.figure(figsize=(15, 8))
166191
ax = fig.add_axes([0.04, 0.06, 0.94, 0.88], projection="full_axes")
167192
close_to_i2.plot(ax, color_cycle=close_to_i2.COLORS)
@@ -173,6 +198,7 @@
173198
# %%
174199
# Get merging event
175200
# -----------------
201+
# Display the position of the eddies after a merging
176202
fig = plt.figure(figsize=(15, 8))
177203
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88], projection="full_axes")
178204
merging = close_to_i2.merging_event()
@@ -183,6 +209,7 @@
183209
# %%
184210
# Get spliting event
185211
# ------------------
212+
# Display the position of the eddies before a splitting
186213
fig = plt.figure(figsize=(15, 8))
187214
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88], projection="full_axes")
188215
spliting = close_to_i2.spliting_event()
@@ -193,6 +220,7 @@
193220
# %%
194221
# Get birth event
195222
# ------------------
223+
# Display the starting position of non-splitted eddies
196224
fig = plt.figure(figsize=(15, 8))
197225
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88], projection="full_axes")
198226
birth = close_to_i2.birth_event()
@@ -203,6 +231,7 @@
203231
# %%
204232
# Get death event
205233
# ------------------
234+
# Display the last position of non-merged eddies
206235
fig = plt.figure(figsize=(15, 8))
207236
ax = fig.add_axes([0.04, 0.06, 0.90, 0.88], projection="full_axes")
208237
death = close_to_i2.death_event()

0 commit comments

Comments
 (0)