From 638a6bf5e54fb9f831365a08b05954721e4095f3 Mon Sep 17 00:00:00 2001
From: Marco Matthies <71844+marcom@users.noreply.github.com>
Date: Mon, 3 Feb 2025 23:08:27 +0100
Subject: [PATCH] Fix soil type mapping from Bodenatlas identifiers to
 Persefone soil type enum

---
 src/world/landscape.jl | 65 +++++++++++++++++++++++++++++-------------
 1 file changed, 45 insertions(+), 20 deletions(-)

diff --git a/src/world/landscape.jl b/src/world/landscape.jl
index cfc2669..cdd6d18 100644
--- a/src/world/landscape.jl
+++ b/src/world/landscape.jl
@@ -9,27 +9,51 @@ using Printf
 "The land cover classes encoded in the Mundialis Sentinel data."
 @enum LandCover nodata forest grass water builtup soil agriculture
 
-# TODO: check names and order of enum
-# TODO: note where values come from
-## IMPORTANT: do not change the order of this enum, or initlandscape() will break!
-"The soil type"
+"The soil type of a Pixel or FarmPlot"
 @enum SoilType begin
-    soiltype_nodata = 0       # 0
-    soiltype_sand             # 1
-    soiltype_loamy_sand       # 2
-    soiltype_sandy_loam       # 3
-    soiltype_loam             # 4
-    soiltype_silt_loam        # 5
-    soiltype_silt             # 6
-    soiltype_sandy_clay_loam  # 7
-    soiltype_clay_loam        # 8
-    soiltype_silty_clay_loam  # 9
-    soiltype_sandy_clay       # 10
-    soiltype_silty_clay       # 11
-    soiltype_clay             # 12
-    soiltype_unknown          # 13  TODO: invented this to get a type 13
+    nosoildata = 0   # 0
+    sand             # 1
+    loamy_sand       # 2
+    sandy_loam       # 3
+    loam             # 4
+    silt_loam        # 5
+    silt             # 6
+    sandy_clay_loam  # 7
+    clay_loam        # 8
+    silty_clay_loam  # 9
+    sandy_clay       # 10
+    silty_clay       # 11
+    clay             # 12
+    nosoil           # 13
 end
 
+# TODO: move this into a CSV file and read it from there
+"""Bodenatlas soil type id, corresponding Persefone soil type, and numbers to Persefone SoilType enum and the
+   original Bodenatlas description of the soil type"""
+const df_soiltypes_bodenatlas = DataFrame(
+    NamedTuple{(:bodenatlas_id, :bodenatlas_name, :persefone_soiltype), Tuple{Int, String, SoilType}}.([
+        ( 1, "Abbauflächen",      nosoil),
+        ( 2, "Gewässer",          nosoil),
+        ( 3, "Lehmsande (ls)",    loamy_sand),
+        ( 4, "Lehmschluffe (lu)", silt_loam),
+        ( 5, "Moore",             nosoil),
+        ( 6, "Normallehme (ll)",  loam),
+        ( 7, "Reinsande (ss)",    sand),
+        ( 8, "Sandlehme (sl)",    sandy_loam),
+        ( 9, "Schluffsande (us)", sandy_loam),
+        (10, "Schlufftone (ut)",  silty_clay),
+        (11, "Siedlung",          nosoil),
+        (12, "Tonlehme (tl)",     clay_loam),
+        (13, "Tonschluffe (tu)",  silty_clay_loam),
+        (14, "Watt",              nosoil),
+    ])
+)
+
+"Map a Bodenatlas soil type integer to a Persefone `SoilType` enum"
+const soiltype_bodenatlas_to_persefone =
+    Dict{Int,SoilType}(row.bodenatlas_id => row.persefone_soiltype for row in eachrow(df_soiltypes_bodenatlas))
+
+
 "The types of management event that can be simulated"
 @enum Management tillage sowing fertiliser pesticide harvesting
 
@@ -53,7 +77,7 @@ end
 Pixel(landcover::LandCover, soiltype::SoilType, fieldid::Union{Missing,Int64}) =
     Pixel(landcover, soiltype, fieldid, Vector{Management}(), Vector{Int64}(), Vector{String}())
 Pixel(landcover::LandCover, fieldid::Union{Missing,Int64}) =
-    Pixel(landcover, soiltype_nodata, fieldid)
+    Pixel(landcover, nosoildata, fieldid)
 Pixel(landcover::LandCover) = Pixel(landcover, missing)
 
 showlandscape(mat::T) where T <: AbstractMatrix{Pixel} = showlandscape(stdout, mat)
@@ -154,8 +178,9 @@ function initlandscape(directory::String, landcovermap::String, farmfieldsmap::S
             # convert the numeric landcover value to LandCover, then create the Pixel object
             lcv = LandCover(Int(landcover[x,y][1]/10))
             ff = Int64(farmfields[x,y][1])
+            st = soiltype_bodenatlas_to_persefone[Int(soiltypes[x, y][1])]
             (iszero(ff)) && (ff = missing)
-            landscape[x,y] = Pixel(lcv, ff)
+            landscape[x,y] = Pixel(lcv, st, ff)
         end
     end
     return landscape
-- 
GitLab