Plotting

This one's complicated. Yikes.

Essentially, build your plots with makeplots and save them to interactive html with savehtmlplot.

For makeplots, you pass the dataframe (typically gss.df or similar), a bunch of Strings or Symbols specifying columns to map to various variables, and whatever other random settings you need.

The docstring is horrendously complicated and so is the signature, but remember: if you don't need the functionality, just don't include it, and it'll (maybe (probably (surely))) be fine.

PowerSystemsExperiments.savehtmlplotFunction
savehtmlplot(plot, filename::String=nothing)

utility to save plot to filename.html. Default filename is the plot's image download filename, if it exists, or worst case just "plot.html"

source
PowerSystemsExperiments.makeplotsFunction
makeplots(
    df::DataFrame;

    rows::Union{AbstractString, Symbol, Nothing}=nothing,
    cols::Union{AbstractString, Symbol, Nothing}=nothing,
    legendgroup::Union{AbstractString, Symbol, Nothing}=nothing,
    markershape::Union{AbstractString, Symbol, Nothing}=nothing,
    trace_names::Union{AbstractString, Symbol, Nothing}=nothing,
    color::Union{AbstractString, Symbol, Nothing}=nothing,
    opacity::Union{AbstractString, Symbol, Real}=1.0,
    markersize::Union{AbstractString, Symbol, Real}=8,
    hovertext::Union{AbstractString, Symbol, Nothing}=nothing,
    scattermode::Union{AbstractString, Symbol}="markers",
    scattertext::Union{AbstractString, Symbol, Nothing}=nothing,
    
    colorbar::Bool=false,
    map_to_colorbar::Bool=true,
    marker_line_width::Union{Real, Nothing} = nothing,

    slider_trace_id::Union{AbstractString, Symbol, Nothing}=nothing,

    row_sort_func::Function = identity,
    col_sort_func::Function = identity,
    color_sort_func::Function = identity,
    slider_sort_func::Function = identity,


    slider::Union{AbstractString, Symbol, Nothing}=nothing,
    slider_label_func::Function = x->round(x, sigdigits=2),
    slider_current_value_prefix::Union{AbstractString, Nothing} = nothing,
    x::Union{AbstractString, Symbol, NamedTuple{(:x0, :dx), <:Tuple{Real, Real}}, Vector{<:Real}}=nothing,
    y::Union{AbstractString, Symbol, NamedTuple{(:y0, :dy), <:Tuple{Real, Real}}, Vector{<:Real}}=nothing,
    x_title::Union{AbstractString, Nothing} = nothing,
    y_title::Union{AbstractString, Nothing} = nothing,

    col_title_func::Function=identity,
    row_title_func::Function=identity,
    legendgroup_title_func::Function=identity,
    supertitle::Union{AbstractString, Nothing} = nothing,

    yaxis_home_range::Union{NamedTuple{(:min, :max), <:Tuple{Real, Real}}, Nothing} = nothing,
    xaxis_home_range::Union{NamedTuple{(:min, :max), <:Tuple{Real, Real}}, Nothing} = nothing,

    image_export_filename::String = "saved_plot",
    image_export_size::@NamedTuple{height::Int64, width::Int64}=(height=1200, width=1200),
    colorlist::Union{Vector{String}, Vector{<:Colors.Colorant}} = Colors.distinguishable_colors(10),
    symbollist::Vector{<:AbstractString} = ["circle", "square", "diamond", "cross", "triangle-up", "star", "circle-cross", "y-up", "circle-open", "square-open", "diamond-open", "cross-open", "triangle-up-open", "star-open"],
    colorbar_args::Dict = Dict(attr(autocolorscale=true, colorbar=attr(outlinecolor=colorant"black", outlinewidth=1))),
    use_webgl::Bool = false,
    hide_legend_duplicates::Bool = true,
    legend_location::@NamedTuple{x::Float64, y::Float64} = (x=0.9, y=0.9),
    legend_visible::Bool=true,
    shared_xaxes::Union{String, Bool}="all",
    shared_yaxes::Union{String, Bool}="all",
    fontsize::Real=18,
    offsets::NamedTuple{(:xtitle, :ytitle, :coltitle, :rowtitle), <:Tuple{Real, Real, Real, Real}} = (xtitle = -0.03, ytitle=-0.05, coltitle=0.01, rowtitle=0.01),
    subplotgaps::NamedTuple{(:horizontal_spacing, :vertical_spacing), <:Tuple{Real, Real}}=(horizontal_spacing=0.1, vertical_spacing=0.06),
)

Plot data from a dataframe. allows high dimensional data through a grid of subplots, trace colors, and a slider.

  • 2 variables for (x, y) on plot
  • 2 variables for row and column in subplot grid
  • 1 variable for color
  • 1 variable for marker symbol
  • 1 variable on a slider
  • 1 variable on hovertext
  • 1 variable on marker text
  • 1 variable on opacity
  • 1 variable on trace name
  • 1 variable for trace or datapoint size/thickness
  • 0 variables for legend group (typically can't work independently; pair with color or marker symbol)

= 12 max variables

In reality, you should use less. For example, it's impossible to read the opacity correctly, so you should make hovertext and opacity the same. Also, if you don't need that many variables, you can just leave them out. If you don't specify what to separate along subplot rows and columns, makeplots will just give you a single subplot.

Notes

  • colorbar doesn't work very well with line plots. If you want to vary color by trace, that's ok, just set the colorlist to make the legend effectively a discrete colorbar.
  • for slider:
    • make sure that each slider value has the exact same number of traces
    • either provide the slider_trace_id or sort the dataframe such that subsetting to each slider value gives the remaining traces in the same order every time

Arguments

Mandatory Arguments

  • df: the DataFrame to get data from.

DATA TO PLOT

x and y can be:

  • AbstractString, Symbol: get from column of df
  • NamedTuple of (x0, dx) or (y0, dy): evenly spaced values with given parameters
  • Vector{<:Real}: this specific array every time

Use the data_sigdigits (default: 6) argument to specify how much to round this input data. This significantly helps reduce the size of the exported HTML files.

If you choose to get the series from the dataframe, each element of the column will be one series/trace, so it better be a vector! If you have scalar or categorical values, try the default PlotlyJS.plot(df, ...) - it's pretty good for that.

Specifying which columns to use for what

  • rows: the column of the dataframe specifying which row of subplots this data should be on
  • cols: the column of the dataframe specifying which column of subplots this data should be on
  • legendgroup: the column of the dataframe specifying which legendgroup this trace should be. Value of this column is the legendgroup name.
  • color: the column of the dataframe specifying the color of this trace (or the color of each datapoint in this trace). Mapped to colorlist after being sorted by color_sort_func if colorbar==false, otherwise used raw for colorbar.
  • opacity (default: 1.0): the opacity of all datapoints OR the column of the dataframe specifying the opacity of each datapoint
  • markershape: the column of the dataframe to map to marker shape. Uses shapes provided in symbollist.
  • markersize (default: 8): the size of all markers OR the column of the dataframe specifying the size of each trace or datapoint.
  • trace_names: the column of the dataframe specifying the text name of this trace. Visible in legend and on hover. If hide_legend_duplicates==true, duplicates of trace_names will not be seen in each legend group.
  • hovertext: the column of the dataframe specifying any additional text that appears for this trace on hover
  • slider: the column of the dataframe specifying which slider value this trace corresponds to. See Slider Config
  • scattertext: the column of the dataframe specifying the text to appear next to datapoints. Only has effect if scattermode contains the text flag.

Titles

  • x_title: x axis title for every plot.
  • y_title: y axis title for every plot.
  • col_title_func: function to get column title from value in column of df passed in cols. Default: identity
  • row_title_func: function to get row title from value in column of df passed in row. Default: identity
  • legendgroup_title_func: function to get the legendgroup title text from the legendgroup name. Default: identity
  • supertitle: Biggest title on the graph.

Legend & Axes

  • colorbar (default: false): whether to display the colorbar. Can be finnicky, only really works for non-line plots.
  • colorbar_args: Dictionary of parameters for the colorbar. See Julia PlotlyJS docs for Layout.coloraxis.
  • shared_xaxes, shared_yaxes: how to share axes. see Subplots.
  • hide_legend_duplicates (default: true): hide duplicate trace names for each legend group.
  • legend_visible (default: true): show the legend

Markers & Colors

  • scattermode (default: "markers"): mode for scatterplot. Some combination of "markers", "lines", and "text", joined with "+". ie, "markers+text".
  • colorlist (default: 10 ok colors): list of colors to use. If you have more than 10 different values you want represented by color, or you want a specific set of colors, set this array.
  • color_sort_func (default: identity): function by which to sort values of color before associating with colorlist (if no colorbar)
  • symbollist (default: 14 different symbols): list of symbols to use for the different values of markershape. If you have more than 14 different values, set this array.
  • use_webgl (default: true): Whether to use scattergl or plain scatter.
  • map_to_colorbar (default: true): whether to associate markers with colorbar and show the scale. Generally keep this set to true. You may have to set it to false when you have "lines" in your scattermode. The PlotlyJS documentation is not entirely clear on the effect of these options.

Sizes

  • fontsize (default 18): font size for most/main text
  • margin (default: 200): Int, just the margin size (px)
  • offsets (default: (xtitle = -0.03, ytitle=-0.05, coltitle=0.01, rowtitle=0.01)): where to put the titles, as a fraction of the plot
  • yaxis_home_range and xaxis_home_range can be NamedTuple{(:min, :max), <:Tuple{Real, Real}}
  • legend_location (default: (x=0.9, y=0.9)): NamedTuple with Float64 x and y defining the legend location relative to the paper.
  • image_export_size (default: (height=1200, width=1200)): NamedTuple with Integers height and width specifying the size in pixels of the SVG plots saved with the "download plot" button.
    • image_export_filename (default: "saved_plot"): default filename when image is exported using button on plot.

Slider Config

  • slider_sort_func (default: identity): a function to get keys for the sort of the slider labels. For example, (x -> -x) would reverse the slider.
  • slider_trace_id: the column in the dataframe corresponding to a trace identifier. There must be exactly one row for each unique combination of this column and the slider column. If not passed, will use the order of the dataframe.
  • slider_label_func (default: x->round(x, sigdigits=2)): gets slider tick label from value.
  • slider_current_value_prefix: prefix to put before the value on the slider's label. For example, "val: " would make the label "val: 0.5" or something
source

Things to be aware of

Also known as Questionable Things I'm Not Willing To Fix Right Now

  • if colorbar==false, color is assumed to be categorical and each unique color is mapped to an element of colorlist after being sorted by color_sort_func
  • colorbar doesn't really work with lines because you can't have lines of variable color. To get it to work, you need to pass colorlist and ensure that it matches the right values on the colorscale you give in colorbar_args
  • colorbar_args are kinda complicated. Here's an example:
Dict(attr(
    autocolorscale=false, 
    cmax= 1.0,
    # cmid=0.5,
    cmin= -1.2,
    title="",
    colorbar=attr(
        outlinecolor=colorant"black",
        outlinewidth=1,
        tickmode="array",
        ticktext=(["Z=1.0", "P=1.0", "P=0.8", "P=0.6", "P=0.4", "P=0.2", "P=E=0", "E=0.2", "E=0.4", "E=0.6", "E=0.8", "E=1.0"]),
        tickvals=(collect(range(-1.2, 1, 13)).+(2.2/(2*12)))[1:end - 1],
        xref="paper",
        yref="paper",
        x=1.02,
        thickness=40
    ),
    colorscale=[[0.0, RGB(colorant"yellow")], 
                [1.0, RGB(colorant"purple")]]
))

Note that colorscale's numerical scale is in $[0, 1]$, which is different from cmax and cmin.

  • You can have a legend and a colorbar at the same time, but it is recommended to just use hide_legend_duplicates=true (which is default true) and use the legend to represent a different variable. Since color cannot be used, you'll have to pair it with another method of conveying information, like opacity or marker shape.
  • symbollist and colorlist provide some initial values, but if you have more unique values represented by symbol or color respectively, you'll need to provide new lists with more new values.
  • scattertext and hovertext can make plot files MASSIVE. Take care to include as little information as possible in them. Round numbers to the appropriate length.
  • similarly, high values of data_sigdigits can increase plot file size. Do not set it to a high number unless you absolutely need to.
  • slider_trace_id is funny. You don't actually have to make some fancy id - often using the default, the order of the rows in the dataframe, is best. Just make sure to sort the dataframe beforehand by as many things as possible so that you have a very predictable and consistent order of traces across slider values.