Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: replace all the dates methods #115

Merged
merged 5 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
78 changes: 78 additions & 0 deletions geetools/DateRange.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""Extra tools for the ``ee.DateRange`` class."""
from __future__ import annotations

from typing import Union

import ee

from .accessors import geetools_accessor


@geetools_accessor(ee.DateRange)
class DateRange:
"""Toolbox for the ``ee.DateRange`` class."""

def __init__(self, obj: ee.DateRange):
"""Initialize the DateRange class."""
self._obj = obj

def split(
self,
interval: Union[int, ee.Number],
unit: str = "day",
) -> ee.List:
"""Convert a ``ee.DateRange`` to a list of ``ee.DateRange``.

The DateRange will be split in multiple DateRanges of the specified interval and Unit.
For example "1", "day". if the end date is not included the last dateRange length will be adapted.

Parameters:
interval: The interval to split the DateRange
unit: The unit to split the DateRange. One of: ``second``, ``minute``, ``hour``, ``day``, ``month``, ``year``.

Returns:
The list of DateRanges

Examples:
.. jupyter-execute::

import ee, geetools

ee.Initialize()

d = ee.DateRange('2020-01-01', '2020-01-31').geetools.split(1, 'day')
d.getInfo()
"""
interval = ee.Number(interval).toInt().multiply(self._unitMillis(unit))
start, end = self._obj.start().millis(), self._obj.end().millis()

timestampList = ee.List.sequence(start, end, interval)
timestampList = timestampList.add(ee.Number(end).toFloat()).distinct()

indexList = ee.List.sequence(0, timestampList.size().subtract(2))

return indexList.map(
lambda i: ee.DateRange(
timestampList.get(i), timestampList.get(ee.Number(i).add(1))
)
)

@classmethod
def _check_unit(cls, unit: str) -> None:
"""Check if the unit is valid."""
if unit not in (units := ["second", "minute", "hour", "day", "month", "year"]):
raise ValueError(f"unit must be one of: {','.join(units)}")

@classmethod
def _unitMillis(cls, unit: str) -> ee.Number:
"""Get the milliseconds of a unit."""
cls._check_unit(unit)
millis = {
"second": 1000,
"minute": 1000 * 60,
"hour": 1000 * 60 * 60,
"day": 1000 * 60 * 60 * 24,
"month": 1000 * 60 * 60 * 24 * 30,
"year": 1000 * 60 * 60 * 24 * 365,
}
return ee.Number(millis[unit])
40 changes: 40 additions & 0 deletions geetools/Image.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""Toolbox for the ``ee.Image`` class."""
from __future__ import annotations

import ee

from .accessors import geetools_accessor


@geetools_accessor(ee.Image)
class Image:
"""Toolbox for the ``ee.Image`` class."""

def __init__(self, obj: ee.Image):
"""Initialize the Image class."""
self._obj = obj

def addDate(self) -> ee.Image:
"""Add a band with the date of the image in the provided format.

The date is stored as a Timestamp in millisecond in a band date.

Returns:
The image with the date band added.

Examples:
.. jupyter-execute::

import ee, geetools

ee.Initialize()

image = ee.Image('COPERNICUS/S2_SR_HARMONIZED/20200101T100319_20200101T100321_T32TQM')
image = image.geetools.addDate()
date = image.select('date')
value = date.reduceRegion(ee.Reducer.first()).get("date")
ee.Date(value).format('YYYY-MM-dd').getInfo()
"""
return self._obj.addBands(
ee.Image.constant(self._obj.date().millis()).rename("date")
)
2 changes: 2 additions & 0 deletions geetools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,11 @@
# then we extend all the other classes
from .Array import Array # noqa: F401
from .Date import Date # noqa: F401
from .DateRange import DateRange # noqa: F401
from .Dictionary import Dictionary # noqa: F401
from .Filter import Filter # noqa: F401
from .Float import Float
from .Image import Image # noqa: F401
from .Integer import Integer
from .List import List # noqa: F401
from .Number import Number # noqa: F401
Expand Down
26 changes: 26 additions & 0 deletions geetools/tools/_deprecated_date.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,29 @@ def fromDOY(year, doy):
def isLeap(date):
"""Check if a date is leap."""
return ee.Date(date).geetools.isLeap()


@deprecated(version="1.0.0", reason="Use ee.DateRange.geetools.split instead")
def daterangeList(start, end, interval, unit):
"""Divide a range that goes from start_date to end_date into many."""
return ee.DateRange(start, end).geetools.split(interval, unit)


@deprecated(version="1.0.0", reason="Use ee.DateRange.geetools.split instead")
def daterangeIntervals(
start,
end,
interval=1,
unit="month",
date_range=(1, 1),
date_range_unit="day",
direction="backward",
):
"""Divide a range that goes from start_date to end_date into many."""
return ee.DateRange(start, end).geetools.split(interval, unit)


@deprecated(version="1.0.0", reason="Use ee.Image.geetools.addDate instead")
def makeDateBand(image, format="YMMdd", bandname="date"):
"""Add a band name to the image."""
return ee.Image(image).geetools.addDate()