From d1dbb1bf2ad396e43bb792b5664f5e3301b86bac Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Tue, 3 Mar 2020 23:03:46 +0100 Subject: [PATCH 1/2] format file --- src/recipes.jl | 349 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 232 insertions(+), 117 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 89343fd5..9baec4f0 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -44,7 +44,7 @@ end # ---------------------------------------------------------------------------------- -num_series(x::AMat) = size(x,2) +num_series(x::AMat) = size(x, 2) num_series(x) = 1 RecipesBase.apply_recipe(plotattributes::AKW, ::Type{T}, plt::AbstractPlot) where {T} = throw(MethodError(T, "Unmatched plot recipe: $T")) @@ -55,13 +55,26 @@ RecipesBase.apply_recipe(plotattributes::AKW, ::Type{T}, plt::AbstractPlot) wher # for seriestype `line`, need to sort by x values const POTENTIAL_VECTOR_ARGUMENTS = [ - :seriescolor, :seriesalpha, - :linecolor, :linealpha, :linewidth, :linestyle, :line_z, - :fillcolor, :fillalpha, :fill_z, - :markercolor, :markeralpha, :markershape, :marker_z, - :markerstrokecolor, :markerstrokealpha, - :yerror, :yerror, - :series_annotations, :fillrange + :seriescolor, + :seriesalpha, + :linecolor, + :linealpha, + :linewidth, + :linestyle, + :line_z, + :fillcolor, + :fillalpha, + :fill_z, + :markercolor, + :markeralpha, + :markershape, + :marker_z, + :markerstrokecolor, + :markerstrokealpha, + :yerror, + :yerror, + :series_annotations, + :fillrange, ] @recipe function f(::Type{Val{:line}}, x, y, z) @@ -99,7 +112,7 @@ end @recipe function f(::Type{Val{:hline}}, x, y, z) n = length(y) newx = repeat(Float64[-1, 1, NaN], n) - newy = vec(Float64[yi for i=1:3,yi=y]) + newy = vec(Float64[yi for i = 1:3, yi in y]) x := newx y := newy seriestype := :straightline @@ -109,7 +122,7 @@ end @recipe function f(::Type{Val{:vline}}, x, y, z) n = length(y) - newx = vec(Float64[yi for i=1:3,yi=y]) + newx = vec(Float64[yi for i = 1:3, yi in y]) newy = repeat(Float64[-1, 1, NaN], n) x := newx y := newy @@ -121,7 +134,7 @@ end @recipe function f(::Type{Val{:hspan}}, x, y, z) n = div(length(y), 2) newx = repeat([-Inf, Inf, Inf, -Inf, NaN], outer = n) - newy = vcat([[y[2i-1], y[2i-1], y[2i], y[2i], NaN] for i in 1:n]...) + newy = vcat([[y[2i - 1], y[2i - 1], y[2i], y[2i], NaN] for i = 1:n]...) linewidth --> 0 x := newx y := newy @@ -132,7 +145,7 @@ end @recipe function f(::Type{Val{:vspan}}, x, y, z) n = div(length(y), 2) - newx = vcat([[y[2i-1], y[2i-1], y[2i], y[2i], NaN] for i in 1:n]...) + newx = vcat([[y[2i - 1], y[2i - 1], y[2i], y[2i], NaN] for i = 1:n]...) newy = repeat([-Inf, Inf, Inf, -Inf, NaN], outer = n) linewidth --> 0 x := newx @@ -156,7 +169,7 @@ end primary := false () end -() + () end @deps scatterpath path scatter @@ -169,7 +182,7 @@ function make_steps(x::AbstractArray, st) n = length(x) n == 0 && return zeros(0) newx = zeros(2n - 1) - for i in 1:n + for i = 1:n idx = 2i - 1 newx[idx] = x[i] if i > 1 @@ -249,10 +262,10 @@ end end end newx, newy = zeros(3n), zeros(3n) - for i=1:n - rng = 3i-2:3i + for i = 1:n + rng = (3i - 2):(3i) newx[rng] = [x[i], x[i], NaN] - newy[rng] = [_cycle(fr,i), y[i], NaN] + newy[rng] = [_cycle(fr, i), y[i], NaN] end x := newx y := newy @@ -282,16 +295,16 @@ end # get the value of the curve point at position t function bezier_value(pts::AVec, t::Real) val = 0.0 - n = length(pts)-1 - for (i,p) in enumerate(pts) - val += p * binomial(n, i-1) * (1-t)^(n-i+1) * t^(i-1) + n = length(pts) - 1 + for (i, p) in enumerate(pts) + val += p * binomial(n, i - 1) * (1 - t)^(n - i + 1) * t^(i - 1) end val end # create segmented bezier curves in place of line segments @recipe function f(::Type{Val{:curves}}, x, y, z; npoints = 30) - args = z !== nothing ? (x,y,z) : (x,y) + args = z !== nothing ? (x, y, z) : (x, y) newx, newy = zeros(0), zeros(0) fr = plotattributes[:fillrange] newfr = fr !== nothing ? zeros(0) : nothing @@ -304,13 +317,13 @@ end for rng in iter_segments(args...) length(rng) < 2 && continue ts = range(0, stop = 1, length = npoints) - nanappend!(newx, map(t -> bezier_value(_cycle(x,rng), t), ts)) - nanappend!(newy, map(t -> bezier_value(_cycle(y,rng), t), ts)) + nanappend!(newx, map(t -> bezier_value(_cycle(x, rng), t), ts)) + nanappend!(newy, map(t -> bezier_value(_cycle(y, rng), t), ts)) if z !== nothing - nanappend!(newz, map(t -> bezier_value(_cycle(z,rng), t), ts)) + nanappend!(newz, map(t -> bezier_value(_cycle(z, rng), t), ts)) end if fr !== nothing - nanappend!(newfr, map(t -> bezier_value(_cycle(fr,rng), t), ts)) + nanappend!(newfr, map(t -> bezier_value(_cycle(fr, rng), t), ts)) end # if lz !== nothing # lzrng = _cycle(lz, rng) # the line_z's for this segment @@ -343,14 +356,15 @@ end # create a bar plot as a filled step function @recipe function f(::Type{Val{:bar}}, x, y, z) - procx, procy, xscale, yscale, baseline = _preprocess_barlike(plotattributes, x, y) + procx, procy, xscale, yscale, baseline = + _preprocess_barlike(plotattributes, x, y) nx, ny = length(procx), length(procy) axis = plotattributes[:subplot][isvertical(plotattributes) ? :xaxis : :yaxis] - cv = [discrete_value!(axis, xi)[1] for xi=procx] + cv = [discrete_value!(axis, xi)[1] for xi in procx] procx = if nx == ny cv elseif nx == ny + 1 - 0.5diff(cv) + cv[1:end-1] + 0.5 * diff(cv) + cv[1:(end - 1)] else error("bar recipe: x must be same length as y (centers), or one more than y (edges).\n\t\tlength(x)=$(length(x)), length(y)=$(length(y))") end @@ -359,12 +373,12 @@ end bw = plotattributes[:bar_width] hw = if bw === nothing if nx > 1 - 0.5*_bar_width*ignorenan_minimum(filter(x->x>0, diff(procx))) + 0.5 * _bar_width * ignorenan_minimum(filter(x -> x > 0, diff(procx))) else 0.5 * _bar_width end else - Float64[0.5_cycle(bw,i) for i=eachindex(procx)] + Float64[0.5 * _cycle(bw, i) for i in eachindex(procx)] end # make fillto a vector... default fills to 0 @@ -378,13 +392,20 @@ end # create the bar shapes by adding x/y segments xseg, yseg = Segments(), Segments() - for i=1:ny + for i = 1:ny yi = procy[i] if !isnan(yi) center = procx[i] - hwi = _cycle(hw,i) - fi = _cycle(fillto,i) - push!(xseg, center-hwi, center-hwi, center+hwi, center+hwi, center-hwi) + hwi = _cycle(hw, i) + fi = _cycle(fillto, i) + push!( + xseg, + center - hwi, + center - hwi, + center + hwi, + center + hwi, + center - hwi, + ) push!(yseg, yi, fi, fi, yi, yi) end end @@ -415,8 +436,8 @@ end m, n = size(z.surf) x_pts, y_pts = fill(NaN, 6 * m * n), fill(NaN, 6 * m * n) fz = zeros(m * n) - for i in 1:m # y - for j in 1:n # x + for i = 1:m # y + for j = 1:n # x k = (j - 1) * m + i inds = (6 * (k - 1) + 1):(6 * k - 1) x_pts[inds] .= [xe[j], xe[j + 1], xe[j + 1], xe[j], xe[j]] @@ -440,13 +461,17 @@ end # --------------------------------------------------------------------------- # Histograms -_bin_centers(v::AVec) = (v[1:end-1] + v[2:end]) / 2 +_bin_centers(v::AVec) = (v[1:(end - 1)] + v[2:end]) / 2 _is_positive(x) = (x > 0) && !(x ≈ 0) _positive_else_nan(::Type{T}, x::Real) where {T} = _is_positive(x) ? T(x) : T(NaN) -function _scale_adjusted_values(::Type{T}, V::AbstractVector, scale::Symbol) where T<:AbstractFloat +function _scale_adjusted_values( + ::Type{T}, + V::AbstractVector, + scale::Symbol, +) where {T<:AbstractFloat} if scale in _logScales [_positive_else_nan(T, x) for x in V] else @@ -455,7 +480,7 @@ function _scale_adjusted_values(::Type{T}, V::AbstractVector, scale::Symbol) whe end -function _binbarlike_baseline(min_value::T, scale::Symbol) where T<:Real +function _binbarlike_baseline(min_value::T, scale::Symbol) where {T<:Real} if (scale in _logScales) !isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3) else @@ -464,7 +489,11 @@ function _binbarlike_baseline(min_value::T, scale::Symbol) where T<:Real end -function _preprocess_binbarlike_weights(::Type{T}, w, wscale::Symbol) where T<:AbstractFloat +function _preprocess_binbarlike_weights( + ::Type{T}, + w, + wscale::Symbol, +) where {T<:AbstractFloat} w_adj = _scale_adjusted_values(T, w, wscale) w_min = ignorenan_minimum(w_adj) w_max = ignorenan_maximum(w_adj) @@ -490,7 +519,8 @@ end @recipe function f(::Type{Val{:barbins}}, x, y, z) - edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y) + edge, weights, xscale, yscale, baseline = + _preprocess_binlike(plotattributes, x, y) if (plotattributes[:bar_width] === nothing) bar_width := diff(edge) end @@ -503,8 +533,9 @@ end @recipe function f(::Type{Val{:scatterbins}}, x, y, z) - edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y) - xerror := diff(edge)/2 + edge, weights, xscale, yscale, baseline = + _preprocess_binlike(plotattributes, x, y) + xerror := diff(edge) / 2 x := _bin_centers(edge) y := weights seriestype := :scatter @@ -513,7 +544,13 @@ end @deps scatterbins scatter -function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::Symbol) +function _stepbins_path( + edge, + weights, + baseline::Real, + xscale::Symbol, + yscale::Symbol, +) log_scale_x = xscale in _logScales log_scale_y = yscale in _logScales @@ -538,7 +575,7 @@ function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::S w, it_state_w = it_tuple_w if (log_scale_x && a ≈ 0) - a = oftype(a, b/_logScaleBases[xscale]^3) + a = oftype(a, b / _logScaleBases[xscale]^3) end if isnan(w) @@ -575,9 +612,11 @@ end @recipe function f(::Type{Val{:stepbins}}, x, y, z) - axis = plotattributes[:subplot][Plots.isvertical(plotattributes) ? :xaxis : :yaxis] + axis = + plotattributes[:subplot][Plots.isvertical(plotattributes) ? :xaxis : :yaxis] - edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, x, y) + edge, weights, xscale, yscale, baseline = + _preprocess_binlike(plotattributes, x, y) xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale) if !isvertical(plotattributes) @@ -607,9 +646,19 @@ end end Plots.@deps stepbins path -wand_edges(x...) = (@warn("Load the StatsPlots package in order to use :wand bins. Defaulting to :auto", once = true); :auto) +wand_edges(x...) = ( + @warn( + "Load the StatsPlots package in order to use :wand bins. Defaulting to :auto", + once = true + ); + :auto +) -function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto) where N +function _auto_binning_nbins( + vs::NTuple{N,AbstractVector}, + dim::Integer; + mode::Symbol = :auto, +) where {N} max_bins = 10_000 _cl(x) = min(ceil(Int, max(x, one(x))), max_bins) _iqr(v) = (q = quantile(v, 0.75) - quantile(v, 0.25); q > 0 ? q : oftype(q, 1)) @@ -618,8 +667,13 @@ function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::S n_samples = length(LinearIndices(first(vs))) # The nd estimator is the key to most automatic binning methods, and is modified for twodimensional histograms to include correlation - nd = n_samples^(1/(2+N)) - nd = N == 2 ? min(n_samples^(1/(2+N)), nd / (1-cor(first(vs), last(vs))^2)^(3//8)) : nd # the >2-dimensional case does not have a nice solution to correlations + nd = n_samples^(1 / (2 + N)) + nd = N == 2 ? + min( + n_samples^(1 / (2 + N)), + nd / (1 - cor(first(vs), last(vs))^2)^(3 // 8), + ) : + nd # the >2-dimensional case does not have a nice solution to correlations v = vs[dim] @@ -644,32 +698,52 @@ function _auto_binning_nbins(vs::NTuple{N,AbstractVector}, dim::Integer; mode::S end end -_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) where {N} = StatsBase.histrange(vs[dim], binning, :left) -_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) where {N} = _hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning)) -_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::AbstractVector) where {N} = binning +_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) where {N} = + StatsBase.histrange(vs[dim], binning, :left) +_hist_edge(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) where {N} = + _hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning)) +_hist_edge( + vs::NTuple{N,AbstractVector}, + dim::Integer, + binning::AbstractVector, +) where {N} = binning -_hist_edges(vs::NTuple{N,AbstractVector}, binning::NTuple{N, Any}) where {N} = +_hist_edges(vs::NTuple{N,AbstractVector}, binning::NTuple{N,Any}) where {N} = map(dim -> _hist_edge(vs, dim, binning[dim]), (1:N...,)) -_hist_edges(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, AbstractVector}) where {N} = - map(dim -> _hist_edge(vs, dim, binning), (1:N...,)) +_hist_edges( + vs::NTuple{N,AbstractVector}, + binning::Union{Integer,Symbol,AbstractVector}, +) where {N} = map(dim -> _hist_edge(vs, dim, binning), (1:N...,)) _hist_norm_mode(mode::Symbol) = mode _hist_norm_mode(mode::Bool) = mode ? :pdf : :none _filternans(vs::NTuple{1,AbstractVector}) = filter!.(isfinite, vs) -function _filternans(vs::NTuple{N,AbstractVector}) where N - _invertedindex(v, not) = [j for (i,j) in enumerate(v) if !(i ∈ not)] +function _filternans(vs::NTuple{N,AbstractVector}) where {N} + _invertedindex(v, not) = [j for (i, j) in enumerate(v) if !(i ∈ not)] nots = union(Set.(findall.(!isfinite, vs))...) _invertedindex.(vs, Ref(nots)) end -function _make_hist(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) where N +function _make_hist( + vs::NTuple{N,AbstractVector}, + binning; + normed = false, + weights = nothing, +) where {N} localvs = _filternans(vs) edges = _hist_edges(localvs, binning) - h = float( weights === nothing ? - StatsBase.fit(StatsBase.Histogram, localvs, edges, closed = :left) : - StatsBase.fit(StatsBase.Histogram, localvs, StatsBase.Weights(weights), edges, closed = :left) + h = float( + weights === nothing ? + StatsBase.fit(StatsBase.Histogram, localvs, edges, closed = :left) : + StatsBase.fit( + StatsBase.Histogram, + localvs, + StatsBase.Weights(weights), + edges, + closed = :left, + ), ) normalize!(h, mode = _hist_norm_mode(normed)) end @@ -682,7 +756,12 @@ end @deps histogram barhist @recipe function f(::Type{Val{:barhist}}, x, y, z) - h = _make_hist((y,), plotattributes[:bins], normed = plotattributes[:normalize], weights = plotattributes[:weights]) + h = _make_hist( + (y,), + plotattributes[:bins], + normed = plotattributes[:normalize], + weights = plotattributes[:weights], + ) x := h.edges[1] y := h.weights seriestype := :barbins @@ -691,7 +770,12 @@ end @deps barhist barbins @recipe function f(::Type{Val{:stephist}}, x, y, z) - h = _make_hist((y,), plotattributes[:bins], normed = plotattributes[:normalize], weights = plotattributes[:weights]) + h = _make_hist( + (y,), + plotattributes[:bins], + normed = plotattributes[:normalize], + weights = plotattributes[:weights], + ) x := h.edges[1] y := h.weights seriestype := :stepbins @@ -700,7 +784,12 @@ end @deps stephist stepbins @recipe function f(::Type{Val{:scatterhist}}, x, y, z) - h = _make_hist((y,), plotattributes[:bins], normed = plotattributes[:normalize], weights = plotattributes[:weights]) + h = _make_hist( + (y,), + plotattributes[:bins], + normed = plotattributes[:normalize], + weights = plotattributes[:weights], + ) x := h.edges[1] y := h.weights seriestype := :scatterbins @@ -709,19 +798,23 @@ end @deps scatterhist scatterbins -@recipe function f(h::StatsBase.Histogram{T, 1, E}) where {T, E} +@recipe function f(h::StatsBase.Histogram{T,1,E}) where {T,E} seriestype --> :barbins st_map = Dict( - :bar => :barbins, :scatter => :scatterbins, :step => :stepbins, - :steppost => :stepbins # :step can be mapped to :steppost in pre-processing + :bar => :barbins, + :scatter => :scatterbins, + :step => :stepbins, + :steppost => :stepbins, # :step can be mapped to :steppost in pre-processing ) - seriestype := get(st_map, plotattributes[:seriestype], plotattributes[:seriestype]) + seriestype := + get(st_map, plotattributes[:seriestype], plotattributes[:seriestype]) if plotattributes[:seriestype] == :scatterbins # Workaround, error bars currently not set correctly by scatterbins - edge, weights, xscale, yscale, baseline = _preprocess_binlike(plotattributes, h.edges[1], h.weights) - xerror --> diff(h.edges[1])/2 + edge, weights, xscale, yscale, baseline = + _preprocess_binlike(plotattributes, h.edges[1], h.weights) + xerror --> diff(h.edges[1]) / 2 seriestype := :scatter (Plots._bin_centers(edge), weights) else @@ -730,7 +823,7 @@ end end -@recipe function f(hv::AbstractVector{H}) where H <: StatsBase.Histogram +@recipe function f(hv::AbstractVector{H}) where {H<:StatsBase.Histogram} for h in hv @series begin h @@ -769,7 +862,12 @@ Plots.@deps bins2d heatmap @recipe function f(::Type{Val{:histogram2d}}, x, y, z) - h = _make_hist((x, y), plotattributes[:bins], normed = plotattributes[:normalize], weights = plotattributes[:weights]) + h = _make_hist( + (x, y), + plotattributes[:bins], + normed = plotattributes[:normalize], + weights = plotattributes[:weights], + ) x := h.edges[1] y := h.edges[2] z := Surface(h.weights) @@ -779,7 +877,7 @@ end @deps histogram2d bins2d -@recipe function f(h::StatsBase.Histogram{T, 2, E}) where {T, E} +@recipe function f(h::StatsBase.Histogram{T,2,E}) where {T,E} seriestype --> :bins2d (h.edges[1], h.edges[2], Surface(h.weights)) end @@ -855,7 +953,11 @@ end @recipe function f(::Type{Val{:yerror}}, x, y, z) error_style!(plotattributes) markershape := :hline - plotattributes[:x], plotattributes[:y] = error_coords(plotattributes[:x], plotattributes[:y], error_zipit(plotattributes[:yerror])) + plotattributes[:x], plotattributes[:y] = error_coords( + plotattributes[:x], + plotattributes[:y], + error_zipit(plotattributes[:yerror]), + ) () end @deps yerror path @@ -863,7 +965,11 @@ end @recipe function f(::Type{Val{:xerror}}, x, y, z) error_style!(plotattributes) markershape := :vline - plotattributes[:y], plotattributes[:x] = error_coords(plotattributes[:y], plotattributes[:x], error_zipit(plotattributes[:xerror])) + plotattributes[:y], plotattributes[:x] = error_coords( + plotattributes[:y], + plotattributes[:x], + error_zipit(plotattributes[:xerror]), + ) () end @deps xerror path @@ -898,15 +1004,15 @@ function quiver_using_arrows(plotattributes::AKW) first(vi), last(vi) elseif isscalar(vi) vi, vi - elseif isa(vi,Function) + elseif isa(vi, Function) vi(xi, yi) else error("unexpected vi type $(typeof(vi)) for quiver: $vi") end # add the points - nanappend!(x, [xi, xi+vx, NaN]) - nanappend!(y, [yi, yi+vy, NaN]) + nanappend!(x, [xi, xi + vx, NaN]) + nanappend!(y, [yi, yi + vy, NaN]) end plotattributes[:x], plotattributes[:y] = x, y @@ -936,7 +1042,7 @@ function quiver_using_hack(plotattributes::AKW) first(vi), last(vi) elseif isscalar(vi) vi, vi - elseif isa(vi,Function) + elseif isa(vi, Function) vi(xi, yi) else error("unexpected vi type $(typeof(vi)) for quiver: $vi") @@ -951,8 +1057,11 @@ function quiver_using_hack(plotattributes::AKW) U1 *= arrow_h U2 *= arrow_w - ppv = p+v - nanappend!(pts, P2[p, ppv-U1, ppv-U1+U2, ppv, ppv-U1-U2, ppv-U1]) + ppv = p + v + nanappend!( + pts, + P2[p, ppv - U1, ppv - U1 + U2, ppv, ppv - U1 - U2, ppv - U1], + ) end plotattributes[:x], plotattributes[:y] = Plots.unzip(pts[2:end]) @@ -977,32 +1086,28 @@ end "Represent Open High Low Close data (used in finance)" mutable struct OHLC{T<:Real} - open::T - high::T - low::T - close::T + open::T + high::T + low::T + close::T end Base.convert(::Type{OHLC}, tup::Tuple) = OHLC(tup...) # Base.tuple(ohlc::OHLC) = (ohlc.open, ohlc.high, ohlc.low, ohlc.close) # get one OHLC path function get_xy(o::OHLC, x, xdiff) - xl, xm, xr = x-xdiff, x, x+xdiff - ox = [xl, xm, NaN, - xm, xm, NaN, - xm, xr] - oy = [o.open, o.open, NaN, - o.low, o.high, NaN, - o.close, o.close] + xl, xm, xr = x - xdiff, x, x + xdiff + ox = [xl, xm, NaN, xm, xm, NaN, xm, xr] + oy = [o.open, o.open, NaN, o.low, o.high, NaN, o.close, o.close] ox, oy end # get the joined vector function get_xy(v::AVec{OHLC}, x = eachindex(v)) - xdiff = 0.3ignorenan_mean(abs.(diff(x))) + xdiff = 0.3 * ignorenan_mean(abs.(diff(x))) x_out, y_out = zeros(0), zeros(0) - for (i,ohlc) in enumerate(v) - ox,oy = get_xy(ohlc, x[i], xdiff) + for (i, ohlc) in enumerate(v) + ox, oy = get_xy(ohlc, x[i], xdiff) nanappend!(x_out, ox) nanappend!(y_out, oy) end @@ -1015,10 +1120,17 @@ end # to squash ambiguity warnings... @recipe f(x::AVec{Function}, v::AVec{OHLC}) = error() -@recipe f(x::AVec{Function}, v::AVec{Tuple{R1,R2,R3,R4}}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = error() +@recipe f( + x::AVec{Function}, + v::AVec{Tuple{R1,R2,R3,R4}}, +) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = error() # this must be OHLC? -@recipe f(x::AVec, ohlc::AVec{Tuple{R1,R2,R3,R4}}) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = x, OHLC[OHLC(t...) for t in ohlc] +@recipe f( + x::AVec, + ohlc::AVec{Tuple{R1,R2,R3,R4}}, +) where {R1<:Number,R2<:Number,R3<:Number,R4<:Number} = + x, OHLC[OHLC(t...) for t in ohlc] @recipe function f(x::AVec, v::AVec{OHLC}) seriestype := :path @@ -1056,11 +1168,11 @@ end @assert length(g.args) == 1 && typeof(g.args[1]) <: AbstractMatrix seriestype := :spy mat = g.args[1] - n,m = axes(mat) + n, m = axes(mat) Plots.SliceIt, m, n, Surface(mat) end -@recipe function f(::Type{Val{:spy}}, x,y,z) +@recipe function f(::Type{Val{:spy}}, x, y, z) yflip := true aspect_ratio := 1 rs, cs, zs = findnz(z.surf) @@ -1086,7 +1198,8 @@ end # ------------------------------------------------- "Adds ax+b... straight line over the current plot, without changing the axis limits" -abline!(plt::Plot, a, b; kw...) = plot!(plt, [0, 1], [b, b+a]; seriestype = :straightline, kw...) +abline!(plt::Plot, a, b; kw...) = + plot!(plt, [0, 1], [b, b + a]; seriestype = :straightline, kw...) abline!(args...; kw...) = abline!(current(), args...; kw...) @@ -1099,9 +1212,11 @@ datetimeformatter(dt) = string(DateTime(Dates.UTM(dt))) timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t))) @recipe f(::Type{Date}, dt::Date) = (dt -> Dates.value(dt), dateformatter) -@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> Dates.value(dt), datetimeformatter) +@recipe f(::Type{DateTime}, dt::DateTime) = + (dt -> Dates.value(dt), datetimeformatter) @recipe f(::Type{Dates.Time}, t::Dates.Time) = (t -> Dates.value(t), timeformatter) -@recipe f(::Type{P}, t::P) where P <: Dates.Period = (t -> Dates.value(t), t -> string(P(t))) +@recipe f(::Type{P}, t::P) where {P<:Dates.Period} = + (t -> Dates.value(t), t -> string(P(t))) # ------------------------------------------------- # Characters @@ -1111,7 +1226,7 @@ timeformatter(t) = string(Dates.Time(Dates.Nanosecond(t))) # ------------------------------------------------- # Complex Numbers -@recipe function f(A::Array{Complex{T}}) where T<:Number +@recipe function f(A::Array{Complex{T}}) where {T<:Number} xguide --> "Re(x)" yguide --> "Im(x)" real.(A), imag.(A) @@ -1120,10 +1235,10 @@ end # Splits a complex matrix to its real and complex parts # Reals defaults solid, imaginary defaults dashed # Label defaults are changed to match the real-imaginary reference / indexing -@recipe function f(x::AbstractArray{T},y::Array{Complex{T2}}) where {T<:Real,T2} - ylabel --> "Re(y)" - zlabel --> "Im(y)" - x,real.(y),imag.(y) +@recipe function f(x::AbstractArray{T}, y::Array{Complex{T2}}) where {T<:Real,T2} + ylabel --> "Re(y)" + zlabel --> "Im(y)" + x, real.(y), imag.(y) end @@ -1137,7 +1252,7 @@ end end library = PlotUtils.color_libraries[cl.args[1]] - z = sqrt.((1:15)*reshape(1:20,1,:)) + z = sqrt.((1:15) * reshape(1:20, 1, :)) seriestype := :heatmap ticks := nothing @@ -1161,7 +1276,7 @@ end if !(length(grad.args) == 1 && isa(grad.args[1], Symbol)) error("showgradient takes the name of a color gradient as a Symbol") end - z = sqrt.((1:15)*reshape(1:20,1,:)) + z = sqrt.((1:15) * reshape(1:20, 1, :)) seriestype := :heatmap ticks := nothing legend := false @@ -1184,9 +1299,9 @@ end weights = cumsum(weights, dims = 2) seriestype := :shape - # create a filled polygon for each item - for c=axes(weights,2) - sx = vcat(weights[:,c], c==1 ? zeros(n) : reverse(weights[:,c-1])) + # create a filled polygon for each item + for c in axes(weights, 2) + sx = vcat(weights[:, c], c == 1 ? zeros(n) : reverse(weights[:, c - 1])) sy = vcat(returns, reverse(returns)) @series Plots.isvertical(plotattributes) ? (sx, sy) : (sy, sx) end @@ -1205,13 +1320,13 @@ julia> areaplot(1:3, [1 2 3; 7 8 9; 4 5 6], seriescolor = [:red :green :blue], f @userplot AreaPlot @recipe function f(a::AreaPlot) - data = cumsum(a.args[end], dims=2) + data = cumsum(a.args[end], dims = 2) x = length(a.args) == 1 ? (axes(data, 1)) : a.args[1] seriestype := :line for i in axes(data, 2) @series begin - fillrange := i > 1 ? data[:,i-1] : 0 - x, data[:,i] + fillrange := i > 1 ? data[:, i - 1] : 0 + x, data[:, i] end end end From 369d510b3ef9f482b79474ce7fe3774ecfd55608 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Wed, 4 Mar 2020 14:48:21 +0100 Subject: [PATCH 2/2] format examples.jl --- src/examples.jl | 1398 +++++++++++++++++++++++++++++------------------ 1 file changed, 879 insertions(+), 519 deletions(-) diff --git a/src/examples.jl b/src/examples.jl index a00a61d9..9cf91a05 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -2,503 +2,857 @@ Holds all data needed for a documentation example... header, description, and plotting expression (Expr) """ mutable struct PlotExample - header::AbstractString - desc::AbstractString - exprs::Vector{Expr} + header::AbstractString + desc::AbstractString + exprs::Vector{Expr} end # the _examples we'll run for each const _examples = PlotExample[ + PlotExample( + "Lines", + "A simple line plot of the columns.", + [:( + begin + plot(Plots.fakedata(50, 5), w = 3) + end + )], + ), + PlotExample( + "Functions, adding data, and animations", + """ + Plot multiple functions. You can also put the function first, or use the form `plot(f, + xmin, xmax)` where f is a Function or AbstractVector{Function}.\n\nGet series data: + `x, y = plt[i]`. Set series data: `plt[i] = (x,y)`. Add to the series with + `push!`/`append!`.\n\nEasily build animations. (`convert` or `ffmpeg` must be available + to generate the animation.) Use command `gif(anim, filename, fps=15)` to save the + animation. + """, + [:( + begin + p = plot([sin, cos], zeros(0), leg = false) + anim = Animation() + for x in range(0, stop = 10π, length = 100) + push!(p, x, Float64[sin(x), cos(x)]) + frame(anim) + end + end + )], + ), + PlotExample( + "Parametric plots", + "Plot function pair (x(u), y(u)).", + [ + :( + begin + plot( + sin, + x -> sin(2x), + 0, + 2π, + line = 4, + leg = false, + fill = (0, :orange), + ) + end + ), + ], + ), + PlotExample( + "Colors", + """ + Access predefined palettes (or build your own with the `colorscheme` method). + Line/marker colors are auto-generated from the plot's palette, unless overridden. Set + the `z` argument to turn on series gradients. + """, + [ + :( + begin + y = rand(100) + plot( + 0:10:100, + rand(11, 4), + lab = "lines", + w = 3, + palette = :grays, + fill = 0, + α = 0.6, + ) + scatter!( + y, + zcolor = abs.(y .- 0.5), + m = (:heat, 0.8, Plots.stroke(1, :green)), + ms = 10 * abs.(y .- 0.5) .+ 4, + lab = "grad", + ) + end + ), + ], + ), + PlotExample( + "Global", + """ + Change the guides/background/limits/ticks. Convenience args `xaxis` and `yaxis` allow + you to pass a tuple or value which will be mapped to the relevant args automatically. + The `xaxis` below will be replaced with `xlabel` and `xlims` args automatically during + the preprocessing step. You can also use shorthand functions: `title!`, `xaxis!`, + `yaxis!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!` + """, + [ + :( + begin + using Statistics + y = rand(20, 3) + plot( + y, + xaxis = ("XLABEL", (-5, 30), 0:2:20, :flip), + background_color = RGB(0.2, 0.2, 0.2), + leg = false, + ) + hline!( + mean(y, dims = 1) + rand(1, 3), + line = (4, :dash, 0.6, [:lightgreen :green :darkgreen]), + ) + vline!([5, 10]) + title!("TITLE") + yaxis!("YLABEL", :log10) + end + ), + ], + ), -PlotExample("Lines", - "A simple line plot of the columns.", - [:(begin - plot(Plots.fakedata(50,5), w=3) - end)] -), + # PlotExample("Two-axis", + # "Use the `axis` arguments.", + # [ + # :(plot(Vector[randn(100), randn(100)*100], axis = [:l :r], ylabel="LEFT", yrightlabel="RIGHT", xlabel="X", title="TITLE")) + # ]), -PlotExample("Functions, adding data, and animations", -""" -Plot multiple functions. You can also put the function first, or use the form `plot(f, -xmin, xmax)` where f is a Function or AbstractVector{Function}.\n\nGet series data: -`x, y = plt[i]`. Set series data: `plt[i] = (x,y)`. Add to the series with -`push!`/`append!`.\n\nEasily build animations. (`convert` or `ffmpeg` must be available -to generate the animation.) Use command `gif(anim, filename, fps=15)` to save the -animation. -""", - [:(begin - p = plot([sin,cos], zeros(0), leg=false) - anim = Animation() - for x in range(0, stop=10π, length=100) - push!(p, x, Float64[sin(x), cos(x)]) - frame(anim) + PlotExample( + "Images", + "Plot an image. y-axis is set to flipped", + [ + :( + begin + import FileIO + path = + download("http://juliaplots.org/PlotReferenceImages.jl/Plots/pyplot/0.7.0/ref1.png") + img = FileIO.load(path) + plot(img) + end + ), + ], + ), + PlotExample( + "Arguments", + """ + Plot multiple series with different numbers of points. Mix arguments that apply to all + series (marker/markersize) with arguments unique to each series (colors). Special + arguments `line`, `marker`, and `fill` will automatically figure out what arguments to + set (for example, we are setting the `linestyle`, `linewidth`, and `color` arguments with + `line`.) Note that we pass a matrix of colors, and this applies the colors to each + series. + """, + [ + :( + begin + ys = Vector[rand(10), rand(20)] + plot( + ys, + color = [:black :orange], + line = (:dot, 4), + marker = ([:hex :d], 12, 0.8, Plots.stroke(3, :gray)), + ) + end + ), + ], + ), + PlotExample( + "Build plot in pieces", + "Start with a base plot...", + [:( + begin + plot(rand(100) / 3, reg = true, fill = (0, :green)) + end + )], + ), + PlotExample( + "", + "and add to it later.", + [:( + begin + scatter!(rand(100), markersize = 6, c = :orange) + end + )], + ), + PlotExample( + "Histogram2D", + "", + [:( + begin + histogram2d(randn(10000), randn(10000), nbins = 20) + end + )], + ), + PlotExample( + "Line types", + "", + [ + :( + begin + linetypes = [:path :steppre :steppost :sticks :scatter] + n = length(linetypes) + x = Vector[sort(rand(20)) for i = 1:n] + y = rand(20, n) + plot( + x, + y, + line = (linetypes, 3), + lab = map(string, linetypes), + ms = 15, + ) + end + ), + ], + ), + PlotExample( + "Line styles", + "", + [ + :( + begin + styles = filter( + s -> s in Plots.supported_styles(), + [:solid, :dash, :dot, :dashdot, :dashdotdot], + ) + styles = reshape(styles, 1, length(styles)) # Julia 0.6 unfortunately gives an error when transposing symbol vectors + n = length(styles) + y = cumsum(randn(20, n), dims = 1) + plot( + y, + line = (5, styles), + label = map(string, styles), + legendtitle = "linestyle", + ) + end + ), + ], + ), + PlotExample( + "Marker types", + "", + [ + :( + begin + markers = filter( + m -> m in Plots.supported_markers(), + Plots._shape_keys, + ) + markers = reshape(markers, 1, length(markers)) + n = length(markers) + x = range(0, stop = 10, length = n + 2)[2:(end - 1)] + y = repeat(reshape(reverse(x), 1, :), n, 1) + scatter( + x, + y, + m = (8, :auto), + lab = map(string, markers), + bg = :linen, + xlim = (0, 10), + ylim = (0, 10), + ) + end + ), + ], + ), + PlotExample( + "Bar", + "`x` is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)", + [:( + begin + bar(randn(99)) + end + )], + ), + PlotExample( + "Histogram", + "", + [ + :( + begin + histogram( + randn(1000), + bins = :scott, + weights = repeat(1:5, outer = 200), + ) + end + ), + ], + ), + PlotExample( + "Subplots", + """ + Use the `layout` keyword, and optionally the convenient `@layout` macro to generate + arbitrarily complex subplot layouts. + """, + [ + :( + begin + l = @layout([a{0.1h}; b [c; d e]]) + plot( + randn(100, 5), + layout = l, + t = [:line :histogram :scatter :steppre :bar], + leg = false, + ticks = nothing, + border = :none, + ) + end + ), + ], + ), + PlotExample( + "Adding to subplots", + """ + Note here the automatic grid layout, as well as the order in which new series are added + to the plots. + """, + [ + :( + begin + plot( + Plots.fakedata(100, 10), + layout = 4, + palette = [:grays :blues :heat :lightrainbow], + bg_inside = [:orange :pink :darkblue :black], + ) + end + ), + ], + ), + PlotExample("", "", [:( + begin + using Random + Random.seed!(111) + plot!(Plots.fakedata(100, 10)) end - end)] -), + )]), + PlotExample( + "Open/High/Low/Close", + """ + Create an OHLC chart. Pass in a list of (open,high,low,close) tuples as your `y` + argument. This uses recipes to first convert the tuples to OHLC objects, and + subsequently create a :path series with the appropriate line segments. + """, + [ + :( + begin + n = 20 + hgt = rand(n) .+ 1 + bot = randn(n) + openpct = rand(n) + closepct = rand(n) + y = OHLC[ + ( + openpct[i] * hgt[i] + bot[i], + bot[i] + hgt[i], + bot[i], + closepct[i] * hgt[i] + bot[i], + ) + for i = 1:n + ] + ohlc(y) + end + ), + ], + ), + PlotExample( + "Annotations", + """ + The `annotations` keyword is used for text annotations in data-coordinates. Pass in a + tuple (x,y,text) or a vector of annotations. `annotate!(ann)` is shorthand for `plot!(; + annotation=ann)`. Series annotations are used for annotating individual data points. + They require only the annotation... x/y values are computed. A `PlotText` object can be + build with the method `text(string, attr...)`, which wraps font and color attributes. + """, + [ + :( + begin + y = rand(10) + plot( + y, + annotations = (3, y[3], Plots.text("this is #3", :left)), + leg = false, + ) + annotate!([ + (5, y[5], Plots.text("this is #5", 16, :red, :center)), + ( + 10, + y[10], + Plots.text("this is #10", :right, 20, "courier"), + ), + ]) + scatter!( + range(2, stop = 8, length = 6), + rand(6), + marker = (50, 0.2, :orange), + series_annotations = [ + "series", + "annotations", + "map", + "to", + "series", + Plots.text("data", :green), + ], + ) + end + ), + ], + ), + PlotExample( + "Custom Markers", + """A `Plots.Shape` is a light wrapper around vertices of a polygon. For supported + backends, pass arbitrary polygons as the marker shapes. Note: The center is (0,0) and + the size is expected to be rougly the area of the unit circle. + """, + [ + :( + begin + verts = [ + (-1.0, 1.0), + (-1.28, 0.6), + (-0.2, -1.4), + (0.2, -1.4), + (1.28, 0.6), + (1.0, 1.0), + (-1.0, 1.0), + (-0.2, -0.6), + (0.0, -0.2), + (-0.4, 0.6), + (1.28, 0.6), + (0.2, -1.4), + (-0.2, -1.4), + (0.6, 0.2), + (-0.2, 0.2), + (0.0, -0.2), + (0.2, 0.2), + (-0.2, -0.6), + ] + x = 0.1:0.2:0.9 + y = 0.7 * rand(5) .+ 0.15 + plot( + x, + y, + line = (3, :dash, :lightblue), + marker = (Shape(verts), 30, RGBA(0, 0, 0, 0.2)), + bg = :pink, + fg = :darkblue, + xlim = (0, 1), + ylim = (0, 1), + leg = false, + ) + end + ), + ], + ), + PlotExample( + "Contours", + """ + Any value for fill works here. We first build a filled contour from a function, then an + unfilled contour from a matrix. + """, + [:( + begin + x = 1:0.5:20 + y = 1:0.5:10 + f(x, y) = (3x + y^2) * abs(sin(x) + cos(y)) + X = repeat(reshape(x, 1, :), length(y), 1) + Y = repeat(y, 1, length(x)) + Z = map(f, X, Y) + p1 = contour(x, y, f, fill = true) + p2 = contour(x, y, Z) + plot(p1, p2) + end + )], + ), + PlotExample( + "Pie", + "", + [:( + begin + x = ["Nerds", "Hackers", "Scientists"] + y = [0.4, 0.35, 0.25] + pie(x, y, title = "The Julia Community", l = 0.5) + end + )], + ), + PlotExample( + "3D", + "", + [ + :( + begin + n = 100 + ts = range(0, stop = 8π, length = n) + x = ts .* map(cos, ts) + y = 0.1ts .* map(sin, ts) + z = 1:n + plot( + x, + y, + z, + zcolor = reverse(z), + m = (10, 0.8, :blues, Plots.stroke(0)), + leg = false, + cbar = true, + w = 5, + ) + plot!(zeros(n), zeros(n), 1:n, w = 10) + end + ), + ], + ), + PlotExample( + "DataFrames", + "Plot using DataFrame column symbols.", + [ + :(using StatsPlots), # can't be inside begin block because @df gets expanded first + :( + begin + import RDatasets + iris = RDatasets.dataset("datasets", "iris") + @df iris scatter( + :SepalLength, + :SepalWidth, + group = :Species, + title = "My awesome plot", + xlabel = "Length", + ylabel = "Width", + marker = (0.5, [:cross :hex :star7], 12), + bg = RGB(0.2, 0.2, 0.2), + ) + end + ), + ], + ), + PlotExample( + "Groups and Subplots", + "", + [ + :( + begin + group = rand(map(i -> "group $i", 1:4), 100) + plot( + rand(100), + layout = @layout([a b; c]), + group = group, + linetype = [:bar :scatter :steppre], + linecolor = :match, + ) + end + ), + ], + ), + PlotExample( + "Polar Plots", + "", + [:( + begin + Θ = range(0, stop = 1.5π, length = 100) + r = abs.(0.1 * randn(100) + sin.(3Θ)) + plot(Θ, r, proj = :polar, m = 2) + end + )], + ), + PlotExample( + "Heatmap, categorical axes, and aspect_ratio", + "", + [:( + begin + xs = [string("x", i) for i = 1:10] + ys = [string("y", i) for i = 1:4] + z = float((1:4) * reshape(1:10, 1, :)) + heatmap(xs, ys, z, aspect_ratio = 1) + end + )], + ), + PlotExample( + "Layouts, margins, label rotation, title location", + "", + [ + :( + begin + using Plots.PlotMeasures # for Measures, e.g. mm and px + plot( + rand(100, 6), + layout = @layout([a b; c]), + title = ["A" "B" "C"], + title_location = :left, + left_margin = [20mm 0mm], + bottom_margin = 10px, + xrotation = 60, + ) + end + ), + ], + ), + PlotExample( + "Boxplot and Violin series recipes", + "", + [ + :(using StatsPlots), # can't be inside begin block because @df gets expanded first + :( + begin + import RDatasets + singers = RDatasets.dataset("lattice", "singer") + @df singers violin( + :VoicePart, + :Height, + line = 0, + fill = (0.2, :blue), + ) + @df singers boxplot!( + :VoicePart, + :Height, + line = (2, :black), + fill = (0.3, :orange), + ) + end + ), + ], + ), + PlotExample( + "Animation with subplots", + "The `layout` macro can be used to create an animation with subplots.", + [ + :( + begin + l = @layout([[a; b] c]) + p = plot( + plot([sin, cos], 1, leg = false), + scatter([atan, cos], 1, leg = false), + plot(log, 1, xlims = (1, 10π), ylims = (0, 5), leg = false), + layout = l, + ) -PlotExample("Parametric plots", - "Plot function pair (x(u), y(u)).", - [:(begin - plot(sin, x->sin(2x), 0, 2π, line=4, leg=false, fill=(0,:orange)) - end)] -), - -PlotExample("Colors", -""" -Access predefined palettes (or build your own with the `colorscheme` method). -Line/marker colors are auto-generated from the plot's palette, unless overridden. Set -the `z` argument to turn on series gradients. -""", - [:(begin -y = rand(100) -plot(0:10:100,rand(11,4),lab="lines",w=3,palette=:grays,fill=0, α=0.6) -scatter!(y, zcolor=abs.(y.-0.5), m=(:heat,0.8,Plots.stroke(1,:green)), ms=10*abs.(y.-0.5).+4, - lab="grad") - end)] -), - -PlotExample("Global", -""" -Change the guides/background/limits/ticks. Convenience args `xaxis` and `yaxis` allow -you to pass a tuple or value which will be mapped to the relevant args automatically. -The `xaxis` below will be replaced with `xlabel` and `xlims` args automatically during -the preprocessing step. You can also use shorthand functions: `title!`, `xaxis!`, -`yaxis!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!` -""", - [:(begin -using Statistics -y = rand(20,3) -plot(y, xaxis=("XLABEL",(-5,30),0:2:20,:flip), background_color = RGB(0.2,0.2,0.2), - leg=false) -hline!(mean(y, dims = 1)+rand(1,3), line=(4,:dash,0.6,[:lightgreen :green :darkgreen])) -vline!([5,10]) -title!("TITLE") -yaxis!("YLABEL", :log10) - end)] -), - -# PlotExample("Two-axis", -# "Use the `axis` arguments.", -# [ -# :(plot(Vector[randn(100), randn(100)*100], axis = [:l :r], ylabel="LEFT", yrightlabel="RIGHT", xlabel="X", title="TITLE")) -# ]), - -PlotExample("Images", - "Plot an image. y-axis is set to flipped", - [:(begin - import FileIO - path = download("http://juliaplots.org/PlotReferenceImages.jl/Plots/pyplot/0.7.0/ref1.png") - img = FileIO.load(path) - plot(img) - end)] -), - -PlotExample("Arguments", -""" -Plot multiple series with different numbers of points. Mix arguments that apply to all -series (marker/markersize) with arguments unique to each series (colors). Special -arguments `line`, `marker`, and `fill` will automatically figure out what arguments to -set (for example, we are setting the `linestyle`, `linewidth`, and `color` arguments with -`line`.) Note that we pass a matrix of colors, and this applies the colors to each -series. -""", - [:(begin - ys = Vector[rand(10), rand(20)] - plot(ys, color=[:black :orange], line=(:dot,4), marker=([:hex :d],12,0.8,Plots.stroke(3,:gray))) - end)] -), - -PlotExample("Build plot in pieces", - "Start with a base plot...", - [:(begin - plot(rand(100)/3, reg=true, fill=(0,:green)) - end)] -), - -PlotExample("", - "and add to it later.", - [:(begin - scatter!(rand(100), markersize=6, c=:orange) - end)] -), - -PlotExample("Histogram2D", - "", - [:(begin - histogram2d(randn(10000), randn(10000), nbins=20) - end)] -), - -PlotExample("Line types", - "", - [:(begin - linetypes = [:path :steppre :steppost :sticks :scatter] - n = length(linetypes) - x = Vector[sort(rand(20)) for i in 1:n] - y = rand(20,n) - plot(x, y, line=(linetypes,3), lab=map(string,linetypes), ms=15) - end)] -), - -PlotExample("Line styles", - "", - [:(begin -styles = filter(s -> s in Plots.supported_styles(), - [:solid, :dash, :dot, :dashdot, :dashdotdot]) -styles = reshape(styles, 1, length(styles)) # Julia 0.6 unfortunately gives an error when transposing symbol vectors -n = length(styles) -y = cumsum(randn(20,n), dims = 1) -plot(y, line = (5, styles), label = map(string,styles), legendtitle = "linestyle") - end)] -), - -PlotExample("Marker types", - "", - [:(begin - markers = filter(m -> m in Plots.supported_markers(), Plots._shape_keys) - markers = reshape(markers, 1, length(markers)) - n = length(markers) - x = range(0, stop=10, length=n+2)[2:end-1] - y = repeat(reshape(reverse(x),1,:), n, 1) - scatter(x, y, m=(8,:auto), lab=map(string,markers), bg=:linen, xlim=(0,10), ylim=(0,10)) - end)] -), - -PlotExample("Bar", - "`x` is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)", - [:(begin - bar(randn(99)) - end)] -), - -PlotExample("Histogram", - "", - [:(begin - histogram(randn(1000), bins = :scott, weights = repeat(1:5, outer = 200)) - end)] -), - -PlotExample("Subplots", -""" -Use the `layout` keyword, and optionally the convenient `@layout` macro to generate -arbitrarily complex subplot layouts. -""", - [:(begin -l = @layout([a{0.1h}; b [c;d e]]) -plot(randn(100,5), layout=l, t=[:line :histogram :scatter :steppre :bar], leg=false, - ticks=nothing, border=:none) - end)] -), - -PlotExample("Adding to subplots", -""" -Note here the automatic grid layout, as well as the order in which new series are added -to the plots. -""", - [:(begin -plot(Plots.fakedata(100,10), layout=4, palette=[:grays :blues :heat :lightrainbow], - bg_inside=[:orange :pink :darkblue :black]) - end)] -), - -PlotExample("", - "", - [:(begin - using Random - Random.seed!(111) - plot!(Plots.fakedata(100,10)) - end)] -), - -PlotExample("Open/High/Low/Close", -""" -Create an OHLC chart. Pass in a list of (open,high,low,close) tuples as your `y` -argument. This uses recipes to first convert the tuples to OHLC objects, and -subsequently create a :path series with the appropriate line segments. -""", - [:(begin -n=20 -hgt=rand(n).+1 -bot=randn(n) -openpct=rand(n) -closepct=rand(n) -y = OHLC[(openpct[i]*hgt[i]+bot[i], bot[i]+hgt[i], bot[i], - closepct[i]*hgt[i]+bot[i]) for i in 1:n] -ohlc(y) - end)] -), - -PlotExample("Annotations", -""" -The `annotations` keyword is used for text annotations in data-coordinates. Pass in a -tuple (x,y,text) or a vector of annotations. `annotate!(ann)` is shorthand for `plot!(; -annotation=ann)`. Series annotations are used for annotating individual data points. -They require only the annotation... x/y values are computed. A `PlotText` object can be -build with the method `text(string, attr...)`, which wraps font and color attributes. -""", - [:(begin -y = rand(10) -plot(y, annotations = (3,y[3], Plots.text("this is #3",:left)), leg=false) -annotate!([(5, y[5], Plots.text("this is #5",16,:red,:center)), - (10, y[10], Plots.text("this is #10",:right,20,"courier"))]) -scatter!(range(2, stop=8, length=6), rand(6), marker=(50,0.2,:orange), - series_annotations = ["series","annotations","map","to","series", - Plots.text("data",:green)]) - end)] -), - -PlotExample("Custom Markers", -"""A `Plots.Shape` is a light wrapper around vertices of a polygon. For supported -backends, pass arbitrary polygons as the marker shapes. Note: The center is (0,0) and -the size is expected to be rougly the area of the unit circle. -""", - [:(begin -verts = [(-1.0,1.0),(-1.28,0.6),(-0.2,-1.4),(0.2,-1.4),(1.28,0.6),(1.0,1.0), - (-1.0,1.0),(-0.2,-0.6),(0.0,-0.2),(-0.4,0.6),(1.28,0.6),(0.2,-1.4), - (-0.2,-1.4),(0.6,0.2),(-0.2,0.2),(0.0,-0.2),(0.2,0.2),(-0.2,-0.6)] -x = 0.1:0.2:0.9 -y = 0.7rand(5).+0.15 -plot(x, y, line = (3,:dash,:lightblue), marker = (Shape(verts),30,RGBA(0,0,0,0.2)), - bg=:pink, fg=:darkblue, xlim = (0,1), ylim=(0,1), leg=false) - end)] -), - -PlotExample("Contours", -""" -Any value for fill works here. We first build a filled contour from a function, then an -unfilled contour from a matrix. -""", - [:(begin - x = 1:0.5:20 - y = 1:0.5:10 - f(x,y) = (3x+y^2)*abs(sin(x)+cos(y)) - X = repeat(reshape(x,1,:), length(y), 1) - Y = repeat(y, 1, length(x)) - Z = map(f, X, Y) - p1 = contour(x, y, f, fill=true) - p2 = contour(x, y, Z) - plot(p1, p2) - end)] -), - -PlotExample("Pie", - "", - [:(begin - x = ["Nerds", "Hackers", "Scientists"] - y = [0.4, 0.35, 0.25] - pie(x, y, title="The Julia Community", l=0.5) - end)] -), - -PlotExample("3D", - "", - [:(begin - n = 100 - ts = range(0, stop=8π, length=n) - x = ts .* map(cos,ts) - y = 0.1ts .* map(sin,ts) - z = 1:n - plot(x, y, z, zcolor=reverse(z), m=(10,0.8,:blues,Plots.stroke(0)), leg=false, cbar=true, w=5) - plot!(zeros(n),zeros(n),1:n, w=10) - end)] -), - -PlotExample("DataFrames", - "Plot using DataFrame column symbols.", - [:(using StatsPlots), # can't be inside begin block because @df gets expanded first - :(begin - import RDatasets - iris = RDatasets.dataset("datasets", "iris") - @df iris scatter(:SepalLength, :SepalWidth, group=:Species, - title = "My awesome plot", xlabel = "Length", ylabel = "Width", - marker = (0.5, [:cross :hex :star7], 12), bg=RGB(.2,.2,.2)) - end)] -), - -PlotExample("Groups and Subplots", - "", - [:(begin - group = rand(map(i->"group $i",1:4),100) - plot(rand(100), layout=@layout([a b;c]), group=group, - linetype=[:bar :scatter :steppre], linecolor = :match) - end)] -), - -PlotExample("Polar Plots", - "", - [:(begin - Θ = range(0, stop=1.5π, length=100) - r = abs.(0.1randn(100)+sin.(3Θ)) - plot(Θ, r, proj=:polar, m=2) - end)] -), - -PlotExample("Heatmap, categorical axes, and aspect_ratio", - "", - [:(begin - xs = [string("x",i) for i=1:10] - ys = [string("y",i) for i=1:4] - z = float((1:4)*reshape(1:10,1,:)) - heatmap(xs, ys, z, aspect_ratio=1) - end)] -), - -PlotExample("Layouts, margins, label rotation, title location", - "", - [:(begin - using Plots.PlotMeasures # for Measures, e.g. mm and px - plot(rand(100,6),layout=@layout([a b; c]),title=["A" "B" "C"], - title_location=:left, left_margin=[20mm 0mm], - bottom_margin=10px, xrotation=60) - end)] -), - -PlotExample("Boxplot and Violin series recipes", - "", - [:(using StatsPlots), # can't be inside begin block because @df gets expanded first - :(begin - import RDatasets - singers = RDatasets.dataset("lattice", "singer") - @df singers violin(:VoicePart, :Height, line = 0, fill = (0.2, :blue)) - @df singers boxplot!(:VoicePart, :Height, line = (2,:black), fill = (0.3, :orange)) - end)] -), - -PlotExample("Animation with subplots", - "The `layout` macro can be used to create an animation with subplots.", - [:(begin - l = @layout([[a; b] c]) - p = plot(plot([sin,cos],1,leg=false), - scatter([atan,cos],1,leg=false), - plot(log,1,xlims=(1,10π),ylims=(0,5),leg=false),layout=l) - - anim = Animation() - for x = range(1, stop=10π, length=100) - plot(push!(p,x,Float64[sin(x),cos(x),atan(x),cos(x),log(x)])) - frame(anim) - end - end)] -), - -PlotExample("Spy", -""" -For a matrix `mat` with unique nonzeros `spy(mat)` returns a colorless plot. If `mat` has -various different nonzero values, a colorbar is added. The colorbar can be disabled with -`legend = nothing`. -""", - [:(begin - using SparseArrays - a = spdiagm(0 => ones(50), 1 => ones(49), -1 => ones(49), 10 => ones(40), -10 => ones(40)) - b = spdiagm(0 => 1:50, 1 => 1:49, -1 => 1:49, 10 => 1:40, -10 => 1:40) - plot(spy(a), spy(b), title = ["Unique nonzeros" "Different nonzeros"]) - end)] -), - -PlotExample("Magic grid argument", -""" -The grid lines can be modified individually for each axis with the magic `grid` argument. -""", - [:(begin - x = rand(10) - p1 = plot(x, title = "Default looks") - p2 = plot(x, grid = (:y, :olivedrab, :dot, 1, 0.9), title = "Modified y grid") - p3 = plot(deepcopy(p2), title = "Add x grid") - xgrid!(p3, :on, :cadetblue, 2, :dashdot, 0.4) - plot(p1, p2, p3, layout = (1, 3), label = "", fillrange = 0, fillalpha = 0.3) - end)] -), - -PlotExample("Framestyle", -""" -The style of the frame/axes of a (sub)plot can be changed with the `framestyle` -attribute. The default framestyle is `:axes`. -""", - [:(begin - scatter(fill(randn(10), 6), fill(randn(10), 6), - framestyle = [:box :semi :origin :zerolines :grid :none], - title = [":box" ":semi" ":origin" ":zerolines" ":grid" ":none"], - color = permutedims(1:6), layout = 6, label = "", markerstrokewidth = 0, - ticks = -2:2) - end)] -), - -PlotExample("Lines and markers with varying colors", -""" -You can use the `line_z` and `marker_z` properties to associate a color with -each line segment or marker in the plot. -""", - [:(begin - t = range(0, stop=1, length=100) - θ = 6π .* t - x = t .* cos.(θ) - y = t .* sin.(θ) - p1 = plot(x, y, line_z=t, linewidth=3, legend=false) - p2 = scatter(x, y, marker_z=+, color=:bluesreds, legend=false) - plot(p1, p2) - end)] -), - -PlotExample("Portfolio Composition maps", -""" -see: http://stackoverflow.com/a/37732384/5075246 -""", - [:(begin - using Random - Random.seed!(111) - tickers = ["IBM", "Google", "Apple", "Intel"] - N = 10 - D = length(tickers) - weights = rand(N,D) - weights ./= sum(weights, dims = 2) - returns = sort!((1:N) + D*randn(N)) - - portfoliocomposition(weights, returns, labels = permutedims(tickers)) - end)] -), - -PlotExample("Ribbons", - """ - Ribbons can be added to lines via the `ribbon` keyword; - you can pass a tuple of arrays (upper and lower bounds), - a single Array (for symmetric ribbons), a Function, or a number. - """, - [:(begin - plot( - plot(0:10; ribbon = (LinRange(0, 2, 10), LinRange(0, 1, 10))), - plot(0:10; ribbon = 0:0.5:5), - plot(0:10; ribbon = sqrt), - plot(0:10; ribbon = 1), - ) - end)] -), - -PlotExample("Histogram2D (complex values)", - "", - [:(begin - n = 10_000 - x = exp.(0.1randn(n) .+ randn(n).*(im)) - histogram2d(x, nbins=(20,40), show_empty_bins=true, - normed=true, aspect_ratio=1) - end)] -), - -PlotExample("Unconnected lines using `missing` or `NaN`", -""" -Missing values and non-finite values, including `NaN`, are not plotted. -Instead, lines are separated into segments at these values. -""", - [:(begin - x,y = [1,2,2,1,1], [1,2,1,2,1] - plot( - plot([rand(5); NaN; rand(5); NaN; rand(5)]), - plot([1,missing,2,3], marker=true), - plot([x; NaN; x.+2], [y; NaN; y.+1], arrow=2), - plot([1, 2+3im, Inf, 4im, 3, -Inf*im, 0, 3+3im], marker=true), - legend=false - ) - end)] -), + anim = Animation() + for x in range(1, stop = 10π, length = 100) + plot(push!( + p, + x, + Float64[sin(x), cos(x), atan(x), cos(x), log(x)], + )) + frame(anim) + end + end + ), + ], + ), + PlotExample( + "Spy", + """ + For a matrix `mat` with unique nonzeros `spy(mat)` returns a colorless plot. If `mat` has + various different nonzero values, a colorbar is added. The colorbar can be disabled with + `legend = nothing`. + """, + [ + :( + begin + using SparseArrays + a = spdiagm( + 0 => ones(50), + 1 => ones(49), + -1 => ones(49), + 10 => ones(40), + -10 => ones(40), + ) + b = spdiagm( + 0 => 1:50, + 1 => 1:49, + -1 => 1:49, + 10 => 1:40, + -10 => 1:40, + ) + plot( + spy(a), + spy(b), + title = ["Unique nonzeros" "Different nonzeros"], + ) + end + ), + ], + ), + PlotExample( + "Magic grid argument", + """ + The grid lines can be modified individually for each axis with the magic `grid` argument. + """, + [ + :( + begin + x = rand(10) + p1 = plot(x, title = "Default looks") + p2 = plot( + x, + grid = (:y, :olivedrab, :dot, 1, 0.9), + title = "Modified y grid", + ) + p3 = plot(deepcopy(p2), title = "Add x grid") + xgrid!(p3, :on, :cadetblue, 2, :dashdot, 0.4) + plot( + p1, + p2, + p3, + layout = (1, 3), + label = "", + fillrange = 0, + fillalpha = 0.3, + ) + end + ), + ], + ), + PlotExample( + "Framestyle", + """ + The style of the frame/axes of a (sub)plot can be changed with the `framestyle` + attribute. The default framestyle is `:axes`. + """, + [ + :( + begin + scatter( + fill(randn(10), 6), + fill(randn(10), 6), + framestyle = [:box :semi :origin :zerolines :grid :none], + title = [":box" ":semi" ":origin" ":zerolines" ":grid" ":none"], + color = permutedims(1:6), + layout = 6, + label = "", + markerstrokewidth = 0, + ticks = -2:2, + ) + end + ), + ], + ), + PlotExample( + "Lines and markers with varying colors", + """ + You can use the `line_z` and `marker_z` properties to associate a color with + each line segment or marker in the plot. + """, + [ + :( + begin + t = range(0, stop = 1, length = 100) + θ = 6π .* t + x = t .* cos.(θ) + y = t .* sin.(θ) + p1 = plot(x, y, line_z = t, linewidth = 3, legend = false) + p2 = scatter( + x, + y, + marker_z = +, + color = :bluesreds, + legend = false, + ) + plot(p1, p2) + end + ), + ], + ), + PlotExample( + "Portfolio Composition maps", + """ + see: http://stackoverflow.com/a/37732384/5075246 + """, + [ + :( + begin + using Random + Random.seed!(111) + tickers = ["IBM", "Google", "Apple", "Intel"] + N = 10 + D = length(tickers) + weights = rand(N, D) + weights ./= sum(weights, dims = 2) + returns = sort!((1:N) + D * randn(N)) + portfoliocomposition( + weights, + returns, + labels = permutedims(tickers), + ) + end + ), + ], + ), + PlotExample( + "Ribbons", + """ + Ribbons can be added to lines via the `ribbon` keyword; + you can pass a tuple of arrays (upper and lower bounds), + a single Array (for symmetric ribbons), a Function, or a number. + """, + [ + :( + begin + plot( + plot( + 0:10; + ribbon = (LinRange(0, 2, 10), LinRange(0, 1, 10)), + ), + plot(0:10; ribbon = 0:0.5:5), + plot(0:10; ribbon = sqrt), + plot(0:10; ribbon = 1), + ) + end + ), + ], + ), + PlotExample( + "Histogram2D (complex values)", + "", + [ + :( + begin + n = 10_000 + x = exp.(0.1 * randn(n) .+ randn(n) .* (im)) + histogram2d( + x, + nbins = (20, 40), + show_empty_bins = true, + normed = true, + aspect_ratio = 1, + ) + end + ), + ], + ), + PlotExample( + "Unconnected lines using `missing` or `NaN`", + """ + Missing values and non-finite values, including `NaN`, are not plotted. + Instead, lines are separated into segments at these values. + """, + [ + :( + begin + x, y = [1, 2, 2, 1, 1], [1, 2, 1, 2, 1] + plot( + plot([rand(5); NaN; rand(5); NaN; rand(5)]), + plot([1, missing, 2, 3], marker = true), + plot([x; NaN; x .+ 2], [y; NaN; y .+ 1], arrow = 2), + plot( + [1, 2 + 3im, Inf, 4im, 3, -Inf * im, 0, 3 + 3im], + marker = true, + ), + legend = false, + ) + end + ), + ], + ), ] # Some constants for PlotDocs and PlotReferenceImages @@ -517,21 +871,21 @@ _backend_skips = Dict( # make and display one plot function test_examples(pkgname::Symbol, idx::Int; debug = false, disp = true) - Plots._debugMode.on = debug - @info("Testing plot: $pkgname:$idx:$(_examples[idx].header)") - backend(pkgname) - backend() + Plots._debugMode.on = debug + @info("Testing plot: $pkgname:$idx:$(_examples[idx].header)") + backend(pkgname) + backend() - # prevent leaking variables (esp. functions) directly into Plots namespace - m = Module(:PlotExampleModule) - Base.eval(m, :(using Plots)) - map(exprs -> Base.eval(m, exprs), _examples[idx].exprs) + # prevent leaking variables (esp. functions) directly into Plots namespace + m = Module(:PlotExampleModule) + Base.eval(m, :(using Plots)) + map(exprs -> Base.eval(m, exprs), _examples[idx].exprs) - plt = current() - if disp - gui(plt) - end - plt + plt = current() + if disp + gui(plt) + end + plt end # generate all plots and create a dict mapping idx --> plt @@ -542,23 +896,29 @@ test_examples(pkgname[, idx]; debug = false, disp = true, sleep = nothing, Run the `idx` test example for a given backend, or all examples if `idx` is not specified. """ -function test_examples(pkgname::Symbol; debug = false, disp = true, sleep = nothing, - skip = [], only = nothing) - Plots._debugMode.on = debug - plts = Dict() - for i in eachindex(_examples) - only !== nothing && !(i in only) && continue - i in skip && continue - try - plt = test_examples(pkgname, i, debug=debug, disp=disp) - plts[i] = plt - catch ex - # TODO: put error info into markdown? - @warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex") +function test_examples( + pkgname::Symbol; + debug = false, + disp = true, + sleep = nothing, + skip = [], + only = nothing, +) + Plots._debugMode.on = debug + plts = Dict() + for i in eachindex(_examples) + only !== nothing && !(i in only) && continue + i in skip && continue + try + plt = test_examples(pkgname, i, debug = debug, disp = disp) + plts[i] = plt + catch ex + # TODO: put error info into markdown? + @warn("Example $pkgname:$i:$(_examples[i].header) failed with: $ex") + end + if sleep !== nothing + Base.sleep(sleep) + end end - if sleep !== nothing - Base.sleep(sleep) - end - end - plts + plts end