66from  py_eddy_tracker  import  EddyParser 
77from  glob  import  glob 
88from  yaml  import  load  as  yaml_load 
9+ from  py_eddy_tracker .tracking  import  \
10+     Correspondance 
911from  py_eddy_tracker .observations  import  \
1012    EddiesObservations , TrackEddiesObservations , \
1113    VirtualEddiesObservations 
1214
1315import  logging 
14- import  numpy  as  np 
16+ from  numpy  import  array , arange , bool_ , uint16 , unique , setdiff1d , \
17+     ones , zeros 
1518import  datetime  as  dt 
1619
1720
18- D2R  =  0.017453292519943295 
1921UINT32_MAX  =  4294967295 
2022UINT16_MAX  =  65535 
23+ # ID limit to 4294967295 
24+ ID_DTYPE  =  'u4' 
25+ # Track limit to 65535 
26+ N_DTYPE  =  'u2' 
27+ # Prolongation limit to 255 
28+ VIRTUAL_DTYPE  =  'u1' 
2129
2230
23- if  __name__  ==  '__main__' :
31+ def  usage ():
32+     """Usage 
33+     """ 
2434    # Run using: 
25-     PARSER  =  EddyParser (
35+     parser  =  EddyParser (
2636        "Tool to use identification step to compute tracking" )
27-     PARSER .add_argument ('yaml_file' ,
37+     parser .add_argument ('yaml_file' ,
2838                        help = 'Yaml file to configure py-eddy-tracker' )
29-     YAML_FILE  =  PARSER .parse_args ().yaml_file 
39+     yaml_file  =  parser .parse_args ().yaml_file 
3040
3141    # Read yaml configuration file 
32-     with  open (YAML_FILE , 'r' ) as  stream :
33-         CONFIG  =  yaml_load (stream )
42+     with  open (yaml_file , 'r' ) as  stream :
43+         config  =  yaml_load (stream )
44+     return  config 
45+ 
46+ 
47+ if  __name__  ==  '__main__' :
48+     CONFIG  =  usage ()
3449
3550    NB_OBS_MIN  =  int (CONFIG ['TRACK_DURATION_MIN' ])
3651    NB_VIRTUAL_OBS_MAX_BY_SEGMENT  =  int (CONFIG ['VIRTUAL_LEGNTH_MAX' ])
52+     
53+     ACTIVE_VIRTUAL  =  NB_VIRTUAL_OBS_MAX_BY_SEGMENT  >  0 
3754
3855    PATTERN  =  CONFIG ['PATHS' ]['FILES_PATTERN' ]
3956    FILENAMES  =  glob (PATTERN )
4057    FILENAMES .sort ()
4158
42-     e_previous  =  EddiesObservations .load_from_netcdf (FILENAMES [0 ])
43- 
4459    START_TIME  =  dt .datetime .now ()
4560    logging .info ('Start tracking on %d files' , len (FILENAMES ))
61+ 
4662    # To count id tracks 
4763    CURRENT_ID  =  0 
64+     # Will contain all correspondance between each step 
4865    CORRESPONDANCES  =  []
4966    START  =  True 
5067    FLG_VIRTUAL  =  False 
68+     
69+     # Dtype for correpondance 
70+     STANDARD_DTYPE  =  [
71+         ('in' , 'u2' ),
72+         ('out' , 'u2' ),
73+         ('id' , ID_DTYPE )]
74+ 
75+     if  ACTIVE_VIRTUAL :
76+         STANDARD_DTYPE  +=  [
77+             ('virtual' , bool_ ),
78+             ('virtual_length' , VIRTUAL_DTYPE )]
79+ 
80+     # Init 
81+     e_previous  =  EddiesObservations .load_from_netcdf (FILENAMES [0 ])
5182
83+     # We begin with second file, first one is in previous 
5284    for  file_name  in  FILENAMES [1 :]:
5385        logging .debug ('%s match with previous state' , file_name )
5486        e_current  =  EddiesObservations .load_from_netcdf (file_name )
@@ -60,35 +92,29 @@ if __name__ == '__main__':
6092                          len (virtual_obs ))
6193            # If you comment this the virtual fonctionnality will be disable 
6294            e_previous  =  e_previous .merge (virtual_obs )
63-         dist   =   e_previous . distance ( e_current ) 
64-         i_previous , i_current  =  np . where ( dist   <   20. )
95+         
96+         i_previous , i_current  =  e_previous . tracking ( e_current )
6597        nb_match  =  i_previous .shape [0 ]
6698
67-         logging .debug ('%d match with previous' , nb_match )
68-         correspondance  =  np .array (
69-             i_previous ,
70-             dtype = [
71-                 ('in' , 'u2' ),
72-                 ('out' , 'u2' ),
73-                 ('id' , 'u4' ),
74-                 ('virtual' , np .bool_ ),
75-                 ('virtual_length' , 'u1' )])
99+         #~ Correspondance() 
100+         correspondance  =  array (i_previous , dtype = STANDARD_DTYPE )
76101        correspondance ['out' ] =  i_current 
77102
78-         if  FLG_VIRTUAL :
79-             correspondance ['virtual' ] =  i_previous  >=  nb_real_obs 
80-         else :
81-             correspondance ['virtual' ] =  False 
103+         if  ACTIVE_VIRTUAL :
104+             if  FLG_VIRTUAL :
105+                 correspondance ['virtual' ] =  i_previous  >=  nb_real_obs 
106+             else :
107+                 correspondance ['virtual' ] =  False 
82108
83109        if  START :
84110            START  =  False 
85111            # Set an id for each match 
86-             correspondance ['id' ] =  np . arange (nb_match )
112+             correspondance ['id' ] =  arange (nb_match )
87113            # Set counter 
88114            CURRENT_ID  +=  nb_match 
89115        else :
90116            # We set all id to UINT32_MAX 
91-             id_previous  =  np . ones (len (e_previous ), dtype = 'u4' ) *  UINT32_MAX 
117+             id_previous  =  ones (len (e_previous ), dtype = ID_DTYPE ) *  UINT32_MAX 
92118            # We get old id for previously eddies tracked 
93119            previous_id  =  CORRESPONDANCES [- 1 ]['id' ]
94120            id_previous [CORRESPONDANCES [- 1 ]['out' ]] =  previous_id 
@@ -110,7 +136,7 @@ if __name__ == '__main__':
110136            if  FLG_VIRTUAL :
111137                # Save previous state to count virtual obs 
112138                previous_virtual_obs  =  virtual_obs 
113-                 virtual_dead_id  =  np . setdiff1d (virtual_obs .obs ['track' ],
139+                 virtual_dead_id  =  setdiff1d (virtual_obs .obs ['track' ],
114140                                               correspondance ['id' ])
115141                list_previous_virtual_id  =  virtual_obs .obs ['track' ].tolist ()
116142                i_virtual_dead_id  =  [
@@ -122,7 +148,7 @@ if __name__ == '__main__':
122148                              'next step' , nb_virtual_prolongate )
123149
124150            # List previous id which are not use in the next step 
125-             dead_id  =  np . setdiff1d (previous_id , correspondance ['id' ])
151+             dead_id  =  setdiff1d (previous_id , correspondance ['id' ])
126152            nb_dead_track  =  len (dead_id )
127153            logging .debug ('%d death of real obs in this step' , nb_dead_track )
128154            # Creation of an virtual step for dead one 
@@ -163,7 +189,7 @@ if __name__ == '__main__':
163189                    ] =  obs_to_prolongate ['segment_size' ]
164190            # Count 
165191            virtual_obs .obs ['segment_size' ] +=  1 
166-             if  NB_VIRTUAL_OBS_MAX_BY_SEGMENT   >   0 :
192+             if  ACTIVE_VIRTUAL :
167193                FLG_VIRTUAL  =  True 
168194            # END 
169195
@@ -173,7 +199,7 @@ if __name__ == '__main__':
173199            nb_new_tracks  =  mask_new_id .sum ()
174200            logging .debug ('%d birth in this step' , nb_new_tracks )
175201            # Set new id 
176-             correspondance ['id' ][mask_new_id ] =  np . arange (
202+             correspondance ['id' ][mask_new_id ] =  arange (
177203                CURRENT_ID , CURRENT_ID  +  nb_new_tracks )
178204            # Set counter 
179205            CURRENT_ID  +=  nb_new_tracks 
@@ -186,12 +212,13 @@ if __name__ == '__main__':
186212    logging .info ('Track finish' )
187213    logging .info ('Start merging' )
188214    # count obs by tracks 
189-     nb_obs_by_tracks  =  np . zeros (CURRENT_ID , dtype = 'u2' ) +  1 
215+     nb_obs_by_tracks  =  zeros (CURRENT_ID , dtype = N_DTYPE ) +  1 
190216    for  correspondance  in  CORRESPONDANCES :
191217        nb_obs_by_tracks [correspondance ['id' ]] +=  1 
192-         # When start is virtual, we don't have a previous correspondance 
193-         nb_obs_by_tracks [correspondance ['id' ][correspondance ['virtual' ]]
194-                          ] +=  correspondance ['virtual_length' ][correspondance ['virtual' ]]
218+         if  ACTIVE_VIRTUAL :
219+             # When start is virtual, we don't have a previous correspondance 
220+             nb_obs_by_tracks [correspondance ['id' ][correspondance ['virtual' ]]
221+                              ] +=  correspondance ['virtual_length' ][correspondance ['virtual' ]]
195222
196223    # Compute index of each tracks 
197224    i_current_by_tracks  =  nb_obs_by_tracks .cumsum () -  nb_obs_by_tracks 
@@ -205,11 +232,11 @@ if __name__ == '__main__':
205232    # Calculate the index in each tracks, we compute in u4 and translate 
206233    # in u2 (which are limited to 65535) 
207234    logging .debug ('Compute global index array (N)' )
208-     n  =  np . arange (nb_obs ,
209-                    dtype = 'u4' ) -  i_current_by_tracks .repeat (nb_obs_by_tracks )
210-     FINAL_EDDIES .obs ['n' ] =  np . uint16 (n )
235+     n  =  arange (nb_obs ,
236+                dtype = 'u4' ) -  i_current_by_tracks .repeat (nb_obs_by_tracks )
237+     FINAL_EDDIES .obs ['n' ] =  uint16 (n )
211238    logging .debug ('Compute global track array' )
212-     FINAL_EDDIES .obs ['track' ] =  np . arange (CURRENT_ID ).repeat (nb_obs_by_tracks )
239+     FINAL_EDDIES .obs ['track' ] =  arange (CURRENT_ID ).repeat (nb_obs_by_tracks )
213240
214241    # Start loading identification again to save in the finals tracks 
215242    # Load first file 
@@ -218,8 +245,8 @@ if __name__ == '__main__':
218245    FINAL_EDDIES .sign_type  =  eddies_previous .sign_type 
219246
220247    # To know if the track start 
221-     first_obs_save_in_tracks  =  np . zeros (i_current_by_tracks .shape ,
222-                                         dtype = np . bool_ )
248+     first_obs_save_in_tracks  =  zeros (i_current_by_tracks .shape ,
249+                                         dtype = bool_ )
223250
224251    for  i , file_name  in  enumerate (FILENAMES [1 :]):
225252        # Load current file (we begin with second one) 
@@ -246,16 +273,18 @@ if __name__ == '__main__':
246273
247274        # Index in the current file 
248275        index_current  =  CORRESPONDANCES [i ]['out' ]
249-         # If the flag virtual in correspondance is active, 
250-         # the previous is virtual 
251-         m_virtual  =  CORRESPONDANCES [i ]['virtual' ]
252-         if  m_virtual .any ():
253-             index_virtual  =  index_final [m_virtual ]
254-             # Incrementing index 
255-             i_current_by_tracks [i_id [m_virtual ]
256-                 ] +=  CORRESPONDANCES [i ]['virtual_length' ][m_virtual ]
257-             # Get new index 
258-             index_final  =  i_current_by_tracks [i_id ]
276+         
277+         if  ACTIVE_VIRTUAL :
278+             # If the flag virtual in correspondance is active, 
279+             # the previous is virtual 
280+             m_virtual  =  CORRESPONDANCES [i ]['virtual' ]
281+             if  m_virtual .any ():
282+                 index_virtual  =  index_final [m_virtual ]
283+                 # Incrementing index 
284+                 i_current_by_tracks [i_id [m_virtual ]
285+                     ] +=  CORRESPONDANCES [i ]['virtual_length' ][m_virtual ]
286+                 # Get new index 
287+                 index_final  =  i_current_by_tracks [i_id ]
259288
260289        # Copy all variable 
261290        for  var , _  in  eddies_current .obs .dtype .descr :
@@ -267,28 +296,16 @@ if __name__ == '__main__':
267296        eddies_previous  =  eddies_current 
268297
269298    # We flag obs 
270-     FINAL_EDDIES .obs ['virtual' ] =  FINAL_EDDIES .obs ['time' ] ==  0 
271- 
272-     FINAL_EDDIES .filled_by_interpolation (FINAL_EDDIES .obs ['virtual' ] ==  1 )
273-     # Localization of virtual observation 
274-     m_i  =  FINAL_EDDIES .obs ['virtual' ] ==  1 
275-     # Count virtual observations 
276-     nb_virtual  =  FINAL_EDDIES .obs ['virtual' ].sum ()
277- 
278-     logging .info ('%d obs are virtual (unobserved)' , nb_virtual )
279-     logging .info ('Start extrapolation of values for virtual observations' )
280-     nb_obs  =  len (FINAL_EDDIES )
281-     index  =  np .arange (nb_obs )
282-     for  var , _  in  eddies_current .obs .dtype .descr :
283-         FINAL_EDDIES .obs [var ][m_i ] =  np .interp (
284-             index [m_i ],
285-             index [- m_i ],
286-             FINAL_EDDIES .obs [var ][- m_i ])
299+     if  ACTIVE_VIRTUAL :
300+         FINAL_EDDIES .obs ['virtual' ] =  FINAL_EDDIES .obs ['time' ] ==  0 
301+ 
302+         FINAL_EDDIES .filled_by_interpolation (FINAL_EDDIES .obs ['virtual' ] ==  1 )
287303
288304    # Total running time 
305+     FULL_TIME  =  dt .datetime .now () -  START_TIME 
289306    logging .info ('Mean duration by loop : %s' ,
290-                  ( dt . datetime . now ()  -   START_TIME )  /  (len (FILENAMES ) -  1 ))
291-     logging .info ('Duration : %s' , dt . datetime . now ()  -   START_TIME )
307+                  FULL_TIME  /  (len (FILENAMES ) -  1 ))
308+     logging .info ('Duration : %s' , FULL_TIME )
292309
293310    logging .info ('The longest tracks have %d observations' ,
294311                 nb_obs_by_tracks .max ())
@@ -297,6 +314,6 @@ if __name__ == '__main__':
297314        NB_OBS_MIN , nb_obs_by_tracks .repeat (nb_obs_by_tracks ))
298315
299316    logging .info ('%d tracks will be saved' ,
300-                  len (np . unique (SUBSET_EDDIES .obs ['track' ])))
317+                  len (unique (SUBSET_EDDIES .obs ['track' ])))
301318
302319    SUBSET_EDDIES .write_netcdf ()
0 commit comments