working on display/writemime overhaul

This commit is contained in:
Thomas Breloff 2015-09-22 12:54:55 -04:00
parent f8fb473981
commit eced15b712
10 changed files with 144 additions and 63 deletions

View File

@ -36,6 +36,10 @@ export
ohlc,
ohlc!,
title!,
xlabel!,
ylabel!,
savepng,
backends,
@ -86,12 +90,35 @@ ohlc(args...; kw...) = plot(args...; kw..., linetype = :ohlc)
ohlc!(args...; kw...) = plot!(args...; kw..., linetype = :ohlc)
title!(s::AbstractString) = plot!(title = s)
xlabel!(s::AbstractString) = plot!(xlabel = s)
ylabel!(s::AbstractString) = plot!(ylabel = s)
title!(plt::Plot, s::AbstractString) = plot!(plt; title = s)
xlabel!(plt::Plot, s::AbstractString) = plot!(plt; xlabel = s)
ylabel!(plt::Plot, s::AbstractString) = plot!(plt; ylabel = s)
# ---------------------------------------------------------
savepng(args...; kw...) = savepng(currentPlot(), args...; kw...)
savepng(plt::PlottingObject, args...; kw...) = savepng(plt.plotter, plt, args...; kw...)
savepng(::PlottingPackage, plt::PlottingObject, fn::AbstractString, args...) = error("unsupported") # fallback so multiple dispatch doesn't get confused if it's missing
savepng(plt::PlottingObject, fn::AbstractString; kw...) = (io = open(fn); writemime(io, MIME"image/png", plt); close(io))
# savepng(plt::PlottingObject, args...; kw...) = savepng(plt.plotter, plt, args...; kw...)
# savepng(::PlottingPackage, plt::PlottingObject, fn::AbstractString, args...) = error("unsupported") # fallback so multiple dispatch doesn't get confused if it's missing
# function Base.writemime(io::IO, ::MIME"image/png", plt::Plot)
# function Base.writemime(io::IO, ::MIME"text/html", plt::Plot)
# # print(io, "<p>")
# png = MIME("image/png")
# print(io, "<img src=\"data:image/png; base64,", base64encode(writemime, png), "\" />")
# end
# override the REPL display
Base.display(::Base.REPL.REPLDisplay, ::MIME"text/plain", plt::PlottingObject) = display(PlotsDisplay(), plt)
function __init__()

View File

@ -210,24 +210,52 @@ function plot!(::GadflyPackage, plt::Plot; kw...)
plt
end
function findGuideAndSet(plt::Plot, t::DataType, s::AbstractString)
for guide in plt.o.guides
if isa(guide, t)
guide.label = s
end
end
end
function updatePlotItems(::GadflyPackage, plt::Plot, d::Dict)
haskey(d, :title) && findGuideAndSet(plt, Gadfly.Guide.title, d[:title])
haskey(d, :xlabel) && findGuideAndSet(plt, Gadfly.Guide.xlabel, d[:xlabel])
haskey(d, :ylabel) && findGuideAndSet(plt, Gadfly.Guide.ylabel, d[:ylabel])
end
function setGadflyDisplaySize(w,h)
Compose.set_default_graphic_size(w * Compose.px, h * Compose.px)
end
function Base.display(::GadflyPackage, plt::Plot)
# function Base.display(::GadflyPackage, plt::Plot)
# # function Base.writemime(io::IO, ::MIME")
# setGadflyDisplaySize(plt.initargs[:size]...)
# display(plt.o)
# end
function Base.display(::PlotsDisplay, plt::Plot{GadflyPackage})
setGadflyDisplaySize(plt.initargs[:size]...)
display(plt.o)
end
# -------------------------------
function savepng(::GadflyPackage, plt::PlottingObject, fn::AbstractString;
w = plt.initargs[:size][1] * Gadfly.px, # 6 * Gadfly.inch,
h = plt.initargs[:size][2] * Gadfly.px) # 4 * Gadfly.inch)
o = getGadflyContext(plt.plotter, plt)
Gadfly.draw(Gadfly.PNG(fn, w, h), o)
end
# function savepng(::GadflyPackage, plt::PlottingObject, fn::AbstractString;
# w = plt.initargs[:size][1] * Gadfly.px, # 6 * Gadfly.inch,
# h = plt.initargs[:size][2] * Gadfly.px) # 4 * Gadfly.inch)
# o = getGadflyContext(plt.plotter, plt)
# Gadfly.draw(Gadfly.PNG(fn, w, h), o)
# end
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{GadflyPackage})
# w = plt.initargs[:size][1] * Gadfly.px, # 6 * Gadfly.inch,
# h = plt.initargs[:size][2] * Gadfly.px) # 4 * Gadfly.inch)
gplt = getGadflyContext(plt.plotter, plt)
setGadflyDisplaySize(plt.initargs[:size]...)
Gadfly.draw(Gadfly.PNG(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt)
end
# -------------------------------
@ -246,12 +274,12 @@ function buildGadflySubplotContext(subplt::Subplot)
end
# create the underlying object (each backend will do this differently)
function buildSubplotObject!(::GadflyPackage, subplt::Subplot)
function buildSubplotObject!(subplt::Subplot{GadflyPackage})
subplt.o = nothing
end
function Base.display(::GadflyPackage, subplt::Subplot)
function Base.display(::PlotsDisplay, subplt::Subplot{GadflyPackage})
setGadflyDisplaySize(plt.initargs[:size]...)
display(buildGadflySubplotContext(subplt))
end

View File

@ -75,7 +75,7 @@ end
# -------------------------------
function buildSubplotObject!(::ImmersePackage, subplt::Subplot)
function buildSubplotObject!(subplt::Subplot{ImmersePackage})
# create the Gtk window with vertical box vsep
d = subplt.initargs[1]
@ -120,12 +120,6 @@ function buildSubplotObject!(::ImmersePackage, subplt::Subplot)
end
# # create the underlying object
# function buildSubplotObject!(::ImmersePackage, subplt::Subplot)
# subplt.o = (nothing, nothing)
# end
function Base.display(::ImmersePackage, subplt::Subplot)
# display the plots by creating a fresh Immerse.Figure object from the GtkCanvas and Gadfly.Plot

View File

@ -94,8 +94,7 @@ function getPyPlotFunction(plt::Plot, axis::Symbol, linetype::Symbol)
# return linetype == :hist ? PyPlot.plt[:hist] : (linetype in (:sticks,:bar) ? PyPlot.bar : (linetype in (:heatmap,:hexbin) ? PyPlot.hexbin : PyPlot.plot))
end
function updateAxisColors(o, fgcolor)
ax = o[:axes][1]
function updateAxisColors(ax, fgcolor)
for loc in ("bottom", "top", "left", "right")
ax[:spines][loc][:set_color](fgcolor)
end
@ -108,6 +107,8 @@ function updateAxisColors(o, fgcolor)
ax[:title][:set_color](fgcolor)
end
makePlotCurrent(plt::Plot) = PyPlot.figure(plt.o[1].o[:number])
# ------------------------------------------------------------------
# TODO:
@ -125,13 +126,10 @@ function plot(pkg::PyPlotPackage; kw...)
d = Dict(kw)
w,h = map(px2inch, d[:size])
bgcolor = getPyPlotColor(d[:background_color])
o = PyPlot.figure(; figsize = (w,h), facecolor = bgcolor, dpi = 96)
fig = PyPlot.figure(; figsize = (w,h), facecolor = bgcolor, dpi = 96)
PyPlot.title(d[:title])
PyPlot.xlabel(d[:xlabel])
PyPlot.ylabel(d[:ylabel])
plt = Plot(o, pkg, 0, d, Dict[])
num = fig.o[:number]
plt = Plot((fig, num), pkg, 0, d, Dict[])
plt
end
@ -139,6 +137,10 @@ end
function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
d = Dict(kw)
fig, num = plt.o
# PyPlot.figure(num) # makes this current
makePlotCurrent(plt)
if !(d[:linetype] in supportedTypes(pkg))
error("linetype $(d[:linetype]) is unsupported in PyPlot. Choose from: $(supportedTypes(pkg))")
end
@ -207,13 +209,21 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
d[:serieshandle] = plotfunc(d[:x], d[:y]; extraargs...)[1]
end
# this sets the bg color inside the grid (plt.o.o == matplotlib.Figure)
plt.o.o[:axes][1][:set_axis_bgcolor](getPyPlotColor(plt.initargs[:background_color]))
# this sets the bg color inside the grid
fig.o[:axes][1][:set_axis_bgcolor](getPyPlotColor(plt.initargs[:background_color]))
push!(plt.seriesargs, d)
plt
end
function updatePlotItems(::PyPlotPackage, plt::Plot, d::Dict)
makePlotCurrent(plt)
haskey(d, :title) && PyPlot.title(d[:title])
haskey(d, :xlabel) && PyPlot.xlabel(d[:xlabel])
haskey(d, :ylabel) && PyPlot.ylabel(d[:ylabel])
end
function addPyPlotLegend(plt::Plot)
# add a legend?
# try
@ -230,40 +240,34 @@ function addPyPlotLegend(plt::Plot)
end
function Base.display(::PyPlotPackage, plt::Plot)
fig, num = plt.o
# PyPlot.figure(num) # makes this current
makePlotCurrent(plt)
addPyPlotLegend(plt)
updateAxisColors(plt.o.o, getPyPlotColor(plt.initargs[:foreground_color]))
display(plt.o)
ax = fig.o[:axes][1]
updateAxisColors(ax, getPyPlotColor(plt.initargs[:foreground_color]))
display(fig)
end
# -------------------------------
function savepng(::PyPlotPackage, plt::PlottingObject, fn::AbstractString, args...)
fig, num = plt.o
addPyPlotLegend(plt)
f = open(fn, "w")
writemime(f, "image/png", plt.o)
writemime(f, "image/png", fig)
close(f)
end
# -------------------------------
# create the underlying object (each backend will do this differently)
function buildSubplotObject!(::PyPlotPackage, subplt::Subplot)
# i = 0
# rows = []
# for rowcnt in subplt.layout.rowcounts
# push!(rows, Qwt.hsplitter([plt.o for plt in subplt.plts[(1:rowcnt) + i]]...))
# i += rowcnt
# end
# subplt.o = Qwt.vsplitter(rows...)
function buildSubplotObject!(subplt::Subplot{PyPlotPackage})
error("unsupported")
end
function Base.display(::PyPlotPackage, subplt::Subplot)
# for plt in subplt.plts
# Qwt.refresh(plt.o)
# end
# Qwt.showwidget(subplt.o)
display(subplt.o)
end

View File

@ -57,6 +57,12 @@ function plot!(::QwtPackage, plt::Plot; kw...)
plt
end
function updatePlotItems(::QwtPackage, plt::Plot, d::Dict)
haskey(d, :title) && Qwt.title(plt.o, d[:title])
haskey(d, :xlabel) && Qwt.xlabel(plt.o, d[:xlabel])
haskey(d, :ylabel) && Qwt.ylabel(plt.o, d[:ylabel])
end
function Base.display(::QwtPackage, plt::Plot)
Qwt.refresh(plt.o)
Qwt.showwidget(plt.o)
@ -69,7 +75,7 @@ savepng(::QwtPackage, plt::PlottingObject, fn::AbstractString, args...) = Qwt.sa
# -------------------------------
# create the underlying object (each backend will do this differently)
function buildSubplotObject!(::QwtPackage, subplt::Subplot)
function buildSubplotObject!(subplt::Subplot{QwtPackage})
i = 0
rows = []
for rowcnt in subplt.layout.rowcounts

View File

@ -35,24 +35,42 @@ function plot!(::[PkgName]Package, plt::Plot; kw...)
end
function Base.display(::[PkgName]Package, plt::Plot)
# TODO: override this to update plot items (title, xlabel, etc) after creation
function updatePlotItems(plt::Plot{[PkgName]Package}, d::Dict)
end
# function Base.display(::[PkgName]Package, plt::Plot)
# # TODO: display/show the plot
# end
function Base.display(::PlotsDisplay, plt::Plot{[PkgName]Package})
# TODO: display/show the plot
end
# -------------------------------
function savepng(::[PkgName]Package, plt::PlottingObject, fn::AbstractString; kw...)
# TODO: save a PNG of the underlying plot/subplot object
# function savepng(::[PkgName]Package, plt::PlottingObject, fn::AbstractString; kw...)
# # TODO: save a PNG of the underlying plot/subplot object
# end
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{[PkgName]Package})
# TODO: write a png to io
end
# -------------------------------
function buildSubplotObject!(::[PkgName]Package, subplt::Subplot)
function buildSubplotObject!(subplt::Subplot{[PkgName]Package})
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
end
function Base.display(::[PkgName]Package, subplt::Subplot)
# TODO: display/show the Subplot object
# function Base.display(::[PkgName]Package, subplt::Subplot)
# # TODO: display/show the Subplot object
# end
function Base.display(::PlotsDisplay, plt::Subplot{[PkgName]Package})
# TODO: display/show the subplot
end

View File

@ -93,6 +93,7 @@ function plot!(plt::Plot, args...; kw...)
plot!(plt.plotter, plt; d...)
end
updatePlotItems(plt.plotter, plt, d)
currentPlot!(plt)
# NOTE: lets ignore the show param and effectively use the semicolon at the end of the REPL statement
@ -104,10 +105,10 @@ function plot!(plt::Plot, args...; kw...)
plt
end
# show/update the plot
function Base.display(plt::PlottingObject)
display(plt.plotter, plt)
end
# # show/update the plot
# function Base.display(plt::PlottingObject)
# display(plt.plotter, plt)
# end
# --------------------------------------------------------------------

View File

@ -13,11 +13,12 @@ include("backends/winston.jl")
plot(pkg::PlottingPackage; kw...) = error("plot($pkg; kw...) is not implemented")
plot!(pkg::PlottingPackage, plt::Plot; kw...) = error("plot!($pkg, plt; kw...) is not implemented")
Base.display(pkg::PlottingPackage, plt::Plot) = error("display($pkg, plt) is not implemented")
updatePlotItems(pkg::PlottingPackage, plt::Plot, d::Dict) = error("updatePlotItems($pkg, plt, d) is not implemented")
# Base.display(pkg::PlottingPackage, plt::Plot) = error("display($pkg, plt) is not implemented")
subplot(pkg::PlottingPackage; kw...) = error("subplot($pkg; kw...) is not implemented")
subplot!(pkg::PlottingPackage, subplt::Subplot; kw...) = error("subplot!($pkg, subplt; kw...) is not implemented")
Base.display(pkg::PlottingPackage, subplt::Subplot) = error("display($pkg, subplt) is not implemented")
# Base.display(pkg::PlottingPackage, subplt::Subplot) = error("display($pkg, subplt) is not implemented")
# ---------------------------------------------------------

View File

@ -132,7 +132,7 @@ function subplot!(subplt::Subplot, args...; kw...)
# create the underlying object (each backend will do this differently)
if !subplt.initialized
buildSubplotObject!(subplt.plotter, subplt)
buildSubplotObject!(subplt)
subplt.initialized = true
end

View File

@ -2,12 +2,14 @@
typealias AVec AbstractVector
typealias AMat AbstractMatrix
abstract PlottingObject
abstract PlottingPackage
immutable PlotsDisplay <: Display end
type Plot <: PlottingObject
abstract PlottingPackage
abstract PlottingObject{T<:PlottingPackage}
type Plot{T<:PlottingPackage} <: PlottingObject{T}
o # the underlying object
plotter::PlottingPackage
plotter::T
n::Int # number of series
# store these just in case
@ -22,10 +24,10 @@ type SubplotLayout
end
type Subplot <: PlottingObject
type Subplot{T<:PlottingPackage} <: PlottingObject{T}
o # the underlying object
plts::Vector{Plot} # the individual plots
plotter::PlottingPackage
plotter::T
p::Int # number of plots
n::Int # number of series
layout::SubplotLayout