From 8f1fa49489c8a37ae545919a1f76f07448bfe775 Mon Sep 17 00:00:00 2001 From: BRAUN REMI Date: Wed, 21 Jun 2023 12:52:45 +0200 Subject: [PATCH] FIX: Use already computed bands stored in `tmp` for Planet products --- CHANGES.md | 6 ++ eoreader/__meta__.py | 2 +- eoreader/products/optical/pla_product.py | 35 --------- eoreader/products/optical/planet_product.py | 84 ++++++++++++++++++--- eoreader/products/optical/re_product.py | 36 --------- eoreader/products/optical/sky_product.py | 35 --------- 6 files changed, 80 insertions(+), 118 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3cc7ab96..07040f40 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,11 @@ # Release History +## 0.20.2 (2023-06-20) + +### Bug Fixes + +- FIX: Use already computed bands stored in `tmp` for Planet products + ## 0.20.1 (2023-06-20) ### Bug Fixes diff --git a/eoreader/__meta__.py b/eoreader/__meta__.py index 4ef603bc..7b725255 100644 --- a/eoreader/__meta__.py +++ b/eoreader/__meta__.py @@ -17,7 +17,7 @@ """ **EOReader** library """ -__version__ = "0.20.1" +__version__ = "0.20.2.dev0" __title__ = "eoreader" __description__ = ( "Remote-sensing opensource python library reading optical and SAR constellations, " diff --git a/eoreader/products/optical/pla_product.py b/eoreader/products/optical/pla_product.py index a3f8240d..b3109b79 100644 --- a/eoreader/products/optical/pla_product.py +++ b/eoreader/products/optical/pla_product.py @@ -467,41 +467,6 @@ def _get_stack_path(self, as_list: bool = False) -> Union[str, list]: return stack_path - def get_band_paths( - self, band_list: list, pixel_size: float = None, **kwargs - ) -> dict: - """ - Return the paths of required bands. - - .. code-block:: python - - >>> from eoreader.reader import Reader - >>> from eoreader.bands import * - >>> path = r"SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2" - >>> prod = Reader().open(path) - >>> prod.get_band_paths([GREEN, RED]) - { - : - 'SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2/SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2_FRE_B3.tif', - : - 'SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2/SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2_FRE_B4.tif' - } - - Args: - band_list (list): List of the wanted bands - pixel_size (float): Band pixel size - kwargs: Other arguments used to load bands - - Returns: - dict: Dictionary containing the path of each queried band - """ - band_paths = {} - path = self._get_stack_path(as_list=False) - for band in band_list: - band_paths[band] = path - - return band_paths - def _to_reflectance( self, band_arr: xr.DataArray, diff --git a/eoreader/products/optical/planet_product.py b/eoreader/products/optical/planet_product.py index d3b06caf..7fea7972 100644 --- a/eoreader/products/optical/planet_product.py +++ b/eoreader/products/optical/planet_product.py @@ -28,6 +28,7 @@ import geopandas as gpd import numpy as np +import rasterio import xarray as xr from cloudpathlib import CloudPath from lxml import etree @@ -200,7 +201,9 @@ def _post_init(self, **kwargs) -> None: (setting sensor type, band names and so on) """ # Manage Raw unit - band_name = files.get_filename(self.get_default_band_path()).upper().split("_") + band_name = ( + files.get_filename(self._get_stack_path(as_list=False)).upper().split("_") + ) if "SR" in band_name: self._raw_units = RawUnits.REFL elif "DN" in band_name: @@ -389,6 +392,48 @@ def footprint(self) -> gpd.GeoDataFrame: return gpd.GeoDataFrame(geometry=footprint.geometry, crs=footprint.crs) + def get_band_paths( + self, band_list: list, pixel_size: float = None, **kwargs + ) -> dict: + """ + Return the paths of required bands. + + .. code-block:: python + + >>> from eoreader.reader import Reader + >>> from eoreader.bands import * + >>> path = r"SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2" + >>> prod = Reader().open(path) + >>> prod.get_band_paths([GREEN, RED]) + { + : + 'SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2/SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2_FRE_B3.tif', + : + 'SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2/SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2_FRE_B4.tif' + } + + Args: + band_list (list): List of the wanted bands + pixel_size (float): Band pixel size + kwargs: Other arguments used to load bands + + Returns: + dict: Dictionary containing the path of each queried band + """ + band_paths = {} + path = self._get_stack_path(as_list=False) + for band in band_list: + # Get clean band path + clean_band = self._get_clean_band_path( + band, pixel_size=pixel_size, **kwargs + ) + if clean_band.is_file(): + band_paths[band] = clean_band + else: + band_paths[band] = path + + return band_paths + def _read_band( self, path: Union[CloudPath, Path], @@ -413,15 +458,32 @@ def _read_band( xr.DataArray: Band xarray """ - # Read band - band_arr = utils.read( - path, - pixel_size=pixel_size, - size=size, - resampling=Resampling.bilinear, - indexes=[self.bands[band].id], - **kwargs, - ) + with rasterio.open(str(path)) as dst: + # Manage the case if we open a simple band (EOReader processed bands) + if dst.count == 1: + # Read band + band_arr = utils.read( + path, + pixel_size=pixel_size, + size=size, + resampling=Resampling.bilinear, + **kwargs, + ) + + # Manage the case if we open a stack (native DIMAP bands) + else: + band_arr = utils.read( + path, + pixel_size=pixel_size, + size=size, + resampling=Resampling.bilinear, + indexes=[self.bands[band].id], + **kwargs, + ) + + # Pop useless long name + if "long_name" in band_arr.attrs: + band_arr.attrs.pop("long_name") # To float32 if band_arr.dtype != np.float32: @@ -526,7 +588,7 @@ def _load_bands( return {} # Get band paths - band_paths = self.get_band_paths(bands, **kwargs) + band_paths = self.get_band_paths(bands, pixel_size, **kwargs) # Open bands and get array (resampled if needed) band_arrays = self._open_bands( diff --git a/eoreader/products/optical/re_product.py b/eoreader/products/optical/re_product.py index 24f118ed..5a7215b3 100644 --- a/eoreader/products/optical/re_product.py +++ b/eoreader/products/optical/re_product.py @@ -261,42 +261,6 @@ def _get_stack_path(self, as_list: bool = False) -> Union[str, list]: return stack_path - def get_band_paths( - self, band_list: list, pixel_size: float = None, **kwargs - ) -> dict: - """ - Return the paths of required bands. - - .. code-block:: python - - >>> from eoreader.reader import Reader - >>> from eoreader.bands import * - >>> path = r"SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2" - >>> prod = Reader().open(path) - >>> prod.get_band_paths([GREEN, RED]) - { - : - 'SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2/SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2_FRE_B3.tif', - : - 'SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2/SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2_FRE_B4.tif' - } - - Args: - band_list (list): List of the wanted bands - pixel_size (float): Band pixel size - kwargs: Other arguments used to load bands - - Returns: - dict: Dictionary containing the path of each queried band - """ - band_paths = {} - path = self._get_stack_path(as_list=False) - - for band in band_list: - band_paths[band] = path - - return band_paths - def _dn_to_toa_rad(self, dn_arr: xr.DataArray, band: BandNames) -> xr.DataArray: """ Compute DN to TOA radiance diff --git a/eoreader/products/optical/sky_product.py b/eoreader/products/optical/sky_product.py index 2b561fac..ae4c7041 100644 --- a/eoreader/products/optical/sky_product.py +++ b/eoreader/products/optical/sky_product.py @@ -375,41 +375,6 @@ def _get_stack_path(self, as_list: bool = False) -> Union[str, list]: return stack_path - def get_band_paths( - self, band_list: list, pixel_size: float = None, **kwargs - ) -> dict: - """ - Return the paths of required bands. - - .. code-block:: python - - >>> from eoreader.reader import Reader - >>> from eoreader.bands import * - >>> path = r"SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2" - >>> prod = Reader().open(path) - >>> prod.get_band_paths([GREEN, RED]) - { - : - 'SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2/SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2_FRE_B3.tif', - : - 'SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2/SENTINEL2A_20190625-105728-756_L2A_T31UEQ_C_V2-2_FRE_B4.tif' - } - - Args: - band_list (list): List of the wanted bands - pixel_size (float): Band pixel size - kwargs: Other arguments used to load bands - - Returns: - dict: Dictionary containing the path of each queried band - """ - band_paths = {} - path = self._get_stack_path(as_list=False) - for band in band_list: - band_paths[band] = path - - return band_paths - def _to_reflectance( self, band_arr: xr.DataArray,