Skip to content

Plot methods

Makie offers a simple but powerful set of methods for each plotting function, which allow you to easily create and manipulate the most common aspects of a figure.

Each plot object like Scatter has two plotting functions associated to it, a non-mutating version (scatter) and a mutating version (scatter!). These functions have different methods that behave slightly differently depending on the first argument.

Here's a short list before we show each version in more detail. We use Scatter as our example, but the principles apply to every plot type.


The non-mutating methods create and return something in addition to the plot object, either a figure with an axis in default position, or an axis at a given GridPosition or GridSubposition.

scatter(args...; kwargs...) -> ::FigureAxisPlot
scatter(gridposition, args...; kwargs...) -> ::AxisPlot

FigureAxisPlot is just a collection of the new figure, axis and plot. For convenience it has the same display overload as Figure, so that scatter(args...) displays a plot without further work. It can be destructured at assignment like fig, ax, plotobj = scatter(args...).

AxisPlot is a collection of a new axis and plot. It has no special display overload but can also be destructured like ax, plotobj = scatter(gridposition, args...).

Special Keyword Arguments

Methods that create an AxisPlot accept a special-cased axis keyword, where you can pass a dict-like object containing keyword arguments that should be passed to the created axis. Methods that create a FigureAxisPlot additionally accept a special cased figure keyword, where you can pass a dict-like object containing keyword arguments that should be passed to the created figure.

All other keyword arguments are passed as attributes to the plotting function.

Here are two examples with the scatter function (take care to create single-argument NamedTuples correctly, for example with a trailing comma):

using CairoMakie
# FigureAxisPlot takes figure and axis keywords
fig, ax, p = lines(cumsum(randn(1000)),
    figure = (size = (1000, 600),),
    axis = (ylabel = "Temperature",),
    color = :red)

# AxisPlot takes axis keyword
lines(fig[2, 1], cumsum(randn(1000)),
    axis = (xlabel = "Time (sec)", ylabel = "Stock Value"),
    color = :blue)



The mutating methods always just return a plot object. If no figure is passed, the current_figure() is used, if no axis or scene is given, the current_axis() is used.

scatter!(args...; kwargs...) -> ::Scatter
scatter!(figure, args...; kwargs...) -> ::Scatter
scatter!(gridposition, args...; kwargs...) -> ::Scatter
scatter!(axis, args...; kwargs...) -> ::Scatter
scatter!(scene, args...; kwargs...) -> ::Scatter


In the background, each Figure has a GridLayout from GridLayoutBase.jl, which takes care of layouting plot elements nicely. For convenience, you can index into a figure multiple times to refer to nested grid positions, which makes it easy to quickly assemble complex layouts.

For example, fig[1, 2] creates a GridPosition referring to row 1 and column 2, while fig[1, 2][3, 1:2] creates a GridSubposition that refers to row 3 and columns 1 to 2 in a nested GridLayout which is located at row 1 and column 2. The link to the Figure is in the parent field of the top layout.

With Non-Mutating Plotting Functions

Using the non-mutating plotting functions with GridPositions creates new axes at the given locations. If a GridLayout along the nesting levels doesn't exist, yet, it is created automatically for convenience.

using CairoMakie
fig = Figure()

# first row, first column
scatter(fig[1, 1], 1.0..10, sin)

# first row, second column
lines(fig[1, 2], 1.0..10, sin)

# first row, third column, then nested first row, first column
lines(fig[1, 3][1, 1], cumsum(randn(1000)), color = :blue)

# first row, third column, then nested second row, first column
lines(fig[1, 3][2, 1], cumsum(randn(1000)), color = :red)

# second row, first to third column
ax, hm = heatmap(fig[2, 1:3], randn(30, 10))

# across all rows, new column after the last one
fig[:, end+1] = Colorbar(fig, hm)


With Mutating Plotting Functions

Mutating plotting functions work a bit differently with GridPositions. First, it is checked if one - and only one - axis exists already at the given position. If that's the case, that axis is plotted into. If it's not the case, the function will error.

using CairoMakie
fig = Figure()

lines(fig[1, 1], 1.0..10, sin, color = :blue)
# this works because the previous command created an axis at fig[1, 1]
lines!(fig[1, 1], 1.0..10, cos, color = :red)

# the following line wouldn't work yet because no axis exists at fig[1, 2]
# lines!(fig[1, 2], 1.0..10, sin, color = :green)

fig[1, 2] = Axis(fig)
# now it works
lines!(fig[1, 2], 1.0..10, sin, color = :green)

# also works with nested grids
fig[2, 1:2][1, 3] = Axis(fig)
lines!(fig[2, 1:2][1, 3], 1.0..10, cos, color = :orange)

# but often it's more convenient to save an axis to reuse it
ax, _ = lines(fig[2, 1:2][1, 1:2], 1.0..10, sin, color = :black)
lines!(ax, 1.0..10, cos, color = :yellow)