-
-
Notifications
You must be signed in to change notification settings - Fork 31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC Switch to Colorschemes #87
Conversation
Does ColorSchemes have all the colours which were previously in PlotUtils, or do we need to add some there? |
We had 13 ColorSchemes in PlotUtils that are not (or in a different form) in ColorSchemes. They are now stored in PlotUtils |
I may have to rethink |
Yes, that would also need to happen for log-scaled gradients. |
Hi @daschw this is great and I agree with almost all of your ideas. Comments and thoughts: About I think the areaplot(x, palette = :blues) has a different behaviour from areaplot(x, palette = palette(:blues)) Similar it's unintuitive that you can retrieve the old behaviour by palette = cgrad(grad)) given that a gradient is defined as something that varies the colors sequentially, and a palette is where you'd expect them to be spaced apart. In sum, I think there's some unclarity about the relationships between the I really love that there is now support for categorical gradients, though I wonder if
wouldn't be more intuitive to form a categorical one (it's type stable if it's always categorical when that keyword is defined)? About your two questions at the end:
|
src/colorschemes.jl
Outdated
colors::ColorScheme | ||
end | ||
|
||
Base.reverse(cg::ColorGradient) = ColorGradient(reverse(cg.colors)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldn't this need to pass scale and alpha cg too?
Thanks a lot for your feedback! I think I have updated to a cleaner and more feature-rich version now.
function f(x, y)
r = sqrt(x^2 + y^2)
return cos(r) / (1 + r)
end
x = range(-2π, 2π, length = 50)
sym = :alpine
grads = [
cgrad(sym)
cgrad(sym, 10, categorical = true)
cgrad(sym, [0.1, 0.15, 0.8])
cgrad(sym, [0.1, 0.15, 0.8], categorical = true)
]
plot((heatmap(x, x, f, c = g) for g in grads)...) loggrads = [
cgrad(sym, scale = :log)
cgrad(sym, 10, categorical = true, scale = :log)
cgrad(sym, [0.1, 0.15, 0.8], scale = :log)
cgrad(sym, [0.1, 0.15, 0.8], categorical = true, scale = :log)
]
plot((heatmap(x, x, f, c = g) for g in loggrads)...) revgrads = [
cgrad(sym, rev = true)
cgrad(sym, 10, categorical = true, rev = true)
cgrad(sym, [0.1, 0.15, 0.8], rev = true)
cgrad(sym, [0.1, 0.15, 0.8], categorical = true, rev = true)
]
plot((heatmap(x, x, f, c = g) for g in revgrads)...) logrevgrads = [
cgrad(sym, scale = :log, rev = true)
cgrad(sym, 10, categorical = true, scale = :log, rev = true)
cgrad(sym, [0.1, 0.15, 0.8], scale = :log, rev = true)
cgrad(sym, [0.1, 0.15, 0.8], categorical = true, scale = :log, rev = true)
]
plot((heatmap(x, x, f, c = g) for g in logrevgrads)...) This works for GR, Plotly(JS), PyPlot and PGPPlotsX bachends. Note that all plots from my original post still work the same way. When color palettes are passed as color attribute for a plot with gradients they are converted to Some comments to @mkborregaard comments:
You are talking about palettes being passed as gradient, right? What does running out of colors mean here for a gradient? A gradient is defined by the colors passed and interpolated linearly in between.
It does not. Note that above I used
Agreed. Actually I don't care too much about the old behaviour. I don't know If anyone uses that. I just thought this was the easiest way to keep it still available. |
function Base.get(cg::CategoricalColorGradient, x::AbstractFloat, rangescale = (0.0, 1.0)) | ||
isfinite(x) || return invisible() | ||
rangescale = get_rangescale(rangescale) | ||
x = clamp.(x, rangescale...) | ||
if rangescale != (0.0, 1.0) | ||
x = ColorSchemes.remap(x, rangescale..., 0, 1) | ||
end | ||
return cg.colors[x == 0 ? 1 : findlast(<(x), cg.values)] | ||
return cg.colors[x == 0 ? 1 : findlast(z -> z < x, cg.values)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just curious - why this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the former version does not work on julia 1.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you fix the RecipesPipeline bug on 1.0 with the splatting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it was due to outdated precompile statements in Plots.
Thanks for answering my concerns. This is awesome. |
@asinghvi17 it would be great if you could check if these changes are fine for AbstractPlotting/Makie too. |
I suspect that the introduction of a new type is already breaking...it may make sense to refactor the backends to use these types, though. @simon could we deprecate Sampler in favor of these? The alternative is to convert these to Sampler, but since they're already the same thing it might make sense to share the code. |
I would like to go ahead with this soon. Are there any objections @asinghvi17 @SimonDanisch ? |
btw - ColorSchemes 3.8 is "order of magnitude faster' apparently... |
I'd say just release a breaking version and then we can figure out how to upgrade AbstractPlotting? |
Part 1
This is an attempt to switch from PlotUtils color libraries to ColorSchemes.
We define two types,
ColorGradient
andColorPalette
, both wrapping aColorScheme
. and differing in the methods forgetindex(c, z::AbstractFloat)
. Gradients interpolate linearly, while palettes choose the nearest color.The changes here are breaking, so we need a new minor release:
clibrary
,clibraries
andcgradients
. They are deleted.palette
(a convenience function to construct palettes from symbols pointing to colorschemes or former Plots gradients)ColorPalette
color_list
(get the vector of colors defining gradients, palettes or colorschemes)cgrad(:<grad>r)
is no longer working for getting the reverse gradient ofcgrad(:<grad>)
. Now we usecgrad(:<grad>, rev = true)
Plots gradients not defined in ColorSchemes are still defined including Plots default color palette. Former gradients with a different name than the ColorSchemes equivalent are mapped to the correct colorscheme.
This requires a follow-up PR in PlotThemes, which also will be breaking. PlotThemes can no longer export
palette(sym)
to get the palette of a Theme.palette(sym) is now used (analog to
cgrad) to get a palette from a colorscheme defined in ColorSchemes. The PlotThemes version will be renamed to
theme_palette(sym)`.Furthermore I prepared a follow-up PR for Plots. This will be kind of breaking because Plots reexports PlotUtils and PlotThemes. Typical plotting however will barely have breaking changes with two exceptions:
plot(..., palette = grad::Symbol)
will no longer spread the colors as distant as possible among the provided color scheme, but cycle through its colors. The old behavior can be achieved withplot(..., palette = cgrad(grad))
Here's the rationale behind the second change: When passed a Symbol, the
palette
attribute defaults topalette(sym)
. This way colorschemes like:Dark2
can be used withpalette = :Dark2
. ColorSchemes like:inferno
also have to fallback to this behavior. We are only passed a symbol and we cannot know if it is a categorical colorscheme or a gradient. I users want the old behavior for gradients they can simply pass gradients topalette
with e.g.cgrad(:inferno)
old
new
old
new
both
only new
When a Symbol is passed to a
color
attribute (and it is not aColorant
), conversely, it defaults tocgrad(sym)
. By providing a palette explicitely we get a new feature of a categorical gradient.This also works for surface, marker_z, line_z and fill_z.
I'm unsure about two points:
Note also that this requires a new ColorSchemes release.