Skip to content

Commit

Permalink
v0.0.14
Browse files Browse the repository at this point in the history
v0.0.14
  • Loading branch information
nkarasiak authored Apr 11, 2024
2 parents 52192e4 + c7c77e3 commit a9d1509
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 108 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.0.14] - 2024-04-11

### Fixed

- `GeoSeries` supported in GeometryManager.
- `ed.sel_nearest_dates` accessor avoid duplicated times.
- Issue when managing multiple indices with accessor `xr.ed`.
- Issue when same datetime when rescaling dataset.

### Added

- `mode` for zonal stats in `operations.reducers`.

### Changed

- `ag_cloud_mask_items` queries items per batch.

### Removed

- Typing decorator, expected new typing library.

## [0.0.13] - 2024-03-06

### Fixed
Expand Down
2 changes: 1 addition & 1 deletion earthdaily/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
# to hide warnings from rioxarray or nano seconds conversion
warnings.filterwarnings("ignore")

__version__ = "0.0.13"
__version__ = "0.0.14"
125 changes: 31 additions & 94 deletions earthdaily/accessor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,86 +12,7 @@
from xarray.core.extensions import AccessorRegistrationWarning
from ..earthdatastore.cube_utils import GeometryManager

warnings.filterwarnings("ignore", category=AccessorRegistrationWarning)


class MisType(Warning):
pass


def _typer(raise_mistype=False, custom_types={}):
"""
Parameters
----------
raise_mistype : TYPE, optional
DESCRIPTION. The default is False.
custom_types : TYPE, optional
DESCRIPTION. The default is {}.
Example : {
np.ndarray:{"func":np.asarray},
xr.Dataset:{"func":xr.DataArray.to_dataset,"kwargs":{"dim":"band"}}
}
Raises
------
MisType
DESCRIPTION.
Returns
-------
TYPE
DESCRIPTION.
"""

def decorator(func):
def force(*args, **kwargs):
_args = list(args)
for key, vals in func.__annotations__.items():
if not isinstance(vals, (list, tuple)):
vals = [vals]
val = vals[0]
idx = func.__code__.co_varnames.index(key)
is_kwargs = key in kwargs.keys()
if not is_kwargs and idx >= len(_args):
break
value = kwargs.get(key, None) if is_kwargs else args[idx]
if type(value) in vals:
continue
if (
type(kwargs.get(key)) not in vals
if is_kwargs
else type(args[idx]) not in vals
):
if raise_mistype:
if is_kwargs:
expected = f"{type(kwargs[key]).__name__} ({kwargs[key]})"
else:
expected = f"{type(args[idx]).__name__} ({args[idx]})"
raise MisType(f"{key} expected {val.__name__}, not {expected}.")
if any(val == k for k in custom_types.keys()):
exp = custom_types[val]
var = args[idx]
res = exp["func"](var, **exp.get("kwargs", {}))
if is_kwargs:
kwargs[key] = res
else:
_args[idx] = res
elif is_kwargs:
kwargs[key] = (
val(kwargs[key]) if val is not list else [kwargs[key]]
)
else:
_args[idx] = val(args[idx]) if val is not list else [args[idx]]
args = tuple(_args)
return func(*args, **kwargs)

return force

return decorator


@_typer()

def xr_loop_func(
dataset: xr.Dataset,
func,
Expand Down Expand Up @@ -122,7 +43,6 @@ def _xr_loop_func(dataset, metafunc, loop_dimension, **kwargs):
)


@_typer()
def _lee_filter(img, window_size: int):
img_ = img.copy()
if isinstance(img, np.ndarray):
Expand Down Expand Up @@ -166,7 +86,6 @@ def clip(self, geom):
def _max_time_wrap(self, wish=5, col="time"):
return np.min((wish, self._obj[col].size))

@_typer()
def plot_band(self, cmap="Greys", col="time", col_wrap=5, **kwargs):
return self._obj.plot.imshow(
cmap=cmap,
Expand All @@ -175,6 +94,29 @@ def plot_band(self, cmap="Greys", col="time", col_wrap=5, **kwargs):
**kwargs,
)

def whittaker(
self,
lmbd: float,
weights: np.ndarray = None,
a: float = 0.5,
min_value: float = -np.inf,
max_value: float = np.inf,
max_iter: int = 10,
time="time",
):
from . import whittaker

return whittaker.xr_wt(
self._obj.to_dataset(name="index"),
lmbd,
time=time,
weights=weights,
a=a,
min_value=min_value,
max_value=max_value,
max_iter=max_iter,
)["index"]


@xr.register_dataset_accessor("ed")
class EarthDailyAccessorDataset:
Expand All @@ -187,7 +129,6 @@ def clip(self, geom):
def _max_time_wrap(self, wish=5, col="time"):
return np.min((wish, self._obj[col].size))

@_typer()
def plot_rgb(
self,
red: str = "red",
Expand All @@ -205,7 +146,6 @@ def plot_rgb(
)
)

@_typer()
def plot_band(self, band, cmap="Greys", col="time", col_wrap=5, **kwargs):
return self._obj[band].plot.imshow(
cmap=cmap,
Expand All @@ -214,7 +154,6 @@ def plot_band(self, band, cmap="Greys", col="time", col_wrap=5, **kwargs):
**kwargs,
)

@_typer()
def lee_filter(self, window_size: int):
return xr.apply_ufunc(
_lee_filter,
Expand All @@ -225,7 +164,6 @@ def lee_filter(self, window_size: int):
kwargs=dict(window_size=window_size),
)

@_typer()
def centroid(self, to_wkt: str = False, to_4326: bool = True):
"""Return the geographic center point in 4326/WKT of this dataset."""
# we can use a cache on our accessor objects, because accessors
Expand Down Expand Up @@ -288,7 +226,6 @@ def available_indices(self, details=False):
available_indices.append(spyndex.indices[k] if details else k)
return available_indices

@_typer()
def add_indices(self, indices: list, **kwargs):
"""
Uses spyndex to compute and add index.
Expand All @@ -313,12 +250,11 @@ def add_indices(self, indices: list, **kwargs):
idx = spyndex.computeIndex(index=indices, params=params, **kwargs)

if len(indices) == 1:
idx = idx.expand_dims(indices=indices)
idx = idx.to_dataset(dim="indices")
idx = idx.expand_dims(index=indices)
idx = idx.to_dataset(dim="index")

return xr.merge((self._obj, idx))

@_typer()
def sel_nearest_dates(
self,
target: (xr.Dataset, xr.DataArray),
Expand All @@ -334,14 +270,14 @@ def sel_nearest_dates(
for i, j in enumerate(pos)
if j.days <= max_delta
]
pos = np.unique(pos)
if return_target:
method_convert = {"bfill": "ffill", "ffill": "bfill", "nearest": "nearest"}
return self._obj.sel(time=pos), target.sel(
time=pos, method=method_convert[method]
)
return self._obj.sel(time=pos)

@_typer()
def whittaker(
self,
lmbd: float,
Expand All @@ -350,15 +286,16 @@ def whittaker(
min_value: float = -np.inf,
max_value: float = np.inf,
max_iter: int = 10,
time="time",
):
from . import whittaker

return whittaker.xr_wt(
self._obj,
lmbd,
time="time",
weights=None,
a=0.5,
time=time,
weights=weights,
a=a,
min_value=min_value,
max_value=max_value,
max_iter=max_iter,
Expand Down
2 changes: 1 addition & 1 deletion earthdaily/accessor/whittaker/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,4 @@ def xr_wt(
output_core_dims=ocd,
dask="allowed",
)
return xr.where(np.isnan(datacube_), datacube_, datacube)
return xr.where(np.isnan(datacube_).all(dim=time), datacube_, datacube)
3 changes: 2 additions & 1 deletion earthdaily/earthdatastore/cube_utils/_zonal.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import numpy as np
import xarray as xr
import tqdm
from . import custom_operations

from . import custom_reducers
from .preprocessing import rasterize
from scipy.sparse import csr_matrix

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
earthdaily.earthdatastore.cube_utils.asset_mapper.__asset_mapper_config_path
)
asset_mapper_config = (
earthdaily.earthdatastore.cube_utils.asset_mapper.__asset_mapper_config
earthdaily.earthdatastore.cube_utils.asset_mapper._asset_mapper_config
)

for collection in eds.explore():
Expand All @@ -23,6 +23,7 @@
print(f"collection {collection} has no items")
continue
for asset_name in assets_name:
print(asset_name)
if asset_mapper_config.get(collection) is None:
asset_mapper_config[collection] = [{}]
if asset_name not in asset_mapper_config[collection][0].values():
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import numpy as np


class CustomOperations:
class CustomReducers:
@staticmethod
def _np_mode(arr, **kwargs):
if isinstance(arr, list):
Expand All @@ -22,17 +22,17 @@ def _np_mode(arr, **kwargs):
def mode(data_array_grouped, optional_arg=None):
# Apply _xrmode to DataArrayGroupBy object
result = data_array_grouped.reduce(
CustomOperations._np_mode,
CustomReducers._np_mode,
list(dim for dim in data_array_grouped.dims if dim != "time"),
)
return result

@staticmethod
def register_custom_operations():
def register_custom_reducers():
# register custom methods fo DataArrayGroupBy
xr.core.groupby.DataArrayGroupBy.mode = CustomOperations.mode
xr.core.groupby.DatasetGroupBy.mode = CustomOperations.mode
np.mode = CustomOperations._np_mode
xr.core.groupby.DataArrayGroupBy.mode = CustomReducers.mode
xr.core.groupby.DatasetGroupBy.mode = CustomReducers.mode
np.mode = CustomReducers._np_mode


CustomOperations.register_custom_operations()
CustomReducers.register_custom_reducers()
13 changes: 10 additions & 3 deletions earthdaily/earthdatastore/cube_utils/geometry_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ def __init__(self, geometry):
self.geometry = geometry
self._obj = self.to_geopandas()

def __call__(self):
return self._obj

def to_intersects(self, crs="EPSG:4326"):
return json.loads(self._obj.to_crs(crs).dissolve().to_json(drop_id=True))[
"features"
Expand Down Expand Up @@ -55,8 +58,12 @@ def _unknow_geometry_to_geodataframe(self, geometry):
[geometry["coordinates"][0]]
)
return gpd.GeoDataFrame(geometry=[geom], crs="EPSG:4326")
elif isinstance(geometry, gpd.GeoSeries):
self.input_type = "GeoSeries"
return gpd.GeoDataFrame(geometry=geometry, crs="EPSG:4326")
elif isinstance(geometry, gpd.GeoSeries):
self.input_type = "GeoSeries"

return gpd.GeoDataFrame(
geometry=geometry,
crs="EPSG:4326" if geometry.crs is None else geometry.crs,
)
else:
raise NotImplementedError("Couldn't guess your geometry type")

0 comments on commit a9d1509

Please sign in to comment.