Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prep_hyp3: skip relative_orbit, start/stopUTC for isce2_burst products #1200

Merged
merged 1 commit into from
May 28, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 60 additions & 54 deletions src/mintpy/prep_hyp3.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
############################################################
# Program is part of MintPy #
# Copyright (c) 2013, Zhang Yunjun, Heresh Fattahi #
# Author: Forrest Williams, Mar 2021 #
# Author: Forrest Williams, Zhang Yunjun, Mar 2021 #
############################################################


Expand All @@ -15,45 +15,47 @@

#########################################################################
def add_hyp3_metadata(fname, meta, is_ifg=True):
'''Read/extract attribute data from HyP3 metadata file and add to metadata dictionary
Inputs:
*unw_phase.tif, *corr.tif file name, *dem.tif, *inc_map.tif, e.g.
S1AA_20161223T070700_20170116T070658_VVP024_INT80_G_ueF_74C2_unw_phase_clip.tif
S1AA_20161223T070700_20170116T070658_VVP024_INT80_G_ueF_74C2_corr_clip.tif
S1AA_20161223T070700_20170116T070658_VVP024_INT80_G_ueF_74C2_dem_clip.tif
Metadata dictionary (meta)
Output:
Metadata dictionary (meta)
'''Read/extract metadata from HyP3 metadata file and add to metadata dictionary.

Two types of ASF HyP3 products are supported: isce2_burst, gamma_scene
1. isce2_burst (burst-wide product using ISCE2) metadata file:
format: {SAT}_{FRAME}_{SUBSWATH}_{DATE1}_{DATE2}_{POL}_{RES}_{IDS}.txt
example: S1_213524_IW1_20170411_20170517_VV_INT80_8E81.txt
content:
Reference Granule: S1_213524_IW1_20170411T133605_VV_BD30-BURST
...
2. gamma_scene (scene-wide product using Gamma) metadata file:
format: {SAT}_{DATE1}_{DATE2}_{POL}_{RES}_{SOFT}_{PROC}_{IDS}.txt
example: S1AA_20190610T135156_20190622T135157_VVP012_INT80_G_ueF_F8BF.txt
content:
Reference Granule: S1A_IW_SLC__1SDV_20190704T135158_20190704T135225_027968_032877_1C4D
...

Parameters: fname - str, path to the hyp3 data file, e.g. *unw_phase_clip*.tif, *dem_clip*.tif
meta - dict, existing metadata
is_ifg - bool, is the data file interferogram (unw/corr) or geometry (dem/angles)
Returns: meta - dict, return metadata
'''

# read hyp3 metadata file
# e.g.: burst-wide product using ISCE2: {SAT}_{FRAME}_{SUBSWATH}_{DATE1}_{DATE2}_{POL}_{RES}_{IDS}.txt
# scene-wide product using Gamma: {SAT}_{DATE1}_{DATE2}_{POL}_{RES}_{SOFT}_{PROC}_{IDS}.txt
# job_id -> prod_type and date1/2 objects
job_id = '_'.join(os.path.basename(fname).split('_')[:8])
meta_file = os.path.join(os.path.dirname(fname), f'{job_id}.txt')
hyp3_meta = {}
with open(meta_file) as f:
for line in f:
key, value = line.strip().replace(' ','').split(':')[:2]
hyp3_meta[key] = value

# get product type and the correponding insar processor
if job_id.split('_')[2].startswith('IW'):
# burst-wide product using ISCE2
prod_type = 'isce2_burst'
date1, date2 = (dt.datetime.strptime(x,'%Y%m%d') for x in job_id.split('_')[3:5])
else:
# scene-wide product using Gamma
prod_type = 'gamma_scene'
date1, date2 = (dt.datetime.strptime(x,'%Y%m%dT%H%M%S') for x in job_id.split('_')[1:3])

# get date1/2 objects
if prod_type == 'isce2_burst':
date1_str, date2_str = job_id.split('_')[3:5]
date1 = dt.datetime.strptime(f'{date1_str}','%Y%m%d')
date2 = dt.datetime.strptime(f'{date2_str}','%Y%m%d')
else:
date1_str, date2_str = job_id.split('_')[1:3]
date1 = dt.datetime.strptime(date1_str,'%Y%m%dT%H%M%S')
date2 = dt.datetime.strptime(date2_str,'%Y%m%dT%H%M%S')
# read hyp3 metadata file
meta_file = os.path.join(os.path.dirname(fname), f'{job_id}.txt')
hyp3_meta = {}
with open(meta_file) as f:
for line in f:
key, value = line.strip().replace(' ','').split(':')[:2]
hyp3_meta[key] = value
ref_granule = hyp3_meta['ReferenceGranule']

# add universal hyp3 metadata
meta['PROCESSOR'] = 'hyp3'
Expand All @@ -63,8 +65,7 @@ def add_hyp3_metadata(fname, meta, is_ifg=True):
meta['EARTH_RADIUS'] = hyp3_meta['Earthradiusatnadir']
meta['HEIGHT'] = hyp3_meta['Spacecraftheight']
meta['STARTING_RANGE'] = hyp3_meta['Slantrangenear']
# ensure negative value for the heading angle
meta['HEADING'] = float(hyp3_meta['Heading']) % 360. - 360.
meta['HEADING'] = float(hyp3_meta['Heading']) % 360. - 360. # ensure negative value

# add LAT/LON_REF1/2/3/4 based on whether satellite ascending or descending
meta['ORBIT_DIRECTION'] = 'ASCENDING' if abs(meta['HEADING']) < 90 else 'DESCENDING'
Expand Down Expand Up @@ -92,52 +93,57 @@ def add_hyp3_metadata(fname, meta, is_ifg=True):
meta['LON_REF3'] = str(E)
meta['LON_REF4'] = str(W)

# note: HyP3 currently only supports Sentinel-1 data, so Sentinel-1
# configuration is hard-coded.
if hyp3_meta['ReferenceGranule'].startswith('S1'):
# hard-coded metadata for Sentinel-1
if ref_granule.startswith('S1'):
meta['PLATFORM'] = 'Sen'
meta['ANTENNA_SIDE'] = -1
meta['WAVELENGTH'] = SPEED_OF_LIGHT / sensor.SEN['carrier_frequency']
meta['RANGE_PIXEL_SIZE'] = sensor.SEN['range_pixel_size'] * int(meta['RLOOKS'])
meta['AZIMUTH_PIXEL_SIZE'] = sensor.SEN['azimuth_pixel_size'] * int(meta['ALOOKS'])

# note: HyP3 (incidence, azimuth) angle datasets are in the unit of radian
# HyP3 (incidence, azimuth) angle datasets are in the unit of radian,
# which is different from the isce-2 convention of degree
if any(x in os.path.basename(fname) for x in ['lv_theta', 'lv_phi']):
meta['UNIT'] = 'radian'

# add metadata that is only relevant to interferogram files
# interferogram related metadata
if is_ifg:
meta['DATE12'] = f'{date1.strftime("%y%m%d")}-{date2.strftime("%y%m%d")}'
meta['P_BASELINE_TOP_HDR'] = hyp3_meta['Baseline']
meta['P_BASELINE_BOTTOM_HDR'] = hyp3_meta['Baseline']

# HDF-EOS5 metadata
ref_granule = hyp3_meta['ReferenceGranule']
# [optional] HDF-EOS5 metadata, including:
# beam_mode/swath, relative_orbit, first/last_frame, unwrap_method
if ref_granule.startswith('S1'):
# beam_mode
meta['beam_mode'] = 'IW'

# beam_swath
if prod_type == 'isce2_burst':
# burst-wide product using ISCE2
meta['beam_swath'] = job_id.split('_')[2][2:]

# relative_orbit [to be added]
# first/last_frame [to be added]

else:
# scene-wide product using Gamma
meta['beam_swath'] = '123'

# relative_orbit
if ref_granule.startswith('S1A'):
meta['relative_orbit'] = ((int(hyp3_meta['ReferenceOrbitNumber']) - 73) % 175) + 1
elif ref_granule.startswith('S1B'):
meta['relative_orbit'] = ((int(hyp3_meta['ReferenceOrbitNumber']) - 202) % 175) + 1
else:
raise ValueError('Un-recognized Sentinel-1 satellite from {ref_granule}!')

# first/last_frame [from start/stopUTC]
# NOTE by Yunjun, Apr 2024: ascending node time is needed to calculate the first/last frame
# based on the start/end UTC time.
t0, t1 = ref_granule.split('_')[-5:-3]
meta['startUTC'] = dt.datetime.strptime(t0, '%Y%m%dT%H%M%S').strftime('%Y-%m-%d %H:%M:%S.%f')
meta['stopUTC'] = dt.datetime.strptime(t1, '%Y%m%dT%H%M%S').strftime('%Y-%m-%d %H:%M:%S.%f')
# relative_orbit
abs_orbit = int(hyp3_meta['ReferenceOrbitNumber'])
if ref_granule.startswith('S1A'):
meta['relative_orbit'] = ((abs_orbit - 73) % 175) + 1
elif ref_granule.startswith('S1B'):
meta['relative_orbit'] = ((abs_orbit - 202) % 175) + 1
else:
# add equation for Sentinel-C/D in the future
raise ValueError('Un-recognized Sentinel-1 satellite from {ref_granule}!')

# first/last_frame [to be completed]
t0, t1 = ref_granule.split('_')[-5:-3]
meta['startUTC'] = dt.datetime.strptime(t0, '%Y%m%dT%H%M%S').strftime('%Y-%m-%d %H:%M:%S.%f')
meta['stopUTC'] = dt.datetime.strptime(t1, '%Y%m%dT%H%M%S').strftime('%Y-%m-%d %H:%M:%S.%f')
# ascendingNodeTime [to be added]

# unwrap_method
meta['unwrap_method'] = hyp3_meta['Unwrappingtype']
Expand Down