Skip to content
Draft
20 changes: 15 additions & 5 deletions hyp3_testing/opera_compare.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@

RTC_S1_PRODUCTS_ERROR_REL_TOLERANCE = 1e-03
RTC_S1_PRODUCTS_ERROR_ABS_TOLERANCE = 1e-04
LIST_EXCLUDE_COMPARISON_HDF5 = ['//identification/processingDateTime']
LIST_EXCLUDE_COMPARISON_HDF5 = [
'//identification/processingDateTime',
# TODO: figure out why these don't exist
# '//metadata/qa/rfi/frequencyDomainRfiBurstReport',
# '//metadata/qa/rfi/timeDomainRfiReport',
]
LIST_NAME_COMPARISON_XML = [
'/gmi:MI_Metadata/gmd:fileIdentifier/gco:CharacterString',
'/gmi:MI_Metadata/gmd:identificationInfo/gmd:MD_DataIdentification/gmd:citation/gmd:CI_Citation/gmd:title/gmx:FileName',
Expand Down Expand Up @@ -159,6 +164,9 @@ def compare_hdf5_elements(hdf5_obj_1: h5py.Group, hdf5_obj_2: h5py.Group, str_ke
str_key: Key to the dataset or attribute
is_attr: Designate if `str_key` is for dataset or attribute
"""
if any([str_key.startswith(x) for x in LIST_EXCLUDE_COMPARISON_HDF5]):
return

# Prepare to comapre the data in the HDF objects
if is_attr:
# str_key is for attribute
Expand Down Expand Up @@ -196,9 +204,6 @@ def compare_hdf5_elements(hdf5_obj_1: h5py.Group, hdf5_obj_2: h5py.Group, str_ke
if is_void or is_reference:
val_2 = _unpack_array(val_2, hdf5_obj_2)

if str_key in LIST_EXCLUDE_COMPARISON_HDF5:
return

shape_val_1 = val_1.shape
shape_val_2 = val_2.shape
assert shape_val_1 == shape_val_2
Expand Down Expand Up @@ -308,7 +313,6 @@ def _compare_rtc_s1_metadata(metadata_1: dict, metadata_2: dict) -> None:
check_product_id(v1, v2)
continue
elif k1 in LIST_EXCLUDE_COMPARISON_IMAGE:
print(v1)
continue
assert v2 == v1, f'Values for key {k1} do not match ({v1} | {v2})'

Expand Down Expand Up @@ -339,6 +343,12 @@ def compare_rtc_s1_products(file_1: Path, file_2: Path) -> None:
image_2 = gdal_band_2.ReadAsArray()
assert image_1.shape == image_2.shape
assert image_1.dtype == image_2.dtype
# try:
# assert np.allclose(image_1, image_2, **ALL_CLOSE_ARGS)
# except AssertionError:
# diff = image_1 - image_2
# is_diff = ~np.isclose(image_1, image_2, **ALL_CLOSE_ARGS)
# n_diff = np.sum(is_diff)
assert np.allclose(image_1, image_2, **ALL_CLOSE_ARGS)


Expand Down
179 changes: 156 additions & 23 deletions hyp3_testing/templates/opera_rtc_s1_golden.json.j2
Original file line number Diff line number Diff line change
@@ -1,32 +1,165 @@
{% set granules = [
'S1_191606_IW2_20230801T204912_HH_89E5-BURST',
'S1_133460_IW3_20220501T001600_VV_8F14-BURST',
'S1_359575_IW2_20220201T053045_VV_EDCF-BURST',
'S1_025990_IW3_20220801T135534_VV_8811-BURST',
'S1_015793_IW1_20220801T060646_VV_A2E0-BURST',
'S1_009422_IW3_20220801T011355_VV_62C3-BURST',
'S1_144642_IW1_20220501T085001_HH_C30B-BURST',
'S1_007270_IW3_20220201T233452_VV_8221-BURST',
'S1_165731_IW1_20230801T005941_VV_747D-BURST',
'S1_002348_IW1_20220201T194834_VV_E8FC-BURST',
'S1_292529_IW1_20230501T020840_VV_4083-BURST',
'S1_036775_IW1_20220801T221120_VV_D5EC-BURST',
'S1_359524_IW1_20220201T052823_VV_9C97-BURST',
'S1_359459_IW1_20220201T052524_VV_E64A-BURST',
'S1_373594_IW1_20220201T161512_VV_8E82-BURST',
'S1_150514_IW1_20220501T131958_VV_1DD0-BURST',
'S1_152738_IW1_20220501T150212_VV_4C3F-BURST',
'S1_151212_IW1_20230201T135208_VV_61E6-BURST',
'S1_295264_IW1_20230501T041423_VV_2A63-BURST',
'S1_359352_IW1_20220201T052028_VV_49C6-BURST',
'S1_163331_IW2_20230201T230916_VV_FA24-BURST',
'S1_146245_IW2_20220501T100343_VV_7FA3-BURST',
'S1_320310_IW2_20230501T232548_VV_29E4-BURST',
'S1_307331_IW2_20230501T132909_VV_9FD2-BURST',
'S1_318168_IW2_20230501T214720_VV_57C2-BURST',
'S1_157300_IW2_20230201T183201_HH_4FE0-BURST',
'S1_036632_IW2_20220801T220447_VV_3139-BURST',
'S1_150573_IW2_20220501T132241_VV_9BBB-BURST',
'S1_136524_IW2_20230201T023655_VV_4369-BURST',
'S1_292489_IW2_20230501T020650_VV_1BAD-BURST',
'S1_163283_IW3_20220501T230700_VV_6037-BURST',
'S1_182787_IW3_20230801T140348_VV_F35F-BURST',
'S1_195410_IW3_20230801T234406_VV_E5B0-BURST',
'S1_353213_IW3_20220201T003817_VV_BE3A-BURST',
'S1_170810_IW3_20230801T045312_VV_CB00-BURST',
'S1_181343_IW3_20230801T125725_VV_66F1-BURST',
'S1_136211_IW3_20220501T022228_VV_CC2B-BURST',
'S1_316880_IW3_20230501T204808_VV_CDF5-BURST',
'S1_036797_IW3_20220801T221223_VV_26DA-BURST',
'S1_019168_IW3_20220801T084157_VV_F678-BURST',
'S1_028384_IW3_20220801T154538_HH_AF88-BURST',
'S1_152176_IW1_20220501T143622_HH_5576-BURST',
'S1_163354_IW3_20220501T231016_VV_C1F2-BURST',
'S1_146042_IW3_20230201T095429_VV_5E5B-BURST',
'S1_006633_IW2_20220201T230534_VV_A454-BURST',
'S1_004739_IW3_20220201T213831_HH_D539-BURST',
'S1_154470_IW1_20230201T162154_VV_F832-BURST',
'S1_006513_IW2_20220201T230003_VV_CC3F-BURST',
'S1_150505_IW3_20230201T131940_VV_18F5-BURST',
'S1_148182_IW2_20230201T113251_VV_3142-BURST',
'S1_177292_IW2_20230801T095110_VV_BAA1-BURST',
'S1_017996_IW2_20220801T074804_VV_BC02-BURST',
'S1_361683_IW1_20220201T070738_VV_1E85-BURST',
'S1_297118_IW1_20230501T053937_VV_3E40-BURST',
'S1_166282_IW1_20230801T012501_VV_4D24-BURST',
'S1_136507_IW3_20220501T023604_VV_30A6-BURST',
'S1_145149_IW1_20230201T091324_VV_1BCD-BURST',
'S1_370089_IW2_20220201T133405_HH_B613-BURST',
'S1_168760_IW2_20230801T031857_VV_4BCE-BURST',
'S1_026556_IW2_20220801T142135_VV_1765-BURST',
'S1_152176_IW3_20230201T143629_HH_F01D-BURST',
'S1_152156_IW1_20220501T143527_HH_A04F-BURST',
'S1_371294_IW2_20220201T142929_HH_DE7D-BURST',
'S1_371278_IW1_20220201T142844_HH_20DE-BURST',
'S1_152180_IW2_20220501T143634_HH_5576-BURST',
'S1_152222_IW2_20220501T143830_HH_BBE4-BURST',
'S1_371301_IW2_20220201T142948_HH_DE7D-BURST',
'S1_152183_IW3_20220501T143643_HH_B198-BURST',
'S1_371315_IW3_20220201T143028_HH_3964-BURST',
'S1_152189_IW2_20230201T143704_HH_F3AE-BURST',
'S1_020108_IW1_20220801T092508_HH_9042-BURST',
'S1_176837_IW1_20230801T093014_HH_E423-BURST',
'S1_157213_IW1_20230201T182800_HH_4C34-BURST',
'S1_144602_IW2_20220501T084811_HH_DCD1-BURST',
'S1_157227_IW3_20230201T182841_HH_A729-BURST',
'S1_144644_IW1_20230201T085011_HH_7305-BURST',
'S1_157235_IW1_20220501T182856_HH_2295-BURST',
'S1_020078_IW1_20220801T092345_HH_F5F4-BURST',
'S1_365790_IW3_20220201T101628_HH_CFEC-BURST',
'S1_144625_IW1_20220501T084914_HH_8D2F-BURST',
'S1_146123_IW2_20230201T095812_VV_248E-BURST',
'S1_146128_IW3_20220501T095822_VV_F1B2-BURST',
'S1_146121_IW3_20220501T095802_VV_F4C1-BURST',
'S1_146117_IW2_20230201T095755_VV_E636-BURST',
'S1_146110_IW2_20230201T095736_VV_E636-BURST',
'S1_146131_IW1_20220501T095828_VV_F1B2-BURST',
'S1_146132_IW3_20230201T095837_VV_D627-BURST',
'S1_146136_IW3_20230201T095848_VV_D627-BURST',
'S1_146125_IW2_20230201T095817_VV_248E-BURST',
'S1_146126_IW3_20220501T095816_VV_F4C1-BURST',
'S1_143891_IW3_20230201T081536_VV_4C51-BURST',
'S1_371718_IW2_20220201T144858_VV_EB5E-BURST',
'S1_018016_IW3_20220801T074900_VV_4238-BURST',
'S1_363285_IW1_20220201T082117_VV_5CE1-BURST',
'S1_138553_IW1_20230201T041011_VV_0C19-BURST',
'S1_290821_IW3_20230501T005010_VV_C471-BURST',
'S1_030357_IW2_20220801T171619_VV_EF3F-BURST',
'S1_374111_IW2_20220201T163859_VV_63AF-BURST',
'S1_011909_IW2_20220801T030814_VV_30A5-BURST',
'S1_184638_IW1_20230801T152852_VV_0126-BURST',
'S1_172597_IW2_20230801T061520_VV_B62C-BURST',
'S1_313623_IW3_20230501T181825_VV_891D-BURST',
'S1_015800_IW3_20220801T060708_VV_AA46-BURST',
'S1_156859_IW1_20220501T181139_VV_70B8-BURST',
'S1_156892_IW3_20230201T181317_VV_A4CB-BURST',
'S1_140037_IW2_20230201T051825_HH_787D-BURST',
'S1_015837_IW2_20220801T060849_VV_9BBA-BURST',
'S1_172601_IW2_20230801T061531_VV_B62C-BURST',
'S1_172613_IW1_20230801T061603_VV_1C0C-BURST',
'S1_156886_IW3_20230201T181300_VV_4666-BURST',
'S1_170529_IW3_20230801T044017_VV_A29C-BURST',
'S1_154891_IW1_20220501T164111_VV_911F-BURST',
'S1_038840_IW1_20220801T234616_VV_2366-BURST',
'S1_154886_IW2_20220501T164058_VV_A295-BURST',
'S1_033361_IW3_20220801T193426_VV_9176-BURST',
'S1_038658_IW1_20220801T233754_VV_F85F-BURST',
'S1_318190_IW2_20230501T214821_VV_69F9-BURST',
'S1_309683_IW3_20230501T151717_VV_3047-BURST',
'S1_293050_IW1_20230501T023237_VV_408A-BURST',
'S1_028190_IW3_20220801T153643_VV_5D7F-BURST',
'S1_172529_IW2_20230801T061213_VV_33F9-BURST',
'S1_005400_IW2_20220201T220853_VV_7058-BURST',
'S1_361667_IW2_20220201T070655_VV_2E36-BURST',
'S1_015764_IW2_20220801T060527_VV_D6ED-BURST',
'S1_163328_IW1_20220501T230902_VV_222F-BURST',
'S1_157240_IW3_20220501T182912_HH_2295-BURST',
'S1_136507_IW3_20220501T023604_VV_30A6-BURST',
'S1_195557_IW3_20230801T235051_VV_15A8-BURST',
'S1_003264_IW2_20220201T203041_VV_62C7-BURST',
'S1_180539_IW2_20230801T122026_VV_982C-BURST',
'S1_290836_IW3_20230501T005052_VV_92B9-BURST',
'S1_015738_IW1_20220801T060415_VV_AC5B-BURST',
'S1_367475_IW3_20220201T113356_VV_DC26-BURST',
'S1_030344_IW3_20220801T171544_VV_1932-BURST',
'S1_007338_IW2_20220201T233759_VV_1E1A-BURST',
'S1_367470_IW3_20220201T113342_VV_78AC-BURST',
'S1_359504_IW2_20220201T052729_VV_E5DB-BURST',
'S1_367476_IW1_20220201T113357_VV_DC26-BURST',
'S1_367486_IW3_20220201T113426_VV_5019-BURST',
'S1_367488_IW1_20220201T113430_VV_5019-BURST',
'S1_141650_IW3_20230201T063235_VV_2C85-BURST',
'S1_312626_IW2_20230501T173234_VV_F346-BURST',
'S1_000684_IW2_20220201T183205_VV_A461-BURST',
'S1_141657_IW3_20230201T063254_VV_2C85-BURST',
'S1_000705_IW1_20220201T183302_VV_4AE0-BURST',
'S1_312639_IW1_20230501T173308_VV_5543-BURST',
'S1_312632_IW2_20230501T173250_VV_F346-BURST',
'S1_312638_IW1_20230501T173306_VV_5543-BURST',
'S1_141655_IW3_20230201T063249_VV_2C85-BURST',
'S1_140036_IW2_20230201T051822_HH_787D-BURST'
] %}
[
{# Swath 1 scene with homogenous backscatter (Amazon Rainforest) #}
{% for granule in granules %}
{
"job_type": "OPERA_RTC_S1",
"name": "{{ name }}",
"job_parameters": {
"granules": [
"S1_366240_IW1_20220321T103707_VV_8575-BURST"
"{{ granule }}"
]
}
},
{# Swath 2 scene with varying backscatter regions (San Francisco) #}
{
"job_type": "OPERA_RTC_S1",
"name": "{{ name }}",
"job_parameters": {
"granules": [
"S1_073251_IW2_20220111T020806_VV_9D98-BURST"
]
}
},
{# Swath 3 scene with HH co-pol (Nova Scotia) #}
{
"job_type": "OPERA_RTC_S1",
"name": "{{ name }}",
"job_parameters": {
"granules": [
"S1_209152_IW2_20220103T101538_HH_BD12-BURST"
]
}
}
}{% if not loop.last %},{% endif %}
{% endfor %}
]
46 changes: 27 additions & 19 deletions scripts/opera-rtc/choose_granules.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@

import requests
import shapely
from shapely.strtree import STRtree


session = requests.Session()


def get_attribute_values(granule, attribute_name: str) -> list[str]:
for attribute in granule['umm']['AdditionalAttributes']:
if attribute['Name'] == attribute_name:
return attribute['Values']
raise ValueError(f'Attribute {attribute_name} not found for granule {granule["meta"]["native-id"]}')


def get_corresponding_burst_granule_name(opera_granule: dict) -> str:
start = opera_granule['umm']['TemporalExtent']['RangeDateTime']['BeginningDateTime']
end = opera_granule['umm']['TemporalExtent']['RangeDateTime']['EndingDateTime']
Expand All @@ -28,16 +36,11 @@ def get_corresponding_burst_granule_name(opera_granule: dict) -> str:
return response.json()['items'][0]['meta']['native-id']


def get_attribute_values(granule, attribute_name: str) -> list[str]:
for attribute in granule['umm']['AdditionalAttributes']:
if attribute['Name'] == attribute_name:
return attribute['Values']
raise ValueError(f'Attribute {attribute_name} not found for granule {granule["meta"]["native-id"]}')


def choose_sample(candidates: list) -> None:
def choose_sample(candidates: list, n=10) -> None:
print(f'Provided {len(candidates)} candidates')
for granule in random.sample(candidates, 10):
print(f'{granule["meta"]["native-id"]},{get_corresponding_burst_granule_name(granule)}')
granule_name = granule['meta']['native-id']
print(f'{granule_name},{get_corresponding_burst_granule_name(granule)}')


def over_antimeridian(granule: dict) -> bool:
Expand All @@ -58,27 +61,31 @@ def over_prime_meridian(granule: dict) -> bool:
return min(longitudes) < 0 < max(longitudes)


def percent_overlap(granule: dict, area: shapely.Geometry) -> float:
def percent_overlap(granule: dict, area: shapely.Geometry, area_strt) -> float:
granule_shape = shapely.MultiPolygon(
[
shapely.Polygon([point['Longitude'], point['Latitude']] for point in poly['Boundary']['Points'])
for poly in granule['umm']['SpatialExtent']['HorizontalSpatialDomain']['Geometry']['GPolygons']
]
)
return shapely.intersection(granule_shape, area).area / granule_shape.area
indexes = list(area_strt.query(granule_shape))
if len(indexes) == 0:
return 0.0
intersecting_area = shapely.geometry.GeometryCollection([area.geoms[i] for i in indexes])
return shapely.intersection(granule_shape, intersecting_area).area / granule_shape.area


def main():
with open('rtc_granules.json') as f:
granules = json.load(f)
with open('GSHHS_c_L1.geojson') as f:
land = shapely.from_geojson(f.read())
with open('extreme_terrain.geojson') as f:
extreme_terrain = shapely.from_geojson(f.read())
with open('rtc_granules.json') as f:
granules = json.load(f)

print('S1A')
choose_sample([g for g in granules if g['umm']['Platforms'][0]['ShortName'] == 'Sentinel-1A'])
print('S1B')
# print('S1B')
# choose_sample([g for g in granules if g['umm']['Platforms'][0]['ShortName'] == 'Sentinel-1B'])
print('IW1')
choose_sample([g for g in granules if 'IW1' in get_attribute_values(g, 'SUBSWATH_NAME')])
Expand All @@ -100,14 +107,15 @@ def main():
choose_sample([g for g in granules if get_attribute_values(g, 'POLARIZATION') == ['VV', 'VH']])
print('prime meridian')
choose_sample([g for g in granules if over_prime_meridian(g)])
print('antimeridian')
choose_sample([g for g in granules if over_antimeridian(g)])
pct_lands = [percent_overlap(g, land, STRtree(land.geoms)) for g in granules]
print('9-11% land')
choose_sample([g for g in granules if 0.09 < percent_overlap(g, land) < 0.11])
choose_sample([g for g, pct_land in zip(granules, pct_lands) if 0.09 < pct_land < 0.11])
print('0% land')
choose_sample([g for g in granules if percent_overlap(g, land) == 0.0])
choose_sample([g for g, pct_land in zip(granules, pct_lands) if pct_land == 0.0])
print('extreme terrain')
choose_sample([g for g in granules if 0.8 <= percent_overlap(g, extreme_terrain)])
choose_sample([g for g in granules if 0.8 <= percent_overlap(g, extreme_terrain, STRtree(extreme_terrain.geoms))])
print('antimeridian')
choose_sample([g for g in granules if over_antimeridian(g)])


if __name__ == '__main__':
Expand Down
Loading
Loading