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

V7.1.1 #300

Merged
merged 20 commits into from
Apr 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c3e3575
makes ASFProduct more resilient to missing sort keys for results sort…
Apr 4, 2024
8f89be3
update changelog
Apr 4, 2024
469c056
minor tweak to repair log message
Apr 4, 2024
4c87595
moves ariaS1GUNWProduct check in search_generator directly into class…
Apr 4, 2024
7be92a7
changes ASFSearchOptions __str__ json serialization to use default ke…
Apr 4, 2024
57d6ce5
Merge branch 'master' into topic-exp-product-debugging
SpicyGarlicAlbacoreRoll Apr 17, 2024
32dcc60
swaps dateparser for ciso8601 for parsing dates in stacking operations
Apr 22, 2024
ec134ef
removes unused python-dateutil from setup.py
Apr 22, 2024
cae1c34
updates setup.py, dev status now Production/Stable, adds versions 10-…
Apr 22, 2024
9ace097
update pytest and pytest-automation requirement
Apr 24, 2024
136ad97
Merge branch 'master' into topic-exp-product-debugging
SpicyGarlicAlbacoreRoll Apr 24, 2024
1eb8e68
removes _get_populated_properties(), makes _read_property() that wrap…
Apr 24, 2024
28039b3
update changelog
Apr 24, 2024
a7ca6bc
Merge pull request #290 from asfadmin/topic-exp-product-debugging
SpicyGarlicAlbacoreRoll Apr 24, 2024
6359140
Merge branch 'master' into topic-setup-update
SpicyGarlicAlbacoreRoll Apr 24, 2024
0167999
Merge branch 'master' into topic-baseline-speedup
SpicyGarlicAlbacoreRoll Apr 24, 2024
564899d
Merge pull request #298 from asfadmin/topic-baseline-speedup
SpicyGarlicAlbacoreRoll Apr 25, 2024
57b9079
Merge branch 'master' into topic-setup-update
SpicyGarlicAlbacoreRoll Apr 25, 2024
0bdc60c
Merge pull request #299 from asfadmin/topic-setup-update
SpicyGarlicAlbacoreRoll Apr 25, 2024
1bf62d1
Merge branch 'stable' into master
SpicyGarlicAlbacoreRoll Apr 25, 2024
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
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,24 @@ and uses [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
-

-->
------
## [v7.1.1](https://github.com/asfadmin/Discovery-asf_search/compare/v7.1.0...v7.1.1)
### Changed
- Uses `ciso8601.parse_datetime()` in baseline calculations, speeds up calculations on larger stacks
### Added
- Adds `ASF_LOGGER` logging in `search_generator()` and related methods
### Fixed
- `ASFProduct.get_sort_keys()` will no longer returns `None` if missing sort key, defaults to empty string

------
## [v7.1.0](https://github.com/asfadmin/Discovery-asf_search/compare/v7.0.9...v7.1.0)
### Added
- Improved logging in `ASFSession` authentication methods

### Changed
- Uses `ciso8601` module for parsing dates from CMR response, significant performance improvement post-query
- `ASFSession` now allows for authorized user access to hidden/restricted CMR datasets via `auth_with_creds()` or `auth_with_cookiejar()` authentication methods (previously only supported via `auth_with_token()` method)
- `ASFSession.auth_with_token()` now authenticates directly against EDL endpoint
- UMM Platform ShortName used as final fallback criteria for product subclass assignment

------
## [v7.0.9](https://github.com/asfadmin/Discovery-asf_search/compare/v7.0.8...v7.0.9)
Expand Down
26 changes: 23 additions & 3 deletions asf_search/ASFProduct.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,32 @@ def get_property_paths() -> Dict:
"""
return ASFProduct._base_properties

def get_sort_keys(self) -> Tuple:
def get_sort_keys(self) -> Tuple[str, str]:
"""
Returns tuple of primary and secondary date values used for sorting final search results
Any subclasses must return string for final `sort()` to work
"""
return (self.properties.get('stopTime'), self.properties.get('fileID', 'sceneName'))

# `sort()` will raise an error when comparing `NoneType`,
# using self._read_property() to wrap standard `dict.get()` for possible `None` values
primary_key = self._read_property(key='stopTime', default='')
secondary_key = self._read_property(
key='fileID',
default=self._read_property('sceneName', '')
)

return (primary_key, secondary_key)

def _read_property(self, key: str, default: Any = None) -> Any:
"""
Helper method wraps `properties.get()`.
Since a property can be `None`, if the key exists `dict.get('key', 'default')` will never return the default
"""
output = default
if (value:=self.properties.get(key)) is not None:
output = value

return output

@final
@staticmethod
def umm_get(item: Dict, *args):
Expand Down
2 changes: 1 addition & 1 deletion asf_search/ASFSearchOptions/ASFSearchOptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def __str__(self):
"""
What to display if `print(opts)` is called.
"""
return json.dumps(dict(self), indent=4)
return json.dumps(dict(self), indent=4, default=str)

# Default is set to '...', since 'None' is a very valid value here
def pop(self, key, default=...):
Expand Down
12 changes: 11 additions & 1 deletion asf_search/Products/ARIAS1GUNWProduct.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import Dict
from asf_search import ASFSession
from asf_search.ASFProduct import ASFProduct
from asf_search.ASFSearchOptions import ASFSearchOptions
from asf_search.Products import S1Product
from asf_search.CMR.translate import try_parse_float
Expand Down Expand Up @@ -54,4 +55,13 @@ def get_default_baseline_product_type() -> None:
"""
Returns the product type to search for when building a baseline stack.
"""
return None
return None

@staticmethod
def is_ARIAS1GUNWProduct(item: Dict) -> bool:
platform = ASFProduct.umm_get(item['umm'], 'Platforms', 0, 'ShortName')
if platform in ['SENTINEL-1A', 'SENTINEL-1B']:
asf_platform = ASFProduct.umm_get(item['umm'], 'AdditionalAttributes', ('Name', 'ASF_PLATFORM'), 'Values', 0)
return 'Sentinel-1 Interferogram' in asf_platform

return False
10 changes: 5 additions & 5 deletions asf_search/Products/NISARProduct.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Dict, Union
from typing import Dict, Tuple, Union
from asf_search import ASFSearchOptions, ASFSession, ASFStackableProduct
from asf_search.CMR.translate import try_parse_float, try_parse_int, try_round_float
from asf_search.constants import PRODUCT_TYPE
Expand Down Expand Up @@ -48,10 +48,10 @@ def get_property_paths() -> Dict:
**NISARProduct._base_properties
}

def get_sort_keys(self):
def get_sort_keys(self) -> Tuple[str, str]:
keys = super().get_sort_keys()

if keys[0] is None:
return (self.properties.get('processingDate', ''), keys[1])
if keys[0] == '':
return (self._read_property('processingDate', ''), keys[1])

return keys
8 changes: 4 additions & 4 deletions asf_search/Products/OPERAS1Product.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Dict
from typing import Dict, Tuple
from asf_search import ASFSearchOptions, ASFSession
from asf_search.CMR.translate import try_parse_date
from asf_search.Products import S1Product
Expand Down Expand Up @@ -71,10 +71,10 @@ def get_stack_opts(self, opts: ASFSearchOptions = None) -> ASFSearchOptions:
"""
return None

def get_sort_keys(self):
def get_sort_keys(self) -> Tuple[str, str]:
keys = super().get_sort_keys()

if keys[0] is None:
keys = self.properties.get('validityStartDate'), keys[1]
if keys[0] == '':
return (self._read_property('validityStartDate', ''), keys[1])

return keys
2 changes: 1 addition & 1 deletion asf_search/WKT/RepairEntry.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ def __init__(self, report_type: str, report: str) -> None:
self.report = report

def __str__(self) -> str:
return f'{self.report_type}\n\t{self.report}'
return f"{self.report_type}: {self.report}"
6 changes: 3 additions & 3 deletions asf_search/WKT/validate_wkt.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from asf_search.exceptions import ASFWKTError


def validate_wkt(aoi: Union[str, BaseGeometry]) -> Tuple[BaseGeometry, List[RepairEntry]]:
def validate_wkt(aoi: Union[str, BaseGeometry]) -> Tuple[BaseGeometry, BaseGeometry, List[RepairEntry]]:
"""
Param aoi: the WKT string or Shapely Geometry to validate and prepare for the CMR query
Validates the given area of interest, and returns a validated and simplified WKT string
Expand Down Expand Up @@ -52,7 +52,7 @@ def _search_wkt_prep(shape: BaseGeometry):
if isinstance(shape, Polygon):
return orient(Polygon(shape.exterior), sign=1.0)

def _simplify_geometry(geometry: BaseGeometry) -> Tuple[BaseGeometry, List[RepairEntry]]:
def _simplify_geometry(geometry: BaseGeometry) -> Tuple[BaseGeometry, BaseGeometry, List[RepairEntry]]:
"""
param geometry: AOI Shapely Geometry to be prepped for CMR
prepares geometry for CMR by:
Expand Down Expand Up @@ -165,7 +165,7 @@ def _counter_clockwise_reorientation(geometry: Union[Point, LineString, Polygon]
return reoriented, None


def _get_clamped_and_wrapped_geometry(shape: BaseGeometry) -> Tuple[BaseGeometry, List[RepairEntry]]:
def _get_clamped_and_wrapped_geometry(shape: BaseGeometry) -> Tuple[BaseGeometry, BaseGeometry, List[RepairEntry]]:
"""
param geometry: Shapely geometry to clamp
Clamps geometry to +/-90 latitude and wraps longitude +/-180
Expand Down
12 changes: 6 additions & 6 deletions asf_search/baseline/calc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from typing import List

import numpy as np
from dateutil.parser import parse
from ciso8601 import parse_datetime

from asf_search import ASFProduct
# WGS84 constants
Expand All @@ -23,17 +23,17 @@ def calculate_perpendicular_baselines(reference: str, stack: List[ASFProduct]):
baselineProperties['noStateVectors'] = True
continue

asc_node_time = parse(baselineProperties['ascendingNodeTime']).timestamp()
asc_node_time = parse_datetime(baselineProperties['ascendingNodeTime']).timestamp()

start = parse(product.properties['startTime']).timestamp()
end = parse(product.properties['stopTime']).timestamp()
start = parse_datetime(product.properties['startTime']).timestamp()
end = parse_datetime(product.properties['stopTime']).timestamp()
center = start + ((end - start) / 2)
baselineProperties['relative_start_time'] = start - asc_node_time
baselineProperties['relative_center_time'] = center - asc_node_time
baselineProperties['relative_end_time'] = end - asc_node_time

t_pre = parse(positionProperties['prePositionTime']).timestamp()
t_post = parse(positionProperties['postPositionTime']).timestamp()
t_pre = parse_datetime(positionProperties['prePositionTime']).timestamp()
t_post = parse_datetime(positionProperties['postPositionTime']).timestamp()
product.baseline['relative_sv_pre_time'] = t_pre - asc_node_time
product.baseline['relative_sv_post_time'] = t_post - asc_node_time

Expand Down
6 changes: 3 additions & 3 deletions asf_search/baseline/stack.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from typing import Tuple, List
from dateutil.parser import parse
from ciso8601 import parse_datetime
import pytz

from .calc import calculate_perpendicular_baselines
Expand Down Expand Up @@ -66,12 +66,12 @@ def calculate_temporal_baselines(reference: ASFProduct, stack: ASFSearchResults)
:param stack: The stack to operate on.
:return: None, as the operation occurs in-place on the stack provided.
"""
reference_time = parse(reference.properties['startTime'])
reference_time = parse_datetime(reference.properties['startTime'])
if reference_time.tzinfo is None:
reference_time = pytz.utc.localize(reference_time)

for secondary in stack:
secondary_time = parse(secondary.properties['startTime'])
secondary_time = parse_datetime(secondary.properties['startTime'])
if secondary_time.tzinfo is None:
secondary_time = pytz.utc.localize(secondary_time)
secondary.properties['temporalBaseline'] = (secondary_time.date() - reference_time.date()).days
Expand Down
7 changes: 5 additions & 2 deletions asf_search/search/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from copy import copy
import datetime

from asf_search import ASFSearchResults
from asf_search import ASF_LOGGER, ASFSearchResults
from asf_search.ASFSearchOptions import ASFSearchOptions
from asf_search.search.search_generator import search_generator

Expand Down Expand Up @@ -99,6 +99,9 @@ def search(
results.searchComplete = page.searchComplete
results.searchOptions = page.searchOptions

results.sort(key=lambda p: p.get_sort_keys(), reverse=True)
try:
results.sort(key=lambda p: p.get_sort_keys(), reverse=True)
except TypeError as exc:
ASF_LOGGER.warning(f"Failed to sort final results, leaving results unsorted. Reason: {exc}")

return results
Loading
Loading