# Plotting¶

## Plots.jl¶

Visually, PlotlyJS produces the most appealing plots (for me). But it does not install on my system (1.5).

When a plotting related library is not found (as in “error compiling display”), try ]build Plots.

Defaults are set with the defaults command.

### Axis labels¶

bar tends to have too small default margins for axis labels to show (at least in subplots). Try

using Plots.PlotMeasures

### Colors¶

Saturation is given by a number between 0 and 1 as in color = (:blue, 0.2).

### Legends¶

The label is set when each series is plotted. If labels are set when the plot is created (before the series are plotted), the entries are ignored.

### Bar graphs¶

Switch off lines around bars with linealpha = 0.

### Default arguments¶

Make a Dict with default arguments for each plot type, such as:

bar_defaults() = Dict([:leg => :bottom, :linecolor => :black]);


Make a function for each plot type, such as:

function bar_graph(groupLabelV, dataV; kwargs...)
args = merge(bar_defaults(), kwargs);
p = bar(groupLabelV, dataV;  args...);
return p
end


Now any default arguments can be overridden and bar_graph is called exactly as bar would be.

## Makie.jl¶

### Subplots¶

It helps to write plotting functions that take a Figure as an input:

# Make a stand-alone figure. Could be omitted.
function myplot(x, y; kwargs...)
fig = Figure();
myplot!(f, x, y; kwargs...)
return fig
end

# Plot into existing Figure.
function myplot!(fig :: Figure, x, y; pos = (1,1), kwargs...)
ax = fig[pos...] = Axis(fig; xlabel = "x");
myplot!(ax, x, y; kwargs...);
return ax
end

# Plot into existing Axis
function myplot!(ax :: Axis, x, y; kwargs...)
lines!(ax, x, y; kwargs...);
end

# Now we can make a stand-alone figure with
fig = Figure();
myplot!(fig, x, y);
# Or we can make a subplot with
fig = Figure();
myplot!(fig, x, y; pos = (2,1));


Limitations: The kwargs cannot be used to create the axis.

### Looping over axes¶

One way of creating a figure with subplots is:

fig = Figure();
nr = 2; nc = 3;
for ir = 1:nr, ic = 1:nc
ax = fig[ir, ic] = Axis(fig);
end


This fixes the layout. Now we can iterate over the subplots with

ind2sub(j, sz) = Tuple(CartesianIndices(sz)[j]);
for j = 1 : (nr * nc)
fig[ind2sub(j, (nr,nc))...]
end


The roundabout way is necessary because Figure does not support linear or cartesian indexing.

### Grouped bar graphs¶

Building up a grouped bar graph by plotting each series one at a time does not work. The first series bar is too wide (it covers the width of the entire group of bars). One could set it by hand, but it is not clear how.

axislegend does not work for grouped bar graphs (lacking labels).

### Keyword arguments¶

Makie ignores invalid keyword arguments. This makes it possible to "flatten" keyword arguments; i.e., one can provide that Axis arguments in the same list as the series arguments. For example, this works:

lines(x, y; xlabel = "x");


But

lines!(ax, x, y; xlabel = "x");


ignores the xlabel.

nothing works with keyword arguments such as title.

ylims appears to be ignored. Need to use ylims!(ax, lims). Unspecified bounds are set to nothing (not Inf).

### Themes¶

update_theme!(thm, Lines = (linewidth = 4,)) creates a new "section" thm.Lines that applies to lines.

update_theme!(thm, Lines = (linestyle = :dash,)) merges the new information into the existing Lines section. It does not replace previous content.

Text sizes are determined by separate attributes for all elements; e.g., xticklabelsize.

Setting line colors from the theme's colormap:

thm = theme_dark();
update_theme!(thm; colormap = ColorSchemes.leonardo);
function make_figure()
fig = Figure();
ax = fig[1,1] = Axis(fig);
for j = 1 : 4;
lines!(ax, 1:10, (1:10) .^ (1/j); color = fill(j, 10), colorrange = (1,4));
end
return fig
end
fig = with_theme(make_figure, thm);


Errors in theme settings cause merge! errors when plotting that bear no obvious relationship to themes.

## Saving data with plots¶

VegaLite does this natively.

with Plots.jl one can use hdf5plot_write to write an entire plot, including the data, to an hdf5 file.

This means that each plot has to be generated twice; once with whatever backend is used to generate PDF files; and then again with hdf5. In particular, one cannot first plot with another backend and then save the resulting plot object to hdf5.

The approach is then to first save the plot to hdf5, then load it and save it with another backend.

Note: In my current (v.1.3) installation, hdf5plot_write generates a bunch or warnings followed by a crash due to world age problems.