Skip to content

Commit

Permalink
ENH: Allow to give eoreader.Product instead of paths to create any …
Browse files Browse the repository at this point in the history
…Set #8
  • Loading branch information
remi-braun committed Jan 14, 2025
1 parent 1df7563 commit 959b1e4
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 31 deletions.
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Release History

## 0.2.6 (2024-mm-dd)
## 0.3.0 (2024-mm-dd)

- **ENH: Allow to give `eoreader.Product` instead of paths to create any Set** ([#8](https://github.com/sertit/eoreader/issues/8))
- **ENH: Drop `isort`, `black` and `flake8` and use `ruff`**
- **ENH: Use `pyproject.toml` instead of `setup.py`**
- FIX: Don't fail in case of a string is given as Mosaic path.
Expand Down
2 changes: 1 addition & 1 deletion NOTICE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
EOSets Copyright 2022 ICube-Sertit - France
EOSets Copyright 2025 ICube-Sertit - France

This software is distributed under the Apache Software License (ASL) v2.0, see LICENSE
file or http://www.apache.org/licenses/LICENSE-2.0 for details.
Expand Down
30 changes: 30 additions & 0 deletions ci/test_mosaic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest
from eoreader.bands import NBR, NDVI, RED
from eoreader.env_vars import CI_EOREADER_BAND_FOLDER, DEM_PATH
from eoreader.reader import Reader
from sertit import ci
from tempenv import tempenv

Expand Down Expand Up @@ -131,6 +132,35 @@ def test_mono_mosaic(tmp_path):
# Just see if this doesn't fail


def test_mosaic_from_custom_prod(tmp_path):
with tempenv.TemporaryEnvironment(
{CI_EOREADER_BAND_FOLDER: get_ci_mosaic_data_dir()}
):
output = get_output(tmp_path, "MOSAIC", ON_DISK)

# Get a custom stack path
pld_psh_path = data_folder() / "pld_psh.tif"

# Create object
pld_psh = Reader().open(
pld_psh_path,
custom=True,
sensor_type="OPTICAL",
band_map={"BLUE": 1, "GREEN": 2, "RED": 3, "NIR": 4},
)
mosaic = Mosaic(pld_psh, mosaic_method="VRT", remove_tmp=not ON_DISK)
mosaic.output = os.path.join(output, mosaic.condensed_name)
mosaic.stack(
[NDVI],
pixel_size=60,
)

# Some checks
# TODO: add more
ci.assert_val(mosaic.is_optical, True, "Is Optical?")
ci.assert_val(mosaic.is_sar, False, "Is SAR?")


def test_ci_eoreader_band_folder(tmp_path):
"""Test mosaic with CI_EOREADER_BAND_FOLDER set to an arbitrary diretcory."""
with tempenv.TemporaryEnvironment(
Expand Down
25 changes: 25 additions & 0 deletions ci/test_pair.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pytest
from eoreader.bands import BLUE, GREEN, NIR, PAN, RED
from eoreader.env_vars import CI_EOREADER_BAND_FOLDER, DEM_PATH
from eoreader.reader import Reader
from sertit import ci
from tempenv import tempenv

Expand Down Expand Up @@ -187,6 +188,30 @@ def test_pair_no_secondary(tmp_path):
_test_pair_core(l8_paths, tmp_path)


def test_pair_from_custom_prod(tmp_path):
with tempenv.TemporaryEnvironment(
{CI_EOREADER_BAND_FOLDER: get_ci_pair_data_dir()}
):
output = get_output(tmp_path, "PAIR", ON_DISK)

# Get a custom stack path
pld_psh_path = data_folder() / "pld_psh.tif"

# Create object
pld_psh = Reader().open(
pld_psh_path,
custom=True,
sensor_type="OPTICAL",
band_map={"BLUE": 1, "GREEN": 2, "RED": 3, "NIR": 4},
)
pair = Pair(**{"reference_paths": pld_psh}, remove_tmp=not ON_DISK)
pair.output = os.path.join(output, pair.condensed_name)
pair.stack(
["NDVI"],
pixel_size=60,
)


@s3_env
def test_pair_fail():
"""Test failure for pair objects"""
Expand Down
25 changes: 25 additions & 0 deletions ci/test_series.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import pytest
from eoreader.bands import RED
from eoreader.env_vars import CI_EOREADER_BAND_FOLDER
from eoreader.reader import Reader
from sertit import ci
from tempenv import tempenv

Expand Down Expand Up @@ -121,3 +122,27 @@ def test_mono_series(tmp_path):
series.stack(RED, window=aoi_path, pixel_size=60)

# Just see if this doesn't fail


def test_series_from_custom_prod(tmp_path):
with tempenv.TemporaryEnvironment(
{CI_EOREADER_BAND_FOLDER: get_ci_series_data_dir()}
):
output = get_output(tmp_path, "SERIES", ON_DISK)

# Get a custom stack path
pld_psh_path = data_folder() / "pld_psh.tif"

# Create object
pld_psh = Reader().open(
pld_psh_path,
custom=True,
sensor_type="OPTICAL",
band_map={"BLUE": 1, "GREEN": 2, "RED": 3, "NIR": 4},
)
series = Series([pld_psh], remove_tmp=not ON_DISK)
series.output = os.path.join(output, series.condensed_name)
series.stack(
["NDVI"],
pixel_size=60,
)
60 changes: 31 additions & 29 deletions eosets/mosaic.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from eosets import EOSETS_NAME
from eosets.exceptions import IncompatibleProducts
from eosets.set import GeometryCheck, GeometryCheckType, Set
from eosets.utils import BandsType, stack
from eosets.utils import AnyProductType, BandsType, stack

READER = Reader()

Expand All @@ -58,7 +58,7 @@ class Mosaic(Set):

def __init__(
self,
paths: Union[list, AnyPathStrType],
paths: Union[list, AnyProductType],
output_path: AnyPathStrType = None,
id: str = None,
remove_tmp: bool = True,
Expand Down Expand Up @@ -121,60 +121,62 @@ def _manage_output(self):

def _manage_prods(
self,
paths: Union[list, AnyPathStrType],
paths: Union[list, AnyProductType],
contiguity_check: GeometryCheck,
**kwargs,
):
"""
Manage products attributes and check the compatibility of the mosaic's components
Args:
paths (Union[list, AnyPathStrType]): Paths of the mosaic
paths (Union[list, AnyProductType]): Paths of the mosaic
contiguity_check (GeometryCheck): Method to check the contiguity of the mosaic
**kwargs: Other arguments
Raises:
IncompatibleProducts: Incompatible products if not contiguous or not the same date
"""

def __open(prod_or_path: AnyProductType) -> Product:
"""Open an EOReader product"""
if path.is_path(prod_or_path):
prod_: Product = READER.open(
prod_or_path,
remove_tmp=self._remove_tmp,
output_path=self._get_tmp_folder(writable=True),
**kwargs,
)
elif isinstance(prod_or_path, Product):
prod_ = prod_or_path
else:
raise NotImplementedError(
"You should give either a path or 'eoreader.Product' to build your Mosaic!"
)

if prod_ is None:
raise ValueError(
f"There is no existing products in EOReader corresponding to {paths[0]}"
)

return prod_

if types.is_iterable(paths):
ref_path = paths[0]
assert path.is_path(ref_path), "You should give paths to build your Mosaic!"
else:
assert path.is_path(
paths
), "You should give at least one path for your Mosaic!"
ref_path = paths
paths = [paths]

# Nof prods (before checks)
self.nof_prods = len(paths)

# Open first product as a reference
first_prod: Product = READER.open(
ref_path,
remove_tmp=self._remove_tmp,
output_path=self._get_tmp_folder(writable=True),
**kwargs,
)
if first_prod is None:
raise ValueError(
f"There is no existing products in EOReader corresponding to {paths[0]}"
)
first_prod = __open(ref_path)

self.prods[first_prod.condensed_name] = first_prod

# Open others
for prod_path in paths[1:]:
prod: Product = READER.open(
prod_path,
remove_tmp=self._remove_tmp,
output_path=self._get_tmp_folder(writable=True),
**kwargs,
)
if prod is None:
raise ValueError(
f"There is no existing products in EOReader corresponding to {prod_path}"
)
prod = __open(prod_path)

# Ensure compatibility of the mosaic component, i.e. unique date and contiguous product
self.prods[prod.condensed_name] = prod
Expand Down Expand Up @@ -533,5 +535,5 @@ def _update_attrs_constellation_specific(
return xarr


AnyMosaicType = Union[list, AnyPathStrType, Product, Mosaic]
AnyMosaicType = Union[list, AnyProductType, Mosaic]
""" Any Mosaic type (either a list or paths or products, a path, a product or a mosaic itself) """
4 changes: 4 additions & 0 deletions eosets/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"""Utils file"""

from eoreader import utils
from eoreader.products import Product
from sertit.types import AnyPathStrType

read = utils.read
write = utils.write
Expand All @@ -32,3 +34,5 @@
from eoreader.bands import BandType

BandsType = Union[list, BandType]

AnyProductType = Union[AnyPathStrType, Product]

0 comments on commit 959b1e4

Please sign in to comment.