From f9a18e0d13324896a20f2cab38923f5240c49c98 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 10 May 2022 15:22:12 +0200 Subject: [PATCH] properly deprecated to_colormap(cm, n) (#1901) * properly deprecated to_colormap(cm, n) * add resample_cmap * actually mention the breaking change --- NEWS.md | 1 + src/Makie.jl | 2 +- src/basic_recipes/series.jl | 27 ------------------- src/conversions.jl | 53 +++++++++++++++++++++++++++++++++---- src/utilities/utilities.jl | 22 +++++++++++++++ test/conversions.jl | 22 ++++++++++++++- 6 files changed, 93 insertions(+), 34 deletions(-) diff --git a/NEWS.md b/NEWS.md index 58eed99a184..acfe2f58797 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,6 +5,7 @@ - **Breaking** Added `space` as a generic attribute to switch between data, pixel, relative and clip space for positions. `space` in text has been renamed to `markerspace` because of this. `Pixel` and `SceneSpace` are no longer valid inputs for `space` or `markerspace` [#1596](https://github.com/JuliaPlots/Makie.jl/pull/1596). - **Breaking** Deprecated `mouse_selection(scene)` for `pick(scene)`. - **Breaking** Bumped `GridLayoutBase` version to `v0.7`, which introduced offset layouts. Now, indexing into row 0 doesn't create a new row 1, but a new row 0, so that all previous content positions stay the same. This makes building complex layouts order-independent [#1704](https://github.com/JuliaPlots/Makie.jl/pull/1704). +- **Breaking** deprecate `to_colormap(cmap, ncolors)` in favor of `categorical_colors(cmap, ncolors)` and `resample_cmap(cmap, ncolors)` - Added `empty!(fig)` and changed `empty!(scene)` to remove all child plots without detaching windows [#1818](https://github.com/JuliaPlots/Makie.jl/pull/1818). - Switched to erroring instead of warning for deprecated events `mousebuttons`, `keyboardbuttons` and `mousedrag`. - `Layoutable` was renamed to `Block` and the infrastructure changed such that attributes are fixed fields and each block has its own `Scene` for better encapsulation [#1796](https://github.com/JuliaPlots/Makie.jl/pull/1796). diff --git a/src/Makie.jl b/src/Makie.jl index 11c77ca768a..623ecee5a69 100644 --- a/src/Makie.jl +++ b/src/Makie.jl @@ -191,7 +191,7 @@ export broadcast_foreach, to_vector, replace_automatic! # conversion infrastructure export @key_str, convert_attribute, convert_arguments -export to_color, to_colormap, to_rotation, to_font, to_align, to_textsize +export to_color, to_colormap, to_rotation, to_font, to_align, to_textsize, categorical_colors, resample_cmap export to_ndim, Reverse # Transformations diff --git a/src/basic_recipes/series.jl b/src/basic_recipes/series.jl index 6a237171346..c1329f17363 100644 --- a/src/basic_recipes/series.jl +++ b/src/basic_recipes/series.jl @@ -35,33 +35,6 @@ Curves can be: ) end -function categorical_colors(cols::AbstractVector{<: Colorant}, categories::Integer) - if length(cols) < categories - error("Not enough colors for number of categories. Categories: $(categories), colors: $(length(cols))") - end - return to_colormap(cols) -end - -function categorical_colors(cols::AbstractVector, categories::Integer) - return categorical_colors(to_color.(cols), categories) -end - -function categorical_colors(cs::Union{String, Symbol}, categories::Integer) - cs_string = string(cs) - if cs_string in all_gradient_names - cols = PlotUtils.get_colorscheme(Symbol(cs_string)).colors - categorical_colors(cols, categories) - else - error( - """ - There is no color gradient named $cs. - See `available_gradients()` for the list of available gradients, - or look at http://makie.juliaplots.org/dev/generated/colors#Colormap-reference. - """ - ) - end -end - replace_missing(x) = ismissing(x) ? NaN : x function convert_arguments(T::Type{<: Series}, y::AbstractMatrix) diff --git a/src/conversions.jl b/src/conversions.jl index 65b413f28e6..447cd068379 100644 --- a/src/conversions.jl +++ b/src/conversions.jl @@ -291,7 +291,7 @@ function convert_arguments(SL::SurfaceLike, x::AbstractVecOrMat{<: Number}, y::A return map(el32convert, adjust_axes(SL, x, y, z)) end -convert_arguments(::SurfaceLike, x::AbstractMatrix, y::AbstractMatrix) = (x, y, zeros(size(y))) +convert_arguments(sl::SurfaceLike, x::AbstractMatrix, y::AbstractMatrix) = convert_arguments(sl, x, y, zeros(size(y))) """ convert_arguments(P, x, y, z)::Tuple{ClosedInterval, ClosedInterval, Matrix} @@ -724,9 +724,9 @@ Converts a `color` symbol (e.g. `:blue`) to a color RGBA. convert_attribute(color, ::key"color") = to_color(color) """ - to_colormap(cm[, N = 20]) + to_colormap(cm) -Converts a colormap `cm` symbol (e.g. `:Spectral`) to a colormap RGB array, where `N` specifies the number of color points. +Converts a colormap `cm` symbol/string (e.g. `:Spectral`) to a colormap RGB array. """ convert_attribute(colormap, ::key"colormap") = to_colormap(colormap) convert_attribute(rotation, ::key"rotation") = to_rotation(rotation) @@ -744,7 +744,7 @@ struct Palette i::Ref{Int} Palette(colors) = new(to_color.(colors), zero(Int)) end -Palette(name::Union{String, Symbol}, n = 8) = Palette(to_colormap(name, n)) +Palette(name::Union{String, Symbol}, n = 8) = Palette(categorical_colors(name, n)) function to_color(p::Palette) N = length(p.colors) p.i[] = p.i[] == N ? 1 : p.i[] + 1 @@ -1009,6 +1009,45 @@ function available_gradients() end end + +to_colormap(cm, categories::Integer) = error("`to_colormap(cm, categories)` is deprecated. Use `Makie.categorical_colors(cm, categories)` for categorical colors, and `resample_cmap(cmap, ncolors)` for continous resampling.") + +""" + categorical_colors(colormaplike, categories::Integer) + +Creates categorical colors and tries to match `categories`. +Will error if color scheme doesn't contain enough categories. Will drop the n last colors, if request less colors than contained in scheme. +""" +function categorical_colors(cols::AbstractVector{<: Colorant}, categories::Integer) + if length(cols) < categories + error("Not enough colors for number of categories. Categories: $(categories), colors: $(length(cols))") + end + return cols[1:categories] +end + +function categorical_colors(cols::AbstractVector, categories::Integer) + return categorical_colors(to_color.(cols), categories) +end + +function categorical_colors(cs::Union{String, Symbol}, categories::Integer) + cs_string = string(cs) + if cs_string in all_gradient_names + if haskey(ColorBrewer.colorSchemes, cs_string) + return to_colormap(ColorBrewer.palette(cs_string, categories)) + else + return categorical_colors(to_colormap(cs_string), categories) + end + else + error( + """ + There is no color gradient named $cs. + See `available_gradients()` for the list of available gradients, + or look at http://makie.juliaplots.org/dev/generated/colors#Colormap-reference. + """ + ) + end +end + """ Reverses the attribute T upon conversion """ @@ -1019,8 +1058,10 @@ end to_colormap(r::Reverse) = reverse(to_colormap(r.data)) to_colormap(cs::ColorScheme) = to_colormap(cs.colors) + + """ - to_colormap(b) + to_colormap(b::AbstractVector) An `AbstractVector{T}` with any object that [`to_color`](@ref) accepts. """ @@ -1033,6 +1074,8 @@ function to_colormap(cs::Tuple{<: Union{Reverse, Symbol, AbstractString}, Real}) end """ + to_colormap(cs::Union{String, Symbol})::Vector{RGBAf} + A Symbol/String naming the gradient. For more on what names are available please see: `available_gradients()`. For now, we support gradients from `PlotUtils` natively. """ diff --git a/src/utilities/utilities.jl b/src/utilities/utilities.jl index ab77fb91898..faf99f80914 100644 --- a/src/utilities/utilities.jl +++ b/src/utilities/utilities.jl @@ -13,6 +13,28 @@ function resample(A::AbstractVector, len::Integer) return interpolated_getindex.((A,), range(0.0, stop=1.0, length=len)) end + +""" + resample_cmap(cmap, ncolors::Integer; alpha=1.0) + +* cmap: anything that `to_colormap` accepts +* ncolors: number of desired colors +* alpha: additional alpha applied to each color. Can also be an array, matching `colors`, or a tuple giving a start + stop alpha value. +""" +function resample_cmap(cmap, ncolors::Integer; alpha=1.0) + cols = to_colormap(cmap) + r = range(0.0, stop=1.0, length=ncolors) + if alpha isa Tuple{<:Number, <:Number} + alphas = LinRange(alpha..., ncolors) + else + alphas = alpha + end + return broadcast(r, alphas) do i, a + c = interpolated_getindex(cols, i) + return RGBAf(Colors.color(c), Colors.alpha(c) * a) + end +end + """ resampled_colors(attributes::Attributes, levels::Integer) diff --git a/test/conversions.jl b/test/conversions.jl index 97e61eba1aa..c6081821fa3 100644 --- a/test/conversions.jl +++ b/test/conversions.jl @@ -176,7 +176,27 @@ end @test categorical_colors([to_color(:red)], 1) == [to_color(:red)] @test categorical_colors([:red], 1) == [to_color(:red)] @test_throws ErrorException categorical_colors([to_color(:red)], 2) - @test categorical_colors(:darktest, 1) == to_color.(Makie.PlotUtils.palette(:darktest)) + @test categorical_colors(:darktest, 1) == to_color.(Makie.PlotUtils.palette(:darktest))[1:1] + @test_throws ErrorException to_colormap(:viridis, 10) # deprecated + @test categorical_colors(:darktest, 1) == to_color.(Makie.PlotUtils.palette(:darktest))[1:1] + @test categorical_colors(:viridis, 10) == to_colormap(:viridis)[1:10] + # TODO why don't they exactly match? + @test categorical_colors(:Set1, 9) ≈ to_colormap(:Set1) + + @test_throws ArgumentError Makie.categorical_colors(:PuRd, 20) # not enough categories +end + +@testset "resample colormap" begin + cs = Makie.resample_cmap(:viridis, 10; alpha=LinRange(0, 1, 10)) + @test Colors.alpha.(cs) == Float32.(LinRange(0, 1, 10)) + cs = Makie.resample_cmap(:viridis, 2; alpha=0.5) + @test all(x-> x == 0.5, Colors.alpha.(cs)) + @test Colors.color.(cs) == Colors.color.(Makie.resample(to_colormap(:viridis), 2)) + cs = Makie.resample_cmap(:Set1, 100) + @test all(x-> x == 1.0, Colors.alpha.(cs)) + @test Colors.color.(cs) == Colors.color.(Makie.resample(to_colormap(:Set1), 100)) + cs = Makie.resample_cmap(:Set1, 10; alpha=(0, 1)) + @test Colors.alpha.(cs) == Float32.(LinRange(0, 1, 10)) end @testset "colors" begin