diff --git a/CHANGES.md b/CHANGES.md index aa19ddf7..698639ec 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ - ENH: Anticipate Sentinel C and D platforms in Reader's regexes - FIX: Resolve the inversion of resolution and pixel size between `stripmap` and `sliding_spotlight` types for `Capella` products - FIX: Get better window name (if available) when writing bands on disk (in tmp folder) +- FIX: Reject buggy Maxar products (with version 28.4) as the workaround would be too heavy to implement. ([#106](https://github.com/sertit/eoreader/issues/106)) - OPTIM: Save rasterized masks of DIMAP V2 products on disk to avoid recomputing them (`features.rasterize` could be a heavy computation that shouldn't be done twice) - COMPAT: EOReader works correctly with SNAP 10 ([#165](https://github.com/sertit/eoreader/issues/165)) diff --git a/eoreader/products/optical/maxar_product.py b/eoreader/products/optical/maxar_product.py index 3495fc0f..02c9b326 100644 --- a/eoreader/products/optical/maxar_product.py +++ b/eoreader/products/optical/maxar_product.py @@ -30,10 +30,12 @@ import numpy as np import xarray as xr from lxml import etree +from packaging.version import Version from rasterio import crs as riocrs -from sertit import geometry, path, rasters, vectors +from sertit import geometry, misc, path, rasters, vectors from sertit.misc import ListEnum -from sertit.types import AnyPathType +from sertit.types import AnyPathStrType, AnyPathType +from sertit.vectors import EPSG_4326 from shapely.geometry import Polygon from eoreader import DATETIME_FMT, EOREADER_NAME, cache @@ -395,6 +397,19 @@ class MaxarProduct(VhrProduct): for more information. """ + def __init__( + self, + product_path: AnyPathStrType, + archive_path: AnyPathStrType = None, + output_path: AnyPathStrType = None, + remove_tmp: bool = False, + **kwargs, + ) -> None: + self._version = None + + # Initialization from the super class + super().__init__(product_path, archive_path, output_path, remove_tmp, **kwargs) + def _pre_init(self, **kwargs) -> None: """ Function used to pre_init the products @@ -458,9 +473,24 @@ def _post_init(self, **kwargs) -> None: root, _ = self.read_mtd() band_combi = root.findtext(".//IMD/BANDID") if not band_combi: - raise InvalidProductError("Cannot find from BANDID in the metadata file") + raise InvalidProductError("Cannot find BANDID in the metadata file") self.band_combi = getattr(MaxarBandId, band_combi) + # Version + version = root.findtext(".//IMD/VERSION") + if not version: + raise InvalidProductError("Cannot find VERSION in the metadata file") + self._version = Version(version) + + if misc.compare_version(self._version, "28.4", "=="): + raise InvalidProductError( + f"This product (version {self._version}) is bugged." + "\nIt's .TIL file is maybe broken and the product may bundle several sub-products. " + "The best thing to do is to manually create a mosaic from all embedded .TIF files and pass it as a CustomStack to EOReader. " + "\nIf you want to have a stack in reflectance, don't forget to apply the corrections on each subproducts separatly before creating the mosaic." + "\nIf you want a workaround to be implemented, please reopen the issue https://github.com/sertit/eoreader/issues/106 and pledad you usecase :)" + ) + # Post init done by the super class super()._post_init(**kwargs) @@ -828,7 +858,7 @@ def _get_raw_crs(self) -> riocrs.CRS: if not map_proj_name: raise InvalidProductError("Cannot find MAPPROJNAME in the metadata file") if map_proj_name == "Geographic (Lat/Long)": - crs = riocrs.CRS.from_string("EPSG:4326") + crs = EPSG_4326 elif map_proj_name == "UTM": map_hemi = root.findtext(".//MAPHEMI") map_zone = root.findtext(".//MAPZONE") diff --git a/eoreader/reader.py b/eoreader/reader.py index 72aea111..bce48510 100644 --- a/eoreader/reader.py +++ b/eoreader/reader.py @@ -355,13 +355,13 @@ class Constellation(ListEnum): r"\d+_[RHV]{2}\.tif", ], }, - Constellation.QB02: r"\d{2}\w{3}\d{8}-.{4}(_R\dC\d|)-\d{12}_\d{2}_P\d{3}.TIL", - Constellation.GE01: r"\d{2}\w{3}\d{8}-.{4}(_R\dC\d|)-\d{12}_\d{2}_P\d{3}.TIL", - Constellation.WV01: r"\d{2}\w{3}\d{8}-.{4}(_R\dC\d|)-\d{12}_\d{2}_P\d{3}.TIL", - Constellation.WV02: r"\d{2}\w{3}\d{8}-.{4}(_R\dC\d|)-\d{12}_\d{2}_P\d{3}.TIL", - Constellation.WV03: r"\d{2}\w{3}\d{8}-.{4}(_R\dC\d|)-\d{12}_\d{2}_P\d{3}.TIL", - Constellation.WV04: r"\d{2}\w{3}\d{8}-.{4}(_R\dC\d|)-\d{12}_\d{2}_P\d{3}.TIL", - Constellation.MAXAR: r"\d{2}\w{3}\d{8}-.{4}(_R\dC\d|)-\d{12}_\d{2}_P\d{3}.TIL", + Constellation.QB02: r"\d{2}\w{3}\d{8}-.*.TIL", + Constellation.GE01: r"\d{2}\w{3}\d{8}-.*.TIL", + Constellation.WV01: r"\d{2}\w{3}\d{8}-.*.TIL", + Constellation.WV02: r"\d{2}\w{3}\d{8}-.*.TIL", + Constellation.WV03: r"\d{2}\w{3}\d{8}-.*.TIL", + Constellation.WV04: r"\d{2}\w{3}\d{8}-.*.TIL", + Constellation.MAXAR: r"\d{2}\w{3}\d{8}-.*.TIL", Constellation.ICEYE: r"ICEYE_(X\d{1,}_|)(SLC|GRD)_((SM|SL|SC)H*|SLEA)_\d{5,}_\d{8}T\d{6}\.xml", Constellation.SAOCOM: r"S1[AB]_OPER_SAR_EOSSP__CORE_L1[A-D]_OL(F|VF)_\d{8}T\d{6}.xemt", Constellation.CAPELLA: rf"{CONSTELLATION_REGEX[Constellation.CAPELLA]}.*\.json", @@ -562,8 +562,15 @@ def open( if not prod: LOGGER.warning( - "There is no existing products in EOReader corresponding to %s", - product_path, + f"There is no existing products in EOReader corresponding to {product_path}." + ) + LOGGER.info( + "Your given path may not be a satellite image. If it is, maybe the product isn't handled by EOReader. " + "If you are sure this product is handled, it is either corrupted or you may need to go deeper in the filetree to find the correct path to give." + ) + LOGGER.debug( + "Please look at what folder you should give to EOReader by accessing the documentation: " + "https://eoreader.readthedocs.io/en/latest/main_features.html#recognized-paths" ) return prod