Skip to content

Commit

Permalink
OPTIM: Use default (and optimized) predictor in rasters.write if SN…
Browse files Browse the repository at this point in the history
…AP is version 10 or higher #173
  • Loading branch information
remi-braun committed Aug 13, 2024
1 parent 123a0cb commit 0202839
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 25 deletions.
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

- ENH: Add a `BandType` alias for any types that could be a band: a string, a `BandNames` or any of its children: Spectral, SAR, DEM or Cloud band names
- FIX: Get better window name (if available) when writing bands on disk (in tmp folder)
- COMPAT: EOReader handles with SNAP10 ([#165](https://github.com/sertit/eoreader/issues/165))
- OPTIM: Use default (and optimized) predictor in `rasters.write` if SNAP is version 10 or higher ([#173](https://github.com/sertit/eoreader/issues/173))
- COMPAT: EOReader works correctly with SNAP 10 ([#165](https://github.com/sertit/eoreader/issues/165))

## 0.21.2 (2024-07-30)

Expand Down
2 changes: 1 addition & 1 deletion eoreader/bands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ def is_sar_band(band: BandType) -> bool:
return is_valid


def is_sat_band(BandType) -> bool:
def is_sat_band(band: BandType) -> bool:
"""
Returns True if is a satellite band (from both :code:`SarBandNames` or :code:`SpectralBandNames`)
Expand Down
6 changes: 2 additions & 4 deletions eoreader/products/sar/cosmo_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
from eoreader.exceptions import InvalidProductError
from eoreader.products import SarProduct, SarProductType
from eoreader.products.product import OrbitDirection
from eoreader.products.sar.sar_product import SAR_PREDICTOR

LOGGER = logging.getLogger(EOREADER_NAME)

Expand Down Expand Up @@ -577,15 +576,14 @@ def _pre_process_sar(self, band, pixel_size: float = None, **kwargs) -> str:
# Write
# WARNING: Set nodata to 0 here as it is the value wanted by SNAP !

# SNAP fails with classic predictor !!! Set the predictor to the default value (1) !!!
# SNAP < 10.0.0 fails with classic predictor !!! Set the predictor to the default value (1) !!!
# Caused by: javax.imageio.IIOException: Illegal value for Predictor in TIFF file
# https://forum.step.esa.int/t/exception-found-when-reading-compressed-tif/654/7
rasters_rio.write(
merged_array,
merged_meta,
pp_path,
nodata=self._snap_no_data,
predictor=SAR_PREDICTOR,
predictor=self._get_predictor(),
)

return pp_path
91 changes: 72 additions & 19 deletions eoreader/products/sar/sar_product.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,6 @@

LOGGER = logging.getLogger(EOREADER_NAME)

SAR_PREDICTOR = 1
"""
Set LZW predictor to 1 in order SNAP to be able to read this GEoTiff.
Caused by: javax.imageio.IIOException: Illegal value for Predictor in TIFF file
https://forum.step.esa.int/t/exception-found-when-reading-compressed-tif/654/7
"""


@unique
class SnapDems(ListEnum):
Expand Down Expand Up @@ -193,6 +184,8 @@ def __init__(
self._snap_no_data = 0
self._raw_no_data = 0

self._need_snap = None

# Calibrate or not
self._calibrate = True

Expand Down Expand Up @@ -225,6 +218,7 @@ def _pre_init(self, **kwargs) -> 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 All @@ -234,6 +228,70 @@ def _post_init(self, **kwargs) -> None:
self._set_sensor_mode()
self.pol_channels = self._get_raw_bands()

@cache
def get_snap_version(self):
try:
return snap.get_snap_version()
except AttributeError:
# TODO: To be removed with sertit >= 1.42
import subprocess

from packaging.version import Version

snap_version = None
try:
output = subprocess.run(["gpt", "--diag"], capture_output=True)
except FileNotFoundError:
raise FileNotFoundError("'gpt' not found in your PATH")

stdout = output.stdout.decode("utf-8")

if stdout is not None:
version_str = stdout.split("\n")
try:
version_str = [v for v in version_str if "version" in v][0]
except IndexError as ex:
LOGGER.debug(ex)
else:
snap_version = version_str.split(" ")[-1]

snap_version = Version(snap_version)

return snap_version

@cache
def _has_snap_10_or_higher(self) -> bool:
"""True if SNAP version is 10 or higher"""
try:
return misc.compare_version(self.get_snap_version(), "10.0.0", ">=")
except TypeError:
# TODO: To be removed with sertit >= 1.42
from packaging.version import Version

misc.compare(self.get_snap_version(), Version("10.0.0"), ">=")

def _get_predictor(self) -> int:
"""
Get LZW predictor to 1 in order SNAP < 10.0.0 to be able to read this GeoTiff (in dspk operations mostly).
Caused by: javax.imageio.IIOException: Illegal value for Predictor in TIFF file
Leave it to None if SNAP is 10 or higher
"""
return None if self._has_snap_10_or_higher() else 1

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)
return need_snap

@cache
@simplify
def footprint(self) -> gpd.GeoDataFrame:
Expand Down Expand Up @@ -668,14 +726,10 @@ def _pre_process_sar(self, band: sab, pixel_size: float = None, **kwargs) -> str
else def_pixel_size
)

raw_band_path = str(self.get_raw_band_paths(**kwargs)[band])
with rasterio.open(raw_band_path) as ds:
raw_crs = ds.crs

if raw_crs and raw_crs.is_projected:
if not self._need_snap:
# Set the nodata and write the image where they belong
arr = utils.read(
raw_band_path,
self.get_raw_band_paths(**kwargs)[band],
pixel_size=pixel_size if pixel_size != 0 else None,
masked=False,
)
Expand All @@ -690,7 +744,7 @@ def _pre_process_sar(self, band: sab, pixel_size: float = None, **kwargs) -> str
file_path,
dtype=np.float32,
nodata=self._snap_no_data,
predictor=SAR_PREDICTOR,
predictor=self._get_predictor(),
)
return file_path
else:
Expand Down Expand Up @@ -915,15 +969,14 @@ def interp_na(array, dim):
)
# WARNING: Set nodata to 0 here as it is the value wanted by SNAP !

# SNAP fails with classic predictor !!! Set the predictor to the default value (1) !!!
# SNAP < 10.0.0 fails with classic predictor !!! Set the predictor to the default value (1) !!!
# Caused by: javax.imageio.IIOException: Illegal value for Predictor in TIFF file
# https://forum.step.esa.int/t/exception-found-when-reading-compressed-tif/654/7
utils.write(
arr,
file_path,
dtype=np.float32,
nodata=self._snap_no_data,
predictor=SAR_PREDICTOR,
predictor=self._get_predictor(),
)

return file_path
Expand Down

0 comments on commit 0202839

Please sign in to comment.