From 4039ac906cfb332350b5600e76f4a69bfd37d27b Mon Sep 17 00:00:00 2001 From: nicolasK Date: Tue, 19 Nov 2024 16:39:53 +0100 Subject: [PATCH 1/2] feat(custom indices) --- CHANGELOG.md | 7 ++++++ earthdaily/__init__.py | 2 +- earthdaily/accessor/__init__.py | 39 +++++++++++++++++++++++++-------- 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c35a6e0c..9f8fdc53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ 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.3.0] - 2024-11-19 + +### Added + +- `ed.add_indices` accessor now supports list of strings and dict for custom +indices. For example : `['NDVI',{'NDVI':'(nir-red)/(nir+red)'}]`. + ## [0.2.15] - 2024-11-13 ### Fixed diff --git a/earthdaily/__init__.py b/earthdaily/__init__.py index ae08842d..43b8cc53 100644 --- a/earthdaily/__init__.py +++ b/earthdaily/__init__.py @@ -7,7 +7,7 @@ # to hide warnings from rioxarray or nano seconds conversion # warnings.filterwarnings("ignore") -__version__ = "0.2.15" +__version__ = "0.3.0" def EarthDataStore( diff --git a/earthdaily/accessor/__init__.py b/earthdaily/accessor/__init__.py index 9f5a184d..3d3ea1dd 100644 --- a/earthdaily/accessor/__init__.py +++ b/earthdaily/accessor/__init__.py @@ -291,7 +291,7 @@ def available_indices(self, details=False): available_indices.append(spyndex.indices[k] if details else k) return available_indices - def add_indices(self, indices: list, **kwargs): + def add_indices(self, indices: list[str|dict], **kwargs): """ Uses spyndex to compute and add index. @@ -300,8 +300,9 @@ def add_indices(self, indices: list, **kwargs): Parameters ---------- - indices : list - ['NDVI']. + indices : list[str|dict] + ['NDVI',{'NDVI2':'(red-nir)/(red+nir)'}]. + Returns ------- xr.Dataset @@ -312,10 +313,30 @@ def add_indices(self, indices: list, **kwargs): params = {} params = self._auto_mapper() params.update(**kwargs) - idx = spyndex.computeIndex(index=indices, params=params, **kwargs) - if len(indices) == 1: - idx = idx.expand_dims(index=indices) - idx = idx.to_dataset(dim="index") - - return xr.merge((self._obj, idx)) + # str is for spyndex + indices_str = [index for index in indices if isinstance(index,str)] + # dict is customized ones + custom_indices = {k: v for index in indices if isinstance(index, dict) for k, v in index.items()} + + if len(indices_str)>=1: + idx = spyndex.computeIndex(index=indices_str, params=params, **kwargs) + + if len(indices_str) == 1: + idx = idx.expand_dims(index=indices_str) + idx = idx.to_dataset(dim="index") + + self._obj = xr.merge((self._obj, idx)) + + if len(custom_indices)>=1: + # custom indices + def custom_index_to_eval(ds, custom_index): + for data_var in ds.data_vars: + custom_index = custom_index.replace(data_var,f"self._obj['{data_var}']") + return custom_index + + for data_var,formula in custom_indices.items(): + index_eval = custom_index_to_eval(self._obj, formula) + self._obj[data_var] = eval(index_eval) + + return self._obj From a38c8da7ebfc9140a078ec772cfc88b5e815ed42 Mon Sep 17 00:00:00 2001 From: nkarasiak Date: Tue, 19 Nov 2024 15:40:31 +0000 Subject: [PATCH 2/2] style(ruff) : automatic lint/format --- earthdaily/accessor/__init__.py | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/earthdaily/accessor/__init__.py b/earthdaily/accessor/__init__.py index 3d3ea1dd..a01f5b1c 100644 --- a/earthdaily/accessor/__init__.py +++ b/earthdaily/accessor/__init__.py @@ -291,7 +291,7 @@ def available_indices(self, details=False): available_indices.append(spyndex.indices[k] if details else k) return available_indices - def add_indices(self, indices: list[str|dict], **kwargs): + def add_indices(self, indices: list[str | dict], **kwargs): """ Uses spyndex to compute and add index. @@ -302,7 +302,7 @@ def add_indices(self, indices: list[str|dict], **kwargs): ---------- indices : list[str|dict] ['NDVI',{'NDVI2':'(red-nir)/(red+nir)'}]. - + Returns ------- xr.Dataset @@ -315,27 +315,34 @@ def add_indices(self, indices: list[str|dict], **kwargs): params.update(**kwargs) # str is for spyndex - indices_str = [index for index in indices if isinstance(index,str)] + indices_str = [index for index in indices if isinstance(index, str)] # dict is customized ones - custom_indices = {k: v for index in indices if isinstance(index, dict) for k, v in index.items()} - - if len(indices_str)>=1: + custom_indices = { + k: v + for index in indices + if isinstance(index, dict) + for k, v in index.items() + } + + if len(indices_str) >= 1: idx = spyndex.computeIndex(index=indices_str, params=params, **kwargs) - + if len(indices_str) == 1: idx = idx.expand_dims(index=indices_str) idx = idx.to_dataset(dim="index") - + self._obj = xr.merge((self._obj, idx)) - - if len(custom_indices)>=1: + + if len(custom_indices) >= 1: # custom indices def custom_index_to_eval(ds, custom_index): for data_var in ds.data_vars: - custom_index = custom_index.replace(data_var,f"self._obj['{data_var}']") + custom_index = custom_index.replace( + data_var, f"self._obj['{data_var}']" + ) return custom_index - - for data_var,formula in custom_indices.items(): + + for data_var, formula in custom_indices.items(): index_eval = custom_index_to_eval(self._obj, formula) self._obj[data_var] = eval(index_eval)