6
6
import numpy as np
7
7
import xarray as xr
8
8
9
- from slcl1butils .legacy_ocean .ocean .xPolarSpectrum import find_closest_ww3
9
+ from slcl1butils .legacy_ocean .ocean .xPolarSpectrum import haversine
10
10
11
11
# from ocean.xspectrum import from_ww3
12
12
# from ocean.xPolarSpectrum import find_closest_ww3
15
15
from slcl1butils .symmetrize_l1b_spectra import symmetrize_xspectrum
16
16
from slcl1butils .utils import xndindex
17
17
18
+ COLOC_LIMIT_SPACE = 100 # km
19
+ COLOC_LIMIT_TIME = 3 # hours
20
+ INDEX_WW3_FILL_VALUE = - 999
21
+
22
+
23
+ def check_colocation (cartesianspWW3 , lon , lat , time ):
24
+ """
25
+ from information associated to the closest WW3 spectra found, check whether it is a usable co-location or not.
26
+ and add co-location score information
27
+
28
+ Args:
29
+ cartesianspWW3 (xr.DataArray): closest cartesian wave spectra WW3 found (could be too far for colocation)
30
+ lon (float): longitude of interest (eg SAR)
31
+ lat (float): latitude of interest (eg SAR)
32
+ time (datetime.datetime or tuple of int): Tuple of the form (year, month, day, hour, minute, second) (eg SAR)
33
+
34
+
35
+ Returns:
36
+ (xr.DataArray): time index of spatio-temporal closest point in the WW3 file
37
+ """
38
+ coloc_ds = xr .Dataset ()
39
+ mytime = (
40
+ np .datetime64 (time )
41
+ if type (time ) == datetime .datetime
42
+ else np .datetime64 (datetime .datetime (* time ))
43
+ )
44
+ # time_dist = np.abs(cartesianspWW3.time - mytime)
45
+
46
+ # isel = np.where(time_dist == time_dist.min())
47
+ closest_dist_in_space = haversine (
48
+ lon ,
49
+ lat ,
50
+ cartesianspWW3 .attrs ["longitude" ],
51
+ cartesianspWW3 .attrs ["latitude" ],
52
+ )
53
+ # spatial_dist = haversine(
54
+ # lon,
55
+ # lat,
56
+ # ww3spds[{"time": isel[0]}].longitude,
57
+ # ww3spds[{"time": isel[0]}].latitude,
58
+ # )
59
+ # logging.debug(spatial_dist)
60
+ # relative_index = np.argmin(spatial_dist.data)
61
+ # absolute_index = isel[0][relative_index]
62
+ # closest_dist_in_space = spatial_dist[relative_index].data
63
+ # time_dist_minutes = (ww3spec[{"time": absolute_index}].time - mytime).data / (1e9 * 60)
64
+ # time_dist_minutes = (
65
+ # ww3spds[{"time": absolute_index}].time - mytime
66
+ # ) / np.timedelta64(1, "m")
67
+ time_dist_minutes = (cartesianspWW3 .time - mytime ) / np .timedelta64 (1 , "m" )
68
+ logging .debug (
69
+ "Wave Watch III closest point @ {} km and {} minutes" .format (
70
+ closest_dist_in_space , time_dist_minutes
71
+ )
72
+ )
73
+ if (
74
+ abs (time_dist_minutes ) > COLOC_LIMIT_TIME * 60
75
+ or closest_dist_in_space > COLOC_LIMIT_SPACE
76
+ ):
77
+ logging .debug (
78
+ "closest in time then in space is beyond the limits -> No ww3 spectra will be associated "
79
+ )
80
+ absolute_index = INDEX_WW3_FILL_VALUE
81
+ ww3_lon = np .nan
82
+ ww3_lat = np .nan
83
+ ww3_date = np .nan
84
+ selection = xr .DataArray (
85
+ absolute_index ,
86
+ attrs = {
87
+ "method" : "closest in time then in space" ,
88
+ "limit_of_selection_in_space" : "%f km" % COLOC_LIMIT_SPACE ,
89
+ "limit_of_selection_in_time" : "%f hours" % COLOC_LIMIT_TIME ,
90
+ "description" : "index of the WW3 spectra selected (None=no WW3 spectra found)" ,
91
+ },
92
+ )
93
+ else :
94
+ # ww3_lon = ww3spds[{"time": isel[0]}].longitude.data[relative_index]
95
+ # ww3_lat = ww3spds[{"time": isel[0]}].latitude.data[relative_index]
96
+ # ww3_date = ww3spds[{"time": absolute_index}].time
97
+ ww3_lon = cartesianspWW3 .attrs ["longitude" ]
98
+ ww3_lat = cartesianspWW3 .attrs ["latitude" ]
99
+ ww3_date = cartesianspWW3 .time
100
+ selection = xr .DataArray (
101
+ cartesianspWW3 .attrs ["time_index" ],
102
+ attrs = {
103
+ "method" : "closest in time then in space" ,
104
+ "limit_of_selection_in_space" : "%f km" % COLOC_LIMIT_SPACE ,
105
+ "limit_of_selection_in_time" : "%f hours" % COLOC_LIMIT_TIME ,
106
+ "description" : "index of the WW3 spectra selected (None=no WW3 spectra found)" ,
107
+ "_FillValue" : INDEX_WW3_FILL_VALUE ,
108
+ },
109
+ )
110
+ coloc_ds ["WW3spectra_index" ] = selection
111
+ coloc_ds ["WW3spectra_delta_time" ] = xr .DataArray (
112
+ time_dist_minutes ,
113
+ attrs = {"description" : "temporal distance (WW3-SAR) in minutes" , "units" : "minutes" },
114
+ )
115
+ coloc_ds ["WW3spectra_delta_space" ] = xr .DataArray (
116
+ closest_dist_in_space ,
117
+ attrs = {
118
+ "description" : "spatial distance between SAR tile center and WW3 spectra grid point (km)" ,
119
+ "units" : "kilometer" ,
120
+ },
121
+ )
122
+ coloc_ds ["WW3spectra_longitude" ] = xr .DataArray (
123
+ ww3_lon , attrs = {"description" : "longitude of colocated WW3 spectra" }
124
+ )
125
+ coloc_ds ["WW3spectra_latitude" ] = xr .DataArray (
126
+ ww3_lat , attrs = {"description" : "latitude of colocated WW3 spectra" }
127
+ )
128
+ coloc_ds ["WW3spectra_time" ] = xr .DataArray (
129
+ ww3_date , attrs = {"description" : "time associated to colocated WW3 spectra" }
130
+ )
131
+ coloc_ds ["WW3spectra_path" ] = xr .DataArray (
132
+ cartesianspWW3 .attrs ["pathWW3" ],
133
+ attrs = {"description" : "file path used to colocate WW3 spectra" },
134
+ )
135
+ return coloc_ds
136
+
18
137
19
138
def resampleWW3spectra_on_TOPS_SAR_cartesian_grid (dsar , xspeckind ):
20
139
"""
@@ -67,6 +186,7 @@ def resampleWW3spectra_on_TOPS_SAR_cartesian_grid(dsar, xspeckind):
67
186
68
187
list_ww3_cart_sp = []
69
188
list_ww3_efth_sp = []
189
+ list_ww3_coloc_sp_ds = []
70
190
dk_az = np .diff (xsSAR ["k_az" ])
71
191
dk_rg = np .diff (xsSAR ["k_rg" ])
72
192
dk = (dk_rg .mean (), dk_az .mean ())
@@ -80,10 +200,12 @@ def resampleWW3spectra_on_TOPS_SAR_cartesian_grid(dsar, xspeckind):
80
200
if pathww3sp :
81
201
if os .path .exists (pathww3sp ):
82
202
flag_ww3spectra_found = True
203
+
83
204
dsww3raw = xr .open_dataset (pathww3sp )
84
205
for i in xndindex (gridsar ):
85
206
lonsar = dsar ["longitude" ][i ].values
86
207
latsar = dsar ["latitude" ][i ].values
208
+ sensing_time = dsar ["sensing_time" ][i ].values
87
209
heading = dsar ["ground_heading" ][i ].values
88
210
logging .debug ("heading %s" , heading )
89
211
logging .debug ("timesar :%s" , start_date_dt )
@@ -100,37 +222,61 @@ def resampleWW3spectra_on_TOPS_SAR_cartesian_grid(dsar, xspeckind):
100
222
clockwise_to_trigo = True ,
101
223
lon = lonsar ,
102
224
lat = latsar ,
103
- time = start_date_dt ,
104
- ) # TODO use sensingTime
105
- ds_ww3_cartesian .attrs ["source" ] = "ww3"
106
- # TODO: check kx ky names to be same as the one from intra burst ds
107
- indiceww3spectra = find_closest_ww3 (
108
- ww3_path = pathww3sp , lon = lonsar , lat = latsar , time = start_date_dt
109
- )
110
- # add the raw EFTH(f,dir) spectra from WW3
111
- rawspww3 = (
112
- dsww3raw ["efth" ]
113
- .isel (time = indiceww3spectra )
114
- .rename ("ww3EFTHraw" )
225
+ time = sensing_time ,
115
226
)
116
- rawspww3 .attrs ["description " ] = "raw EFTH(f,dir) spectra "
117
- ds_ww3_cartesian = ds_ww3_cartesian . swap_dims (
118
- { "kx" : "k_rg" , "ky" : "k_az" }
119
- ). T
120
- rawspww3 = rawspww3 . assign_coords ( i )
121
- rawspww3 = rawspww3 . expand_dims ([ "tile_line" , "tile_sample" ])
122
- # rawspww3 = rawspww3.expand_dims(["burst", "tile_line", "tile_sample"])
123
- ds_ww3_cartesian = ds_ww3_cartesian . assign_coords ( i )
124
- ds_ww3_cartesian = ds_ww3_cartesian . expand_dims (
125
- [ "tile_line" , "tile_sample" ]
227
+ ds_ww3_cartesian .attrs ["source " ] = "ww3 "
228
+ ds_ww3_cartesian . attrs [
229
+ "description"
230
+ ] = "WW3spectra_EFTHraw resampled on SAR cartesian grid"
231
+ ds_ww3_cartesian = ds_ww3_cartesian . rename ( "WW3spectra_EFTHcart" )
232
+ colocww3sp_ds = check_colocation (
233
+ cartesianspWW3 = ds_ww3_cartesian ,
234
+ lon = lonsar ,
235
+ lat = latsar ,
236
+ time = start_date_dt ,
126
237
)
127
- # ds_ww3_cartesian = ds_ww3_cartesian.expand_dims(["burst", "tile_line", "tile_sample"])
128
- list_ww3_cart_sp .append (ds_ww3_cartesian )
129
- list_ww3_efth_sp .append (rawspww3 )
238
+ del ds_ww3_cartesian .attrs ["longitude" ]
239
+ del ds_ww3_cartesian .attrs ["latitude" ]
240
+ if colocww3sp_ds ["WW3spectra_index" ].data != INDEX_WW3_FILL_VALUE :
241
+ # add the raw EFTH(f,dir) spectra from WW3
242
+ rawspww3 = (
243
+ dsww3raw ["efth" ]
244
+ .isel (time = colocww3sp_ds ["WW3spectra_index" ].data )
245
+ .rename ("WW3spectra_EFTHraw" )
246
+ )
247
+ rawspww3 .attrs [
248
+ "description"
249
+ ] = "colocated raw EFTH(f,dir) WAVEWATCH III wave height spectra"
250
+ colocww3sp_ds = colocww3sp_ds .assign_coords (i )
251
+ colocww3sp_ds = colocww3sp_ds .expand_dims (
252
+ ["tile_line" , "tile_sample" ]
253
+ )
254
+ list_ww3_coloc_sp_ds .append (colocww3sp_ds )
255
+
256
+ ds_ww3_cartesian = ds_ww3_cartesian .swap_dims (
257
+ {"kx" : "k_rg" , "ky" : "k_az" }
258
+ ).T
259
+ rawspww3 = rawspww3 .assign_coords (i )
260
+ rawspww3 = rawspww3 .expand_dims (["tile_line" , "tile_sample" ])
261
+ ds_ww3_cartesian = ds_ww3_cartesian .assign_coords (i )
262
+ ds_ww3_cartesian = ds_ww3_cartesian .expand_dims (
263
+ ["tile_line" , "tile_sample" ]
264
+ )
265
+ list_ww3_cart_sp .append (ds_ww3_cartesian )
266
+ list_ww3_efth_sp .append (rawspww3 )
267
+ flag_ww3spectra_added = True
130
268
ds_ww3_cartesian_merged = xr .merge (list_ww3_cart_sp )
131
269
ds_ww3_efth_merged = xr .merge (list_ww3_efth_sp )
132
- dsar = xr .merge ([dsar , ds_ww3_cartesian_merged , ds_ww3_efth_merged ])
133
- flag_ww3spectra_added = True
270
+ ds_ww3_coloc_merged = xr .merge (list_ww3_coloc_sp_ds )
271
+
272
+ dsar = xr .merge (
273
+ [
274
+ dsar ,
275
+ ds_ww3_cartesian_merged ,
276
+ ds_ww3_efth_merged ,
277
+ ds_ww3_coloc_merged ,
278
+ ]
279
+ )
134
280
if xspeckind == "intra" :
135
281
dsar = dsar .drop_vars (["xspectra_2tau_Re" , "xspectra_2tau_Im" ])
136
282
elif xspeckind == "inter" :
0 commit comments