Legend additionally shows marker for `Lines` and line for `Scatter` plot
Bug description
The legend shows markers (lines) even though the corresponding plots do not show any markers (lines).
Steps to reproduce
julia> using AlgebraOfGraphics
julia> df1 = (x = rand(100), y = rand(100), group = rand(["a", "b", "c", "d"], 100));
julia> df2 = (x = repeat(range(0, 1; length=25), 4), y = repeat(range(0, 1; length=10), 10), group = repeat(["a", "b", "c", "d"]; inner=25));
julia> spec1 = data(df1) * mapping(:x, :y, layout = :group, color = direct("Data 1")) * visual(Scatter);
julia> spec2 = data(df2) * mapping(:x, :y, layout = :group, color = direct("Data 2")) * visual(Lines);
julia> draw(spec1 + spec2)
Images
The figure contains a scatter plot ("Data 1") and a line plot ("Data 2"). However, the legend displays both plots as combined scatter + lines plots:
Version info
Please include the output of versioninfo() and Pkg.status() for the environment
where the issue occurred.
julia> versioninfo()
Julia Version 1.11.0
Commit 501a4f25c2b (2024-10-07 11:40 UTC)
Build Info:
Official https://julialang.org/ release
Platform Info:
OS: macOS (arm64-apple-darwin22.4.0)
CPU: 10 × Apple M2 Pro
WORD_SIZE: 64
LLVM: libLLVM-16.0.6 (ORCJIT, apple-m2)
Threads: 1 default, 0 interactive, 1 GC (on 6 virtual cores)
Environment:
JULIA_PKG_USE_CLI_GIT = true
JULIA_PKG_PRESERVE_TIERED_INSTALLED = true
julia> Pkg.status()
Status `/private/var/folders/n6/98_7bm0j0hb57zv3l3tj8sxh0000gn/T/jl_pEIopb/Project.toml`
[cbdf2221] AlgebraOfGraphics v0.8.13
⌃ [13f3f980] CairoMakie v0.12.14
Info Packages marked with ⌃ have new versions available and may be upgradable.
It's not checked if data for some group is nonempty before its legend marker is added. And because both of your plots share the same color scale, you get both entries for both. I'm not sure if legend markers should be conditional of some data in the respective group. It's conceivable to have a plot type that shows something even when it has no data..
Ah, so it's not relevant that spec1 and spec2 have completely distinct colors, both visuals are combined because potentially there could be a value that shows up in both of them?
I wonder, is there a better way to achieve what I actually wanted to do here and for which I used the direct: To add two labeled plots in two different colors based on the current color scheme with an automatically generated legend?
Initially, I had tried e.g.
julia> spec1 = data(df1) * mapping(:x, :y, layout = :group) * visual(Scatter; color = Cycled(1));
julia> spec2 = data(df2) * mapping(:x, :y, layout = :group) * visual(Lines; color = Cycled(2));
julia> draw(spec1 + spec2)
ERROR: Attribute `color` was passed with an explicit `Cycled` value, but color is not specified in the cycler for this plot type Scatter{Tuple{Vector{Point{2, Float64}}}}.
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:35
[2] add_cycle_attributes!(plot::Any, cycle::Cycle, cycler::Makie.Cycler, palette::Attributes)
@ Makie ~/.julia/packages/Makie/6c4lt/src/makielayout/blocks/axis.jl:725
[3] add_cycle_attribute!(plot::Scatter{Tuple{Vector{Point{2, Float64}}}}, scene::Scene, cycle::Cycle)
@ Makie ~/.julia/packages/Makie/6c4lt/src/interfaces.jl:5
[4] add_cycle_attribute!(plot::Scatter{Tuple{Vector{Point{2, Float64}}}}, scene::Scene)
@ Makie ~/.julia/packages/Makie/6c4lt/src/interfaces.jl:3
[5] color_and_colormap!(plot::Scatter{Tuple{Vector{Point{2, Float64}}}}, colors::Observable{Any})
@ Makie ~/.julia/packages/Makie/6c4lt/src/interfaces.jl:12
[6] color_and_colormap!(plot::Scatter{Tuple{Vector{Point{2, Float64}}}})
@ Makie ~/.julia/packages/Makie/6c4lt/src/interfaces.jl:10
[7] calculated_attributes!
@ ~/.julia/packages/Makie/6c4lt/src/interfaces.jl:64 [inlined]
[8] connect_plot!(parent::Scene, plot::Scatter{Tuple{Vector{Point{2, Float64}}}})
@ Makie ~/.julia/packages/Makie/6c4lt/src/interfaces.jl:388
[9] plot!
@ ~/.julia/packages/Makie/6c4lt/src/interfaces.jl:412 [inlined]
[10] plot!(ax::Axis, plot::Scatter{Tuple{Vector{Point{2, Float64}}}})
@ Makie ~/.julia/packages/Makie/6c4lt/src/figureplotting.jl:412
[11] plot!(ae::AxisEntries)
@ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/BPWA1/src/entries.jl:82
[12] foreach(f::typeof(plot!), itr::Matrix{AxisEntries})
@ Base ./abstractarray.jl:3187
[13] plot!(fig::Figure, d::Layers, scales::AlgebraOfGraphics.Scales; axis::Dictionaries.Dictionary{Symbol, Any})
@ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/BPWA1/src/draw.jl:21
[14] plot!
@ ~/.julia/packages/AlgebraOfGraphics/BPWA1/src/draw.jl:16 [inlined]
[15] (::AlgebraOfGraphics.var"#374#379"{Dictionaries.Dictionary{…}, Dictionaries.Dictionary{…}, Dictionaries.Dictionary{…}, Dictionaries.Dictionary{…}, Layers, AlgebraOfGraphics.Scales, AlgebraOfGraphics.FigureSettings})(f::Figure)
@ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/BPWA1/src/draw.jl:162
[16] update
@ ~/.julia/packages/AlgebraOfGraphics/BPWA1/src/draw.jl:10 [inlined]
[17] _draw(d::Layers, scales::AlgebraOfGraphics.Scales; axis::Dictionaries.Dictionary{…}, figure::Dictionaries.Dictionary{…}, facet::Dictionaries.Dictionary{…}, legend::Dictionaries.Dictionary{…}, colorbar::Dictionaries.Dictionary{…})
@ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/BPWA1/src/draw.jl:161
[18] _draw
@ ~/.julia/packages/AlgebraOfGraphics/BPWA1/src/draw.jl:154 [inlined]
[19] draw(d::Layers, scales::AlgebraOfGraphics.Scales; axis::@NamedTuple{}, figure::@NamedTuple{}, facet::@NamedTuple{}, legend::@NamedTuple{}, colorbar::@NamedTuple{}, palette::Nothing)
@ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/BPWA1/src/draw.jl:85
[20] draw
@ ~/.julia/packages/AlgebraOfGraphics/BPWA1/src/draw.jl:75 [inlined]
[21] draw(d::Layers)
@ AlgebraOfGraphics ~/.julia/packages/AlgebraOfGraphics/BPWA1/src/draw.jl:75
[22] top-level scope
@ REPL[29]:1
Some type information was truncated. Use `show(err)` to see complete types.
The cycler is actually specifically disabled in AoG so that you don't get unintended colors where you don't want any. I guess currently the easiest is to retrieve the palette manually and use label for the legend:
p = Makie.current_default_theme()[:palette][:color][]
pregrouped([1:2], [1:2]) * visual(Scatter, color = p[1], label = "A") +
pregrouped([3:4], [3:4]) * visual(Lines, color = p[2], label = "B") |> draw