diff --git a/CHANGES.md b/CHANGES.md index 2cb42f61..e7f450cb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ - **ENH: Handle Python 3.12. ([#113](https://github.com/sertit/eoreader/issues/113))** - **ENH: Guard against S1 COG format, not yet handled by SNAP.** - **ENH: Calibration step for `Capella` products now exists in ESA SNAP. Add it in pre-processing.** +- **ENH: Handling of Sentinel-1 SM products.** - FIX: Fix jpg, png... quicklooks management when plotting - FIX: Fix an `xarray` issue when trying to compute percentiles when stacking bands - CI: Update pre-commit hooks diff --git a/CI/SCRIPTS_SNAP/test_all_sat_end_to_end_on_disk.py b/CI/SCRIPTS_SNAP/test_all_sat_end_to_end_on_disk.py index 7d795f9c..fd9f7ce7 100644 --- a/CI/SCRIPTS_SNAP/test_all_sat_end_to_end_on_disk.py +++ b/CI/SCRIPTS_SNAP/test_all_sat_end_to_end_on_disk.py @@ -307,6 +307,12 @@ def test_s1_slc_zip_core(): test_s1_slc_zip_core() +@dask_env +def test_s1_slc_sm(): + """Function testing the support of Sentinel-1 constellation""" + _test_core_sar("*S1*_S4_SLC*.SAFE") + + @dask_env def test_s1_grdh(): """Function testing the support of Sentinel-1 constellation""" diff --git a/eoreader/data/cplx_s1_sm_preprocess_default.xml b/eoreader/data/cplx_s1_sm_preprocess_default.xml new file mode 100644 index 00000000..f7ea86ed --- /dev/null +++ b/eoreader/data/cplx_s1_sm_preprocess_default.xml @@ -0,0 +1,144 @@ + + 1.0 + + Read + + + ${file} + SENTINEL-1 + + + + + ThermalNoiseRemoval + + + + + + true + false + + + + + Calibration + + + + + + Latest Auxiliary File + + false + false + false + false + ${calib_pola} + true + false + false + + + + + Multilook + + + + + + 2 + 2 + true + true + + + + + + Terrain-Correction + + + + + + ${dem_name} + ${dem_path} + 0.0 + true + BILINEAR_INTERPOLATION + BILINEAR_INTERPOLATION + ${res_m} + ${res_deg} + ${crs} + false + 0.0 + 0.0 + false + false + false + false + false + false + true + false + false + false + false + Use projected local incidence angle from DEM + Use projected local incidence angle from DEM + Latest Auxiliary File + + + + + + LinearToFromdB + + + + + + + + + + Write + + + + + ${out} + BEAM-DIMAP + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/eoreader/products/optical/s2_e84_product.py b/eoreader/products/optical/s2_e84_product.py index c99c89e5..0aad33f2 100644 --- a/eoreader/products/optical/s2_e84_product.py +++ b/eoreader/products/optical/s2_e84_product.py @@ -1013,13 +1013,11 @@ def _get_path(self, file_id: str, ext="tif") -> str: def _read_mtd(self) -> (etree._Element, dict): """ - Read Landsat metadata as: - - - :code:`pandas.DataFrame` whatever its collection is (by default for collection 1) - - XML root + its namespace if the product is retrieved from the 2nd collection (by default for collection 2) + Read mtd. Args: force_pd (bool): If collection 2, return a pandas.DataFrame instead of an XML root + namespace + Returns: Tuple[Union[pd.DataFrame, etree._Element], dict]: Metadata as a Pandas.DataFrame or as (etree._Element, dict): Metadata XML root and its namespaces diff --git a/eoreader/products/sar/s1_product.py b/eoreader/products/sar/s1_product.py index 850ef6ad..c3d0eb0b 100644 --- a/eoreader/products/sar/s1_product.py +++ b/eoreader/products/sar/s1_product.py @@ -312,14 +312,13 @@ def _set_sensor_mode(self) -> None: if not mode: raise InvalidProductError("mode not found in metadata!") + # Mono swath SM + if mode in ["S1", "S2", "S3", "S4", "S5", "S6"]: + mode = "SM" + # Get sensor mode self.sensor_mode = S1SensorMode.from_value(mode) - # Discard invalid sensor mode - if self.sensor_mode != S1SensorMode.IW: - raise NotImplementedError( - f"For now, only IW sensor mode is used in EOReader processes: {self.name}" - ) if not self.sensor_mode: raise InvalidProductError( f"Invalid {self.constellation.value} name: {self.name}" diff --git a/eoreader/products/sar/sar_product.py b/eoreader/products/sar/sar_product.py index 0469d41b..920e8704 100644 --- a/eoreader/products/sar/sar_product.py +++ b/eoreader/products/sar/sar_product.py @@ -713,11 +713,12 @@ def _pre_process_sar(self, band: sab, pixel_size: float = None, **kwargs) -> str ) else: - sat = ( - "s1" - if self.constellation_id == Constellation.S1.name - else "sar" - ) + if self.constellation_id == Constellation.S1.name: + sat = "s1" + if self.sensor_mode.value == "SM": + sat += "_sm" + else: + sat = "sar" spt = ( "grd" if self.sar_prod_type == SarProductType.GDRG diff --git a/eoreader/reader.py b/eoreader/reader.py index e49955e3..bb456ccf 100644 --- a/eoreader/reader.py +++ b/eoreader/reader.py @@ -208,7 +208,7 @@ class Constellation(ListEnum): CONSTELLATION_REGEX = { - Constellation.S1: r"S1[AB]_(IW|EW|SM|WV)_(RAW|SLC|GRD|OCN)[FHM_]_[0-2]S[SD][HV]_\d{8}T\d{6}_\d{8}T\d{6}_\d{6}_.{11}(_COG|)", + Constellation.S1: r"S1[AB]_(IW|EW|SM|WV|S\d)_(RAW|SLC|GRD|OCN)[FHM_]_[0-2]S[SD][HV]_\d{8}T\d{6}_\d{8}T\d{6}_\d{6}_.{11}(_COG|)", Constellation.S2: r"S2[AB]_MSIL(1C|2A)_\d{8}T\d{6}_N\d{4}_R\d{3}_T\d{2}\w{3}_\d{8}T\d{6}", # Element84 : S2A_31UDQ_20230714_0_L2A, Sinergise: 0 or 1... Constellation.S2_E84: r"S2[AB]_\d{2}\w{3}_\d{8}_\d_L(1C|2A)", @@ -273,7 +273,7 @@ class Constellation(ListEnum): Constellation.S1: { "nested": 1, # File that can be found at any level (product/**/file) - "regex": r".*s1[ab]-(iw|ew|sm|wv)\d*-(raw|slc|grd|ocn)-[hv]{2}-\d{8}t\d{6}-\d{8}t\d{6}-\d{6}-\w{6}-\d{3}(-cog|)\.xml", + "regex": r".*s1[ab]-(iw|ew|sm|wv|s\d)\d*-(raw|slc|grd|ocn)-[hv]{2}-\d{8}t\d{6}-\d{8}t\d{6}-\d{6}-\w{6}-\d{3}(-cog|)\.xml", }, Constellation.S2: {"nested": 3, "regex": r"MTD_TL.xml"}, Constellation.S2_E84: rf"{CONSTELLATION_REGEX[Constellation.S2_E84]}\.json",