Skip to content

Commit 49adbd2

Browse files
committed
update eddy anim to interact with keyboard
1 parent f1e56ad commit 49adbd2

File tree

1 file changed

+115
-67
lines changed

1 file changed

+115
-67
lines changed

src/py_eddy_tracker/appli.py

Lines changed: 115 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,12 @@
2121
===========================================================================
2222
"""
2323

24-
from numpy import arange
24+
from numpy import arange, empty
2525
from matplotlib import pyplot
2626
from netCDF4 import Dataset
2727
from matplotlib.collections import LineCollection
2828
from py_eddy_tracker.poly import create_vertice
29+
from py_eddy_tracker.generic import flatten_line_matrix
2930
from py_eddy_tracker import EddyParser
3031
from py_eddy_tracker.observations.tracking import TrackEddiesObservations
3132

@@ -61,8 +62,118 @@ def merge_eddies():
6162
obs.write_file(filename=args.out)
6263

6364

65+
class Anim:
66+
def __init__(self, eddy, intern, **kwargs):
67+
self.eddy = eddy
68+
x_name, y_name = eddy.intern(intern)
69+
self.t, self.x, self.y = eddy.time, eddy[x_name], eddy[y_name]
70+
self.pause = False
71+
self.period = self.eddy.period
72+
self.setup(**kwargs)
73+
74+
def setup(self, cmap="jet", nb_step=25):
75+
cmap = pyplot.get_cmap(cmap)
76+
self.colors = cmap(arange(nb_step + 1) / nb_step)
77+
self.nb_step = nb_step
78+
79+
x_min, x_max = self.x.min(), self.x.max()
80+
d_x = x_max - x_min
81+
x_min -= 0.05 * d_x
82+
x_max += 0.05 * d_x
83+
y_min, y_max = self.y.min(), self.y.max()
84+
d_y = y_max - y_min
85+
y_min -= 0.05 * d_y
86+
y_max += 0.05 * d_y
87+
88+
# plot
89+
self.fig = pyplot.figure()
90+
self.ax = self.fig.add_axes((0.05, 0.05, 0.9, 0.9))
91+
self.ax.set_xlim(x_min, x_max), self.ax.set_ylim(y_min, y_max)
92+
self.ax.set_aspect("equal")
93+
self.ax.grid()
94+
# init mappable
95+
self.txt = self.ax.text(
96+
x_min + 0.05 * d_x,
97+
y_min + 0.05 * d_y,
98+
"",
99+
zorder=10,
100+
bbox=dict(facecolor="w", alpha=0.85),
101+
)
102+
self.contour = LineCollection([], zorder=1)
103+
self.ax.add_collection(self.contour)
104+
105+
self.fig.canvas.draw()
106+
self.fig.canvas.mpl_connect("key_press_event", self.keyboard)
107+
108+
def show(self, sleep_event=0.1, infinity_loop=False):
109+
pyplot.show(block=False)
110+
# save background for future bliting
111+
self.bg_cache = self.fig.canvas.copy_from_bbox(self.ax.bbox)
112+
loop = True
113+
t0, t1 = self.period
114+
while loop:
115+
self.segs = list()
116+
self.now = t0
117+
while True:
118+
if not self.pause:
119+
self.next()
120+
self.fig.canvas.start_event_loop(sleep_event)
121+
if self.now > t1:
122+
break
123+
if infinity_loop:
124+
self.fig.canvas.start_event_loop(0.5)
125+
else:
126+
loop = False
127+
128+
def next(self):
129+
self.now += 1
130+
return self.draw_contour()
131+
132+
def prev(self):
133+
self.now -= 1
134+
return self.draw_contour()
135+
136+
def draw_contour(self):
137+
t0, t1 = self.period
138+
# select contour for this time step
139+
m = self.t == self.now
140+
self.ax.figure.canvas.restore_region(self.bg_cache)
141+
if m.sum():
142+
self.segs.append(
143+
create_vertice(
144+
flatten_line_matrix(self.x[m]), flatten_line_matrix(self.y[m])
145+
)
146+
)
147+
else:
148+
self.segs.append(empty((0, 2)))
149+
self.contour.set_paths(self.segs)
150+
self.contour.set_color(self.colors[-len(self.segs) :])
151+
self.txt.set_text(f"{t0} -> {self.now} -> {t1}")
152+
self.ax.draw_artist(self.contour)
153+
self.ax.draw_artist(self.txt)
154+
# Remove first segment to keep only T contour
155+
if len(self.segs) > self.nb_step:
156+
self.segs.pop(0)
157+
# paint updated artist
158+
self.ax.figure.canvas.blit(self.ax.bbox)
159+
160+
def keyboard(self, event):
161+
if event.key == "escape":
162+
exit()
163+
elif event.key == " ":
164+
self.pause = not self.pause
165+
elif event.key == "right" and self.pause:
166+
self.next()
167+
elif event.key == "left" and self.pause:
168+
self.segs.pop(-1)
169+
self.segs.pop(-1)
170+
self.prev()
171+
172+
64173
def anim():
65-
parser = EddyParser("Merge eddies")
174+
parser = EddyParser(
175+
"Anim eddy, keyboard shortcut : Escape => exit, SpaceBar => pause, left arrow => t - 1, right arrow => t + 1"
176+
)
66177
parser.add_argument("filename", help="eddy atlas")
67178
parser.add_argument("id", help="Track id to anim", type=int)
68179
parser.add_argument(
@@ -87,68 +198,5 @@ def anim():
87198

88199
atlas = TrackEddiesObservations.load_file(args.filename)
89200
eddy = atlas.extract_ids([args.id])
90-
x_name, y_name = eddy.intern(args.intern)
91-
t0, t1 = eddy.period
92-
t, x, y = eddy.time, eddy[x_name], eddy[y_name]
93-
x_min, x_max = x.min(), x.max()
94-
d_x = x_max - x_min
95-
x_min -= 0.05 * d_x
96-
x_max += 0.05 * d_x
97-
y_min, y_max = y.min(), y.max()
98-
d_y = y_max - y_min
99-
y_min -= 0.05 * d_y
100-
y_max += 0.05 * d_y
101-
102-
# General value
103-
cmap = pyplot.get_cmap(args.cmap)
104-
colors = cmap(arange(args.keep_step + 1) / args.keep_step)
105-
106-
# plot
107-
fig = pyplot.figure()
108-
# manager = plt.get_current_fig_manager()
109-
# fig.window.showMaximized()
110-
ax = fig.add_axes((0.05, 0.05, 0.9, 0.9))
111-
ax.set_xlim(x_min, x_max)
112-
ax.set_ylim(y_min, y_max)
113-
ax.set_aspect("equal")
114-
ax.grid()
115-
# # init mappable
116-
txt = ax.text(16.6, 36.8, "", zorder=10)
117-
c = LineCollection([], zorder=1)
118-
ax.add_collection(c)
119-
120-
fig.canvas.draw()
121-
fig.canvas.mpl_connect("key_press_event", keyboard)
122-
pyplot.show(block=False)
123-
# save background for future bliting
124-
bg_cache = fig.canvas.copy_from_bbox(ax.bbox)
125-
loop = True
126-
while loop:
127-
segs = list()
128-
# display contour every day
129-
for t_ in range(t0, t1 + 1, 1):
130-
fig.canvas.restore_region(bg_cache)
131-
# select contour for this time step
132-
m = t == t_
133-
if m.sum():
134-
segs.append(create_vertice(x[m][0], y[m][0]))
135-
c.set_paths(segs)
136-
c.set_color(colors[-len(segs) :])
137-
txt.set_text(f"{t0} -> {t_} -> {t1}")
138-
ax.draw_artist(c)
139-
ax.draw_artist(txt)
140-
# Remove first segment to keep only T contour
141-
if len(segs) > args.keep_step:
142-
segs.pop(0)
143-
# paint updated artist
144-
fig.canvas.blit(ax.bbox)
145-
fig.canvas.start_event_loop(args.time_sleep)
146-
if args.infinity_loop:
147-
fig.canvas.start_event_loop(0.5)
148-
else:
149-
loop = False
150-
151-
152-
def keyboard(event):
153-
if event.key == "escape":
154-
exit()
201+
a = Anim(eddy, intern=args.intern, cmap=args.cmap, nb_step=args.keep_step)
202+
a.show(sleep_event=args.time_sleep, infinity_loop=args.infinity_loop)

0 commit comments

Comments
 (0)