Sindbad.Visualization Module
VisualizationVisualization utilities for SINDBAD experiments. This module focuses on plotting model outputs, diagnostics, and experiment metadata via Plots.jl.
Purpose
Provide ready-to-use plotting helpers that understand SINDBAD's
info, outputs, and metric structures.Speed up exploratory analysis by wrapping common visual layouts (time series, site comparisons, diagnostic summaries).
Dependencies
Internal (within Sindbad)
namedTupleToFlareJSONandgetAllVariables(utilsVisualization.jl) have no external plotting dependency and are always available.
Optional (via SindbadPlotsExt)
plotPerformanceHistograms,plotTimeSeries,plotForcing,plotSpinup, andplotIOModelStructuredispatch on aVisualizationTypesbackend value read frominfo.helpers.run.visualization_backend(set fromexe_rules.visualization_backendin the experiment config, defaulting to"Types"). The defaultVisualizationTypesbackend logs an info message and returnsnothing. Settingvisualization_backend = "Plots"in the config selects theVisualizationPlotsbackend, whose real plotting methods are only added oncePlots.jlis loaded, at which point Julia's package extension mechanism loadsSindbadPlotsExt(see rootProject.toml[weakdeps]+[extensions]).using Sindbadalone is sufficient oncePlotsis also loaded in the session — end users typically should notusing SindbadPlotsExtdirectly.plotTimeSeriesWithObsandplotTimeSeriesDebugare deprecated-but-supported aliases ofplotTimeSeries, kept for backward compatibility with their original signatures.
Notes
Additional plot recipes are being added progressively; current focus is on covering the default experiment workflow.
The API is reexported via
Sindbad.Visualization, so users simply loadSindbadto access plotting helpers (oncePlotsis loaded for the plotting functions).
Usage:
using Sindbad, Plots
plotPerformanceHistograms(opt_results)
plotIOModelStructure(info)
plotCarbonFlows(cCycleBase_CASA) # writes tmp_carbon_flow_matrix_cCycleBase_CASA_default.pdfplotCarbonFlows draws a cCycleBase approach's carbon flow topology as a giver-by-taker matrix, labelled with each flow's turnover time, allocation fraction, microbial efficiency and quality-partition fraction. Called with just the approach, it needs no experiment or run and writes tmp_carbon_flow_matrix_<approach>_default.pdf (_actual.pdf with a real land given, tmp_-prefixed so it's gitignored); a second positional argument names the file, nothing skips the write. Called as plotCarbonFlows(info, approach), it resolves the backend from info.helpers.run.visualization_backend and saves into info.output.dirs.figure instead – the form getExperimentInfo calls automatically when a cCycleBase approach is selected.
Functions
namedTupleToFlareJSON
Sindbad.Visualization.namedTupleToFlareJSON Function
namedTupleToFlareJSON(info::NamedTuple)Convert a nested NamedTuple into a flare.json format suitable for d3.js visualization.
Arguments
info::NamedTuple: The input NamedTuple to convert
Returns
A dictionary in flare.json format with the following structure:
json{ "name": "root", "children": [ { "name": "field1", "children": [...] }, { "name": "field2", "value": 42 } ] }
Notes
The function recursively traverses the NamedTuple structure
Fields with no children are treated as leaf nodes with a value of 1
The structure is flattened to show the full path to each field
Examples
julia> using Sindbad
julia> # Convert experiment info to flare.json format
julia> # flare_json = namedTupleToFlareJSON(info)Code
function namedTupleToFlareJSON(info::NamedTuple)
function _convert_to_flare(nt::NamedTuple, name="sindbad_info")
children = []
for field in propertynames(nt)
value = getfield(nt, field)
if value isa NamedTuple
push!(children, _convert_to_flare(value, string(field)))
else
# println("field: $field, value: $value")
push!(children, Dict("name" => string(field), "value" => 1))
end
end
return Dict("name" => name, "children" => children)
end
return _convert_to_flare(info)
endplotCarbonFlows
Sindbad.Visualization.plotCarbonFlows Function
plotCarbonFlows(approach=nothing; kwargs...)
plotCarbonFlows(approach, file_path; kwargs...)
plotCarbonFlows(info::NamedTuple, approach=nothing; kwargs...)Draws the carbon flow topology of a cCycleBase approach as a giver by taker matrix, labelled with each flow's turnover time, allocation fraction, microbial efficiency and quality-partition fraction.
Arguments
approach: thecCycleBaseapproach, ornothingto take it from alandgiven inkwargsfile_path: where the figure is saved, ornothingto skip savinginfo: Information structure containing experiment details. The backend is read from it and the figure is saved ininfo.output.dirs.figure.
Notes
Without
infoorfile_path, the figure istmp_carbon_flow_matrix_<approach>_default.pdfin the working directory, or_actual.pdfwhen a reallandis given.Without a loaded plotting backend, it logs an info message and returns
nothing.
Code
function plotCarbonFlows(approach=nothing; kwargs...)
suffix = isnothing(get(kwargs, :land, nothing)) ? "default" : "actual"
file_path = "tmp_carbon_flow_matrix_$(_approachName(approach, kwargs))_$(suffix).pdf"
return plotCarbonFlows(approach, file_path; kwargs...)
end
function plotCarbonFlows(approach, file_path; kwargs...)
backend = VisualizationPlots()
return plotCarbonFlows(approach, file_path, _resolvedBackend(plotCarbonFlows, backend, approach, file_path); kwargs...)
end
function plotCarbonFlows(info::NamedTuple, approach=nothing; kwargs...)
backend = info.helpers.run.visualization_backend
suffix = isnothing(get(kwargs, :land, nothing)) ? "default" : "actual"
approach_name = _approachName(approach, kwargs)
file_path = joinpath(info.output.dirs.figure,
"carbon_flow_matrix_$(approach_name)_$(suffix).pdf")
# an explicit pool_configuration or helpers in kwargs (rare) wins over info's,
# since it comes later in this merge
kwargs = (; pool_configuration=_experimentPoolConfiguration(info), helpers=info.helpers, kwargs...)
return plotCarbonFlows(approach, file_path, _resolvedBackend(plotCarbonFlows, backend, approach, file_path); kwargs...)
end
function plotCarbonFlows(approach, file_path, ::VisualizationTypes; kwargs...)
print_info(plotCarbonFlows, @__FILE__, @__LINE__, _visualizationFallbackMessage(plotCarbonFlows, VisualizationPlots()), n_f=4)
return nothing
endplotForcing
Sindbad.Visualization.plotForcing Function
plotForcing(out)
plotForcing(info, forcing)Saves figures of every forcing variable in info.output.dirs.figure, as forcing_<variable>.png for one location.
Arguments
out: the output of an experiment run, which carries.infoand.forcinginfo: Information structure containing experiment detailsforcing: the forcing NamedTuple with thevariablesand theirdata
Notes
- The backend is read from
info.helpers.run.visualization_backend. Without a loaded plotting backend, it logs an info message and returnsnothing.
Code
function plotForcing(info, forcing)
backend = info.helpers.run.visualization_backend
return plotForcing(info, forcing, _resolvedBackend(plotForcing, backend, info, forcing))
end
function plotForcing(info, forcing, ::VisualizationTypes)
print_info(plotForcing, @__FILE__, @__LINE__, _visualizationFallbackMessage(plotForcing, info.helpers.run.visualization_backend), n_f=4)
return nothing
endplotIOModelStructure
Sindbad.Visualization.plotIOModelStructure Function
plotIOModelStructure(info, which_function=:compute, which_field=[:input, :output])Plots which variables each selected model reads and writes in one of its functions, and saves the figure as a PDF in the experiment's output directory.
Arguments
info: Information structure containing experiment detailswhich_function: the model function to analyze, e.g.:computeor:definewhich_field: aSymbolor a vector ofSymbols among:inputand:output
Notes
- The backend is read from
info.helpers.run.visualization_backend. Without a loaded plotting backend, it logs an info message and returnsnothing.
Code
function plotIOModelStructure(info, which_function, which_field)
backend = info.helpers.run.visualization_backend
return plotIOModelStructure(info, which_function, which_field, _resolvedBackend(plotIOModelStructure, backend, info, which_function, which_field))
end
function plotIOModelStructure(info, which_function, which_field, ::VisualizationTypes)
print_info(plotIOModelStructure, @__FILE__, @__LINE__, _visualizationFallbackMessage(plotIOModelStructure, info.helpers.run.visualization_backend), n_f=4)
return nothing
endplotPerformanceHistograms
Sindbad.Visualization.plotPerformanceHistograms Function
plotPerformanceHistograms(out_opti)Plots histograms of the performance metrics of the default and optimized runs of an optimization.
Arguments
out_opti: the output of an optimization run, which carries.info
Notes
- The backend is read from
info.helpers.run.visualization_backend. Without a loaded plotting backend, it logs an info message and returnsnothing.
Code
function plotPerformanceHistograms(out_opti)
backend = out_opti.info.helpers.run.visualization_backend
return plotPerformanceHistograms(out_opti, _resolvedBackend(plotPerformanceHistograms, backend, out_opti))
end
function plotPerformanceHistograms(out_opti, ::VisualizationTypes)
print_info(plotPerformanceHistograms, @__FILE__, @__LINE__, _visualizationFallbackMessage(plotPerformanceHistograms, out_opti.info.helpers.run.visualization_backend), n_f=4)
return nothing
endplotSpinup
Sindbad.Visualization.plotSpinup Function
plotSpinup(out; kwargs...)
plotSpinup(info, spinup; loc_index=1, output=nothing)Plots cEco and TWS at every stored step of the spinup of one location and saves one figure per pool, spinup_<pool>.png, in info.output.dirs.figure.
Arguments
out: the output of a forward or optimization run, which carries.info, the stored.spinupand the.outputof the forward run that followed itinfo: Information structure containing experiment detailsspinup: the stored spinup fromprepSpinupOutloc_index: the index of the location inspinup.sequencesoutput: the output of the forward run after the spinup, appended to the plot when given
Notes
The spinup is only stored with
store_spinupset to true.The backend is read from
info.helpers.run.visualization_backend. Without a loaded plotting backend, it logs an info message and returnsnothing.
Code
function plotSpinup(info, spinup; kwargs...)
backend = info.helpers.run.visualization_backend
return plotSpinup(info, spinup, _resolvedBackend(plotSpinup, backend, info, spinup); kwargs...)
end
function plotSpinup(info, spinup, ::VisualizationTypes; kwargs...)
print_info(plotSpinup, @__FILE__, @__LINE__, _visualizationFallbackMessage(plotSpinup, info.helpers.run.visualization_backend), n_f=4)
return nothing
endplotTimeSeries
Sindbad.Visualization.plotTimeSeries Function
plotTimeSeries(out_opti)
plotTimeSeries(out, cost_options)
plotTimeSeries(info, opt_dat, def_dat; forcing_helpers=nothing)Plots the time series of the model output, with the observations where there are any, and saves one figure per variable in info.output.dirs.figure.
Arguments
out_opti: the output of an optimization run, which carries.infoout: the output of a run, which carries.infoand.observationcost_options: the cost options that pair model variables with observationsinfo: Information structure containing experiment detailsopt_dat,def_dat: the optimized and default model outputforcing_helpers: gives the spatial dimensions, which a spatial run needs
Notes
- The backend is read from
info.helpers.run.visualization_backend. Without a loaded plotting backend, it logs an info message and returnsnothing.
Code
function plotTimeSeries(out_opti)
backend = out_opti.info.helpers.run.visualization_backend
return plotTimeSeries(out_opti, _resolvedBackend(plotTimeSeries, backend, out_opti))
end
function plotTimeSeries(out, cost_options)
backend = out.info.helpers.run.visualization_backend
return plotTimeSeries(out, cost_options, _resolvedBackend(plotTimeSeries, backend, out, cost_options))
end
function plotTimeSeries(info, opt_dat, def_dat; forcing_helpers=nothing)
backend = info.helpers.run.visualization_backend
return plotTimeSeries(info, opt_dat, def_dat, _resolvedBackend(plotTimeSeries, backend, info, opt_dat, def_dat); forcing_helpers=forcing_helpers)
end
function plotTimeSeriesWithObs(out, obs_array, cost_options)
backend = out.info.helpers.run.visualization_backend
return plotTimeSeries(out.info, obs_array, cost_options, out.output, _resolvedBackend(plotTimeSeries, backend, out.info, obs_array, cost_options, out.output))
end
function plotTimeSeries(out_opti, ::VisualizationTypes)
print_info(plotTimeSeries, @__FILE__, @__LINE__, _visualizationFallbackMessage(plotTimeSeries, out_opti.info.helpers.run.visualization_backend), n_f=4)
return nothing
end
function plotTimeSeries(out, cost_options, ::VisualizationTypes)
print_info(plotTimeSeries, @__FILE__, @__LINE__, _visualizationFallbackMessage(plotTimeSeries, out.info.helpers.run.visualization_backend), n_f=4)
return nothing
end
function plotTimeSeries(info, opt_dat, def_dat, ::VisualizationTypes; kwargs...)
print_info(plotTimeSeries, @__FILE__, @__LINE__, _visualizationFallbackMessage(plotTimeSeries, info.helpers.run.visualization_backend), n_f=4)
return nothing
end
function plotTimeSeries(info, obs_array, cost_options, def_dat, ::VisualizationTypes; kwargs...)
print_info(plotTimeSeries, @__FILE__, @__LINE__, _visualizationFallbackMessage(plotTimeSeries, info.helpers.run.visualization_backend), n_f=4)
return nothing
endplotTimeSeriesDebug
Sindbad.Visualization.plotTimeSeriesDebug Function
plotTimeSeriesDebug(info, opt_dat, def_dat; kwargs...)Deprecated alias of plotTimeSeries, kept with its original signature.
plotTimeSeriesWithObs
Sindbad.Visualization.plotTimeSeriesWithObs Function
plotTimeSeriesWithObs(out_opti)
plotTimeSeriesWithObs(out, obs_array, cost_options)Deprecated alias of plotTimeSeries, kept with its original signatures.
Code
function plotTimeSeriesWithObs(out, obs_array, cost_options)
backend = out.info.helpers.run.visualization_backend
return plotTimeSeries(out.info, obs_array, cost_options, out.output, _resolvedBackend(plotTimeSeries, backend, out.info, obs_array, cost_options, out.output))
end