This script integrates APSIM Next Generation, climate data, soil information, and machine learning to generate high-resolution (0.1°) maize yield maps for Egypt, including uncertainty and climate-change scenarios.
1️⃣ Environment Setup
rm(list=ls())
options(stringsAsFactors = FALSE)
🔹 Ensures a clean R session
🔹 Avoids accidental reuse of variables from previous runs
2️⃣ Packages
pkgs <- c("apsimx","data.table","dplyr","sf","foreach","doParallel",
"ranger","FNN","ggplot2","DBI","RSQLite","rnaturalearth",
"jsonlite","httr")
Why each package is needed
Package Role
apsimx Run APSIM NG & edit APSIMX files
DBI, RSQLite Read APSIM .db outputs
data.table, dplyr Fast data manipulation
sf, rnaturalearth Spatial grids & Egypt boundary
foreach, doParallel Parallel APSIM runs
ranger Random Forest ML
FNN k-nearest-neighbor interpolation
httr, jsonlite SoilGrids API
ggplot2 Visualization
3️⃣ User Settings (Paths & Controls)
base_dir <- "D:/APSIMICARDATraining/AnotherFullScript"
work_dir <- file.path(base_dir, "EG_Maize_CMIP6_FULL")
coarse_dir <- file.path(work_dir, "coarse")
Folder Logic
EG_Maize_CMIP6_FULL/
├─ coarse/
│ ├─ EG_0001/
│ │ ├─ MaizeFull.apsimx
│ │ ├─ EG_0001.met
│ │ └─ MaizeFull.db (created by APSIM)
├─ outputs_master/
└─ _cache/
This structure is critical — APSIM expects the .apsimx and .met files inside each site folder.
4️⃣ Helper Functions
Logging
msg("Running APSIM…")
Adds timestamps so participants can see progress.
Numeric Safety
to_na()
impute_median()
Guarantees:
No crashes from Inf, NaN
ML models never fail due to missing data
5️⃣ Indexing Coarse APSIM Sites
site_dirs <- list.dirs(coarse_dir, recursive=FALSE)
✔ Automatically discovers all EG_#### folders
✔ Builds a run index that controls the entire pipeline
This design allows:
10 sites or 1,000 sites
No hard-coded filenames
6️⃣ APSIM Report Configuration (Key Stability Step)
report_vars <- c(
"[Clock].Today as Date",
"[Maize].Grain.Total.Wt*10 as Yield",
"[Maize].Leaf.LAI as LAI",
"[Maize].AboveGround.Wt as Biomass"
)
Why this works
Uses existing Report node
No JSON hacking
Event = EndOfDay (universally safe)
Aliases columns so DB tables are predictable
This is the main reas …