backend template renaming/reorg/cleanup, pyplot fixes
This commit is contained in:
parent
d4d388a94b
commit
ef0d99340a
@ -51,6 +51,7 @@ like_line(seriestype::Symbol) = seriestype in (:line, :path, :steppre, :ste
|
||||
like_surface(seriestype::Symbol) = seriestype in (:contour, :contour3d, :heatmap, :surface, :wireframe, :image)
|
||||
|
||||
is3d(seriestype::Symbol) = seriestype in _3dTypes
|
||||
is3d(series::Series) = is3d(series.d)
|
||||
is3d(d::KW) = trueOrAllTrue(is3d, d[:seriestype])
|
||||
|
||||
const _allStyles = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
||||
|
||||
@ -53,10 +53,10 @@ _update_plot(pkg::AbstractBackend, plt::Plot, d::KW) = error("_update_plot($pkg
|
||||
|
||||
# don't do anything as a default
|
||||
_create_backend_figure(plt::Plot) = nothing
|
||||
_before_add_series(plt::Plot) = nothing
|
||||
_add_series(plt::Plot) = nothing
|
||||
_add_annotations{X,Y,V}(plt::Plot, anns::AVec{Tuple{X,Y,V}}) = nothing
|
||||
_update_plot_pos_size(plt::AbstractPlot, d::KW) = nothing
|
||||
_before_update(plt::Plot) = nothing
|
||||
_series_added(plt::Plot) = nothing
|
||||
# _add_annotations{X,Y,V}(plt::Plot, anns::AVec{Tuple{X,Y,V}}) = nothing
|
||||
# _update_plot_pos_size(plt::AbstractPlot, d::KW) = nothing
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
@ -79,13 +79,6 @@ function _initialize_backend(::BokehBackend; kw...)
|
||||
end
|
||||
end
|
||||
|
||||
# make255(x) = round(Int, 255 * x)
|
||||
|
||||
# function bokehcolor(c::Colorant)
|
||||
# @sprintf("rgba(%d, %d, %d, %1.3f)", [make255(f(c)) for f in [red,green,blue]]..., alpha(c))
|
||||
# end
|
||||
# bokehcolor(cs::ColorScheme) = bokehcolor(getColor(cs))
|
||||
|
||||
|
||||
const _glyphtypes = KW(
|
||||
:ellipse => :Circle,
|
||||
@ -154,8 +147,8 @@ function _create_backend_figure(plt::Plot{BokehBackend})
|
||||
end
|
||||
|
||||
|
||||
# function _add_series(::BokehBackend, plt::Plot, d::KW)
|
||||
function _add_series(plt::Plot{BokehBackend}, series::Series)
|
||||
# function _series_added(::BokehBackend, plt::Plot, d::KW)
|
||||
function _series_added(plt::Plot{BokehBackend}, series::Series)
|
||||
bdata = Dict{Symbol, Vector}(:x => collect(series.d[:x]), :y => collect(series.d[:y]))
|
||||
|
||||
glyph = Bokeh.Bokehjs.Glyph(
|
||||
@ -180,9 +173,6 @@ end
|
||||
function _update_plot(plt::Plot{BokehBackend}, d::KW)
|
||||
end
|
||||
|
||||
function _update_plot_pos_size(plt::AbstractPlot{BokehBackend}, d::KW)
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# accessors for x/y data
|
||||
@ -199,29 +189,9 @@ end
|
||||
# end
|
||||
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
function _add_annotations{X,Y,V}(plt::Plot{BokehBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
|
||||
for ann in anns
|
||||
# TODO: add the annotation to the plot
|
||||
end
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# function _create_subplot(subplt::Subplot{BokehBackend}, isbefore::Bool)
|
||||
# # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
|
||||
#
|
||||
# end
|
||||
|
||||
|
||||
function _expand_limits(lims, plt::Plot{BokehBackend}, isx::Bool)
|
||||
# TODO: call expand limits for each plot data
|
||||
end
|
||||
|
||||
function _remove_axis(plt::Plot{BokehBackend}, isx::Bool)
|
||||
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
|
||||
@ -580,8 +580,8 @@ end
|
||||
|
||||
|
||||
# plot one data series
|
||||
# function _add_series(::GadflyBackend, plt::Plot, d::KW)
|
||||
function _add_series(plt::Plot{GadflyBackend}, series::Series)
|
||||
# function _series_added(::GadflyBackend, plt::Plot, d::KW)
|
||||
function _series_added(plt::Plot{GadflyBackend}, series::Series)
|
||||
# first clear out the temporary layer
|
||||
gplt = getGadflyContext(plt)
|
||||
if gplt.layers[1].geom.tag == :remove
|
||||
|
||||
@ -95,8 +95,8 @@ function _create_backend_figure(plt::Plot{GLVisualizeBackend})
|
||||
end
|
||||
|
||||
|
||||
# function _add_series(::GLVisualizeBackend, plt::Plot, d::KW)
|
||||
function _add_series(plt::Plot{GLVisualizeBackend}, series::Series)
|
||||
# function _series_added(::GLVisualizeBackend, plt::Plot, d::KW)
|
||||
function _series_added(plt::Plot{GLVisualizeBackend}, series::Series)
|
||||
# TODO: add one series to the underlying package
|
||||
# push!(plt.seriesargs, d)
|
||||
# TODO: this should be moved to the display method?
|
||||
|
||||
@ -873,7 +873,7 @@ end
|
||||
# Plot(nothing, pkg, 0, d, KW[])
|
||||
# end
|
||||
|
||||
# function _add_series(::GRBackend, plt::Plot, d::KW)
|
||||
# function _series_added(::GRBackend, plt::Plot, d::KW)
|
||||
# push!(plt.seriesargs, d)
|
||||
# plt
|
||||
# end
|
||||
|
||||
@ -42,13 +42,13 @@ end
|
||||
|
||||
|
||||
# # plot one data series
|
||||
# function _add_series(::ImmerseBackend, plt::Plot, d::KW)
|
||||
# function _series_added(::ImmerseBackend, plt::Plot, d::KW)
|
||||
# addGadflySeries!(plt, d)
|
||||
# push!(plt.seriesargs, d)
|
||||
# plt
|
||||
# end
|
||||
|
||||
function _add_series(plt::Plot{ImmerseBackend}, series::Series)
|
||||
function _series_added(plt::Plot{ImmerseBackend}, series::Series)
|
||||
addGadflySeries!(plt, series.d)
|
||||
end
|
||||
|
||||
|
||||
@ -238,7 +238,7 @@ end
|
||||
# end
|
||||
|
||||
|
||||
# function _add_series(::PGFPlotsBackend, plt::Plot, d::KW)
|
||||
# function _series_added(::PGFPlotsBackend, plt::Plot, d::KW)
|
||||
# # TODO: add one series to the underlying package
|
||||
# push!(plt.seriesargs, d)
|
||||
# plt
|
||||
|
||||
@ -91,7 +91,7 @@ end
|
||||
# end
|
||||
|
||||
|
||||
# function _add_series(::PlotlyBackend, plt::Plot, d::KW)
|
||||
# function _series_added(::PlotlyBackend, plt::Plot, d::KW)
|
||||
# # TODO: add one series to the underlying package
|
||||
# push!(plt.seriesargs, d)
|
||||
# plt
|
||||
|
||||
@ -113,7 +113,7 @@ function _create_backend_figure(plt::Plot{PlotlyJSBackend})
|
||||
end
|
||||
|
||||
|
||||
function _add_series(plt::Plot{PlotlyJSBackend}, series::Series)
|
||||
function _series_added(plt::Plot{PlotlyJSBackend}, series::Series)
|
||||
d = series.d
|
||||
syncplot = plt.o
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -137,8 +137,8 @@ function _create_backend_figure(plt::Plot{QwtBackend})
|
||||
# plt
|
||||
end
|
||||
|
||||
# function _add_series(::QwtBackend, plt::Plot, d::KW)
|
||||
function _add_series(plt::Plot{QwtBackend}, series::Series)
|
||||
# function _series_added(::QwtBackend, plt::Plot, d::KW)
|
||||
function _series_added(plt::Plot{QwtBackend}, series::Series)
|
||||
d = adjustQwtKeywords(plt, false; series.d...)
|
||||
fixcolors(d)
|
||||
dumpdict(d,"\n\n!!! plot!")
|
||||
|
||||
@ -1,84 +1,74 @@
|
||||
|
||||
# TODO: find/replace all [PkgName] with CamelCase, all [pkgname] with lowercase
|
||||
# TODO: find/replace all [PkgName] with CamelCase
|
||||
|
||||
# [WEBSITE]
|
||||
# [ADD BACKEND WEBSITE]
|
||||
|
||||
function _initialize_backend(::[PkgName]AbstractBackend; kw...)
|
||||
@eval begin
|
||||
import [PkgName]
|
||||
export [PkgName]
|
||||
# TODO: other initialization that needs to be eval-ed
|
||||
end
|
||||
# TODO: other initialization
|
||||
@eval begin
|
||||
import [PkgName]
|
||||
export [PkgName]
|
||||
# todo: other initialization that needs to be eval-ed
|
||||
end
|
||||
# todo: other initialization
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Create the window/figure for this backend.
|
||||
function _create_backend_figure(plt::Plot{[PkgName]Backend})
|
||||
# TODO: create the window/figure for this backend
|
||||
nothing
|
||||
end
|
||||
|
||||
|
||||
function _add_series(plt::Plot{[PkgName]Backend}, series::Series)
|
||||
# TODO: add one series to the underlying package
|
||||
# Set up the subplot within the backend object.
|
||||
function _initialize_subplot(plt::Plot{PyPlotBackend}, sp::Subplot{PyPlotBackend})
|
||||
end
|
||||
|
||||
# function _add_annotations{X,Y,V}(plt::Plot{[PkgName]AbstractBackend}, anns::AVec{@compat(Tuple{X,Y,V})})
|
||||
# for ann in anns
|
||||
# # TODO: add the annotation to the plot
|
||||
# end
|
||||
# end
|
||||
# Set the (left, top, right, bottom) minimum padding around the plot area
|
||||
# to fit ticks, tick labels, guides, colorbars, etc.
|
||||
function _update_min_padding!(sp::Subplot{[PkgName]Backend})
|
||||
sp.minpad = (20mm, 5mm, 2mm, 10mm)
|
||||
end
|
||||
|
||||
# Use the bounding boxes (and methods left/top/right/bottom/width/height) `sp.bbox` and `sp.plotarea` to
|
||||
# position the subplot in the backend.
|
||||
function _update_position!(sp::Subplot{[PkgName]Backend})
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
function _before_update_plot(plt::Plot{[PkgName]AbstractBackend})
|
||||
# This is called before series processing... use it if you need to make the backend object current or something.
|
||||
function _before_update(plt::Plot{[PkgName]AbstractBackend})
|
||||
end
|
||||
|
||||
# TODO: override this to update plot items (title, xlabel, etc) after creation
|
||||
|
||||
# Add one series to the underlying backend object.
|
||||
function _series_added(plt::Plot{[PkgName]Backend}, series::Series)
|
||||
end
|
||||
|
||||
|
||||
# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations])
|
||||
function _update_plot(plt::Plot{[PkgName]AbstractBackend}, d::KW)
|
||||
end
|
||||
|
||||
function _update_plot_pos_size(plt::AbstractPlot{[PkgName]AbstractBackend}, d::KW)
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# When series data is added/changed, this callback can do dynamic updates to the backend object.
|
||||
# note: if the backend rebuilds the plot from scratch on display, then you might not do anything here.
|
||||
function _series_updated(plt::Plot{[PkgName]AbstractBackend}, series::Series)
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# accessors for x/y data
|
||||
|
||||
# function getxy(plt::Plot{[PkgName]AbstractBackend}, i::Int)
|
||||
# # TODO: return a tuple of (x, y) vectors
|
||||
# end
|
||||
#
|
||||
# function setxy!{X,Y}(plt::Plot{[PkgName]AbstractBackend}, xy::Tuple{X,Y}, i::Integer)
|
||||
# # TODO: set the plot data from the (x,y) tuple
|
||||
# plt
|
||||
# end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# function _create_subplot(subplt::Subplot{[PkgName]AbstractBackend}, isbefore::Bool)
|
||||
# # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
|
||||
# end
|
||||
|
||||
# function _expand_limits(lims, plt::Plot{[PkgName]AbstractBackend}, isx::Bool)
|
||||
# # TODO: call expand limits for each plot data
|
||||
# end
|
||||
#
|
||||
# function _remove_axis(plt::Plot{[PkgName]AbstractBackend}, isx::Bool)
|
||||
# # TODO: if plot is inner subplot, might need to remove ticks or axis labels
|
||||
# end
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
|
||||
# Write a png to io. You could define methods for:
|
||||
# "application/eps" => "eps",
|
||||
# "image/eps" => "eps",
|
||||
# "application/pdf" => "pdf",
|
||||
# "image/png" => "png",
|
||||
# "application/postscript" => "ps",
|
||||
# "image/svg+xml" => "svg"
|
||||
function Base.writemime(io::IO, ::MIME"image/png", plt::AbstractPlot{[PkgName]AbstractBackend})
|
||||
# TODO: write a png to io
|
||||
end
|
||||
|
||||
# Display/show the plot (open a GUI window, or browser page, for example).
|
||||
function Base.display(::PlotsDisplay, plt::Plot{[PkgName]AbstractBackend})
|
||||
# TODO: display/show the plot
|
||||
end
|
||||
|
||||
# function Base.display(::PlotsDisplay, plt::Subplot{[PkgName]AbstractBackend})
|
||||
# # TODO: display/show the subplot
|
||||
# end
|
||||
|
||||
@ -195,7 +195,7 @@ function _create_backend_figure(plt::Plot{UnicodePlotsBackend})
|
||||
# plt
|
||||
end
|
||||
|
||||
function _add_series(plt::Plot{UnicodePlotsBackend}, series::Series)
|
||||
function _series_added(plt::Plot{UnicodePlotsBackend}, series::Series)
|
||||
d = series.d
|
||||
# TODO don't need these once the "bar" series recipe is done
|
||||
if d[:seriestype] in (:sticks, :bar)
|
||||
|
||||
@ -96,7 +96,7 @@ end
|
||||
:star5 => "asterisk"
|
||||
)
|
||||
|
||||
function _before_add_series(plt::Plot{WinstonBackend})
|
||||
function _before_update(plt::Plot{WinstonBackend})
|
||||
Winston.ghf(plt.o)
|
||||
end
|
||||
|
||||
@ -127,7 +127,7 @@ function getWinstonItems(plt::Plot)
|
||||
window, canvas, wplt
|
||||
end
|
||||
|
||||
function _add_series(plt::Plot{WinstonBackend}, series::Series)
|
||||
function _series_added(plt::Plot{WinstonBackend}, series::Series)
|
||||
d = series.d
|
||||
window, canvas, wplt = getWinstonItems(plt)
|
||||
|
||||
|
||||
@ -5,6 +5,8 @@
|
||||
const px = AbsoluteLength(0.254)
|
||||
const pct = Length{:pct, Float64}(1.0)
|
||||
|
||||
const _cbar_width = 5mm
|
||||
|
||||
Base.(:.*)(m::Measure, n::Number) = m * n
|
||||
Base.(:.*)(n::Number, m::Measure) = m * n
|
||||
Base.(:-)(m::Measure, a::AbstractArray) = map(ai -> m - ai, a)
|
||||
@ -65,6 +67,15 @@ function crop(parent::BoundingBox, child::BoundingBox)
|
||||
BoundingBox(l, t, w, h)
|
||||
end
|
||||
|
||||
# convert a bounding box from absolute coords to percentages... returns an array of percentages of figure size: [left, bottom, width, height]
|
||||
function bbox_to_pcts(bb::BoundingBox, figw, figh, flipy = true)
|
||||
mms = Float64[f(bb).value for f in (left,bottom,width,height)]
|
||||
if flipy
|
||||
mms[2] = figh.value - mms[2] # flip y when origin in bottom-left
|
||||
end
|
||||
mms ./ Float64[figw.value, figh.value, figw.value, figh.value]
|
||||
end
|
||||
|
||||
function Base.show(io::IO, bbox::BoundingBox)
|
||||
print(io, "BBox{l,t,r,b,w,h = $(left(bbox)),$(top(bbox)), $(right(bbox)),$(bottom(bbox)), $(width(bbox)),$(height(bbox))}")
|
||||
end
|
||||
@ -93,7 +104,7 @@ padding_w(layout::AbstractLayout) = left_padding(layout) + right_padding(layout)
|
||||
padding_h(layout::AbstractLayout) = bottom_padding(layout) + top_padding(layout)
|
||||
padding(layout::AbstractLayout) = (padding_w(layout), padding_h(layout))
|
||||
|
||||
update_position!(layout::AbstractLayout) = nothing
|
||||
_update_position!(layout::AbstractLayout) = nothing
|
||||
update_child_bboxes!(layout::AbstractLayout) = nothing
|
||||
|
||||
width(layout::AbstractLayout) = width(layout.bbox)
|
||||
@ -105,6 +116,11 @@ attr(layout::AbstractLayout, k::Symbol, v) = get(layout.attr, k, v)
|
||||
attr!(layout::AbstractLayout, v, k::Symbol) = (layout.attr[k] = v)
|
||||
hasattr(layout::AbstractLayout, k::Symbol) = haskey(layout.attr, k)
|
||||
|
||||
leftpad(layout::AbstractLayout) = 0mm
|
||||
toppad(layout::AbstractLayout) = 0mm
|
||||
rightpad(layout::AbstractLayout) = 0mm
|
||||
bottompad(layout::AbstractLayout) = 0mm
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# RootLayout
|
||||
|
||||
@ -138,6 +154,7 @@ Base.getindex(layout::EmptyLayout, r::Int, c::Int) = nothing
|
||||
# nested, gridded layout with optional size percentages
|
||||
type GridLayout <: AbstractLayout
|
||||
parent::AbstractLayout
|
||||
minpad::Tuple # leftpad, toppad, rightpad, bottompad
|
||||
bbox::BoundingBox
|
||||
grid::Matrix{AbstractLayout} # Nested layouts. Each position is a AbstractLayout, which allows for arbitrary recursion
|
||||
widths::Vector{Measure}
|
||||
@ -155,6 +172,7 @@ function GridLayout(dims...;
|
||||
grid = Matrix{AbstractLayout}(dims...)
|
||||
layout = GridLayout(
|
||||
parent,
|
||||
(20mm, 5mm, 2mm, 10mm),
|
||||
defaultbox,
|
||||
grid,
|
||||
Measure[w*pct for w in widths],
|
||||
@ -173,13 +191,39 @@ function Base.setindex!(layout::GridLayout, v, r::Int, c::Int)
|
||||
layout.grid[r,c] = v
|
||||
end
|
||||
|
||||
min_padding_left(layout::GridLayout) = maximum(map(min_padding_left, layout.grid[:,1]))
|
||||
min_padding_top(layout::GridLayout) = maximum(map(min_padding_top, layout.grid[1,:]))
|
||||
min_padding_right(layout::GridLayout) = maximum(map(min_padding_right, layout.grid[:,end]))
|
||||
min_padding_bottom(layout::GridLayout) = maximum(map(min_padding_bottom, layout.grid[end,:]))
|
||||
leftpad(layout::GridLayout) = layout.minpad[1]
|
||||
toppad(layout::GridLayout) = layout.minpad[2]
|
||||
rightpad(layout::GridLayout) = layout.minpad[3]
|
||||
bottompad(layout::GridLayout) = layout.minpad[4]
|
||||
|
||||
# min_padding_left(layout::GridLayout) = maximum(map(min_padding_left, layout.grid[:,1]))
|
||||
# min_padding_top(layout::GridLayout) = maximum(map(min_padding_top, layout.grid[1,:]))
|
||||
# min_padding_right(layout::GridLayout) = maximum(map(min_padding_right, layout.grid[:,end]))
|
||||
# min_padding_bottom(layout::GridLayout) = maximum(map(min_padding_bottom, layout.grid[end,:]))
|
||||
|
||||
|
||||
update_position!(layout::GridLayout) = map(update_position!, layout.grid)
|
||||
# leftpad, toppad, rightpad, bottompad
|
||||
function _update_min_padding!(layout::GridLayout)
|
||||
# minpad_matrix = map(_update_min_padding!, layout.grid)
|
||||
# nr,nc = size(layout)
|
||||
# leftpad = maximum([minpad_matrix[r,1][1] for r=1:nr])
|
||||
# toppad = maximum([minpad_matrix[1,c][2] for c=1:nc])
|
||||
# rightpad = maximum([minpad_matrix[r,end][3] for r=1:nr])
|
||||
# bottompad = maximum([minpad_matrix[end,c][4] for c=1:nc])
|
||||
map(_update_min_padding!, layout.grid)
|
||||
layout.minpad = (
|
||||
maximum(map(leftpad, layout.grid[:,1])),
|
||||
maximum(map(toppad, layout.grid[1,:])),
|
||||
maximum(map(rightpad, layout.grid[:,end])),
|
||||
maximum(map(bottompad, layout.grid[end,:]))
|
||||
)
|
||||
# layout.minpad = (leftpad, toppad, rightpad, bottompad)
|
||||
end
|
||||
|
||||
|
||||
function _update_position!(layout::GridLayout)
|
||||
map(_update_position!, layout.grid)
|
||||
end
|
||||
|
||||
|
||||
# recursively compute the bounding boxes for the layout and plotarea (relative to canvas!)
|
||||
@ -187,10 +231,16 @@ function update_child_bboxes!(layout::GridLayout)
|
||||
nr, nc = size(layout)
|
||||
|
||||
# create a matrix for each minimum padding direction
|
||||
minpad_left = map(min_padding_left, layout.grid)
|
||||
minpad_top = map(min_padding_top, layout.grid)
|
||||
minpad_right = map(min_padding_right, layout.grid)
|
||||
minpad_bottom = map(min_padding_bottom, layout.grid)
|
||||
_update_min_padding!(layout)
|
||||
# minpad_left = map(l -> l.minpad[1], layout.grid)
|
||||
# minpad_left = map(min_padding_left, layout.grid)
|
||||
# minpad_top = map(min_padding_top, layout.grid)
|
||||
# minpad_right = map(min_padding_right, layout.grid)
|
||||
# minpad_bottom = map(min_padding_bottom, layout.grid)
|
||||
minpad_left = map(leftpad, layout.grid)
|
||||
minpad_top = map(toppad, layout.grid)
|
||||
minpad_right = map(rightpad, layout.grid)
|
||||
minpad_bottom = map(bottompad, layout.grid)
|
||||
# @show minpad_left minpad_top minpad_right minpad_bottom
|
||||
|
||||
# get the max horizontal (left and right) padding over columns,
|
||||
|
||||
168
src/plot.jl
168
src/plot.jl
@ -94,9 +94,7 @@ end
|
||||
# natively by the backend
|
||||
function _apply_series_recipe(plt::Plot, d::KW)
|
||||
st = d[:seriestype]
|
||||
# dumpdict(d, "apply_series_recipe", true)
|
||||
if st in supportedTypes()
|
||||
# println("adding series!!")
|
||||
|
||||
# getting ready to add the series... last update to subplot from anything
|
||||
# that might have been added during series recipes
|
||||
@ -134,7 +132,7 @@ function _apply_series_recipe(plt::Plot, d::KW)
|
||||
warnOnUnsupported(plt.backend, d)
|
||||
series = Series(d)
|
||||
push!(plt.series_list, series)
|
||||
_add_series(plt, series)
|
||||
_series_added(plt, series)
|
||||
|
||||
else
|
||||
# get a sub list of series for this seriestype
|
||||
@ -158,7 +156,7 @@ end
|
||||
# note: at entry, we only have those preprocessed args which were passed in... no default values yet
|
||||
function _plot!(plt::Plot, d::KW, args...)
|
||||
# just in case the backend needs to set up the plot (make it current or something)
|
||||
_before_add_series(plt)
|
||||
_before_update(plt)
|
||||
|
||||
# first apply any args for the subplots
|
||||
for (idx,sp) in enumerate(plt.subplots)
|
||||
@ -172,15 +170,6 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
args = tuple(extractGroupArgs(d[:group], args...), args...)
|
||||
end
|
||||
|
||||
# # initialize the annotations list with what was passed in
|
||||
# # TODO: there must be cleaner way to handle this!
|
||||
# anns = annotations(get(d, :annotation, NTuple{3}[]))
|
||||
# if typeof(anns) <: AVec{PlotText}
|
||||
# anns = NTuple{3}[]
|
||||
# else
|
||||
# delete!(d, :annotation)
|
||||
# end
|
||||
|
||||
|
||||
# for plotting recipes, swap out the args and update the parameter dictionary
|
||||
# we are keeping a queue of series that still need to be processed.
|
||||
@ -212,7 +201,6 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
|
||||
# if there was a grouping, filter the data here
|
||||
_filter_input_data!(kw)
|
||||
# @show typeof((kw[:x], kw[:y], kw[:z]))
|
||||
|
||||
# map marker_z if it's a Function
|
||||
if isa(get(kw, :marker_z, nothing), Function)
|
||||
@ -250,38 +238,9 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
|
||||
# !!! note: at this point, kw_list is fully decomposed into individual series... one KW per series !!!
|
||||
|
||||
# # TODO: move annotations into subplot update
|
||||
# # now include any annotations which were added during recipes
|
||||
# for kw in kw_list
|
||||
# append!(anns, annotations(pop!(kw, :annotation, [])))
|
||||
# end
|
||||
# # @show anns
|
||||
|
||||
|
||||
# for kw in kw_list
|
||||
# @show typeof((kw[:x], kw[:y], kw[:z]))
|
||||
# end
|
||||
|
||||
# # merge plot args... this is where we combine all the plot args from the user and
|
||||
# # from the recipes... axis info, colors, etc
|
||||
# # TODO: why do i need to check for the subplot key?
|
||||
# # if !haskey(d, :subplot)
|
||||
# # for kw in vcat(kw_list, d)
|
||||
# for kw in kw_list
|
||||
# _update_subplot_args(plt, kw[:subplot], kw)
|
||||
# # _add_plotargs!(plt, kw)
|
||||
# end
|
||||
# # handlePlotColors(plt.backend, plt.plotargs)
|
||||
# # end
|
||||
|
||||
# for kw in kw_list
|
||||
# @show typeof((kw[:x], kw[:y], kw[:z]))
|
||||
# end
|
||||
|
||||
# this is it folks!
|
||||
# TODO: we probably shouldn't use i for tracking series index, but rather explicitly track it in recipes
|
||||
for (i,kw) in enumerate(kw_list)
|
||||
# DD(kw, "series $i before")
|
||||
if !(get(kw, :seriestype, :none) in (:xerror, :yerror))
|
||||
plt.n += 1
|
||||
end
|
||||
@ -309,16 +268,10 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
sp.attr[:annotations] = vcat(sp_anns, anns)
|
||||
|
||||
# we update subplot args in case something like the color palatte is part of the recipe
|
||||
# DD(sp.attr[:xaxis].d, "before USA $i")
|
||||
# DD(kw, "kw")
|
||||
_update_subplot_args(plt, sp, kw, idx)
|
||||
# DD(sp.attr[:xaxis].d, "after USA $i")
|
||||
|
||||
# set default values, select from attribute cycles, and generally set the final attributes
|
||||
_add_defaults!(kw, plt, sp, i)
|
||||
# DD(kw, "series $i after")
|
||||
|
||||
#
|
||||
|
||||
# now we have a fully specified series, with colors chosen. we must recursively handle
|
||||
# series recipes, which dispatch on seriestype. If a backend does not natively support a seriestype,
|
||||
@ -326,14 +279,9 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
# For example, a histogram is just a bar plot with binned data, a bar plot is really a filled step plot,
|
||||
# and a step plot is really just a path. So any backend that supports drawing a path will implicitly
|
||||
# be able to support step, bar, and histogram plots (and any recipes that use those components).
|
||||
# DD(sp.attr[:xaxis].d, "before $i")
|
||||
_apply_series_recipe(plt, kw)
|
||||
# DD(sp.attr[:xaxis].d, "after $i")
|
||||
end
|
||||
|
||||
# # now that we're done adding all the series, add the annotations
|
||||
# _add_annotations(plt, anns)
|
||||
|
||||
# TODO just need to pass plt... and we should do all non-series updates here
|
||||
_update_plot(plt, plt.plotargs)
|
||||
|
||||
@ -348,18 +296,6 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
plt
|
||||
end
|
||||
|
||||
# # handle the grouping
|
||||
# function _add_series(plt::Plot, d::KW, groupby::GroupBy, args...)
|
||||
# starting_n = plt.n
|
||||
# for (i, glab) in enumerate(groupby.groupLabels)
|
||||
# tmpd = copy(d)
|
||||
# tmpd[:numUncounted] = plt.n - starting_n
|
||||
# _add_series(plt, tmpd, nothing, args...;
|
||||
# idxfilter = groupby.groupIds[i],
|
||||
# grouplabel = string(glab))
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
function _replace_linewidth(d::KW)
|
||||
# get a good default linewidth... 0 for surface and heatmaps
|
||||
@ -368,63 +304,6 @@ function _replace_linewidth(d::KW)
|
||||
end
|
||||
end
|
||||
|
||||
# # no grouping
|
||||
# function _add_series(plt::Plot, d::KW, args...;
|
||||
# idxfilter = nothing,
|
||||
# grouplabel = "")
|
||||
#
|
||||
# # get the list of dictionaries, one per series
|
||||
# dumpdict(d, "before process_inputs")
|
||||
# process_inputs(plt, d, args...)
|
||||
# dumpdict(d, "after process_inputs")
|
||||
#
|
||||
# if idxfilter != nothing
|
||||
# # add the group name as the label if there isn't one passed in
|
||||
# get!(d, :label, grouplabel)
|
||||
# # filter the data
|
||||
# filter_data!(d, idxfilter)
|
||||
# end
|
||||
# # dumpdict(d,"",true)
|
||||
#
|
||||
# seriesArgList, xmeta, ymeta = build_series_args(plt, d) #, idxfilter)
|
||||
# # seriesArgList, xmeta, ymeta = build_series_args(plt, groupargs..., args...; d...)
|
||||
#
|
||||
# # # if we were able to extract guide information from the series inputs, then update the plot
|
||||
# # # @show xmeta, ymeta
|
||||
# # updateDictWithMeta(d, plt.plotargs, xmeta, true)
|
||||
# # updateDictWithMeta(d, plt.plotargs, ymeta, false)
|
||||
#
|
||||
#
|
||||
# # function _add_series(plt::Plot, ds::)
|
||||
# # now we can plot the series
|
||||
# for (i,di) in enumerate(seriesArgList)
|
||||
# plt.n += 1
|
||||
#
|
||||
# if !stringsSupported() && di[:seriestype] != :pie
|
||||
# setTicksFromStringVector(plt, d, di, "x")
|
||||
# setTicksFromStringVector(plt, d, di, "y")
|
||||
# setTicksFromStringVector(plt, d, di, "z")
|
||||
# end
|
||||
#
|
||||
# # remove plot args
|
||||
# for k in keys(_plot_defaults)
|
||||
# delete!(di, k)
|
||||
# end
|
||||
#
|
||||
# # merge in plotarg_overrides
|
||||
# plotarg_overrides = pop!(di, :plotarg_overrides, nothing)
|
||||
# if plotarg_overrides != nothing
|
||||
# merge!(plt.plotargs, plotarg_overrides)
|
||||
# end
|
||||
# # dumpdict(plt.plotargs, "pargs", true)
|
||||
#
|
||||
# dumpdict(di, "Series $i")
|
||||
#
|
||||
# _replace_linewidth(di)
|
||||
#
|
||||
# _add_series(plt.backend, plt, di)
|
||||
# end
|
||||
# end
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
@ -482,54 +361,11 @@ end
|
||||
# end
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# TODO: remove
|
||||
# # should we update the x/y label given the meta info during input slicing?
|
||||
# function updateDictWithMeta(d::KW, plotargs::KW, meta::Symbol, isx::Bool)
|
||||
# lsym = isx ? :xguide : :yguide
|
||||
# if plotargs[lsym] == default(lsym)
|
||||
# d[lsym] = string(meta)
|
||||
# end
|
||||
# end
|
||||
# updateDictWithMeta(d::KW, plotargs::KW, meta, isx::Bool) = nothing
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
annotations(::Void) = []
|
||||
annotations(anns::AVec) = anns
|
||||
annotations(anns) = Any[anns]
|
||||
# annotations{X,Y,V}(v::AVec{@compat(Tuple{X,Y,V})}) = v
|
||||
# annotations{X,Y,V}(t::@compat(Tuple{X,Y,V})) = [t]
|
||||
# annotations(v::AVec{PlotText}) = v
|
||||
# annotations(v::AVec) = map(PlotText, v)
|
||||
# annotations(anns) = error("Expecting a tuple (or vector of tuples) for annotations: ",
|
||||
# "(x, y, annotation)\n got: $(typeof(anns))")
|
||||
|
||||
# function annotations(plt::Plot, anns)
|
||||
# anns = annotations(anns)
|
||||
# # if we just have a list of PlotText objects, then create (x,y,text) tuples
|
||||
# if typeof(anns) <: AVec{PlotText}
|
||||
# x, y = plt[plt.n]
|
||||
# anns = Tuple{Float64,Float64,PlotText}[(x[i], y[i], t) for (i,t) in enumerate(anns)]
|
||||
# end
|
||||
# anns
|
||||
# end
|
||||
|
||||
|
||||
# function _add_annotations(plt::Plot, d::KW)
|
||||
# anns = annotations(get(d, :annotation, nothing))
|
||||
# if !isempty(anns)
|
||||
#
|
||||
# # if we just have a list of PlotText objects, then create (x,y,text) tuples
|
||||
# if typeof(anns) <: AVec{PlotText}
|
||||
# x, y = plt[plt.n]
|
||||
# anns = Tuple{Float64,Float64,PlotText}[(x[i], y[i], t) for (i,t) in enumerate(anns)]
|
||||
# end
|
||||
#
|
||||
# _add_annotations(plt, anns)
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
@ -1,7 +1,15 @@
|
||||
|
||||
|
||||
function Subplot{T<:AbstractBackend}(::T; parent = RootLayout())
|
||||
Subplot{T}(parent, defaultbox, defaultbox, KW(), nothing, nothing)
|
||||
Subplot{T}(
|
||||
parent,
|
||||
(20mm, 5mm, 2mm, 10mm),
|
||||
defaultbox,
|
||||
defaultbox,
|
||||
KW(),
|
||||
nothing,
|
||||
nothing
|
||||
)
|
||||
end
|
||||
|
||||
plotarea!(sp::Subplot, bbox::BoundingBox) = (sp.plotarea = bbox)
|
||||
@ -11,6 +19,10 @@ Base.size(sp::Subplot) = (1,1)
|
||||
Base.length(sp::Subplot) = 1
|
||||
Base.getindex(sp::Subplot, r::Int, c::Int) = sp
|
||||
|
||||
leftpad(sp::Subplot) = sp.minpad[1]
|
||||
toppad(sp::Subplot) = sp.minpad[2]
|
||||
rightpad(sp::Subplot) = sp.minpad[3]
|
||||
bottompad(sp::Subplot) = sp.minpad[4]
|
||||
|
||||
get_subplot(plt::Plot, sp::Subplot) = sp
|
||||
get_subplot(plt::Plot, i::Integer) = plt.subplots[i]
|
||||
|
||||
@ -32,6 +32,7 @@ end
|
||||
# a single subplot
|
||||
type Subplot{T<:AbstractBackend} <: AbstractLayout
|
||||
parent::AbstractLayout
|
||||
minpad::Tuple # leftpad, toppad, rightpad, bottompad
|
||||
bbox::BoundingBox # the canvas area which is available to this subplot
|
||||
plotarea::BoundingBox # the part where the data goes
|
||||
attr::KW # args specific to this subplot
|
||||
|
||||
40
src/utils.jl
40
src/utils.jl
@ -481,14 +481,44 @@ function getxyz(plt::Plot, i::Integer)
|
||||
end
|
||||
|
||||
function setxy!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer)
|
||||
d = plt.series_list[i].d
|
||||
d[:x], d[:y] = xy
|
||||
series = plt.series_list[i]
|
||||
series.d[:x], series.d[:y] = xy
|
||||
_series_updated(plt, series)
|
||||
end
|
||||
function setxyz!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer)
|
||||
d = plt.series_list[i].d
|
||||
d[:x], d[:y], d[:z] = xyz
|
||||
series = plt.series_list[i]
|
||||
series.d[:x], series.d[:y], series.d[:z] = xyz
|
||||
_series_updated(plt, series)
|
||||
end
|
||||
|
||||
#
|
||||
#
|
||||
# function setxy!{X,Y}(plt::Plot{PyPlotBackend}, xy::Tuple{X,Y}, i::Integer)
|
||||
# series = plt.series_list[i]
|
||||
# d = series.d
|
||||
# d[:x], d[:y] = xy
|
||||
# for handle in d[:serieshandle]
|
||||
# try
|
||||
# handle[:set_data](xy...)
|
||||
# catch
|
||||
# handle[:set_offsets](hcat(xy...))
|
||||
# end
|
||||
# end
|
||||
# update_limits!(d[:subplot], series, (:x,:y))
|
||||
# plt
|
||||
# end
|
||||
#
|
||||
#
|
||||
# function setxyz!{X,Y,Z}(plt::Plot{PyPlotBackend}, xyz::Tuple{X,Y,Z}, i::Integer)
|
||||
# series = plt.series_list[i]
|
||||
# d = series.d
|
||||
# d[:x], d[:y], d[:z] = xyz
|
||||
# for handle in d[:serieshandle]
|
||||
# handle[:set_data](d[:x], d[:y])
|
||||
# handle[:set_3d_properties](d[:z])
|
||||
# end
|
||||
# update_limits!(d[:subplot], series, (:x,:y,:z))
|
||||
# plt
|
||||
# end
|
||||
|
||||
# -------------------------------------------------------
|
||||
# indexing notation
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user