From da38bd88db141e00d3584fc9ee6f389c812ed7eb Mon Sep 17 00:00:00 2001 From: Ben Arthur Date: Sun, 15 Apr 2018 19:32:35 -0400 Subject: [PATCH] rephrase docstrings to remove explicit Arguments section --- docs/src/dev/regression.md | 2 +- docs/src/gallery/geometries.md | 4 +- docs/src/lib/statistics.md | 2 +- src/Gadfly.jl | 124 ++++++---------- src/geom/bar.jl | 69 ++++----- src/geom/beeswarm.jl | 18 +-- src/geom/boxplot.jl | 39 ++--- src/geom/errorbar.jl | 37 ++--- src/geom/hexbin.jl | 22 +-- src/geom/hvabline.jl | 23 +-- src/geom/label.jl | 26 +--- src/geom/line.jl | 119 +++++---------- src/geom/point.jl | 25 +++- src/geom/polygon.jl | 50 +++---- src/geom/rectbin.jl | 52 ++----- src/geom/ribbon.jl | 9 +- src/geom/segment.jl | 63 ++------ src/geom/violin.jl | 2 +- src/guide.jl | 103 ++++--------- src/poetry.jl | 53 +------ src/scale.jl | 260 ++++++++++----------------------- src/statistics.jl | 250 +++++++++++++------------------ src/theme.jl | 19 ++- 23 files changed, 453 insertions(+), 918 deletions(-) diff --git a/docs/src/dev/regression.md b/docs/src/dev/regression.md index 79a6aa9b2..8e0c3f5e0 100644 --- a/docs/src/dev/regression.md +++ b/docs/src/dev/regression.md @@ -28,6 +28,6 @@ So the automated regression analysis workflow is then as follows: 6. `Pkg.test` again, 7. `Pkg.add("ArgParse")` and, for B&W images, Cairo, Fontconfig, Rsvg, and Images as well, 8. check for differences with `julia test/compare_examples.jl [--diff] [--two] -[--bw] [-h] [filter]`. For example, `julia test/compare_examples.jl -bw +[--bw] [-h] [filter]`. For example, `julia test/compare_examples.jl --bw .js.svg` will show black and white images hightlighting the differences between the svg test images. diff --git a/docs/src/gallery/geometries.md b/docs/src/gallery/geometries.md index 8be454ddb..68f903e1f 100644 --- a/docs/src/gallery/geometries.md +++ b/docs/src/gallery/geometries.md @@ -63,10 +63,10 @@ plot(dataset("lattice", "singer"), x="VoicePart", y="Height", Geom.boxplot) ## Geom.contour ```@example -using Gadfly, RDatasets +using Gadfly set_default_plot_size(14cm, 8cm) plot(z=(x,y) -> x*exp(-(x-round(Int, x))^2-y^2), - x=linspace(-8,8,150), y=linspace(-2,2,150), Geom.contour) + xmin=[-8], xmax=[8], ymin=[-2], ymax=[2], Geom.contour) ``` ```@example diff --git a/docs/src/lib/statistics.md b/docs/src/lib/statistics.md index b2b17c5f7..c9d990273 100644 --- a/docs/src/lib/statistics.md +++ b/docs/src/lib/statistics.md @@ -5,7 +5,7 @@ Author = "Daniel C. Jones" # [Statistics](@id lib_stat) Statistics are functions taking as input one or more aesthetics, operating on -those values, then output to one or more aesthetics. For example, drawing of +those values, then outputting to one or more aesthetics. For example, drawing of boxplots typically uses the boxplot statistic ([`Stat.boxplot`](@ref)) that takes as input the `x` and `y` aesthetic, and outputs the middle, and upper and lower hinge, and upper and lower fence aesthetics. diff --git a/src/Gadfly.jl b/src/Gadfly.jl index 576df56e1..ca0c43443 100644 --- a/src/Gadfly.jl +++ b/src/Gadfly.jl @@ -69,6 +69,15 @@ default_scales(x::Any, t) = default_scales(x) default_statistic(::Any) = Stat.identity() element_coordinate_type(::Any) = Coord.cartesian +function aes2str(aes) + list = join([string('`',x,'`') for x in aes], ", ", " and ") + if length(aes)>1 + return string(list," aesthetics") + else + return string(list," aesthetic") + end +end + abstract type Element end abstract type ScaleElement <: Element end @@ -102,7 +111,8 @@ const gadflyjs = joinpath(dirname(Base.source_path()), "gadfly.js") """ set_default_plot_size(width::Compose.MeasureOrNumber, height::Compose.MeasureOrNumber) -Sets preferred canvas size when rendering a plot without an explicit call to draw +Sets preferred canvas size when rendering a plot without an explicit call to draw. Units +can be `inch`, `cm`, `mm`, `pt`, or `px`. """ set_default_plot_size(width::Compose.MeasureOrNumber, height::Compose.MeasureOrNumber) = Compose.set_default_graphic_size(width, height) @@ -111,7 +121,7 @@ set_default_plot_size(width::Compose.MeasureOrNumber, height::Compose.MeasureOrN """ set_default_plot_format(fmt::Symbol) -Sets the default plot format +Sets the default plot format. (NOT SURE THIS DOES ANYTHING.) """ set_default_plot_format(fmt::Symbol) = Compose.set_default_graphic_format(fmt) @@ -133,18 +143,15 @@ copy(l::Layer) = Layer(l) """ - layer(data_source::@compat(Union{AbstractDataFrame, (@compat Void)}), - elements::ElementOrFunction...; mapping...) + layer(data_source::Union{AbstractDataFrame, Void}), + elements::ElementOrFunction...; mapping...) -> [Layers] Creates layers based on elements -### Args -* data_source: The data source as a dataframe -* elements: The elements -* mapping: mapping - -### Returns -An array of layers +# Args +- data_source: The data source as a dataframe +- elements: The elements +- mapping: mapping """ function layer(data_source::Union{AbstractDataFrame, (Void)}, elements::ElementOrFunction...; mapping...) @@ -244,24 +251,6 @@ add_plot_element!(p::Plot, f::Type{T}) where {T <: Element} = add_plot_element!( add_plot_element!(p::Plot, theme::Theme) = p.theme = theme -# Create a new plot. -# -# Grammar of graphics style plotting consists of specifying a dataset, one or -# more plot elements (scales, coordinates, geometries, etc), and binding of -# aesthetics to columns or expressions of the dataset. -# -# For example, a simple scatter plot would look something like: -# -# plot(my_data, Geom.point, x="time", y="price") -# -# Where "time" and "price" are the names of columns in my_data. -# -# Args: -# data_source: Data to be bound to aesthetics. -# mapping: Aesthetics symbols (e.g. :x, :y, :color) mapped to -# names of columns in the data frame or other expressions. -# elements: Geometries, statistics, etc. - # because a call to layer() expands to a vector of layers (one for each Geom # supplied), we need to allow Vector{Layer} to count as an Element for the # purposes of plot(). @@ -269,10 +258,8 @@ const ElementOrFunctionOrLayers = Union{ElementOrFunction, Vector{Layer}} """ -``` - plot(data_source::@compat(Union{AbstractMatrix, AbstractDataFrame}), + plot(data_source::Union{AbstractMatrix, AbstractDataFrame}, elements::ElementOrFunctionOrLayers...; mapping...) -``` Create a new plot. @@ -282,14 +269,14 @@ aesthetics to columns or expressions of the dataset. For example, a simple scatter plot would look something like: -plot(my_data, Geom.point, x="time", y="price") + plot(my_data, Geom.point, x=:time, y=:price) -Where "time" and "price" are the names of columns in my_data. +Where `:time` and `:price` are the names of columns in my_data. -### Args: -* data_source: Data to be bound to aesthetics. -* elements: Geometries, statistics, etc. -* mapping: Aesthetics symbols (e.g. :x, :y, :color) mapped to names of columns in the data frame or other expressions. +# Args: +- data_source: Data to be bound to aesthetics. +- elements: Geometries, statistics, etc. +- mapping: Aesthetics symbols (e.g. :x, :y, :color) mapped to names of columns in the data frame or other expressions. """ function plot(data_source::Union{AbstractArray, AbstractDataFrame}, elements::ElementOrFunctionOrLayers...; mapping...) @@ -304,39 +291,22 @@ function plot(elements::ElementOrFunctionOrLayers...; mapping...) end -# The old fashioned (pre named arguments) version of plot. -# -# This version takes an explicit mapping dictionary, mapping aesthetics symbols -# to expressions or columns in the data frame. -# -# Args: -# data_source: Data to be bound to aesthetics. -# mapping: Dictionary of aesthetics symbols (e.g. :x, :y, :color) to -# names of columns in the data frame or other expressions. -# elements: Geometries, statistics, etc. -# -# Returns: -# A Plot object. -# """ - plot(data_source::@compat(Union{(@compat Void), AbstractMatrix, AbstractDataFrame}), - mapping::Dict, elements::ElementOrFunctionOrLayers...) + plot(data_source::Union{Void, AbstractMatrix, AbstractDataFrame}, + mapping::Dict, elements::ElementOrFunctionOrLayers...) -> Plot The old fashioned (pre named arguments) version of plot. This version takes an explicit mapping dictionary, mapping aesthetics symbols to expressions or columns in the data frame. -### Args: -* data_source: Data to be bound to aesthetics. -* mapping: Dictionary of aesthetics symbols (e.g. :x, :y, :color) to +# Args: +- data_source: Data to be bound to aesthetics. +- mapping: Dictionary of aesthetics symbols (e.g. :x, :y, :color) to names of columns in the data frame or other expressions. -* elements: Geometries, statistics, etc. - -### Returns: -A Plot object. +- elements: Geometries, statistics, etc. """ -function plot(data_source::Union{(Void), AbstractArray, AbstractDataFrame}, +function plot(data_source::Union{Void, AbstractArray, AbstractDataFrame}, mapping::Dict, elements::ElementOrFunctionOrLayers...) mapping = cleanmapping(mapping) p = Plot() @@ -735,16 +705,9 @@ function render_prepare(plot::Plot) end """ -``` -render(plot::Plot) -``` -Render a plot based on the Plot object - -### Args -* plot: Plot to be rendered. + render(plot::Plot) -> Context -### Returns -A Compose context containing the rendered plot. +Render `plot` to a `Compose` context. """ function render(plot::Plot) (plot, coord, plot_aes, @@ -855,17 +818,14 @@ end draw(backend::Compose.Backend, p::Plot) A convenience version of Compose.draw without having to call render - -### Args -* backend: The Compose.Backend object -* p: The Plot object """ draw(backend::Compose.Backend, p::Plot) = draw(backend, render(p)) """ title(ctx::Context, str::String, props::Property...) -> Context -Add a title string to a group of plots, typically created with `vstack`, `hstack`, or `gridstack`. +Add a title string to a group of plots, typically created with `vstack`, +`hstack`, or `gridstack`. # Examples @@ -884,7 +844,9 @@ title(ctx::Context, str::String, props::Compose.Property...) = vstack( vstack(ps::Union{Plot,Context}...) vstack(ps::Vector) -Arrange plots into a vertical column. Use `context()` as a placeholder for an empty panel. Heterogeneous vectors must be typed. See also `hstack`, `gridstack`, `subplot_grid`. +Arrange plots into a vertical column. Use `context()` as a placeholder for an +empty panel. Heterogeneous vectors must be typed. See also `hstack`, +`gridstack`, `subplot_grid`. # Examples @@ -902,7 +864,9 @@ vstack(ps::Vector{Union{Plot,Context}}) = vstack(ps...) hstack(ps::Union{Plot,Context}...) hstack(ps::Vector) -Arrange plots into a horizontal row. Use `context()` as a placeholder for an empty panel. Heterogeneous vectors must be typed. See also `vstack`, `gridstack`, `subplot_grid`. +Arrange plots into a horizontal row. Use `context()` as a placeholder for an +empty panel. Heterogeneous vectors must be typed. See also `vstack`, +`gridstack`, `subplot_grid`. # Examples @@ -919,7 +883,9 @@ hstack(ps::Vector{Union{Plot,Context}}) = hstack(ps...) """ gridstack(ps::Matrix{Union{Plot,Context}}) -Arrange plots into a rectangular array. Use `context()` as a placeholder for an empty panel. Heterogeneous matrices must be typed. See also `hstack`, `vstack`. +Arrange plots into a rectangular array. Use `context()` as a placeholder for +an empty panel. Heterogeneous matrices must be typed. See also `hstack`, +`vstack`. # Examples diff --git a/src/geom/bar.jl b/src/geom/bar.jl index 272e7f365..21811b25e 100644 --- a/src/geom/bar.jl +++ b/src/geom/bar.jl @@ -11,58 +11,39 @@ BarGeometry(; position=:stack, orientation=:vertical, tag=empty_tag) = """ - Geom.bar[(; position, orientation)] + Geom.bar[(; position=:stack, orientation=:vertical)] -Draw bar plots. This geometry works on pre-summarized data such as counts. To -draw histograms from a series of observations, add [`Stat.histogram`](@ref) to the plot, -or use the convenient geometry [`Geom.histogram`](@ref). +Draw bars of height `y` centered at positions `x`, or from `xmin` to `xmax`. +If orientation is `:horizontal` switch x for y. -# Aesthetics -- `y`: Height of each bar. -- `color` (optional): Group categorically by color. +Optionally categorically groups bars using the `color` aesthetic. If +`position` is `:stack` they will placed on top of each other; if it is +`:dodge` they will be placed side by side. -Either - -- `x`: Position of each bar. - -Or +To draw histograms from a series of observations, instead of counts, add +[`Stat.histogram`](@ref) to the plot, or use the convenient geometry +[`Geom.histogram`](@ref). +""" +const bar = BarGeometry -- `xmin`: Starting x positions for each bar. -- `xmax`: End x positions for each bar. +""" + Geom.histogram[(; position=:stack, bincount=nothing, + minbincount=3, maxbincount=150, + orientation=:vertical, density=false)] -If `x` is given, a bar will be drawn at each x value, specifying both `xmin` and -`xmax` allows bars of variable width to be drawn. +Plot histograms of the `x` aesthetic if `orientation` is `:vertical`, or the `y` +aesthetic if it is `:horizontal`. Optionally group by the `color` aesthetic, +in which case the bars are arranged on top of each other if `position` is +`:stack`, or placed side by side if it is `:dodge`. -# Arguments -- `position`: Either `:stack` or `:dodge`. If the `color` aesthetic is - bound this determines how bars of different colors should be arranged: - stacked on top of each other, or placed side by side. +Alternatively, if `density` is true, plot a line showing continuous density +rather than discrete bars of counts. -- `orientation`: Either `:vertical` (default) or `:horizontal`. If - `:horizontal`, then the required aesthetics are `y` or `ymin/ymax`. -""" -const bar = BarGeometry +`bincount` specifies the number of bins to use. If set to `nothing`, an +optimization method is used to determine a reasonable value which uses +`minbincount` and `maxbincount` to set the lower and upper limits. -""" - Geom.histogram[(; position, orientation, bincount, minbincount, maxbincount, density)] - -Draw histograms. An alias for [`Geom.bar`](@ref) with [`Stat.histogram`](@ref). - -# Aesthetics -- `x`: Sample to draw histogram from. -- `color` (optional): Group categorically by color. - -# Arguments -- `position`: Either `:stack` or `:dodge`. If the `color` aesthetic is - bound this determines how bars of different colors should be arranged: - stacked on top of each other, or placed side by side. -- `orientation`: Either `:vertical` (default) or `:horizontal`. If - `:horizontal`, then the required aesthetic is `y` instead of `x`. -- `bincount`: Number of bins to use. If unspecified, an optimization method - is used to determine a reasonable value. -- `minbincount`: Set a lower limit when automatically choosing a bin count. -- `maxbincount`: Set an upper limit when automatically choosing a bin count. -- `density`: If true, use density rather that counts. +An alias for [`Geom.bar`](@ref) with [`Stat.histogram`](@ref). """ histogram(; position=:stack, bincount=nothing, minbincount=3, maxbincount=150, diff --git a/src/geom/beeswarm.jl b/src/geom/beeswarm.jl index 8e929f45f..5b40a5b51 100644 --- a/src/geom/beeswarm.jl +++ b/src/geom/beeswarm.jl @@ -8,20 +8,12 @@ BeeswarmGeometry(; orientation=:vertical, padding=0.1mm, tag=empty_tag) = BeeswarmGeometry(orientation, padding, tag) """ - Geom.beeswarm[; (orientation,padding)] + Geom.beeswarm[; (orientation=:vertical, padding=0.1mm)] -Plot points, shifting them on the x- or y-axis to avoid overlaps. - -# Aesthetics -- `x`: X-axis position. -- `y`: Y-axis position. -- `color` (optional): Point color (categorial or continuous). - -# Arguments -- `orientation`: `:horizontal` or `:vertical`. Points will be shifted on the - y-axis to avoid overlap if orientation in horizontal, and on the x-axis, if - vertical. -- `padding`: Minimum distance between two points. +Plot the `x` and `y` aesthetics, the former being categorical, by shifting the +x position of each point to ensure that there is at least `padding` gap between +neighbors. If `orientation` is `:horizontal`, switch x for y. Points +can optionally be colored using the `color` aesthetic. """ const beeswarm = BeeswarmGeometry diff --git a/src/geom/boxplot.jl b/src/geom/boxplot.jl index 829802dfb..9dafaf82f 100644 --- a/src/geom/boxplot.jl +++ b/src/geom/boxplot.jl @@ -4,48 +4,27 @@ struct BoxplotGeometry <: Gadfly.GeometryElement tag::Symbol end - BoxplotGeometry(; method=:tukey, suppress_outliers=false, tag=empty_tag) = BoxplotGeometry(Gadfly.Stat.boxplot(method=method), suppress_outliers, tag) - """ - Geom.boxplot[(; suppress_outliers, method)] - -Draw boxplots. - -# Aesthetics - -Aesthetics used directly: - -- `x` -- `middle` -- `lower_hinge` -- `upper_hinge` -- `lower_fence` -- `upper_fence` -- `outliers` - -With default statistic [`Stat.boxplot`](@ref), only the following aesthetics need to be -defined: - -- `x` (optional): Group categorically on the X-axis. -- `y`: Sample from which to draw the boxplot. + Geom.boxplot[(; method=:tukey, suppress_outliers=false)] +Draw box plots of the `middle`, `lower_hinge`, `upper_hinge`, `lower_fence`, +`upper_fence`, and `outliers` aesthetics. The categorical `x` aesthetic is +optional. If `suppress_outliers` is true, don't draw points indicating +outliers. -# Arguments -- `suppress_outliers`: If true, don't draw points indicating outliers. (Default is false.) -- `method`: How boxplot statistics are computed. Either `:tukey` (default) - which uses Tukey's rule (i.e. fences are 1.5 times inter-quartile range), or - a vector of 5 numbers giving quantiles for lower fence, lower hinge, middle, - upper hinge, and upper fence in that order. +Alternatively, if the `y` aesthetic is specified instead, the middle, hinges, +and fences aesthetics will be computed using [`Stat.boxplot`](@ref). """ const boxplot = BoxplotGeometry element_aesthetics(::BoxplotGeometry) = [:x, :y, :color, :middle, :upper_fence, :lower_fence, - :upper_hinge, :lower_hinge] + :upper_hinge, :lower_hinge, + :outliers] default_statistic(geom::BoxplotGeometry) = geom.default_statistic diff --git a/src/geom/errorbar.jl b/src/geom/errorbar.jl index 96c5a5be2..6cf81bb17 100644 --- a/src/geom/errorbar.jl +++ b/src/geom/errorbar.jl @@ -17,45 +17,28 @@ YErrorBarGeometry(; tag=empty_tag) = YErrorBarGeometry(tag) """ Geom.errorbar -Draw vertical and/or horizontal error bars. - -# Aesthetics -- `x`: X-position of the bar. -- `ymin`: Lower Y-position. -- `ymax`: Upper Y-position. -- `y`: Y-position of the bar. -- `xmin`: Left-most X-position -- `ymax`: Right-most X-position. -- `color` (optional): Bar color (categorial or continuous) - -The `x`, `ymin`, `ymax` and/or `y`, `xmin`, `xmax` aesthetics must be defined. -With the later a vertical error bar is drawn, and the former, a horizontal bar. +Draw vertical error bars if the `x`, `ymin`, and `ymax` aesthetics +are specified and/or horizontal error bars for `y`, `xmin`, and `xmax`. +Optionally color them with `color`. + +See also [`Geom.xerrorbar`](@ref) and [`Geom.yerrorbar`](@ref). + """ const errorbar = ErrorBarGeometry """ Geom.xerrorbar -Draw vertical error bars. - -# Aesthetics -- `y`: Y-position of the bar. -- `xmin`: Left-most X-position -- `xmax`: Right-most X-position. -- `color` (optional): Bar color (categorial or continuous) +Draw horizontal error bars at `y` from `xmin` to `xmax`. Optionally +color them with `color`. """ const xerrorbar = XErrorBarGeometry """ Geom.yerrorbar -Draw horizontal error bars. - -# Aesthetics -- `x`: X-position of the bar. -- `ymin`: Lower Y-position. -- `ymax`: Upper Y-position. -- `color` (optional): Bar color (categorial or continuous) +Draw vertical error bars at `x` from `ymin` to `ymax`. Optionally +color them with `color`. """ const yerrorbar = YErrorBarGeometry diff --git a/src/geom/hexbin.jl b/src/geom/hexbin.jl index 84495b397..fe44a6a29 100644 --- a/src/geom/hexbin.jl +++ b/src/geom/hexbin.jl @@ -10,23 +10,15 @@ HexagonalBinGeometry(; xbincount=200, ybincount=200, tag=empty_tag) = HexagonalBinGeometry(Gadfly.Stat.hexbin(xbincount=xbincount, ybincount=ybincount), tag) """ - Geom.hexbin[(; xbincount, ybincount)] + Geom.hexbin[(; xbincount=200, ybincount=200)] -Bin data into tiled hexagonal bins and color by count. +Bin the `x` and `y` aesthetics into tiled hexagons and color by count. +`xbincount` and `ybincount` specify the number of bins. This behavior relies +on the default use of [`Stat.hexbin`](@ref). -# Aesthetics -- `x`: Observations to be binned and plotted on the x-axis. -- `y`: Observations to be binned and plotted on the y-axis. -- `xsize` -- `ysize` - -By default [`Stat.hexbin`](@ref) is applied which bins `x` and `y` observations and -colors hexagons according to count. To override this, pass [`Stat.identity`](@ref) to -`plot` and manually bind the `color` aesthetic. - -# Arguments -- `xbincount`: Number of bins along the x-axis. -- `ybincount`: Number of bins along the y-axis. +Alternatively, draw hexagons of size `xsize` and `ysize` at positions `x` and +`y` by passing [`Stat.identity`](@ref) to `plot` and manually binding the `color` +aesthetic. """ const hexbin = HexagonalBinGeometry diff --git a/src/geom/hvabline.jl b/src/geom/hvabline.jl index 7490eda3e..04a8cced7 100755 --- a/src/geom/hvabline.jl +++ b/src/geom/hvabline.jl @@ -24,12 +24,9 @@ HLineGeometry(; color=nothing, size=nothing, style=nothing, tag=empty_tag) = HLineGeometry(color, size, style, tag) """ - Geom.hline[(; color,size,style)] + Geom.hline[(; color=nothing, size=nothing, style=nothing)] -Draw horizontal lines across the plot canvas. - -## Aesthetics -- `yintercept`: Y-axis intercept +Draw horizontal lines across the plot canvas at each position in `yintercept`. """ const hline = HLineGeometry @@ -74,12 +71,9 @@ VLineGeometry(; color=nothing, size=nothing, style=nothing, tag=empty_tag) = VLineGeometry(color, size, style, tag) """ - Geom.vline[(; color,size,style)] - -Draw vertical lines across the plot canvas. + Geom.vline[(; color=nothing, size=nothing, style=nothing)] -## Aesthetics -- `xintercept`: X-axis intercept +Draw vertical lines across the plot canvas at each position in `xintercept`. """ const vline = VLineGeometry @@ -124,16 +118,13 @@ ABLineGeometry(; color=nothing, size=nothing, style=nothing, tag::Symbol=empty_t ABLineGeometry(color, size, style, tag) """ - Geom.abline[(; color, size, style)] + Geom.abline[(; color=nothing, size=nothing, style=nothing)] For each corresponding pair of elements in `intercept` and `slope`, draw the -lines `y = slope * x + intercept` across the plot canvas. +lines `y = slope * x + intercept` across the plot canvas. If unspecified, +`intercept` defaults to [0] and `slope` to [1]. Currently does not support non-linear `Scale` transformations. - -## Aesthetics -- `intercept`: Y-axis intercepts, defaults to [0] -- `slope`: rise over run, defaults to [1] """ abline = ABLineGeometry diff --git a/src/geom/label.jl b/src/geom/label.jl index 5456eac63..5f7cc40fd 100644 --- a/src/geom/label.jl +++ b/src/geom/label.jl @@ -19,26 +19,12 @@ element_aesthetics(::LabelGeometry) = [:x, :y, :label] default_statistic(::LabelGeometry) = Gadfly.Stat.identity() """ - Geom.label[(; position, hide_overlaps)] - -Label positions on the plot frame. - -This geometry attemps to optimize label positioning so that labels do not -overlap, and hides any that would overlap. - -# Aesthetics -- `x`: X-axis position. -- `y`: Y-axis position. -- `label`: Text to render. - -# Arguments -- `position`: One of `:dynamic`, `:left`, `:right`, `:above`, `:below`, - `:centered`. If `:dynamic` is used, label positions will be adjusted to - avoid overaps. Otherwise, labels will be statically positioned left, right, - above, below, or centered relative to the point. -- `hide_overlaps`: If true, and dynamic positioning is used, labels that would - otherwise overlap another label or be drawn outside the plot panel are - hidden. (default: true) + Geom.label[(; position=:dynamic, hide_overlaps=true)] + +Place the text strings in the `label` aesthetic at the `x` and `y` coordinates +on the plot frame. Offset the text according to `position`, which can be +`:left`, `:right`, `:above`, `:below`, `:centered`, or `:dynamic`. The latter +tries a variety of positions for each label to minimize the number that overlap. """ const label = LabelGeometry diff --git a/src/geom/line.jl b/src/geom/line.jl index 47299b7bd..561ad5843 100644 --- a/src/geom/line.jl +++ b/src/geom/line.jl @@ -17,40 +17,22 @@ function LineGeometry(default_statistic=Gadfly.Stat.identity(); end """ - Geom.line[(; preserve_order)] - -# Aesthetics -- `x`: X-axis position. -- `y`: Y-axis position. -- `group` (optional): Group categorically. -- `color` (optional): Group categorically and indicate by color. - -# Arguments -- `preserve_order`: Default behavior for `Geom.line` is to draw lines between - points in order along the x-axis. If this option is true, lines will be - drawn between points in the order they appear in the data. `Geom.path()` is - `Geom.line(preserve_order=true)`. + Geom.line[(; preserve_order=false, order=2)] ### zorder would be more descriptive + +Draw a line connecting the `x` and `y` coordinates. Optionally plot multiple +lines according to the `group` or `color` aesthetics. `order` controls whether +the lines(s) are underneath or on top of other forms. + +Set `preserve_order` to `:true` to *not* sort the points according to their +position along the x axis, or use the equivalent [`Geom.path`](@ref) alias. """ const line = LineGeometry """ - Geom.contours[(; levels)] - -Draw contours of a 2D function or a matrix. - -# Aesthetics -- `z`: 2D function or a matrix that represent "heights" relative to - to the x-y plane. -- `x` (optional): Vector of X-coordinates. If `z` is a matrix, then - the length of `x` must be equal to the number of *rows* in `z`. -- `y` (optional): Vector of Y-coordinates. If `z` is a matrix, then - the length of `y` must be equal to the number of *columns* in `z`. - -# Arguments -- `levels` (optional): Sets the number of contours to draw, defaults - to 15. It takes either a vector of contour levels; an integer - that specifies the number of contours to draw; or a function which - inputs `z` and outputs either a vector or an integer. + Geom.contours[(; levels=15, samples=150, preserve_order=true)] ### why would one ever want to set preserve_order to false here + +Draw contour lines of the 2D function or matrix in the `z` aesthetic. See +[`Stat.contour`](@ref) for more information. """ function contour(; levels=15, samples=150, preserve_order=true) return LineGeometry(Gadfly.Stat.contour(levels=levels, samples=samples), @@ -62,81 +44,52 @@ end """ Geom.path -Draw lines between points in the order they appear in the data. This is an -alias for [`Geom.line`](@ref) with `preserve_order=true`. - -# Aesthetics -- `x`: X-axis position. -- `y`: Y-axis position. -- `color` (optional): Group categorically by color. +Draw lines between points in the order they appear in the data. This +geometry is an equivalent to [`Geom.line`](@ref) with `preserve_order=true`. """ path() = LineGeometry(preserve_order=true) """ - Geom.density[(; bandwidth)] - -Draw a kernel density estimate from data. An alias for [`Geom.line`](@ref) with -[`Stat.density`](@ref). - -# Aesthetics -- `x`: Sample to draw density estimate from. + Geom.density[(; bandwidth=-Inf)] -# Arguments -- `bandwidth`: How closely the density estimate should mirror the data. - Larger values will smooth the density estimate out. +Draw a line showing the density estimate of the `x` aesthetic. +This geometry is an equivalent to [`Geom.line`](@ref) with +[`Stat.density`](@ref); see the latter for more information. """ density(; bandwidth::Real=-Inf) = LineGeometry(Gadfly.Stat.density(bandwidth=bandwidth)) """ - Geom.density2d[(; bandwidth, levels)] + Geom.density2d[(; bandwidth=(-Inf,-Inf), levels=15)] -Draw a kernel density estimate from data. An alias for [`Geom.contour`](@ref) with -[`Stat.density2d`](@ref). - -# Aesthetics -- `x`, `y`: Sample to draw density estimate from. - -# Arguments -- `bandwidth`: See [`Geom.density`](@ref). -- `levels`: See [`Geom.contour`](@ref). +Draw a set of contours showing the density estimate of the `x` and `y +aesthetics. See [`Geom.density`](@ref) and [`Geom.contour`](@ref) for a +description of `bandwidth` and `levels`, respectively. This geometry is an +equivalent to [`Geom.contour`](@ref) with [`Stat.density2d`](@ref). """ density2d(; bandwidth::Tuple{Real,Real}=(-Inf,-Inf), levels=15) = LineGeometry(Gadfly.Stat.density2d(bandwidth=bandwidth, levels=levels); preserve_order=true) """ - Geom.smooth[(; method, smoothing)] - -Plot a smooth function estimated from data. An alias for [`Geom.line`](@ref) with [`Stat.smooth`](@ref). + Geom.smooth[(; method:loess, smoothing=0.75)] -# Aesthetics -- `x`: Predictor data. -- `y`: Response data. -- `color`: (optional) Group categorically by color. - -# Arguments -- `method`: `:loess` and `:lm` are supported. -- `smoothing`: Method specific parameter controlling the degree of smoothing. - For loess, this is the span parameter giving the proportion of data - used for each local fit where 0.75 is the default. Smaller values use more - data (less local context), larger values use less data (more local context). +Plot a smooth function estimated from the `x` and `y` aesthetics. Optionally +group by `color` and plot multiple independent smooth lines. See +[`Stat.smooth`](@ref) for a description of `method` and `smoothing`. This +geometry is an equivalent to [`Geom.line`](@ref) with [`Stat.smooth`](@ref). """ smooth(; method::Symbol=:loess, smoothing::Float64=0.75) = - LineGeometry(Gadfly.Stat.smooth(method=method, smoothing=smoothing), order=5) + LineGeometry(Gadfly.Stat.smooth(method=method, smoothing=smoothing), + order=5) """ - Geom.step[(; direction)] - -Connect points using a stepwise function. Equivalent to [`Geom.line`](@ref) with -[`Stat.step`](@ref). - -# Aesthetics -- `x`: Point x-coordinate. -- `y`: Point y-coordinate. + Geom.step[(; direction=:hv)] -# Arguments -- `direction`: Either `:hv` for horizontal then vertical, or `:vh` for - vertical then horizontal. +Connect points described by the `x` and `y` aesthetics using a stepwise +function. If `direction` is `:hv` the a horizontal lines extends to the right +of each point and a vertical line below it; if `:vh` then vertical above and +horizontal to the left. This geometry is an equivalent to [`Geom.line`](@ref) +with [`Stat.step`](@ref). """ step(; direction::Symbol=:hv) = LineGeometry(Gadfly.Stat.step(direction=direction)) diff --git a/src/geom/point.jl b/src/geom/point.jl index ebe8bf2c8..5d94ba333 100644 --- a/src/geom/point.jl +++ b/src/geom/point.jl @@ -6,14 +6,25 @@ end PointGeometry(; tag=empty_tag) = PointGeometry(tag) """ -Draw various types of scatterplots. + Geom.point -# Aesthetics -- `x`: X-axis position. -- `y`: Y-axis position. -- `color` (optional): Point color. Categorical data will choose maximally distinguishable colors from the LCHab color space. Continuous data will map onto LCHab as well. Colors can also be specified explicitly for each data point with a vector of colors of length(x). A vector of length one specifies the color to use for all points. Default is Theme.default_color. -- `shape` (optional): Point shape. Categorical data will cycle through Theme.point_shapes. Shapes can also be specified explicitly for each data point with a vector of shapes of length(x). A vector of length one specifies the shape to use for all points. Default is Theme.point_shapes[1]. -- `size` (optional): Point size. Categorical data and vectors of Ints will interpolate between Theme.point_size_{min,max}. A continuous vector of AbstractFloats or Measures of length(x) specifies the size of each data point explicitly. A vector of length one specifies the size to use for all points. Default is Theme.point_size. +Draw scatter plots of the `x` and `y` aesthetics. + +# Optional Aesthetics +- `color`: Categorical data will choose maximally distinguishable colors from +the LCHab color space. Continuous data will map onto LCHab as well. Colors +can also be specified explicitly for each data point with a vector of colors of +length(x). A vector of length one specifies the color to use for all points. +Default is `Theme.default_color`. +- `shape`: Categorical data will cycle through `Theme.point_shapes`. Shapes +can also be specified explicitly for each data point with a vector of shapes of +length(x). A vector of length one specifies the shape to use for all points. +Default is `Theme.point_shapes[1]`. +- `size`: Categorical data and vectors of `Ints` will interpolate between +`Theme.point_size_{min,max}`. A continuous vector of `AbstractFloats` or +`Measures` of length(x) specifies the size of each data point explicitly. A +vector of length one specifies the size to use for all points. Default is +`Theme.point_size`. """ const point = PointGeometry diff --git a/src/geom/polygon.jl b/src/geom/polygon.jl index b93a971ef..bdb658091 100644 --- a/src/geom/polygon.jl +++ b/src/geom/polygon.jl @@ -10,44 +10,32 @@ PolygonGeometry(default_statistic=Gadfly.Stat.identity(); order=0, fill=false, p PolygonGeometry(default_statistic, order, fill, preserve_order, tag) """ - Geom.polygon[(; order, fill, preserve_order)] - -Draw polygons. - -# Aesthetics -- `x`: X-axis position. -- `y`: Y-axis position. -- `group` (optional): Group categorically. -- `color` (optional): Group categorically and indicate by color. - -# Arguments -- `order`: Z-order relative to other geometry. -- `fill`: If true, fill the polygon and stroke according to - `Theme.discrete_highlight_color`. If false (default), only stroke. -- `preserve_order`: If true, connect points in the order they are given. If - false (default) order the points around their centroid. + Geom.polygon[(; order=0, fill=false, preserve_order=false)] ### zorder + +Draw polygons with vertices specified by the `x` and `y` aesthetics. +Optionally plot multiple polygons according to the `group` or `color` +aesthetics. `order` controls whether the polygon(s) are underneath or on top +of other forms. If `fill` is true, fill and stroke the polygons according to +`Theme.discrete_highlight_color`, otherwise only stroke. If `preserve_order` +is true, connect points in the order they are given, otherwise order the points +around their centroid. """ const polygon = PolygonGeometry element_aesthetics(::PolygonGeometry) = [:x, :y, :color, :group] """ - Geom.ellipse[(; distribution, levels, nsegments)] - -Confidence ellipse for a scatter or group of points, using a parametric multivariate distribution e.g. multivariate normal. `Geom.ellipse` is an instance of [`Geom.polygon`](@ref) - -# Aesthetics -- `x`: Position of points. -- `y`: Position of points. -- `color` (optional): Color. -- `group` (optional): Group. - -# Arguments -- `distribution`: A multivariate distribution. Default is `MvNormal`. -- `levels`: The quantiles for which confidence ellipses are calculated. Default is [0.95]. -- `nsegments`: Number of segments to draw each ellipse. Default is 51. + Geom.ellipse[(; distribution=MvNormal, levels=[0.95], nsegments=51, fill=false)] + +Draw a confidence ellipse, using a parametric multivariate distribution, for a +scatter of points specified by the `x` and `y` aesthetics. Optionally plot +multiple ellipses according to the `group` or `color` aesthetics. +`distribution` specifies a multivariate distribution to use; `levels` the +quantiles for which confidence ellipses are calculated; and `nsegments` the +number of segments with which to draw each ellipse. `Geom.ellipse` is +equivalent to [`Geom.polygon`](@ref) with [`Stat.ellpise`](@ref). """ -ellipse(;distribution::(Type{<:ContinuousMultivariateDistribution})=MvNormal, +ellipse(; distribution::(Type{<:ContinuousMultivariateDistribution})=MvNormal, levels::Vector=[0.95], nsegments::Int=51, fill::Bool=false) = PolygonGeometry(Gadfly.Stat.ellipse(distribution, levels, nsegments), preserve_order=true, fill=fill) diff --git a/src/geom/rectbin.jl b/src/geom/rectbin.jl index 550fd2c64..dfeaa1845 100644 --- a/src/geom/rectbin.jl +++ b/src/geom/rectbin.jl @@ -12,54 +12,30 @@ end """ Geom.rect -Draw colored rectangles. - -# Aesthetics -- color -- x_min -- x_max -- y_min -- y_max +Draw colored rectangles with the corners specified by the +`x_min`, `x_max`, `y_min` and `y_max` aesthetics. Optionally +specify their `color`. """ rect() = RectangularBinGeometry(Gadfly.Stat.Identity()) """ Geom.rectbin -Draw colored rectangles. - -# Aesthetics -- color -- x -- y - -Equal sizes squares are centered at `x` and `y` positions. +Draw equal sizes rectangles centered at `x` and `y` positions. Optionally +specify their `color`. """ const rectbin = RectangularBinGeometry """ - Geom.histogram2d[(; xbincount, xminbincount, xmaxbincount, - ybincount, yminbincount, ymaxbincount)] - -Bin data in rectangles and indicate density with color. As in heatmaps, etc. - -An alias for [`Geom.rectbin`](@ref) with [`Stat.histogram2d`](@ref). - -# Aesthetics -- `x`: Observations to be binned and plotted on the x coordinate. -- `y`: Observations to binned and plotted on the y coordinate. - -# Arguments -- `xbincount`: Fix the number of bins in the x coordinate. -- `xminbincount`: Set the minimum x coordinate bincount when automatically - determining the number of bins. -- `xmaxbincount`: Set the maximum x coordinate bincount when automatically - determining the number of bins. -- `ybincount`: Fix the number of bins in the y coordinate. -- `yminbincount`: Set the minimum y coordinate bincount when automatically - determining the number of bins. -- `ymaxbincount`: Set the maximum y coordinate bincount when automatically - determining the number of bin. + Geom.histogram2d[(; xbincount=nothing, xminbincount=3, xmaxbincount=150, + ybincount=nothing, yminbincount=3, ymaxbincount=150)] + +Draw a heatmap of the `x` and `y` aesthetics by binning into rectangles and +indicating density with color. `xbincount` and `ybincount` manually fix the +number of bins. Alternatively, `xminbincount`, `xmaxbincount`, `yminbincount` +and `ymaxbincount` set the minima and maxima when automatically determining the +number of bins. This geometry is equivalent to [`Geom.rect`](@ref) with +[`Stat.histogram2d`](@ref). """ function histogram2d(; xbincount=nothing, xminbincount=3, xmaxbincount=150, ybincount=nothing, yminbincount=3, ymaxbincount=150) diff --git a/src/geom/ribbon.jl b/src/geom/ribbon.jl index 7ff09c7dc..c0796871c 100644 --- a/src/geom/ribbon.jl +++ b/src/geom/ribbon.jl @@ -8,13 +8,8 @@ RibbonGeometry(default_statistic=Gadfly.Stat.identity(); tag=empty_tag) = """ Geom.ribbon -Draw a ribbon bounded above and below by `ymin` and `ymax`, respectively. - -# Aesthetics -- `x`: X-axis position -- `ymin`: Y-axis lower bound. -- `ymax`: Y-axis upper bound. -- `color` (optional): Group categorically by color. +Draw a ribbon at the positions in `x` bounded above and below by `ymax` and +`ymin`, respectively. Optionally draw multiple ribbons by grouping with `color`. """ const ribbon = RibbonGeometry diff --git a/src/geom/segment.jl b/src/geom/segment.jl index c3c1d59e7..8c0482843 100755 --- a/src/geom/segment.jl +++ b/src/geom/segment.jl @@ -11,69 +11,38 @@ SegmentGeometry(default_statistic=Gadfly.Stat.identity(); arrow=false, filled=fa SegmentGeometry(default_statistic, arrow, filled, tag) """ - Geom.segment[(; arrow)] + Geom.segment[(; arrow=false, filled=false)] ### what does filled do? + ### why just Scale go with arrows? -Draw separate line segments/vectors/arrows. - -!!! note - - If you want arrows, then you need to provide a `Scale` object for both axes. See example below. - -# Aesthetics -- `x`: Start of line segment. -- `y`: Start of line segment. -- `xend`: End of line segment. -- `yend`: End of line segment. -- `color` (optional): Color of line segments. - -# Arguments -- `arrow`: Default behavior for `Geom.segment` is to draw line segments without arrows. `Geom.vector` is `Geom.segment(arrow=true)`. +Draw line segments from `x`, `y` to `xend`, `yend`. Optionally specify their +`color`. If `arrow` is true, then a `Scale` object for both axes must be +provided. """ const segment = SegmentGeometry # Leave this as a function, pending extra arguments e.g. arrow attributes """ - Geom.vector[(; filled::Bool=false)] + Geom.vector[(; filled=false)] + +This geometry is equivalent to [`Geom.segment(arrow=true)`](@ref). """ vector(; filled::Bool=false) = SegmentGeometry(arrow=true, filled=filled) """ - Geom.hair[(; intercept, orientation)] - -Draws a line from the points to some `intercept` (base line). Looks like hairs standing on end, hence called a hair plot. Also known as a lollipop chart if the end points are plotted. + Geom.hair[(; intercept=0.0, orientation=:vertical)] -# Aesthetics -- `x`: Position of points. -- `y`: Position of points. -- `color` (optional): Color. - -# Arguments -- `intercept`: Base of hairs. Defaults to zero. -- `orientation`: `:vertical` (default) or `:horizontal` +Draw lines from `x`, `y` to y=`intercept` if `orientation` is `:vertical` or +x=`intercept` if `:horizontal`. Optionally specify their `color`. """ hair(;intercept=0.0, orientation=:vertical) = SegmentGeometry(Gadfly.Stat.hair(intercept, orientation)) """ - Geom.vectorfield[(; smoothness, scale samples)] - -Draw a vectorfield of a 2D function or a matrix. A vectorfield consists of gradient vectors calculated for particular points in a space. - -# Aesthetics -- `z`: 2D function or a matrix that represent "heights" relative to - to the x-y plane. -- `x` (optional): Vector of X-coordinates. If `z` is a matrix, then - the length of `x` must be equal to the number of *rows* in `z`. -- `y` (optional): Vector of Y-coordinates. If `z` is a matrix, then - the length of `y` must be equal to the number of *columns* in `z`. - -# Arguments -- `smoothness` (optional): Sets the smoothness of the vectorfield, - defaults to 1.0. Smaller values (→0) result in more local smoothing. - Larger values (→∞) will approach a plane of best fit. -- `scale` (optional): Sets the size of vectors, defaults to 1.0. -- `samples` (optional): Sets the size of the grid at which to estimate vectors, - defaults to 20 (i.e. grid is 20 x 20). See the first example below. + Geom.vectorfield[(; smoothness=1.0, scale=1.0, samples=20, filled=false)] + +Draw a gradient vector field of the 2D function or a matrix in the `z` +aesthetic. This geometry is equivalent to [`Geom.segment`](@ref) with +[`Stat.vectorfield`](@ref); see the latter for more information. """ function vectorfield(;smoothness=1.0, scale=1.0, samples=20, filled::Bool=false) return SegmentGeometry( diff --git a/src/geom/violin.jl b/src/geom/violin.jl index ecffdb728..5bebd6c17 100644 --- a/src/geom/violin.jl +++ b/src/geom/violin.jl @@ -5,7 +5,7 @@ end ViolinGeometry(; order=1, tag=empty_tag) = ViolinGeometry(order, tag) """ - Geom.violin + Geom.violin[(; order=1)] Draw violin plots. diff --git a/src/guide.jl b/src/guide.jl index 02d072e67..eaa97a75d 100644 --- a/src/guide.jl +++ b/src/guide.jl @@ -167,19 +167,22 @@ ColorKey(;title=nothing, labels=nothing, pos=nothing) = ColorKey(title, labels, # ColorKey() = ColorKey(nothing) """ - Guide.colorkey[(; title, labels, pos)] + Guide.colorkey[(; title=nothing, labels=nothing, pos=nothing)] + Guide.colorkey(title, labels, pos) -`Guide.colorkey` enables control of some fields of the auto-generated colorkey. Currently, you can change the colorkey title (for any plot), the item labels (for plots with a discrete color scale), and put the colorkey inside any plot. The fields can be named e.g. `Guide.colorkey(title="Group", labels=["A","B"], pos=[0w,0h])`, or given in order e.g. `Guide.colorkey("Group", ["A","B"], [0w,0h])`. +`Guide.colorkey` enables control of some fields of the auto-generated colorkey. +Currently, you can change the colorkey title (for any plot), the item labels +(for plots with a discrete color scale), and put the colorkey inside any plot. # Arguments - `title`: Legend title (for any plot) - `labels`: Legend item labels (for plots with a discrete color scale) -- `pos`: [x,y] position of the colorkey inside any plot. Setting `Guide.colorkey(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 (see example below) - -# Colorkey position -`pos` can be given in relative or absolute units (do `using Compose` before plotting): -- _Relative units_: e.g. [0.7w, 0.2h] will place the key in the lower right quadrant, [0.05w, -0.25h] in the upper left (see example below). -- _Absolute units_: e.g. [0mm, 0mm] the key is left-centered, or use the plot scales like [x,y]. For the latter, the x-position will make sense, but the key will be offset below the y-position, because of the way the key is rendered. +- `pos`: [x,y] position of the colorkey inside any plot 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. Setting `Guide.colorkey(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 (see example below) """ const colorkey = ColorKey @@ -506,14 +509,9 @@ ManualColorKey(title, labels, colors) = ManualColorKey(title, labels, Gadfly.parse_colorant(colors)) """ - Guide.manual_color_key[(; title, labels, colors)] - -Manually define a color key + Guide.manual_color_key(title, labels, colors) -# Arguments -- `title`: Legend title -- `labels`: Item labels -- `colors`: Item colors +Manually define a color key with the legend `title` and item `labels` and `colors`. """ const manual_color_key = ManualColorKey @@ -572,17 +570,12 @@ end XTicks(; label=true, ticks=:auto, orientation=:auto) = XTicks(label, ticks, orientation) """ - Guide.xticks[(; ticks, label, orientation)] + Guide.xticks[(; label=true, ticks=:auto, orientation=:auto)] + Guide.xticks(label, ticks, orientation) -Formats the tick marks and labels for the x-axis - -# Arguments -- `ticks`: Array of tick locations on the x-axis, `:auto` to automatically - select ticks, or `nothing` to supress x-axis ticks. -- `label`: Determines if the ticks are labeled, either - `true` (default) or `false` -- `orientation`: Label orientation - (`:horizontal, :vertical, :auto`). Defaults to `:auto` +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 @@ -748,17 +741,12 @@ end YTicks(; label=true, ticks=:auto, orientation=:horizontal) = YTicks(label, ticks, orientation) """ - Guide.yticks[(; ticks, label, orientation)] + Guide.yticks[(; label=true, ticks=:auto, orientation=:horizontal)] + Guide.yticks(ticks, label, orientation) ### XTICKS DEFAULTS TO AUTO -Formats the tick marks and labels for the y-axis - -# Arguments -- `ticks`: Array of tick locations on the y-axis, `:auto` to automatically - select ticks, or `nothing` to supress y-axis ticks. -- `label`: Determines if the ticks are labeled, either - `true` (default) or `false` -- `orientation`: Label orientation - (`:horizontal, :vertical, :auto`). Defaults to `:auto` +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 @@ -935,15 +923,8 @@ XLabel(label; orientation=:auto) = XLabel(label, orientation) """ Guide.xlabel(label, orientation=:auto) -Sets the x-axis label for the plot. - -# Arguments -- `label`: X-axis label -- `orientation` (optional): `:horizontal`, `:vertical`, or `:auto` (default) - -`label` is not a keyword parameter, it must be supplied as the first -argument of [Guide.xlabel](@ref). Setting it to `nothing` will suppress -the default label. +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 @@ -1009,15 +990,8 @@ YLabel(label; orientation=:auto) = YLabel(label, orientation) """ Guide.ylabel(label, orientation=:auto) -Sets the y-axis label for the plot. - -# Arguments -- `label`: Y-axis label -- `orientation` (optional): `:horizontal`, `:vertical`, or `:auto` (default) - -`label` is not a keyword parameter, it must be supplied as the first -argument of `Guide.ylabel`. Setting it to `nothing` will suppress -the default label. +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 @@ -1076,9 +1050,6 @@ end Geom.title(title) Set the plot title. - -# Arguments -- `title`: Plot title """ const title = Title @@ -1111,10 +1082,7 @@ end """ Guide.xrug -Draw a rug plot along the x-axis of a plot. - -# Aesthetics -- `x`: X positions of notches. +Draw a rug plot along the x-axis of a plot using the `x` aesthetic. """ const xrug = XRug @@ -1140,10 +1108,7 @@ end """ Guide.yrug -Draw a rug plot along the y-axis of a plot. - -# Aesthetics -- `y`: Y positions of notches. +Draw a rug plot along the y-axis of a plot using the 'y' aesthetic. """ const yrug = YRug @@ -1283,14 +1248,10 @@ struct Annotation <: Gadfly.GuideElement end """ - Guide.annotation(ctx) + Guide.annotation(ctx::Compose.Context) -Overlay a plot with an arbitrary [Compose](http://composejl.org/) graphic. The -context will inherit the plot's coordinate system, unless overridden with a -custom unit box. - -# Arguments -- `ctx`: A 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 diff --git a/src/poetry.jl b/src/poetry.jl index 403598ceb..76534d6c3 100644 --- a/src/poetry.jl +++ b/src/poetry.jl @@ -103,55 +103,12 @@ layer(f::Function, a::Number, b::Number, elements::ElementOrFunction...) = layer(Function[f], a, b, elements...) -# Simple heatmap plots of matrices. -# -# It is a wrapper around the `plot()` function using the `rectbin` geometry. -# It also applies a sane set of defaults to make sure that the plots look nice -# by default. Specifically -# - the aspect ratio of the coordinate system is fixed Coord.cartesian(fixed=true), -# so that the rectangles become squares -# - the axes run from 0.5 to N+0.5, because the first row/column is drawn to -# (0.5, 1.5) and the last one to (N-0.5, N+0.5). -# - the y-direction is flipped, so that the [1,1] of a matrix is in the top -# left corner, as is customary -# - NaNs are not drawn. `spy` leaves "holes" instead into the heatmap. -# -# Args: -# M: A matrix. -# -# Returns: -# A plot object. -# -# Known bugs: -# - If the matrix is only NaNs, then it throws an `ArgumentError`, because -# an empty collection gets passed to the `plot` function / `rectbin` geometry. -# """ -``` -spy(M::AbstractMatrix, elements::ElementOrFunction...; mapping...) -``` -Simple heatmap plots of matrices. - -It is a wrapper around the `plot()` function using the `rectbin` geometry. -It also applies a sane set of defaults to make sure that the plots look nice -by default. Specifically -- the aspect ratio of the coordinate system is fixed Coord.cartesian(fixed=true), -so that the rectangles become squares -- the axes run from 0.5 to N+0.5, because the first row/column is drawn to -(0.5, 1.5) and the last one to (N-0.5, N+0.5). -- the y-direction is flipped, so that the [1,1] of a matrix is in the top -left corner, as is customary -- NaNs are not drawn. `spy` leaves "holes" instead into the heatmap. - -### Args: -* M: A matrix. - -### Returns: -A plot object. - -#### Known bugs: - - If the matrix is only NaNs, then it throws an `ArgumentError`, because - an empty collection gets passed to the `plot` function / `rectbin` geometry. + spy(M::AbstractMatrix, elements::ElementOrFunction...; mapping...) -> Plot + +Plots a heatmap of `M` using `plot(Geom.rectbin, +Coord.cartesian(fixed=true)...)`. M[1,1] is in the upper left. NaN values are +left blank, and an error is thrown is all elements of M are NaN. """ function spy(M::AbstractMatrix, elements::ElementOrFunction...; mapping...) diff --git a/src/scale.jl b/src/scale.jl index f890276eb..deb838773 100644 --- a/src/scale.jl +++ b/src/scale.jl @@ -10,7 +10,7 @@ using Showoff using IndirectArrays using CategoricalArrays -import Gadfly: element_aesthetics, isconcrete, concrete_length, discretize_make_ia +import Gadfly: element_aesthetics, isconcrete, concrete_length, discretize_make_ia, aes2str import Distributions: Distribution include("color_misc.jl") @@ -76,9 +76,9 @@ log2_formatter(xs::AbstractArray, format=:plain) = [@sprintf("2%s", x) for x in showoff(xs, format)] const log2_transform = ContinuousScaleTransform(log2, x -> 2^x, log2_formatter) -ln_formatter(xs::AbstractArray, format=:plain) = +log_formatter(xs::AbstractArray, format=:plain) = [@sprintf("e%s", x) for x in showoff(xs, format)] -const ln_transform = ContinuousScaleTransform(log, exp, ln_formatter) +const log_transform = ContinuousScaleTransform(log, exp, log_formatter) asinh_formatter(xs::AbstractArray, format=:plain) = [@sprintf("sinh(%s)", x) for x in showoff(xs, format)] @@ -132,6 +132,8 @@ const x_vars = [:x, :xmin, :xmax, :xintercept, :intercept, :xviewmin, :xviewmax, const y_vars = [:y, :ymin, :ymax, :yintercept, :slope, :middle, :upper_fence, :lower_fence, :upper_hinge, :lower_hinge, :yviewmin, :yviewmax, :yend] +element_aesthetics(scale::ContinuousScale) = scale.vars + function continuous_scale_partial(vars::Vector{Symbol}, trans::ContinuousScaleTransform) function(; minvalue=nothing, maxvalue=nothing, labels=nothing, format=nothing, minticks=2, maxticks=10, scalable=true) @@ -142,114 +144,47 @@ function continuous_scale_partial(vars::Vector{Symbol}, trans::ContinuousScaleTr end # Commonly used scales. -""" - Scale.x_continous[(; minvalue, maxvalue, labels, format, - minticks, maxticks, scalable)] +xy_continuous(var, aess) = """ + Scale.$(var)_continuous[(; minvalue=nothing, maxvalue=nothing, labels=nothing, + format=nothing, minticks=2, maxticks=10, scalable=true)] -Map numerical data to x positions in cartesian coordinates. +Map numerical $(aess) to $var positions in Cartesian coordinates using an identity transform. # Arguments -- `minvalue`: Set scale lower bound to be ≤ this value. -- `maxvalue`: Set scale lower bound to be ≥ this value. - -!!! note - - `minvalue` and `maxvalue` here are soft bounds, Gadfly may choose to ignore - them when constructing an optimal plot. Use [`Coord.cartesian`](@ref) to enforce +- `minvalue`, `maxvalue`: Set the plot's lower and upper bounds. + Note that these are soft-- Gadfly may choose to ignore + them when constructing an optimal plot. Use [`Coord.cartesian`](@ref) to enforce a hard bound. - -- `labels`: Either a `Function` or `nothing`. When a - function is given, values are formatted using this function. The function - should map a value in `x` to a string giving its label. If the scale +- `labels`: Either a `Function` or `nothing`. The function + should map a coordinate value to a string label. If the scale applies a transformation, transformed label values will be passed to this function. -- `format`: How numbers should be formatted. One of `:plain`, `:scientific`, - `:engineering`, or `:auto`. The default in `:auto` which prints very large or very small +- `format`: How numbers should be formatted. One of `:plain`, `:scientific`, + `:engineering`, or `:auto`. The default is `:auto` (IS THIS CORRECT?) which prints very large or very small numbers in scientific notation, and other numbers plainly. -- `scalable`: When set to false, scale is fixed when zooming (default: true) - -# Variations -A number of transformed continuous scales are provided. - -- `Scale.x_continuous` (scale without any transformation). -- `Scale.x_log10` -- `Scale.x_log2` -- `Scale.x_log` -- `Scale.x_asinh` -- `Scale.x_sqrt` - - -# Aesthetics Acted On -`x`, `xmin`, `xmax`, `xintercept` -""" -const x_continuous = continuous_scale_partial(x_vars, identity_transform) +- `scalable`: When set to false, scale is fixed when zooming. +See also [`$(var)_log10`](@ref), [`$(var)_log2`](@ref), [`$(var)_log`](@ref), [`$(var)_asinh`](@ref), and [`$(var)_sqrt`](@ref). """ - Scale.y_continuous[(; minvalue, maxvalue, labels, format, - minticks, maxticks, scalable)] - -Map numerical data to y positions in cartesian coordinates. - -# Arguments -- `minvalue`: Set scale lower bound to be ≤ this value. -- `maxvalue`: Set scale lower bound to be ≥ this value. - -!!! note - `minvalue` and `maxvalue` here are soft bounds, Gadfly may choose to ignore - them when constructing an optimal plot. Use [`Coord.cartesian`](@ref) to enforce - a hard bound. - -- `labels`: Either a `Function` or `nothing`. When a - function is given, values are formatted using this function. The function - should map a value in `x` to a string giving its label. If the scale - applies a transformation, transformed label values will be passed to this - function. -- `format`: How numbers should be formatted. One of `:plain`, `:scientific`, - `:engineering`, or `:auto`. The default in `:auto` which prints very large or very small - numbers in scientific notation, and other numbers plainly. -- `scalable`: When set to false, scale is fixed when zooming (default: true) - -# Variations -A number of transformed continuous scales are provided. +# can be put on two lines with julia 0.7 +@doc xy_continuous("x", aes2str(element_aesthetics(x_continuous()))) const x_continuous = continuous_scale_partial(x_vars, identity_transform) -- `Scale.y_continuous` (scale without any transformation). -- `Scale.y_log10` -- `Scale.y_log2` -- `Scale.y_log` -- `Scale.y_asinh` -- `Scale.y_sqrt` +@doc xy_continuous("y", aes2str(element_aesthetics(y_continuous()))) const y_continuous = continuous_scale_partial(y_vars, identity_transform) +xy_fun(var,fun) = """ + Scale.$(var)_$(fun)[(; minvalue=nothing, maxvalue=nothing, labels=nothing, + format=nothing, minticks=2, maxticks=10, scalable=true)] -# Aesthetics -`y`, `ymin`, `ymax`, `yintercept` +Similar to [`Scale.$(var)_continuous`](@ref), except that the aesthetics are `$(fun)` transformed. """ -const y_continuous = continuous_scale_partial(y_vars, identity_transform) -const x_log10 = continuous_scale_partial(x_vars, log10_transform) -const y_log10 = continuous_scale_partial(y_vars, log10_transform) -const x_log2 = continuous_scale_partial(x_vars, log2_transform) -const y_log2 = continuous_scale_partial(y_vars, log2_transform) -const x_log = continuous_scale_partial(x_vars, ln_transform) -const y_log = continuous_scale_partial(y_vars, ln_transform) -const x_asinh = continuous_scale_partial(x_vars, asinh_transform) -const y_asinh = continuous_scale_partial(y_vars, asinh_transform) -const x_sqrt = continuous_scale_partial(x_vars, sqrt_transform) -const y_sqrt = continuous_scale_partial(y_vars, sqrt_transform) -const size_continuous = continuous_scale_partial([:size], identity_transform) +for xy in [:x,:y], fun in [:log10, :log2, :log, :asinh, :sqrt] + @eval @doc $(xy_fun(xy,fun)) const $(Symbol(xy,'_',fun)) = continuous_scale_partial($(Symbol(xy,"_vars")), $(Symbol(fun,"_transform"))) +end -element_aesthetics(scale::ContinuousScale) = scale.vars +const size_continuous = continuous_scale_partial([:size], identity_transform) -# Apply a continuous scale. -# -# Args: -# scale: A continuous scale. -# datas: Zero or more data objects. -# aess: Aesthetics (of the same length as datas) to update with scaled data. -# -# Return: -# nothing -# function apply_scale(scale::ContinuousScale, aess::Vector{Gadfly.Aesthetics}, datas::Gadfly.Data...) for (aes, data) in zip(aess, datas) @@ -386,68 +321,47 @@ const discrete = DiscreteScale element_aesthetics(scale::DiscreteScale) = scale.vars -""" - Scale.x_discrete[(; labels, levels, order)] +xy_discrete(var, aess) = """ + Scale.$(var)_discrete[(; labels=nothing, levels=nothing, order=nothing)] -Map data categorical to Cartesian coordinates. Unlike [`Scale.x_continuous`](@ref), each -unique x value will be mapped to a equally spaced positions, regardless of -value. +Map categorical $(aess) to Cartesian coordinates. Unlike `Scale.x_continuous`, each +unique $var value will be mapped to equally spaced positions, regardless of value. By default continuous scales are applied to numerical data. If data consists of -numbers specifying categories, explicitly adding [`Scale.x_discrete`](@ref) is the +numbers specifying categories, explicitly adding `Scale.$(var)_discrete` is the easiest way to get that data to plot appropriately. # Arguments -- `labels`: Either a `Function` or `nothing`. When a - function is given, values are formatted using this function. The function - should map a value in `x` to a string giving its label. +- `labels`: Either a `Function` or `nothing`. The function + should map a coordinate value to a string label. - `levels`: If non-nothing, give values for the scale. Order will be respected and anything in the data that's not respresented in `levels` will be set to `missing`. - `order`: If non-nothing, give a vector of integers giving a permutation of the values pool of the data. -# Aesthetics - -`x`, `xmin`, `xmax`, `xintercept` +See also [`group_discrete`](@ref), [`shape_discrete`](@ref), , and [`size_discrete`](@ref). """ -x_discrete(; labels=nothing, levels=nothing, order=nothing) = - DiscreteScale(x_vars, labels=labels, levels=levels, order=order) - -""" - Scale.y_discrete[(; labels, levels, order)] -Map data categorical to Cartesian coordinates. Unlike [`Scale.y_continuous`](@ref), each -unique y value will be mapped to a equally spaced positions, regardless of -value. +@doc xy_discrete("x", aes2str(element_aesthetics(x_discrete()))) x_discrete(; labels=nothing, levels=nothing, order=nothing) = + DiscreteScale(x_vars, labels=labels, levels=levels, order=order) -By default continuous scales are applied to numerical data. If data consists of -numbers specifying categories, explicitly adding [`Scale.y_discrete`](@ref) is the -easiest way to get that data to plot appropriately. +@doc xy_discrete("y", aes2str(element_aesthetics(y_discrete()))) y_discrete(; labels=nothing, levels=nothing, order=nothing) = + DiscreteScale(y_vars, labels=labels, levels=levels, order=order) -# Arguments -- `labels`: Either a `Function` or `nothing`. When a - function is given, values are formatted using this function. The function - should map a value in `x` to a string giving its label. -- `levels`: If non-nothing, give values for the scale. Order will be respected - and anything in the data that's not respresented in `levels` will be set to - `missing`. -- `order`: If non-nothing, give a vector of integers giving a permutation of - the values pool of the data. +type_discrete(aes) = """ + $(aes)_discrete[(; labels=nothing, levels=nothing, order=nothing)] -# Aesthetics -`y`, `ymin`, `ymax`, `yintercept` +Similar to [`Scale.x_discrete`](@ref), except only applied to the `$aes` aesthetic. """ -y_discrete(; labels=nothing, levels=nothing, order=nothing) = - DiscreteScale(y_vars, labels=labels, levels=levels, order=order) -group_discrete(; labels=nothing, levels=nothing, order=nothing) = +@doc type_discrete("group") group_discrete(; labels=nothing, levels=nothing, order=nothing) = DiscreteScale([:group], labels=labels, levels=levels, order=order) -shape_discrete(; labels=nothing, levels=nothing, order=nothing) = +@doc type_discrete("shape") shape_discrete(; labels=nothing, levels=nothing, order=nothing) = DiscreteScale([:shape], labels=labels, levels=levels, order=order) -size_discrete(; labels=nothing, levels=nothing, order=nothing) = +@doc type_discrete("size") size_discrete(; labels=nothing, levels=nothing, order=nothing) = DiscreteScale([:size], labels=labels, levels=levels, order=order) function apply_scale(scale::DiscreteScale, aess::Vector{Gadfly.Aesthetics}, datas::Gadfly.Data...) @@ -492,9 +406,8 @@ end Scale.color_none Suppress a default color scale. Some statistics impose a default color scale. -When no color scale is desired, explicitly including [`Scale.color_none`](@ref) will +When no color scale is desired, explicitly including `Scale.color_none` will suppress this default. - """ const color_none = NoneColorScale @@ -554,19 +467,16 @@ function default_discrete_colors(n) ) end -# Common discrete color scales """ - Scale.color_discrete_hue[(f; levels, order, preserve_order)] + Scale.color_discrete_hue[(f; levels=nothing, order=nothing, preserve_order=true)] -Create a discrete color scale to be used for the plot. `Scale.color_discrete` is an -alias for [`Scale.color_discrete_hue`](@ref). +Create a discrete color scale that maps the categorical levels to `Color`s. # Arguments -- `f`: A function `f(n)` that produces a vector of `n` colors. Usually [`distinguishable_colors`](https://github.com/JuliaGraphics/Colors.jl#distinguishable_colors) can be used for this, with parameters tuned to your liking. +- `f`: A function that produces a vector of colors. For example, [`distinguishable_colors`](https://github.com/JuliaGraphics/Colors.jl#distinguishable_colors). - `levels`: Explicitly set levels used by the scale. -- `order`: A vector of integers giving a permutation of the levels - default order. -- `preserve_order`: If set to `true`, orders levels as they appear in the data +- `order`: A vector of integers giving a permutation of the levels default order. +- `preserve_order`: If set to `true`, orders levels as they appear in the data. """ function color_discrete_hue(f=default_discrete_colors; levels=nothing, @@ -581,24 +491,19 @@ end @deprecate discrete_color_hue(; levels=nothing, order=nothing, preserve_order=true) color_discrete_hue(; levels=levels, order=order, preserve_order=preserve_order) -const color_discrete = color_discrete_hue +const color_discrete = color_discrete_hue ### WHY HAVE THIS ALIAS? @deprecate discrete_color(; levels=nothing, order=nothing, preserve_order=true) color_discrete(; levels=levels, order=order, preserve_order=preserve_order) """ - Scale.color_discrete_manual[(; colors, levels, order)] + Scale.color_discrete_manual(colors...; levels=nothing, order=nothing) -Create a discrete color scale to be used for the plot. +Create a discrete color scale by mapping the `color` aesthetic to `Color`s. # Arguments -- `colors...`: an iterable collection of things that can be converted to colors with `Colors.color` (e.g. "tomato", RGB(1.0,0.388,0.278), colorant"#FF6347") -- `levels` (optional): Explicitly set levels used by the scale. Order is - respected. -- `order` (optional): A vector of integers giving a permutation of the levels - default order. - -# Aesthetics Acted On -`color` +- `colors...`: an iterable collection of colors (e.g. "tomato", RGB(1.0,0.388,0.278), colorant"#FF6347") +- `levels`: Explicitly set levels used by the scale. Order is respected. +- `order`: A vector of integers giving a permutation of the levels default order. """ color_discrete_manual(colors::AbstractString...; levels=nothing, order=nothing) = color_discrete_manual(Gadfly.parse_colorant(colors)...; levels=levels, order=order) @@ -684,45 +589,34 @@ function continuous_color_scale_partial(trans::ContinuousScaleTransform) end end -# Commonly used scales. -""" - Scale.color_continuous[(; minvalue, maxvalue, colormap)] +element_aesthetics(::ContinuousColorScale) = [:color] -Create a continuous color scale that the plot will use. +""" + Scale.color_continuous[(; minvalue=nothing, maxvalue=nothing, colormap)] -This can also be set as the `continuous_color_scheme` in a Theme (see [Themes](@ref)). +Create a continuous color scale by mapping the `color` aesthetic to a `Color`. +This can also be set as the `continuous_color_scheme` in a Theme (see +[Themes](@ref)). # Arguments -- `minvalue` (optional): the data value corresponding to the bottom of the color scale (will be based on the range of the data if not specified). -- `maxvalue` (optional): the data value corresponding to the top of the color scale (will be based on the range of the data if not specified). -- `colormap`: A function defined on the interval from 0 to 1 that returns a `Color` (as from the `Colors` package). +- `minvalue`, `maxvalue`: the data values corresponding to the bottom and top of the color scale. +- `colormap`: A function defined on the interval from 0 to 1 that returns a `Color`. -# Variations - -`color_continuous_gradient` is an alias for [`Scale.color_continuous`](@ref). - -A number of transformed continuous scales are provided. +See also [`color_log10`](@ref), [`color_log2`](@ref), [`color_log`](@ref), [`color_asinh`](@ref), and [`color_sqrt`](@ref). +""" +const color_continuous = continuous_color_scale_partial(identity_transform) -- `Scale.color_continuous` (scale without any transformation). -- `Scale.color_log10` -- `Scale.color_log2` -- `Scale.color_log` -- `Scale.color_asinh` -- `Scale.color_sqrt` +color_fun(fun) = """ + Scale.color_$(fun)[(; minvalue=nothing, maxvalue=nothing, colormap)] -# Aesthetics Acted On -`color` +Similar to `Scale.color_continuous`, except that `color` is $(fun) transformed. """ -const color_continuous = continuous_color_scale_partial(identity_transform) -const color_log10 = continuous_color_scale_partial(log10_transform) -const color_log2 = continuous_color_scale_partial(log2_transform) -const color_log = continuous_color_scale_partial(ln_transform) -const color_asinh = continuous_color_scale_partial(asinh_transform) -const color_sqrt = continuous_color_scale_partial(sqrt_transform) -const color_continuous_gradient = color_continuous +for fun in [:log10, :log2, :log, :asinh, :sqrt] + @eval @doc $(color_fun(fun)) const $(Symbol("color_",fun)) = continuous_color_scale_partial($(Symbol(fun,"_transform"))) +end -element_aesthetics(::ContinuousColorScale) = [:color] +const color_continuous_gradient = color_continuous ### WHY HAVE THIS ALIAS? @deprecate continuous_color_gradient(;minvalue=nothing, maxvalue=nothing) color_continuous_gradient(;minvalue=minvalue, maxvalue=maxvalue) diff --git a/src/statistics.jl b/src/statistics.jl index d556eb866..706161590 100644 --- a/src/statistics.jl +++ b/src/statistics.jl @@ -15,34 +15,15 @@ using CoupledFields # It is registered in METADATA.jl using IndirectArrays import Gadfly: Scale, Coord, input_aesthetics, output_aesthetics, - default_scales, isconcrete, setfield!, discretize_make_ia + default_scales, isconcrete, setfield!, discretize_make_ia, aes2str import KernelDensity # import Distributions: Uniform, Distribution, qqbuild import IterTools: chain, distinct import Compat.Iterators: cycle, product -function aes2str(aes) - list = join([string('`',x,'`') for x in aes], ", ", ", and ") - if length(aes)>1 - return string(list," aesthetics") - else - return string(list," aesthetic") - end -end - include("bincount.jl") -# Apply a series of statistics. -# -# Args: -# stats: Statistics to apply in order. -# scales: Scales used by the plot. -# aes: A Aesthetics instance. -# -# Returns: -# Nothing, modifies aes. -# function apply_statistics(stats::Vector{Gadfly.StatisticElement}, scales::Dict{Symbol, Gadfly.ScaleElement}, coord::Gadfly.CoordinateElement, @@ -524,13 +505,19 @@ struct DensityStatistic <: Gadfly.StatisticElement end DensityStatistic(; n=256, bandwidth=-Inf) = DensityStatistic(n, bandwidth) -input_aesthetics(stat::DensityStatistic) = [:x] -output_aesthetics(stat::DensityStatistic) = [:x, :y] +input_aesthetics(stat::DensityStatistic) = [:x, :colors] +output_aesthetics(stat::DensityStatistic) = [:x, :y, :colors] """ Stat.density[(; n=256, bandwidth=-Inf)] Transform $(aes2str(input_aesthetics(density()))) into $(aes2str(output_aesthetics(density()))). + +`bandwidth` +specifies how closely the density estimate should mirror the data-- larger +values smooth more. + +Estimate the density of the values in the `x` aesthetic at `n` points """ const density = DensityStatistic @@ -735,8 +722,7 @@ end # Find reasonable places to put tick marks and grid lines. struct TickStatistic <: Gadfly.StatisticElement - in_vars::Vector{Symbol} - out_var::AbstractString + axis::AbstractString granularity_weight::Float64 simplicity_weight::Float64 @@ -749,11 +735,16 @@ end @deprecate xticks(ticks) xticks(ticks=ticks) -""" - Stat.xticks(tics, granularity_weight=1/4, simplicity_weight=1/6, - coverage_weight=1/3, niceness_weight=1/4) +input_aesthetics(stat::TickStatistic) = stat.axis=="x" ? [:x, :xmin, :xmax, :xintercept] : + [:y, :ymin, :ymax, :yintercept, :middle, :lower_hinge, :upper_hinge, :lower_fence, :upper_fence] +output_aesthetics(stat::TickStatistic) = stat.axis=="x" ? [:xtick, :xgrid] : [:ytick, :ygrid] + +xy_ticks(var,in_aess,out_aess) = """ + Stat.$(var)ticks[(; ticks=:auto, granularity_weight=1/4, simplicity_weight=1/6, + coverage_weight=1/3, niceness_weight=1/4)] -Compute an appealing set of ticks that encompass the data. +Compute an appealing set of $(var)-ticks that encompass the data by transforming +$(in_aess) into $(out_aess). # Arguments - `ticks`: A fixed array of ticks, or `nothing` to indicate they should be @@ -762,64 +753,32 @@ Compute an appealing set of ticks that encompass the data. - `simplicity_weight`: Importance of including zero - `coverage_weight`: Importance of tightly fitting the span of the data - `niceness_weight`: Importance of having a nice numbering - -# Aesthetics -All x-axis aesthetics are considered, and ticks are output to the `xtick` and -`xgrid` aesthetics. """ -xticks(; ticks=:auto, + +# can be put on two lines with julia 0.7 +@doc xy_ticks("x",aes2str(input_aesthetics(xticks())), aes2str(output_aesthetics(xticks()))) xticks(; ticks=:auto, granularity_weight=1/4, simplicity_weight=1/6, coverage_weight=1/3, niceness_weight=1/4) = - TickStatistic([:x, :xmin, :xmax, :xintercept], "x", + TickStatistic("x", granularity_weight, simplicity_weight, coverage_weight, niceness_weight, ticks) @deprecate yticks(ticks) yticks(ticks=ticks) -""" - Stat.yticks(tics, granularity_weight=1/4, simplicity_weight=1/6, - coverage_weight=1/3, niceness_weight=1/4) - -Compute an appealing set of ticks that encompass the data. - -# Arguments -- `ticks`: A fixed array of ticks, or `nothing` to indicate they should be - computed. -- `granularity_weight`: Importance of having a reasonable number of ticks. -- `simplicity_weight`: Importance of including zero. -- `coverage_weight`: Importance of tightly fitting the span of the data. -- `niceness_weight`: Importance of having a nice numbering. - -# Aesthetics -All y-axis aesthetics are considered, and ticks are output to the `ytick` and -`ygrid` aesthetics. -""" -yticks(; ticks=:auto, +@doc xy_ticks("y",aes2str(input_aesthetics(yticks())), aes2str(output_aesthetics(yticks()))) yticks(; ticks=:auto, granularity_weight=1/4, simplicity_weight=1/6, coverage_weight=1/3, niceness_weight=1/4) = - TickStatistic([:y, :ymin, :ymax, :yintercept, :middle, :lower_hinge, :upper_hinge, - :lower_fence, :upper_fence], "y", + TickStatistic("y", granularity_weight, simplicity_weight, coverage_weight, niceness_weight, ticks) -# Apply a tick statistic. - -# Args: -# stat: statistic. -# aes: aesthetics. - -# Returns: -# nothing - -# Modifies: -# aes -# function apply_statistic(stat::TickStatistic, scales::Dict{Symbol, Gadfly.ScaleElement}, coord::Gadfly.CoordinateElement, aes::Gadfly.Aesthetics) + in_vars = input_aesthetics(stat) isa(stat.ticks, Symbol) && stat.ticks != :auto && error("Invalid value $(stat.ticks) for ticks parameter.") @@ -827,15 +786,15 @@ function apply_statistic(stat::TickStatistic, error("TickStatistic cannot be applied to subplot coordinates.") # don't clobber existing ticks - getfield(aes, Symbol(stat.out_var, "tick")) == nothing || return + getfield(aes, Symbol(stat.axis, "tick")) == nothing || return - in_group_var = Symbol(stat.out_var, "group") + in_group_var = Symbol(stat.axis, "group") minval, maxval = nothing, nothing in_vals = Any[] - categorical = (:x in stat.in_vars && Scale.iscategorical(scales, :x)) || - (:y in stat.in_vars && Scale.iscategorical(scales, :y)) + categorical = (:x in in_vars && Scale.iscategorical(scales, :x)) || + (:y in in_vars && Scale.iscategorical(scales, :y)) - for var in stat.in_vars + for var in in_vars categorical && !in(var,[:x,:y]) && continue vals = getfield(aes, var) if vals != nothing && eltype(vals) != Function @@ -850,9 +809,9 @@ function apply_statistic(stat::TickStatistic, minval = convert(T, minval) maxval = convert(T, maxval) - if stat.out_var == "x" + if stat.axis == "x" dsize = aes.xsize === nothing ? [nothing] : aes.xsize - elseif stat.out_var == "y" + elseif stat.axis == "y" dsize = aes.ysize === nothing ? [nothing] : aes.ysize else dsize = [nothing] @@ -880,14 +839,14 @@ function apply_statistic(stat::TickStatistic, n = Gadfly.concrete_length(in_vals) # check the x/yviewmin/max pesudo-aesthetics - if stat.out_var == "x" + if stat.axis == "x" if aes.xviewmin != nothing minval = min(minval, aes.xviewmin) end if aes.xviewmax != nothing maxval = max(maxval, aes.xviewmax) end - elseif stat.out_var == "y" + elseif stat.axis == "y" if aes.yviewmin != nothing minval = min(minval, aes.yviewmin) end @@ -899,7 +858,7 @@ function apply_statistic(stat::TickStatistic, # take into account a forced viewport in cartesian coordinates. strict_span = false if typeof(coord) == Coord.Cartesian - if stat.out_var == "x" + if stat.axis == "x" if coord.xmin !== nothing minval = coord.xmin strict_span = true @@ -908,7 +867,7 @@ function apply_statistic(stat::TickStatistic, maxval = coord.xmax strict_span = true end - elseif stat.out_var == "y" + elseif stat.axis == "y" if coord.ymin !== nothing minval = coord.ymin strict_span = true @@ -971,20 +930,20 @@ function apply_statistic(stat::TickStatistic, # We use the first label function we find for any of the aesthetics. I'm not # positive this is the right thing to do, or would would be. - labeler = getfield(aes, Symbol(stat.out_var, "_label")) + labeler = getfield(aes, Symbol(stat.axis, "_label")) - setfield!(aes, Symbol(stat.out_var, "tick"), ticks) - setfield!(aes, Symbol(stat.out_var, "grid"), grids) - setfield!(aes, Symbol(stat.out_var, "tick_label"), labeler) - setfield!(aes, Symbol(stat.out_var, "tickvisible"), tickvisible) - setfield!(aes, Symbol(stat.out_var, "tickscale"), tickscale) + setfield!(aes, Symbol(stat.axis, "tick"), ticks) + setfield!(aes, Symbol(stat.axis, "grid"), grids) + setfield!(aes, Symbol(stat.axis, "tick_label"), labeler) + setfield!(aes, Symbol(stat.axis, "tickvisible"), tickvisible) + setfield!(aes, Symbol(stat.axis, "tickscale"), tickscale) - viewmin_var = Symbol(stat.out_var, "viewmin") + viewmin_var = Symbol(stat.axis, "viewmin") if getfield(aes, viewmin_var) === nothing || getfield(aes, viewmin_var) > viewmin setfield!(aes, viewmin_var, viewmin) end - viewmax_var = Symbol(stat.out_var, "viewmax") + viewmax_var = Symbol(stat.axis, "viewmax") if getfield(aes, viewmax_var) === nothing || getfield(aes, viewmax_var) < viewmax setfield!(aes, viewmax_var, viewmax) end @@ -1060,7 +1019,11 @@ output_aesthetics(stat::BoxplotStatistic) = """ Stat.boxplot[(; method=:tukey)] -Transform $(aes2str(input_aesthetics(boxplot()))) into $(aes2str(output_aesthetics(boxplot()))). +Transform $(aes2str(input_aesthetics(boxplot()))) into +$(aes2str(output_aesthetics(boxplot()))). If `method` is `:tukey` then Tukey's +rule is used (i.e. fences are 1.5 times inter-quartile range). Otherwise, a +vector of 5 numbers giving quantiles for lower fence, lower hinge, middle, +upper hinge, and upper fence in that order. """ const boxplot = BoxplotStatistic @@ -1186,7 +1149,11 @@ output_aesthetics(::SmoothStatistic) = [:x, :y] Stat.smooth[(; method=:loess, smoothing=0.75)] Transform $(aes2str(input_aesthetics(smooth()))) into -$(aes2str(output_aesthetics(smooth()))). +$(aes2str(output_aesthetics(smooth()))). `method` can either be`:loess` or +`:lm`. `smoothing` controls the degree of smoothing. For `:loess`, this is +the span parameter giving the proportion of data used for each local fit where +0.75 is the default. Smaller values use more data (less local context), larger +values use less data (more local context). """ const smooth = SmoothStatistic @@ -1330,20 +1297,13 @@ end StepStatistic(; direction=:hv) = StepStatistic(direction) """ - Stat.step[(; direction)] + Stat.step[(; direction=:hv)] -Perform stepwise interpolation between points. If `x` and `y` define a a series -of points, a new point in inserted between each. Between `(x[i], y[i])` and -`(x[i+1], y[i+1])`, either `(x[i+1], y[i])` or `(x[i], y[i+1])` is inserted, -depending on the `direction` argument. - -# Aesthetics -- `x`: Point x-coordinate. -- `y`: Point y-coordinate. - -# Arguments -- `direction`: Either `:hv` for horizontal then vertical, or `:vh` for - vertical then horizontal. +Perform stepwise interpolation between points. The `x` and `y` aesthetics +define a series of points, and a new point in inserted between each. Between +`(x[i], y[i])` and `(x[i+1], y[i+1])`, either `(x[i+1], y[i])` or `(x[i], +y[i+1])` is inserted, depending on whether the `direction` argument is `:hv` +or `:vh`, respectively. """ const step = StepStatistic @@ -1493,14 +1453,21 @@ struct ContourStatistic <: Gadfly.StatisticElement end ContourStatistic(; levels=15, samples=150) = ContourStatistic(levels, samples) -input_aesthetics(::ContourStatistic) = [:z, :xmin, :xmax, :ymin, :ymax] +input_aesthetics(::ContourStatistic) = [:z, :x, :y, :xmin, :xmax, :ymin, :ymax] output_aesthetics(::ContourStatistic) = [:x, :y, :color, :group] """ Stat.contour[(; levels=15, samples=150)] -Transform $(aes2str(input_aesthetics(contour()))) into -$(aes2str(output_aesthetics(contour()))). +Transform the 2D function or matrix in the `z` aesthetic into a set of lines in +`x` and `y` showing the iso-level contours. A function requires that +either the `x` and `y` or the `xmin`, `xmax`, `ymin` and `ymax` aesthetics also +be defined. The latter are interpolated using `samples`. A matrix can +optionally input `x` and `y` aesthetics to specify the coordinates of the rows +and columns, respectively. In each case `levels` sets the number of contours +to draw: either a vector of contour levels, an integer that specifies the +number of contours to draw, or a function which inputs `z` and outputs either a +vector or an integer. """ const contour = ContourStatistic @@ -1578,13 +1545,10 @@ output_aesthetics(::QQStatistic) = [:x, :y] """ Stat.qq -Generates quantile-quantile plots for `x` and `y`. If each is a numeric vector, -their sample quantiles will be compared. If one is a `Distribution`, then its -theoretical quantiles will be compared with the sample quantiles of the other. - -# Aesthetics -- `x`: Data or `Distribution` to be plotted on the x-axis. -- `y`: Data or `Distribution` to be plotted on the y-axis. +Transform the $(aes2str(input_aesthetics(qq()))) into cumulative distrubutions. +If each is a numeric vector, their sample quantiles will be compared. If one +is a `Distribution`, then its theoretical quantiles will be compared with the +sample quantiles of the other. """ const qq = QQStatistic @@ -1655,10 +1619,11 @@ struct ViolinStatistic <: Gadfly.StatisticElement end ViolinStatistic() = ViolinStatistic(300) -input_aesthetics(::ViolinStatistic) = [:x, :y, :width] +input_aesthetics(::ViolinStatistic) = [:x, :y, :color] +output_aesthetics(::ViolinStatistic) = [:x, :y, :width, :color] """ - Stat.violin[(n=300)] + Stat.violin[(n=300)] ### very similar to Stat.density; could be merged Transform $(aes2str(input_aesthetics(violin()))). """ @@ -1696,7 +1661,7 @@ function apply_statistic(stat::ViolinStatistic, append!(colors, fill(grouped_color[x], length(f.x))) end - colorflag && (aes.color = colors) + colorflag && (aes.color = colors) pad = 0.1 maxwidth = maximum(aes.width) @@ -1712,13 +1677,13 @@ struct JitterStatistic <: Gadfly.StatisticElement end JitterStatistic(vars; range=0.8, seed=0x0af5a1f7) = JitterStatistic(vars, range, seed) -""" - Stat.x_jitter[(; range, seed)] +input_aesthetics(stat::JitterStatistic) = stat.vars +output_aesthetics(stat::JitterStatistic) = stat.vars -Nudge values on the x-axis to avoid overplotting. +xy_jitter(var) = """ + Stat.$(var)_jitter[(; range=0.8, seed=0x0af5a1f7)] -# Asethetics -- `x`: Data to nudge. +Nudge values on the $(var)-axis to avoid overplotting. # Arguments - `range`: Maximum jitter is this number times the resolution of the data, @@ -1726,26 +1691,10 @@ Nudge values on the x-axis to avoid overplotting. points. - `seed`: Seed for RNG used to randomly jitter values. """ -x_jitter(; range=0.8, seed=0x0af5a1f7) = JitterStatistic([:x], range=range, seed=seed) - -""" - Stat.y_jitter[(; range, seed)] - -Nudge values on the y-axis to avoid overplotting. -# Asethetics -- `y`: Data to nudge. +@doc xy_jitter("x") x_jitter(; range=0.8, seed=0x0af5a1f7) = JitterStatistic([:x], range=range, seed=seed) -# Arguments -- `range`: Maximum jitter is this number times the resolution of the data, - where the "resolution" is the smallest non-zero difference between two - points. -- `seed`: Seed for RNG used to randomly jitter values. -""" -y_jitter(; range=0.8, seed=0x0af5a1f7) = JitterStatistic([:y], range=range, seed=seed) - -input_aesthetics(stat::JitterStatistic) = stat.vars -output_aesthetics(stat::JitterStatistic) = stat.vars +@doc xy_jitter("y") y_jitter(; range=0.8, seed=0x0af5a1f7) = JitterStatistic([:y], range=range, seed=seed) function minimum_span(vars::Vector{Symbol}, aes::Gadfly.Aesthetics) span = nothing @@ -1794,23 +1743,17 @@ struct BinMeanStatistic <: Gadfly.StatisticElement end BinMeanStatistic(; n=20) = BinMeanStatistic(n) -""" - Stat.binmean[(; n)] - -Plot the mean of `y` against the mean of `x` within `n` quantile bins of `x`. +input_aesthetics(::BinMeanStatistic) = [:x, :y] +output_aesthetics(::BinMeanStatistic) = [:x, :y] -# Aesthetics -- `x`: Data to be plotted on the x-axis. -- `y`: Data to be plotted on the y-axis. +""" + Stat.binmean[(; n=20)] -# Arguments -- `n`: Number of bins +Transform the $(aes2str(input_aesthetics(binmean()))) into `n` bins each +of which contains the mean within than bin. """ const binmean = BinMeanStatistic -input_aesthetics(::BinMeanStatistic) = [:x, :y] -output_aesthetics(::BinMeanStatistic) = [:x, :y] - function apply_statistic(stat::BinMeanStatistic, scales::Dict{Symbol, Gadfly.ScaleElement}, coord::Gadfly.CoordinateElement, @@ -1934,8 +1877,13 @@ default_scales(stat::VecFieldStatistic, t::Gadfly.Theme=Gadfly.current_theme()) """ Stat.vectorfield[(; smoothness=1.0, scale=1.0, samples=20)] -Transform $(aes2str(input_aesthetics(vectorfield()))) into -$(aes2str(output_aesthetics(vectorfield()))). +Transform the 2D function or matrix in the `z` aesthetic into a set of lines +from `x`, `y` to `xend`, `yend` showing the gradient vectors. A function +requires that either the `x` and `y` or the `xmin`, `xmax`, `ymin` and `ymax` +aesthetics also be defined. The latter are interpolated using `samples`. A +matrix can optionally input `x` and `y` aesthetics to specify the coordinates +of the rows and columns, respectively. In each case, `smoothness` can vary +from 0 to Inf; and `scale` sets the size of vectors. """ const vectorfield = VecFieldStatistic diff --git a/src/theme.jl b/src/theme.jl index c52e1ce00..8b129bf5d 100755 --- a/src/theme.jl +++ b/src/theme.jl @@ -214,20 +214,25 @@ end const theme_stack = Theme[Theme()] """ + current_theme() + Get Theme on top of the theme stack """ current_theme() = theme_stack[end] """ -Set some attributes in the current `Theme`. -See `Theme` for available field. + style(; kwargs...) + +Set some attributes in the current `Theme`. See [Themes](@ref) for available fields. """ style(; kwargs...) = Theme(current_theme(); kwargs...) """ -Set the current theme. Pushes the theme to a stack. You can pop it using `pop_theme`. + push_theme(t) + +Set the current theme. Pushes the theme to a stack. You can pop it using `pop_theme`. You can use this in conjunction with `style` to set a subset of Theme attributes. @@ -243,6 +248,8 @@ end """ + pop_theme() + Go back to using the previous theme See also `push_theme` and `with_theme` @@ -254,6 +261,8 @@ end """ + push_theme(t) + Push a theme by its name. Available options are `:default` and `:dark`. A new theme can be added by adding a method to `get_theme` @@ -267,6 +276,8 @@ push_theme(t::Symbol) = push_theme(get_theme(Val{t}())) """ + get_theme() + Register a theme by name. get_theme(::Val{:mytheme}) = Theme(...) @@ -280,6 +291,8 @@ get_theme(::Val{name}) where {name} = error("No theme $name found") """ + with_theme(f, theme) + Call a function after setting a new theme. Theme can be a `Theme` object or a symbol.