DSSAT-wrapper Guide

DSSAT-wrapper lets you run any DSSAT crop model from R and get tidy observed-vs-simulated data back. You point it at your DSSAT installation and an experiment file; it works out which model to use, runs DSSAT, and returns the variable you asked for.

Read the pages in this order

  1. Installed DSSAT Setup — what you need and how to confirm the wrapper can see your DSSAT install. Start here.
  2. Using GitHub-Sourced Example Data — optional: run experiments from a separate data download instead of your DSSAT folder.
  3. Your First Run — a full copy-paste example and how to read the result.
  4. Self-Check and Validation — how to test that your setup works, and what "testing DSSAT" actually means.
  5. Supported Families — every crop family the wrapper drives, with the example used to validate each.
  6. Attribution and Disclaimer.

If you only read one thing

You almost never need to tell the wrapper which model to use — it reads that from your DSSAT install. A minimal run is:

source("R/DSSAT_omniwrapper.R")
result <- DSSAT_omniwrapper(
  model_options = list(
    DSSAT_path   = "C:/DSSAT48",
    DSSAT_exe    = "DSCSM048.EXE",
    project_file = "C:/DSSAT48/Wheat/KSAS8101.WHX"
  ),
  situation = "KSAS8101_1",
  var       = "GSTD"
)

Developers who want to understand or extend the code should read the Architecture (for developers) page (the resolve → run → parse design).

Installed DSSAT Setup

Start here if DSSAT is already installed on your computer. This page gets your environment ready and confirms the wrapper can see DSSAT. The actual run is on the next page, Your First Run.

1. What you need

  • A local DSSAT installation — on Windows this is a folder such as C:\DSSAT48 containing DSCSM048.EXE and crop folders (Wheat, Maize, …).

  • R (4.1 or newer).

  • These R packages (install once):

    install.packages(c("DSSAT", "dplyr", "tidyr", "lubridate", "DBI", "RSQLite"))
    

2. Load the wrapper

You source one file; it loads the rest:

source("R/DSSAT_omniwrapper.R")

Use a full path if you are not in the repository folder, e.g. source("C:/Users/you/DSSAT-wrapper/R/DSSAT_omniwrapper.R").

3. Confirm DSSAT is found (before running anything)

Run the self-check. It does not simulate — it just verifies the executable, genotype files, experiment, situation and variable all exist, so you catch setup problems early:

chk <- DSSAT_omni_self_check(
  model_options = list(
    DSSAT_path   = "C:/DSSAT48",
    DSSAT_exe    = "DSCSM048.EXE",
    project_file = "C:/DSSAT48/Wheat/KSAS8101.WHX"
  ),
  situation    = "KSAS8101_1",
  required_var = "GSTD"
)
chk$ok      # TRUE means you are ready
chk$checks  # a table showing each item and whether it was found

If chk$ok is TRUE, continue to Your First Run. If not, the chk$checks table names exactly which file or setting is missing.

Using GitHub-Sourced Example Data

This page is optional. A normal DSSAT install already ships example experiments inside each crop folder (e.g. C:/DSSAT48/Maize/UFGA8201.MZX), so for most users the Installed DSSAT Setup page is all you need.

Use this page only if you want to run experiments that are not in your DSSAT folder — for example the public example datasets from the DSSAT source repository.

1. Get the example data

Clone (or download) the DSSAT model repository, which contains example data:

git clone https://github.com/DSSAT/dssat-csm-os.git

The crop example files live under that checkout (e.g. a Maize/UFGA8201.MZX).

2. Point the wrapper at it

Keep DSSAT_path pointing at your installed DSSAT (it still provides the executable and genotype files); set project_file to the experiment from your downloaded data. Naming a different model is optional — here we ask for the CERES-IXIM maize model with module_code:

source("R/DSSAT_omniwrapper.R")

result <- DSSAT_omniwrapper(
  model_options = list(
    DSSAT_path   = "C:/DSSAT48",                               # installed DSSAT
    DSSAT_exe    = "DSCSM048.EXE",
    Crop         = "Maize",
    project_file = "C:/path/to/dssat-csm-os/Maize/UFGA8201.MZX",  # downloaded data
    module_code  = "MZIXM048"                                  # optional: force a model
  ),
  situation = "UFGA8201_1",
  var       = "CWAD"
)

3. Validation scripts and the data path

The family-validation script can read example experiments from such a checkout. Tell it where they are with the DSSAT_CSM_DATA environment variable (see Self-Check and Validation). If you do not set it, the scripts look for the data next to the repository, and fall back to your DSSAT install — which, since DSSAT ships its own examples, is usually enough on its own.

Your First Run

This page assumes you have never used the wrapper before. Follow it top to bottom.

0. What you need first

  1. DSSAT installed on your computer. On Windows this is usually a folder like C:\DSSAT48 that contains DSCSM048.EXE and crop folders (Wheat, Maize, …).

  2. R (4.1 or newer).

  3. The R packages the wrapper uses. Install them once:

    install.packages(c("DSSAT", "dplyr", "tidyr", "lubridate", "DBI", "RSQLite"))
    

1. Load the wrapper

You only ever source one file — it loads the rest for you:

source("R/DSSAT_omniwrapper.R")

(Use the full path if you are not in the repository folder, e.g. source("C:/Users/you/DSSAT-wrapper/R/DSSAT_omniwrapper.R").)

2. Run a shipped example (copy–paste)

Every DSSAT install ships example experiments. Here we run the wheat one. You do not need to know the model name — the wrapper figures it out from your DSSAT install (this is "auto-detection").

result <- DSSAT_omniwrapper(
  model_options = list(
    DSSAT_path   = "C:/DSSAT48",                       # <- your DSSAT folder
    DSSAT_exe    = "DSCSM048.EXE",                      # the DSSAT program
    project_file = "C:/DSSAT48/Wheat/KSAS8101.WHX",    # an experiment file (.??X)
    suppress_output = TRUE                             # hide DSSAT console spam
  ),
  situation = "KSAS8101_1",   # which treatment: <experiment name>_<number>
  var       = "GSTD"          # the variable you want back (here: growth stage)
)

3. Look at what you got back

result is a list with two parts:

result$error                       # FALSE means the run succeeded
sim <- result$sim_list[["KSAS8101_1"]]   # the data for your situation
head(sim)                          # a data frame: Date + the variable you asked for
nrow(sim)                          # how many daily rows came back

A good first run means: result$error is FALSE, nrow(sim) is greater than 0, and your variable (GSTD here) is one of the columns.

4. Run it for YOUR OWN data

Change three things in model_options:

  • DSSAT_path → the folder where DSSAT is installed on your machine.
  • project_file → your experiment file (a .??X file, e.g. .SBX soybean, .MZX maize, .WHX wheat). It can be inside the DSSAT crop folder or your own.
  • situation"<experiment file name without extension>_<treatment number>", e.g. the first treatment of MYEXP01.SBX is "MYEXP01_1".

If you want a different output variable, change var (e.g. "CWAD" for above-ground biomass, "HWAM" for yield). You can also use a friendly name like "biomass" or "yield" — the wrapper maps it to the right column for that crop.

5. If something goes wrong

Run the self-check first — it tells you exactly which file or setting is missing before you blame the model. See Self-Check and Validation.

Self-Check and Validation

"Testing DSSAT" here means two different things. Know which one you want.

You want to check…UseAnswers
Is my setup wired up? (is DSSAT found, are files in place?)the self-check"are the executable, genotype files, experiment, situation and variable all present?"
Does the wrapper actually drive DSSAT correctly across crops?the validation scripts"do real experiments run and return data?"

A. Self-check — "is my setup correct?"

This runs no simulation. It just confirms every required file/setting exists, so you can fix setup problems before running anything. From R:

source("R/DSSAT_omniwrapper.R")
chk <- DSSAT_omni_self_check(
  model_options = list(
    DSSAT_path   = "C:/DSSAT48",
    DSSAT_exe    = "DSCSM048.EXE",
    project_file = "C:/DSSAT48/Wheat/KSAS8101.WHX"
  ),
  situation    = "KSAS8101_1",
  required_var = "GSTD"
)
chk$ok        # TRUE if everything needed is present
chk$checks    # a table: each item, the path checked, and exists = TRUE/FALSE

Or run the ready-made script from a terminal:

Rscript R/test_DSSAT_omni_self_check.R

You should see a table ending in Self-check overall status: OK. Any exists = FALSE row on a required = TRUE item tells you exactly what to fix.

B. Run-it-for-real tests

These actually launch DSSAT and check that data comes back.

# one experiment end-to-end
Rscript R/test_DSSAT_omniwrapper.R

# observed-data reading
Rscript R/test_DSSAT_omni_read_obs.R

# every model family (pineapple, cassava, sugarcane, forage, …)
Rscript R/validate_DSSAT_omniwrapper_families.R

validate_DSSAT_omniwrapper_families.R is the big one: it runs one example per model family and stops with an error if any family fails, so a clean finish means all validated families work on your machine.

C. The two environment variables

The scripts need to know where DSSAT and its example data live. Set these once per session (or let them default):

VariableWhat it points toDefault if unset
DSSAT_PATHyour DSSAT install folderC:/DSSAT48
DSSAT_CSM_DATAfolder of example experiments (often the same DSSAT folder, since it ships examples)the repo's examples/ then ../dssat-csm-data

Set them in R:

Sys.setenv(DSSAT_PATH = "C:/DSSAT48", DSSAT_CSM_DATA = "C:/DSSAT48")

…or in a terminal before calling Rscript:

# Windows PowerShell
$env:DSSAT_PATH = "C:/DSSAT48"; $env:DSSAT_CSM_DATA = "C:/DSSAT48"
Rscript R/validate_DSSAT_omniwrapper_families.R

A standard DSSAT install already contains the example experiments the validator needs, so pointing both variables at C:/DSSAT48 is usually enough.

Supported Families

Crop → model-family mapping is taken from the DSSAT install's DSSATPRO.V48 (the authoritative crop-to-module map) and confirmed by running an example experiment shipped in the DSSAT crop folders through DSSAT_omniwrapper().

Validated families

FamilyDSSAT moduleCrops coveredConfirmed example (rows)
CERESMZCER / SGCER / MLCER / SWCER / BSCER / CSCERmaize, sorghum, pearl millet, sweetcorn, sugarbeet, barley, wheatMaize UFGA8201.MZX (129); Sorghum CSKU8201.SGX (122)
CERES-IXIMMZIXMmaize (alternative)UFGA8201.MZX (129)
CROPGROCRGROsoybean, peanut, drybean, cowpea, chickpea, faba/green bean, canola, cotton, tomato, bell pepper, cabbage, sunflower, safflower, lentil, pigeonpea, velvetbean, bambara groundnut, amaranth, chia, quinoa, hemp, guar, strawberry, carinataSoybean GAGR0201.SBX (45)
CROPSIMCSCRPbarley, wheat (Cropsim-CERES)Barley IEBR8201.BAX (181)
NWHEATWHAPS / TFAPSwheat (APSIM-NWheat), teffTeff ETGA0201.TFX (208); Wheat KSAS8101.WHX (251)
OILCROPSUOILsunflowerAUTA8101.SUX (136)
SUGARCANE (CANEGRO / CASUPRO / SAMUCA)SCCAN / SCCSP / SCSAMsugarcaneESAL1401.SCX (328); SAMUCA SAPO8601.SCX (335)
ALOHAPIALOpineappleUHKN8901.PIX (679)
AROIDSTRARO / TNAROtaro, tanierTaro IBHK8901.TRX (404)
CSYCACSYCAcassavaCCPA7801.CSX (363)
SUBSTORPTSUBpotatoAUCB7001.PTX (135)
RICERICERriceDTSP8502.RIX (93)
FORAGEPRFRMalfalfa, bahia grass, bermuda grass, brachiaria, guinea grassAlfalfa AGZG1219.ALX (1483); Bahia TXEL7901.BHX (610)

FORAGE note: perennial-forage (PRFRM) experiments require their mowing/harvest companion file (<EXPERIMENT>.MOW) to be staged into the run directory alongside the experiment. The wrapper now stages .MOW/.HAR companions automatically, so forage crops run without manual setup.

Known blocker

  • CSCAS (older cassava model): launches but the DSSAT executable exits with status 99. This is a DSSAT-side issue, not a wrapper problem — the same experiment (Cassava/CCPA7801.CSX) runs cleanly under CSYCA, the cultivars exist in CSCAS048.CUL, and all genotype files are present. Use CSYCA for cassava.

Auto-detection

You normally do not need to pass module_code. The wrapper resolves the model from the crop's default module in DSSATPRO.V48 (the authoritative DSSAT crop→module map). A model code parsed from the experiment header is only used when it is itself a registered family — otherwise a blank/garbled SMODEL field would override the correct default. With this resolution, 43 of 45 crop folders run from their shipped example with no module_code supplied.

Two shipped examples currently fail on their own data (not a wrapper or family issue):

  • Amaranth — example experiment aborts with DSSAT status 99.
  • BambaraGroundnut — DSSAT reports a missing input file for the shipped example.

Both belong to the working CROPGRO family (20+ other CROPGRO crops run), so these are example-dataset problems, not family-support gaps.

Not crop families

The DSSAT folders ClimateChange, Seasonal, Sequence, Spatial, and YieldForecast are simulation/analysis modes, not crop models, and are intentionally outside the family map.

Architecture (for developers)

Author: Victor Nyabuti Ong'era

This page explains how the code is organised, for anyone who wants to understand or extend it. If you only want to run the wrapper, the earlier pages are enough.

The 30-second mental model

            you call DSSAT_omniwrapper(model_options, situation, var)
                                   │
          ┌────────────────────────┼─────────────────────────┐
          ▼                        ▼                          ▼
   1. RESOLVE              2. RUN                      3. PARSE
   (registry.R)           (run.R)                     (outputs.R)
   "what model is         "stage files, run            "read PlantGro.OUT,
    this crop?"            DSCSM048.EXE"                pick the variable asked for"
          │                        │                          │
          └────────────────────────┴──────────────────────────┘
                                   ▼
                    list(sim_list = <data by situation>, error = FALSE)

The four files (each does one job)

FileJobKey functions
DSSAT_omniwrapper.REntry point. Sources the helpers, exposes the public function.DSSAT_omniwrapper, DSSAT_omni_read_obs
dssat_omni_registry.RResolve. Work out the crop, the 5-char model code, and the output adapter.dssat_omni_family_map, dssat_infer_model_options
dssat_omni_run.RRun. Make a clean run directory, copy in the experiment + genotype + companion files, run DSSAT.dssat_omni_run
dssat_omni_outputs.RParse. Read PlantGro.OUT and translate a friendly variable name (e.g. biomass) to the family's real column (e.g. CWAD).dssat_variable_alias_map, dssat_resolve_requested_vars

Two concepts that explain everything

  1. The family map (dssat_omni_family_map): a small table mapping a 5-char model code → an adapter name (e.g. MZCER → CERES, CRGRO → CROPGRO, PRFRM → FORAGE). The adapter decides which output columns/aliases to use. To support a new family you add one row here.

  2. DSSATPRO.V48 is the source of truth for "which model does this crop use". The DSSAT install ships this file; the wrapper reads it instead of hard-coding crop→model rules. This is what makes auto-detection work (you usually do not pass module_code).

A worked trace (soybean)

  1. You call with project_file = .../Soybean/GAGR0201.SBX.
  2. Resolve: crop code SB → DSSATPRO default module CRGRO048 → model code CRGRO → family map adapter CROPGRO.
  3. Run: copy GAGR0201.SBX + genotype files into a temp run dir, run DSCSM048.EXE, producing PlantGro.OUT.
  4. Parse: read PlantGro.OUT, return the CWAD column for situation GAGR0201_1 as a Date-indexed data frame.

Where to make common changes

  • Add a crop/family: one row in dssat_omni_family_map().
  • A family needs an extra input file (e.g. forage .MOW): the companion-file staging block in dssat_omni_run.R.
  • A variable maps to a different column for some family: the dssat_variable_alias_map() switch in dssat_omni_outputs.R.

Attribution and Disclaimer

This fork builds on the original DSSAT wrapper work associated with the AgMIP Calibration Phase III effort.

Original wrapper credits:

  • Jing Qi
  • Amir Souissi
  • Samuel Buis
  • Vakhtang Shelia

This fork (the registry-driven DSSAT_omniwrapper, multi-family validation, and this documentation) is maintained by Victor Nyabuti Ong'era, preserving the original lineage above.

License note

At the time of writing, the upstream wrapper snapshot used for this fork does not include an explicit LICENSE file. This repository therefore keeps attribution clear and does not claim license terms that are not stated upstream.

This work is shared in good faith for research and educational use. It is provided as-is, without warranty, and you are responsible for checking that it fits your own workflows, data, and redistribution needs.