What does the `primary` attribute do and how to plot curves with scatters added onto it in `Plots.jl`?

For example, we have the following recipe:

using RecipesBase: @userplot, @recipe, @series

@userplot MyPlot
@recipe function f(plot::MyPlot)
    x, y = plot.args
    palette --> :tab20
    @series begin
        seriestype --> :scatter
        primary := false
        x, y
    end
    seriestype --> :path
    label --> ""
    return x, y
end

and the following data:

x = 1:10
y = x.^2 .+ 1 .+ rand(10)

x1 = 2:2:20
y1 = x1.^1.5 .+ rand(10)

x2 = 3:3:30
y2 = x2 / 10 .+ 10

So we plot:

julia> myplot(x, y; label="xy")

julia> myplot!(x1, y1; label="x1y1")

julia> myplot!(x2, y2; label="x2y2")

and get the following figure:

As you can see, the color of the scatters and the lines are not matched in each set of data.
What we want is something like this:

@userplot MyPlot2
@recipe function f(plot::MyPlot2)
    x, y = plot.args
    palette --> :tab20
    @series begin
        seriestype --> :scatter
        label := ""
        x, y
    end
    seriestype --> :path
    label --> ""
    return x, y
end

julia> myplot2(x, y; label="xy")

julia> myplot2!(x1, y1; label="x1y1")

julia> myplot2!(x2, y2; label="x2y2")

Am I using :tab20 correctly? Is it supposed to be used this way? Why does not primary = false not work here?

Well, setting primary = false will cause a series to have the same color as the preceeding series.
Therefore it won’t give you what you are after, if you set that for the first series of the plot.
The following will work better:

@userplot MyPlot
@recipe function f(plot::MyPlot)
    x, y = plot.args
    palette --> :tab20
    @series begin
        seriestype --> :scatter
        x, y
    end
    primary := false
    seriestype --> :path
    label --> ""
    return x, y
end

However, if all you want is to have markers on your path, its enough to set markershape.

2 Likes