From 010b8a382e2ff0bbaaacb71b9d1c990c3f1d21cc Mon Sep 17 00:00:00 2001 From: Thomas Breloff Date: Fri, 27 May 2016 10:58:45 -0400 Subject: [PATCH] working on building plot from existing plots --- src/layouts.jl | 98 +++++++++++++++++++++++++++++++++++------ src/plot.jl | 115 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 199 insertions(+), 14 deletions(-) diff --git a/src/layouts.jl b/src/layouts.jl index 9dce2d81..dd71e0b3 100644 --- a/src/layouts.jl +++ b/src/layouts.jl @@ -312,33 +312,73 @@ end # constructors # pass the layout arg through -function build_layout(d::KW) - build_layout(get(d, :layout, default(:layout))) +function layout_args(d::KW) + layout_args(get(d, :layout, default(:layout))) end -function build_layout(n::Integer) +function layout_args(d::KW, n_override::Integer) + layout, n = layout_args(get(d, :layout, n_override)) + if n != n_override + error("When doing layout, n != n_override. You're probably trying to force existing plots into a layout that doesn't fit them.") + end + layout, n +end + +function layout_args(n::Integer) nr, nc = compute_gridsize(n, -1, -1) - build_layout(GridLayout(nr, nc), n) + GridLayout(nr, nc), n end -function build_layout{I<:Integer}(sztup::NTuple{2,I}) +function layout_args{I<:Integer}(sztup::NTuple{2,I}) nr, nc = sztup - build_layout(GridLayout(nr, nc)) + GridLayout(nr, nc), nr*nc end -function build_layout{I<:Integer}(sztup::NTuple{3,I}) +function layout_args{I<:Integer}(sztup::NTuple{3,I}) n, nr, nc = sztup nr, nc = compute_gridsize(n, nr, nc) - build_layout(GridLayout(nr, nc), n) + GridLayout(nr, nc), n end # compute number of subplots -function build_layout(layout::GridLayout) - # nr, nc = size(layout) - # build_layout(layout, nr*nc) - +function layout_args(layout::GridLayout) # recursively get the size of the grid n = calc_num_subplots(layout) + layout, n +end + +layout_args(huh) = error("unhandled layout type $(typeof(huh)): $huh") + +# # pass the layout arg through +# function build_layout(d::KW) +# build_layout(get(d, :layout, default(:layout))) +# end +# +# function build_layout(n::Integer) +# nr, nc = compute_gridsize(n, -1, -1) +# build_layout(GridLayout(nr, nc), n) +# end +# +# function build_layout{I<:Integer}(sztup::NTuple{2,I}) +# nr, nc = sztup +# build_layout(GridLayout(nr, nc)) +# end +# +# function build_layout{I<:Integer}(sztup::NTuple{3,I}) +# n, nr, nc = sztup +# nr, nc = compute_gridsize(n, nr, nc) +# build_layout(GridLayout(nr, nc), n) +# end +# +# # compute number of subplots +# function build_layout(layout::GridLayout) +# # recursively get the size of the grid +# n = calc_num_subplots(layout) +# build_layout(layout, n) +# end + +function build_layout(args...) + layout, n = layout_args(args...) build_layout(layout, n) end @@ -374,7 +414,39 @@ function build_layout(layout::GridLayout, n::Integer) layout, subplots, spmap end -build_layout(huh) = error("unhandled layout type $(typeof(huh)): $huh") +# build a layout from a list of existing Plot objects +# TODO... much of the logic overlaps with the method above... can we merge? +function build_layout(layout::GridLayout, numsp::Integer, plts::AVec{Plot}) + nr, nc = size(layout) + subplots = Subplot[] + spmap = SubplotMap() + i = 0 + for r=1:nr, c=1:nc + l = layout[r,c] + if isa(l, EmptyLayout) + plt = shift!(plts) # grab the first plot out of the list + layout[r,c] = plt.layout + append!(subplots, plt.subplots) + merge!(spmap, plt.spmap) + if hasattr(l,:width) + layout.widths[c] = attr(l,:width) + end + if hasattr(l,:height) + layout.heights[r] = attr(l,:height) + end + i += length(plt.subplots) + elseif isa(l, GridLayout) + # sub-grid + l, sps, m = build_layout(l, numsp-i, plts) + append!(subplots, sps) + merge!(spmap, m) + i += length(sps) + end + i >= numsp && break # only add n subplots + end + layout, subplots, spmap +end + # ---------------------------------------------------------------------- # @layout macro diff --git a/src/plot.jl b/src/plot.jl index 16bbea78..b1100446 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -65,6 +65,118 @@ function plot(args...; kw...) _plot!(plt, d, args...) end +# build a new plot from existing plots +# note: we split into plt1 and plts_tail so we can dispatch correctly +function plot(plt1::Plot, plts_tail::Plot...; kw...) + d = KW(kw) + preprocessArgs!(d) + + # create a layout, but don't add subplots... we expect nplts == layout capacity + # TODO: move this to layouts.jl + # plts = vcat(plt1, plts) + + # build our plot vector + n = length(plts_tail) + 1 + plts = Array(Plot, n) + plts[1] = plt1 + for (i,plt) in enumerate(plts_tail) + plts[i+1] = plt + end + # plts[2:end] = plts_tail + # @show typeof(plts),n + + # compute the layout + layout = layout_args(d, n)[1] + num_sp = sum([length(p.subplots) for p in plts]) + # @show typeof(layout), num_sp + + # create a new plot object, with subplot list/map made of existing subplots. + # note: we create a new backend figure for this new plot object + # note: all subplots and series "belong" to this new plot... + plt = Plot() + + # update plot args, first with existing plots, then override with d + for p in plts + _update_plot_args(plt, p.attr) + plt.n += p.n + end + _update_plot_args(plt, d) + + # pass new plot to the backend + plt.o = _create_backend_figure(plt) + plt.init = true + + # create the layout and initialize the subplots + plt.layout, plt.subplots, plt.spmap = build_layout(layout, num_sp, copy(plts)) + # @show map(typeof, (plt.layout, plt.subplots, plt.spmap)) + for (idx, sp) in enumerate(plt.subplots) + _initialize_subplot(plt, sp) + serieslist = series_list(sp) + sp.plt = plt + sp.attr[:subplot_index] = idx + for series in serieslist + push!(plt.series_list, series) + _series_added(plt, series) + end + end + + # finish up + current(plt) + if get(d, :show, default(:show)) + gui() + end + plt + + # _update_plot_args(plt, d) + # plt.o = _create_backend_figure(plt) + # + # # create the layout and subplots from the inputs + # plt.layout, plt.subplots, plt.spmap = build_layout(plt.attr) + # for (idx,sp) in enumerate(plt.subplots) + # sp.plt = plt + # sp.attr[:subplot_index] = idx + # # _update_subplot_args(plt, sp, copy(d), idx) + # end + # + # plt.init = true + # + # nr, nc = size(layout) + # subplots = Subplot[] + # spmap = SubplotMap() + # i = 0 + # for r=1:nr, c=1:nc + # l = layout[r,c] + # if isa(l, EmptyLayout) + # i += 1 + # plt = plts[i] + # layout[r,c] = plt.layout + # append!(subplots, plt.subplots) + # merge!(spmap, plt.spmap) + # # if init_sp + # # sp = Subplot(backend(), parent=layout) + # # layout[r,c] = sp + # # push!(subplots, sp) + # # spmap[attr(l,:label,gensym())] = sp + # # end + # if hasattr(l,:width) + # layout.widths[c] = attr(l,:width) + # end + # if hasattr(l,:height) + # layout.heights[r] = attr(l,:height) + # end + # elseif isa(l, GridLayout) + # # sub-grid + # l, sps, m = build_layout(l, n-i) + # append!(subplots, sps) + # merge!(spmap, m) + # i += length(sps) + # end + # i >= n && break # only add n subplots + # end + # layout, subplots, spmap + +end + # this adds to the current plot, or creates a new plot if none are current @@ -344,7 +456,8 @@ function _plot!(plt::Plot, d::KW, args...) # note: lets ignore the show param and effectively use the semicolon at the end of the REPL statement # # do we want to show it? - if haskey(d, :show) && d[:show] + # if haskey(d, :show) && d[:show] + if get(d, :show, default(:show)) gui() end