Skip to content

Commit

Permalink
FIX: Set correctly the SAR product type, with adding two types (`ORTH…
Browse files Browse the repository at this point in the history
…O` and `GEOCODED`)
  • Loading branch information
remi-braun committed Dec 10, 2024
1 parent 938cbe3 commit a89e7ca
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 64 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- FIX: Use the sun elevation angle rather than the sun zenith angle for STAC [#158](https://github.com/sertit/eoreader/issues/158)
- FIX: Create comparison operators for `BandNames`, removing the `xarray RuntimeWarning` about `sort order is undefined for incomparable objects`.
- FIX: Add some missing `@cache` around time-consuming functions
- FIX: Set correctly the SAR product type, with adding two types (`ORTHO` and `GEOCODED`)
- OPTIM: Cache the access to any archived file list, as this operation is expensive when done with large archives stored on the cloud (and thus better done only once).
- CI: Remove useless verbosity in CI
- DOC: Update `conf.py` (remove useless hunks and set Sphinx 7 as base)
Expand Down
8 changes: 6 additions & 2 deletions eoreader/products/sar/capella_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,12 @@ def _set_product_type(self) -> None:
prod_type = self.split_name[3]
self.product_type = getattr(CapellaProductType, prod_type)

if self.product_type in [CapellaProductType.GEO, CapellaProductType.GEC]:
self.sar_prod_type = SarProductType.GDRG
# WARNING: Capella don't seem to have Ground Range products...

if self.product_type == CapellaProductType.GEO:
self.sar_prod_type = SarProductType.ORTHO
elif self.product_type == CapellaProductType.GEC:
self.sar_prod_type = SarProductType.GEOCODED
elif self.product_type == CapellaProductType.SLC:
self.sar_prod_type = SarProductType.CPLX
else:
Expand Down
8 changes: 6 additions & 2 deletions eoreader/products/sar/cosmo_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,12 @@ def _set_product_type(self) -> None:

self.product_type = CosmoProductType.from_value(prod_type)

if self.product_type == CosmoProductType.DGM:
self.sar_prod_type = SarProductType.GDRG
if self.product_type == CosmoProductType.GTC:
self.sar_prod_type = SarProductType.ORTHO
elif self.product_type == CosmoProductType.GEC:
self.sar_prod_type = SarProductType.GEOCODED
elif self.product_type == CosmoProductType.DGM:
self.sar_prod_type = SarProductType.GRD
elif self.product_type == CosmoProductType.SCS:
self.sar_prod_type = SarProductType.CPLX
else:
Expand Down
6 changes: 1 addition & 5 deletions eoreader/products/sar/iceye_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,6 @@ class IceyeProductType(ListEnum):
SLC = "SLC"
""" Level-1 Single Look Complex (SLC) """

# Not released yet
# ORTHO = "ORTHO"
# """ ORTHO """


@unique
class IceyeSensorMode(ListEnum):
Expand Down Expand Up @@ -201,7 +197,7 @@ def _set_product_type(self) -> None:
self.product_type = IceyeProductType.from_value(prod_type)

if self.product_type == IceyeProductType.GRD:
self.sar_prod_type = SarProductType.GDRG
self.sar_prod_type = SarProductType.GRD
elif self.product_type == IceyeProductType.SLC:
self.sar_prod_type = SarProductType.CPLX
else:
Expand Down
47 changes: 28 additions & 19 deletions eoreader/products/sar/rcm_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,32 +42,43 @@
class RcmProductType(ListEnum):
"""
RADARSAT-Constellation projection identifier.
Take a look `here <https://catalyst.earth/catalyst-system-files/help/references/gdb_r/RADARSAT-2.html>`_.
Take a look `here <https://catalyst.earth/catalyst-system-files/enterprise-aerial-help/references/gdb_r/RADARSAT_Constellation.html>`_.
"""

SLC = "SLC"
""" Georeferenced. Single look complex data in slant range. """
"""
SLC represents a SLant range, georeferenced Complex product.
It is equivalent to a single-look complex product for RADARSAT-1 or RADARSAT-2).
"""

GRC = "GRC"
""" Georeferenced. Multilook complex data in ground range. """
"""
GRC represents GRound range, georeferenced, Complex products.
"""

GRD = "GRD"
""" Georeferenced. Multilook detected data in ground range. """
"""
GRD represents GRound range, georeferenced, Detected.
GRD is equivalent to an SGX, SCN, or SCW product for RADARSAT-1 or RADARSAT-2.
"""

GCC = "GCC"
"""
Geocoded to a map projection.
Complex data.
Data commonly projected to Universal Transverse Mercator Projection (UTM)
or Universal Polar Stereographic (UPS) north of 84N or south of 80S.
GCC represents GeoCoded Complex products.
"""

GCD = "GCD"
"""
Geocoded to a map projection.
Detected data.
Data commonly projected to Universal Transverse Mercator (UTM)
or Universal Polar Stereographic (UPS) north of 84N or south of 80S.
GCD represents GeoCoded Detected products.
GCD is equivalent to an SSG or SPG product for RADARSAT-1 or RADARSAT-2.
"""

MLC = "MLC"
"""
MLC represent Multi-Look slant range Complex products.
It is for dual Co-/Cross-Polarization1 or Compact Polarization which is a spatially averaged version of the SLC product condensed to a single multi-burst image of the covariance matrix elements.
The covariance matrix elements consist of two real diagonal elements |xH|2 and |xV|2, and a complex off-diagonal element xH*conj(xV) where x is either Circular,
H or V depending on the SLC product polarization setting and conj denotes the complex conjugate.
"""


Expand Down Expand Up @@ -230,13 +241,11 @@ def _set_product_type(self) -> None:

self.product_type = RcmProductType.from_value(prod_type)

if self.product_type in [RcmProductType.GRD, RcmProductType.GCD]:
self.sar_prod_type = SarProductType.GDRG
elif self.product_type in [
RcmProductType.SLC,
RcmProductType.GRC,
RcmProductType.GCC,
]:
if self.product_type in [RcmProductType.GRD, RcmProductType.GRC]:
self.sar_prod_type = SarProductType.GRD
elif self.product_type in [RcmProductType.GCD, RcmProductType.GCC]:
self.sar_prod_type = SarProductType.GEOCODED
elif self.product_type in [RcmProductType.SLC, RcmProductType.MLC]:
self.sar_prod_type = SarProductType.CPLX
else:
raise NotImplementedError(
Expand Down
6 changes: 5 additions & 1 deletion eoreader/products/sar/rs2_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,12 @@ def _set_product_type(self) -> None:
"""Set products type"""
if self.product_type == Rs2ProductType.SLC:
self.sar_prod_type = SarProductType.CPLX
elif self.product_type in [Rs2ProductType.SGX, Rs2ProductType.SGF]:
self.sar_prod_type = SarProductType.GEOCODED
elif self.product_type in [Rs2ProductType.SSG, Rs2ProductType.SPG]:
self.sar_prod_type = SarProductType.ORTHO
else:
self.sar_prod_type = SarProductType.GDRG
self.sar_prod_type = SarProductType.GRD

if self.product_type not in [
Rs2ProductType.SGF,
Expand Down
10 changes: 3 additions & 7 deletions eoreader/products/sar/s1_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,8 @@ def _pre_init(self, **kwargs) -> None:
# Pre init done by the super class
super()._pre_init(**kwargs)

# Check if COG in name
if (
"_COG" in self.filename
and self._need_snap
and not self._has_snap_10_or_higher()
):
# Check if COG in name (S1 needs always SNAP)
if "_COG" in self.filename and not self._has_snap_10_or_higher():
raise NotImplementedError(
"S1 COG products are only handled by SNAP 10.0 or higher. "
"Please upgrade your software to process this product."
Expand Down Expand Up @@ -277,7 +273,7 @@ def _set_product_type(self) -> None:
self.product_type = S1ProductType.from_value(prod_type)

if self.product_type == S1ProductType.GRD:
self.sar_prod_type = SarProductType.GDRG
self.sar_prod_type = SarProductType.GRD
elif self.product_type == S1ProductType.SLC:
self.sar_prod_type = SarProductType.CPLX
else:
Expand Down
12 changes: 6 additions & 6 deletions eoreader/products/sar/saocom_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,12 +321,12 @@ def _set_product_type(self) -> None:

self.product_type = SaocomProductType.from_value(prod_type)

if self.product_type in [
SaocomProductType.DI,
SaocomProductType.GEC,
SaocomProductType.GTC,
]:
self.sar_prod_type = SarProductType.GDRG
if self.product_type == SaocomProductType.DI:
self.sar_prod_type = SarProductType.GRD
elif self.product_type == SaocomProductType.GEC:
self.sar_prod_type = SarProductType.GEOCODED
elif self.product_type == SaocomProductType.GTC:
self.sar_prod_type = SarProductType.ORTHO
elif self.product_type == SaocomProductType.SLC:
self.sar_prod_type = SarProductType.CPLX
else:
Expand Down
34 changes: 18 additions & 16 deletions eoreader/products/sar/sar_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,19 @@ class SarProductType(ListEnum):
"""

CPLX = "COMPLEX"
"""Single Look Complex"""
"""Complex image (most likely Single Look Complex)"""

GDRG = "GROUND"
"""Ground Range"""
GRD = "GROUND RANGE"
"""Ground Range image"""

GEOCODED = "GEOCODED"
"""Already geocoded image: don't need SNAP. To orthorectify it, you may need to take GCP by hand..."""

ORTHO = "ORTHO"
"""Already orthorecified image: don't need SNAP"""

OTHER = "OTHER"
"""Other products types, no used in EOReader"""
# Add ortho products ?
"""Other products types, not used in EOReader"""


class _ExtendedFormatter(Formatter):
Expand Down Expand Up @@ -193,6 +198,9 @@ def __init__(
# Initialization from the super class
super().__init__(product_path, archive_path, output_path, remove_tmp, **kwargs)

self._need_snap = self._need_snap_to_pre_process()
self.is_ortho = self.sar_prod_type == SarProductType.ORTHO

def _map_bands(self) -> None:
"""
Map bands
Expand All @@ -218,8 +226,6 @@ def _pre_init(self, **kwargs) -> None:
self.tile_name = None
self.sensor_type = SensorType.SAR
self.bands = SarBandMap()
self.is_ortho = False
self._need_snap = self._need_snap_to_pre_process()

def _post_init(self, **kwargs) -> None:
"""
Expand Down Expand Up @@ -258,14 +264,7 @@ def _get_predictor(self) -> int:

def _need_snap_to_pre_process(self):
"""This product needs SNAP for pre-process."""
raw_band_path = self.get_raw_band_paths()

# Cannot use get_default_band here, because of recursion
def_key = list(raw_band_path.keys())[0]
with rasterio.open(raw_band_path[def_key]) as ds:
raw_crs = ds.crs

need_snap = not (raw_crs is not None and raw_crs.is_projected)
need_snap = self.sar_prod_type in [SarProductType.CPLX, SarProductType.GRD]
return need_snap

@cache
Expand Down Expand Up @@ -323,6 +322,7 @@ def get_default_band(self) -> BandNames:

return default_band

@cache
def get_default_band_path(self, **kwargs) -> AnyPathType:
"""
Get default band path (the first existing one between :code:`VV` and :code:`HH` for SAR data), ready to use (orthorectified)
Expand Down Expand Up @@ -504,6 +504,7 @@ def get_raw_band_paths(self, **kwargs) -> dict:
extended_fmt = _ExtendedFormatter()
band_paths = {}
for band in sab.speckle_list():
LOGGER.debug(f"get RAW band path for {band.name}")
band_regex = extended_fmt.format(self._raw_band_regex, band.value)

if self.is_archived:
Expand All @@ -530,6 +531,7 @@ def get_raw_band_paths(self, **kwargs) -> dict:

return band_paths

@cache
def _get_raw_bands(self) -> list:
"""
Return the existing band paths (as they come with th archived products).
Expand Down Expand Up @@ -742,7 +744,7 @@ def _pre_process_sar(self, band: sab, pixel_size: float = None, **kwargs) -> str
sat = "no_calib"
else:
sat = "sar"
spt = "grd" if self.sar_prod_type == SarProductType.GDRG else "cplx"
spt = "grd" if self.sar_prod_type == SarProductType.GRD else "cplx"
pp_graph = utils.get_data_dir().joinpath(
f"{spt}_{sat}_preprocess_default.xml"
)
Expand Down
12 changes: 6 additions & 6 deletions eoreader/products/sar/tsx_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,12 +400,12 @@ def _set_product_type(self) -> None:

self.product_type = TsxProductType.from_value(prod_type)

if self.product_type in [
TsxProductType.MGD,
TsxProductType.GEC,
TsxProductType.EEC,
]:
self.sar_prod_type = SarProductType.GDRG
if self.product_type == TsxProductType.MGD:
self.sar_prod_type = SarProductType.GRD
elif self.product_type == TsxProductType.GEC:
self.sar_prod_type = SarProductType.GEOCODED
elif self.product_type == TsxProductType.EEC:
self.sar_prod_type = SarProductType.ORTHO
elif self.product_type == TsxProductType.SSC:
self.sar_prod_type = SarProductType.CPLX
else:
Expand Down

0 comments on commit a89e7ca

Please sign in to comment.