diff --git a/src/args.jl b/src/args.jl index 53337b87..78e3c59f 100644 --- a/src/args.jl +++ b/src/args.jl @@ -2,8 +2,8 @@ const _allAxes = [:auto, :left, :right] @compat const _axesAliases = Dict( - :a => :auto, - :l => :left, + :a => :auto, + :l => :left, :r => :right ) @@ -138,7 +138,8 @@ _seriesDefaults[:y] = nothing _seriesDefaults[:z] = nothing # depth for contour, surface, etc _seriesDefaults[:zcolor] = nothing # value for color scale # _seriesDefaults[:surface] = nothing -_seriesDefaults[:nlevels] = 15 +# _seriesDefaults[:nlevels] = 15 +_seriesDefaults[:levels] = 15 _seriesDefaults[:orientation] = :vertical @@ -283,6 +284,9 @@ end :foreground_colour => :foreground_color, :regression => :smooth, :reg => :smooth, + :nlevels => :levels, + :nlev => :levels, + :levs => :levels, :xlim => :xlims, :xlimit => :xlims, :xlimits => :xlims, @@ -407,7 +411,7 @@ function processLineArg(d::Dict, arg) # linetype if trueOrAllTrue(a -> get(_typeAliases, a, a) in _allTypes, arg) d[:linetype] = arg - + # linestyle elseif trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg) d[:linestyle] = arg @@ -446,7 +450,7 @@ function processMarkerArg(d::Dict, arg) d[:markershape] = arg elseif trueOrAllTrue(a -> isa(a, Shape), arg) d[:markershape] = arg - + # stroke style elseif trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg) d[:markerstrokestyle] = arg @@ -473,7 +477,7 @@ function processMarkerArg(d::Dict, arg) # markercolor elseif !handleColors!(d, arg, :markercolor) warn("Skipped marker arg $arg.") - + end end @@ -493,7 +497,7 @@ end "Handle all preprocessing of args... break out colors/sizes/etc and replace aliases." function preprocessArgs!(d::Dict) replaceAliases!(d, _keyAliases) - + # handle axis args for axisletter in ("x", "y") asym = symbol(axisletter * "axis") @@ -590,7 +594,7 @@ end function warnOnUnsupported(pkg::PlottingPackage, d::Dict) - (d[:axis] in supportedAxes(pkg) + (d[:axis] in supportedAxes(pkg) || warn("axis $(d[:axis]) is unsupported with $pkg. Choose from: $(supportedAxes(pkg))")) (d[:linetype] == :none || d[:linetype] in supportedTypes(pkg) @@ -683,7 +687,7 @@ function getSeriesArgs(pkg::PlottingPackage, plotargs::Dict, kw, commandIndex::I d[k] = kwdict[k] end end - + if haskey(_typeAliases, d[:linetype]) d[:linetype] = _typeAliases[d[:linetype]] end diff --git a/src/backends/gadfly.jl b/src/backends/gadfly.jl index 441c1b7e..84e8847e 100644 --- a/src/backends/gadfly.jl +++ b/src/backends/gadfly.jl @@ -44,7 +44,7 @@ function getLineGeom(d::Dict) elseif lt == :vline Gadfly.Geom.vline elseif lt == :contour - Gadfly.Geom.contour(levels = d[:nlevels]) + Gadfly.Geom.contour(levels = d[:levels]) else nothing end @@ -667,9 +667,10 @@ getGadflyWriteFunc(::MIME"image/svg+xml") = Gadfly.SVG # getGadflyWriteFunc(::MIME"text/html") = Gadfly.SVGJS getGadflyWriteFunc(::MIME"application/pdf") = Gadfly.PDF getGadflyWriteFunc(::MIME"application/postscript") = Gadfly.PS +getGadflyWriteFunc(::MIME"application/x-tex") = Gadfly.PGF getGadflyWriteFunc(m::MIME) = error("Unsupported in Gadfly/Immerse: ", m) -for mime in (MIME"image/png", MIME"image/svg+xml", MIME"application/pdf", MIME"application/postscript") +for mime in (MIME"image/png", MIME"image/svg+xml", MIME"application/pdf", MIME"application/postscript", MIME"application/x-tex") @eval function Base.writemime{P<:GadflyOrImmerse}(io::IO, ::$mime, plt::PlottingObject{P}) func = getGadflyWriteFunc($mime()) dowritemime(io, func, plt) diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl new file mode 100644 index 00000000..10c59756 --- /dev/null +++ b/src/backends/glvisualize.jl @@ -0,0 +1,105 @@ + + +# [WEBSITE] + +# --------------------------------------------------------------------------- + +immutable GLScreenWrapper + window + render +end + +function _create_plot(pkg::GLVisualizePackage; kw...) + d = Dict(kw) + # TODO: create the window/canvas/context that is the plot within the backend (call it `o`) + # TODO: initialize the plot... title, xlabel, bgcolor, etc + + # TODO: this should be moved to the display method? + w,r=GLVisualize.glscreen() + @async r() + o = GLScreenWrapper(w,r) + + Plot(o, pkg, 0, d, Dict[]) +end + + +function _add_series(::GLVisualizePackage, plt::Plot; kw...) + d = Dict(kw) + # TODO: add one series to the underlying package + push!(plt.seriesargs, d) + + # TODO: this should be moved to the display method? + x, y, z = map(Float32, d[:x]), map(Float32, d[:y]), map(Float32, d[:z].surf) + viz = GLVisualize.visualize(x*ones(y)', ones(x)*y', z, :surface) + GLVisualize.view(viz) + + plt +end + +function _add_annotations{X,Y,V}(plt::Plot{GLVisualizePackage}, 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{GLVisualizePackage}) +end + +# TODO: override this to update plot items (title, xlabel, etc) after creation +function _update_plot(plt::Plot{GLVisualizePackage}, d::Dict) +end + +function _update_plot_pos_size(plt::PlottingObject{GLVisualizePackage}, d::Dict) +end + +# ---------------------------------------------------------------- + +# accessors for x/y data + +function Base.getindex(plt::Plot{GLVisualizePackage}, i::Int) + # TODO: + # series = plt.o.lines[i] + # series.x, series.y + nothing, nothing +end + +function Base.setindex!(plt::Plot{GLVisualizePackage}, xy::Tuple, i::Integer) + # TODO: + # series = plt.o.lines[i] + # series.x, series.y = xy + plt +end + +# ---------------------------------------------------------------- + +function _create_subplot(subplt::Subplot{GLVisualizePackage}) + # 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{GLVisualizePackage}, isx::Bool) + # TODO: call expand limits for each plot data +end + +function _remove_axis(plt::Plot{GLVisualizePackage}, 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{GLVisualizePackage}) + # TODO: write a png to io +end + +function Base.display(::PlotsDisplay, plt::Plot{GLVisualizePackage}) + # TODO: display/show the plot + + # NOTE: I think maybe this should be empty? We can start with the assumption that creating + # and adding to a plot will automatically open a window and draw to it, then the display + # wouldn't actually need to do anything +end + +function Base.display(::PlotsDisplay, plt::Subplot{GLVisualizePackage}) + # TODO: display/show the subplot +end diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index a417d3fb..00db4c62 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -176,8 +176,9 @@ function plotlyaxis(d::Dict, isx::Bool) ax end -function get_plot_json(plt::Plot{PlotlyPackage}) - d = plt.plotargs +# function get_plot_json(plt::Plot{PlotlyPackage}) +# d = plt.plotargs +function plotly_layout(d::Dict) d_out = Dict() bgcolor = webcolor(d[:background_color]) @@ -194,84 +195,6 @@ function get_plot_json(plt::Plot{PlotlyPackage}) d_out[:xaxis] = plotlyaxis(d, true) d_out[:yaxis] = plotlyaxis(d, false) - # # x-axis - # d_out[:xaxis] = Dict( - # :title => d[:xlabel], - # :showgrid => d[:grid], - # :zeroline => false, - # ) - # merge!(d_out[:xaxis], if use_axis_field(d[:xticks]) - # ax = Dict( - # :titlefont => plotlyfont(d[:guidefont]), - # :type => plotlyscale(d[:xscale]), - # :tickfont => plotlyfont(d[:tickfont]), - # :tickcolor => fgcolor, - # :linecolor => fgcolor, - # ) - - # # xlims - # lims = d[:xlims] - # if lims != :auto && limsType(lims) == :limits - # ax[:range] = lims - # end - - # # xflip - # if d[:xflip] - # ax[:autorange] = "reversed" - # end - - # # xticks - # ticks = d[:xticks] - # if ticks != :auto - # ttype = ticksType(ticks) - # if ttype == :ticks - # ax[:tickmode] = "array" - # ax[:tickvals] = ticks - # elseif ttype == :ticks_and_labels - # ax[:tickmode] = "array" - # ax[:tickvals], ax[:ticktext] = ticks - # end - # end - - # ax - # else - # Dict( - # :showticklabels => false, - # :showgrid => false, - # ) - # end) - - - # # y-axis - # d_out[:yaxis] = Dict( - # :title => d[:ylabel], - # :showgrid => d[:grid], - # :zeroline => false, - # ) - # merge!(d_out[:yaxis], if use_axis_field(d[:yticks]) - # Dict( - # :titlefont => plotlyfont(d[:guidefont]), - # :type => plotlyscale(d[:yscale]), - # :tickfont => plotlyfont(d[:tickfont]), - # :tickcolor => fgcolor, - # :linecolor => fgcolor, - # ) - # else - # Dict( - # :showticklabels => false, - # :showgrid => false, - # ) - # end) - - # lims = d[:ylims] - # if lims != :auto && limsType(lims) == :limits - # d_out[:yaxis][:range] = lims - # end - - # if d[:yflip] - # d_out[:yaxis][:autorange] = "reversed" - # end - # legend d_out[:showlegend] = d[:legend] if d[:legend] @@ -288,8 +211,11 @@ function get_plot_json(plt::Plot{PlotlyPackage}) d_out[:annotations] = [get_annotation_dict(ann...) for ann in anns] end - # finally build and return the json - JSON.json(d_out) + d_out +end + +function get_plot_json(plt::Plot{PlotlyPackage}) + JSON.json(plotly_layout(plt.plotargs)) end @@ -309,7 +235,7 @@ const _plotly_markers = Dict( ) # get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict) -function get_series_json(d::Dict; plot_index = nothing) +function plotly_series(d::Dict; plot_index = nothing) d_out = Dict() x, y = collect(d[:x]), collect(d[:y]) @@ -366,7 +292,7 @@ function get_series_json(d::Dict; plot_index = nothing) d_out[:z] = d[:z].surf # d_out[:showscale] = d[:legend] if lt == :contour - d_out[:ncontours] = d[:nlevels] + d_out[:ncontours] = d[:levels] d_out[:contours] = Dict(:coloring => d[:fillrange] != nothing ? "fill" : "lines") end d_out[:colorscale] = plotly_colorscale(d[lt == :contour ? :linecolor : :fillcolor]) @@ -438,14 +364,14 @@ end # get a list of dictionaries, each representing the series params function get_series_json(plt::Plot{PlotlyPackage}) - JSON.json(map(get_series_json, plt.seriesargs)) + JSON.json(map(plotly_series, plt.seriesargs)) end function get_series_json(subplt::Subplot{PlotlyPackage}) ds = Dict[] for (i,plt) in enumerate(subplt.plts) for d in plt.seriesargs - push!(ds, get_series_json(d, plot_index = i)) + push!(ds, plotly_series(d, plot_index = i)) end end JSON.json(ds) diff --git a/src/backends/plotly_blink.jl b/src/backends/plotly_blink.jl new file mode 100644 index 00000000..c5f5a6f5 --- /dev/null +++ b/src/backends/plotly_blink.jl @@ -0,0 +1,48 @@ + +# override some methods to use Plotlyjs/Blink + +import Plotlyjs + +function _create_plot(pkg::PlotlyPackage; kw...) + d = Dict(kw) + # TODO: create the window/canvas/context that is the plot within the backend (call it `o`) + # TODO: initialize the plot... title, xlabel, bgcolor, etc + o = Plotlyjs.Plot() + + Plot(o, pkg, 0, d, Dict[]) +end + + +function _add_series(::PlotlyPackage, plt::Plot; kw...) + d = Dict(kw) + + # add to the data array + pdict = plotly_series(d) + gt = Plotlyjs.GenericTrace(pdict[:type], pdict) + push!(plt.o.data, gt) + if !isnull(plt.o.window) + Plotlyjs.addtraces!(plt.o, gt) + end + + push!(plt.seriesargs, d) + plt +end + +# TODO: override this to update plot items (title, xlabel, etc) after creation +function _update_plot(plt::Plot{PlotlyPackage}, d::Dict) + pdict = plotly_layout(d) + plt.o.layout = Plotlyjs.Layout(pdict) + if !isnull(plt.o.window) + Plotlyjs.relayout!(plt.o, pdict...) + end +end + + +function Base.display(::PlotsDisplay, plt::Plot{PlotlyPackage}) + dump(plt.o) + show(plt.o) +end + +function Base.display(::PlotsDisplay, plt::Subplot{PlotlyPackage}) + error() +end diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index d433eb49..f1ff784f 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -207,6 +207,10 @@ function _create_plot(pkg::PyPlotPackage; kw...) w,h = map(px2inch, d[:size]) bgcolor = getPyPlotColor(d[:background_color]) wrap = PyPlotAxisWrapper(nothing, nothing, PyPlot.figure(; figsize = (w,h), facecolor = bgcolor, dpi = DPI, tight_layout = true), []) + + if haskey(d, :linetype) && first(d[:linetype]) in _3dTypes # && isa(plt.o, PyPlotFigWrapper) + push!(wrap.kwargs, (:projection, "3d")) + end end plt = Plot(wrap, pkg, 0, d, Dict[]) @@ -218,7 +222,7 @@ function _add_series(pkg::PyPlotPackage, plt::Plot; kw...) d = Dict(kw) lt = d[:linetype] - if lt in _3dTypes # && isa(plt.o, PyPlotFigWrapper) + if lt in _3dTypes && isempty(plt.o.kwargs) push!(plt.o.kwargs, (:projection, "3d")) end @@ -232,7 +236,7 @@ function _add_series(pkg::PyPlotPackage, plt::Plot; kw...) if lt == :sticks d,_ = sticksHack(;d...) - + elseif lt in (:scatter, :scatter3d) if d[:markershape] == :none d[:markershape] = :ellipse @@ -249,7 +253,7 @@ function _add_series(pkg::PyPlotPackage, plt::Plot; kw...) end - lt = d[:linetype] + # lt = d[:linetype] extra_kwargs = Dict() plotfunc = getPyPlotFunction(plt, d[:axis], lt) @@ -333,18 +337,35 @@ function _add_series(pkg::PyPlotPackage, plt::Plot; kw...) # do the plot d[:serieshandle] = if ishistlike(lt) plotfunc(d[:y]; extra_kwargs...)[1] + elseif lt == :contour - # NOTE: x/y are backwards in pyplot, so we switch the x and y args (also y is reversed), - # and take the transpose of the surface matrix x, y = d[:x], d[:y] surf = d[:z].surf' - handle = plotfunc(x, y, surf, d[:nlevels]; extra_kwargs...) + levels = d[:levels] + if isscalar(levels) + extra_args = (levels) + elseif isvector(levels) + extra_args = () + extra_kwargs[:levels] = levels + else + error("Only numbers and vectors are supported with levels keyword") + end + handle = plotfunc(x, y, surf, extra_args...; extra_kwargs...) if d[:fillrange] != nothing - handle = ax[:contourf](x, y, surf, d[:nlevels]; cmap = getPyPlotColorMap(d[:fillcolor], d[:fillalpha])) + extra_kwargs[:cmap] = getPyPlotColorMap(d[:fillcolor], d[:fillalpha]) + delete!(extra_kwargs, :linewidths) + handle = ax[:contourf](x, y, surf, extra_args...; extra_kwargs...) end handle + elseif lt in (:surface,:wireframe) - plotfunc(repmat(d[:x]',length(d[:y]),1), repmat(d[:y],1,length(d[:x])), d[:z].surf'; extra_kwargs...) + x, y, z = d[:x], d[:y], Array(d[:z]) + if !ismatrix(x) || !ismatrix(y) + x = repmat(x', length(y), 1) + y = repmat(y, 1, length(d[:x])) + z = z' + end + plotfunc(x, y, z; extra_kwargs...) elseif lt in _3dTypes plotfunc(d[:x], d[:y], d[:z]; extra_kwargs...) elseif lt in (:scatter, :heatmap, :hexbin) @@ -465,7 +486,7 @@ function _update_plot(plt::Plot{PyPlotPackage}, d::Dict) ax[:set_ylabel](d[:ylabel]) end if usingRightAxis(plt) && get(d, :yrightlabel, "") != "" - rightax = getRightAxis(figorax) + rightax = getRightAxis(figorax) rightax[:set_ylabel](d[:yrightlabel]) end @@ -494,7 +515,7 @@ function _update_plot(plt::Plot{PyPlotPackage}, d::Dict) # font sizes for ax in axes # haskey(d, :yrightlabel) || continue - + # guides sz = get(d, :guidefont, plt.plotargs[:guidefont]).pointsize @@ -509,7 +530,7 @@ function _update_plot(plt::Plot{PyPlotPackage}, d::Dict) lab[:set_fontsize](sz) end end - + # grid if get(d, :grid, false) ax[:xaxis][:grid](true) @@ -629,7 +650,7 @@ end function addPyPlotLegend(plt::Plot, ax) if plt.plotargs[:legend] # gotta do this to ensure both axes are included - args = filter(x -> !(x[:linetype] in (:hist,:density,:hexbin,:heatmap,:hline,:vline,:contour, :path3d, :scatter3d)), plt.seriesargs) + args = filter(x -> !(x[:linetype] in (:hist,:density,:hexbin,:heatmap,:hline,:vline,:contour, :surface, :wireframe, :path3d, :scatter3d)), plt.seriesargs) if length(args) > 0 leg = ax[:legend]([d[:serieshandle] for d in args], [d[:label] for d in args], diff --git a/src/backends/supported.jl b/src/backends/supported.jl index 256f33ca..1fdea586 100644 --- a/src/backends/supported.jl +++ b/src/backends/supported.jl @@ -74,10 +74,10 @@ supportedArgs(::GadflyPackage) = [ :legendfont, :grid, # :surface, - :nlevels, + :levels, ] supportedAxes(::GadflyPackage) = [:auto, :left] -supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, +supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour] supportedStyles(::GadflyPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] @@ -154,13 +154,13 @@ supportedArgs(::PyPlotPackage) = [ :legendfont, :grid, # :surface, - :nlevels, + :levels, :fillalpha, :linealpha, :markeralpha, ] supportedAxes(::PyPlotPackage) = _allAxes -supportedTypes(::PyPlotPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, +supportedTypes(::PyPlotPackage) = [:none, :line, :path, :steppre, :steppost, #:sticks, :scatter, :heatmap, :hexbin, :hist, :density, :bar, :hline, :vline, :contour, :path3d, :scatter3d, :surface, :wireframe] supportedStyles(::PyPlotPackage) = [:auto, :solid, :dash, :dot, :dashdot] @@ -485,7 +485,7 @@ supportedArgs(::BokehPackage) = [ # :legendfont, # :grid, # :surface, - # :nlevels, + # :levels, ] supportedAxes(::BokehPackage) = [:auto, :left] supportedTypes(::BokehPackage) = [:none, :path, :scatter] #,:steppre, :steppost, :sticks, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour] @@ -551,7 +551,7 @@ supportedArgs(::PlotlyPackage) = [ :guidefont, :legendfont, :grid, - :nlevels, + :levels, ] supportedAxes(::PlotlyPackage) = [:auto, :left] supportedTypes(::PlotlyPackage) = [:none, :line, :path, :scatter, :steppre, :steppost, @@ -564,3 +564,68 @@ supportedScales(::PlotlyPackage) = [:identity, :log10] #, :ln, :log2, :log10, :a subplotSupported(::PlotlyPackage) = true stringsSupported(::PlotlyPackage) = true + +# -------------------------------------------------------------------------------------- + +supportedArgs(::GLVisualizePackage) = [ + # :annotation, + # :axis, + # :background_color, + # :color_palette, + # :fillrange, + # :fillcolor, + # :fillalpha, + # :foreground_color, + # :group, + # :label, + # :layout, + # :legend, + # :linecolor, + # :linestyle, + # :linetype, + # :linewidth, + # :linealpha, + # :markershape, + # :markercolor, + # :markersize, + # :markeralpha, + # :markerstrokewidth, + # :markerstrokecolor, + # :markerstrokestyle, + # :n, + # :nbins, + # :nc, + # :nr, + # :pos, + # :smooth, + # :show, + # :size, + # :title, + # :windowtitle, + # :x, + # :xlabel, + # :xlims, + # :xticks, + # :y, + # :ylabel, + # :ylims, + # :yrightlabel, + # :yticks, + # :xscale, + # :yscale, + # :xflip, + # :yflip, + # :z, + # :tickfont, + # :guidefont, + # :legendfont, + # :grid, + # :surface + # :levels, + ] +supportedAxes(::GLVisualizePackage) = [:auto, :left] +supportedTypes(::GLVisualizePackage) = [:contour] #, :path, :scatter ,:steppre, :steppost, :sticks, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour] +supportedStyles(::GLVisualizePackage) = [:auto, :solid] #, :dash, :dot, :dashdot, :dashdotdot] +supportedMarkers(::GLVisualizePackage) = [:none, :auto, :ellipse] #, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5] #vcat(_allMarkers, Shape) +supportedScales(::GLVisualizePackage) = [:identity] #, :log, :log2, :log10, :asinh, :sqrt] +subplotSupported(::GLVisualizePackage) = false diff --git a/src/components.jl b/src/components.jl index f1b7114b..5c4be5ba 100644 --- a/src/components.jl +++ b/src/components.jl @@ -231,6 +231,8 @@ end Surface(f::Function, x, y) = Surface(Float64[f(xi,yi) for xi in x, yi in y]) +Base.Array(surf::Surface) = surf.surf + # ----------------------------------------------------------------------- type OHLC{T<:Real} diff --git a/src/output.jl b/src/output.jl index afc98c25..5a97848a 100644 --- a/src/output.jl +++ b/src/output.jl @@ -37,6 +37,15 @@ end ps(fn::@compat(AbstractString)) = ps(current(), fn) +function tex(plt::PlottingObject, fn::@compat(AbstractString)) + fn = addExtension(fn, "tex") + io = open(fn, "w") + writemime(io, MIME("application/x-tex"), plt) + close(io) +end +tex(fn::@compat(AbstractString)) = tex(current(), fn) + + # ---------------------------------------------------------------- @@ -45,6 +54,7 @@ ps(fn::@compat(AbstractString)) = ps(current(), fn) "svg" => svg, "pdf" => pdf, "ps" => ps, + "tex" => tex, ) function getExtension(fn::@compat(AbstractString)) diff --git a/src/plot.jl b/src/plot.jl index ea4e67f7..5eaca478 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -48,7 +48,7 @@ function plot(args...; kw...) preprocessArgs!(d) dumpdict(d, "After plot preprocessing") - plotargs = getPlotArgs(pkg, d, 1) + plotargs = merge(d, getPlotArgs(pkg, d, 1)) dumpdict(plotargs, "Plot args") plt = _create_plot(pkg; plotargs...) # create a new, blank plot @@ -94,7 +94,7 @@ function plot!(plt::Plot, args...; kw...) # get the list of dictionaries, one per series seriesArgList, xmeta, ymeta = createKWargsList(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) @@ -378,16 +378,32 @@ function createKWargsList{T<:Real}(plt::PlottingObject, x::AVec, y::AVec, zmat:: @assert x == sort(x) @assert y == sort(y) @assert size(zmat) == (length(x), length(y)) + # surf = Surface(convert(Matrix{Float64}, zmat)) + # surf = Array(Any,1,1) + # surf[1,1] = convert(Matrix{Float64}, zmat) + d = Dict(kw) + d[:z] = Surface(convert(Matrix{Float64}, zmat)) + if !(get(d, :linetype, :none) in (:contour, :surface, :wireframe)) + d[:linetype] = :contour + end + createKWargsList(plt, x, y; d...) #, z = surf) +end + +# contours or surfaces... general x, y grid +function createKWargsList{T<:Real}(plt::PlottingObject, x::AMat{T}, y::AMat{T}, zmat::AMat{T}; kw...) + @assert size(zmat) == size(x) == size(y) surf = Surface(convert(Matrix{Float64}, zmat)) # surf = Array(Any,1,1) # surf[1,1] = convert(Matrix{Float64}, zmat) d = Dict(kw) + d[:z] = Surface(convert(Matrix{Float64}, zmat)) if !(get(d, :linetype, :none) in (:contour, :surface, :wireframe)) d[:linetype] = :contour end - createKWargsList(plt, x, y; d..., z = surf) + createKWargsList(plt, Any[x], Any[y]; d...) #kw..., z = surf, linetype = :contour) end + function createKWargsList(plt::PlottingObject, surf::Surface; kw...) createKWargsList(plt, 1:size(surf.surf,1), 1:size(surf.surf,2), convert(Matrix{Float64}, surf.surf); kw...) end @@ -431,7 +447,7 @@ function createKWargsList(plt::PlottingObject; kw...) return [], nothing, nothing # error("Called plot/subplot without args... must set y in the keyword args. Example: plot(; y=rand(10))") end - + if haskey(d, :x) return createKWargsList(plt, d[:x], d[:y]; kw...) else @@ -474,4 +490,3 @@ end # -------------------------------------------------------------------- - diff --git a/src/plotter.jl b/src/plotter.jl index 26a925ca..032e4152 100644 --- a/src/plotter.jl +++ b/src/plotter.jl @@ -9,6 +9,7 @@ immutable WinstonPackage <: PlottingPackage end immutable BokehPackage <: PlottingPackage end immutable PlotlyPackage <: PlottingPackage end immutable GRPackage <: PlottingPackage end +immutable GLVisualizePackage <: PlottingPackage end immutable NoPackage <: PlottingPackage end typealias GadflyOrImmerse @compat(Union{GadflyPackage, ImmersePackage}) @@ -21,7 +22,8 @@ export unicodeplots, bokeh, plotly, - gr + gr, + glvisualize # winston gadfly() = backend(:gadfly) @@ -32,6 +34,7 @@ unicodeplots() = backend(:unicodeplots) bokeh() = backend(:bokeh) plotly() = backend(:plotly) gr() = backend(:gr) +glvisualize() = backend(:glvisualize) # winston() = backend(:winston) backend_name(::GadflyPackage) = :gadfly @@ -42,6 +45,7 @@ backend_name(::QwtPackage) = :qwt backend_name(::BokehPackage) = :bokeh backend_name(::PlotlyPackage) = :plotly backend_name(::GRPackage) = :gr +backend_name(::GLVisualizePackage) = :glvisualize backend_name(::NoPackage) = :none include("backends/supported.jl") @@ -58,6 +62,8 @@ include("backends/bokeh.jl") include("backends/plotly.jl") include("backends/gr.jl") +include("backends/glvisualize.jl") + # --------------------------------------------------------- @@ -91,9 +97,10 @@ function backendInstance(sym::Symbol) sym == :bokeh && return BokehPackage() sym == :plotly && return PlotlyPackage() sym == :gr && return GRPackage() + sym == :glvisualize && return GLVisualizePackage() sym == :none && return NoPackage() error("Unsupported backend $sym") -end +end type CurrentBackend @@ -105,7 +112,7 @@ CurrentBackend(sym::Symbol) = CurrentBackend(sym, backendInstance(sym)) # --------------------------------------------------------- function pickDefaultBackend() - for pkgstr in ("Gr", "PyPlot", "Immerse", "Qwt", "Gadfly", "UnicodePlots", "Bokeh") + for pkgstr in ("Gr", "PyPlot", "Immerse", "Qwt", "Gadfly", "UnicodePlots", "Bokeh", "GLVisualize") if Pkg.installed(pkgstr) != nothing return backend(symbol(lowercase(pkgstr))) end @@ -169,7 +176,7 @@ function backend() # @eval const pycolorbar = PyPlot.pywrap(PyPlot.pyimport("matplotlib.colorbar")) if !isa(Base.Multimedia.displays[end], Base.REPL.REPLDisplay) PyPlot.ioff() # stops wierd behavior of displaying incomplete graphs in IJulia - + # # TODO: how the hell can I use PyQt4?? # "pyqt4"=>:qt_pyqt4 # PyPlot.backend[1] = "pyqt4" @@ -234,6 +241,12 @@ function backend() # end borrowing (thanks :) ########################### + # try + # include(joinpath(Pkg.dir("Plots"), "src", "backends", "plotly_blink.jl")) + # catch err + # warn("Error including Plotlyjs: $err\n Note: Will fall back to built-in display.") + # end + end catch err warn("Couldn't setup Plotly") @@ -245,6 +258,14 @@ function backend() @eval import GR catch err warn("Couldn't import GR. Install it with: Pkg.add(\"GR\").") + end + + elseif currentBackendSymbol == :glvisualize + try + @eval import GLVisualize + @eval export GLVisualize + catch err + warn("Couldn't setup GLVisualize") rethrow(err) end @@ -277,7 +298,7 @@ function backend(pkg::PlottingPackage) end function backend(modname) - + # set the PlottingPackage if modname == :qwt CURRENT_BACKEND.pkg = QwtPackage() @@ -297,6 +318,8 @@ function backend(modname) CURRENT_BACKEND.pkg = PlotlyPackage() elseif modname == :gr CURRENT_BACKEND.pkg = GRPackage() + elseif modname == :glvisualize + CURRENT_BACKEND.pkg = GLVisualizePackage() else error("Unknown backend $modname. Choose from: $BACKENDS") end diff --git a/src/utils.jl b/src/utils.jl index 167910b4..a6e65c78 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -174,7 +174,9 @@ function replaceAliases!(d::Dict, aliases::Dict) end createSegments(z) = collect(repmat(z',2,1))[2:end] + Base.first(c::Colorant) = c +Base.first(x::Symbol) = x sortedkeys(d::Dict) = sort(collect(keys(d))) @@ -190,6 +192,17 @@ end isijulia() = isdefined(Main, :IJulia) && Main.IJulia.inited +istuple(::Tuple) = true +istuple(::Any) = false +isvector(::AVec) = true +isvector(::Any) = false +ismatrix(::AMat) = true +ismatrix(::Any) = false +isscalar(::Real) = true +isscalar(::Any) = false + + + # ticksType{T<:Real,S<:Real}(ticks::@compat(Tuple{T,S})) = :limits ticksType{T<:Real}(ticks::AVec{T}) = :ticks @@ -226,6 +239,9 @@ function with(f::Function, args...; kw...) end # save the backend + if CURRENT_BACKEND.sym == :none + pickDefaultBackend() + end oldbackend = CURRENT_BACKEND.sym for arg in args diff --git a/test/imgcomp.jl b/test/imgcomp.jl index e61e7523..b8c65878 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -73,7 +73,7 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is # first Plots._debugMode.on = debug - example = ExamplePlots.examples[idx] + example = ExamplePlots._examples[idx] info("Testing plot: $pkg:$idx:$(example.header)") backend(pkg) backend() @@ -88,7 +88,7 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is end # run the example - # map(eval, PlotExamples.examples[idx].exprs) + # map(eval, PlotExamples._examples[idx].exprs) # # save the png # tmpfn = tempname() * ".png" @@ -148,7 +148,7 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is end function image_comparison_facts(pkg::Symbol; skip = [], debug = false, sigma = [1,1], eps = 1e-2) - for i in 1:length(ExamplePlots.examples) + for i in 1:length(ExamplePlots._examples) i in skip && continue @fact image_comparison_tests(pkg, i, debug=debug, sigma=sigma, eps=eps) |> success --> true end diff --git a/test/refimg/gadfly/ref13.png b/test/refimg/gadfly/ref13.png index a3d1aecc..caf2109c 100644 Binary files a/test/refimg/gadfly/ref13.png and b/test/refimg/gadfly/ref13.png differ diff --git a/test/refimg/pyplot/ref11.png b/test/refimg/pyplot/ref11.png index b6027f37..c7ca4373 100644 Binary files a/test/refimg/pyplot/ref11.png and b/test/refimg/pyplot/ref11.png differ diff --git a/test/refimg/pyplot/ref13.png b/test/refimg/pyplot/ref13.png index 4b80aa7f..e2273cd9 100644 Binary files a/test/refimg/pyplot/ref13.png and b/test/refimg/pyplot/ref13.png differ diff --git a/test/runtests.jl b/test/runtests.jl index 14e879c0..46887353 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -30,7 +30,7 @@ default(show=false) # gadfly() # backend() -img_eps = 2e-2 +img_eps = 5e-2 facts("Gadfly") do @fact gadfly() --> Plots.GadflyPackage() @@ -49,14 +49,14 @@ facts("Gadfly") do # plot(x::AMat, y::AMat; kw...) # multiple lines (one per column of x/y... will assert size(x) == size(y)) @fact plot!(rand(10,3), rand(10,3)) --> not(nothing) - image_comparison_facts(:gadfly, skip=[4,19,23,24], eps=img_eps) + image_comparison_facts(:gadfly, skip=[4,6,19,23,24], eps=img_eps) end facts("PyPlot") do @fact pyplot() --> Plots.PyPlotPackage() @fact backend() --> Plots.PyPlotPackage() - image_comparison_facts(:pyplot, skip=[19,21,23], eps=img_eps) + image_comparison_facts(:pyplot, skip=[10,19,21,23], eps=img_eps) end