working on get/set xy/xyz indexing overhaul

This commit is contained in:
Thomas Breloff 2016-04-11 18:19:06 -04:00
parent d70f462899
commit 82d2cc943d
13 changed files with 249 additions and 158 deletions

View File

@ -124,16 +124,16 @@ end
# accessors for x/y data # accessors for x/y data
function Base.getindex(plt::Plot{BokehBackend}, i::Int) # function getxy(plt::Plot{BokehBackend}, i::Int)
series = plt.o.datacolumns[i].data # series = plt.o.datacolumns[i].data
series[:x], series[:y] # series[:x], series[:y]
end # end
#
function Base.setindex!(plt::Plot{BokehBackend}, xy::Tuple, i::Integer) # function setxy!(plt::Plot{BokehBackend}, xy::Tuple{X,Y}, i::Integer)
series = plt.o.datacolumns[i].data # series = plt.o.datacolumns[i].data
series[:x], series[:y] = xy # series[:x], series[:y] = xy
plt # plt
end # end
# ---------------------------------------------------------------- # ----------------------------------------------------------------

View File

@ -560,12 +560,12 @@ function getGadflyMappings(plt::Plot, i::Integer)
mappings = [l.mapping for l in plt.seriesargs[i][:gadflylayers]] mappings = [l.mapping for l in plt.seriesargs[i][:gadflylayers]]
end end
function Base.getindex(plt::Plot{GadflyBackend}, i::Integer) function getxy(plt::Plot{GadflyBackend}, i::Integer)
mapping = getGadflyMappings(plt, i)[1] mapping = getGadflyMappings(plt, i)[1]
mapping[:x], mapping[:y] mapping[:x], mapping[:y]
end end
function Base.setindex!(plt::Plot{GadflyBackend}, xy::Tuple, i::Integer) function setxy!{X,Y}(plt::Plot{GadflyBackend}, xy::Tuple{X,Y}, i::Integer)
for mapping in getGadflyMappings(plt, i) for mapping in getGadflyMappings(plt, i)
mapping[:x], mapping[:y] = xy mapping[:x], mapping[:y] = xy
end end

View File

@ -59,14 +59,14 @@ end
# accessors for x/y data # accessors for x/y data
function Base.getindex(plt::Plot{GLVisualizeBackend}, i::Int) function getxy(plt::Plot{GLVisualizeBackend}, i::Int)
# TODO: # TODO:
# series = plt.o.lines[i] # series = plt.o.lines[i]
# series.x, series.y # series.x, series.y
nothing, nothing nothing, nothing
end end
function Base.setindex!(plt::Plot{GLVisualizeBackend}, xy::Tuple, i::Integer) function setxy!{X,Y}(plt::Plot{GLVisualizeBackend}, xy::Tuple{X,Y}, i::Integer)
# TODO: # TODO:
# series = plt.o.lines[i] # series = plt.o.lines[i]
# series.x, series.y = xy # series.x, series.y = xy

View File

@ -736,12 +736,12 @@ end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
function Base.getindex(plt::Plot{GRBackend}, i::Int) function getxy(plt::Plot{GRBackend}, i::Int)
d = plt.seriesargs[i] d = plt.seriesargs[i]
d[:x], d[:y] d[:x], d[:y]
end end
function Base.setindex!(plt::Plot{GRBackend}, xy::Tuple, i::Integer) function setxy!{X,Y}(plt::Plot{GRBackend}, xy::Tuple{X,Y}, i::Integer)
d = plt.seriesargs[i] d = plt.seriesargs[i]
d[:x], d[:y] = xy d[:x], d[:y] = xy
plt plt

View File

@ -58,12 +58,12 @@ end
# accessors for x/y data # accessors for x/y data
function Base.getindex(plt::Plot{ImmerseBackend}, i::Integer) function getxy(plt::Plot{ImmerseBackend}, i::Integer)
mapping = getGadflyMappings(plt, i)[1] mapping = getGadflyMappings(plt, i)[1]
mapping[:x], mapping[:y] mapping[:x], mapping[:y]
end end
function Base.setindex!(plt::Plot{ImmerseBackend}, xy::Tuple, i::Integer) function setxy!{X,Y}(plt::Plot{ImmerseBackend}, xy::Tuple{X,Y}, i::Integer)
for mapping in getGadflyMappings(plt, i) for mapping in getGadflyMappings(plt, i)
mapping[:x], mapping[:y] = xy mapping[:x], mapping[:y] = xy
end end

View File

@ -52,16 +52,16 @@ end
# accessors for x/y data # accessors for x/y data
function Base.getindex(plt::Plot{PGFPlotsBackend}, i::Int) # function getxy(plt::Plot{PGFPlotsBackend}, i::Int)
d = plt.seriesargs[i] # d = plt.seriesargs[i]
d[:x], d[:y] # d[:x], d[:y]
end # end
#
function Base.setindex!(plt::Plot{PGFPlotsBackend}, xy::Tuple, i::Integer) # function setxy!{X,Y}(plt::Plot{PGFPlotsBackend}, xy::Tuple{X,Y}, i::Integer)
d = plt.seriesargs[i] # d = plt.seriesargs[i]
d[:x], d[:y] = xy # d[:x], d[:y] = xy
plt # plt
end # end
# ---------------------------------------------------------------- # ----------------------------------------------------------------

View File

@ -77,16 +77,16 @@ end
# accessors for x/y data # accessors for x/y data
function Base.getindex(plt::Plot{PlotlyBackend}, i::Int) # function getxy(plt::Plot{PlotlyBackend}, i::Int)
d = plt.seriesargs[i] # d = plt.seriesargs[i]
d[:x], d[:y] # d[:x], d[:y]
end # end
#
function Base.setindex!(plt::Plot{PlotlyBackend}, xy::Tuple, i::Integer) # function setxy!{X,Y}(plt::Plot{PlotlyBackend}, xy::Tuple{X,Y}, i::Integer)
d = plt.seriesargs[i] # d = plt.seriesargs[i]
d[:x], d[:y] = xy # d[:x], d[:y] = xy
plt # plt
end # end
# ---------------------------------------------------------------- # ----------------------------------------------------------------

View File

@ -85,12 +85,12 @@ end
# accessors for x/y data # accessors for x/y data
function Base.getindex(plt::Plot{PlotlyJSBackend}, i::Int) # function getxy(plt::Plot{PlotlyJSBackend}, i::Int)
d = plt.seriesargs[i] # d = plt.seriesargs[i]
d[:x], d[:y] # d[:x], d[:y]
end # end
function Base.setindex!(plt::Plot{PlotlyJSBackend}, xy::Tuple, i::Integer) function setxy!{X,Y}(plt::Plot{PlotlyJSBackend}, xy::Tuple{X,Y}, i::Integer)
d = plt.seriesargs[i] d = plt.seriesargs[i]
d[:x], d[:y] = xy d[:x], d[:y] = xy
# TODO: this is likely ineffecient... we should make a call that ONLY changes the plot data # TODO: this is likely ineffecient... we should make a call that ONLY changes the plot data

View File

@ -459,7 +459,7 @@ function _add_series(pkg::PyPlotBackend, plt::Plot; kw...)
plotfunc(x, y, z; extra_kwargs...) plotfunc(x, y, z; extra_kwargs...)
elseif lt in _3dTypes elseif lt in _3dTypes
plotfunc(d[:x], d[:y], d[:z]; extra_kwargs...) plotfunc(d[:x], d[:y], d[:z]; extra_kwargs...)[1]
elseif lt in (:scatter, :hist2d, :hexbin) elseif lt in (:scatter, :hist2d, :hexbin)
plotfunc(d[:x], d[:y]; extra_kwargs...) plotfunc(d[:x], d[:y]; extra_kwargs...)
@ -507,15 +507,6 @@ end
# ----------------------------------------------------------------- # -----------------------------------------------------------------
function Base.getindex(plt::Plot{PyPlotBackend}, i::Integer)
series = plt.seriesargs[i][:serieshandle]
try
return series[:get_data]()
catch
xy = series[:get_offsets]()
return vec(xy[:,1]), vec(xy[:,2])
end
end
function minmaxseries(ds, vec, axis) function minmaxseries(ds, vec, axis)
lo, hi = Inf, -Inf lo, hi = Inf, -Inf
@ -552,23 +543,46 @@ function set_lims!(plt::Plot{PyPlotBackend}, axis::Symbol)
end end
end end
function Base.setindex!{X,Y}(plt::Plot{PyPlotBackend}, xy::Tuple{X,Y}, i::Integer) # --------------------------------------------------------------------------
d = plt.seriesargs[i]
series = d[:serieshandle]
x, y = xy
d[:x], d[:y] = x, y
try
series[:set_data](x, y)
catch
series[:set_offsets](hcat(x, y))
end
# function getxy(plt::Plot{PyPlotBackend}, i::Integer)
# series = plt.seriesargs[i][:serieshandle]
# try
# return series[:get_data]()
# catch
# xy = series[:get_offsets]()
# return vec(xy[:,1]), vec(xy[:,2])
# end
# end
function setxy!{X,Y}(plt::Plot{PyPlotBackend}, xy::Tuple{X,Y}, i::Integer)
d = plt.seriesargs[i]
d[:x], d[:y] = xy
series = d[:serieshandle]
try
series[:set_data](d[:x], d[:y])
catch
series[:set_offsets](hcat(d[:x], d[:y]))
end
set_lims!(plt, d[:axis]) set_lims!(plt, d[:axis])
plt plt
end end
function Base.setindex!{X,Y,Z}(plt::Plot{PyPlotBackend}, xyz::Tuple{X,Y,Z}, i::Integer)
warn("setindex not implemented for xyz") function setxyz!{X,Y,Z}(plt::Plot{PyPlotBackend}, xyz::Tuple{X,Y,Z}, i::Integer)
d = plt.seriesargs[i]
# @show typeof(d), typeof(xyz)
d[:x], d[:y], d[:z] = xyz
series = d[:serieshandle]
# @show keys(series)
# try
series[:set_data](d[:x], d[:y])
series[:set_3d_properties](d[:z])
# catch
# series[:set_offsets](hcat(d[:x], d[:y], d[:z]))
# end
set_lims!(plt, d[:axis])
# dumpdict(d, "H",true)
plt plt
end end

View File

@ -199,12 +199,12 @@ end
# accessors for x/y data # accessors for x/y data
function Base.getindex(plt::Plot{QwtBackend}, i::Int) function getxy(plt::Plot{QwtBackend}, i::Int)
series = plt.o.lines[i] series = plt.o.lines[i]
series.x, series.y series.x, series.y
end end
function Base.setindex!(plt::Plot{QwtBackend}, xy::Tuple, i::Integer) function setxy!{X,Y}(plt::Plot{QwtBackend}, xy::Tuple{X,Y}, i::Integer)
series = plt.o.lines[i] series = plt.o.lines[i]
series.x, series.y = xy series.x, series.y = xy
plt plt

View File

@ -51,14 +51,14 @@ end
# accessors for x/y data # accessors for x/y data
function Base.getindex(plt::Plot{[PkgName]AbstractBackend}, i::Int) # function getxy(plt::Plot{[PkgName]AbstractBackend}, i::Int)
# TODO: return a tuple of (x, y) vectors # # TODO: return a tuple of (x, y) vectors
end # end
#
function Base.setindex!(plt::Plot{[PkgName]AbstractBackend}, xy::Tuple, i::Integer) # function setxy!{X,Y}(plt::Plot{[PkgName]AbstractBackend}, xy::Tuple{X,Y}, i::Integer)
# TODO: set the plot data from the (x,y) tuple # # TODO: set the plot data from the (x,y) tuple
plt # plt
end # end
# ---------------------------------------------------------------- # ----------------------------------------------------------------

View File

@ -279,7 +279,10 @@ end
# 3d line or scatter # 3d line or scatter
function process_inputs(plt::AbstractPlot, d::KW, x::AVec, y::AVec, zvec::AVec) function process_inputs(plt::AbstractPlot, d::KW, x::AVec, y::AVec, zvec::AVec)
# default to path3d if we haven't set a 3d linetype # default to path3d if we haven't set a 3d linetype
if !(get(d, :linetype, :none) in _3dTypes) lt = get(d, :linetype, :none)
if lt == :scatter
d[:linetype] = :scatter3d
elseif !(lt in _3dTypes)
d[:linetype] = :path3d d[:linetype] = :path3d
end end
d[:x], d[:y], d[:z] = x, y, zvec d[:x], d[:y], d[:z] = x, y, zvec

View File

@ -114,6 +114,7 @@ function regressionXY(x, y)
regx, regy regx, regy
end end
# ---------------------------------------------------------------
# ------------------------------------------------------------------------------------ # ------------------------------------------------------------------------------------
@ -261,6 +262,7 @@ allReals(arg) = trueOrAllTrue(a -> typeof(a) <: Real, arg)
allFunctions(arg) = trueOrAllTrue(a -> isa(a, Function), arg) allFunctions(arg) = trueOrAllTrue(a -> isa(a, Function), arg)
# --------------------------------------------------------------- # ---------------------------------------------------------------
# ---------------------------------------------------------------
""" """
@ -348,6 +350,7 @@ function with(f::Function, args...; kw...)
ret ret
end end
# ---------------------------------------------------------------
# --------------------------------------------------------------- # ---------------------------------------------------------------
type DebugMode type DebugMode
@ -382,70 +385,7 @@ function dumpcallstack()
end end
# --------------------------------------------------------------- # ---------------------------------------------------------------
# ---------------------------------------------------------------
# push/append/clear/set the underlying plot data
# NOTE: backends should implement the getindex and setindex! methods to get/set the x/y data objects
# index versions
function Base.push!(plt::Plot, i::Integer, x::Real, y::Real)
xdata, ydata = plt[i]
plt[i] = (extendSeriesData(xdata, x), extendSeriesData(ydata, y))
plt
end
function Base.push!(plt::Plot, i::Integer, y::Real)
xdata, ydata = plt[i]
# if !isa(xdata, UnitRange)
# error("Expected x is a UnitRange since you're trying to push a y value only. typeof(x) = $(typeof(xdata))")
# end
plt[i] = (extendSeriesByOne(xdata), extendSeriesData(ydata, y))
plt
end
Base.push!(plt::Plot, y::Real) = push!(plt, 1, y)
# update all at once
function Base.push!(plt::Plot, x::AVec, y::AVec)
nx = length(x)
ny = length(y)
for i in 1:plt.n
push!(plt, i, x[mod1(i,nx)], y[mod1(i,ny)])
end
plt
end
function Base.push!(plt::Plot, x::Real, y::AVec)
push!(plt, [x], y)
end
function Base.push!(plt::Plot, y::AVec)
ny = length(y)
for i in 1:plt.n
push!(plt, i, y[mod1(i,ny)])
end
plt
end
# append to index
function Base.append!(plt::Plot, i::Integer, x::AVec, y::AVec)
@assert length(x) == length(y)
xdata, ydata = plt[i]
plt[i] = (extendSeriesData(xdata, x), extendSeriesData(ydata, y))
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
# used in updating an existing series # used in updating an existing series
extendSeriesByOne(v::UnitRange{Int}, n::Int = 1) = isempty(v) ? (1:n) : (minimum(v):maximum(v)+n) extendSeriesByOne(v::UnitRange{Int}, n::Int = 1) = isempty(v) ? (1:n) : (minimum(v):maximum(v)+n)
@ -456,24 +396,157 @@ extendSeriesData{T}(v::AVec{T}, z::Real) = (push!(v, convert(T, z)); v)
extendSeriesData{T}(v::AVec{T}, z::AVec) = (append!(v, convert(Vector{T}, z)); v) extendSeriesData{T}(v::AVec{T}, z::AVec) = (append!(v, convert(Vector{T}, z)); v)
# -------------------------------------------------------
# NOTE: backends should implement the following methods to get/set the x/y/z data objects
tovec(v::AbstractVector) = v
tovec(v::Void) = zeros(0)
function getxy(plt::Plot, i::Integer)
d = plt.seriesargs[i]
tovec(d[:x]), tovec(d[:y])
end
function getxyz(plt::Plot, i::Integer)
d = plt.seriesargs[i]
tovec(d[:x]), tovec(d[:y]), tovec(d[:z])
end
function setxy!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer)
d = plt.seriesargs[i]
d[:x], d[:y] = xy
end
function setxyz!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer)
d = plt.seriesargs[i]
d[:x], d[:y], d[:z] = xyz
end
# -------------------------------------------------------
# indexing notation
Base.getindex(plt::Plot, i::Integer) = getxy(plt, i)
Base.setindex!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer) = setxy!(plt, xy, i)
Base.setindex!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) = setxyz!(plt, xyz, i)
# -------------------------------------------------------
# push/append for one series
# push value to first series
Base.push!(plt::Plot, y::Real) = push!(plt, 1, y)
Base.push!(plt::Plot, x::Real, y::Real) = push!(plt, 1, x, y)
Base.push!(plt::Plot, x::Real, y::Real, z::Real) = push!(plt, 1, x, y, z)
# 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
Base.push!{X,Y}(plt::Plot, xy::Tuple{X,Y}) = push!(plt, 1, xy...)
Base.push!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}) = push!(plt, 1, xyz...)
Base.push!{X,Y}(plt::Plot, i::Integer, xy::Tuple{X,Y}) = push!(plt, i, xy...)
Base.push!{X,Y,Z}(plt::Plot, i::Integer, xyz::Tuple{X,Y,Z}) = push!(plt, i, xyz...)
# -------------------------------------------------------
# push/append for all series
# push y[i] to the ith series
function Base.push!(plt::Plot, y::AVec)
ny = length(y)
for i in 1:plt.n
push!(plt, i, y[mod1(i,ny)])
end
plt
end
# push y[i] to the ith series
# same x for each series
function Base.push!(plt::Plot, x::Real, y::AVec)
push!(plt, [x], y)
end
# push (x[i], y[i]) to the ith series
function Base.push!(plt::Plot, x::AVec, y::AVec)
nx = length(x)
ny = length(y)
for i in 1:plt.n
push!(plt, i, x[mod1(i,nx)], y[mod1(i,ny)])
end
plt
end
# push (x[i], y[i], z[i]) to the ith series
function Base.push!(plt::Plot, x::AVec, y::AVec, z::AVec)
nx = length(x)
ny = length(y)
nz = length(z)
for i in 1:plt.n
push!(plt, i, x[mod1(i,nx)], y[mod1(i,ny)], z[mod1(i,nz)])
end
plt
end
# --------------------------------------------------------------- # ---------------------------------------------------------------
# ---------------------------------------------------------------
# graphs detailing the features that each backend supports
function supportGraph(allvals, func) function supportGraph(allvals, func)
vals = reverse(sort(allvals)) vals = reverse(sort(allvals))
bs = sort(backends()) bs = sort(backends())
x = ASCIIString[] x = ASCIIString[]
y = ASCIIString[] y = ASCIIString[]
for val in vals for val in vals
for b in bs for b in bs
supported = func(Plots._backend_instance(b)) supported = func(Plots._backend_instance(b))
if val in supported if val in supported
push!(x, string(b)) push!(x, string(b))
push!(y, string(val)) push!(y, string(val))
end
end end
end end
end n = length(vals)
n = length(vals) scatter(x, y, m=:rect, ms=10, size=(300,100+18*n), leg=false)
scatter(x, y, m=:rect, ms=10, size=(300,100+18*n), leg=false)
end end
supportGraphArgs() = supportGraph(_allArgs, supportedArgs) supportGraphArgs() = supportGraph(_allArgs, supportedArgs)
@ -484,14 +557,15 @@ supportGraphScales() = supportGraph(_allScales, supportedScales)
supportGraphAxes() = supportGraph(_allAxes, supportedAxes) supportGraphAxes() = supportGraph(_allAxes, supportedAxes)
function dumpSupportGraphs() function dumpSupportGraphs()
for func in (supportGraphArgs, supportGraphTypes, supportGraphStyles, for func in (supportGraphArgs, supportGraphTypes, supportGraphStyles,
supportGraphMarkers, supportGraphScales, supportGraphAxes) supportGraphMarkers, supportGraphScales, supportGraphAxes)
plt = func() plt = func()
png(joinpath(Pkg.dir("ExamplePlots"), "docs", "examples", "img", "supported", "$(string(func))")) png(joinpath(Pkg.dir("ExamplePlots"), "docs", "examples", "img", "supported", "$(string(func))"))
end end
end end
# --------------------------------------------------------------- # ---------------------------------------------------------------
# ---------------------------------------------------------------
# Some conversion functions # Some conversion functions