From 59e9670f36d829134d6f0f0c76e4bbc3c67730e8 Mon Sep 17 00:00:00 2001 From: Florian Atteneder <florian.atteneder@uni-jena.de> Date: Mon, 5 Aug 2024 11:45:47 +0000 Subject: [PATCH] dg1d: allow parameter overriding on cmd line (https://git.tpi.uni-jena.de/dg/dg1d.jl/-/merge_requests/193) Allows to use `main(parfile, "Mesh.n" => "1")` to override the value given in the parfile. --- To do this we - parse the TOML file - flatten the dict-of-dicts to a single dict with the keys joined by a `.` - insert the parameters - unflatten the dict to a dict-of-dicts - write this to the output directory Unfortunately, `TOML.jl` does not allow to parse into `OrderedDict`. This causes the newly written parfiles to be messed up. Furthermore, by manually re-writing the parfiles we also do not preserve any comments or formatting. --- src/main.jl | 26 +++++++++++++++----------- src/utils.jl | 30 ++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/src/main.jl b/src/main.jl index 2e2f7a42..e8bc29dc 100644 --- a/src/main.jl +++ b/src/main.jl @@ -41,24 +41,27 @@ end Run program specified by a `parfile` in TOML format. """ -function main(parfile) +function main(parfile, parameter_overrides::Pair{String,String}...) parfile = abspath(parfile) + prms = TOML.parsefile(parfile) + flat_prms = flatten(prms) + for (k,v) in parameter_overrides + flat_prms[k] = v + end + prms = unflatten(flat_prms) + dir = dirname(parfile) - dummy_parfile = parfile if basename(dir) == splitext(basename(parfile))[1] # we are running parameter file contained in an output folder # so we backup that folder and run the parameter file one directory above - dummy_parfile = string(dir, ".toml") + parfile = string(dir, ".toml") end # backup any previous output dir and set up a fresh one - outputdir = make_outputdir(dummy_parfile) - if dummy_parfile != parfile - # we moved the initial parfile with the backup of the output folder - cp(joinpath(string(dir,".previous"),string(basename(dir),".toml")), - joinpath(outputdir, basename(parfile))) - else - cp(parfile, joinpath(outputdir, basename(parfile))) + outputdir = make_outputdir(parfile) + parfile = joinpath(outputdir, basename(parfile)) + open(parfile, "w") do file + TOML.print(file, prms) end cp(joinpath(@__DIR__,"..","Manifest.toml"), joinpath(outputdir,"Manifest.toml")) open(joinpath(outputdir, "dirty"), "w") do file @@ -104,7 +107,8 @@ function main(parfile) return end -main(id::Integer) = main(normalize_parfile(id)) +main(id::Integer, parameter_overrides::Pair{String,String}...) = + main(normalize_parfile(id); parameter_overrides) load_parameters(parfile::AbstractString) = parse_parameters(TOML.parsefile(parfile)) diff --git a/src/utils.jl b/src/utils.jl index ddacc763..fc91862c 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -221,8 +221,8 @@ end Flatten a dictionary `d` and concatenate all keys with `prefix_delim`. Returned dictionary is of type `Dict{Symbol,<:Any}`. """ -function flatten(d::AbstractDict{T,<:Any}, prefix_delim = ".") where T - new_d = Dict{T,Any}() +function flatten(d::AbstractDict{String,<:Any}, prefix_delim::String=".") + new_d = Dict{String,Any}() for (key, value) in pairs(d) if isa(value, Dict) flattened_value = flatten(value, prefix_delim) @@ -236,6 +236,32 @@ function flatten(d::AbstractDict{T,<:Any}, prefix_delim = ".") where T return new_d end +function unflatten(d::AbstractDict{String,<:Any}, prefix_delim::String=".") + uf_d = d + while true + prefixes = String[] + for k in keys(uf_d) + parts = split(k, prefix_delim) + if length(parts) > 1 + push!(prefixes, join(parts[1:end-1],prefix_delim)) + end + end + unique!(prefixes) + length(prefixes) == 0 && break + uf_d, tmp_d = Dict{String,Any}(), uf_d + for pre in prefixes + sub_dict = Dict{String,Any}() + for (k,v) in pairs(tmp_d) + if startswith(k, string(pre,prefix_delim)) + sub_dict[last(split(k,prefix_delim))] = v + end + end + uf_d[pre] = sub_dict + end + end + return uf_d +end + """ dirname_path(path) -- GitLab