2121===========================================================================
2222"""
2323
24- from numpy import arange
24+ from numpy import arange , empty
2525from matplotlib import pyplot
2626from netCDF4 import Dataset
2727from matplotlib .collections import LineCollection
2828from py_eddy_tracker .poly import create_vertice
29+ from py_eddy_tracker .generic import flatten_line_matrix
2930from py_eddy_tracker import EddyParser
3031from 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+
64173def 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