@@ -1001,66 +1001,71 @@ def reshape_mask_eff(self, grd):
10011001
10021002class  RossbyWaveSpeed  (object ):
10031003
1004-     def  __init__ (self , domain , grd , ZERO_CROSSING ,  limits ,  rw_path = None ):
1004+     def  __init__ (self , THE_DOMAIN , grd , RW_PATH = None ):
10051005        """ 
10061006        Initialise the RossbyWaveSpeedsobject 
10071007        """ 
1008-         self .domain  =  domain 
1008+         self .THE_DOMAIN  =  THE_DOMAIN 
10091009        self .M  =  grd .M 
1010-         self .ZERO_CROSSING  =  ZERO_CROSSING 
1011-         self .rw_path  =  rw_path 
1012-         if  self .domain  in  ('Global' , 'ROMS' ):
1013-             assert  self .rw_path  is  not None , \
1010+         self .EARTH_RADIUS  =  grd .EARTH_RADIUS 
1011+         self .ZERO_CROSSING  =  grd .ZERO_CROSSING 
1012+         self .RW_PATH  =  RW_PATH 
1013+         if  self .THE_DOMAIN  in  ('Global' , 'ROMS' ):
1014+             assert  self .RW_PATH  is  not None , \
10141015                'Must supply a path for the Rossby deformation radius data' 
1015-             data  =  np .loadtxt (rw_path )
1016+             data  =  np .loadtxt (RW_PATH )
10161017            self ._lon  =  data [:, 1 ] -  360. 
10171018            self ._lat  =  data [:, 0 ]
10181019            self ._defrad  =  data [:, 3 ]
1019-             self .limits  =  limits 
1020+             self .limits  =  [ grd . LONMIN ,  grd . LONMAX ,  grd . LATMIN ,  grd . LATMAX ] 
10201021            self ._make_subset ()._make_kdtree ()
10211022            self .vartype  =  'variable' 
10221023        else :
10231024            self .vartype  =  'constant' 
10241025        self .distance  =  np .empty (1 )
1026+         self .beta  =  np .empty (1 )
1027+         self .r_spd_long  =  np .empty (1 )
10251028        self .start  =  True 
10261029
10271030
10281031    def  get_rwdistance (self , xpt , ypt , DAYS_BTWN_RECORDS ):
10291032        """ 
10301033        """ 
1031-         if  self .domain  in  ('Global' , 'ROMS' ):
1034+         if  self .THE_DOMAIN  in  ('Global' , 'ROMS' ):
10321035	    #print 'xpt, ypt', xpt, ypt 
1033-             self .distance [:] =  self ._get_c (xpt , ypt )
1036+             self .distance [:] =  self ._get_rlongwave_spd (xpt , ypt )
10341037            self .distance  *=  86400. 
1035-             #if self.domain  in 'ROMS': 
1038+             #if self.THE_DOMAIN  in 'ROMS': 
10361039                #self.distance *= 1.5 
1037-         elif  'BlackSea'  in  self .domain :
1040+         elif  'BlackSea'  in  self .THE_DOMAIN :
10381041            self .distance [:] =  15000.  # e.g., Blokhina & Afanasyev, 2003 
1039-         elif  'MedSea'  in  self .domain :
1042+         elif  'MedSea'  in  self .THE_DOMAIN :
10401043            self .distance [:] =  20000. 
10411044        else :
1042-             Exception  # Unknown domain  
1045+             Exception  # Unknown THE_DOMAIN  
10431046
10441047        if  self .start :
1045-             #print x, y 
1046-             if  x  <  0. :
1047-                 lon  =  "" .join ((str (x ), 'W' ))
1048-             elif  x  >=  0 :
1049-                 lon  =  "" .join ((str (x ), 'E' ))
1050-             if  y  <  0 :
1051-                 lat  =  "" .join ((str (y ), 'S' ))
1052-             elif  y  >=  0 :
1053-                 lat  =  "" .join ((str (y ), 'N' ))
1048+             lon , lat  =  self .M .projtran (xpt , ypt , inverse = True )
1049+             lon , lat  =  np .round (lon , 2 ), np .round (lat , 2 )
1050+             if  lon  <  0. :
1051+                 lon  =  "" .join ((str (lon ), 'W' ))
1052+             elif  lon  >=  0 :
1053+                 lon  =  "" .join ((str (lon ), 'E' ))
1054+             if  lat  <  0 :
1055+                 lat  =  "" .join ((str (lat ), 'S' ))
1056+             elif  lat  >=  0 :
1057+                 lat  =  "" .join ((str (lat ), 'N' ))
10541058
10551059            print  "" .join (('--------- setting ellipse for first tracked ' ,
10561060                           'eddy at %s, %s in the %s domain' 
1057-                             %  (lon , lat , self .domain )))
1058-             print  '--------- using %s Rossby deformation radius of %s m'  \
1059-                                 %  (self .vartype , np .abs (self .distance [0 ]))
1061+                             %  (lon , lat , self .THE_DOMAIN )))
1062+             c  =  np .abs (self ._get_rlongwave_spd (xpt , ypt ))[0 ]
1063+             print  "" .join (('--------- with extratropical long baroclinic' ,
1064+                            'Rossby wave phase speed of %s m/s'  %  c ))
10601065            self .start  =  False 
1061-         self . distance   *=   DAYS_BTWN_RECORDS 
1062-         #print 'aaaa',  self.distance
1063-         return  self .distance 
1066+         
1067+         self . distance   =   np . abs ( self .distance ) 
1068+         return  self .distance   *   DAYS_BTWN_RECORDS 
10641069
10651070
10661071    def  _make_subset (self ):
@@ -1074,7 +1079,7 @@ def _make_subset(self):
10741079                               self ._lat  <=  LATMAX  +  pad )
10751080        self ._lon  =  self ._lon [lloi ]
10761081        self ._lat  =  self ._lat [lloi ]
1077-         self ._c  =  self ._c [lloi ]
1082+         self ._defrad  =  self ._defrad [lloi ]
10781083        self .x , self .y  =  self .M (self ._lon , self ._lat )
10791084        return  self 
10801085
@@ -1085,72 +1090,75 @@ def _make_kdtree(self):
10851090        self ._tree  =  spatial .cKDTree (points )
10861091
10871092
1088-     #def _get_defrad(self, x, y): 
1089-         #""" 
1090-         #Get a point average of the deformation radius 
1091-         #at x, y 
1092-         #""" 
1093-         #weights, i = self._tree.query(np.array([x, y]), k=4, p=2) 
1094-         #weights /= weights.sum() 
1095-         #self._weights = weights 
1096-         #self.i = i 
1097-         #return np.average(self._defrad[i], weights=weights) 
1098-     
1099-     def  _get_c (self , xpt , ypt ):
1093+     def  _get_defrad (self , xpt , ypt ):
11001094        """ 
11011095        Get a point average of the deformation radius 
1102-         at x, y  
1096+         at xpt, ypt  
11031097        """ 
1104-         weights , i  =  self ._tree .query (np .array ([x ,  y ]), k = 4 , p = 2 )
1098+         weights , i  =  self ._tree .query (np .array ([xpt ,  ypt ]), k = 4 , p = 2 )
11051099        weights  /=  weights .sum ()
11061100        self ._weights  =  weights 
11071101        self .i  =  i 
11081102        return  np .average (self ._defrad [i ], weights = weights )
11091103
11101104
1111-     def  _get_rlongwave_spd (self , x ,  y ):
1105+     def  _get_rlongwave_spd (self , xpt ,  ypt ):
11121106        """ 
11131107        Get the longwave phase speed, see Chelton etal (2008) pg 446: 
11141108          c = -beta * defrad**2 (this only for extratropical waves...) 
11151109        """ 
1116-         r_spd_long  =  self ._get_defrad (x , y )
1117-         r_spd_long  *=  1000.  # km to m 
1118-         r_spd_long  **=  2 
1119-         lat  =  np .average (self ._lat [self .i ], weights = self ._weights )
1120-         beta  =  np .cos (np .deg2rad (lat ))
1121-         beta  *=  1458e-7  # 1458e-7 ~ (2 * 7.29*10**-5) 
1122-         beta  /=  6371315.0 
1123-         r_spd_long  *=  - beta 
1124-         return  r_spd_long 
1110+         self .r_spd_long [:] =  self ._get_defrad (xpt , ypt )
1111+         self .r_spd_long  *=  1000.  # km to m 
1112+         self .r_spd_long  **=  2 
1113+         self .beta [:] =  np .average (self ._lat [self .i ],
1114+                                   weights = self ._weights ) # lat 
1115+         self .beta [:] =  np .cos (np .deg2rad (self .beta ))
1116+         self .beta  *=  1458e-7  # 1458e-7 ~ (2 * 7.29*10**-5) 
1117+         self .beta  /=  self .EARTH_RADIUS 
1118+         self .r_spd_long  *=  - self .beta 
1119+         return  self .r_spd_long 
11251120
11261121
11271122
11281123
11291124class  SearchEllipse  (object ):
1130-     
1131-     def  __init__ (self , domain , grd , DAYS_BTWN_RECORDS , ZERO_CROSSING ,
1132-                  rw_path , limits ):
1125+     """ 
1126+     Class to construct a search ellipse/circle around a specified point. 
1127+     See CSS11 Appendix B.4. "Automated eddy tracking" for details. 
1128+     """ 
1129+     def  __init__ (self , THE_DOMAIN , grd , DAYS_BTWN_RECORDS , RW_PATH = None ):
11331130        """ 
1134-         Class to construct a search ellipse/circle around a specified point. 
1131+         Set the constant dimensions of the search ellipse. 
1132+         Instantiate a RossbyWaveSpeed object 
11351133         
1134+         Arguments: 
1135+            
1136+           *THE_DOMAIN*: string 
1137+             Refers to THE_DOMAIN specified in yaml configuration file 
1138+            
1139+           *grd*: An AvisoGrid or RomsGrid object. 
1140+            
1141+           *DAYS_BTWN_RECORDS*: integer 
1142+             Constant defined in yaml configuration file. 
1143+            
1144+           *RW_PATH*: string 
1145+             Path to rossrad.dat file, specified in yaml configuration file. 
11361146        """ 
1137-         self .domain  =  domain 
1147+         self .THE_DOMAIN  =  THE_DOMAIN 
11381148        self .DAYS_BTWN_RECORDS  =  DAYS_BTWN_RECORDS 
1139-         self .ZERO_CROSSING  =  ZERO_CROSSING 
1140-         self .rw_path  =  rw_path 
1141-         self .limits  =  limits 
1142-         self .rw_d_fac  =  1.75 
11431149        self .e_w_major  =  self .DAYS_BTWN_RECORDS  *  3e5  /  7. 
11441150        self .n_s_minor  =  self .DAYS_BTWN_RECORDS  *  2  *  15e4  /  7. 
11451151        self .semi_n_s_minor  =  0.5  *  self .n_s_minor 
1146-         self .rwv  =  RossbyWaveSpeed (domain , grd , ZERO_CROSSING , 
1147-                                 limits ,  rw_path = rw_path )
1148-         self .rw_d  =  np .empty (1 )
1149-         self .rw_d_mod  =  np . empty ( 1 ) 
1152+         self .rwv  =  RossbyWaveSpeed (THE_DOMAIN , grd , RW_PATH = RW_PATH ) 
1153+         self . rw_c   =   np . empty ( 1 )
1154+         self .rw_c_mod  =  np .empty (1 )
1155+         self .rw_c_fac  =  1.75 
11501156
11511157
11521158    def  _set_east_ellipse (self ):
11531159        """ 
1160+         The east_ellipse is a full ellipse, but only its eastern 
1161+         part is used to build the search ellipse. 
11541162        """ 
11551163        self .east_ellipse  =  patch .Ellipse ((self .xpt , self .ypt ),
11561164                                           self .e_w_major , self .n_s_minor )
@@ -1159,14 +1167,17 @@ def _set_east_ellipse(self):
11591167
11601168    def  _set_west_ellipse (self ):
11611169        """ 
1170+         The east_ellipse is a full ellipse, but only its eastern 
1171+         part is used to build the search ellipse. 
11621172        """ 
11631173        self .west_ellipse  =  patch .Ellipse ((self .xpt , self .ypt ),
1164-                                            self .rw_d_mod , self .n_s_minor )
1174+                                            self .rw_c_mod , self .n_s_minor )
11651175        return  self 
11661176
11671177
11681178    def  _set_global_ellipse (self ):
11691179        """ 
1180+          
11701181        """ 
11711182        self ._set_east_ellipse ()._set_west_ellipse ()
11721183        e_verts  =  self .east_ellipse .get_verts ()
@@ -1185,7 +1196,7 @@ def _set_black_sea_ellipse(self):
11851196        """ 
11861197        """ 
11871198        self .black_sea_ellipse  =  patch .Ellipse ((self .x , self .y ),
1188-                                2.  *  self .rw_d_mod , 2.  *  self .rw_d_mod )
1199+                                2.  *  self .rw_c_mod , 2.  *  self .rw_c_mod )
11891200        verts  =  self .black_sea_ellipse .get_verts ()
11901201        self .ellipse_path  =  path .Path (np .array ([verts [:, 0 ],
11911202                                                verts [:, 1 ]]).T )
@@ -1198,26 +1209,21 @@ def set_search_ellipse(self, xpt, ypt):
11981209        self .xpt  =  xpt 
11991210        self .ypt  =  ypt 
12001211
1201-         if  self .domain  in  ('Global' , 'ROMS' ):
1202-             self .rw_d [:] =  self .rwv .get_rwdistance (xpt , ypt ,
1212+         if  self .THE_DOMAIN  in  ('Global' , 'ROMS' ):
1213+             self .rw_c [:] =  self .rwv .get_rwdistance (xpt , ypt ,
12031214                                  self .DAYS_BTWN_RECORDS )
1204-             #print self.rw_d 
1205-             #exit() 
1206-             self .rw_d_mod [:] =  1.75 
1207-             self .rw_d_mod  *=  self .rw_d 
1208-             self .rw_d_mod [:] =  np .array ([self .rw_d_mod ,
1215+             self .rw_c_mod [:] =  1.75 
1216+             self .rw_c_mod  *=  self .rw_c 
1217+             self .rw_c_mod [:] =  np .array ([self .rw_c_mod ,
12091218                                         self .semi_n_s_minor ]).max ()
1210-             
1211-             #print self.rw_d_mod, self.semi_n_s_minor 
1212-             
1213-             self .rw_d_mod  *=  2. 
1219+             self .rw_c_mod  *=  2. 
12141220            self ._set_global_ellipse ()
12151221
1216-         elif  'BlackSea'   in  self .domain :
1217-             self .rw_d_mod [:] =  1.75 
1218-             self .rw_d [:] =  self .rwv .get_rwdistance (x , y ,
1219-                                                     self .DAYS_BTWN_RECORDS )
1220-             self .rw_d_mod  *=  self .rw_d 
1222+         elif  'BlackSea'   in  self .THE_DOMAIN :
1223+             self .rw_c_mod [:] =  1.75 
1224+             self .rw_c [:] =  self .rwv .get_rwdistance (x , y ,
1225+                                    self .DAYS_BTWN_RECORDS )
1226+             self .rw_c_mod  *=  self .rw_c 
12211227            self ._set_black_sea_ellipse ()
12221228
12231229        else :
@@ -1232,7 +1238,7 @@ def view_search_ellipse(self, Eddy):
12321238        """ 
12331239        plt .figure ()
12341240        ax  =  plt .subplot ()
1235-         #ax.set_title('Rossby def. rad %s m' %self.rw_d [0]) 
1241+         #ax.set_title('Rossby def. rad %s m' %self.rw_c [0]) 
12361242        Eddy .M .scatter (self .xpt , self .ypt , c = 'b' )
12371243        Eddy .M .plot (self .ellipse_path .vertices [:, 0 ],
12381244                    self .ellipse_path .vertices [:, 1 ], 'r' )
@@ -1242,7 +1248,6 @@ def view_search_ellipse(self, Eddy):
12421248                             labels = [1 , 0 , 0 , 0 ], ax = ax )
12431249        Eddy .M .drawmeridians (np .arange (- 360 , 360.  +  stride , stride ),
12441250                             labels = [0 , 0 , 0 , 1 ], ax = ax )
1245-         #plt.axis('image') 
12461251        plt .show ()
12471252
12481253
0 commit comments