21
21
===========================================================================
22
22
"""
23
23
24
- from numpy import arange
24
+ from numpy import arange , empty
25
25
from matplotlib import pyplot
26
26
from netCDF4 import Dataset
27
27
from matplotlib .collections import LineCollection
28
28
from py_eddy_tracker .poly import create_vertice
29
+ from py_eddy_tracker .generic import flatten_line_matrix
29
30
from py_eddy_tracker import EddyParser
30
31
from py_eddy_tracker .observations .tracking import TrackEddiesObservations
31
32
@@ -61,8 +62,118 @@ def merge_eddies():
61
62
obs .write_file (filename = args .out )
62
63
63
64
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
+
64
173
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
+ )
66
177
parser .add_argument ("filename" , help = "eddy atlas" )
67
178
parser .add_argument ("id" , help = "Track id to anim" , type = int )
68
179
parser .add_argument (
@@ -87,68 +198,5 @@ def anim():
87
198
88
199
atlas = TrackEddiesObservations .load_file (args .filename )
89
200
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