Parse TOML to a nested struct - #689
Conversation
vers-w
left a comment
There was a problem hiding this comment.
Nice work @SouthEndMusic !
Besides a couple of comments/questions, the code coverage has decreased and is failing, also at the project level, would be good to bump this up. I think it would be good if @JoostBuitink also checks the config settings in config.jl.
| reservoir_area__count::String = "" | ||
| reservoir_location__count::String = "" |
There was a problem hiding this comment.
If reservoir__flag is true these are required, maybe worth adding?
There was a problem hiding this comment.
You mean as a comment here? I don't think Configurations.jl supports validation logic like 'if this condition for this field, then that condition for that field'. I think it's best if such conditional validation is done in the code where the field is parsed.
There was a problem hiding this comment.
OK, yeah, it seems indeed Configurations.j does not support this kind of validation. But it would be nice to add this validation to the code, if reservoir__flag is true, reservoir_area__count and reservoir_location__count should be set (not default empty string).
There was a problem hiding this comment.
OK, I'll set the default to nothing and then raise an error when the data is required.
There was a problem hiding this comment.
@vers-w can you point to the best place in the code to validate this? Probably the earliest relevant point in the initialization
There was a problem hiding this comment.
I think it would be best to validate this already when reading the config. Given that Configurations.jl does not support this, and appears to be not too actively maintained, I wonder if it is worth writing our own logic around this, or whether it is better to define our own config object.
It would also be nice to check if certain layers required specifically to the model type/settings (for example layers like soil moisture, glacier locations, reservoir parameters, floodplain volumes) are present. It is a bit tricky that those can be defined both in the [input.static] or [input.cyclic] settings.
Also, some fields like river_routing only support two options ("kinematic-wave" or "local-inertial"). If a user tries something else (or a typo), it would be best to throw an error when creating the config object (rather than within the computation code/initialization like it is now). I once tried to get this sorted using Configurations, but failed to do so.
There was a problem hiding this comment.
Yes, I would say as part of the function Config?
There was a problem hiding this comment.
This hints at a difference we have in 'config philosophy'. In Ribasim the config object is a static representation of the TOML which is only used in initialization (where any validation is done) and post-processing. I'm fine with doing this differently in Wflow, as long as the approach is consistent. I'll look into moving as much of the config validation to the Config constructor as possible.
There was a problem hiding this comment.
Not sure if I understand your comment completely, but generating the config object is the first step before initializing a model from that config. So, I think it makes sense to do the validation here, as @JoostBuitink also indicated.
| end | ||
|
|
||
| # Model configurations | ||
| @option struct ModelSection <: AbstractConfigSection |
There was a problem hiding this comment.
Maybe worth to have model sections per model type?
There was a problem hiding this comment.
That would be nice, but then we have to either:
- Also require this in the TOML, which is breaking
- Do some more processing of the TOML read before passing it to
Configurations.jl, which sort of defeats the purpose ofConfigurations.jl
| river = config.model.river_routing | ||
| @assert river ∈ ROUTING_OPTIONS # Already validated in `validate_config` | ||
|
|
||
| subsurface = config.model.type == "sbm" ? "kinematic-wave" : "groundwaterflow" |
There was a problem hiding this comment.
The nothing here used to be "groundwaterflow" but that is referenced nowhere else
There was a problem hiding this comment.
What nothing do you mean here?
| # Logging related configurations | ||
| @option struct LoggingSection <: AbstractConfigSection | ||
| silent::Bool = false | ||
| loglevel::String = "info" |
There was a problem hiding this comment.
Is the loglevel input allowed to be an integer?
There was a problem hiding this comment.
From checking the code in logging.jl (and the docs) this is allowed.
| var, | ||
| location_dim = nc_var["location"], | ||
| locations = [nc_var["location"]], | ||
| ), |
There was a problem hiding this comment.
I feel like there is some validation missing here, or is that done somewhere else? That could already be done in config.jl
There was a problem hiding this comment.
This is not vaildated somewhere else. What kind of validation were you thinking of?
| if haskey(var, "layer") | ||
| v = get(config.model, "soil_layer__thickness", [100, 300, 800])::Vector{Int64} | ||
| inds = collect(1:(length(v) + 1)) | ||
| inds = collect(1:(length(config.model.soil_layer__thickness) + 1)) |
There was a problem hiding this comment.
I don't understand this code. What is the difference between dim_value and index (apart from the potential out of bounds error)?
There was a problem hiding this comment.
Yeah, I agree, this function is not adding much. Probably a remainder of refactoring (another model concept did support also an extra_dim).
|
As discussed we want to drop the |
|
After discussing with @evetion I'm motivated to keep
My apologies for making the PR so big. I do believe that (most of) this is a good step in making the code easier to understand as a newcomer |
Configurations.jl
I have checked the formatting of the log messages with previously: Do we need to add these default For the scalar output the formatting can be improved a bit I think (is the field And it seems something goes wrong with the reducer |
|
In addition:
|
|
Just did a final check of the logging messages:
|
vers-w
left a comment
There was a problem hiding this comment.
LGTM! A couple of small comments about the logging #689 (comment).
|
@vers-w I resolved all the merge conflicts but there is still one test failing that I don't know how to fix. Can you have a look? |
Caused by fixing `snow_gravitational_transport__flag` TOML key.
@SouthEndMusic : I have resolved the tests and changed the log message for modifying NetCDF parameters (5bcfa41). I think it is fine to merge, @JoostBuitink: maybe you want to do a final check? |
A did a very quick check, but the error when trying to run a simulation without a I'll try to do a slightly more detailed review and testing later today. |
Also removed optional toml/config path (nothing).
Commit 2dbd6a5 should resolve this. I also did change the type of field |
JoostBuitink
left a comment
There was a problem hiding this comment.
Thanks for the quick fix @vers-w! I did a (quick) review and some testing, and all seems to work! So we are good to merge I think!
Yes, @SouthEndMusic : if you agree with the code changes in 2dbd6a5 (including changing |
Fixes #243
Fixes #688
The original idea was to use
Configuration.jlto parse the TOML, but after discussion with @JoostBuitink and @vers-w we decided not to do this. Instead the implementation is custom, usingAbstractConfigSectionand a parse functioninit_config_section.An overview of the changes made in this PR:
PropertyDictsis now used to access nested dictionaries as if they were nested structs (not sure if this is still actually required though)init_config_section, so the types do not have to be specified anymore in the code where the config field is usedEnumXis used to make enumerations of config options, see the top ofconfig_structure.jl. These enumerations are also used to validate these config optionsConfigobject back toTOMLwith the functionto_dict, which is a requirement for Write the parsed config to output #701Configobject mainly for developers, but this could be added to the log if desirable@with_kwmacro