fix: align WALOUS with official class codes
This commit is contained in:
@@ -41,13 +41,15 @@ class WalousProduct:
|
||||
download_url: str
|
||||
source_sha256_filename: str
|
||||
accuracy_label: str
|
||||
observation_start: datetime
|
||||
observation_end: datetime
|
||||
|
||||
|
||||
class WalousLandCoverService:
|
||||
PROVIDER = "spw_walous_land_cover"
|
||||
SOURCE_CRS = "EPSG:3812"
|
||||
SOURCE_RESOLUTION_M = 1.0
|
||||
SOURCE_VALUE_UNIT = "class_1_11"
|
||||
SOURCE_VALUE_UNIT = "walous_class_code"
|
||||
THEME = "land_cover_use"
|
||||
METRIC_KIND = "categorical_area"
|
||||
NODATA = 255
|
||||
@@ -58,31 +60,33 @@ class WalousLandCoverService:
|
||||
"geconfigureerde analyseresolutie. Oppervlakten zijn celgebaseerde schattingen; de kaart is landbedekking, "
|
||||
"geen juridisch landgebruik, eigendom, boomtelling of actuele terreinwaarneming."
|
||||
)
|
||||
# WALOUS has 11 semantic classes, but its official raster codes are not a
|
||||
# continuous 1..11 range. Codes 80 and 90 distinguish low woody cover.
|
||||
CLASS_LABELS = {
|
||||
1: "Jaarlijks wisselende kruidlaag",
|
||||
2: "Jaarronde kruidlaag",
|
||||
3: "Naaldbomen hoger dan 3 m",
|
||||
4: "Loofbomen hoger dan 3 m",
|
||||
5: "Naaldbomen tot 3 m",
|
||||
6: "Loofbomen tot 3 m",
|
||||
7: "Kale bodem",
|
||||
8: "Oppervlaktewater",
|
||||
9: "Kunstmatige bodembedekking",
|
||||
10: "Spoorweg",
|
||||
11: "Kunstmatige constructies boven maaiveld",
|
||||
1: "Kunstmatige bodembedekking",
|
||||
2: "Kunstmatige constructies boven maaiveld",
|
||||
3: "Spoorweg",
|
||||
4: "Kale bodem",
|
||||
5: "Oppervlaktewater",
|
||||
6: "Jaarlijks wisselende kruidlaag",
|
||||
7: "Jaarronde kruidlaag",
|
||||
8: "Naaldbomen hoger dan 3 m",
|
||||
9: "Loofbomen hoger dan 3 m",
|
||||
80: "Naaldbomen tot 3 m",
|
||||
90: "Loofbomen tot 3 m",
|
||||
}
|
||||
CLASS_COLORS = {
|
||||
1: (236, 202, 73),
|
||||
2: (161, 201, 78),
|
||||
3: (28, 89, 51),
|
||||
4: (52, 132, 72),
|
||||
5: (78, 125, 70),
|
||||
6: (107, 164, 87),
|
||||
7: (194, 165, 119),
|
||||
8: (44, 129, 185),
|
||||
9: (155, 155, 155),
|
||||
10: (68, 68, 68),
|
||||
11: (183, 72, 67),
|
||||
1: (155, 155, 155),
|
||||
2: (183, 72, 67),
|
||||
3: (68, 68, 68),
|
||||
4: (194, 165, 119),
|
||||
5: (44, 129, 185),
|
||||
6: (236, 202, 73),
|
||||
7: (161, 201, 78),
|
||||
8: (28, 89, 51),
|
||||
9: (52, 132, 72),
|
||||
80: (78, 125, 70),
|
||||
90: (107, 164, 87),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
@@ -101,6 +105,8 @@ class WalousLandCoverService:
|
||||
),
|
||||
source_sha256_filename="walous_land_cover_2020_3812.sha256",
|
||||
accuracy_label="Officiele globale nauwkeurigheid 83,30%",
|
||||
observation_start=datetime(2020, 4, 1, tzinfo=UTC),
|
||||
observation_end=datetime(2020, 4, 24, 23, 59, 59, tzinfo=UTC),
|
||||
),
|
||||
WalousProduct(
|
||||
key="walous_land_cover_2023",
|
||||
@@ -115,6 +121,8 @@ class WalousLandCoverService:
|
||||
),
|
||||
source_sha256_filename="walous_land_cover_2023_3812.sha256",
|
||||
accuracy_label="Officiele globale nauwkeurigheid 87,10%",
|
||||
observation_start=datetime(2023, 5, 27, tzinfo=UTC),
|
||||
observation_end=datetime(2023, 6, 25, 23, 59, 59, tzinfo=UTC),
|
||||
),
|
||||
)
|
||||
return {product.key: product for product in products}
|
||||
@@ -145,8 +153,8 @@ class WalousLandCoverService:
|
||||
catalog_url=product.catalog_url,
|
||||
attribution=WalousLandCoverService.ATTRIBUTION,
|
||||
license_note=WalousLandCoverService.LICENSE_NOTE,
|
||||
legend_min_label="WALOUS klasse 1",
|
||||
legend_max_label="WALOUS klasse 11",
|
||||
legend_min_label="WALOUS klasse 1 (kunstmatige bodem)",
|
||||
legend_max_label="WALOUS klasse 90 (loofbomen tot 3 m)",
|
||||
included_source_values=list(WalousLandCoverService.CLASS_LABELS),
|
||||
limitation_message=f"{WalousLandCoverService.LIMITATION} {product.accuracy_label}.",
|
||||
coverage_zones=["wallonia"],
|
||||
@@ -250,7 +258,12 @@ class WalousLandCoverService:
|
||||
classes = set(np.unique(valid).astype(int).tolist())
|
||||
unexpected = sorted(classes - set(WalousLandCoverService.CLASS_LABELS))
|
||||
if unexpected:
|
||||
raise AppError(code="WALOUS_SOURCE_INVALID_VALUES", message="WALOUS contains classes outside the governed 1-11 legend", details={"unexpected_classes": unexpected}, status_code=409)
|
||||
raise AppError(
|
||||
code="WALOUS_SOURCE_INVALID_VALUES",
|
||||
message="WALOUS contains classes outside the governed 11-class code set",
|
||||
details={"unexpected_classes": unexpected},
|
||||
status_code=409,
|
||||
)
|
||||
profile = {
|
||||
"driver": "GTiff",
|
||||
"width": width,
|
||||
@@ -345,7 +358,7 @@ class WalousLandCoverService:
|
||||
source_sha256_path = source_path.with_name(product.source_sha256_filename)
|
||||
source_sha256 = source_sha256_path.read_text(encoding="ascii").strip().split()[0] if source_sha256_path.is_file() else None
|
||||
acquired_at = datetime.now(UTC)
|
||||
observed_at = datetime(product.observation_year, 12, 31, 23, 59, 59, tzinfo=UTC)
|
||||
observed_at = product.observation_end
|
||||
spatial_series_hash = hashlib.sha256(json.dumps({"bbox": identity["bbox_epsg4326"], "area_id": identity["area_id"], "resolution": identity["analysis_resolution_m"]}, sort_keys=True).encode()).hexdigest()[:24]
|
||||
dataset = DatasetService.import_raster_bytes(
|
||||
db,
|
||||
@@ -357,8 +370,8 @@ class WalousLandCoverService:
|
||||
source_name=WalousLandCoverService.PROVIDER,
|
||||
temporal_series_key=f"spw:walous:land-cover:{spatial_series_hash}",
|
||||
observed_at=observed_at,
|
||||
valid_from=datetime(product.observation_year, 1, 1, tzinfo=UTC),
|
||||
valid_to=observed_at,
|
||||
valid_from=product.observation_start,
|
||||
valid_to=product.observation_end,
|
||||
temporal_granularity="year",
|
||||
source_version=product.source_version,
|
||||
source_metadata={
|
||||
@@ -374,6 +387,8 @@ class WalousLandCoverService:
|
||||
"source_value_unit": WalousLandCoverService.SOURCE_VALUE_UNIT,
|
||||
"class_labels": WalousLandCoverService.CLASS_LABELS,
|
||||
"observation_year": product.observation_year,
|
||||
"observation_start": product.observation_start.isoformat(),
|
||||
"observation_end": product.observation_end.isoformat(),
|
||||
"valid_pixel_count": validation["valid_pixel_count"],
|
||||
"classes_present": validation["classes_present"],
|
||||
"bbox_epsg4326": bbox_4326,
|
||||
@@ -480,12 +495,12 @@ class WalousLandCoverService:
|
||||
|
||||
metric_specs = [
|
||||
("land_cover_observed_area_ha", "Gekarteerde landbedekking", set(WalousLandCoverService.CLASS_LABELS)),
|
||||
("forest_cover_area_ha", "Boom- en bosbedekking", {3, 4, 5, 6}),
|
||||
("surface_water_area_ha", "Oppervlaktewater", {8}),
|
||||
("artificial_cover_area_ha", "Kunstmatige bedekking en constructies", {9, 10, 11}),
|
||||
("annual_herbaceous_cover_area_ha", "Jaarlijks wisselende kruidlaag", {1}),
|
||||
("permanent_herbaceous_cover_area_ha", "Jaarronde kruidlaag", {2}),
|
||||
("bare_soil_area_ha", "Kale bodem", {7}),
|
||||
("forest_cover_area_ha", "Boom- en bosbedekking", {8, 9, 80, 90}),
|
||||
("surface_water_area_ha", "Oppervlaktewater", {5}),
|
||||
("artificial_cover_area_ha", "Kunstmatige bedekking en constructies", {1, 2, 3}),
|
||||
("annual_herbaceous_cover_area_ha", "Jaarlijks wisselende kruidlaag", {6}),
|
||||
("permanent_herbaceous_cover_area_ha", "Jaarronde kruidlaag", {7}),
|
||||
("bare_soil_area_ha", "Kale bodem", {4}),
|
||||
]
|
||||
metrics = [
|
||||
ThematicRasterMetric(
|
||||
|
||||
Reference in New Issue
Block a user