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

ENH: add latecrop-late detection #177

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ local/

.vs/*
.vscode/*
.mypy_cache/*

# Local History for Visual Studio Code
.history/
Expand Down
144 changes: 57 additions & 87 deletions cropclassification/preprocess/_prepare_input_BEFL.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@
ndvi_latecrop_count = "latecrop_ndvi_count"
ndvi_latecrop_median = "latecrop_ndvi_median"

# TODO: should be in REFE instead of hardcoded!!!
late_main_crops = {
"MAINCROP_BEETS": ["71", "91", "8532", "9532"],
"MAINCROP_MAIZE": ["201", "202"],
"IGNORE_LATE_MAINCROP": ["396"],
}


def prepare_input(
input_parcel_path: Path,
Expand Down Expand Up @@ -318,18 +325,16 @@
min_parcels_in_class=min_parcels_in_class,
is_groundtruth=True,
)
elif classtype_to_prepare == "LATECROP-EARLY":
parceldata_df = prepare_input_latecrop_early(
parceldata_df=parceldata_df,
column_BEFL_latecrop=column_BEFL_latecrop,
column_BEFL_latecrop2=column_BEFL_latecrop2,
column_BEFL_maincrop=column_BEFL_crop,
column_output_class=conf.columns["class"],
classes_refe_path=classes_refe_path,
min_parcels_in_class=min_parcels_in_class,
is_groundtruth=False,
)
elif classtype_to_prepare == "LATECROP":
elif classtype_to_prepare.startswith("LATECROP"):
if classtype_to_prepare.startswith("LATECROP-EARLY"):
scope = "EARLY_MAINCROP"
elif classtype_to_prepare.startswith("LATECROP-LATE"):
scope = "LATE_MAINCROP"

Check warning on line 332 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L328-L332

Added lines #L328 - L332 were not covered by tests
else:
scope = "ALL"

Check warning on line 334 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L334

Added line #L334 was not covered by tests

is_groundtruth = classtype_to_prepare.endswith("-GROUNDTRUTH")

Check warning on line 336 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L336

Added line #L336 was not covered by tests

parceldata_df = prepare_input_latecrop(
parceldata_df=parceldata_df,
column_BEFL_latecrop=column_BEFL_latecrop,
Expand All @@ -338,29 +343,8 @@
column_output_class=conf.columns["class"],
classes_refe_path=classes_refe_path,
min_parcels_in_class=min_parcels_in_class,
is_groundtruth=False,
)
elif classtype_to_prepare == "LATECROP-EARLY-GROUNDTRUTH":
parceldata_df = prepare_input_latecrop_early(
parceldata_df=parceldata_df,
column_BEFL_latecrop=column_BEFL_latecrop_gt_verified,
column_BEFL_latecrop2=None,
column_BEFL_maincrop=column_BEFL_crop,
column_output_class=conf.columns["class_groundtruth"],
classes_refe_path=classes_refe_path,
min_parcels_in_class=min_parcels_in_class,
is_groundtruth=True,
)
elif classtype_to_prepare == "LATECROP-GROUNDTRUTH":
parceldata_df = prepare_input_latecrop(
parceldata_df=parceldata_df,
column_BEFL_latecrop=column_BEFL_latecrop_gt_verified,
column_BEFL_latecrop2=None,
column_BEFL_maincrop=column_BEFL_crop,
column_output_class=conf.columns["class_groundtruth"],
classes_refe_path=classes_refe_path,
min_parcels_in_class=min_parcels_in_class,
is_groundtruth=True,
is_groundtruth=is_groundtruth,
scope=scope,
)
elif classtype_to_prepare == "FABACEAE":
parceldata_df = prepare_input_fabaceae(
Expand Down Expand Up @@ -1091,6 +1075,7 @@
classes_refe_path: Path,
min_parcels_in_class: int,
is_groundtruth: bool,
scope: str,
):
"""Prepare input file for use in the latecrop marker.

Expand All @@ -1105,7 +1090,9 @@
# Check if parameters are OK and init some extra params
# -----------------------------------------------------
if not classes_refe_path.exists():
raise Exception(f"Input classes file doesn't exist: {classes_refe_path}")
raise ValueError(f"Input classes file doesn't exist: {classes_refe_path}")
if scope is None or scope not in ["ALL", "EARLY_MAINCROP", "LATE_MAINCROP"]:
raise ValueError(f"Invalid value for scope: {scope}")

Check warning on line 1095 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L1093-L1095

Added lines #L1093 - L1095 were not covered by tests

# Convert the crops to unicode, in case the input is int
if column_BEFL_latecrop in parceldata_df.columns:
Expand Down Expand Up @@ -1207,6 +1194,40 @@
value=parceldata_df[f"{column_output_class_orig}_LATECROP2"],
)

# If limited scope, apply it
if scope == "EARLY_MAINCROP":

Check warning on line 1198 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L1198

Added line #L1198 was not covered by tests
# Only process parcels with an early main crop.
# Hence, set parcels with a main crop that stays late on the field to an IGNORE
# class.
for class_name, cropcodes in late_main_crops.items():
parceldata_df.loc[

Check warning on line 1203 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L1202-L1203

Added lines #L1202 - L1203 were not covered by tests
parceldata_df[column_BEFL_maincrop].isin(cropcodes), column_output_class
] = class_name
if not is_groundtruth:
parceldata_df.loc[

Check warning on line 1207 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L1206-L1207

Added lines #L1206 - L1207 were not covered by tests
parceldata_df[column_BEFL_maincrop].isin(cropcodes),
conf.columns["class_declared"],
] = class_name

elif scope == "LATE_MAINCROP":

Check warning on line 1212 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L1212

Added line #L1212 was not covered by tests
# Only process parcels with a late main crop.
# Hence, set parcels with a main crop that is remove early to an IGNORE class.
early_maincrop_classname = "IGNORE_EARLY_MAINCROP"

Check warning on line 1215 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L1215

Added line #L1215 was not covered by tests

early_maincrops = []
for _, cropcodes in late_main_crops.items():
early_maincrops.extend(cropcodes)

Check warning on line 1219 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L1217-L1219

Added lines #L1217 - L1219 were not covered by tests

parceldata_df.loc[

Check warning on line 1221 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L1221

Added line #L1221 was not covered by tests
~parceldata_df[column_BEFL_maincrop].isin(early_maincrops),
column_output_class,
] = early_maincrop_classname
if not is_groundtruth:
parceldata_df.loc[

Check warning on line 1226 in cropclassification/preprocess/_prepare_input_BEFL.py

View check run for this annotation

Codecov / codecov/patch

cropclassification/preprocess/_prepare_input_BEFL.py#L1225-L1226

Added lines #L1225 - L1226 were not covered by tests
~parceldata_df[column_BEFL_maincrop].isin(early_maincrops),
conf.columns["class_declared"],
] = early_maincrop_classname

# For rows with no class, set to UNKNOWN
parceldata_df.fillna(value={column_output_class: "UNKNOWN"}, inplace=True)

Expand Down Expand Up @@ -1355,57 +1376,6 @@
return parceldata_df


def prepare_input_latecrop_early(
parceldata_df,
column_BEFL_latecrop: str,
column_BEFL_latecrop2: Optional[str],
column_BEFL_maincrop: str,
column_output_class: str,
classes_refe_path: Path,
min_parcels_in_class: int,
is_groundtruth: bool,
):
"""Prepare input file for use in the latecrop_early marker.

Prepare a classname column to classify the crop groups for early detection of
late crops. During this early detection, some main crops will still be on the field
during the entire perios. For these cases, replace the class with a class based on
the main crop.
"""
# First run the standard latecrop prepare
parceldata_df = prepare_input_latecrop(
parceldata_df=parceldata_df,
column_BEFL_latecrop=column_BEFL_latecrop,
column_BEFL_latecrop2=column_BEFL_latecrop2,
column_BEFL_maincrop=column_BEFL_maincrop,
column_output_class=column_output_class,
classes_refe_path=classes_refe_path,
min_parcels_in_class=min_parcels_in_class,
is_groundtruth=is_groundtruth,
)

# Set parcels having a main crop that stays late on the field to another class, as
# the main crop will still be on the field:
# TODO: should be in REFE instead of hardcoded!!!
late_main_crops = {
"MAINCROP_BEETS": ["71", "91", "8532", "9532"],
"MAINCROP_MAIZE": ["201", "202"],
"IGNORE_LATE_MAINCROP": ["396"],
}

for class_name, cropcodes in late_main_crops.items():
parceldata_df.loc[
parceldata_df[column_BEFL_maincrop].isin(cropcodes), column_output_class
] = class_name
if not is_groundtruth:
parceldata_df.loc[
parceldata_df[column_BEFL_maincrop].isin(cropcodes),
conf.columns["class_declared"],
] = class_name

return parceldata_df


def prepare_input_cropgroup_early(
parceldata_df,
column_BEFL_cropcode: str,
Expand Down
Loading