30
30
from level1c4pps import (get_encoding , compose_filename ,
31
31
set_header_and_band_attrs_defaults ,
32
32
rename_latitude_longitude ,
33
+ dt64_to_datetime ,
33
34
update_angle_attributes , get_header_attrs ,
34
35
convert_angles )
35
36
import pyspectral # testing that pyspectral is available # noqa: F401
59
60
60
61
61
62
REFL_BANDS = ["M01" , "M02" , "M03" , "M04" , "M05" , "M06" , "M07" , "M08" ,
62
- "M09" ]
63
+ "M09" , "M10" , "M11" , "I01" , "I02" , "I03" ]
63
64
64
65
MBAND_PPS = ["M05" , "M07" , "M09" , "M10" , "M11" , "M12" , "M14" , "M15" , "M16" ]
65
66
@@ -172,12 +173,83 @@ def set_header_and_band_attrs(scene, orbit_n=0):
172
173
scene [band ].attrs ['sun_zenith_angle_correction_applied' ] = 'True'
173
174
return nimg
174
175
176
+ def midnight_scene (scene ):
177
+ """Check if scene passes midnight."""
178
+ start_date = scene ["M05" ].attrs ["start_time" ].strftime ("%Y%m%d" )
179
+ end_date = scene ["M05" ].attrs ["end_time" ].strftime ("%Y%m%d" )
180
+ if start_date == end_date :
181
+ return False
182
+ return True
183
+
184
+
185
+ def get_midnight_line_nr (scene ):
186
+ """Find midnight_line, start_time and new end_time."""
187
+ start_date = scene ["M05" ].attrs ["start_time" ].strftime ("%Y-%m-%d" )
188
+ end_date = scene ["M05" ].attrs ["end_time" ].strftime ("%Y-%m-%d" )
189
+ start_fine_search = len (scene ['scanline_timestamps' ]) - 1 # As default start the fine search from end of time array
190
+ for ind in range (0 , len (scene ['scanline_timestamps' ]), 100 ):
191
+ # Search from the beginning in large chunks (100) and break when we
192
+ # pass midnight.
193
+ dt_obj = dt64_to_datetime (scene ['scanline_timestamps' ].values [:][ind ])
194
+ date_linei = dt_obj .strftime ("%Y-%m-%d" )
195
+ if date_linei == end_date :
196
+ # We just passed midnight stop and search backwards for exact line.
197
+ start_fine_search = ind
198
+ break
199
+ for indj in range (start_fine_search , start_fine_search - 100 , - 1 ):
200
+ # Midnight is in one of the previous 100 lines.
201
+ dt_obj = dt64_to_datetime (scene ['scanline_timestamps' ].values [:][indj ])
202
+ date_linei = dt_obj .strftime ("%Y-%m-%d" )
203
+ if date_linei == start_date :
204
+ # We just passed midnight this is the last line for previous day.
205
+ midnight_linenr = indj
206
+ break
207
+ return midnight_linenr
208
+
209
+
210
+
211
+ def set_exact_time_and_crop (scene , start_line , end_line , time_key = 'scanline_timestamps' ):
212
+ """Crop datasets and update start_time end_time objects."""
213
+ if start_line is None :
214
+ start_line = 0
215
+ if end_line is None :
216
+ end_line = len (scene [time_key ]) - 1
217
+ start_time_dt64 = scene [time_key ].values [start_line ]
218
+ end_time_dt64 = scene [time_key ].values [end_line ]
219
+ start_time = dt64_to_datetime (start_time_dt64 )
220
+ end_time = dt64_to_datetime (end_time_dt64 )
221
+ for ds in BANDNAMES + ANGLE_NAMES + ['latitude' , 'longitude' , 'scanline_timestamps' ]:
222
+ if ds in scene and 'nscn' in scene [ds ].dims :
223
+ scene [ds ] = scene [ds ].isel (nscn = slice (start_line , end_line + 1 ))
224
+ try :
225
+ # Update scene attributes to get the filenames right
226
+ scene [ds ].attrs ['start_time' ] = start_time
227
+ scene [ds ].attrs ['end_time' ] = end_time
228
+ except TypeError :
229
+ pass
230
+ if start_time_dt64 != scene [time_key ].values [0 ]:
231
+ raise ValueError
232
+ if end_time_dt64 != scene [time_key ].values [- 1 ]:
233
+ raise ValueError
234
+
235
+ def split_scene_at_midnight (scene ):
236
+ """Split scenes at midnight."""
237
+ if midnight_scene (scene ):
238
+ midnight_linenr = get_midnight_line_nr (scene )
239
+ scene1 = scene .copy ()
240
+ scene2 = scene .copy ()
241
+ set_exact_time_and_crop (scene1 , None , midnight_linenr )
242
+ set_exact_time_and_crop (scene2 , midnight_linenr + 1 , None )
243
+ return [scene1 , scene2 ]
244
+ return [scene ]
245
+
175
246
176
247
def process_one_scene (scene_files , out_path , engine = 'h5netcdf' ,
177
- all_channels = False , pps_channels = False , orbit_n = 0 , as_noaa19 = False , avhrr_channels = False ):
248
+ all_channels = False , pps_channels = False , orbit_n = 0 , as_noaa19 = False , avhrr_channels = False ,
249
+ split_files_at_midnight = True ):
178
250
"""Make level 1c files in PPS-format."""
179
251
tic = time .time ()
180
- scn_ = Scene (
252
+ scn_in = Scene (
181
253
reader = 'viirs_vgac_l1c_nc' ,
182
254
filenames = scene_files )
183
255
@@ -192,41 +264,46 @@ def process_one_scene(scene_files, out_path, engine='h5netcdf',
192
264
if avhrr_channels :
193
265
MY_MBAND = MBAND_AVHRR
194
266
195
- scn_ .load (MY_MBAND
196
- + ANGLE_NAMES
197
- # + ['M12_LUT', 'M13_LUT', 'M15_LUT', 'M16_LUT']
198
- + ['latitude' , 'longitude' , 'scanline_timestamps' ])
199
-
200
- # one ir channel
201
- irch = scn_ ['M15' ]
202
-
203
- # Set header and band attributes
204
- set_header_and_band_attrs (scn_ , orbit_n = orbit_n )
205
-
206
- # Rename longitude, latitude to lon, lat.
207
- rename_latitude_longitude (scn_ )
208
-
209
- # Convert angles to PPS
210
- convert_angles (scn_ , delete_azimuth = False )
211
- update_angle_attributes (scn_ , irch )
212
-
213
- # Adjust to noaa19 with sbafs from KG
214
- sensor = "viirs"
215
- if as_noaa19 :
216
- sensor = "avhrr"
217
- convert_to_noaa19 (scn_ )
218
-
219
- filename = compose_filename (scn_ , out_path , instrument = sensor , band = irch )
220
- encoding = get_encoding_viirs (scn_ )
221
-
222
- scn_ .save_datasets (writer = 'cf' ,
223
- filename = filename ,
224
- header_attrs = get_header_attrs (scn_ , band = irch , sensor = sensor ),
225
- engine = engine ,
226
- include_lonlats = False ,
227
- flatten_attrs = True ,
228
- encoding = encoding )
229
- print ("Saved file {:s} after {:3.1f} seconds" .format (
230
- os .path .basename (filename ),
231
- time .time ()- tic ))
232
- return filename
267
+ scn_in .load (MY_MBAND
268
+ + ANGLE_NAMES
269
+ # + ['M12_LUT', 'M13_LUT', 'M15_LUT', 'M16_LUT']
270
+ + ['latitude' , 'longitude' , 'scanline_timestamps' ])
271
+ if split_files_at_midnight :
272
+ scenes = split_scene_at_midnight (scn_in )
273
+ else :
274
+ scenes = [scn_in ]
275
+ filenames = []
276
+ for scn_ in scenes :
277
+ # one ir channel
278
+ irch = scn_ ['M15' ]
279
+
280
+ # Set header and band attributes
281
+ set_header_and_band_attrs (scn_ , orbit_n = orbit_n )
282
+
283
+ # Rename longitude, latitude to lon, lat.
284
+ rename_latitude_longitude (scn_ )
285
+
286
+ # Convert angles to PPS
287
+ convert_angles (scn_ , delete_azimuth = False )
288
+ update_angle_attributes (scn_ , irch )
289
+ # Adjust to noaa19 with sbafs from KG
290
+ sensor = "viirs"
291
+ if as_noaa19 :
292
+ sensor = "avhrr"
293
+ convert_to_noaa19 (scn_ )
294
+
295
+ filename = compose_filename (scn_ , out_path , instrument = sensor , band = irch )
296
+ encoding = get_encoding_viirs (scn_ )
297
+
298
+ scn_ .save_datasets (writer = 'cf' ,
299
+ filename = filename ,
300
+ header_attrs = get_header_attrs (scn_ , band = irch , sensor = sensor ),
301
+ engine = engine ,
302
+ include_lonlats = False ,
303
+ flatten_attrs = True ,
304
+ encoding = encoding )
305
+ print ("Saved file {:s} after {:3.1f} seconds" .format (
306
+ os .path .basename (filename ),
307
+ time .time ()- tic ))
308
+ filenames .append (filename )
309
+ return filenames
0 commit comments