From e6c2bbf3ffc74c222155cba43ce029c5f950f2ad Mon Sep 17 00:00:00 2001 From: Mattriks Date: Sun, 18 Mar 2018 21:40:04 +1100 Subject: [PATCH] Theme_colormaps --- docs/src/lib/scales/scale_color_continuous.md | 4 +- .../lib/scales/scale_color_discrete_hue.md | 29 ++--- docs/src/man/themes.md | 51 +++++++- src/Gadfly.jl | 6 +- src/scale.jl | 24 +--- src/statistics.jl | 8 +- src/theme.jl | 119 +++++++++++------- test/testscripts/Theme_colormaps.jl | 27 ++++ test/testscripts/density_dark.jl | 3 +- test/testscripts/theme_ggplot.jl | 22 ++++ 10 files changed, 189 insertions(+), 104 deletions(-) create mode 100644 test/testscripts/Theme_colormaps.jl create mode 100644 test/testscripts/theme_ggplot.jl diff --git a/docs/src/lib/scales/scale_color_continuous.md b/docs/src/lib/scales/scale_color_continuous.md index 493ccae28..08ac7331f 100644 --- a/docs/src/lib/scales/scale_color_continuous.md +++ b/docs/src/lib/scales/scale_color_continuous.md @@ -6,7 +6,9 @@ Author = "David Chudzicki" Create a continuous color scale that the plot will use. -This can also be set as the `continuous_color_scheme` in a [`Theme`](@ref) +There are 2 ways to change the color palette in a continuous color scale: +* for single plots, by using `Scale.color_continuous(colormap=)`, see Examples below +* for a set of plots, by using `Gadfly.push_theme(style(continuous_colormap=))`, see [Themes](@ref) ## Arguments diff --git a/docs/src/lib/scales/scale_color_discrete_hue.md b/docs/src/lib/scales/scale_color_discrete_hue.md index 7c425e095..ec35a2850 100644 --- a/docs/src/lib/scales/scale_color_discrete_hue.md +++ b/docs/src/lib/scales/scale_color_discrete_hue.md @@ -18,17 +18,15 @@ alias for [Scale.color_discrete_hue](@ref). ## Examples ```@setup 1 -using Gadfly -using Colors +using Colors, Gadfly srand(1234) ``` -## Examples +There are 2 ways to change the discrete color scale: -You can set a discrete color scale of your choice in a plot. +* For a single plot, provide a color mapping function, i.e `f` above, to `Scale.color_discrete`: ```@example 1 - function gen_colors(n) cs = distinguishable_colors(n, [colorant"#FE4365", colorant"#eca25c"], # seed colors @@ -42,30 +40,23 @@ function gen_colors(n) end using RDatasets - iris = dataset("datasets", "iris") plot(iris, x=:SepalLength, y=:SepalWidth, color=:Species, Geom.point, Scale.color_discrete(gen_colors)) - ``` -You can force the use of a discrete scale on data that would otherwise receive a continuous scale: +* For a set of plots, provide a color mapping function to `style(discrete_colormap=)`, and use `Gadfly.push_theme()`. See [Themes](@ref). ```@example 1 -plot(x=rand(12), y=rand(12), color=repeat([1,2,3], outer=[4]), - Scale.color_discrete()) +Gadfly.push_theme( style(discrete_colormap=gen_colors) ) + +Gadfly.pop_theme() # hide ``` -To set a default color scale for plots, you can set it in the current [Theme](@ref) using `push_theme`, using `style` to modify the current theme. +Also, you can force the use of a discrete scale on data that would otherwise receive a continuous scale: ```@example 1 -Gadfly.push_theme( - style( - discrete_color_scale=Scale.color_discrete(gen_colors) - ) -) - -Gadfly.pop_theme() # hide +plot(x=rand(12), y=rand(12), color=repeat([1,2,3], outer=[4]), + Scale.color_discrete()) ``` - diff --git a/docs/src/man/themes.md b/docs/src/man/themes.md index c63808dcd..240dfea61 100755 --- a/docs/src/man/themes.md +++ b/docs/src/man/themes.md @@ -88,14 +88,13 @@ These parameters can either be used with `Theme` or `style` * `bar_highlight`: Color used to stroke bars in bar plots. If a function is given, it's used to transform the fill color of the bars to obtain a stroke color. (Function, Color, or Nothing) - * `discrete_color_scale`: A `DiscreteColorScale` see [Scale.color_discrete_hue](@ref) - * `continuous_color_scale`: A `ContinuousColorScale` see [Scale.color_continuous](@ref) + * `discrete_colormap`: The function `f` in [Scale.color_discrete_hue](@ref) + * `continuous_colormap`: The function `colormap` in [Scale.color_continuous](@ref) ## Examples ```@setup 1 -using RDatasets -using Gadfly +using RDatasets, Gadfly Gadfly.set_default_plot_size(12cm, 8cm) srand(12345) ``` @@ -170,11 +169,11 @@ Gadfly.with_theme(:orange) do end ``` -Gadfly comes built in with 2 named themes: `:default` and `:dark`. You can also set a theme to use by default by setting the `GADFLY_THEME` environment variable *before* loading Gadfly. +Gadfly comes built in with 3 named themes: `:default`, `:dark` and `:ggplot`. You can also set a theme to use by default by setting the `GADFLY_THEME` environment variable *before* loading Gadfly. ## The Dark theme -This is one of the two themes the ship with Gadfly the other being `:default`. Here are a few plots that use the dark theme. +Here are a few plots that use the dark theme. ```@example 1 Gadfly.push_theme(:dark) @@ -229,4 +228,44 @@ plot(x=X[1,:], y=X[2,:], Geom.hexbin(xbincount=100, ybincount=100)) ```@example 1 Gadfly.pop_theme() +nothing # hide +``` + +## The ggplot theme + +Here are examples of the ggplot theme. When using named themes, note how you can change the `order` of key colors (see [Scale.color_discrete_hue](@ref)), or use a transformed color axis (see [Scale.color_continuous](@ref)), in the usual way: + + +```@setup 2 +using RDatasets, Gadfly +Gadfly.set_default_plot_size(17cm, 8cm) ``` + +```@example 2 +Gadfly.push_theme(:ggplot) +nothing # hide +``` +```@example 2 +pa = plot(dataset("datasets","iris"), + x=:PetalWidth, y=:SepalLength, color=:Species, Geom.point, + Scale.color_discrete(order=[3,2,1]), + Guide.colorkey(title="Iris", pos=[0.1, 9.3]) +) + +pb = plot(dataset("ggplot2","diamonds"), x=:Price, y=:Carat, + Geom.histogram2d(xbincount=25, ybincount=25), + Scale.color_log10, + Scale.x_continuous(format=:plain) +) + +hstack(pa, pb) +``` + +```@example 2 +Gadfly.pop_theme() +nothing # hide +``` + + + + diff --git a/src/Gadfly.jl b/src/Gadfly.jl index 2d5f3b7ec..42efd0299 100644 --- a/src/Gadfly.jl +++ b/src/Gadfly.jl @@ -1200,10 +1200,8 @@ get_scale{t,var}(::Val{t}, ::Val{var}, theme::Theme) = default_aes_scales[t][var get_scale(t::Symbol, var::Symbol, theme::Theme) = get_scale(Val{t}(), Val{var}(), theme) ### Override default getters for color scales -get_scale(::Val{:categorical}, ::Val{:color}, theme::Theme=current_theme()) = - theme.discrete_color_scale -get_scale(::Val{:numerical}, ::Val{:color}, theme::Theme=current_theme()) = - theme.continuous_color_scale +get_scale(::Val{:categorical}, ::Val{:color}, theme::Theme=current_theme()) = Scale.color_discrete() +get_scale(::Val{:numerical}, ::Val{:color}, theme::Theme=current_theme()) = Scale.color_continuous() function scale_exists(t::Symbol, var::Symbol) diff --git a/src/scale.jl b/src/scale.jl index 51be82c63..3482e8ff8 100644 --- a/src/scale.jl +++ b/src/scale.jl @@ -442,19 +442,9 @@ DiscreteColorScale(f; levels=nothing, order=nothing, preserve_order=true) = element_aesthetics(scale::DiscreteColorScale) = [:color] -function default_discrete_colors(n) - convert(Vector{Color}, - distinguishable_colors(n, [LCHab(70, 60, 240)], - transform=c -> deuteranopic(c, 0.5), - lchoices=Float64[65, 70, 75, 80], - cchoices=Float64[0, 50, 60, 70], - hchoices=linspace(0, 330, 24), - ) - ) -end # Common discrete color scales -function color_discrete_hue(f=default_discrete_colors; +function color_discrete_hue(f=Gadfly.current_theme().discrete_colormap; levels=nothing, order=nothing, preserve_order=true) @@ -541,18 +531,8 @@ ContinuousColorScale(f, trans=identity_transform; minvalue=nothing, maxvalue=not ContinuousColorScale(f, trans, minvalue, maxvalue) function continuous_color_scale_partial(trans::ContinuousScaleTransform) - lch_diverge2 = function(l0=30, l1=100, c=40, h0=260, h1=10, hmid=20, power=1.5) - lspan = l1 - l0 - hspan1 = hmid - h0 - hspan0 = h1 - hmid - function(r) - r2 = 2r - 1 - return LCHab(min(80, l1 - lspan * abs(r2)^power), max(10, c * abs(r2)), - (1-r)*h0 + r * h1) - end - end - function(; minvalue=nothing, maxvalue=nothing, colormap=lch_diverge2()) + function(; minvalue=nothing, maxvalue=nothing, colormap=Gadfly.current_theme().continuous_colormap) ContinuousColorScale(colormap, trans, minvalue=minvalue, maxvalue=maxvalue) end end diff --git a/src/statistics.jl b/src/statistics.jl index ab0f49f36..c6e6fa820 100644 --- a/src/statistics.jl +++ b/src/statistics.jl @@ -564,7 +564,7 @@ input_aesthetics(stat::Histogram2DStatistic) = [:x, :y] output_aesthetics(stat::Histogram2DStatistic) = [:xmin, :ymax, :ymin, :ymax, :color] default_scales(::Histogram2DStatistic, t::Gadfly.Theme=Gadfly.current_theme()) = - [t.continuous_color_scale] + [Scale.color_continuous()] const histogram2d = Histogram2DStatistic @@ -1219,7 +1219,7 @@ function apply_statistic(stat::HexBinStatistic, Scale.apply_scale(color_scale, [aes], data) end -default_scales(::HexBinStatistic, t::Gadfly.Theme) = [t.continuous_color_scale] +default_scales(::HexBinStatistic, t::Gadfly.Theme) = [Scale.color_continuous()] immutable StepStatistic <: Gadfly.StatisticElement @@ -1376,7 +1376,7 @@ const contour = ContourStatistic default_scales(::ContourStatistic, t::Gadfly.Theme=Gadfly.current_theme()) = [Gadfly.Scale.z_func(), Gadfly.Scale.x_continuous(), Gadfly.Scale.y_continuous(), - t.continuous_color_scale] + Scale.color_continuous()] function apply_statistic(stat::ContourStatistic, scales::Dict{Symbol, Gadfly.ScaleElement}, @@ -1729,7 +1729,7 @@ input_aesthetics(stat::VecFieldStatistic) = [:z, :x, :y, :color] output_aesthetics(stat::VecFieldStatistic) = [:x, :y, :xend, :yend, :color] default_scales(stat::VecFieldStatistic, t::Gadfly.Theme=Gadfly.current_theme()) = [Gadfly.Scale.z_func(), Gadfly.Scale.x_continuous(), Gadfly.Scale.y_continuous(), - t.continuous_color_scale ] + Scale.color_continuous() ] const vectorfield = VecFieldStatistic diff --git a/src/theme.jl b/src/theme.jl index 08df4077c..9fb7feb19 100755 --- a/src/theme.jl +++ b/src/theme.jl @@ -58,6 +58,30 @@ function get_stroke_vector(linestyle::Symbol) error("unsupported linestyle: ", linestyle) end + +function default_discrete_colors(n) + convert(Vector{Color}, + distinguishable_colors(n, [LCHab(70, 60, 240)], + transform=c -> deuteranopic(c, 0.5), + lchoices=Float64[65, 70, 75, 80], + cchoices=Float64[0, 50, 60, 70], + hchoices=linspace(0, 330, 24), + ) + ) +end + +lch_diverge2 = function(l0=30, l1=100, c=40, h0=260, h1=10, hmid=20, power=1.5) + lspan = l1 - l0 +# hspan1 = hmid - h0; hspan0 = h1 - hmid + function(r) + r2 = 2r - 1 + return LCHab(min(80, l1 - lspan * abs(r2)^power), max(10, c * abs(r2)), (1-r)*h0 + r * h1) + end +end + +default_continuous_colors = lch_diverge2() + + @varset Theme begin # If the color aesthetic is not mapped to anything, this is the color that # is used. @@ -202,11 +226,11 @@ end # Number of columns in key key_max_columns, Int, 4 - # Discrete color scale - discrete_color_scale, Scale.DiscreteColorScale, Scale.color_discrete() + # Discrete colormap + discrete_colormap, Function, default_discrete_colors - # Continuous color scale - continuous_color_scale, Scale.ContinuousColorScale, Scale.color_continuous() + # Continuous colormap + continuous_colormap, Function, default_continuous_colors end @@ -309,7 +333,7 @@ const dark_theme = let label_color=colorant"#a1a1a1", fgcol1=colorant"#FE4365", fgcol2=colorant"#eca25c", fgcol3=colorant"#3f9778", - fgcol4=colorant"#005D7F" + cpalette = [colorant"#005D7F", fgcol2, fgcol1] function border_color(fill_color) fill_color = convert(LCHab, fill_color) @@ -317,18 +341,6 @@ const dark_theme = let label_color=colorant"#a1a1a1", LCHab(60, 20, c.h) end - - function gen_dark_colors(n) - cs = distinguishable_colors(n, [fgcol1, fgcol2,fgcol3], - lchoices=Float64[58, 45, 72.5, 90], - transform=c -> deuteranopic(c, 0.1), - cchoices=Float64[20,40], - hchoices=[75,51,35,120,180,210,270,310] - ) - - convert(Vector{Color}, cs) - end - function lowlight_color(fill_color) fill_color = convert(LCHab, fill_color) c = LCHab(fill_color.l, fill_color.c, fill_color.h) @@ -336,40 +348,53 @@ const dark_theme = let label_color=colorant"#a1a1a1", RGBA(c2.r, c2.g, c2.b, .53) end - function dark_theme_discrete_colors(; - levels=nothing, - order=nothing, - preserve_order=true) - - Gadfly.Scale.DiscreteColorScale( - gen_dark_colors, - levels=levels, - order=order, - preserve_order=preserve_order + function dark_discrete_colors(n) + cs = distinguishable_colors(n, [fgcol1, fgcol2, fgcol3], + lchoices=Float64[58, 45, 72.5, 90], + transform=c -> deuteranopic(c, 0.1), + cchoices=Float64[20,40], + hchoices=[75,51,35,120,180,210,270,310] ) - end + convert(Vector{Color}, cs) + end + + Theme( + default_color= fgcol1, + stroke_color= default_stroke_color, + panel_fill= bgcolor, + major_label_color= label_color, + minor_label_color= label_color, + grid_color= grid_color, + key_title_color= label_color, + key_label_color= label_color, + lowlight_color= lowlight_color, + background_color= bgcolor, + discrete_highlight_color= border_color, + discrete_colormap= dark_discrete_colors, + continuous_colormap= Scale.lab_gradient(cpalette...), + ) +end + +get_theme(::Val{:dark}) = dark_theme - function dark_theme_continuous_colors() - Scale.color_continuous( - colormap=Scale.lab_gradient(fgcol4, fgcol2, fgcol1) - ) - end + +### ggplot theme + +const ggplot_theme = let fgcol1=LCHuv(30, 70, 12), + fgcol2=LCHuv(100, 0, 108), + cpalette = [ LCHuv(30, 70, 266), fgcol2, fgcol1] + + dpalette(n::Int) = LCHuv.(65, 100, 15:(360/n):374) Theme( - default_color=fgcol1, - stroke_color=default_stroke_color, - panel_fill=bgcolor, - major_label_color=label_color, - minor_label_color=label_color, - grid_color=grid_color, - key_title_color=label_color, - key_label_color=label_color, - lowlight_color=lowlight_color, - background_color=bgcolor, - discrete_highlight_color=border_color, - discrete_color_scale=dark_theme_discrete_colors(), - continuous_color_scale=dark_theme_continuous_colors(), + panel_fill= "gray92", + grid_color= "white", + grid_line_style= :solid, + discrete_colormap= dpalette, + continuous_colormap= Scale.lab_gradient(cpalette...) ) end -get_theme(::Val{:dark}) = dark_theme +get_theme(::Val{:ggplot}) = ggplot_theme + + diff --git a/test/testscripts/Theme_colormaps.jl b/test/testscripts/Theme_colormaps.jl new file mode 100644 index 000000000..1fb99b278 --- /dev/null +++ b/test/testscripts/Theme_colormaps.jl @@ -0,0 +1,27 @@ +using Colors, RDatasets, Gadfly + +set_default_plot_size(7inch, 3.3inch) + +dpalette(n::Int) = LCHab.(65, 100, 15:(360/n):374) +cpalette = [ LCHab(30, 70, 266), LCHab(100, 0, 108), LCHab(30, 70, 12)] + +mytheme = Theme(discrete_colormap= dpalette, continuous_colormap= Scale.lab_gradient(cpalette...) ) + + +Gadfly.with_theme(mytheme) do + + pa = plot(dataset("datasets","iris"), + x=:PetalWidth, y=:SepalLength, color=:Species, Geom.point, + Scale.color_discrete(order=[3,2,1]), + Guide.colorkey(title="Iris", pos=[0.1, 9.3]) + ) + + pb = plot(dataset("ggplot2","diamonds"), x=:Price, y=:Carat, + Geom.histogram2d(xbincount=25, ybincount=25), + Scale.color_log10, + Scale.x_continuous(format=:plain) + ) + + hstack(pa, pb) +end + \ No newline at end of file diff --git a/test/testscripts/density_dark.jl b/test/testscripts/density_dark.jl index d8a450ea3..9fedc5f72 100644 --- a/test/testscripts/density_dark.jl +++ b/test/testscripts/density_dark.jl @@ -5,7 +5,8 @@ set_default_plot_size(6inch, 3inch) global density_dark_tested p = Gadfly.with_theme(:dark) do - plot(dataset("ggplot2", "diamonds"), x="Price", color="Cut", Geom.density) + p = plot(dataset("ggplot2", "diamonds"), x="Price", color="Cut", Geom.density) + render(p) end # prevent these tests from running more than once diff --git a/test/testscripts/theme_ggplot.jl b/test/testscripts/theme_ggplot.jl new file mode 100644 index 000000000..c156b2754 --- /dev/null +++ b/test/testscripts/theme_ggplot.jl @@ -0,0 +1,22 @@ + +using RDatasets, Gadfly + +set_default_plot_size(7inch, 3.3inch) + +Gadfly.with_theme(:ggplot) do + + pa = plot(dataset("datasets","iris"), + x=:PetalWidth, y=:SepalLength, color=:Species, Geom.point, + Scale.color_discrete(order=[3,2,1]), + Guide.colorkey(title="Iris", pos=[0.1, 9.3]) + ) + + pb = plot(dataset("ggplot2","diamonds"), x=:Price, y=:Carat, + Geom.histogram2d(xbincount=25, ybincount=25), + Scale.color_log10, + Scale.x_continuous(format=:plain) + ) + + hstack(pa, pb) +end +