From 6bb53b5181307b10f1a9cf6cf2847b9aaac3783a Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 16:53:54 +0100 Subject: [PATCH 1/5] remove default recipes --- src/series.jl | 64 --------------------------------------------------- 1 file changed, 64 deletions(-) diff --git a/src/series.jl b/src/series.jl index bba2f313..59cbb489 100644 --- a/src/series.jl +++ b/src/series.jl @@ -107,70 +107,6 @@ compute_xyz(x::Nothing, y::Nothing, z::Nothing) = error("x/y/z are all no # we are going to build recipes to do the processing and splitting of the args -# ensure we dispatch to the slicer -struct SliceIt end - -# the catch-all recipes -@recipe function f(::Type{SliceIt}, x, y, z) - - # handle data with formatting attached - if typeof(x) <: Formatted - xformatter := x.formatter - x = x.data - end - if typeof(y) <: Formatted - yformatter := y.formatter - y = y.data - end - if typeof(z) <: Formatted - zformatter := z.formatter - z = z.data - end - - xs = convertToAnyVector(x, plotattributes) - ys = convertToAnyVector(y, plotattributes) - zs = convertToAnyVector(z, plotattributes) - - - fr = pop!(plotattributes, :fillrange, nothing) - fillranges = process_fillrange(fr, plotattributes) - mf = length(fillranges) - - rib = pop!(plotattributes, :ribbon, nothing) - ribbons = process_ribbon(rib, plotattributes) - mr = length(ribbons) - - # @show zs - - mx = length(xs) - my = length(ys) - mz = length(zs) - if mx > 0 && my > 0 && mz > 0 - for i in 1:max(mx, my, mz) - # add a new series - di = copy(plotattributes) - xi, yi, zi = xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)] - di[:x], di[:y], di[:z] = compute_xyz(xi, yi, zi) - - # handle fillrange - fr = fillranges[mod1(i,mf)] - di[:fillrange] = isa(fr, Function) ? map(fr, di[:x]) : fr - - # handle ribbons - rib = ribbons[mod1(i,mr)] - di[:ribbon] = isa(rib, Function) ? map(rib, di[:x]) : rib - - push!(series_list, RecipeData(di, ())) - end - end - nothing # don't add a series for the main block -end - -# this is the default "type recipe"... just pass the object through -@recipe f(::Type{T}, v::T) where {T<:Any} = v - -# this should catch unhandled "series recipes" and error with a nice message -@recipe f(::Type{V}, x, y, z) where {V<:Val} = error("The backend must not support the series type $V, and there isn't a series recipe defined.") _apply_type_recipe(plotattributes, v) = RecipesBase.apply_recipe(plotattributes, typeof(v), v)[1].args[1] From 7ed9fbd7fc4ca5e32d866e06841c744ba9ac9809 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 18:11:46 +0100 Subject: [PATCH 2/5] factor out SliceIt dependencies --- src/series.jl | 68 --------------------------------------------------- 1 file changed, 68 deletions(-) diff --git a/src/series.jl b/src/series.jl index 59cbb489..218bdced 100644 --- a/src/series.jl +++ b/src/series.jl @@ -1,71 +1,4 @@ - -# create a new "build_series_args" which converts all inputs into xs = Any[xitems], ys = Any[yitems]. -# Special handling for: no args, xmin/xmax, parametric, dataframes -# Then once inputs have been converted, build the series args, map functions, etc. -# This should cut down on boilerplate code and allow more focused dispatch on type -# note: returns meta information... mainly for use with automatic labeling from DataFrames for now - -const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} -const MaybeNumber = Union{Number, Missing} -const MaybeString = Union{AbstractString, Missing} -const DataPoint = Union{MaybeNumber, MaybeString} - -prepareSeriesData(x) = error("Cannot convert $(typeof(x)) to series data for plotting") -prepareSeriesData(::Nothing) = nothing -prepareSeriesData(t::Tuple{T, T}) where {T<:Number} = t -prepareSeriesData(f::Function) = f -prepareSeriesData(a::AbstractArray{<:MaybeNumber}) = replace!( - x -> ismissing(x) || isinf(x) ? NaN : x, - map(float,a)) -prepareSeriesData(a::AbstractArray{<:MaybeString}) = replace(x -> ismissing(x) ? "" : x, a) -prepareSeriesData(s::Surface{<:AMat{<:MaybeNumber}}) = Surface(prepareSeriesData(s.surf)) -prepareSeriesData(s::Surface) = s # non-numeric Surface, such as an image -prepareSeriesData(v::Volume) = Volume(prepareSeriesData(v.v), v.x_extents, v.y_extents, v.z_extents) - -# default: assume x represents a single series -convertToAnyVector(x, plotattributes) = Any[prepareSeriesData(x)] - -# fixed number of blank series -convertToAnyVector(n::Integer, plotattributes) = Any[zeros(0) for i in 1:n] - -# vector of data points is a single series -convertToAnyVector(v::AVec{<:DataPoint}, plotattributes) = Any[prepareSeriesData(v)] - -# list of things (maybe other vectors, functions, or something else) -function convertToAnyVector(v::AVec, plotattributes) - if all(x -> x isa MaybeNumber, v) - convertToAnyVector(Vector{MaybeNumber}(v), plotattributes) - elseif all(x -> x isa MaybeString, v) - convertToAnyVector(Vector{MaybeString}(v), plotattributes) - else - vcat((convertToAnyVector(vi, plotattributes) for vi in v)...) - end -end - -# Matrix is split into columns -function convertToAnyVector(v::AMat{<:DataPoint}, plotattributes) - if all3D(plotattributes) - Any[prepareSeriesData(Surface(v))] - else - Any[prepareSeriesData(v[:, i]) for i in axes(v, 2)] - end -end - -# -------------------------------------------------------------------- -# Fillranges & ribbons - - -process_fillrange(range::Number, plotattributes) = [range] -process_fillrange(range, plotattributes) = convertToAnyVector(range, plotattributes) - -process_ribbon(ribbon::Number, plotattributes) = [ribbon] -process_ribbon(ribbon, plotattributes) = convertToAnyVector(ribbon, plotattributes) -# ribbon as a tuple: (lower_ribbons, upper_ribbons) -process_ribbon(ribbon::Tuple{Any,Any}, plotattributes) = collect(zip(convertToAnyVector(ribbon[1], plotattributes), - convertToAnyVector(ribbon[2], plotattributes))) - - # -------------------------------------------------------------------- # TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array @@ -214,7 +147,6 @@ end @recipe f(n::Integer) = is3d(get(plotattributes,:seriestype,:path)) ? (SliceIt, n, n, n) : (SliceIt, n, n, nothing) -all3D(plotattributes) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image, :plots_heatmap), get(plotattributes, :seriestype, :none)) # return a surface if this is a 3d plot, otherwise let it be sliced up @recipe function f(mat::AMat{T}) where T<:Union{Integer,AbstractFloat,Missing} From 52c081758da8fa3c1454eb3e6c2d0c741044e67e Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 21:14:16 +0100 Subject: [PATCH 3/5] move Formatted and import --- src/Plots.jl | 2 +- src/components.jl | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index 92546af7..c9bb7af3 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -24,7 +24,7 @@ import RecipePipeline: _process_userrecipe, _process_plotrecipe, finalize_subplot!, recipe_pipeline!, _recipe_init!, _recipe_after_user!, _recipe_after_plot!, _recipe_before_series!, - _recipe_finish!, is_st_supported + _recipe_finish!, is_st_supported, Formatted, SliceIt, FuncOrFuncs, MaybeNumber, MaybeString, DataPoint using Requires diff --git a/src/components.jl b/src/components.jl index c87fa50f..02abd8b8 100644 --- a/src/components.jl +++ b/src/components.jl @@ -771,13 +771,6 @@ function add_arrows(func::Function, x::AVec, y::AVec) end end -# ----------------------------------------------------------------------- - -"Represents data values with formatting that should apply to the tick labels." -struct Formatted{T} - data::T - formatter::Function -end # ----------------------------------------------------------------------- "create a BezierCurve for plotting" From dd25893a70146efb553ad4b22c52e5dabc15c5af Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 21:22:59 +0100 Subject: [PATCH 4/5] move Surface and trueOrAllTrue --- src/Plots.jl | 3 ++- src/components.jl | 17 ----------------- src/utils.jl | 3 --- 3 files changed, 2 insertions(+), 21 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index c9bb7af3..080707bf 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -24,7 +24,8 @@ import RecipePipeline: _process_userrecipe, _process_plotrecipe, finalize_subplot!, recipe_pipeline!, _recipe_init!, _recipe_after_user!, _recipe_after_plot!, _recipe_before_series!, - _recipe_finish!, is_st_supported, Formatted, SliceIt, FuncOrFuncs, MaybeNumber, MaybeString, DataPoint + _recipe_finish!, is_st_supported, Formatted, SliceIt, FuncOrFuncs, MaybeNumber, MaybeString, DataPoint, trueOrAllTrue, + Surface, AbstractSurface using Requires diff --git a/src/components.jl b/src/components.jl index 02abd8b8..ecc81d61 100644 --- a/src/components.jl +++ b/src/components.jl @@ -650,23 +650,6 @@ end # ----------------------------------------------------------------------- -abstract type AbstractSurface end - -"represents a contour or surface mesh" -struct Surface{M<:AMat} <: AbstractSurface - surf::M -end - -Surface(f::Function, x, y) = Surface(Float64[f(xi,yi) for yi in y, xi in x]) - -Base.Array(surf::Surface) = surf.surf - -for f in (:length, :size) - @eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...) -end -Base.copy(surf::Surface) = Surface(copy(surf.surf)) -Base.eltype(surf::Surface{T}) where {T} = eltype(T) - function expand_extrema!(a::Axis, surf::Surface) ex = a[:extrema] for vi in surf.surf diff --git a/src/utils.jl b/src/utils.jl index ef15b8b5..08244500 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -717,9 +717,6 @@ makekw(; kw...) = KW(kw) wraptuple(x::Tuple) = x wraptuple(x) = (x,) -trueOrAllTrue(f::Function, x::AbstractArray) = all(f, x) -trueOrAllTrue(f::Function, x) = f(x) - allLineTypes(arg) = trueOrAllTrue(a -> get(_typeAliases, a, a) in _allTypes, arg) allStyles(arg) = trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg) allShapes(arg) = trueOrAllTrue(a -> is_marker_supported(get(_markerAliases, a, a)), arg) || From a65d41ca39df7b064d34105af77b5973f5b61799 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Sun, 15 Mar 2020 21:48:51 +0100 Subject: [PATCH 5/5] move Volume --- src/Plots.jl | 33 +++++++++++++++++++++++++-------- src/components.jl | 24 ------------------------ 2 files changed, 25 insertions(+), 32 deletions(-) diff --git a/src/Plots.jl b/src/Plots.jl index 080707bf..27f3faad 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -18,14 +18,31 @@ using Base.Meta import Showoff import StatsBase import JSON -import RecipePipeline: _process_userrecipe, _process_plotrecipe, - _process_seriesrecipe, _preprocess_args, - preprocessArgs!, is_st_supported, - finalize_subplot!, recipe_pipeline!, - _recipe_init!, _recipe_after_user!, - _recipe_after_plot!, _recipe_before_series!, - _recipe_finish!, is_st_supported, Formatted, SliceIt, FuncOrFuncs, MaybeNumber, MaybeString, DataPoint, trueOrAllTrue, - Surface, AbstractSurface +import RecipePipeline: + _process_userrecipe, + _process_plotrecipe, + _process_seriesrecipe, + _preprocess_args, + preprocessArgs!, + is_st_supported, + finalize_subplot!, + recipe_pipeline!, + _recipe_init!, + _recipe_after_user!, + _recipe_after_plot!, + _recipe_before_series!, + _recipe_finish!, + is_st_supported, + Formatted, + SliceIt, + FuncOrFuncs, + MaybeNumber, + MaybeString, + DataPoint, + trueOrAllTrue, + Surface, + AbstractSurface, + Volume using Requires diff --git a/src/components.jl b/src/components.jl index ecc81d61..6157c53a 100644 --- a/src/components.jl +++ b/src/components.jl @@ -669,30 +669,6 @@ end # # I don't want to clash with ValidatedNumerics, but this would be nice: # ..(a::T, b::T) = (a,b) -struct Volume{T} - v::Array{T,3} - x_extents::Tuple{T,T} - y_extents::Tuple{T,T} - z_extents::Tuple{T,T} -end - -default_extents(::Type{T}) where {T} = (zero(T), one(T)) - -function Volume(v::Array{T,3}, - x_extents = default_extents(T), - y_extents = default_extents(T), - z_extents = default_extents(T)) where T - Volume(v, x_extents, y_extents, z_extents) -end - -Base.Array(vol::Volume) = vol.v -for f in (:length, :size) - @eval Base.$f(vol::Volume, args...) = $f(vol.v, args...) -end -Base.copy(vol::Volume{T}) where {T} = Volume{T}(copy(vol.v), vol.x_extents, vol.y_extents, vol.z_extents) -Base.eltype(vol::Volume{T}) where {T} = T - -# ----------------------------------------------------------------------- # style is :open or :closed (for now) struct Arrow