Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
dcb8b6a
added or modified data for testing erase_layer
KriWay-LV Sep 27, 2024
b43cccb
add erase_layer_filename
KriWay-LV Sep 27, 2024
6d06207
add option to exlude erase_layer from parcels
KriWay-LV Sep 27, 2024
1471ec4
mofified test_task_calc_marker to work with exclude erase_layer
KriWay-LV Sep 27, 2024
2127a76
refactor
KriWay-LV Sep 27, 2024
b2cd74b
refactor code + test
KriWay-LV Sep 27, 2024
9be3972
refactor test
KriWay-LV Sep 27, 2024
680075a
refactor test
KriWay-LV Sep 27, 2024
2694d0a
refactor end2end test
KriWay-LV Sep 27, 2024
96ac6b8
Merge branch 'main' into feature/exclude-erase-layer
KriWay-LV Feb 13, 2025
f8d67a1
expect float16 in stead of float32
KriWay-LV Apr 30, 2026
0811a8a
undo the changes
KriWay-LV Apr 30, 2026
6e8b0b9
redo changes
KriWay-LV May 4, 2026
b4b70b9
pinned version rasterio and tests with minimal python 3.12
KriWay-LV May 4, 2026
9464546
use python 3.13 for macos-latest test
KriWay-LV May 5, 2026
16c7b74
skip tests when certain rasterio version
KriWay-LV May 5, 2026
77090f6
rasterio not pinned
KriWay-LV May 5, 2026
0b61113
set minimal python version to 3.10
KriWay-LV May 5, 2026
e750708
refactor yml
KriWay-LV May 5, 2026
6f2bdc6
refactor yml
KriWay-LV May 5, 2026
d51fc23
updated gpkg
KriWay-LV May 8, 2026
9196bca
Merge remote-tracking branch 'upstream/main' into feature/exclude-era…
KriWay-LV May 8, 2026
67ca893
merge main branch
KriWay-LV May 8, 2026
1b10240
refactor comment
KriWay-LV May 8, 2026
4c93687
Merge branch 'feature/fix-tests' into feature/exclude-erase-layer
KriWay-LV May 8, 2026
74255f3
refactor
KriWay-LV May 11, 2026
ebc47a6
ne eraselayer tsv file
KriWay-LV May 11, 2026
659478a
fix test exclude_erase_layer
KriWay-LV May 11, 2026
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: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
matrix:
os: [ubuntu-latest]
dev: [false]
python: ["3.10", "3.11", "3.12"]
python: ["3.10", "3.11", "3.12", "3.13"]
env: ["latest"]
# Use openblas instead of mkl saves 600 MB. Linux OK, 50% slower on Windows and OSX!
extra: ["nomkl"]
Expand All @@ -44,7 +44,7 @@ jobs:
- env: latest
os: windows-latest
dev: false
python: "3.12"
python: "3.13"

steps:
- uses: actions/checkout@v6
Expand Down
13 changes: 11 additions & 2 deletions cropclassification/calc_cropclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ def run_cropclass(
input_model_to_use_relativepath = conf.calc_marker_params.getpath(
"input_model_to_use_relativepath"
)
erase_layer_filename = conf.calc_marker_params.getpath("erase_layer_filename")

# Prepare input paths
if input_model_to_use_relativepath is not None:
Expand All @@ -138,6 +139,11 @@ def run_cropclass(
refe_dir = conf.paths.getpath("refe_dir")
classes_refe_path = refe_dir / classes_refe_filename

if erase_layer_filename is not None:
erase_layer_path = input_dir / erase_layer_filename
else:
erase_layer_path = None

# Check if the necessary input files exist...
for path in [classes_refe_path, input_parcel_path]:
if path is not None and not path.exists():
Expand All @@ -157,8 +163,9 @@ def run_cropclass(
# -------------------------------------------------------------

# Prepare the input data for optimal image data extraction:
# 1) apply a negative buffer on the parcel to evade mixels
# 2) remove features that became null because of buffer
# 1) exlude erase_layer from agricultural parcels
# 2) apply a negative buffer on the parcel to evade mixels
# 3) remove features that became null because of buffer
input_preprocessed_dir = conf.paths.getpath("input_preprocessed_dir")
buffer = conf.timeseries.getfloat("buffer")
input_parcel_nogeo_path = (
Expand All @@ -174,6 +181,8 @@ def run_cropclass(
input_parcel_path=input_parcel_path,
output_imagedata_parcel_input_path=imagedata_input_parcel_path,
output_parcel_nogeo_path=input_parcel_nogeo_path,
erase_layer_path=erase_layer_path,
classes_refe_path=classes_refe_path,
)

# STEP 2: Get the timeseries data needed for the classification
Expand Down
2 changes: 2 additions & 0 deletions cropclassification/general.ini
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ input_parcel_filename = MUST_OVERRIDE
input_parcel_filetype = MUST_OVERRIDE
# The lookup table (LUT) file where classes to classify to are specified
classes_refe_filename = MUST_OVERRIDE
# The filename of the erase_layer geofile
erase_layer_filename
# A groundtruth file for extra reporting, optional
input_groundtruth_filename
# The model to use if you want to reuse one instead of training one, optional
Expand Down
70 changes: 69 additions & 1 deletion cropclassification/preprocess/_timeseries_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ def prepare_input(
input_parcel_path: Path,
output_imagedata_parcel_input_path: Path,
output_parcel_nogeo_path: Path | None = None,
erase_layer_path: Path | None = None,
classes_refe_path: Path | None = None,
force: bool = False,
) -> bool:
"""Prepare a file so it is ready for timeseries extraction of sentinel images.

Args:
input_parcel_path (Path): input file
output_imagedata_parcel_input_path (Path): prepared output file
output_parcel_nogeo_path (Path): output file with a copy of the non-geo data
output_parcel_nogeo_path (Path | None): output file with a copy of non-geo data
erase_layer_path (Path | None): erase layer path
classes_refe_path: (Path | None): classes reference path
force: force creation, even if output file(s) exist already
"""
# Check if parameters are OK and init some extra params
Expand Down Expand Up @@ -101,6 +105,17 @@ def prepare_input(
)
return False

# Exclude erase_layer from agricultural parcels
if erase_layer_path is not None and classes_refe_path is not None:
output_imagedata_parcel_input_path = exclude_erase_layer(
input_parcel_path=input_parcel_path,
output_imagedata_parcel_input_path=output_imagedata_parcel_input_path,
erase_layer_path=erase_layer_path,
classes_refe_path=classes_refe_path,
)
else:
logger.info("No erase layer file found, erase_layer will not be excluded")

# Apply buffer
parceldata_buf_gdf = parceldata_gdf.copy()
# resolution = number of segments per circle
Expand Down Expand Up @@ -272,3 +287,56 @@ def get_fileinfo_timeseries_periods(path: Path) -> dict:
}

return get_fileinfo_timeseries(path)


def exclude_erase_layer(
input_parcel_path: Path,
output_imagedata_parcel_input_path: Path,
classes_refe_path: Path,
erase_layer_path: Path,
) -> Path:
"""This function excludes the erase layer from the agricultural parcels."""
# Read reference data
# Select all parcels where ignore_erase_layer is True
classes_refe_df = pdh.read_file(classes_refe_path)

# Check if ignore_erase_layer_df has columns IGNORE_ERASE_LAYER
if "IGNORE_ERASE_LAYER" not in classes_refe_df.columns:
raise Exception("IGNORE_ERASE_LAYER column not found in classes reference file")

ignore_erase_layer_df = classes_refe_df[classes_refe_df["IGNORE_ERASE_LAYER"] == 1][
"CROPCODE"
]
gewascodes = tuple(map(str, (ignore_erase_layer_df)))

logger.info("Erase layer will be excluded")

# Create temp dir to store temporary data for tracebility
temp_output_dir = output_imagedata_parcel_input_path.parent / "temp"
temp_output_dir.mkdir(parents=True, exist_ok=True)

# Select all parcels where gwscod_h is in gewascodes
sql_stmt = f"""
SELECT *
FROM "{{input_layer}}"
WHERE gwscod_h IN {gewascodes}
"""
gfo.select(
input_path=input_parcel_path,
output_path=temp_output_dir / "ignore_erase_layer.gpkg",
sql_stmt=sql_stmt,
)
# Create erase_layer_prc file by erasing all
# agricultural parcels with "ignore_erase_layer" True from the erase_layer" file
gfo.erase(
input_path=erase_layer_path,
erase_path=temp_output_dir / "ignore_erase_layer.gpkg",
output_path=temp_output_dir / "erase_layer_prc.gpkg",
)
# Erase the erase_layer_prc from the input agricultural parcels
gfo.erase(
input_path=input_parcel_path,
erase_path=temp_output_dir / "erase_layer_prc.gpkg",
output_path=output_imagedata_parcel_input_path,
)
return output_imagedata_parcel_input_path
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ UID HOOFDTEELT_CTRL_COD HOOFDTEELT_CTRL_COD_ORIG HOOFDTEELT_CTRL_NAM_ORIG GESP_P
000028105F1645A400000001 91 91 Suikerbieten
000028104AD7C78000000007 60 60 Grasland MAA BG
000028104AD7CB7600000004 60 60 Grasland MAA BG
000028104C44425B00000001 60 60 Grasland MAA BG
000028104C44425B00000001 8915 8915 Bebossing
000028104C4440C700000001 60 60 Grasland MAA BG
00002810694D925500000002 60 60 Grasland MAA BG
000028104AD7C7E500000001 60 60 Grasland MAA BG
Expand Down
Binary file not shown.
Loading
Loading