started work on new FlexLayout, some reorg/cleaning

This commit is contained in:
Thomas Breloff 2016-03-10 22:43:02 -05:00
parent 09d45aa64b
commit 7a5197df63
4 changed files with 177 additions and 107 deletions

View File

@ -14,6 +14,7 @@ export
Subplot,
SubplotLayout,
GridLayout,
RowsLayout,
FlexLayout,
AVec,
AMat,
@ -26,7 +27,7 @@ export
current,
default,
with,
scatter,
scatter!,
bar,
@ -138,6 +139,7 @@ include("plotter2.jl")
include("args.jl")
include("plot.jl")
include("subplot.jl")
include("layouts.jl")
include("recipes.jl")
include("animation.jl")
include("output.jl")

120
src/layouts.jl Normal file
View File

@ -0,0 +1,120 @@
# -----------------------------------------------------------
# we're taking in a nested structure of some kind... parse it out and build a FlexLayout
function subplotlayout(mat::AbstractVecOrMat; widths = nothing, heights = nothing)
n = 0
nr, nc = size(mat)
grid = Array(IntOrFlex, nr, nc)
for i=1:nr, j=1:nc
v = mat[i,j]
if isa(v, Integer)
grid[i,j] = Int(v)
n += 1
elseif isa(v, Tuple)
warn("need to handle tuples somehow... (idx, sizepct)")
grid[i,j] = nothing
elseif v == nothing
grid[i,j] = nothing
elseif isa(v, AbstractVecOrMat)
grid[i,j] = layout(v)
n += grid[i,j].n
else
error("How do we process? $v")
end
end
if widths == nothing
widths = ones(nc) ./ nc
end
if heights == nothing
heights = ones(nr) ./ nr
end
FlexLayout(n, grid, widths, heights)
end
function subplotlayout(sz::Tuple{Int,Int})
GridLayout(sz...)
end
function subplotlayout(rowcounts::AVec{Int})
RowsLayout(sum(rowcounts), rowcounts)
end
function subplotlayout(numplts::Int, nr::Int, nc::Int)
# figure out how many rows/columns we need
if nr == -1
if nc == -1
nr = round(Int, sqrt(numplts))
nc = ceil(Int, numplts / nr)
else
nr = ceil(Int, numplts / nc)
end
else
nc = ceil(Int, numplts / nr)
end
# if it's a perfect rectangle, just create a grid
if numplts == nr * nc
return GridLayout(nr, nc)
end
# create the rowcounts vector
i = 0
rowcounts = Int[]
for r in 1:nr
cnt = min(nc, numplts - i)
push!(rowcounts, cnt)
i += cnt
end
RowsLayout(numplts, rowcounts)
end
Base.length(layout::RowsLayout) = layout.numplts
Base.start(layout::RowsLayout) = 1
Base.done(layout::RowsLayout, state) = state > length(layout)
function Base.next(layout::RowsLayout, state)
r = 1
c = 0
for i = 1:state
c += 1
if c > layout.rowcounts[r]
r += 1
c = 1
end
end
(r,c), state + 1
end
nrows(layout::RowsLayout) = length(layout.rowcounts)
ncols(layout::RowsLayout, row::Int) = row < 1 ? 0 : (row > nrows(layout) ? 0 : layout.rowcounts[row])
# get the plot index given row and column
Base.getindex(layout::RowsLayout, r::Int, c::Int) = sum(layout.rowcounts[1:r-1]) + c
Base.length(layout::GridLayout) = layout.nr * layout.nc
Base.start(layout::GridLayout) = 1
Base.done(layout::GridLayout, state) = state > length(layout)
function Base.next(layout::GridLayout, state)
r = div(state-1, layout.nc) + 1
c = mod1(state, layout.nc)
(r,c), state + 1
end
nrows(layout::GridLayout) = layout.nr
ncols(layout::GridLayout) = layout.nc
ncols(layout::GridLayout, row::Int) = layout.nc
# get the plot index given row and column
Base.getindex(layout::GridLayout, r::Int, c::Int) = (r-1) * layout.nc + c

View File

@ -1,83 +1,4 @@
function subplotlayout(sz::@compat(Tuple{Int,Int}))
GridLayout(sz...)
end
function subplotlayout(rowcounts::AVec{Int})
FlexLayout(sum(rowcounts), rowcounts)
end
function subplotlayout(numplts::Int, nr::Int, nc::Int)
# figure out how many rows/columns we need
if nr == -1
if nc == -1
nr = round(Int, sqrt(numplts))
nc = ceil(Int, numplts / nr)
else
nr = ceil(Int, numplts / nc)
end
else
nc = ceil(Int, numplts / nr)
end
# if it's a perfect rectangle, just create a grid
if numplts == nr * nc
return GridLayout(nr, nc)
end
# create the rowcounts vector
i = 0
rowcounts = Int[]
for r in 1:nr
cnt = min(nc, numplts - i)
push!(rowcounts, cnt)
i += cnt
end
FlexLayout(numplts, rowcounts)
end
Base.length(layout::FlexLayout) = layout.numplts
Base.start(layout::FlexLayout) = 1
Base.done(layout::FlexLayout, state) = state > length(layout)
function Base.next(layout::FlexLayout, state)
r = 1
c = 0
for i = 1:state
c += 1
if c > layout.rowcounts[r]
r += 1
c = 1
end
end
(r,c), state + 1
end
nrows(layout::FlexLayout) = length(layout.rowcounts)
ncols(layout::FlexLayout, row::Int) = row < 1 ? 0 : (row > nrows(layout) ? 0 : layout.rowcounts[row])
# get the plot index given row and column
Base.getindex(layout::FlexLayout, r::Int, c::Int) = sum(layout.rowcounts[1:r-1]) + c
Base.length(layout::GridLayout) = layout.nr * layout.nc
Base.start(layout::GridLayout) = 1
Base.done(layout::GridLayout, state) = state > length(layout)
function Base.next(layout::GridLayout, state)
r = div(state-1, layout.nc) + 1
c = mod1(state, layout.nc)
(r,c), state + 1
end
nrows(layout::GridLayout) = layout.nr
ncols(layout::GridLayout) = layout.nc
ncols(layout::GridLayout, row::Int) = layout.nc
# get the plot index given row and column
Base.getindex(layout::GridLayout, r::Int, c::Int) = (r-1) * layout.nc + c
Base.getindex(subplt::Subplot, args...) = subplt.plts[subplt.layout[args...]]
# handle "linking" the subplot axes together
@ -308,7 +229,7 @@ function subplot!(subplt::Subplot, args...; kw...)
# create the underlying object (each backend will do this differently)
# note: we call it once before doing the individual plots, and once after
# this is because some backends need to set up the subplots and then plot,
# this is because some backends need to set up the subplots and then plot,
# and others need to do it the other way around
if !subplt.initialized
subplt.initialized = _create_subplot(subplt, true)
@ -343,7 +264,7 @@ function subplot!(subplt::Subplot, args...; kw...)
end
dumpdict(di, "subplot! kwList $i")
dumpdict(plt.plotargs, "plt.plotargs before plotting")
_add_series_subplot(plt; di...)
end
@ -366,7 +287,7 @@ function _add_series_subplot(plt::Plot, args...; kw...)
setTicksFromStringVector(d, d, :y, :yticks)
_add_series(plt.backend, plt; d...)
_add_annotations(plt, d)
warnOnUnsupportedScales(plt.backend, d)
end

View File

@ -3,47 +3,74 @@ typealias AVec AbstractVector
typealias AMat AbstractMatrix
immutable PlotsDisplay <: Display end
abstract PlottingPackage
abstract PlottingObject{T<:PlottingPackage}
type Plot{T<:PlottingPackage} <: PlottingObject{T}
o # the underlying object
backend::T
n::Int # number of series
# -----------------------------------------------------------
# Plot
# -----------------------------------------------------------
# store these just in case
plotargs::Dict
seriesargs::Vector{Dict} # args for each series
type Plot{T<:PlottingPackage} <: PlottingObject{T}
o # the backend's plot object
backend::T # the backend type
n::Int # number of series
plotargs::Dict # arguments for the whole plot
seriesargs::Vector{Dict} # arguments for each series
end
# -----------------------------------------------------------
# Layouts
# -----------------------------------------------------------
abstract SubplotLayout
# -----------------------------------------------------------
"Simple grid, indices are row-major."
immutable GridLayout <: SubplotLayout
nr::Int
nc::Int
nr::Int
nc::Int
end
# -----------------------------------------------------------
"Number of plots per row"
immutable RowsLayout <: SubplotLayout
numplts::Int
rowcounts::AbstractVector{Int}
end
# -----------------------------------------------------------
"Flexible, nested layout with optional size percentages."
immutable FlexLayout <: SubplotLayout
numplts::Int
rowcounts::AbstractVector{Int}
n::Int
grid::Matrix # Nested layouts. Each position
# can be a plot index or another FlexLayout
widths::Vector{Float64}
heights::Vector{Float64}
end
typealias IntOrFlex Union{Int,FlexLayout}
# -----------------------------------------------------------
# Subplot
# -----------------------------------------------------------
type Subplot{T<:PlottingPackage, L<:SubplotLayout} <: PlottingObject{T}
o # the underlying object
plts::Vector{Plot{T}} # the individual plots
backend::T
p::Int # number of plots
n::Int # number of series
layout::L
# plotargs::Vector{Dict}
plotargs::Dict
initialized::Bool
linkx::Bool
linky::Bool
linkfunc::Function # maps (row,column) -> (BoolOrNothing, BoolOrNothing)... if xlink/ylink are nothing, then use subplt.linkx/y
o # the underlying object
plts::Vector{Plot{T}} # the individual plots
backend::T
p::Int # number of plots
n::Int # number of series
layout::L
# plotargs::Vector{Dict}
plotargs::Dict
initialized::Bool
linkx::Bool
linky::Bool
linkfunc::Function # maps (row,column) -> (BoolOrNothing, BoolOrNothing)... if xlink/ylink are nothing, then use subplt.linkx/y
end
# -----------------------------------------------------------------------