From 7566b0159c0c08a4886f55767d84b19fdb4857fa Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Fri, 25 Dec 2015 20:11:05 +0100 Subject: [PATCH] Start experimenting with GR.jl backend --- src/backends/gr.jl | 80 +++++++++++++++++++++++++++++++++++++++ src/backends/supported.jl | 73 +++++++++++++++++++++++++++++++++++ src/plotter.jl | 22 +++++++++-- 3 files changed, 172 insertions(+), 3 deletions(-) create mode 100644 src/backends/gr.jl diff --git a/src/backends/gr.jl b/src/backends/gr.jl new file mode 100644 index 00000000..5888a61f --- /dev/null +++ b/src/backends/gr.jl @@ -0,0 +1,80 @@ + +# https://github.com/jheinen/GR.jl + +function _create_plot(pkg::GRPackage; kw...) + d = Dict(kw) + GR.title(d[:title]) + GR.xlabel(d[:xlabel]) + GR.ylabel(d[:ylabel]) + Plot(nothing, pkg, 0, d, Dict[]) +end + + +function _add_series(::GRPackage, plt::Plot; kw...) + d = Dict(kw) + # TODO: add one series to the underlying package + GR.plot(d[:x], d[:y]) + push!(plt.seriesargs, d) + plt +end + +function _add_annotations{X,Y,V}(plt::Plot{GRPackage}, anns::AVec{@compat(Tuple{X,Y,V})}) + for ann in anns + # TODO: add the annotation to the plot + end +end + +# ---------------------------------------------------------------- + +function _before_update_plot(plt::Plot{GRPackage}) +end + +# TODO: override this to update plot items (title, xlabel, etc) after creation +function _update_plot(plt::Plot{GRPackage}, d::Dict) +end + +function _update_plot_pos_size(plt::PlottingObject{GRPackage}, d::Dict) +end + +# ---------------------------------------------------------------- + +# accessors for x/y data + +function Base.getindex(plt::Plot{GRPackage}, i::Int) + series = plt.o.lines[i] + series.x, series.y +end + +function Base.setindex!(plt::Plot{GRPackage}, xy::Tuple, i::Integer) + series = plt.o.lines[i] + series.x, series.y = xy + plt +end + +# ---------------------------------------------------------------- + +function _create_subplot(subplt::Subplot{GRPackage}, 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{GRPackage}, isx::Bool) + # TODO: call expand limits for each plot data +end + +function _remove_axis(plt::Plot{GRPackage}, isx::Bool) + # TODO: if plot is inner subplot, might need to remove ticks or axis labels +end + +# ---------------------------------------------------------------- + +function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{GRPackage}) + # TODO: write a png to io +end + +function Base.display(::PlotsDisplay, plt::Plot{GRPackage}) + # TODO: display/show the plot +end + +function Base.display(::PlotsDisplay, plt::Subplot{GRPackage}) + # TODO: display/show the subplot +end diff --git a/src/backends/supported.jl b/src/backends/supported.jl index 70253e10..2b970907 100644 --- a/src/backends/supported.jl +++ b/src/backends/supported.jl @@ -174,6 +174,79 @@ subplotSupported(::PyPlotPackage) = true +supportedArgs(::GRPackage) = [ + :annotation, + :axis, + :background_color, + :linecolor, + :color_palette, + :fillrange, + :fillcolor, + :foreground_color, + :group, + :label, + :layout, + :legend, + :linestyle, + :linetype, + :linewidth, + :markershape, + :markercolor, + :markersize, + :markerstrokewidth, + :markerstrokecolor, + # :markerstrokestyle, + :n, + :nbins, + :nc, + :nr, + # :pos, + :smooth, + # :ribbon, + :show, + :size, + :title, + :windowtitle, + :x, + :xlabel, + :xlims, + :xticks, + :y, + :ylabel, + :ylims, + :yrightlabel, + :yticks, + :xscale, + :yscale, + :xflip, + :yflip, + :z, + :zcolor, # only supported for scatter/scatter3d + :tickfont, + :guidefont, + :legendfont, + :grid, + # :surface, + :nlevels, + :fillalpha, + :linealpha, + :markeralpha, + ] +supportedAxes(::GRPackage) = _allAxes +supportedTypes(::GRPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, + :scatter, :heatmap, :hexbin, :hist, :density, :bar, + :hline, :vline, :contour, :path3d, :scatter3d, :surface, :wireframe] +supportedStyles(::GRPackage) = [:auto, :solid, :dash, :dot, :dashdot] +# supportedMarkers(::GRPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :hexagon] +supportedMarkers(::GRPackage) = vcat(_allMarkers, Shape) +supportedScales(::GRPackage) = [:identity, :ln, :log2, :log10] +subplotSupported(::GRPackage) = true + + +# -------------------------------------------------------------------------------------- + + + supportedArgs(::QwtPackage) = [ :annotation, # :args, diff --git a/src/plotter.jl b/src/plotter.jl index 20176fdb..26a925ca 100644 --- a/src/plotter.jl +++ b/src/plotter.jl @@ -8,6 +8,7 @@ immutable UnicodePlotsPackage <: PlottingPackage end immutable WinstonPackage <: PlottingPackage end immutable BokehPackage <: PlottingPackage end immutable PlotlyPackage <: PlottingPackage end +immutable GRPackage <: PlottingPackage end immutable NoPackage <: PlottingPackage end typealias GadflyOrImmerse @compat(Union{GadflyPackage, ImmersePackage}) @@ -19,7 +20,8 @@ export qwt, unicodeplots, bokeh, - plotly + plotly, + gr # winston gadfly() = backend(:gadfly) @@ -29,6 +31,7 @@ qwt() = backend(:qwt) unicodeplots() = backend(:unicodeplots) bokeh() = backend(:bokeh) plotly() = backend(:plotly) +gr() = backend(:gr) # winston() = backend(:winston) backend_name(::GadflyPackage) = :gadfly @@ -38,6 +41,7 @@ backend_name(::UnicodePlotsPackage) = :unicodeplots backend_name(::QwtPackage) = :qwt backend_name(::BokehPackage) = :bokeh backend_name(::PlotlyPackage) = :plotly +backend_name(::GRPackage) = :gr backend_name(::NoPackage) = :none include("backends/supported.jl") @@ -52,6 +56,7 @@ include("backends/winston.jl") include("backends/web.jl") include("backends/bokeh.jl") include("backends/plotly.jl") +include("backends/gr.jl") # --------------------------------------------------------- @@ -71,7 +76,7 @@ subplot!(pkg::PlottingPackage, subplt::Subplot; kw...) = error("subplot!($pkg, s # --------------------------------------------------------- -const BACKENDS = [:qwt, :gadfly, :unicodeplots, :pyplot, :immerse, :bokeh, :plotly] +const BACKENDS = [:qwt, :gadfly, :unicodeplots, :pyplot, :immerse, :bokeh, :plotly, :gr] const INITIALIZED_BACKENDS = Set{Symbol}() backends() = BACKENDS @@ -85,6 +90,7 @@ function backendInstance(sym::Symbol) sym == :winston && return WinstonPackage() sym == :bokeh && return BokehPackage() sym == :plotly && return PlotlyPackage() + sym == :gr && return GRPackage() sym == :none && return NoPackage() error("Unsupported backend $sym") end @@ -99,7 +105,7 @@ CurrentBackend(sym::Symbol) = CurrentBackend(sym, backendInstance(sym)) # --------------------------------------------------------- function pickDefaultBackend() - for pkgstr in ("PyPlot", "Immerse", "Qwt", "Gadfly", "UnicodePlots", "Bokeh") + for pkgstr in ("Gr", "PyPlot", "Immerse", "Qwt", "Gadfly", "UnicodePlots", "Bokeh") if Pkg.installed(pkgstr) != nothing return backend(symbol(lowercase(pkgstr))) end @@ -234,6 +240,14 @@ function backend() rethrow(err) end + elseif currentBackendSymbol == :gr + try + @eval import GR + catch err + warn("Couldn't import GR. Install it with: Pkg.add(\"GR\").") + rethrow(err) + end + elseif currentBackendSymbol == :winston warn("Winston support is deprecated and broken. Try another backend: $BACKENDS") try @@ -281,6 +295,8 @@ function backend(modname) CURRENT_BACKEND.pkg = BokehPackage() elseif modname == :plotly CURRENT_BACKEND.pkg = PlotlyPackage() + elseif modname == :gr + CURRENT_BACKEND.pkg = GRPackage() else error("Unknown backend $modname. Choose from: $BACKENDS") end