Skip to content
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

Scale.alpha_continuous and Scale.alpha_discrete #1252

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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 1.1.0
* Add `alpha` aesthetic, `Scale.alpha_continuous` and `Scale.alpha_discrete` (#1252)
* Add `limits=(min= , max= )` to `Stat.histogram` (#1249)
* Add dodged boxplots (#1246)
* Add `Stat.dodge` (#1240)
Expand Down
10 changes: 5 additions & 5 deletions docs/src/gallery/geometries.md
Original file line number Diff line number Diff line change
Expand Up @@ -412,13 +412,13 @@ x = -4:0.1:4
Da = [DataFrame(x=0:0.1:20, y=X[:,j], ymin=X[:,j].-0.5, ymax=X[:,j].+0.5, f="$f") for (j,f) in enumerate(["cos","sin"])]
Db = [DataFrame(x=x, ymax=pdf.(Normal(μ),x), ymin=0.0, u="μ=$μ") for μ in [-1,1] ]

# In the line below, 0.4 is the color opacity
p1 = plot(vcat(Da...), x=:x, y=:y, ymin=:ymin, ymax=:ymax, color=:f, Geom.line, Geom.ribbon,
Theme(lowlight_color=c->RGBA{Float32}(c.r, c.g, c.b, 0.4))
# In the line below, 0.6 is the color opacity
p1 = plot(vcat(Da...), x=:x, y=:y, ymin=:ymin, ymax=:ymax, color=:f,
Geom.line, Geom.ribbon, Theme(alphas=[0.6])
)
p2 = plot(vcat(Db...), x = :x, y=:ymax, ymin = :ymin, ymax = :ymax, color = :u,
p2 = plot(vcat(Db...), x = :x, y=:ymax, ymin = :ymin, ymax = :ymax,
color = :u, alpha=:u, Theme(alphas=[0.8,0.2]),
Geom.line, Geom.ribbon, Guide.ylabel("Density"),
Theme(lowlight_color=c->RGBA{Float32}(c.r, c.g, c.b, 0.4)),
Guide.colorkey(title="", pos=[2.5,0.6]), Guide.title("Parametric PDF")
)
hstack(p1,p2)
Expand Down
44 changes: 44 additions & 0 deletions docs/src/gallery/scales.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,49 @@
# Scales

## [`Scale.alpha_continuous`](@ref)

```@example
using Gadfly
set_default_plot_size(21cm, 8cm)
palettef = Scale.lab_gradient("darkgreen", "orange", "blue")
p1 = plot(x=1:10, y=rand(10), color=[1:10;], Geom.point,
Scale.color_continuous(colormap=palettef, minvalue=0, maxvalue=10),
Guide.title("Scale.color_continuous, Theme(alphas=[0.5])"),
Theme(alphas=[0.5], continuous_highlight_color=identity,
point_size=2mm)
)
p2 = plot(x=1:10, y=rand(10), alpha=[1:10;], Geom.point,
Scale.alpha_continuous(minvalue=0, maxvalue=10),
Guide.title("Scale.alpha_continuous, Theme(default_color=\"blue\")"),
Theme(default_color="blue", discrete_highlight_color=c->"gray",
point_size=2mm)
)
hstack(p1, p2)
```

## [`Scale.alpha_discrete`](@ref)

```@example
using DataFrames, Gadfly
set_default_plot_size(21cm, 8cm)
D = DataFrame(x=1:6, y=rand(6), Shape=repeat(["a","b","c"], outer=2))
coord = Coord.cartesian(xmin=0, xmax=7, ymin=0, ymax=1.0)
p1 = plot(D, x=:x, y=:y, color=:x, coord,
Scale.color_discrete, Geom.point, Geom.hair,
Guide.title("Scale.color_discrete, Theme(alphas=[0.5])"),
Theme(alphas=[0.5], discrete_highlight_color=identity,
point_size=2mm)
)
p2 = plot(D, x=:x, y=:y, alpha=:x, shape=:Shape, coord,
Scale.alpha_discrete, Geom.point, Geom.hair,
Guide.title("Scale.alpha_discrete, Theme(default_color=\"green\")"),
Theme(default_color="green", discrete_highlight_color=c->"gray",
point_size=2mm, alphas=[0.0,0.2,0.4,0.6,0.8,1.0])
)
hstack(p1,p2)
```


## [`Scale.color_continuous`](@ref)

```@example
Expand Down
13 changes: 5 additions & 8 deletions docs/src/gallery/statistics.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,15 @@ using Colors, DataFrames, Gadfly, Distributions
set_default_plot_size(21cm, 8cm)
x = -4:0.1:4
Da = [DataFrame(x=x, ymax=pdf.(Normal(μ),x), ymin=0.0, u="μ=$μ") for μ in [-1,1]]
Db = [DataFrame(x=randn(200).+μ, u="μ=$μ") for μ in [-1,1]]
Db = [DataFrame(x=randn(200).+μ, u="μ=$μ") for μ in [-1,1]]

p1 = plot(vcat(Da...), x=:x, y=:ymax, ymin=:ymin, ymax=:ymax, color=:u,
Geom.line, Geom.ribbon, Guide.ylabel("Density"),
Theme(lowlight_color=c->RGBA{Float32}(c.r, c.g, c.b, 0.4)),
Geom.line, Geom.ribbon, Guide.ylabel("Density"), Theme(alphas=[0.6]),
Guide.colorkey(title="", pos=[2.5,0.6]), Guide.title("Parametric PDF")
)
p2 = plot(vcat(Db...), x=:x, color=:u,
p2 = plot(vcat(Db...), x=:x, color=:u, Theme(alphas=[0.6]),
Stat.density(bandwidth=0.5), Geom.polygon(fill=true, preserve_order=true),
Coord.cartesian(xmin=-4, xmax=4),
Theme(lowlight_color=c->RGBA{Float32}(c.r, c.g, c.b, 0.4)),
Coord.cartesian(xmin=-4, xmax=4, ymin=0, ymax=0.4),
Guide.colorkey(title="", pos=[2.5,0.6]), Guide.title("Kernel PDF")
)
hstack(p1,p2)
Expand Down Expand Up @@ -88,8 +86,7 @@ p = plot(salaries[salaries.Rank.=="Prof",:], x=:YrsService, y=:Salary,
layer(Stat.smooth(method=:lm, levels=[0.95, 0.99]), Geom.line, Geom.ribbon)),
Scale.xgroup(levels=["Discipline A", "Discipline B"]),
Guide.colorkey(title="", pos=[0.43w, -0.4h]),
Theme(point_size=2pt,
lowlight_color=c->RGBA{Float32}(c.r, c.g, c.b, 0.2) )
Theme(point_size=2pt, alphas=[0.5] )
)
```

Expand Down
7 changes: 5 additions & 2 deletions docs/src/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ All aesthetics (e.g. `x`, `y`, `color`) have a Scale e.g. `Scale.x_continuous()`
| `x` | `x_continuous` | `xticks` |
| `y` | `y_continuous` | `yticks` |
| `color` | `color_continuous` | `colorkey` |
| `size` | `size_continuous` | sizekey (tbd) |
| `size` | `size_continuous` | sizekey (tbd) |
| `alpha` | `alpha_continuous` | alphakey (tbd) |

e.g. `Scale.x_continuous(format= , minvalue= , maxvalue= )`\
`format` can be: `:plain`, `:scientific`, `:engineering`, or `:auto`.
Expand Down Expand Up @@ -213,7 +214,8 @@ hstack(p3, p4)
| `shape` | `shape_discrete` | `shapekey` |
| `size` | `size_discrete` | sizekey (tbd) |
| `linestyle` | `linestyle_discrete` | linekey (tbd) |
| `group` | `group_discrete` | |
| `alpha` | `alpha_discrete` | alphakey (tbd) |
| `group` | `group_discrete` | |
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'm not sure the tables of Scales are appropriate in the Tutorial. they are all enumerated in the Library. we don't enumerate all Guides or Geoms. and listing them here disrupts the flow of teaching by example. i might submit a PR to smooth things out.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tables were introduced in a previous PR (#1245): http://gadflyjl.org/dev/tutorial/. The relationship between aesthetic, scales and guides is a generally not well understood, and hence these tables need to be in the tutorial.

| `xgroup` | `xgroup` | |
| `ygroup` | `ygroup` | |

Expand All @@ -236,6 +238,7 @@ hstack(p5, p6)
If you don't supply Scales or Guides, Gadfly will make an educated guess.

```@example 1
set_default_plot_size(14cm, 8cm) # hide
gasoline = dataset("Ecdat", "Gasoline")
plot(gasoline, x=:Year, y=:LGasPCar, color=:Country, Geom.point, Geom.line)
```
Expand Down
2 changes: 2 additions & 0 deletions src/Gadfly.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1146,6 +1146,7 @@ const default_aes_scales = Dict{Symbol, Dict}(
:size => Scale.size_continuous(),
:group => Scale.group_discrete(),
:label => Scale.label(),
:alpha => Scale.alpha_continuous(),
:linestyle => Scale.linestyle_discrete()
),

Expand All @@ -1166,6 +1167,7 @@ const default_aes_scales = Dict{Symbol, Dict}(
:size => Scale.size_discrete(),
:group => Scale.group_discrete(),
:label => Scale.label(),
:alpha => Scale.alpha_discrete(),
:linestyle => Scale.linestyle_discrete()
)
)
Expand Down
1 change: 1 addition & 0 deletions src/aesthetics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const NumericalAesthetic =
size, Union{CategoricalAesthetic,Vector,Nothing}
shape, Union{CategoricalAesthetic,Vector,Nothing}
color, Union{CategoricalAesthetic,Vector,Nothing}
alpha, NumericalOrCategoricalAesthetic
linestyle, Union{CategoricalAesthetic,Vector,Nothing}

label, CategoricalAesthetic
Expand Down
1 change: 1 addition & 0 deletions src/data.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
color
group
label
alpha
func
titles, Dict{Symbol, AbstractString}, Dict{Symbol, AbstractString}()
end
Expand Down
16 changes: 8 additions & 8 deletions src/gadfly.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 7 additions & 3 deletions src/geom/point.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Draw scatter plots of the `x` and `y` aesthetics.
"""
const point = PointGeometry

element_aesthetics(::PointGeometry) = [:x, :y, :size, :color, :shape]
element_aesthetics(::PointGeometry) = [:x, :y, :size, :color, :shape, :alpha]

# Generate a form for a point geometry.
#
Expand All @@ -48,6 +48,7 @@ function render(geom::PointGeometry, theme::Gadfly.Theme, aes::Gadfly.Aesthetics
default_aes.shape = Function[Shape.circle]
default_aes.color = discretize_make_ia(RGBA{Float32}[theme.default_color])
default_aes.size = Measure[theme.point_size]
default_aes.alpha = [theme.alphas[1]]
aes = inherit(aes, default_aes)

if eltype(aes.size) <: Int
Expand All @@ -57,9 +58,11 @@ function render(geom::PointGeometry, theme::Gadfly.Theme, aes::Gadfly.Aesthetics
interpolate_size(x) = theme.point_size_min + (x-size_min) / size_range * point_size_range
end

aes_alpha = eltype(aes.alpha) <: Int ? theme.alphas[aes.alpha] : aes.alpha

ctx = context()

for (x, y, color, size, shape) in Compose.cyclezip(aes.x, aes.y, aes.color, aes.size, aes.shape)
for (x, y, color, size, shape, alpha) in Compose.cyclezip(aes.x, aes.y, aes.color, aes.size, aes.shape, aes_alpha)
shapefun = typeof(shape) <: Function ? shape : theme.point_shapes[shape]
sizeval = typeof(size) <: Int ? interpolate_size(size) : size
strokecolor = aes.color_key_continuous != nothing && aes.color_key_continuous ?
Expand All @@ -68,7 +71,8 @@ function render(geom::PointGeometry, theme::Gadfly.Theme, aes::Gadfly.Aesthetics
class = svg_color_class_from_label(aes.color_label([color])[1])
compose!(ctx, (context(),
(context(), shapefun([x], [y], [sizeval]), svgclass("marker")),
fill(color), stroke(strokecolor), svgclass(class)))
fill(color), stroke(strokecolor), fillopacity(alpha),
svgclass(class)))
end

compose!(ctx, linewidth(theme.highlight_width))
Expand Down
16 changes: 11 additions & 5 deletions src/geom/polygon.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@ function render(geom::PolygonGeometry, theme::Gadfly.Theme, aes::Gadfly.Aestheti
default_aes.group = IndirectArray(fill(1,length(aes.x)))
default_aes.color = fill(theme.default_color, length(aes.x))
default_aes.linestyle = fill(1, length(aes.x))
default_aes.alpha = fill(1, length(aes.x))
aes = inherit(aes, default_aes)

aes_x, aes_y, aes_color, aes_linestyle, aes_group = concretize(aes.x, aes.y, aes.color, aes.linestyle, aes.group)
aes_x, aes_y, aes_color, aes_linestyle, aes_group, aes_alpha = concretize(aes.x, aes.y, aes.color, aes.linestyle, aes.group, aes.alpha)

XT, YT, CT, GT, LST = eltype(aes_x), eltype(aes_y), eltype(aes_color), eltype(aes_group), eltype(aes_linestyle)
XT, YT, CT, GT, LST, AT = eltype(aes_x), eltype(aes_y), eltype(aes_color), eltype(aes_group), eltype(aes_linestyle), eltype(aes_alpha)

groups = collect((Tuple{CT, GT, LST}), zip(aes_color, aes_group, aes_linestyle))
groups = collect((Tuple{CT, GT, LST, AT}), zip(aes_color, aes_group, aes_linestyle, aes_alpha))
ug = unique(groups)

n = length(ug)
Expand All @@ -69,20 +70,25 @@ function render(geom::PolygonGeometry, theme::Gadfly.Theme, aes::Gadfly.Aestheti
colors = Vector{CT}(undef, n)
line_styles = Vector{LST}(undef, n)
linestyle_palette_length = length(theme.line_style)
alphas = Vector{Float64}(undef, n)
alpha_discrete = AT <: Int

for (k,g) in enumerate(ug)
i = groups.==[g]
polys[k] = polygon_points(aes_x[i], aes_y[i], geom.preserve_order)
colors[k] = first(aes_color[i])
line_styles[k] = mod1(first(aes_linestyle[i]), linestyle_palette_length)
alphas[k] = first(alpha_discrete ? theme.alphas[aes_alpha[i]] : aes_alpha[i])
end

plinestyles = Gadfly.get_stroke_vector.(theme.line_style[line_styles])
pcolors = theme.lowlight_color.(colors)

properties = geom.fill ? (fill(pcolors), stroke(theme.discrete_highlight_color.(colors))) :
properties = geom.fill ? (fill(pcolors), stroke(theme.discrete_highlight_color.(colors)), fillopacity(alphas)) :
(fill(nothing), stroke(pcolors), strokedash(plinestyles))

ctx = compose!(context(order=geom.order), Compose.polygon(polys, geom.tag), properties...)
ctx = context(order=geom.order)
compose!(ctx, Compose.polygon(polys, geom.tag), properties...)

return compose!(ctx, linewidth(theme.line_width), svgclass("geometry"))
end
47 changes: 28 additions & 19 deletions src/geom/ribbon.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,36 @@ const ribbon = RibbonGeometry

default_statistic(geom::RibbonGeometry) = geom.default_statistic

element_aesthetics(::RibbonGeometry) = [:x, :ymin, :ymax, :color, :linestyle]
element_aesthetics(::RibbonGeometry) = [:x, :ymin, :ymax, :color, :linestyle, :alpha]

function render(geom::RibbonGeometry, theme::Gadfly.Theme, aes::Gadfly.Aesthetics)
Gadfly.assert_aesthetics_defined("Geom.ribbon", aes, :x, :ymin, :ymax)
Gadfly.assert_aesthetics_equal_length("Geom.ribbon", aes,
element_aesthetics(geom)...)
Gadfly.assert_aesthetics_equal_length("Geom.ribbon", aes, element_aesthetics(geom)...)

default_aes = Gadfly.Aesthetics()
default_aes.linestyle = fill(1, length(aes.x))
default_aes.color = fill(theme.default_color, length(aes.x))
default_aes.alpha = fill(1, length(aes.x))
aes = inherit(aes, default_aes)

aes_x, aes_ymin, aes_ymax, aes_color, aes_linestyle = concretize(aes.x, aes.ymin, aes.ymax, aes.color, aes.linestyle)
XT, CT, LST = eltype(aes_x), eltype(aes_color), eltype(aes_linestyle)
aes_x, aes_ymin, aes_ymax, aes_color, aes_linestyle, aes_alpha =
concretize(aes.x, aes.ymin, aes.ymax, aes.color, aes.linestyle, aes.alpha)
XT, CT, LST, AT = eltype(aes_x), eltype(aes_color), eltype(aes_linestyle), eltype(aes_alpha)
YT = Float64
groups = collect((Tuple{CT, LST}), zip(aes_color, aes_linestyle))
groups = collect((Tuple{CT, LST, AT}), zip(aes_color, aes_linestyle, aes_alpha))
ug = unique(groups)

V = Vector{Tuple{XT, YT}}
K = Tuple{CT, LST}
K = Tuple{CT, LST, AT}

max_points = Dict{K, V}(g=>V[] for g in ug)
for (x, y, c, ls) in zip(aes_x, aes_ymax, aes_color, aes_linestyle)
push!(max_points[(c,ls)], (x, y))
for (x, y, c, ls, a) in zip(aes_x, aes_ymax, aes_color, aes_linestyle, aes_alpha)
push!(max_points[(c,ls,a)], (x, y))
end

min_points = Dict{K, V}(g=>V[] for g in ug)
for (x, y, c, ls) in zip(aes_x, aes_ymin, aes_color, aes_linestyle)
push!(min_points[(c,ls)], (x, y))
for (x, y, c, ls, a) in zip(aes_x, aes_ymin, aes_color, aes_linestyle, aes_alpha)
push!(min_points[(c,ls,a)], (x, y))
end

for k in keys(max_points)
Expand All @@ -56,14 +57,22 @@ function render(geom::RibbonGeometry, theme::Gadfly.Theme, aes::Gadfly.Aesthetic
polys = [collect(Tuple{XT, YT}, Iterators.flatten((min_points[k], max_points[k]))) for k in kys]
lines = [collect(Tuple{XT, YT}, Iterators.flatten((min_points[k], [(last(min_points[k])[1], NaN)], max_points[k]))) for k in kys]

colors = [theme.lowlight_color(c) for (c,ls) in kys]
linestyles = [Gadfly.get_stroke_vector(theme.line_style[ls]) for (c,ls) in kys]
n = length(kys)
colors = Vector{Union{Colorant, String}}(undef, n)
linestyles = Vector{Vector{Measure}}(undef, n)
alphas = Vector{Float64}(undef, n)
alpha_discrete = AT <: Int

for (i, (c,ls,a)) in enumerate(kys)
colors[i] = theme.lowlight_color(c)
linestyles[i] = Gadfly.get_stroke_vector(theme.line_style[ls])
alphas[i] = alpha_discrete ? theme.alphas[a] : a
end

ctx = context()

ctx = geom.fill ? compose!(context(), Compose.polygon(polys, geom.tag), fill(colors)) :
compose!(context(), Compose.line(lines, geom.tag), fill(nothing), stroke(colors), strokedash(linestyles))
geom.fill ? compose!(ctx, Compose.polygon(polys, geom.tag), fill(colors), fillopacity(alphas)) :
compose!(ctx, Compose.line(lines, geom.tag), fill(nothing), stroke(colors), strokedash(linestyles))

return compose!(
ctx,
svgclass("geometry"),
linewidth(theme.line_width))
return compose!(ctx, svgclass("geometry"), linewidth(theme.line_width))
end
Loading