Visualizations#

Diagrams#

Stock and flow diagrams are a useful way to visually check that component references are set up as expected, with corresponding lines between flow, variables, and stock based on what other equations they’re used in. The basic method for generating a stock and flow diagram is the model.graph() function, which as shown on the getting started page might look something like this:

../_images/tub_sf_diagram.png

Highly complex models with lots of variables can render a simplified diagram by either excluding variables entirely with exclude_vars=True, or hiding a specific set of variables with names listed in exclude_var_names=["my_var1", ..."].

Highly linear models that don’t have many branches or cycles can be oriented left-to-right instead of top-down by passing lr=True.

Sparklines#

Mini “sparkline” plots can be added to the sides of various component types within the stock and flow diagrams to quickly get an overview of component values in the context of where they sit in the overall system. The three parameters to control this are sparklines, sparkdensities, and sparkall.

Running with sparklines=True will add a sparkline plot to every stock in the system.

../_images/tub_w_sparklines.png

sparkall=True will further add plots for every flow:

../_images/tub_sparkall.png

Finally, sparkdensities=True will add histograms/density plots for all variables (mostly only useful when variables have probability distributions associated with them either directly or upstream.)

../_images/tub_all_sparks.png

By default, the sparkline plots will be based on the last simulation run that completed. To use specific runs or render multiple runs at the same time, pass the traces to the traces array parameter

Groups/Color groups#

Every tracked reference optionally has both a group and cgroup attribute, which influences how they appear in the diagrams. The group attribute is used to encourage graphviz to visually tighten up/keep elements within the same group closer to each other. This is primarily done by straightening and shortening any connections between elements of a group where possible.

In this example, suppose a variable applies to two different flows:

import reno as r

m = r.Model()
with m:
    s1 = r.Stock()
    v1 = r.Variable()
    f1, f2 = r.Flow(v1), r.Flow(v1)
    f1 >> s1 >> f2

The stock/flow diagram looks like this:

../_images/non_grouped_diagram.png

If we assign the same group name to the variable and the second flow, it straightens out the connection between v1 and f2:

import reno as r

m = r.Model()
with m:
    s1 = r.Stock()
    v1 = r.Variable(group="test")
    f1, f2 = r.Flow(v1), r.Flow(v1, group="test")
    f1 >> s1 >> f2
../_images/grouped_diagram.png

cgroup is a “color group” attribute intended to make it easier to change colors of specific sets of references in the diagram without influencing layout.

Either groups or color groups can be colored from a model.graph() call with the group_colors attribute:

m.graph(group_colors={"test":"#4499AA"})
../_images/colored_diagram.png

Settings can be defined on models to hide specific groups or set default colors for designated groups, making them potentially easier to interpret when given to someone else.

These settings can also be specified manually on a model.graph() call with the hide_groups, show_groups (to override a model’s default_hide_groups setting), and group_colors.

Get a list of the groups/cgroups on a model with the groups property.

Universe#

To limit diagram rendering to only a specific set of components (beyond just hiding certain variables), directly pass a list of tracked references to include in the diagram to the universe parameter. This is useful if a very large system has multiple “areas” and you want to individually render each area separately.

Latex#

As shown on the getting started page, an interactive latex output listing all component equations can be generated with the model.latex() function:

../_images/tub_latex_example.png

The latex view can also be useful for debugging systems by passing a t parameter - this will include the values of every reference at the specified timestep:

tub.latex(t=5)
../_images/tub_latex_t_example.png

This can be taken one step further by including debug_ops=True, which will additionally use under braces to show the evaluated output at every single operation:

tub.latex(t=5, debug_ops=True)
../_images/tub_latex_t_debug_ops_example.png

Note that you can selectively render only a specific set of reference equations by passing a list of strings and/or component references with the ref_list parameter:

tub.latex(t=5, ref_list=["faucet", tub.drain])
../_images/tub_latex_ref_list_example.png

Plots#

Multi-trace plots#

The reno.viz.plot_trace_refs() function allows comparing specified components across multiple different simulation runs.

trace1 = predator_prey(
    rabbit_growth_rate=0.07,
    rabbit_death_rate=0.0001,
    fox_death_rate=0.01,
    fox_growth_rate=1e-05,
    rabbits_0=200.0,
    foxes_0=700.0,
    steps=2000
)
trace2 = predator_prey(
    rabbit_growth_rate=0.071,
    rabbit_death_rate=0.0001,
    fox_death_rate=0.012,
    fox_growth_rate=1e-05,
    rabbits_0=200.0,
    foxes_0=700.0,
    steps=2000
)
reno.plot_trace_refs(
    predator_prey,
    {"run1": trace1, "run2": trace2},
    ref_list=["foxes", predator_prey.rabbits]
)
../_images/foxes_rabbits_separate.png

Single axis plots#

A common figure type used for system dynamics models compares multiple components on the same plot axes. The logic for labelling the axes is a bit tricky, so reno.viz.plot_refs_single_axis() handles it for you:

(Note this can only handle rendering from one trace/simulation run at a time.)

reno.plot_refs_single_axis(trace1, [predator_prey.foxes, predator_prey.rabbits])
../_images/foxes_rabbits_single_axis.png