Skip to content

Commit

Permalink
Guide_shapekey
Browse files Browse the repository at this point in the history
  • Loading branch information
Mattriks committed Jun 7, 2018
1 parent f28c02c commit 47aae36
Show file tree
Hide file tree
Showing 9 changed files with 353 additions and 27 deletions.
4 changes: 2 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ This is a log of major changes in Gadfly between releases. It is not exhaustive.
Each release typically has a number of minor bug fixes beyond what is listed here.

# Version 0.7.1

* `Geom.contour`: add support for `DataFrame`.
* Add `Guide.shapekey` (#1156)
* `Geom.contour`: add support for `DataFrame` (#1150)

# Version 0.7.0

Expand Down
34 changes: 34 additions & 0 deletions docs/src/lib/guides/guide_shapekey.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
```@meta
Author = "Mattriks"
```

# Guide.shapekey

`Guide.shapekey` enables control of the fields of the auto-generated shapekey. Currently, you can change the shapekey title, the item labels, and position the shapekey inside the plot. The fields can be named e.g. `Guide.shapekey(title="Group", labels=["A","B"], pos=[0w,0h])`, or given in order e.g. `Guide.shapekey("Group", ["A","B"], [0w,0h])`.

## Arguments
* `title`: Legend title
* `labels`: Legend item labels
* `pos`: [x,y] position of the shapekey inside the plot. Setting `Guide.shapekey(pos=)` will override the `Theme(key_position=)` setting. Setting `Theme(key_position=:inside)` without setting `pos` will place the key in the lower right quadrant of the plot.

## Examples

```@setup 1
using RDatasets
using Compose
using Gadfly
Gadfly.set_default_plot_size(16cm, 8cm)
```

```@example 1
Dsleep = dataset("ggplot2", "msleep")
Dsleep = dropmissing!(Dsleep[[:Vore, :Name,:BrainWt,:BodyWt, :SleepTotal]])
Dsleep[:SleepTime] = Dsleep[:SleepTotal] .> 8
plot(Dsleep, x=:BodyWt, y=:BrainWt, Geom.point, color=:Vore, shape=:SleepTime,
Guide.colorkey(pos=[0.05w, -0.25h]),
Guide.shapekey(title="Sleep (hrs)", labels=[">8","≤8"], pos=[0.18w,-0.315h]),
Scale.x_log10, Scale.y_log10,
Theme(point_size=2mm, key_swatch_color="slategrey", point_shapes=[Shape.utriangle, Shape.dtriangle]),
)
```
6 changes: 4 additions & 2 deletions docs/src/man/themes.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,10 @@ These parameters can either be used with `Theme` or `style`
* `key_label_font_size`: Font size used for key entry labels. (Measure)
* `key_label_color`: Color used for key entry labels. (Color)
* `key_max_columns`: Maximum number of columns for key entry labels. (Int)
* `bar_spacing`: Spacing between bars in [Geom.bar](@ref). (Measure)
* `boxplot_spacing`: Spacing between boxplots in [Geom.boxplot](@ref). (Measure)
* `key_swatch_shape`: General purpose, will eventually replace `colorkey_swatch_shape` (Function as in `point_shapes`)
* `key_swatch_color`: General purpose, currently works for `Guide.shapekey` (Color)
* `bar_spacing`: Spacing between bars in [`Geom.bar`](@ref). (Measure)
* `boxplot_spacing`: Spacing between boxplots in [`Geom.boxplot`](@ref). (Measure)
* `errorbar_cap_length`: Length of caps on error bars. (Measure)
* `highlight_width`: Width of lines drawn around plot geometry like points,
and boxplot rectangles. (Measure)
Expand Down
58 changes: 39 additions & 19 deletions src/Gadfly.jl
Original file line number Diff line number Diff line change
Expand Up @@ -677,20 +677,35 @@ function render_prepare(plot::Plot)
layer_aess = Scale.apply_scales(IterTools.distinct(values(scales)),
datas..., subplot_datas...)

# set default labels
for (i, layer) in enumerate(plot.layers)
if layer_aess[i].color_key_title == nothing &&
haskey(layer.mapping, :color) &&
!isa(layer.mapping[:color], AbstractArray)
layer_aess[i].color_key_title = string(layer.mapping[:color])
end
# set defaults for key titles
keyvars = [:color, :shape]
for (i, layer) in enumerate(plot.layers)
for kv in keyvars
fflag = (getfield(layer_aess[i], Symbol(kv,"_key_title")) == nothing) && haskey(layer.mapping, kv) && !isa(layer.mapping[kv], AbstractArray)
fflag && setfield!(layer_aess[i], Symbol(kv,"_key_title"), string(layer.mapping[kv]))
end
end

for kv in keyvars
fflag = (getfield(layer_aess[1], Symbol(kv,"_key_title")) == nothing) && haskey(plot.mapping, kv) && !isa(plot.mapping[kv], AbstractArray)
fflag && setfield!(layer_aess[1], Symbol(kv,"_key_title"), string(plot.mapping[kv]))
end

if layer_aess[1].color_key_title == nothing &&
haskey(plot.mapping, :color) && !isa(plot.mapping[:color], AbstractArray)
layer_aess[1].color_key_title = string(plot.mapping[:color])
# Auto-update color scale if shape==color
catdatas = vcat(datas, subplot_datas)
shapev = getfield.(catdatas, :shape)
di = (shapev.!=nothing) .& (shapev.== getfield.(catdatas, :color))

supress_colorkey = false
for (aes, data) in zip(layer_aess[di], catdatas[di])
aes.shape_key_title==nothing && (aes.shape_key_title=aes.color_key_title="Shape")
colorf = scales[:color].f
scales[:color] = Scale.color_discrete(colorf, levels=scales[:shape].levels, order=scales[:shape].order)
Scale.apply_scale(scales[:color], [aes], Gadfly.Data(color=getfield(data,:color)) )
supress_colorkey=true
end


# IIa. Layer-wise statistics
if !facet_plot
for (stats, aes) in zip(layer_stats, layer_aess)
Expand All @@ -704,20 +719,25 @@ function render_prepare(plot::Plot)
Stat.apply_statistics(statistics, scales, coord, plot_aes)

# Add some default guides determined by defined aesthetics
supress_colorkey = false
keytypes = [Guide.ColorKey, Guide.ShapeKey]
supress_keys = false
for layer in plot.layers
if isa(layer.geom, Geom.SubplotGeometry) &&
haskey(layer.geom.guides, Guide.ColorKey)
supress_colorkey = true
if isa(layer.geom, Geom.SubplotGeometry) && any(haskey.(layer.geom.guides, keytypes))
supress_keys = true
break
end
end

if !supress_colorkey &&
!all([aes.color === nothing for aes in [plot_aes, layer_aess...]]) &&
!in(Guide.ColorKey, explicit_guide_types) &&
!in(Guide.ManualColorKey, explicit_guide_types)
push!(guides, Guide.colorkey())
if supress_colorkey
deleteat!(keytypes, 1)
deleteat!(keyvars, 1)
end

if !supress_keys
for (KT, kv) in zip(keytypes, keyvars)
fflag = !all([getfield(aes, kv)==nothing for aes in [plot_aes, layer_aess...]])
fflag && !in(KT, explicit_guide_types) && push!(guides, KT())
end
end

# build arrays of scaled aesthetics for layers within subplots
Expand Down
2 changes: 2 additions & 0 deletions src/aesthetics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const NumericalAesthetic =
color_key_continuous, Maybe(Bool)
color_function, Maybe(Function)
titles, Maybe(Dict{Symbol, AbstractString})
shape_key_title, Maybe(AbstractString)

# mark some ticks as initially invisible
xtickvisible, Maybe(Vector{Bool})
Expand All @@ -83,6 +84,7 @@ const NumericalAesthetic =
color_label, Function, showoff
xgroup_label, Function, showoff
ygroup_label, Function, showoff
shape_label, Function, showoff

# pseudo-aesthetics
pad_categorical_x, Nullable{Bool}, Nullable{Bool}()
Expand Down
75 changes: 71 additions & 4 deletions src/guide.jl
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,16 @@ ColorKey(;title=nothing, labels=nothing, pos=nothing) = ColorKey(title, labels,

# ColorKey() = ColorKey(nothing)

"""
Guide.colorkey[(; title=nothing, labels=nothing, pos=nothing)]
Guide.colorkey(title, labels, pos)
Enable control of the auto-generated colorkey. Set the colorkey `title` for
any plot, and the item `labels` for plots with a discrete color scale. `pos`
overrides [Theme(key_position=)](@ref Parameters) and can be in either
relative (e.g. [0.7w, 0.2h] is the lower right quadrant), absolute (e.g. [0mm,
0mm]), or plot scale (e.g. [0,0]) coordinates.
"""
const colorkey = ColorKey

# A helper for render(::ColorKey) for rendering guides for discrete color
Expand Down Expand Up @@ -356,7 +366,7 @@ function render_continuous_color_key(colors::Dict,
end


function render_colorkey_title(title::AbstractString, theme::Gadfly.Theme)
function render_key_title(title::AbstractString, theme::Gadfly.Theme)
title_width, title_height = max_text_extents(theme.key_title_font,
theme.key_title_font_size,
title)
Expand Down Expand Up @@ -433,7 +443,7 @@ function render(guide::ColorKey, theme::Gadfly.Theme,
pretty_labels[color] = join(labels[color], ", ")
end

title_context, title_width = render_colorkey_title(guide_title, theme)
title_context, title_width = render_key_title(guide_title, theme)

theme.colorkey_swatch_shape != :circle && theme.colorkey_swatch_shape != :square &&
error("$(theme.colorkey_swatch_shape) is not a valid color key swatch shape")
Expand Down Expand Up @@ -490,6 +500,11 @@ ManualColorKey(title, labels, colors::Vector{C}) where {C<:Color} =
ManualColorKey(title, labels, colors) =
ManualColorKey(title, labels, Gadfly.parse_colorant(colors))

"""
Guide.manual_color_key(title, labels, colors)
Manually define a color key with the legend `title` and item `labels` and `colors`.
"""
const manual_color_key = ManualColorKey

function render(guide::ManualColorKey, theme::Gadfly.Theme,
Expand All @@ -508,7 +523,7 @@ function render(guide::ManualColorKey, theme::Gadfly.Theme,
guide_title = "Color"
end

title_context, title_width = render_colorkey_title(guide_title, theme)
title_context, title_width = render_key_title(guide_title, theme)

labels = OrderedDict{Color, AbstractString}()
for (c, l) in zip(guide.colors, guide.labels)
Expand Down Expand Up @@ -546,6 +561,14 @@ end

XTicks(; label=true, ticks=:auto, orientation=:auto) = XTicks(label, ticks, orientation)

"""
Guide.xticks[(; label=true, ticks=:auto, orientation=:auto)]
Guide.xticks(label, ticks, orientation)
Formats the tick marks and labels for the x-axis. `label` toggles the label
visibility. `ticks` can also be an array of locations, or `nothing`.
`orientation` can also be `:horizontal` or `:vertical`.
"""
const xticks = XTicks

default_statistic(guide::XTicks) =
Expand Down Expand Up @@ -709,6 +732,14 @@ end

YTicks(; label=true, ticks=:auto, orientation=:horizontal) = YTicks(label, ticks, orientation)

"""
Guide.yticks[(; label=true, ticks=:auto, orientation=:horizontal)]
Guide.yticks(ticks, label, orientation)
Formats the tick marks and labels for the y-axis. `label` toggles the label
visibility. `ticks` can also be an array of locations, or `nothing`.
`orientation` can also be `:auto` or `:vertical`.
"""
const yticks = YTicks

function default_statistic(guide::YTicks)
Expand Down Expand Up @@ -881,6 +912,12 @@ struct XLabel <: Gadfly.GuideElement
end
XLabel(label; orientation=:auto) = XLabel(label, orientation)

"""
Guide.xlabel(label, orientation=:auto)
Sets the x-axis label for the plot. `label` is either a `String` or `nothing`.
`orientation` can also be `:horizontal` or `:vertical`.
"""
const xlabel = XLabel

function render(guide::XLabel, theme::Gadfly.Theme,
Expand Down Expand Up @@ -942,6 +979,12 @@ struct YLabel <: Gadfly.GuideElement
end
YLabel(label; orientation=:auto) = YLabel(label, orientation)

"""
Guide.ylabel(label, orientation=:auto)
Sets the y-axis label for the plot. `label` is either a `String` or `nothing`.
`orientation` can also be `:horizontal` or `:vertical`.
"""
const ylabel = YLabel


Expand Down Expand Up @@ -995,6 +1038,11 @@ struct Title <: Gadfly.GuideElement
label::Union{(Void), AbstractString}
end

"""
Geom.title(title)
Set the plot title.
"""
const title = Title

function render(guide::Title, theme::Gadfly.Theme,
Expand Down Expand Up @@ -1023,6 +1071,11 @@ end
struct XRug <: Gadfly.GuideElement
end

"""
Guide.xrug
Draw a short vertical lines along the x-axis of a plot at the positions in the `x` aesthetic.
"""
const xrug = XRug

function render(guide::XRug, theme::Gadfly.Theme,
Expand All @@ -1044,6 +1097,11 @@ end
struct YRug <: Gadfly.GuideElement
end

"""
Guide.yrug
Draw short horizontal lines along the y-axis of a plot at the positions in the 'y' aesthetic.
"""
const yrug = YRug

function render(guide::YRug, theme::Gadfly.Theme,
Expand Down Expand Up @@ -1181,6 +1239,12 @@ struct Annotation <: Gadfly.GuideElement
ctx::Context
end

"""
Guide.annotation(ctx::Compose.Context)
Overlay a plot with an arbitrary `Compose` graphic. The context will inherit
the plot's coordinate system, unless overridden with a custom unit box.
"""
const annotation = Annotation

function render(guide::Annotation, theme::Gadfly.Theme,
Expand All @@ -1190,4 +1254,7 @@ function render(guide::Annotation, theme::Gadfly.Theme,
end


end # module Guide
include("guide/keys.jl")


end # module Guide
Loading

0 comments on commit 47aae36

Please sign in to comment.