@@ -307,6 +307,31 @@ def is_eap_correction_necessary(ipf_version: version.Version) -> SimpleNamespace
307
307
308
308
return eap
309
309
310
+ def get_track_burst_num (track_burst_num_file : str = esa_track_burst_id_file ):
311
+ '''Read the start / stop burst number info of each track from ESA.
312
+
313
+ Parameters:
314
+ -----------
315
+ track_burst_num_file : str
316
+ Path to the track burst number files.
317
+
318
+ Returns:
319
+ --------
320
+ track_burst_num : dict
321
+ Dictionary where each key is the track number, and each value is a list
322
+ of two integers for the start and stop burst number
323
+ '''
324
+
325
+ # read the text file to list
326
+ track_burst_info = np .loadtxt (track_burst_num_file , dtype = int )
327
+
328
+ # convert lists into dict
329
+ track_burst_num = dict ()
330
+ for track_num , burst_num0 , burst_num1 in track_burst_info :
331
+ track_burst_num [track_num ] = [burst_num0 , burst_num1 ]
332
+
333
+ return track_burst_num
334
+
310
335
def burst_from_xml (annotation_path : str , orbit_path : str , tiff_path : str ,
311
336
iw2_annotation_path : str , open_method = open ):
312
337
'''Parse bursts in Sentinel-1 annotation XML.
@@ -331,16 +356,13 @@ def burst_from_xml(annotation_path: str, orbit_path: str, tiff_path: str,
331
356
List of Sentinel1BurstSlc objects found in annotation XML.
332
357
'''
333
358
334
- # a 1D array where the indices are the Sentinel-1 track number
335
- # and the data at each row are the corresponding cumulative ID
336
- # number for the last burst of the given track (i.e., line number)
337
- # get last burst ID number of each track and prepend 0
338
- tracks_burst_id = np .insert (np .loadtxt (esa_track_burst_id_file ,
339
- usecols = [2 ], dtype = int ),
340
- 0 , 0 )
359
+ # a dict where the key is the track number and the value is a list of
360
+ # two integers for the start and stop burst number
361
+ track_burst_num = get_track_burst_num ()
341
362
342
363
_ , tail = os .path .split (annotation_path )
343
- platform_id , subswath_id , _ , pol = [x .upper () for x in tail .split ('-' )[:4 ]]
364
+ platform_id , swath_name , _ , pol = [x .upper () for x in tail .split ('-' )[:4 ]]
365
+ safe_filename = os .path .basename (annotation_path .split ('.SAFE' )[0 ])
344
366
345
367
# For IW mode, one burst has a duration of ~2.75 seconds and a burst
346
368
# overlap of approximately ~0.4 seconds.
@@ -360,17 +382,20 @@ def burst_from_xml(annotation_path: str, orbit_path: str, tiff_path: str,
360
382
# tree_lads = ET.parse(f_lads)
361
383
# product_annotation = s1_annotation.ProductAnnotation.from_et(tree_lads)
362
384
363
- #load the Calibraton annotation
364
- calibration_annotation_path = annotation_path .replace ('annotation/' , 'annotation/calibration/calibration-' )
365
- with open_method (calibration_annotation_path , 'r' ) as f_cads :
366
- tree_cads = ET .parse (f_cads )
367
- calibration_annotation = s1_annotation .CalibrationAnnotation .from_et (tree_cads )
385
+ eap = is_eap_correction_necessary (ipf_version )
386
+ if eap .magnitude_correction or eap .phase_correction :
368
387
369
- #load the Noise annotation
370
- noise_annotation_path = annotation_path .replace ('annotation/' , 'annotation/calibration/noise-' )
371
- with open_method (noise_annotation_path , 'r' ) as f_nads :
372
- tree_nads = ET .parse (f_nads )
373
- noise_annotation = s1_annotation .NoiseAnnotation .from_et (tree_nads , ipf_version )
388
+ #load the Calibraton annotation
389
+ calibration_annotation_path = annotation_path .replace ('annotation/' , 'annotation/calibration/calibration-' )
390
+ with open_method (calibration_annotation_path , 'r' ) as f_cads :
391
+ tree_cads = ET .parse (f_cads )
392
+ calibration_annotation = s1_annotation .CalibrationAnnotation .from_et (tree_cads )
393
+
394
+ #load the Noise annotation
395
+ noise_annotation_path = annotation_path .replace ('annotation/' , 'annotation/calibration/noise-' )
396
+ with open_method (noise_annotation_path , 'r' ) as f_nads :
397
+ tree_nads = ET .parse (f_nads )
398
+ noise_annotation = s1_annotation .NoiseAnnotation .from_et (tree_nads , ipf_version )
374
399
375
400
# Nearly all metadata loaded here is common to all bursts in annotation XML
376
401
with open_method (annotation_path , 'r' ) as f :
@@ -443,16 +468,11 @@ def burst_from_xml(annotation_path: str, orbit_path: str, tiff_path: str,
443
468
sensing_starts [i ] = sensing_start
444
469
sensing_times [i ] = as_datetime (burst_list_element .find ('sensingTime' ).text )
445
470
dt = sensing_times [i ] - ascending_node_time
446
- id_burst = int ((dt .seconds + dt .microseconds / 1e6 ) // burst_interval )
447
-
448
- # To be consistent with ESA let's start the counter of the ID
449
- # from 1 instead of from 0, i,e, the ID of the first burst of the
450
- # first track is 1
451
- id_burst += 1
471
+ # local burst_num within one track, starting from 0
472
+ burst_num = int ((dt .seconds + dt .microseconds / 1e6 ) // burst_interval )
452
473
453
- # the IDs are currently local to one track. Let's adjust based on
454
- # the last ID of the previous track
455
- id_burst += tracks_burst_id [track_number - 1 ]
474
+ # convert the local burst_num to the global burst_num, starting from 1
475
+ burst_num += track_burst_num [track_number ][0 ]
456
476
457
477
# choose nearest azimuth FM rate
458
478
d_seconds = 0.5 * (n_lines - 1 ) * azimuth_time_interval
@@ -487,29 +507,32 @@ def burst_from_xml(annotation_path: str, orbit_path: str, tiff_path: str,
487
507
last_valid_samples [last_line ])
488
508
489
509
490
- burst_id = f't{ track_number :03d} _{ id_burst } _{ subswath_id .lower ()} '
510
+ burst_id = f't{ track_number :03d} _{ burst_num } _{ swath_name .lower ()} '
491
511
492
512
493
513
#Extract burst-wise information for Calibration, Noise, and EAP correction
494
- burst_calibration = s1_annotation .BurstCalibration .from_calibration_annotation (calibration_annotation , sensing_start )
495
- bursts_noise = s1_annotation .BurstNoise ()
496
- bursts_noise .from_noise_annotation (noise_annotation ,sensing_start ,i * n_lines ,(i + 1 )* n_lines - 1 ,ipf_version )
514
+ if eap .magnitude_correction or eap .phase_correction :
515
+ burst_calibration = s1_annotation .BurstCalibration .from_calibration_annotation (calibration_annotation , sensing_start )
516
+ bursts_noise = s1_annotation .BurstNoise ()
517
+ bursts_noise .from_noise_annotation (noise_annotation ,sensing_start ,i * n_lines ,(i + 1 )* n_lines - 1 ,ipf_version )
518
+ else :
519
+ burst_calibration = None
520
+ bursts_noise = None
497
521
498
522
bursts [i ] = Sentinel1BurstSlc (ipf_version , sensing_start , radar_freq , wavelength ,
499
523
azimuth_steer_rate , azimuth_time_interval ,
500
524
slant_range_time , starting_range , iw2_mid_range ,
501
525
range_sampling_rate , range_pxl_spacing ,
502
526
(n_lines , n_samples ), az_fm_rate , doppler ,
503
527
rng_processing_bandwidth , pol , burst_id ,
504
- platform_id , center_pts [i ],
528
+ platform_id , safe_filename , center_pts [i ],
505
529
boundary_pts [i ], orbit , orbit_direction , orbit_number ,
506
530
tiff_path , i , first_valid_sample ,
507
531
last_sample , first_valid_line , last_line ,
508
532
range_window_type , range_window_coeff ,
509
533
rank , prf_raw_data , range_chirp_ramp_rate ,
510
534
burst_calibration , bursts_noise , None )
511
535
512
-
513
536
return bursts
514
537
515
538
def _is_zip_annotation_xml (path : str , id_str : str ) -> bool :
@@ -534,8 +557,8 @@ def _is_zip_annotation_xml(path: str, id_str: str) -> bool:
534
557
return True
535
558
return False
536
559
537
- def load_bursts (path : str , orbit_path : str , swath_num : int , pol : str = 'vv' ,
538
- burst_ids : list [str ]= None ):
560
+ def load_bursts (path : str , orbit_path : str , swath_num : int , pol : str = 'vv' ,
561
+ burst_ids : list [str ] = None ):
539
562
'''Find bursts in a Sentinel-1 zip file or a SAFE structured directory.
540
563
541
564
Parameters:
@@ -685,8 +708,9 @@ def _burst_from_safe_dir(safe_dir_path: str, id_str: str, orbit_path: str):
685
708
if 'measurement' in f and id_str in f and 'tiff' in f ]
686
709
f_tiff = f'{ safe_dir_path } /measurement/{ f_tiff [0 ]} ' if f_tiff else ''
687
710
else :
688
- warning_str = f'measurement directory not found in { safe_dir_path } '
689
- warnings .warn (warning_str )
711
+ msg = f'measurement directory NOT found in { safe_dir_path } '
712
+ msg += ', continue with metadata only.'
713
+ print (msg )
690
714
f_tiff = ''
691
715
692
716
bursts = burst_from_xml (f_annotation , orbit_path , f_tiff , iw2_f_annotation )
0 commit comments