diff --git a/CHANGELOG.md b/CHANGELOG.md index 2be6ab8f2a7..012493dd6c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Added `scale` attribute to `violin` [#3352](https://github.com/MakieOrg/Makie.jl/pull/3352). - Use label formatter in barplot [#3718](https://github.com/MakieOrg/Makie.jl/pull/3718). - Fix the incorrect shading with non uniform markerscale in meshscatter [#3722](https://github.com/MakieOrg/Makie.jl/pull/3722) +- Add `scale_to=:flip` option to `hist`, which flips the direction of the bars [#3732](https://github.com/MakieOrg/Makie.jl/pull/3732) - Fixed an issue with the texture atlas not updating in WGLMakie after display, causing new symbols to not show up [#3737](https://github.com/MakieOrg/Makie.jl/pull/3737) ## [0.20.8] - 2024-02-22 diff --git a/ReferenceTests/src/tests/examples2d.jl b/ReferenceTests/src/tests/examples2d.jl index 0f567313313..2bedc371f4b 100644 --- a/ReferenceTests/src/tests/examples2d.jl +++ b/ReferenceTests/src/tests/examples2d.jl @@ -1068,6 +1068,40 @@ end f end +@reference_test "Histogram" begin + data = sin.(1:1000) + + fig = Figure(size = (900, 900)) + hist(fig[1, 1], data) + hist(fig[1, 2], data, bins = 30, color = :orange) + a, p = hist(fig[1, 3], data, bins = 10, color = :transparent, strokecolor = :red, strokewidth = 4.0) + a.xgridcolor[] = RGBAf(0,0,0,1); a.ygridcolor[] = RGBAf(0,0,0,1) + + hist(fig[2, 1], data, normalization = :pdf, direction = :x) + hist(fig[2, 2], data, normalization = :density, color = 1:15) + hist(fig[2, 3], data, normalization = :probability, scale_to = :flip) + + hist(fig[3, 1], data, offset = 20.0) + hlines!(0.0, color = :black, linewidth = 3) + hist(fig[3, 2], data, fillto = 1.0, scale_to = -5.0, direction = :x) + vlines!(0.0, color = :black, linewidth = 3) + hist(fig[3, 3], data, bar_labels = :y, label_size = 10, bins = 10) + + hist( + fig[4, 1], data, scale_to = :flip, offset = 20, + bar_labels = :x, label_size = 12, label_color = :green + ) + hlines!(0.0, color = :black, linewidth = 3) + i12 = mod1.(1:10, 2) + hist(fig[4, 2], data, scale_to = :flip, bins = 10, direction = :x, + bar_labels = :x, label_size = [14, 10][i12], + label_color = [:yellow, :blue][i12], label_offset = [-30, 10][i12] + ) + hist(fig[4, 3], data, weights = 1.0 ./ (2.0 .+ data)) + + fig +end + @reference_test "Stephist" begin stephist(RNG.rand(10000)) current_figure() @@ -1406,7 +1440,7 @@ end end @reference_test "Violin plots differently scaled" begin - fig = Figure() + fig = Figure() xs = vcat([fill(i, i * 1000) for i in 1:4]...) ys = vcat(RNG.randn(6000), RNG.randn(4000) * 2) for (i, scale) in enumerate([:area, :count, :width]) diff --git a/docs/reference/plots/hist.md b/docs/reference/plots/hist.md index 6df7ff2520a..aa1c711f60c 100644 --- a/docs/reference/plots/hist.md +++ b/docs/reference/plots/hist.md @@ -41,7 +41,8 @@ hist(data, normalization = :pdf, bar_labels = :values, With `scale_to`, and `offset`, one can put multiple histograms into the same plot. Note, that offset automatically sets fillto, to move the whole barplot. -Also, one can use a negative `scale_to` amount to flip the histogram. +Also, one can use a negative `scale_to` amount to flip the histogram, +or `scale_to=:flip` to flip the direction of the bars without changing their height. \begin{examplefigure}{} ```julia diff --git a/src/basic_recipes/barplot.jl b/src/basic_recipes/barplot.jl index 794ce08701c..e08fede2e9e 100644 --- a/src/basic_recipes/barplot.jl +++ b/src/basic_recipes/barplot.jl @@ -198,18 +198,18 @@ function text_attributes(values, in_y_direction, flip_labels_at, color_over_back if isflipped # plot text inside bar - push!(offsets, swap(0, -label_offset)) + push!(offsets, swap(0, -sv_getindex(label_offset, i))) push!(text_colors, geti(color_over_bar, i)) else # plot text next to bar - push!(offsets, swap(0, label_offset)) + push!(offsets, swap(0, sv_getindex(label_offset, i))) push!(text_colors, geti(color_over_background, i)) end end return aligns, offsets, text_colors end -function barplot_labels(xpositions, ypositions, bar_labels, in_y_direction, flip_labels_at, +function barplot_labels(xpositions, ypositions, offset, bar_labels, in_y_direction, flip_labels_at, color_over_background, color_over_bar, label_formatter, label_offset, label_rotation, label_align) if bar_labels isa Symbol && bar_labels in (:x, :y) @@ -225,8 +225,8 @@ function barplot_labels(xpositions, ypositions, bar_labels, in_y_direction, flip if length(bar_labels) == length(xpositions) attributes = text_attributes(ypositions, in_y_direction, flip_labels_at, color_over_background, color_over_bar, label_offset, label_rotation, label_align) - label_pos = map(xpositions, ypositions, bar_labels) do x, y, l - return (string(label_formatter(l)), in_y_direction ? Point2f(x, y) : Point2f(y, x)) + label_pos = broadcast(xpositions, ypositions, offset, bar_labels) do x, y, off, l + return (string(label_formatter(l)), in_y_direction ? Point2f(x, y+off) : Point2f(y, x+off)) end return (label_pos, attributes...) else @@ -296,7 +296,7 @@ function Makie.plot!(p::BarPlot) if !isnothing(bar_labels) oback = color_over_background === automatic ? label_color : color_over_background obar = color_over_bar === automatic ? label_color : color_over_bar - label_args = barplot_labels(x̂, y, bar_labels, in_y_direction, + label_args = barplot_labels(x̂, y, offset, bar_labels, in_y_direction, flip_labels_at, to_color(oback), to_color(obar), label_formatter, label_offset, label_rotation, label_align) labels[], label_aligns[], label_offsets[], label_colors[] = label_args diff --git a/src/stats/hist.jl b/src/stats/hist.jl index 165f361bc07..1b4a5bb2196 100644 --- a/src/stats/hist.jl +++ b/src/stats/hist.jl @@ -13,7 +13,9 @@ function _hist_center_weights(values, edges, normalization, scale_to, wgts) h_norm = StatsBase.normalize(h; mode = normalization) weights = h_norm.weights centers = edges[1:end-1] .+ (diff(edges) ./ 2) - if !isnothing(scale_to) + if scale_to === :flip + weights .= -weights + elseif !isnothing(scale_to) max = maximum(weights) weights .= weights ./ max .* scale_to end @@ -106,14 +108,18 @@ The following attributes can move the histogram around, which comes in handy when placing multiple histograms into one plot: * `offset = 0.0`: adds an offset to every value * `fillto = 0.0`: defines where the bar starts -* `scale_to = nothing`: allows to scale all values to a certain height -* `flip = false`: flips all values +* `scale_to = nothing`: allows to scale all values to a certain height. This +can also be set to `:flip` to flip the direction of histogram bars without +scaling them to a common height. Color can either be: * a vector of `bins` colors * a single color * `:values`, to color the bars with the values from the histogram +You can also draw a histogram in x-direction rather than y-direction by setting +`direction = :x`. + ## Attributes $(ATTRIBUTES) """