How to get empty markers, Plots, gr() backend

If I have something like this

plot(x, y, shape = :rect, m = (5, :black, stroke(1, :red))

the second option in m fills my marker with that color. But what I want is an empty marker, not white. Empty! Is this possible here?

1 Like

You can’t - it’s a weakness of the current gr backend to Plots. The other backends will do this if you set markeralpha = 0.

Too bad. I really like gr. However, if I change to pyplot, i.e.

using Plots
data = rand(10,2)
plot(data[:,1], data[:,2], m = (8, 0.0, :red, stroke(1, :blue)), 
    framestyle=:box, grid = false, size = (400,400))

where now the second option in m is the markeralpha = 0, it turns out that the label is not right. The label should be a circle (the stroke) and a line. Any ideas?

I am not actually sure about that are you looking for. I guess when you talk about label you want to say legend. In that case, in
there is an example, adding the shape in marker (with :circle). Maybe it could work for you.

Yes, I mean legend. The problem is that if you set in the example that you mention the

markeralpha =0

then the whole marker goes away in the legend. Ideally I will hope to see just the stroke and the corresponding line.

I realize this is an old topic, but I am running into the same issue. Is there a way to obtain the correct legend?

The best you can do with Plots, I think is the following. If more control is needed, then use matplotlib.

using Plots
data = rand(10,2)
color = :red
plot(data[:,1], data[:,2], m = (7, :white, stroke(1, color)),
    lw =1.0, c = color, linestyle =:dash, framestyle=:box, 
    grid = false,  size = (400,400))

That’s not true, Plots supports empty markers with markercolor = :transparent. But it is not supported by the GR backend.

Indeed, setting markercolor = :transparent gives the correct behavior for the legend and the plot with pyplot. i.e., m = (5, :transparent, stroke(1, color)) .

1 Like

any workaround for this?

GR still doesn’t support hollow markers. Sad… I like GR because, for 2D figures, I think GR is more elegant…

If one is not too choosy, pseudo-transparency is possible:

using Plots; gr()
M = rand(10,2)
scatter(M[:,1], M[:,2], mc=:white, msc=:darkred, msw=2, label="Am I transparent?")
plot!(M[:,1], M[:,2], ls=:dot, c=:red, framestyle=:box, grid = false)

But the marker will cover the lines (if there’s other data behind them)

Because I knew you would not be happy see code below, adapted from this great Plots.jl solution.

Plots.jl gr() code
using Plots; gr()

circle(x, y, r) = Plots.Shape(r*sind.(0:10:360) .+ x, r*cosd.(0:10:360) .+ y)

M = rand(12,2)
circles = circle.([M[:,1], M[:,2]]..., (0.02,))
p = plot(M[:,1], M[:,2], ls=:dot, c=:red, framestyle=:box, grid=false)
plot!(circles, ratio=1, fc=:transparent, lc=:darkred, lw=1, label=false)
scatter!([-1e16], [circles[1].y[1]], mc=:white, msc=:darkred, lw=1, label="I am transparent!",
         xlims=Plots.xlims(p), ylims=Plots.ylims(p))

Plots actually has an exported partialcircle function that can also draw full circles.

1 Like