From 60cb12ce3b42f901c92b8addc62de18b4b691a72 Mon Sep 17 00:00:00 2001 From: Simeon David Schaub Date: Tue, 21 Jan 2025 11:40:43 +0100 Subject: [PATCH 1/2] allow combining `histogram` with `visual(Stairs)` and other plot types such as `Scatter`. Possibly an alternative to #572. The only drawback here is that the `visual(...)` needs to come before `histogram()`, otherwise an error is thrown because `width` is not mapped for other plot types. What do you think of this approach? --- src/transformations/histogram.jl | 23 +++++++--- test/reference_tests.jl | 40 ++++++++++++------ .../histogram scatter cat color ref.png | Bin 0 -> 10499 bytes .../histogram stairs cat color ref.png | Bin 0 -> 10182 bytes 4 files changed, 43 insertions(+), 20 deletions(-) create mode 100644 test/reference_tests/histogram scatter cat color ref.png create mode 100644 test/reference_tests/histogram stairs cat color ref.png diff --git a/src/transformations/histogram.jl b/src/transformations/histogram.jl index a7fff0f69..aacb88454 100644 --- a/src/transformations/histogram.jl +++ b/src/transformations/histogram.jl @@ -45,23 +45,34 @@ function (h::HistogramAnalysis)(input::ProcessedLayer) datalimits = h.datalimits === automatic ? defaultdatalimits(input.positional) : h.datalimits options = valid_options(; datalimits, h.bins, h.closed, h.normalization) + N = length(input.positional) + default_plottype = categoricalplottypes[N] + plottype = Makie.plottype(input.plottype, default_plottype) + output = map(input) do p, n hist = _histogram(Tuple(p); pairs(n)..., pairs(options)...) edges, weights = hist.edges, hist.weights - named = length(edges) == 1 ? (; width=diff(first(edges))) : (;) - return (map(midpoints, edges)..., weights), named + named = plottype == BarPlot ? (; width=diff(first(edges))) : (;) + positional = if plottype == Stairs + edges = only(edges) + phantomedge = edges[end] # to bring step back to baseline + edges = vcat(edges, phantomedge) + z = zero(eltype(weights)) + heights = vcat(z, weights, z) + (edges, heights) + else + (map(midpoints, edges)..., weights) + end + return positional, named end - N = length(input.positional) label = h.normalization == :none ? "count" : string(h.normalization) labels = set(output.labels, N+1 => label) - attributes = if N == 1 + attributes = if plottype == BarPlot set(output.attributes, :gap => 0, :dodge_gap => 0) else output.attributes end - default_plottype = categoricalplottypes[N] - plottype = Makie.plottype(output.plottype, default_plottype) return ProcessedLayer(output; plottype, labels, attributes) end diff --git a/test/reference_tests.jl b/test/reference_tests.jl index 1d3b89226..fb2492357 100644 --- a/test/reference_tests.jl +++ b/test/reference_tests.jl @@ -27,7 +27,7 @@ reftest("barplot cat color palette") do draw(scales(Color = (; palette = :Set1_3))) end -reftest("barplot layout") do +reftest("barplot layout") do data((; x = ["A", "B", "C"], y = 1:3, z = ["X", "Y", "Z"])) * mapping(:x, :y; layout = :z) * visual(BarPlot) |> draw end @@ -244,6 +244,18 @@ reftest("histogram stack") do draw(specs) end +reftest("histogram stairs cat color") do + df = (x=[sin.(1:500); sin.(1:500) .* 2], z=repeat(["a", "b"], inner = 500)) + specs = data(df) * mapping(:x, layout=:z, color = :z) * visual(Stairs) * histogram() + draw(specs) +end + +reftest("histogram scatter cat color") do + df = (x=[sin.(1:500); sin.(1:500) .* 2], z=repeat(["a", "b"], inner = 500)) + specs = data(df) * mapping(:x, layout=:z, color = :z) * visual(Scatter) * histogram() + draw(specs) +end + reftest("histogram 2d") do df = (x=sin.(1:300), y=cos.(1:300)) specs = data(df) * mapping(:x, :y) * histogram() @@ -736,7 +748,7 @@ function presorted_plot(; with_missing::Bool) end group = ["2", "3", "1", "1", "3", "2"] some_value = sort(exp.(sin.(1:6))) - + df = (; countries, group, some_value) m1 = mapping(:countries, :some_value, color = :group) @@ -744,7 +756,7 @@ function presorted_plot(; with_missing::Bool) m3 = mapping(:countries => presorted, :some_value, color = :group => presorted) base = data(df) * visual(BarPlot, direction = :x) - + f = Figure() fg1 = draw!(f[1, 1], base * m1) fg2 = draw!(f[2, 1], base * m2) @@ -795,7 +807,7 @@ reftest("categorical color from continuous") do f end -reftest("title subtitle footnotes") do +reftest("title subtitle footnotes") do spec = pregrouped( fill(1:5, 6), fill(11:15, 6), @@ -816,7 +828,7 @@ reftest("title subtitle footnotes") do ) end -reftest("title subtitle footnotes single unconstrained facet") do +reftest("title subtitle footnotes single unconstrained facet") do spec = data((; x = 1:10, y = 11:20)) * mapping(:x, :y) * visual(Scatter) draw( spec; @@ -831,7 +843,7 @@ reftest("title subtitle footnotes single unconstrained facet") do ) end -reftest("title") do +reftest("title") do spec = pregrouped( fill(1:5, 6), fill(11:15, 6), @@ -847,7 +859,7 @@ reftest("title") do ) end -reftest("title subtitle footnotes settings") do +reftest("title subtitle footnotes settings") do spec = pregrouped( fill(1:5, 6), fill(11:15, 6), @@ -877,10 +889,10 @@ reftest("title subtitle footnotes settings") do ), axis = (; width = 100, height = 100) ) - + end -reftest("title subtitle footnotes fontsize inherit") do +reftest("title subtitle footnotes fontsize inherit") do spec = pregrouped( fill(1:5, 6), fill(11:15, 6), @@ -902,7 +914,7 @@ reftest("title subtitle footnotes fontsize inherit") do ) end -reftest("dodge barplot with errorbars") do +reftest("dodge barplot with errorbars") do f = Figure() df = ( x = [1, 1, 2, 2], @@ -960,7 +972,7 @@ reftest("dodge scatter with rangebars") do yhigh = cos.(range(0, 2pi, length = 20)) .+ 0.3, dodge = repeat(["A", "B"], 10) ) - + f = Figure() spec1 = data(df) * (mapping(:x, :y, dodge_x = :dodge, color = :dodge) * visual(Scatter) + mapping(:x, :ylow, :yhigh, dodge_x = :dodge, color = :dodge) * visual(Rangebars)) spec2 = data(df) * (mapping(:y, :x, dodge_y = :dodge, color = :dodge) * visual(Scatter) + mapping(:x, :ylow, :yhigh, dodge_y = :dodge, color = :dodge) * visual(Rangebars, direction = :x)) @@ -974,10 +986,10 @@ end reftest("manual legend labels in visual") do df_subjects = (; x = repeat(1:10, 10), y = cos.(1:100), id = repeat(1:10, inner = 10)) df_func = (; x = range(1, 10, length = 20), y = cos.(range(1, 10, length = 20))) - + spec1 = data(df_subjects) * mapping(:x, :y, group = :id => nonnumeric) * visual(Lines, linestyle = :dash, color = (:black, 0.2), label = "Subject data") spec2 = data(df_func) * mapping(:x, :y) * (visual(Lines, color = :tomato) + visual(Scatter, markersize = 12, color = :tomato, strokewidth = 2)) * visual(label = L"\cos(x)") - + draw(spec1 + spec2) end @@ -986,7 +998,7 @@ reftest("manual legend order") do spec1 = data(df) * mapping(:x, :y, color = :group) * visual(Lines) spec2 = data((; x = 1:10, y = cos.(1:10) .+ 2)) * mapping(:x, :y) * visual(Scatter, color = :purple, label = "Scatter") - + f = Figure() fg = draw!(f[1, 1], spec1 + spec2) legend!(f[1, 2], fg) diff --git a/test/reference_tests/histogram scatter cat color ref.png b/test/reference_tests/histogram scatter cat color ref.png new file mode 100644 index 0000000000000000000000000000000000000000..9d0da343cf417533dcb702c2e2b8174cebab47e4 GIT binary patch literal 10499 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 literal 0 HcmV?d00001 diff --git a/test/reference_tests/histogram stairs cat color ref.png b/test/reference_tests/histogram stairs cat color ref.png new file mode 100644 index 0000000000000000000000000000000000000000..5a80979b7985089a1bffad08cf86f4d43e519016 GIT binary patch literal 10182 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 Date: Thu, 30 Jan 2025 12:51:30 +0100 Subject: [PATCH 2/2] implement review suggestions --- src/transformations/histogram.jl | 16 ++++++++++------ test/reference_tests.jl | 4 ++-- .../histogram scatter cat color ref.png | Bin 10499 -> 10637 bytes .../histogram stairs cat color ref.png | Bin 10182 -> 10551 bytes 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/transformations/histogram.jl b/src/transformations/histogram.jl index aacb88454..5294d60e0 100644 --- a/src/transformations/histogram.jl +++ b/src/transformations/histogram.jl @@ -39,15 +39,17 @@ Base.@kwdef struct HistogramAnalysis{D, B} bins::B=automatic closed::Symbol=:left normalization::Symbol=:none + visual::Union{typeof(automatic), Layer}=automatic end function (h::HistogramAnalysis)(input::ProcessedLayer) datalimits = h.datalimits === automatic ? defaultdatalimits(input.positional) : h.datalimits options = valid_options(; datalimits, h.bins, h.closed, h.normalization) + visual = h.visual N = length(input.positional) default_plottype = categoricalplottypes[N] - plottype = Makie.plottype(input.plottype, default_plottype) + plottype = Makie.plottype(input.plottype, visual === automatic ? default_plottype : (visual.transformation::Visual).plottype) output = map(input) do p, n hist = _histogram(Tuple(p); pairs(n)..., pairs(options)...) @@ -68,16 +70,18 @@ function (h::HistogramAnalysis)(input::ProcessedLayer) label = h.normalization == :none ? "count" : string(h.normalization) labels = set(output.labels, N+1 => label) - attributes = if plottype == BarPlot - set(output.attributes, :gap => 0, :dodge_gap => 0) - else - output.attributes + attributes = output.attributes + if plottype == BarPlot + attributes = set(attributes, :gap => 0, :dodge_gap => 0) + end + if visual !== automatic + attributes = merge(attributes, (visual.transformation::Visual).attributes) end return ProcessedLayer(output; plottype, labels, attributes) end """ - histogram(; bins=automatic, datalimits=automatic, closed=:left, normalization=:none) + histogram(; bins=automatic, datalimits=automatic, closed=:left, normalization=:none, visual=automatic) Compute a histogram. diff --git a/test/reference_tests.jl b/test/reference_tests.jl index fb2492357..dd3282b28 100644 --- a/test/reference_tests.jl +++ b/test/reference_tests.jl @@ -246,13 +246,13 @@ end reftest("histogram stairs cat color") do df = (x=[sin.(1:500); sin.(1:500) .* 2], z=repeat(["a", "b"], inner = 500)) - specs = data(df) * mapping(:x, layout=:z, color = :z) * visual(Stairs) * histogram() + specs = data(df) * mapping(:x, layout=:z, color = :z) * histogram(; visual = visual(Stairs; alpha = 0.8, linewidth = 4)) draw(specs) end reftest("histogram scatter cat color") do df = (x=[sin.(1:500); sin.(1:500) .* 2], z=repeat(["a", "b"], inner = 500)) - specs = data(df) * mapping(:x, layout=:z, color = :z) * visual(Scatter) * histogram() + specs = data(df) * mapping(:x, layout=:z, color = :z) * histogram(visual = visual(Scatter; alpha = 0.8, marker = :cross, markersize = 20)) draw(specs) end diff --git a/test/reference_tests/histogram scatter cat color ref.png b/test/reference_tests/histogram scatter cat color ref.png index 9d0da343cf417533dcb702c2e2b8174cebab47e4..733ac4f9f59cc68ffd423df354324255c15b1bc5 100644 GIT binary patch literal 10637 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 AHUIzs literal 10499 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 diff --git a/test/reference_tests/histogram stairs cat color ref.png b/test/reference_tests/histogram stairs cat color ref.png index 5a80979b7985089a1bffad08cf86f4d43e519016..1dbce5696955a16b51f87f08da3f395a23463d3c 100644 GIT binary patch literal 10551 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%0Am>l&cc3n9S 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 literal 10182 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