Skip to content

Commit

Permalink
introduce Feature type alias
Browse files Browse the repository at this point in the history
  • Loading branch information
zigaLuksic committed Aug 28, 2023
1 parent 93b4172 commit 9bddd0b
Show file tree
Hide file tree
Showing 34 changed files with 153 additions and 142 deletions.
12 changes: 6 additions & 6 deletions eolearn/core/core_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from .eodata_merge import merge_eopatches
from .eotask import EOTask
from .exceptions import EODeprecationWarning
from .types import EllipsisType, FeaturesSpecification
from .types import EllipsisType, Feature, FeaturesSpecification
from .utils.fs import get_filesystem, pickle_fs, unpickle_fs


Expand Down Expand Up @@ -227,7 +227,7 @@ def execute(
class AddFeatureTask(EOTask):
"""Adds a feature to the given EOPatch."""

def __init__(self, feature: tuple[FeatureType, str]):
def __init__(self, feature: Feature):
"""
:param feature: Feature to be added
"""
Expand Down Expand Up @@ -335,7 +335,7 @@ class InitializeFeatureTask(EOTask):
def __init__(
self,
features: FeaturesSpecification,
shape: tuple[int, ...] | tuple[FeatureType, str],
shape: tuple[int, ...] | Feature,
init_value: int = 0,
dtype: np.dtype | type = np.uint8,
):
Expand Down Expand Up @@ -530,7 +530,7 @@ def zip_method(self, *f):
def __init__(
self,
input_features: FeaturesSpecification,
output_feature: tuple[FeatureType, str],
output_feature: Feature,
zip_function: Callable | None = None,
**kwargs: Any,
):
Expand Down Expand Up @@ -597,8 +597,8 @@ class ExplodeBandsTask(EOTask):

def __init__(
self,
input_feature: tuple[FeatureType, str],
output_mapping: dict[tuple[FeatureType, str], int | Iterable[int]],
input_feature: Feature,
output_mapping: dict[Feature, int | Iterable[int]],
):
"""
:param input_feature: A source feature from which to take the subset of bands.
Expand Down
10 changes: 5 additions & 5 deletions eolearn/core/eodata.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
from .constants import FEATURETYPE_DEPRECATION_MSG, TIMESTAMP_COLUMN, FeatureType, OverwritePermission
from .eodata_io import FeatureIO, load_eopatch_content, save_eopatch
from .exceptions import EODeprecationWarning, TemporalDimensionWarning
from .types import EllipsisType, FeaturesSpecification
from .types import EllipsisType, Feature, FeaturesSpecification
from .utils.common import deep_eq, is_discrete_type
from .utils.fs import get_filesystem
from .utils.parsing import parse_features
Expand Down Expand Up @@ -394,7 +394,7 @@ def __setitem__(self, key: FeatureType | tuple[FeatureType, str | None | Ellipsi
else:
setattr(self, ftype_attr, value)

def __delitem__(self, feature: FeatureType | tuple[FeatureType, str]) -> None:
def __delitem__(self, feature: FeatureType | Feature) -> None:
"""Deletes the selected feature type or feature."""
if isinstance(feature, tuple):
feature_type, feature_name = feature
Expand Down Expand Up @@ -585,12 +585,12 @@ def get_spatial_dimension(self, feature_type: FeatureType, feature_name: str) ->

raise ValueError(f"Features of type {feature_type} do not have a spatial dimension or are not arrays.")

def get_features(self) -> list[tuple[FeatureType, str]]:
def get_features(self) -> list[Feature]:
"""Returns a list of all non-empty features of EOPatch.
:return: List of non-empty features
"""
feature_list: list[tuple[FeatureType, str]] = []
feature_list: list[Feature] = []
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message=FEATURETYPE_DEPRECATION_MSG.format(".*?", ".*?"))
removed_ftypes = {FeatureType.BBOX, FeatureType.TIMESTAMPS} # list comprehensions make ignoring hard
Expand Down Expand Up @@ -748,7 +748,7 @@ def consolidate_timestamps(self, timestamps: list[dt.datetime]) -> set[dt.dateti

def plot(
self,
feature: tuple[FeatureType, str],
feature: Feature,
*,
times: list[int] | slice | None = None,
channels: list[int] | slice | None = None,
Expand Down
6 changes: 3 additions & 3 deletions eolearn/core/eodata_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

from .constants import TIMESTAMP_COLUMN, FeatureType, OverwritePermission
from .exceptions import EODeprecationWarning
from .types import EllipsisType, FeaturesSpecification
from .types import EllipsisType, Feature, FeaturesSpecification
from .utils.fs import get_full_path, split_all_extensions
from .utils.parsing import FeatureParser

Expand Down Expand Up @@ -92,7 +92,7 @@ class FilesystemDataInfo:
old_meta_info: str | None = None
features: dict[FeatureType, dict[str, str]] = field(default_factory=lambda: defaultdict(dict))

def iterate_features(self) -> Iterator[tuple[tuple[FeatureType, str], str]]:
def iterate_features(self) -> Iterator[tuple[Feature, str]]:
"""Yields `(ftype, fname), path` tuples from `features`."""
for ftype, ftype_dict in self.features.items():
for fname, path in ftype_dict.items():
Expand Down Expand Up @@ -342,7 +342,7 @@ def _load_features(
temporal_selection: None | slice | list[int] | list[bool],
err_msg: str,
file_information: FilesystemDataInfo,
) -> dict[tuple[FeatureType, str], FeatureIO]:
) -> dict[Feature, FeatureIO]:
features_dict = {}
if file_information.old_meta_info is not None and any(ftype is FeatureType.META_INFO for ftype, _ in feature_specs):
msg = (
Expand Down
14 changes: 6 additions & 8 deletions eolearn/core/eodata_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from .constants import FeatureType
from .eodata import EOPatch
from .exceptions import EORuntimeWarning
from .types import FeaturesSpecification
from .types import Feature, FeaturesSpecification
from .utils.parsing import FeatureParser

OperationInputType = Union[Literal[None, "concatenate", "min", "max", "mean", "median"], Callable]
Expand Down Expand Up @@ -161,7 +161,7 @@ def _check_if_optimize(eopatches: Sequence[EOPatch], operation_input: OperationI

def _merge_time_dependent_raster_feature(
eopatches: Sequence[EOPatch],
feature: tuple[FeatureType, str],
feature: Feature,
operation: Callable,
order_mask_per_eopatch: Sequence[np.ndarray],
optimize: bool,
Expand Down Expand Up @@ -204,7 +204,7 @@ def _merge_time_dependent_raster_feature(

def _extract_and_join_time_dependent_feature_values(
eopatches: Sequence[EOPatch],
feature: tuple[FeatureType, str],
feature: Feature,
order_mask_per_eopatch: Sequence[np.ndarray],
optimize: bool,
) -> tuple[np.ndarray, np.ndarray]:
Expand Down Expand Up @@ -237,9 +237,7 @@ def _is_strictly_increasing(array: np.ndarray) -> bool:
return (np.diff(array) > 0).all().astype(bool)


def _merge_timeless_raster_feature(
eopatches: Sequence[EOPatch], feature: tuple[FeatureType, str], operation: Callable
) -> np.ndarray:
def _merge_timeless_raster_feature(eopatches: Sequence[EOPatch], feature: Feature, operation: Callable) -> np.ndarray:
"""Merges numpy arrays of a timeless raster feature with a given operation."""
arrays = _extract_feature_values(eopatches, feature)

Expand All @@ -255,7 +253,7 @@ def _merge_timeless_raster_feature(
) from exception


def _merge_vector_feature(eopatches: Sequence[EOPatch], feature: tuple[FeatureType, str]) -> GeoDataFrame:
def _merge_vector_feature(eopatches: Sequence[EOPatch], feature: Feature) -> GeoDataFrame:
"""Merges GeoDataFrames of a vector feature."""
dataframes = _extract_feature_values(eopatches, feature)

Expand Down Expand Up @@ -299,7 +297,7 @@ def _get_common_bbox(eopatches: Sequence[EOPatch]) -> BBox | None:
raise ValueError("Cannot merge EOPatches because they are defined for different bounding boxes.")


def _extract_feature_values(eopatches: Sequence[EOPatch], feature: tuple[FeatureType, str]) -> list[Any]:
def _extract_feature_values(eopatches: Sequence[EOPatch], feature: Feature) -> list[Any]:
"""A helper function that extracts a feature values from those EOPatches where a feature exists."""
feature_type, feature_name = feature
return [eopatch[feature] for eopatch in eopatches if feature_name in eopatch[feature_type]]
Expand Down
6 changes: 3 additions & 3 deletions eolearn/core/eotask.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from .constants import FeatureType
from .eodata import EOPatch
from .exceptions import EODeprecationWarning
from .types import EllipsisType, FeaturesSpecification, SingleFeatureSpec
from .types import EllipsisType, Feature, FeaturesSpecification, SingleFeatureSpec
from .utils.parsing import FeatureParser, parse_feature, parse_features, parse_renamed_feature, parse_renamed_features

LOGGER = logging.getLogger(__name__)
Expand Down Expand Up @@ -84,7 +84,7 @@ def parse_feature(
feature: SingleFeatureSpec,
eopatch: EOPatch | None = None,
allowed_feature_types: EllipsisType | Iterable[FeatureType] | Callable[[FeatureType], bool] = ...,
) -> tuple[FeatureType, str]:
) -> Feature:
"""See `eolearn.core.utils.parse_feature`."""
return parse_feature(feature, eopatch, allowed_feature_types)

Expand All @@ -93,7 +93,7 @@ def parse_features(
features: FeaturesSpecification,
eopatch: EOPatch | None = None,
allowed_feature_types: EllipsisType | Iterable[FeatureType] | Callable[[FeatureType], bool] = ...,
) -> list[tuple[FeatureType, str]]:
) -> list[Feature]:
"""See `eolearn.core.utils.parse_features`."""
return parse_features(features, eopatch, allowed_feature_types)

Expand Down
3 changes: 2 additions & 1 deletion eolearn/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@


# DEVELOPER NOTE: the #: comments are applied as docstrings
Feature: TypeAlias = Tuple[FeatureType, str]

SingleFeatureSpec: TypeAlias = Union[Tuple[FeatureType, str], Tuple[FeatureType, str, str]]
SingleFeatureSpec: TypeAlias = Union[Feature, Tuple[FeatureType, str, str]]

SequenceFeatureSpec: TypeAlias = Sequence[Union[SingleFeatureSpec, FeatureType, Tuple[FeatureType, EllipsisType]]]
DictFeatureSpec: TypeAlias = Dict[FeatureType, Union[EllipsisType, Iterable[Union[str, Tuple[str, str]]]]]
Expand Down
7 changes: 4 additions & 3 deletions eolearn/core/utils/parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from ..types import (
DictFeatureSpec,
EllipsisType,
Feature,
FeaturesSpecification,
SequenceFeatureSpec,
SingleFeatureSpec,
Expand Down Expand Up @@ -238,7 +239,7 @@ def get_feature_specifications(self) -> list[tuple[FeatureType, str | EllipsisTy
"""
return [(ftype, ... if fname is None else fname) for ftype, fname, _ in self._feature_specs]

def get_features(self, eopatch: EOPatch | None = None) -> list[tuple[FeatureType, str]]:
def get_features(self, eopatch: EOPatch | None = None) -> list[Feature]:
"""Returns a list of `(feature_type, feature_name)` pairs.
For features that specify renaming, the new name of the feature is ignored.
Expand Down Expand Up @@ -285,7 +286,7 @@ def parse_feature(
feature: SingleFeatureSpec,
eopatch: EOPatch | None = None,
allowed_feature_types: EllipsisType | Iterable[FeatureType] | Callable[[FeatureType], bool] = ...,
) -> tuple[FeatureType, str]:
) -> Feature:
"""Parses input describing a single feature into a `(feature_type, feature_name)` pair.
See :class:`FeatureParser<eolearn.core.utilities.FeatureParser>` for viable inputs.
Expand Down Expand Up @@ -317,7 +318,7 @@ def parse_features(
features: FeaturesSpecification,
eopatch: EOPatch | None = None,
allowed_feature_types: EllipsisType | Iterable[FeatureType] | Callable[[FeatureType], bool] = ...,
) -> list[tuple[FeatureType, str]]:
) -> list[Feature]:
"""Parses input describing features into a list of `(feature_type, feature_name)` pairs.
See :class:`FeatureParser<eolearn.core.utilities.FeatureParser>` for viable inputs.
Expand Down
3 changes: 2 additions & 1 deletion eolearn/core/utils/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

from ..constants import FeatureType
from ..eodata import EOPatch
from ..types import Feature
from ..utils.parsing import FeatureParser

DEFAULT_BBOX = BBox((0, 0, 100, 100), crs=CRS("EPSG:32633"))
Expand All @@ -45,7 +46,7 @@ def __post_init__(self) -> None:


def generate_eopatch(
features: list[tuple[FeatureType, str]] | None = None,
features: list[Feature] | None = None,
bbox: BBox = DEFAULT_BBOX,
timestamps: list[dt.datetime] | None = None,
seed: int = 42,
Expand Down
8 changes: 4 additions & 4 deletions eolearn/coregistration/coregistration.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

from eolearn.core import EOPatch, EOTask, FeatureType
from eolearn.core.exceptions import EORuntimeWarning
from eolearn.core.types import FeaturesSpecification
from eolearn.core.types import Feature, FeaturesSpecification

LOGGER = logging.getLogger(__name__)

Expand All @@ -36,10 +36,10 @@ class ECCRegistrationTask(EOTask):

def __init__(
self,
registration_feature: tuple[FeatureType, str],
reference_feature: tuple[FeatureType, str],
registration_feature: Feature,
reference_feature: Feature,
channel: int,
valid_mask_feature: tuple[FeatureType, str] | None = None,
valid_mask_feature: Feature | None = None,
apply_to_features: FeaturesSpecification = ...,
interpolation_mode: int = cv2.INTER_LINEAR,
warp_mode: int = cv2.MOTION_TRANSLATION,
Expand Down
11 changes: 6 additions & 5 deletions eolearn/features/bands_extraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@

import numpy as np

from eolearn.core import FeatureType, MapFeatureTask
from eolearn.core import MapFeatureTask
from eolearn.core.types import Feature


class EuclideanNormTask(MapFeatureTask):
Expand All @@ -23,8 +24,8 @@ class EuclideanNormTask(MapFeatureTask):

def __init__(
self,
input_feature: tuple[FeatureType, str],
output_feature: tuple[FeatureType, str],
input_feature: Feature,
output_feature: Feature,
bands: list[int] | None = None,
):
"""
Expand Down Expand Up @@ -55,8 +56,8 @@ class NormalizedDifferenceIndexTask(MapFeatureTask):

def __init__(
self,
input_feature: tuple[FeatureType, str],
output_feature: tuple[FeatureType, str],
input_feature: Feature,
output_feature: Feature,
bands: tuple[int, int],
acorvi_constant: float = 0,
undefined_value: float = np.nan,
Expand Down
3 changes: 2 additions & 1 deletion eolearn/features/clustering.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from sklearn.feature_extraction.image import grid_to_graph

from eolearn.core import EOPatch, EOTask, FeatureType
from eolearn.core.types import Feature


class ClusteringTask(EOTask):
Expand All @@ -28,7 +29,7 @@ class ClusteringTask(EOTask):

def __init__(
self,
features: tuple[FeatureType, str],
features: Feature,
new_feature_name: str,
distance_threshold: float | None = None,
n_clusters: int | None = None,
Expand Down
7 changes: 4 additions & 3 deletions eolearn/features/doubly_logistic_approximation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from scipy.optimize import curve_fit

from eolearn.core import EOPatch, EOTask, FeatureType
from eolearn.core.types import Feature


def doubly_logistic(middle, initial_value, scale, a1, a2, a3, a4, a5) -> np.ndarray: # type: ignore[no-untyped-def]
Expand All @@ -35,10 +36,10 @@ class DoublyLogisticApproximationTask(EOTask):

def __init__(
self,
feature: tuple[FeatureType, str],
new_feature: tuple[FeatureType, str] = (FeatureType.DATA_TIMELESS, "DOUBLY_LOGISTIC_PARAM"),
feature: Feature,
new_feature: Feature = (FeatureType.DATA_TIMELESS, "DOUBLY_LOGISTIC_PARAM"),
initial_parameters: list[float] | None = None,
valid_mask: tuple[FeatureType, str] | None = None,
valid_mask: Feature | None = None,
):
self.initial_parameters = initial_parameters
self.feature = self.parse_feature(feature)
Expand Down
10 changes: 5 additions & 5 deletions eolearn/features/feature_manipulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@

from sentinelhub import bbox_to_dimensions

from eolearn.core import EOPatch, EOTask, FeatureType, MapFeatureTask
from eolearn.core import EOPatch, EOTask, MapFeatureTask
from eolearn.core.constants import TIMESTAMP_COLUMN
from eolearn.core.types import FeaturesSpecification
from eolearn.core.types import Feature, FeaturesSpecification
from eolearn.core.utils.parsing import parse_renamed_features

from .utils import ResizeLib, ResizeMethod, ResizeParam, spatially_resize_image
Expand All @@ -39,7 +39,7 @@ class SimpleFilterTask(EOTask):

def __init__(
self,
feature: tuple[FeatureType, str] | Literal["timestamps"],
feature: Feature | Literal["timestamps"],
filter_func: Callable[[np.ndarray], bool] | Callable[[dt.datetime], bool],
filter_features: FeaturesSpecification = ...,
):
Expand All @@ -49,7 +49,7 @@ def __init__(
:param filter_features: A collection of features which will be filtered into a new EOPatch
"""
if feature == "timestamps":
self.feature: tuple[FeatureType, str] | Literal["timestamps"] = "timestamps"
self.feature: Feature | Literal["timestamps"] = "timestamps"
else:
self.feature = self.parse_feature(
feature, allowed_feature_types=lambda fty: fty.is_temporal() and fty.is_array()
Expand Down Expand Up @@ -132,7 +132,7 @@ class ValueFilloutTask(EOTask):

def __init__(
self,
feature: tuple[FeatureType, str],
feature: Feature,
operations: Literal["f", "b", "fb", "bf"] = "fb",
value: float = np.nan,
axis: int = 0,
Expand Down
Loading

0 comments on commit 9bddd0b

Please sign in to comment.