Skip to content
Sindbad.Visualization Module
julia
Visualization

Visualization 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)

  • namedTupleToFlareJSON and getAllVariables (utilsVisualization.jl) have no external plotting dependency and are always available.

Optional (via SindbadPlotsExt)

  • plotPerformanceHistograms, plotTimeSeries, plotForcing, plotSpinup, and plotIOModelStructure dispatch on a VisualizationTypes backend value read from info.helpers.run.visualization_backend (set from exe_rules.visualization_backend in the experiment config, defaulting to "Types"). The default VisualizationTypes backend logs an info message and returns nothing. Setting visualization_backend = "Plots" in the config selects the VisualizationPlots backend, whose real plotting methods are only added once Plots.jl is loaded, at which point Julia's package extension mechanism loads SindbadPlotsExt (see root Project.toml [weakdeps] + [extensions]). using Sindbad alone is sufficient once Plots is also loaded in the session — end users typically should not using SindbadPlotsExt directly.

  • plotTimeSeriesWithObs and plotTimeSeriesDebug are deprecated-but-supported aliases of plotTimeSeries, 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 load Sindbad to access plotting helpers (once Plots is loaded for the plotting functions).

Usage:

julia
using Sindbad, Plots

plotPerformanceHistograms(opt_results)
plotIOModelStructure(info)
plotCarbonFlows(cCycleBase_CASA)  # writes tmp_carbon_flow_matrix_cCycleBase_CASA_default.pdf

plotCarbonFlows 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.

source

Functions ​

namedTupleToFlareJSON ​

Sindbad.Visualization.namedTupleToFlareJSON Function
julia
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
julia> using Sindbad

julia> # Convert experiment info to flare.json format
julia> # flare_json = namedTupleToFlareJSON(info)
source
Code
julia
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)
end

plotCarbonFlows ​

Sindbad.Visualization.plotCarbonFlows Function
julia
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: the cCycleBase approach, or nothing to take it from a land given in kwargs

  • file_path: where the figure is saved, or nothing to skip saving

  • info: Information structure containing experiment details. The backend is read from it and the figure is saved in info.output.dirs.figure.

Notes

  • Without info or file_path, the figure is tmp_carbon_flow_matrix_<approach>_default.pdf in the working directory, or _actual.pdf when a real land is given.

  • Without a loaded plotting backend, it logs an info message and returns nothing.

source
Code
julia
    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
    end

plotForcing ​

Sindbad.Visualization.plotForcing Function
julia
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 .info and .forcing

  • info: Information structure containing experiment details

  • forcing: the forcing NamedTuple with the variables and their data

Notes

  • The backend is read from info.helpers.run.visualization_backend. Without a loaded plotting backend, it logs an info message and returns nothing.
source
Code
julia
    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
    end

plotIOModelStructure ​

Sindbad.Visualization.plotIOModelStructure Function
julia
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 details

  • which_function: the model function to analyze, e.g. :compute or :define

  • which_field: a Symbol or a vector of Symbols among :input and :output

Notes

  • The backend is read from info.helpers.run.visualization_backend. Without a loaded plotting backend, it logs an info message and returns nothing.
source
Code
julia
    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
    end

plotPerformanceHistograms ​

Sindbad.Visualization.plotPerformanceHistograms Function
julia
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 returns nothing.
source
Code
julia
    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
    end

plotSpinup ​

Sindbad.Visualization.plotSpinup Function
julia
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 .spinup and the .output of the forward run that followed it

  • info: Information structure containing experiment details

  • spinup: the stored spinup from prepSpinupOut

  • loc_index: the index of the location in spinup.sequences

  • output: the output of the forward run after the spinup, appended to the plot when given

Notes

  • The spinup is only stored with store_spinup set to true.

  • The backend is read from info.helpers.run.visualization_backend. Without a loaded plotting backend, it logs an info message and returns nothing.

source
Code
julia
    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
    end

plotTimeSeries ​

Sindbad.Visualization.plotTimeSeries Function
julia
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 .info

  • out: the output of a run, which carries .info and .observation

  • cost_options: the cost options that pair model variables with observations

  • info: Information structure containing experiment details

  • opt_dat, def_dat: the optimized and default model output

  • forcing_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 returns nothing.
source
Code
julia
    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
    end

plotTimeSeriesDebug ​

Sindbad.Visualization.plotTimeSeriesDebug Function
julia
plotTimeSeriesDebug(info, opt_dat, def_dat; kwargs...)

Deprecated alias of plotTimeSeries, kept with its original signature.

source

plotTimeSeriesWithObs ​

Sindbad.Visualization.plotTimeSeriesWithObs Function
julia
plotTimeSeriesWithObs(out_opti)
plotTimeSeriesWithObs(out, obs_array, cost_options)

Deprecated alias of plotTimeSeries, kept with its original signatures.

source
Code
julia
    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