27
27
===========================================================================
28
28
29
29
"""
30
- from numpy import empty , arange , where , unique , \
31
- interp , ones , bool_ , zeros , array
30
+ from numpy import empty , arange , where , unique , interp , ones , bool_ , zeros , array
32
31
from .. import VAR_DESCR_inv
33
32
import logging
34
33
from datetime import datetime , timedelta
39
38
class TrackEddiesObservations (EddiesObservations ):
40
39
"""Class to practice Tracking on observations
41
40
"""
42
- __slots__ = ('__obs_by_track' , '__first_index_of_track' )
43
41
44
- ELEMENTS = ['lon' , 'lat' , 'radius_s' , 'radius_e' , 'amplitude' , 'speed_radius' , 'time' , 'shape_error_e' ,
45
- 'shape_error_s' , 'nb_contour_selected' , 'height_max_speed_contour' , 'height_external_contour' ,
46
- 'height_inner_contour' , 'cost_association' ]
42
+ __slots__ = ("__obs_by_track" , "__first_index_of_track" )
43
+
44
+ ELEMENTS = [
45
+ "lon" ,
46
+ "lat" ,
47
+ "radius_s" ,
48
+ "radius_e" ,
49
+ "amplitude" ,
50
+ "speed_radius" ,
51
+ "time" ,
52
+ "shape_error_e" ,
53
+ "shape_error_s" ,
54
+ "nb_contour_selected" ,
55
+ "height_max_speed_contour" ,
56
+ "height_external_contour" ,
57
+ "height_inner_contour" ,
58
+ "cost_association" ,
59
+ ]
47
60
48
61
def __init__ (self , * args , ** kwargs ):
49
62
super (TrackEddiesObservations , self ).__init__ (* args , ** kwargs )
@@ -54,73 +67,80 @@ def filled_by_interpolation(self, mask):
54
67
"""Filled selected values by interpolation
55
68
"""
56
69
nb_filled = mask .sum ()
57
- logging .info (' %d obs will be filled (unobserved)' , nb_filled )
70
+ logging .info (" %d obs will be filled (unobserved)" , nb_filled )
58
71
59
72
nb_obs = len (self )
60
73
index = arange (nb_obs )
61
74
62
75
for field in self .obs .dtype .descr :
63
76
var = field [0 ]
64
- if var in ['n' , 'virtual' , 'track' , 'cost_association' ] or var in self .array_variables :
77
+ if (
78
+ var in ["n" , "virtual" , "track" , "cost_association" ]
79
+ or var in self .array_variables
80
+ ):
65
81
continue
66
82
# to normalize longitude before interpolation
67
- if var == ' lon' :
83
+ if var == " lon" :
68
84
lon = self .obs [var ]
69
- first = where (self .obs ['n' ] == 0 )[0 ]
70
- nb_obs = empty (first .shape , dtype = 'u4' )
85
+ first = where (self .obs ["n" ] == 0 )[0 ]
86
+ nb_obs = empty (first .shape , dtype = "u4" )
71
87
nb_obs [:- 1 ] = first [1 :] - first [:- 1 ]
72
88
nb_obs [- 1 ] = lon .shape [0 ] - first [- 1 ]
73
89
lon0 = (lon [first ] - 180 ).repeat (nb_obs )
74
90
self .obs [var ] = (lon - lon0 ) % 360 + lon0
75
- self .obs [var ][mask ] = interp (index [mask ], index [~ mask ], self .obs [var ][~ mask ])
91
+ self .obs [var ][mask ] = interp (
92
+ index [mask ], index [~ mask ], self .obs [var ][~ mask ]
93
+ )
76
94
77
95
def extract_longer_eddies (self , nb_min , nb_obs , compress_id = True ):
78
96
"""Select eddies which are longer than nb_min
79
97
"""
80
98
mask = nb_obs >= nb_min
81
99
nb_obs_select = mask .sum ()
82
- logging .info (' Selection of %d observations' , nb_obs_select )
100
+ logging .info (" Selection of %d observations" , nb_obs_select )
83
101
eddies = TrackEddiesObservations (
84
102
size = nb_obs_select ,
85
103
track_extra_variables = self .track_extra_variables ,
86
104
track_array_variables = self .track_array_variables ,
87
- array_variables = self .array_variables
105
+ array_variables = self .array_variables ,
88
106
)
89
107
eddies .sign_type = self .sign_type
90
108
for field in self .obs .dtype .descr :
91
- logging .debug (' Copy of field %s ...' , field )
109
+ logging .debug (" Copy of field %s ..." , field )
92
110
var = field [0 ]
93
111
eddies .obs [var ] = self .obs [var ][mask ]
94
112
if compress_id :
95
- list_id = unique (eddies .obs [' track' ])
113
+ list_id = unique (eddies .obs [" track" ])
96
114
list_id .sort ()
97
115
id_translate = arange (list_id .max () + 1 )
98
116
id_translate [list_id ] = arange (len (list_id )) + 1
99
- eddies .obs [' track' ] = id_translate [eddies .obs [' track' ]]
117
+ eddies .obs [" track" ] = id_translate [eddies .obs [" track" ]]
100
118
return eddies
101
119
102
120
@property
103
121
def elements (self ):
104
122
elements = super (TrackEddiesObservations , self ).elements
105
- elements .extend ([' track' , 'n' , ' virtual' ])
123
+ elements .extend ([" track" , "n" , " virtual" ])
106
124
return list (set (elements ))
107
125
108
126
def set_global_attr_netcdf (self , h_nc ):
109
127
"""Set global attr
110
128
"""
111
- h_nc .title = 'Cyclonic' if self .sign_type == - 1 else 'Anticyclonic'
112
- h_nc .Metadata_Conventions = 'Unidata Dataset Discovery v1.0'
113
- h_nc .comment = 'Surface product; mesoscale eddies'
114
- h_nc .framework_used = 'https://github.com/AntSimi/py-eddy-tracker'
115
- h_nc .standard_name_vocabulary = 'NetCDF Climate and Forecast (CF) Metadata Convention Standard Name Table'
116
- h_nc .date_created = datetime .now ().strftime ('%Y-%m-%dT%H:%M:%SZ' )
117
- t = h_nc .variables [VAR_DESCR_inv ['j1' ]]
129
+ h_nc .title = "Cyclonic" if self .sign_type == - 1 else "Anticyclonic"
130
+ h_nc .Metadata_Conventions = "Unidata Dataset Discovery v1.0"
131
+ h_nc .comment = "Surface product; mesoscale eddies"
132
+ h_nc .framework_used = "https://github.com/AntSimi/py-eddy-tracker"
133
+ h_nc .standard_name_vocabulary = (
134
+ "NetCDF Climate and Forecast (CF) Metadata Convention Standard Name Table"
135
+ )
136
+ h_nc .date_created = datetime .now ().strftime ("%Y-%m-%dT%H:%M:%SZ" )
137
+ t = h_nc .variables [VAR_DESCR_inv ["j1" ]]
118
138
delta = t .max - t .min + 1
119
- h_nc .time_coverage_duration = ' P%dD' % delta
139
+ h_nc .time_coverage_duration = " P%dD" % delta
120
140
d_start = datetime (1950 , 1 , 1 ) + timedelta (int (t .min ))
121
141
d_end = datetime (1950 , 1 , 1 ) + timedelta (int (t .max ))
122
- h_nc .time_coverage_start = d_start .strftime (' %Y-%m-%dT00:00:00Z' )
123
- h_nc .time_coverage_end = d_end .strftime (' %Y-%m-%dT00:00:00Z' )
142
+ h_nc .time_coverage_start = d_start .strftime (" %Y-%m-%dT00:00:00Z" )
143
+ h_nc .time_coverage_end = d_end .strftime (" %Y-%m-%dT00:00:00Z" )
124
144
125
145
def extract_with_area (self , area , ** kwargs ):
126
146
"""
@@ -132,10 +152,10 @@ def extract_with_area(self, area, **kwargs):
132
152
Returns:
133
153
134
154
"""
135
- mask = (self .latitude > area [' llcrnrlat' ]) * (self .latitude < area [' urcrnrlat' ])
136
- lon0 = area [' llcrnrlon' ]
155
+ mask = (self .latitude > area [" llcrnrlat" ]) * (self .latitude < area [" urcrnrlat" ])
156
+ lon0 = area [" llcrnrlon" ]
137
157
lon = (self .longitude - lon0 ) % 360 + lon0
138
- mask *= (lon > lon0 ) * (lon < area [' urcrnrlon' ])
158
+ mask *= (lon > lon0 ) * (lon < area [" urcrnrlon" ])
139
159
return self .__extract_with_mask (mask , ** kwargs )
140
160
141
161
def extract_with_period (self , period , ** kwargs ):
@@ -181,11 +201,11 @@ def compute_index(self):
181
201
# Doesn't work => core dump with numba, maybe he wait i8 instead of u4
182
202
# self.__first_index_of_track = -ones(s, self.tracks.dtype)
183
203
# self.__obs_by_track = zeros(s, self.observation_number.dtype)
184
- self .__first_index_of_track = - ones (s , 'i8' )
185
- self .__obs_by_track = zeros (s , 'i8' )
186
- logging .debug (' Start computing index ...' )
204
+ self .__first_index_of_track = - ones (s , "i8" )
205
+ self .__obs_by_track = zeros (s , "i8" )
206
+ logging .debug (" Start computing index ..." )
187
207
compute_index (self .tracks , self .__first_index_of_track , self .__obs_by_track )
188
- logging .debug (' ... OK' )
208
+ logging .debug (" ... OK" )
189
209
190
210
@property
191
211
def index_from_track (self ):
@@ -227,7 +247,9 @@ def __extract_with_mask(self, mask, full_path=False, remove_incomplete=False, co
227
247
same object with selected observations
228
248
"""
229
249
if full_path and remove_incomplete :
230
- logging .warning ('Incompatible option, remove_incomplete option will be remove' )
250
+ logging .warning (
251
+ "Incompatible option, remove_incomplete option will be remove"
252
+ )
231
253
remove_incomplete = False
232
254
233
255
if full_path :
@@ -243,22 +265,22 @@ def __extract_with_mask(self, mask, full_path=False, remove_incomplete=False, co
243
265
track_extra_variables = self .track_extra_variables ,
244
266
track_array_variables = self .track_array_variables ,
245
267
array_variables = self .array_variables ,
246
- raw_data = self .raw_data
268
+ raw_data = self .raw_data ,
247
269
)
248
270
new .sign_type = self .sign_type
249
271
if nb_obs == 0 :
250
- logging .warning (' Empty dataset will be created' )
272
+ logging .warning (" Empty dataset will be created" )
251
273
else :
252
274
for field in self .obs .dtype .descr :
253
- logging .debug (' Copy of field %s ...' , field )
275
+ logging .debug (" Copy of field %s ..." , field )
254
276
var = field [0 ]
255
277
new .obs [var ] = self .obs [var ][mask ]
256
278
if compress_id :
257
- list_id = unique (new .obs [' track' ])
279
+ list_id = unique (new .obs [" track" ])
258
280
list_id .sort ()
259
281
id_translate = arange (list_id .max () + 1 )
260
282
id_translate [list_id ] = arange (len (list_id )) + 1
261
- new .obs [' track' ] = id_translate [new .obs [' track' ]]
283
+ new .obs [" track" ] = id_translate [new .obs [" track" ]]
262
284
return new
263
285
264
286
0 commit comments