### Persephone - a socio-economic-ecological model of European agricultural landscapes. ### ### This file includes functions for configuring the model and reading in map files. ### ## Note: much of this code was adapted from the GeMM model by Leidinger et al. ## (https://github.com/CCTB-Ecomods/gemm/blob/master/src/input.jl) ##XXX Does it make sense to move the settings dict into the model object itself? ## (It could be integrated into the properties dict.) Advantage: we have less ## global state lying around, and serialising becomes easier (if we want to do ## that). Also, during testing we often need to change individual parameters, ## which is currently impossible. Disadvantage: immutability of parameters at ## runtime is intended, and some start-up functions may have problems if they need ## access to parameters before the model object has been created. ##TODO -> yes, changing this is probably sensible let settings::Dict{String, Dict{String, Any}} """ initsettings(configfile) Initialise the global model settings for this run. """ global function initsettings(configfile::String) settings = getsettings(configfile) end """ param(domainparam) Return a configuration parameter from the global settings. The argument should be in the form `"<domain>.<parameter>"`, for example `param("core.outdir")`. Possible values for <domain> are "core", "nature", "farm", or "crop". For a full list of parameters, see `src/parameters.toml`. """ global function param(domainparam::String) domain, paramname = split(domainparam, ".") settings[domain][paramname] end """ printparameters(io) Print all settings in TOML format to the given output stream. """ global function printparameters(stream::IO=stdout) TOML.print(stream, settings) end end """ getsettings(configfile) Combines all configuration options to produce a single settings dict. Precedence: commandline parameters - user config file - default values """ function getsettings(configfile::String) # read in and merge configurations from the commandline, the default config file # and a user-supplied config file defaults = TOML.parsefile(configfile) commandline = parsecommandline() if haskey(commandline, "configfile") && isfile(commandline["configfile"]) configs = TOML.parsefile(commandline["configfile"]) else configs = nothing end settings = deepcopy(defaults) for domain in keys(defaults) for param in keys(defaults[domain]) if param in keys(commandline) settings[domain][param] = commandline[param] elseif !isnothing(configs) && param in keys(configs[domain]) settings[domain][param] = configs[domain][param] end end end # pre-process certain parameters if settings["core"]["seed"] == 0 settings["core"]["seed"] = abs(rand(RandomDevice(), Int32)) end defaultoutdir = defaults["core"]["outdir"] if settings["core"]["outdir"] == defaultoutdir outdir = defaultoutdir*"_"*string(Dates.today())*"_s"*string(settings["core"]["seed"]) settings["core"]["outdir"] = outdir end settings end """ parsecommandline() Certain software parameters can be set via the commandline. """ function parsecommandline() versionstring = """ Persephone $(@project_version), commit $(read(`git rev-parse HEAD`, String)[1:8]) © 2022 Daniel Vedder, Lea Kolb (MIT license) https://git.idiv.de/xo30xoqa/persephone """ s = ArgParseSettings(add_version=true, version=versionstring) @add_arg_table! s begin "--configfile", "-c" help = "name of the configuration file" arg_type = String required = false "--seed", "-s" help = "inital random seed" arg_type = Int "--outdir", "-o" help = "location of the output directory" arg_type = String required = false "--loglevel", "-l" help = "verbosity: \"debug\", \"info\", or \"quiet\"" arg_type = String required = false end args = parse_args(s) for a in keys(args) (args[a] == nothing) && delete!(args, a) end args end