Skip to content
Merged
Show file tree
Hide file tree
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
44 changes: 43 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,50 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-->
------
## [1.0.4](https://github.com/asfadmin/Discovery-SearchAPI-v3/compare/v1.0.3...v1.0.4)
### Added
- Added experimental ARIA S1 GUNW baseline stacking support
- requires: `dataset` keyword be set to "ARIA S1 GUNW" and using the desired frame as the `reference`
- returns json object list partially formatted for submitting jobs to ASF's On Demand processing.
``` json
[
{
"date": "2025-06-04T00:26:25Z",
"products": [
"S1A_IW_SLC__1SDV_20250604T002649_20250604T002716_059489_076290_7E0F",
"S1A_IW_SLC__1SDV_20250604T002625_20250604T002651_059489_076290_7FE0"
],
"group_granule_idx": 0,
"perpendicularBaseline": 0,
"temporalBaseline": 0
},
{
"date": "2025-05-23T00:26:25Z",
"products": [
"S1A_IW_SLC__1SDV_20250523T002650_20250523T002717_059314_075C80_5A5D",
"S1A_IW_SLC__1SDV_20250523T002625_20250523T002652_059314_075C80_BBE7"
],
"group_granule_idx": 0,
"perpendicularBaseline": 47,
"temporalBaseline": -12
},

...

{
"date": "2014-10-12T00:25:42Z",
"products": [
"S1A_IW_SLC__1SSV_20141012T002607_20141012T002634_002789_00323B_2DB9",
"S1A_IW_SLC__1SSV_20141012T002542_20141012T002609_002789_00323B_0E9F"
],
"group_granule_idx": 0,
"perpendicularBaseline": -160,
"temporalBaseline": -3888
}
]
```
### Changed
- bumped asf-search to 9.0.0 for nisar search types, browse images, and UAT collections
- bumped asf-search to 9.0.2 for nisar search types, browse images, and UAT collections, `productionConfiguration` list support, bbox validation, opera-disp jsonlite outputs


------
## [1.0.3](https://github.com/asfadmin/Discovery-SearchAPI-v3/compare/v1.0.2...v1.0.3)
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ujson==5.7.0
uvicorn==0.21.1
watchfiles==0.19.0

asf_search==9.0.0
asf_search==9.0.2
python-json-logger==2.0.7

pyshp==2.1.3
Expand Down
1 change: 1 addition & 0 deletions src/SearchAPI/application/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
from .output import *
from .logger import *
from .log_router import *
from .search import *
from .application import *
16 changes: 14 additions & 2 deletions src/SearchAPI/application/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
from .asf_opts import process_baseline_request, process_search_request, process_wkt_request
from .health import get_cmr_health
from .models import BaselineSearchOptsModel, SearchOptsModel
from .output import as_output, get_asf_search_script
from .output import as_output, get_asf_search_script, make_filename
from .files_to_wkt import FilesToWKT
from . import constants
from .search import stack_aria_gunw
import time


Expand Down Expand Up @@ -93,8 +94,19 @@ async def query_baseline(searchOptions: BaselineSearchOptsModel = Depends(proces
output = searchOptions.output
reference = searchOptions.reference
request_method = searchOptions.request_method
# Load the reference scene:

if searchOptions.opts.dataset is not None:
if searchOptions.opts.dataset[0] == asf.DATASET.ARIA_S1_GUNW:
return JSONResponse(
content=stack_aria_gunw(reference),
status_code=200,
headers= {
**constants.DEFAULT_HEADERS,
'Content-Disposition': f"attachment; filename={make_filename('json')}",
}
)
# Load the reference scene:

if output.lower() == 'python':
file_name, search_script = get_asf_search_script(opts, reference=reference, search_endpoint='baseline')

Expand Down
61 changes: 61 additions & 0 deletions src/SearchAPI/application/search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from collections import defaultdict

import dateparser
import asf_search as asf
from shapely.wkt import dumps as dump_to_wkt
from shapely import Polygon

def stack_aria_gunw(frame: str):
reference = asf.search(frame=int(frame), dataset=asf.DATASET.ARIA_S1_GUNW, maxResults=1)[0]

opts = asf.ASFSearchOptions(
relativeOrbit=reference.properties['pathNumber'],
processingLevel=asf.PRODUCT_TYPE.SLC,
dataset=asf.DATASET.SENTINEL1,
beamMode='IW',
polarization=['VV','VV+VH'],
flightDirection=reference.properties['flightDirection'],
intersectsWith=dump_to_wkt(Polygon(reference.geometry['coordinates'][0]))
)

slc_stack = asf.search(opts=opts)

groups = defaultdict(list)
for product in slc_stack:
group_id = product.properties['platform'] + '_' + str(product.properties['orbit'])
groups[group_id].append(product)
# dateparser.parse(str(value))
aria_groups = [
{
'date': min(dateparser.parse(product.properties['startTime']) for product in group),
'products': [product for product in group],
}
for group in groups.values()
]

# track group index on each product, naively choose first granule available
for idx, group in enumerate(aria_groups):
group_granule_idx = None
for idy, product in enumerate(group['products']):
product.properties['groupIDX'] = idx
if group_granule_idx is None:
if product.has_baseline():
group_granule_idx = idy

group['group_granule_idx'] = group_granule_idx



stack = asf.ASFSearchResults([group['products'][group['group_granule_idx']] for group in aria_groups if group['group_granule_idx'] is not None])
target_stack, warnings = asf.baseline.get_baseline_from_stack(reference, stack)
for product in target_stack:
group_idx = product.properties.pop('groupIDX')
aria_groups[group_idx]['perpendicularBaseline'] = product.properties['perpendicularBaseline']
aria_groups[group_idx]['temporalBaseline'] = product.properties['temporalBaseline']

for group in aria_groups:
for idx, product in enumerate(group['products']):
group['products'][idx] = product.properties['sceneName']
group['date'] = group['date'].strftime('%Y-%m-%dT%H:%M:%SZ')

return aria_groups