Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
d9dba5091b
6
deps/generateprecompiles.jl
vendored
6
deps/generateprecompiles.jl
vendored
@ -26,13 +26,15 @@
|
|||||||
|
|
||||||
using SnoopCompile
|
using SnoopCompile
|
||||||
|
|
||||||
|
project_flag = string("--project=", joinpath(homedir(), ".julia", "dev", "Plots"))
|
||||||
log_path = joinpath(tempdir(), "compiles.log")
|
log_path = joinpath(tempdir(), "compiles.log")
|
||||||
precompiles_path = joinpath(tempdir(), "precompile")
|
precompiles_path = joinpath(tempdir(), "precompile")
|
||||||
|
|
||||||
# run examples with GR backend, logging what needs to be compiled
|
# run examples with GR backend, logging what needs to be compiled
|
||||||
SnoopCompile.@snoopc log_path begin
|
SnoopCompile.@snoopc project_flag log_path begin
|
||||||
using Plots
|
using Plots
|
||||||
Plots.test_examples(:gr, disp=true)
|
Plots.test_examples(:gr)
|
||||||
|
Plots.test_examples(:plotly, skip = Plots._backend_skips[:plotly])
|
||||||
end
|
end
|
||||||
|
|
||||||
# precompile calls containing the following strings are dropped
|
# precompile calls containing the following strings are dropped
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -70,23 +70,19 @@ process_ribbon(ribbon::Tuple{Any,Any}, plotattributes) = collect(zip(convertToAn
|
|||||||
|
|
||||||
# --------------------------------------------------------------------
|
# --------------------------------------------------------------------
|
||||||
|
|
||||||
# TODO: can we avoid the copy here? one error that crops up is that mapping functions over the same array
|
compute_x(x::Nothing, y::Nothing, z) = axes(z,1)
|
||||||
# result in that array being shared. push!, etc will add too many items to that array
|
compute_x(x::Nothing, y, z) = axes(y,1)
|
||||||
|
compute_x(x::Function, y, z) = map(x, y)
|
||||||
|
compute_x(x, y, z) = x
|
||||||
|
|
||||||
compute_x(x::Nothing, y::Nothing, z) = axes(z,1)
|
compute_y(x::Nothing, y::Nothing, z) = axes(z,2)
|
||||||
compute_x(x::Nothing, y, z) = axes(y,1)
|
compute_y(x, y::Function, z) = map(y, x)
|
||||||
compute_x(x::Function, y, z) = map(x, y)
|
compute_y(x, y, z) = y
|
||||||
compute_x(x, y, z) = copy(x)
|
|
||||||
|
|
||||||
# compute_y(x::Void, y::Function, z) = error()
|
compute_z(x, y, z::Function) = map(z, x, y)
|
||||||
compute_y(x::Nothing, y::Nothing, z) = axes(z,2)
|
compute_z(x, y, z::AbstractMatrix) = Surface(z)
|
||||||
compute_y(x, y::Function, z) = map(y, x)
|
compute_z(x, y, z::Nothing) = nothing
|
||||||
compute_y(x, y, z) = copy(y)
|
compute_z(x, y, z) = z
|
||||||
|
|
||||||
compute_z(x, y, z::Function) = map(z, x, y)
|
|
||||||
compute_z(x, y, z::AbstractMatrix) = Surface(z)
|
|
||||||
compute_z(x, y, z::Nothing) = nothing
|
|
||||||
compute_z(x, y, z) = copy(z)
|
|
||||||
|
|
||||||
nobigs(v::AVec{BigFloat}) = map(Float64, v)
|
nobigs(v::AVec{BigFloat}) = map(Float64, v)
|
||||||
nobigs(v::AVec{BigInt}) = map(Int64, v)
|
nobigs(v::AVec{BigInt}) = map(Int64, v)
|
||||||
|
|||||||
@ -271,6 +271,7 @@ Draw a 3D surface plot.
|
|||||||
|
|
||||||
# Example
|
# Example
|
||||||
```julia-repl
|
```julia-repl
|
||||||
|
julia> using LinearAlgebra
|
||||||
julia> x = y = range(-3, 3, length = 100)
|
julia> x = y = range(-3, 3, length = 100)
|
||||||
julia> surface(x, y, (x, y) -> sinc(norm([x, y])))
|
julia> surface(x, y, (x, y) -> sinc(norm([x, y])))
|
||||||
```
|
```
|
||||||
|
|||||||
469
src/utils.jl
469
src/utils.jl
@ -1,119 +1,4 @@
|
|||||||
|
|
||||||
calcMidpoints(edges::AbstractVector) = Float64[0.5 * (edges[i] + edges[i+1]) for i in 1:length(edges)-1]
|
|
||||||
|
|
||||||
"Make histogram-like bins of data"
|
|
||||||
function binData(data, nbins)
|
|
||||||
lo, hi = ignorenan_extrema(data)
|
|
||||||
edges = collect(range(lo, stop=hi, length=nbins+1))
|
|
||||||
midpoints = calcMidpoints(edges)
|
|
||||||
buckets = Int[max(2, min(searchsortedfirst(edges, x), length(edges)))-1 for x in data]
|
|
||||||
counts = zeros(Int, length(midpoints))
|
|
||||||
for b in buckets
|
|
||||||
counts[b] += 1
|
|
||||||
end
|
|
||||||
edges, midpoints, buckets, counts
|
|
||||||
end
|
|
||||||
|
|
||||||
"""
|
|
||||||
A hacky replacement for a histogram when the backend doesn't support histograms directly.
|
|
||||||
Convert it into a bar chart with the appropriate x/y values.
|
|
||||||
"""
|
|
||||||
function histogramHack(; kw...)
|
|
||||||
plotattributes = KW(kw)
|
|
||||||
|
|
||||||
# we assume that the y kwarg is set with the data to be binned, and nbins is also defined
|
|
||||||
edges, midpoints, buckets, counts = binData(plotattributes[:y], plotattributes[:bins])
|
|
||||||
plotattributes[:x] = midpoints
|
|
||||||
plotattributes[:y] = float(counts)
|
|
||||||
plotattributes[:seriestype] = :bar
|
|
||||||
plotattributes[:fillrange] = plotattributes[:fillrange] === nothing ? 0.0 : plotattributes[:fillrange]
|
|
||||||
plotattributes
|
|
||||||
end
|
|
||||||
|
|
||||||
"""
|
|
||||||
A hacky replacement for a bar graph when the backend doesn't support bars directly.
|
|
||||||
Convert it into a line chart with fillrange set.
|
|
||||||
"""
|
|
||||||
function barHack(; kw...)
|
|
||||||
plotattributes = KW(kw)
|
|
||||||
midpoints = plotattributes[:x]
|
|
||||||
heights = plotattributes[:y]
|
|
||||||
fillrange = plotattributes[:fillrange] === nothing ? 0.0 : plotattributes[:fillrange]
|
|
||||||
|
|
||||||
# estimate the edges
|
|
||||||
dists = diff(midpoints) * 0.5
|
|
||||||
edges = zeros(length(midpoints)+1)
|
|
||||||
for i in eachindex(edges)
|
|
||||||
if i == 1
|
|
||||||
edge = midpoints[1] - dists[1]
|
|
||||||
elseif i == length(edges)
|
|
||||||
edge = midpoints[i-1] + dists[i-2]
|
|
||||||
else
|
|
||||||
edge = midpoints[i-1] + dists[i-1]
|
|
||||||
end
|
|
||||||
edges[i] = edge
|
|
||||||
end
|
|
||||||
|
|
||||||
x = Float64[]
|
|
||||||
y = Float64[]
|
|
||||||
for i in eachindex(heights)
|
|
||||||
e1, e2 = edges[i:i+1]
|
|
||||||
append!(x, [e1, e1, e2, e2])
|
|
||||||
append!(y, [fillrange, heights[i], heights[i], fillrange])
|
|
||||||
end
|
|
||||||
|
|
||||||
plotattributes[:x] = x
|
|
||||||
plotattributes[:y] = y
|
|
||||||
plotattributes[:seriestype] = :path
|
|
||||||
plotattributes[:fillrange] = fillrange
|
|
||||||
plotattributes
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
|
||||||
A hacky replacement for a sticks graph when the backend doesn't support sticks directly.
|
|
||||||
Convert it into a line chart that traces the sticks, and a scatter that sets markers at the points.
|
|
||||||
"""
|
|
||||||
function sticksHack(; kw...)
|
|
||||||
plotattributesLine = KW(kw)
|
|
||||||
plotattributesScatter = copy(plotattributesLine)
|
|
||||||
|
|
||||||
# these are the line vertices
|
|
||||||
x = Float64[]
|
|
||||||
y = Float64[]
|
|
||||||
fillrange = plotattributesLine[:fillrange] === nothing ? 0.0 : plotattributesLine[:fillrange]
|
|
||||||
|
|
||||||
# calculate the vertices
|
|
||||||
yScatter = plotattributesScatter[:y]
|
|
||||||
for (i,xi) in enumerate(plotattributesScatter[:x])
|
|
||||||
yi = yScatter[i]
|
|
||||||
for j in 1:3 push!(x, xi) end
|
|
||||||
append!(y, [fillrange, yScatter[i], fillrange])
|
|
||||||
end
|
|
||||||
|
|
||||||
# change the line args
|
|
||||||
plotattributesLine[:x] = x
|
|
||||||
plotattributesLine[:y] = y
|
|
||||||
plotattributesLine[:seriestype] = :path
|
|
||||||
plotattributesLine[:markershape] = :none
|
|
||||||
plotattributesLine[:fillrange] = nothing
|
|
||||||
|
|
||||||
# change the scatter args
|
|
||||||
plotattributesScatter[:seriestype] = :none
|
|
||||||
|
|
||||||
plotattributesLine, plotattributesScatter
|
|
||||||
end
|
|
||||||
|
|
||||||
function regressionXY(x, y)
|
|
||||||
# regress
|
|
||||||
β, α = convert(Matrix{Float64}, [x ones(length(x))]) \ convert(Vector{Float64}, y)
|
|
||||||
|
|
||||||
# make a line segment
|
|
||||||
regx = [ignorenan_minimum(x), ignorenan_maximum(x)]
|
|
||||||
regy = β * regx + α
|
|
||||||
regx, regy
|
|
||||||
end
|
|
||||||
|
|
||||||
function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
|
function replace_image_with_heatmap(z::Array{T}) where T<:Colorant
|
||||||
n, m = size(z)
|
n, m = size(z)
|
||||||
colors = ColorGradient(vec(z))
|
colors = ColorGradient(vec(z))
|
||||||
@ -262,10 +147,10 @@ mapFuncOrFuncs(f::Function, u::AVec) = map(f, u)
|
|||||||
mapFuncOrFuncs(fs::AVec{F}, u::AVec) where {F<:Function} = [map(f, u) for f in fs]
|
mapFuncOrFuncs(fs::AVec{F}, u::AVec) where {F<:Function} = [map(f, u) for f in fs]
|
||||||
|
|
||||||
for i in 2:4
|
for i in 2:4
|
||||||
@eval begin
|
@eval begin
|
||||||
unzip(v::Union{AVec{<:Tuple{Vararg{T,$i} where T}},
|
unzip(v::Union{AVec{<:Tuple{Vararg{T,$i} where T}},
|
||||||
AVec{<:GeometryTypes.Point{$i}}}) = $(Expr(:tuple, (:([t[$j] for t in v]) for j=1:i)...))
|
AVec{<:GeometryTypes.Point{$i}}}) = $(Expr(:tuple, (:([t[$j] for t in v]) for j=1:i)...))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
unzip(v::Union{AVec{<:GeometryTypes.Point{N}},
|
unzip(v::Union{AVec{<:GeometryTypes.Point{N}},
|
||||||
@ -275,15 +160,13 @@ unzip(v::Union{AVec{<:GeometryTypes.Point},
|
|||||||
|
|
||||||
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
|
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
|
||||||
function _expand_limits(lims, x)
|
function _expand_limits(lims, x)
|
||||||
try
|
try
|
||||||
e1, e2 = ignorenan_extrema(x)
|
e1, e2 = ignorenan_extrema(x)
|
||||||
lims[1] = NaNMath.min(lims[1], e1)
|
lims[1] = NaNMath.min(lims[1], e1)
|
||||||
lims[2] = NaNMath.max(lims[2], e2)
|
lims[2] = NaNMath.max(lims[2], e2)
|
||||||
# catch err
|
catch
|
||||||
# @warn(err)
|
end
|
||||||
catch
|
nothing
|
||||||
end
|
|
||||||
nothing
|
|
||||||
end
|
end
|
||||||
|
|
||||||
expand_data(v, n::Integer) = [_cycle(v, i) for i=1:n]
|
expand_data(v, n::Integer) = [_cycle(v, i) for i=1:n]
|
||||||
@ -301,21 +184,21 @@ function addOrReplace(v::AbstractVector, t::DataType, args...; kw...)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function replaceType(vec, val)
|
function replaceType(vec, val)
|
||||||
filter!(x -> !isa(x, typeof(val)), vec)
|
filter!(x -> !isa(x, typeof(val)), vec)
|
||||||
push!(vec, val)
|
push!(vec, val)
|
||||||
end
|
end
|
||||||
|
|
||||||
function replaceAlias!(plotattributes::AKW, k::Symbol, aliases::Dict{Symbol,Symbol})
|
function replaceAlias!(plotattributes::AKW, k::Symbol, aliases::Dict{Symbol,Symbol})
|
||||||
if haskey(aliases, k)
|
if haskey(aliases, k)
|
||||||
plotattributes[aliases[k]] = pop_kw!(plotattributes, k)
|
plotattributes[aliases[k]] = pop_kw!(plotattributes, k)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function replaceAliases!(plotattributes::AKW, aliases::Dict{Symbol,Symbol})
|
function replaceAliases!(plotattributes::AKW, aliases::Dict{Symbol,Symbol})
|
||||||
ks = collect(keys(plotattributes))
|
ks = collect(keys(plotattributes))
|
||||||
for k in ks
|
for k in ks
|
||||||
replaceAlias!(plotattributes, k, aliases)
|
replaceAlias!(plotattributes, k, aliases)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
createSegments(z) = collect(repeat(reshape(z,1,:),2,1))[2:end]
|
createSegments(z) = collect(repeat(reshape(z,1,:),2,1))[2:end]
|
||||||
@ -334,20 +217,20 @@ const _scale_base = Dict{Symbol, Real}(
|
|||||||
)
|
)
|
||||||
|
|
||||||
function _heatmap_edges(v::AVec, isedges::Bool = false)
|
function _heatmap_edges(v::AVec, isedges::Bool = false)
|
||||||
length(v) == 1 && return v[1] .+ [-0.5, 0.5]
|
length(v) == 1 && return v[1] .+ [-0.5, 0.5]
|
||||||
if isedges return v end
|
if isedges return v end
|
||||||
# `isedges = true` means that v is a vector which already describes edges
|
# `isedges = true` means that v is a vector which already describes edges
|
||||||
# and does not need to be extended.
|
# and does not need to be extended.
|
||||||
vmin, vmax = ignorenan_extrema(v)
|
vmin, vmax = ignorenan_extrema(v)
|
||||||
extra_min = (v[2] - v[1]) / 2
|
extra_min = (v[2] - v[1]) / 2
|
||||||
extra_max = (v[end] - v[end - 1]) / 2
|
extra_max = (v[end] - v[end - 1]) / 2
|
||||||
vcat(vmin-extra_min, 0.5 * (v[1:end-1] + v[2:end]), vmax+extra_max)
|
vcat(vmin-extra_min, 0.5 * (v[1:end-1] + v[2:end]), vmax+extra_max)
|
||||||
end
|
end
|
||||||
|
|
||||||
"create an (n+1) list of the outsides of heatmap rectangles"
|
"create an (n+1) list of the outsides of heatmap rectangles"
|
||||||
function heatmap_edges(v::AVec, scale::Symbol = :identity, isedges::Bool = false)
|
function heatmap_edges(v::AVec, scale::Symbol = :identity, isedges::Bool = false)
|
||||||
f, invf = scalefunc(scale), invscalefunc(scale)
|
f, invf = scalefunc(scale), invscalefunc(scale)
|
||||||
map(invf, _heatmap_edges(map(f,v), isedges))
|
map(invf, _heatmap_edges(map(f,v), isedges))
|
||||||
end
|
end
|
||||||
|
|
||||||
function heatmap_edges(x::AVec, xscale::Symbol, y::AVec, yscale::Symbol, z_size::Tuple{Int, Int})
|
function heatmap_edges(x::AVec, xscale::Symbol, y::AVec, yscale::Symbol, z_size::Tuple{Int, Int})
|
||||||
@ -367,8 +250,8 @@ function heatmap_edges(x::AVec, xscale::Symbol, y::AVec, yscale::Symbol, z_size:
|
|||||||
end
|
end
|
||||||
|
|
||||||
function is_uniformly_spaced(v; tol=1e-6)
|
function is_uniformly_spaced(v; tol=1e-6)
|
||||||
dv = diff(v)
|
dv = diff(v)
|
||||||
maximum(dv) - minimum(dv) < tol * mean(abs.(dv))
|
maximum(dv) - minimum(dv) < tol * mean(abs.(dv))
|
||||||
end
|
end
|
||||||
|
|
||||||
function convert_to_polar(theta, r, r_extrema = ignorenan_extrema(r))
|
function convert_to_polar(theta, r, r_extrema = ignorenan_extrema(r))
|
||||||
@ -380,11 +263,11 @@ function convert_to_polar(theta, r, r_extrema = ignorenan_extrema(r))
|
|||||||
end
|
end
|
||||||
|
|
||||||
function fakedata(sz...)
|
function fakedata(sz...)
|
||||||
y = zeros(sz...)
|
y = zeros(sz...)
|
||||||
for r in 2:size(y,1)
|
for r in 2:size(y,1)
|
||||||
y[r,:] = 0.95 * vec(y[r-1,:]) + randn(size(y,2))
|
y[r,:] = 0.95 * vec(y[r-1,:]) + randn(size(y,2))
|
||||||
end
|
end
|
||||||
y
|
y
|
||||||
end
|
end
|
||||||
|
|
||||||
isijulia() = :IJulia in nameof.(collect(values(Base.loaded_modules)))
|
isijulia() = :IJulia in nameof.(collect(values(Base.loaded_modules)))
|
||||||
@ -752,119 +635,107 @@ function with(f::Function, args...; kw...)
|
|||||||
newdefs[:legend] = false
|
newdefs[:legend] = false
|
||||||
end
|
end
|
||||||
|
|
||||||
# dict to store old and new keyword args for anything that changes
|
# dict to store old and new keyword args for anything that changes
|
||||||
olddefs = KW()
|
olddefs = KW()
|
||||||
for k in keys(newdefs)
|
for k in keys(newdefs)
|
||||||
olddefs[k] = default(k)
|
olddefs[k] = default(k)
|
||||||
end
|
|
||||||
|
|
||||||
# save the backend
|
|
||||||
if CURRENT_BACKEND.sym == :none
|
|
||||||
_pick_default_backend()
|
|
||||||
end
|
|
||||||
oldbackend = CURRENT_BACKEND.sym
|
|
||||||
|
|
||||||
for arg in args
|
|
||||||
|
|
||||||
# change backend?
|
|
||||||
if arg in backends()
|
|
||||||
backend(arg)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# # TODO: generalize this strategy to allow args as much as possible
|
# save the backend
|
||||||
# # as in: with(:gr, :scatter, :legend, :grid) do; ...; end
|
if CURRENT_BACKEND.sym == :none
|
||||||
# # TODO: can we generalize this enough to also do something similar in the plot commands??
|
_pick_default_backend()
|
||||||
|
end
|
||||||
|
oldbackend = CURRENT_BACKEND.sym
|
||||||
|
|
||||||
# k = :seriestype
|
for arg in args
|
||||||
# if arg in _allTypes
|
|
||||||
# olddefs[k] = default(k)
|
|
||||||
# newdefs[k] = arg
|
|
||||||
# elseif haskey(_typeAliases, arg)
|
|
||||||
# olddefs[k] = default(k)
|
|
||||||
# newdefs[k] = _typeAliases[arg]
|
|
||||||
# end
|
|
||||||
|
|
||||||
k = :legend
|
# change backend?
|
||||||
if arg in (k, :leg)
|
if arg in backends()
|
||||||
olddefs[k] = default(k)
|
backend(arg)
|
||||||
newdefs[k] = true
|
end
|
||||||
|
|
||||||
|
# TODO: generalize this strategy to allow args as much as possible
|
||||||
|
# as in: with(:gr, :scatter, :legend, :grid) do; ...; end
|
||||||
|
# TODO: can we generalize this enough to also do something similar in the plot commands??
|
||||||
|
|
||||||
|
# k = :seriestype
|
||||||
|
# if arg in _allTypes
|
||||||
|
# olddefs[k] = default(k)
|
||||||
|
# newdefs[k] = arg
|
||||||
|
# elseif haskey(_typeAliases, arg)
|
||||||
|
# olddefs[k] = default(k)
|
||||||
|
# newdefs[k] = _typeAliases[arg]
|
||||||
|
# end
|
||||||
|
|
||||||
|
k = :legend
|
||||||
|
if arg in (k, :leg)
|
||||||
|
olddefs[k] = default(k)
|
||||||
|
newdefs[k] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
k = :grid
|
||||||
|
if arg == k
|
||||||
|
olddefs[k] = default(k)
|
||||||
|
newdefs[k] = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
k = :grid
|
# display(olddefs)
|
||||||
if arg == k
|
# display(newdefs)
|
||||||
olddefs[k] = default(k)
|
|
||||||
newdefs[k] = true
|
# now set all those defaults
|
||||||
|
default(; newdefs...)
|
||||||
|
|
||||||
|
# call the function
|
||||||
|
ret = f()
|
||||||
|
|
||||||
|
# put the defaults back
|
||||||
|
default(; olddefs...)
|
||||||
|
|
||||||
|
# revert the backend
|
||||||
|
if CURRENT_BACKEND.sym != oldbackend
|
||||||
|
backend(oldbackend)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# display(olddefs)
|
# return the result of the function
|
||||||
# display(newdefs)
|
ret
|
||||||
|
|
||||||
# now set all those defaults
|
|
||||||
default(; newdefs...)
|
|
||||||
|
|
||||||
# call the function
|
|
||||||
ret = f()
|
|
||||||
|
|
||||||
# put the defaults back
|
|
||||||
default(; olddefs...)
|
|
||||||
|
|
||||||
# revert the backend
|
|
||||||
if CURRENT_BACKEND.sym != oldbackend
|
|
||||||
backend(oldbackend)
|
|
||||||
end
|
|
||||||
|
|
||||||
# return the result of the function
|
|
||||||
ret
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
# ---------------------------------------------------------------
|
# ---------------------------------------------------------------
|
||||||
|
|
||||||
mutable struct DebugMode
|
mutable struct DebugMode
|
||||||
on::Bool
|
on::Bool
|
||||||
end
|
end
|
||||||
const _debugMode = DebugMode(false)
|
const _debugMode = DebugMode(false)
|
||||||
|
|
||||||
function debugplots(on = true)
|
function debugplots(on = true)
|
||||||
_debugMode.on = on
|
_debugMode.on = on
|
||||||
end
|
end
|
||||||
|
|
||||||
debugshow(io, x) = show(io, x)
|
debugshow(io, x) = show(io, x)
|
||||||
debugshow(io, x::AbstractArray) = print(io, summary(x))
|
debugshow(io, x::AbstractArray) = print(io, summary(x))
|
||||||
|
|
||||||
function dumpdict(io::IO, plotattributes::AKW, prefix = "", alwaysshow = false)
|
function dumpdict(io::IO, plotattributes::AKW, prefix = "", alwaysshow = false)
|
||||||
_debugMode.on || alwaysshow || return
|
_debugMode.on || alwaysshow || return
|
||||||
println(io)
|
println(io)
|
||||||
if prefix != ""
|
if prefix != ""
|
||||||
println(io, prefix, ":")
|
println(io, prefix, ":")
|
||||||
end
|
end
|
||||||
for k in sort(collect(keys(plotattributes)))
|
for k in sort(collect(keys(plotattributes)))
|
||||||
@printf("%14s: ", k)
|
@printf("%14s: ", k)
|
||||||
debugshow(io, plotattributes[k])
|
debugshow(io, plotattributes[k])
|
||||||
|
println(io)
|
||||||
|
end
|
||||||
println(io)
|
println(io)
|
||||||
end
|
|
||||||
println(io)
|
|
||||||
end
|
end
|
||||||
DD(io::IO, plotattributes::AKW, prefix = "") = dumpdict(io, plotattributes, prefix, true)
|
DD(io::IO, plotattributes::AKW, prefix = "") = dumpdict(io, plotattributes, prefix, true)
|
||||||
DD(plotattributes::AKW, prefix = "") = DD(stdout, plotattributes, prefix)
|
DD(plotattributes::AKW, prefix = "") = DD(stdout, plotattributes, prefix)
|
||||||
|
|
||||||
function dumpcallstack()
|
function dumpcallstack()
|
||||||
error() # well... you wanted the stacktrace, didn't you?!?
|
error() # well... you wanted the stacktrace, didn't you?!?
|
||||||
end
|
end
|
||||||
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
# ---------------------------------------------------------------
|
|
||||||
# used in updating an existing series
|
|
||||||
|
|
||||||
extendSeriesByOne(v::UnitRange{Int}, n::Int = 1) = isempty(v) ? (1:n) : (minimum(v):maximum(v)+n)
|
|
||||||
extendSeriesByOne(v::AVec, n::Integer = 1) = isempty(v) ? (1:n) : vcat(v, (1:n) + ignorenan_maximum(v))
|
|
||||||
extendSeriesData(v::AbstractRange{T}, z::Real) where {T} = extendSeriesData(float(collect(v)), z)
|
|
||||||
extendSeriesData(v::AbstractRange{T}, z::AVec) where {T} = extendSeriesData(float(collect(v)), z)
|
|
||||||
extendSeriesData(v::AVec{T}, z::Real) where {T} = (push!(v, convert(T, z)); v)
|
|
||||||
extendSeriesData(v::AVec{T}, z::AVec) where {T} = (append!(v, convert(Vector{T}, z)); v)
|
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
# NOTE: backends should implement the following methods to get/set the x/y/z data objects
|
# NOTE: backends should implement the following methods to get/set the x/y/z data objects
|
||||||
|
|
||||||
@ -908,33 +779,60 @@ Base.setindex!(plt::Plot, xy::Tuple{X,Y}, i::Integer) where {X,Y} = (setxy!(plt,
|
|||||||
Base.setindex!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z} = (setxyz!(plt, xyz, i); plt)
|
Base.setindex!(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) where {X,Y,Z} = (setxyz!(plt, xyz, i); plt)
|
||||||
|
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
|
|
||||||
# operate on individual series
|
# operate on individual series
|
||||||
|
|
||||||
function push_x!(series::Series, xi)
|
Base.push!(series::Series, args...) = extend_series!(series, args...)
|
||||||
push!(series[:x], xi)
|
Base.append!(series::Series, args...) = extend_series!(series, args...)
|
||||||
expand_extrema!(series[:subplot][:xaxis], xi)
|
|
||||||
return
|
function extend_series!(series::Series, yi)
|
||||||
end
|
y = extend_series_data!(series, yi, :y)
|
||||||
function push_y!(series::Series, yi)
|
x = extend_to_length!(series[:x], length(y))
|
||||||
push!(series[:y], yi)
|
expand_extrema!(series[:subplot][:xaxis], x)
|
||||||
expand_extrema!(series[:subplot][:yaxis], yi)
|
return x, y
|
||||||
return
|
|
||||||
end
|
|
||||||
function push_z!(series::Series, zi)
|
|
||||||
push!(series[:z], zi)
|
|
||||||
expand_extrema!(series[:subplot][:zaxis], zi)
|
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Base.push!(series::Series, yi)
|
function extend_series!(series::Series, xi, yi)
|
||||||
x = extendSeriesByOne(series[:x])
|
x = extend_series_data!(series, xi, :x)
|
||||||
expand_extrema!(series[:subplot][:xaxis], x[end])
|
y = extend_series_data!(series, yi, :y)
|
||||||
series[:x] = x
|
return x, y
|
||||||
push_y!(series, yi)
|
end
|
||||||
|
|
||||||
|
function extend_series!(series::Series, xi, yi, zi)
|
||||||
|
x = extend_series_data!(series, xi, :x)
|
||||||
|
y = extend_series_data!(series, yi, :y)
|
||||||
|
z = extend_series_data!(series, zi, :z)
|
||||||
|
return x, y, z
|
||||||
|
end
|
||||||
|
|
||||||
|
function extend_series_data!(series::Series, v, letter)
|
||||||
|
copy_series!(series, letter)
|
||||||
|
d = extend_by_data!(series[letter], v)
|
||||||
|
expand_extrema!(series[:subplot][Symbol(letter, :axis)], d)
|
||||||
|
return d
|
||||||
|
end
|
||||||
|
|
||||||
|
function copy_series!(series, letter)
|
||||||
|
plt = series[:plot_object]
|
||||||
|
for s in plt.series_list
|
||||||
|
for l in (:x, :y, :z)
|
||||||
|
if s !== series || l !== letter
|
||||||
|
if s[l] === series[letter]
|
||||||
|
series[letter] = copy(series[letter])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
extend_to_length!(v::AbstractRange, n) = range(first(v), step = step(v), length = n)
|
||||||
|
function extend_to_length!(v::AbstractVector, n)
|
||||||
|
vmax = isempy(v) ? 0 : ignorenan_maximum(v)
|
||||||
|
extend_by_data!(v, vmax .+ (1:(n - length(v))))
|
||||||
|
end
|
||||||
|
extend_by_data!(v::AbstractVector, x) = isimmutable(v) ? vcat(v, x) : push!(v, x)
|
||||||
|
function extend_by_data!(v::AbstractVector, x::AbstractVector)
|
||||||
|
isimmutable(v) ? vcat(v, x) : append!(v, x)
|
||||||
end
|
end
|
||||||
Base.push!(series::Series, xi, yi) = (push_x!(series,xi); push_y!(series,yi))
|
|
||||||
Base.push!(series::Series, xi, yi, zi) = (push_x!(series,xi); push_y!(series,yi); push_z!(series,zi))
|
|
||||||
|
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
|
|
||||||
@ -968,59 +866,16 @@ end
|
|||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
# push/append for one series
|
# push/append for one series
|
||||||
|
|
||||||
# push value to first series
|
Base.push!(plt::Plot, args::Real...) = push!(plt, 1, args...)
|
||||||
Base.push!(plt::Plot, y::Real) = push!(plt, 1, y)
|
Base.push!(plt::Plot, i::Integer, args::Real...) = push!(plt.series_list[i], args...)
|
||||||
Base.push!(plt::Plot, x::Real, y::Real) = push!(plt, 1, x, y)
|
Base.append!(plt::Plot, args::AbstractVector...) = append!(plt, 1, args...)
|
||||||
Base.push!(plt::Plot, x::Real, y::Real, z::Real) = push!(plt, 1, x, y, z)
|
Base.append!(plt::Plot, i::Integer, args::Real...) = append!(plt.series_list[i], args...)
|
||||||
|
|
||||||
# y only
|
|
||||||
function Base.push!(plt::Plot, i::Integer, y::Real)
|
|
||||||
xdata, ydata = getxy(plt, i)
|
|
||||||
setxy!(plt, (extendSeriesByOne(xdata), extendSeriesData(ydata, y)), i)
|
|
||||||
plt
|
|
||||||
end
|
|
||||||
function Base.append!(plt::Plot, i::Integer, y::AVec)
|
|
||||||
xdata, ydata = plt[i]
|
|
||||||
if !isa(xdata, UnitRange{Int})
|
|
||||||
error("Expected x is a UnitRange since you're trying to push a y value only")
|
|
||||||
end
|
|
||||||
plt[i] = (extendSeriesByOne(xdata, length(y)), extendSeriesData(ydata, y))
|
|
||||||
plt
|
|
||||||
end
|
|
||||||
|
|
||||||
# x and y
|
|
||||||
function Base.push!(plt::Plot, i::Integer, x::Real, y::Real)
|
|
||||||
xdata, ydata = getxy(plt, i)
|
|
||||||
setxy!(plt, (extendSeriesData(xdata, x), extendSeriesData(ydata, y)), i)
|
|
||||||
plt
|
|
||||||
end
|
|
||||||
function Base.append!(plt::Plot, i::Integer, x::AVec, y::AVec)
|
|
||||||
@assert length(x) == length(y)
|
|
||||||
xdata, ydata = getxy(plt, i)
|
|
||||||
setxy!(plt, (extendSeriesData(xdata, x), extendSeriesData(ydata, y)), i)
|
|
||||||
plt
|
|
||||||
end
|
|
||||||
|
|
||||||
# x, y, and z
|
|
||||||
function Base.push!(plt::Plot, i::Integer, x::Real, y::Real, z::Real)
|
|
||||||
# @show i, x, y, z
|
|
||||||
xdata, ydata, zdata = getxyz(plt, i)
|
|
||||||
# @show xdata, ydata, zdata
|
|
||||||
setxyz!(plt, (extendSeriesData(xdata, x), extendSeriesData(ydata, y), extendSeriesData(zdata, z)), i)
|
|
||||||
plt
|
|
||||||
end
|
|
||||||
function Base.append!(plt::Plot, i::Integer, x::AVec, y::AVec, z::AVec)
|
|
||||||
@assert length(x) == length(y) == length(z)
|
|
||||||
xdata, ydata, zdata = getxyz(plt, i)
|
|
||||||
setxyz!(plt, (extendSeriesData(xdata, x), extendSeriesData(ydata, y), extendSeriesData(zdata, z)), i)
|
|
||||||
plt
|
|
||||||
end
|
|
||||||
|
|
||||||
# tuples
|
# tuples
|
||||||
Base.push!(plt::Plot, xy::Tuple{X,Y}) where {X,Y} = push!(plt, 1, xy...)
|
Base.push!(plt::Plot, t::Tuple) = push!(plt, 1, t...)
|
||||||
Base.push!(plt::Plot, xyz::Tuple{X,Y,Z}) where {X,Y,Z} = push!(plt, 1, xyz...)
|
Base.push!(plt::Plot, i::Integer, t::Tuple) = push!(plt, i, t...)
|
||||||
Base.push!(plt::Plot, i::Integer, xy::Tuple{X,Y}) where {X,Y} = push!(plt, i, xy...)
|
Base.append!(plt::Plot, t::Tuple) = append!(plt, 1, t...)
|
||||||
Base.push!(plt::Plot, i::Integer, xyz::Tuple{X,Y,Z}) where {X,Y,Z} = push!(plt, i, xyz...)
|
Base.append!(plt::Plot, i::Integer, t::Tuple) = append!(plt, i, t...)
|
||||||
|
|
||||||
# -------------------------------------------------------
|
# -------------------------------------------------------
|
||||||
# push/append for all series
|
# push/append for all series
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user