AlgebraOfGraphics.jl icon indicating copy to clipboard operation
AlgebraOfGraphics.jl copied to clipboard

Legend additionally shows marker for `Lines` and line for `Scatter` plot

Open devmotion opened this issue 1 year ago • 3 comments

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:

Image

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.

devmotion avatar Nov 06 '24 13:11 devmotion

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..

jkrumbiegel avatar Nov 06 '24 14:11 jkrumbiegel

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.

devmotion avatar Nov 06 '24 15:11 devmotion

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

Image

jkrumbiegel avatar Nov 06 '24 17:11 jkrumbiegel