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

extract from first day to last day of month #148

Merged
merged 2 commits into from
Sep 5, 2024
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions scripts/extractions/patch_extractions/extract_worldcereal.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ def create_job_dataframe_worldcereal(
start_date = max(start_date, WORLDCEREAL_BEGIN_DATE)
end_date = min(end_date, datetime.now())

# We need to start 1st of the month and end on the last day of the month
start_date = start_date.replace(day=1)
end_date = end_date + pd.offsets.MonthEnd(0)

# Convert dates to string format
start_date, end_date = start_date.strftime("%Y-%m-%d"), end_date.strftime(
"%Y-%m-%d"
Expand Down
67 changes: 66 additions & 1 deletion src/worldcereal/openeo/preprocessing.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from pathlib import Path
from typing import List, Optional, Union

import pandas as pd
from geojson import GeoJSON
from openeo import UDF, Connection, DataCube
from openeo_gfmap import (
Expand All @@ -19,7 +20,9 @@
from openeo_gfmap.preprocessing.sar import compress_backscatter_uint16
from openeo_gfmap.utils.catalogue import UncoveredS1Exception, select_s1_orbitstate_vvvh

COMPOSITE_WINDOW = "month"

class InvalidTemporalContextError(Exception):
pass


def raw_datacube_S2(
Expand Down Expand Up @@ -305,6 +308,10 @@ def worldcereal_preprocessed_inputs(
s1_orbit_state: Optional[str] = None,
tile_size: Optional[int] = None,
) -> DataCube:

# First validate the temporal context
_validate_temporal_context(temporal_extent)

# Extraction of S2 from GFMAP
s2_data = raw_datacube_S2(
connection=connection,
Expand Down Expand Up @@ -382,3 +389,61 @@ def worldcereal_preprocessed_inputs(
data = data.merge_cubes(meteo_data)

return data


def _validate_temporal_context(temporal_context: TemporalContext) -> None:
"""validation method to ensure proper specification of temporal context.
which requires that the start and end date are at the first and last day of a month.

Parameters
----------
temporal_context : TemporalContext
temporal context to validate

Raises
------
InvalidTemporalContextError
if start_date is not on the first day of a month or end_date
is not on the last day of a month
"""

start_date, end_date = temporal_context.to_datetime()

if start_date != start_date.replace(
day=1
) or end_date != end_date + pd.offsets.MonthEnd(0):
error_msg = (
"WorldCereal uses monthly compositing. For this to work properly, "
"requested temporal range should start and end at the first and last "
"day of a month. Instead, got: "
f"{temporal_context.start_date} - {temporal_context.end_date}. "
"You may use `worldcereal.preprocessing.correct_temporal_context()` "
"to correct the temporal context."
)
raise InvalidTemporalContextError(error_msg)


def correct_temporal_context(temporal_context: TemporalContext) -> TemporalContext:
"""Corrects the temporal context to ensure that the start and end date are
at the first and last day of a month as required by the WorldCereal processing.

Parameters
----------
temporal_context : TemporalContext
temporal context to correct

Returns
-------
TemporalContext
corrected temporal context
"""

start_date, end_date = temporal_context.to_datetime()

start_date = start_date.replace(day=1)
end_date = end_date + pd.offsets.MonthEnd(0)

return TemporalContext(
start_date=start_date.strftime("%Y-%m-%d"),
end_date=end_date.strftime("%Y-%m-%d"),
)
30 changes: 30 additions & 0 deletions tests/worldcerealtests/test_preprocessing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import pytest
from openeo_gfmap.temporal import TemporalContext

from worldcereal.openeo.preprocessing import (
InvalidTemporalContextError,
_validate_temporal_context,
correct_temporal_context,
)


def test_temporal_context_validation():
"""Test the validation of temporal context."""

temporal_context = TemporalContext("2020-01-01", "2022-03-31")
_validate_temporal_context(temporal_context)

incorrect_temporal_context = TemporalContext("2022-01-05", "2020-03-15")

with pytest.raises(InvalidTemporalContextError):
_validate_temporal_context(incorrect_temporal_context)


def test_temporal_context_correction():
"""Test the automatic correction of invalid temporal context."""

incorrect_temporal_context = TemporalContext("2022-01-05", "2020-03-15")
corrected_temporal_context = correct_temporal_context(incorrect_temporal_context)

# Should no longer raise an exception
_validate_temporal_context(corrected_temporal_context)
Loading