diff --git a/src/Plots.jl b/src/Plots.jl index e7d5f404..feca5ce9 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -1,7 +1,5 @@ -if VERSION >= v"0.4-" - __precompile__() -end + __precompile__() module Plots @@ -55,6 +53,8 @@ export contour!, surface, surface!, + wireframe, + wireframe!, path3d, path3d!, scatter3d, @@ -168,6 +168,8 @@ contour(args...; kw...) = plot(args...; kw..., linetype = :contour) contour!(args...; kw...) = plot!(args...; kw..., linetype = :contour) surface(args...; kw...) = plot(args...; kw..., linetype = :surface) surface!(args...; kw...) = plot!(args...; kw..., linetype = :surface) +wireframe(args...; kw...) = plot(args...; kw..., linetype = :wireframe) +wireframe!(args...; kw...) = plot!(args...; kw..., linetype = :wireframe) path3d(args...; kw...) = plot(args...; kw..., linetype = :path3d) path3d!(args...; kw...) = plot!(args...; kw..., linetype = :path3d) scatter3d(args...; kw...) = plot(args...; kw..., linetype = :scatter3d) diff --git a/src/args.jl b/src/args.jl index 5e3d05e4..53337b87 100644 --- a/src/args.jl +++ b/src/args.jl @@ -7,11 +7,11 @@ const _allAxes = [:auto, :left, :right] :r => :right ) -const _3dTypes = [:path3d, :scatter3d] +const _3dTypes = [:path3d, :scatter3d, :surface, :wireframe] const _allTypes = vcat([ :none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :density, :bar, :hline, :vline, :ohlc, - :contour, :surface, :pie + :contour, :pie ], _3dTypes) @compat const _typeAliases = Dict( :n => :none, @@ -34,6 +34,7 @@ const _allTypes = vcat([ :contours => :contour, :line3d => :path3d, :surf => :surface, + :wire => :wireframe, ) ishistlike(lt::Symbol) = lt in (:hist, :density) @@ -90,12 +91,13 @@ const _allMarkers = vcat(:none, :auto, sort(collect(keys(_shapes)))) :hep => :heptagon, :o => :octagon, :oct => :octagon, + :spike => :vline, ) -const _allScales = [:identity, :log, :log2, :log10, :asinh, :sqrt] +const _allScales = [:identity, :ln, :log2, :log10, :asinh, :sqrt] @compat const _scaleAliases = Dict( :none => :identity, - :ln => :log, + :log => :log10, ) # ----------------------------------------------------------------------------- @@ -130,7 +132,7 @@ _seriesDefaults[:markerstrokealpha] = nothing _seriesDefaults[:nbins] = 30 # number of bins for heatmaps and hists _seriesDefaults[:smooth] = false # regression line? _seriesDefaults[:group] = nothing # groupby vector -_seriesDefaults[:annotation] = nothing # annotation tuple(s)... (x,y,annotation) +# _seriesDefaults[:annotation] = nothing # annotation tuple(s)... (x,y,annotation) _seriesDefaults[:x] = nothing _seriesDefaults[:y] = nothing _seriesDefaults[:z] = nothing # depth for contour, surface, etc @@ -175,6 +177,7 @@ _plotDefaults[:tickfont] = font(8) _plotDefaults[:guidefont] = font(11) _plotDefaults[:legendfont] = font(8) _plotDefaults[:grid] = true +_plotDefaults[:annotation] = nothing # annotation tuple(s)... (x,y,annotation) diff --git a/src/backends/bokeh.jl b/src/backends/bokeh.jl index 824e524a..c6b678df 100644 --- a/src/backends/bokeh.jl +++ b/src/backends/bokeh.jl @@ -68,8 +68,8 @@ function _create_plot(pkg::BokehPackage; kw...) filename = tempname() * ".html" title = d[:title] w, h = d[:size] - xaxis_type = d[:xscale] == :log ? :log : :auto - yaxis_type = d[:yscale] == :log ? :log : :auto + xaxis_type = d[:xscale] == :log10 ? :log : :auto + yaxis_type = d[:yscale] == :log10 ? :log : :auto # legend = d[:legend] ? xxxx : nothing legend = nothing extra_args = Dict() # TODO: we'll put extra settings (xlim, etc) here diff --git a/src/backends/gadfly.jl b/src/backends/gadfly.jl index f4a4e93e..441c1b7e 100644 --- a/src/backends/gadfly.jl +++ b/src/backends/gadfly.jl @@ -375,7 +375,7 @@ function getGadflyScaleFunction(d::Dict, isx::Bool) hasScaleKey = haskey(d, scalekey) if hasScaleKey scale = d[scalekey] - scale == :log && return isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log, hasScaleKey + scale == :ln && return isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log, hasScaleKey scale == :log2 && return isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log2, hasScaleKey scale == :log10 && return isx ? Gadfly.Scale.x_log10 : Gadfly.Scale.y_log10, hasScaleKey scale == :asinh && return isx ? Gadfly.Scale.x_asinh : Gadfly.Scale.y_asinh, hasScaleKey diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 25b88793..a417d3fb 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -19,8 +19,11 @@ function _add_series(::PlotlyPackage, plt::Plot; kw...) end function _add_annotations{X,Y,V}(plt::Plot{PlotlyPackage}, anns::AVec{@compat(Tuple{X,Y,V})}) - for ann in anns - # TODO: add the annotation to the plot + # set or add to the annotation_list + if haskey(plt.plotargs, :annotation_list) + append!(plt.plotargs[:annotation_list], anns) + else + plt.plotargs[:annotation_list] = anns end end @@ -41,20 +44,21 @@ end # accessors for x/y data function Base.getindex(plt::Plot{PlotlyPackage}, i::Int) - series = plt.o.lines[i] - series.x, series.y + d = plt.seriesargs[i] + d[:x], d[:y] end function Base.setindex!(plt::Plot{PlotlyPackage}, xy::Tuple, i::Integer) - series = plt.o.lines[i] - series.x, series.y = xy + d = plt.seriesargs[i] + d[:x], d[:y] = xy plt end # ---------------------------------------------------------------- -function _create_subplot(subplt::Subplot{PlotlyPackage}) +function _create_subplot(subplt::Subplot{PlotlyPackage}, isbefore::Bool) # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example + true end function _expand_limits(lims, plt::Plot{PlotlyPackage}, isx::Bool) @@ -67,7 +71,7 @@ end # ---------------------------------------------------------------- - +# TODO: # _plotDefaults[:yrightlabel] = "" # _plotDefaults[:xlims] = :auto # _plotDefaults[:ylims] = :auto @@ -78,107 +82,216 @@ end # _plotDefaults[:xflip] = false # _plotDefaults[:yflip] = false -function plotlyfont(font::Font) +function plotlyfont(font::Font, color = font.color) Dict( :family => font.family, - :size => font.pointsize, - :color => webcolor(font.color), + :size => round(Int, font.pointsize*1.4), + :color => webcolor(color), ) end +function get_annotation_dict(x, y, val::Union{AbstractString,Symbol}) + Dict( + :text => val, + :xref => "x", + :x => x, + :yref => "y", + :y => y, + :showarrow => false, + ) +end + +function get_annotation_dict(x, y, ptxt::PlotText) + merge(get_annotation_dict(x, y, ptxt.str), Dict( + :font => plotlyfont(ptxt.font), + :xanchor => ptxt.font.halign == :hcenter ? :center : ptxt.font.halign, + :yanchor => ptxt.font.valign == :vcenter ? :middle : ptxt.font.valign, + :rotation => ptxt.font.rotation, + )) +end + function plotlyscale(scale::Symbol) - if scale == :log + if scale == :log10 "log" else "-" end end -function get_plot_html(plt::Plot{PlotlyPackage}) +use_axis_field(ticks) = !(ticks in (nothing, :none)) + +tickssym(isx::Bool) = symbol((isx ? "x" : "y") * "ticks") +limssym(isx::Bool) = symbol((isx ? "x" : "y") * "lims") +flipsym(isx::Bool) = symbol((isx ? "x" : "y") * "flip") +scalesym(isx::Bool) = symbol((isx ? "x" : "y") * "scale") +labelsym(isx::Bool) = symbol((isx ? "x" : "y") * "label") + +function plotlyaxis(d::Dict, isx::Bool) + ax = Dict( + :title => d[labelsym(isx)], + :showgrid => d[:grid], + :zeroline => false, + ) + + fgcolor = webcolor(d[:foreground_color]) + tsym = tickssym(isx) + + if use_axis_field(d[tsym]) + ax[:titlefont] = plotlyfont(d[:guidefont], fgcolor) + ax[:type] = plotlyscale(d[scalesym(isx)]) + ax[:tickfont] = plotlyfont(d[:tickfont], fgcolor) + ax[:tickcolor] = fgcolor + ax[:linecolor] = fgcolor + + # xlims + lims = d[limssym(isx)] + if lims != :auto && limsType(lims) == :limits + ax[:range] = lims + end + + # xflip + if d[flipsym(isx)] + ax[:autorange] = "reversed" + end + + # xticks + ticks = d[tsym] + 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 + ax[:showticklabels] = false + ax[:showgrid] = false + end + + ax +end + +function get_plot_json(plt::Plot{PlotlyPackage}) d = plt.plotargs d_out = Dict() bgcolor = webcolor(d[:background_color]) fgcolor = webcolor(d[:foreground_color]) - # TODO: set the fields for the plot + # set the fields for the plot d_out[:title] = d[:title] - d_out[:titlefont] = plotlyfont(d[:guidefont]) - d_out[:width], d_out[:height] = d[:size] - d_out[:margin] = Dict(:l=>30, :b=>30, :r=>15, :t=>15) - # d_out[:margin] = Dict(:t=>20) - d_out[:paper_bgcolor] = bgcolor + d_out[:titlefont] = plotlyfont(d[:guidefont], fgcolor) + d_out[:margin] = Dict(:l=>35, :b=>30, :r=>8, :t=>20) d_out[:plot_bgcolor] = bgcolor + d_out[:paper_bgcolor] = bgcolor # TODO: x/y axis tick values/labels - # TODO: x/y axis range + d_out[:xaxis] = plotlyaxis(d, true) + d_out[:yaxis] = plotlyaxis(d, false) - d_out[:xaxis] = Dict( - :title => d[:xlabel], - :titlefont => plotlyfont(d[:guidefont]), - :type => plotlyscale(d[:xscale]), - :tickfont => plotlyfont(d[:tickfont]), - :tickcolor => fgcolor, - :linecolor => fgcolor, - :showgrid => d[:grid], - ) - d_out[:yaxis] = Dict( - :title => d[:ylabel], - :titlefont => plotlyfont(d[:guidefont]), - :type => plotlyscale(d[:yscale]), - :tickfont => plotlyfont(d[:tickfont]), - :tickcolor => fgcolor, - :linecolor => fgcolor, - :showgrid => d[:grid], - ) + # # 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] d_out[:legend] = Dict( :bgcolor => bgcolor, :bordercolor => fgcolor, :font => plotlyfont(d[:legendfont]), - # :yanchor => "middle", ) end - # TODO: d_out[:annotations] + # annotations + anns = get(d, :annotation_list, []) + if !isempty(anns) + d_out[:annotations] = [get_annotation_dict(ann...) for ann in anns] + end + # finally build and return the json JSON.json(d_out) end -# _seriesDefaults[:axis] = :left -# _seriesDefaults[:label] = "AUTO" -# _seriesDefaults[:linetype] = :path -# _seriesDefaults[:linestyle] = :solid -# _seriesDefaults[:linewidth] = 1 -# _seriesDefaults[:linecolor] = :auto -# _seriesDefaults[:linealpha] = nothing -# _seriesDefaults[:fillrange] = nothing # ribbons, areas, etc -# _seriesDefaults[:fillcolor] = :match -# _seriesDefaults[:fillalpha] = nothing -# _seriesDefaults[:markershape] = :none -# _seriesDefaults[:markercolor] = :match -# _seriesDefaults[:markeralpha] = nothing -# _seriesDefaults[:markersize] = 6 -# _seriesDefaults[:markerstrokestyle] = :solid -# _seriesDefaults[:markerstrokewidth] = 1 -# _seriesDefaults[:markerstrokecolor] = :match -# _seriesDefaults[:markerstrokealpha] = nothing -# _seriesDefaults[:nbins] = 30 # number of bins for heatmaps and hists -# _seriesDefaults[:smooth] = false # regression line? -# _seriesDefaults[:group] = nothing # groupby vector -# _seriesDefaults[:annotation] = nothing # annotation tuple(s)... (x,y,annotation) -# _seriesDefaults[:x] = nothing -# _seriesDefaults[:y] = nothing -# _seriesDefaults[:z] = nothing # depth for contour, surface, etc -# _seriesDefaults[:zcolor] = nothing # value for color scale -# _seriesDefaults[:surface] = nothing -# _seriesDefaults[:nlevels] = 15 - -# supportedTypes(::PyPlotPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, -# :scatter, :heatmap, :hexbin, :hist, :density, :bar, -# :hline, :vline, :contour, :path3d, :scatter3d] function plotly_colorscale(grad::ColorGradient) [[grad.values[i], webcolor(grad.colors[i])] for i in 1:length(grad.colors)] @@ -186,20 +299,20 @@ end plotly_colorscale(c) = plotly_colorscale(ColorGradient(:bluesreds)) const _plotly_markers = Dict( - :rect => "square", - :xcross => "x", - :utriangle => "triangle-up", - :dtriangle => "triangle-down", - :star5 => "star-triangle-up", + :rect => "square", + :xcross => "x", + :utriangle => "triangle-up", + :dtriangle => "triangle-down", + :star5 => "star-triangle-up", + :vline => "line-ns", + :hline => "line-ew", ) # get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict) -function get_series_html(d::Dict) +function get_series_json(d::Dict; plot_index = nothing) d_out = Dict() x, y = collect(d[:x]), collect(d[:y]) - # d_out[:x] = collect(d[:x]) - # d_out[:y] = collect(d[:y]) d_out[:name] = d[:label] lt = d[:linetype] @@ -247,8 +360,8 @@ function get_series_html(d::Dict) d_out[:histnorm] = "probability density" end - elseif lt in (:contour, :surface) - d_out[:type] = string(lt) + elseif lt in (:contour, :surface, :wireframe) + d_out[:type] = lt == :wireframe ? :surface : string(lt) d_out[:x], d_out[:y] = x, y d_out[:z] = d[:z].surf # d_out[:showscale] = d[:legend] @@ -256,7 +369,7 @@ function get_series_html(d::Dict) d_out[:ncontours] = d[:nlevels] d_out[:contours] = Dict(:coloring => d[:fillrange] != nothing ? "fill" : "lines") end - d_out[:colorscale] = plotly_colorscale(d[:linecolor]) + d_out[:colorscale] = plotly_colorscale(d[lt == :contour ? :linecolor : :fillcolor]) elseif lt == :pie d_out[:type] = "pie" @@ -275,7 +388,8 @@ function get_series_html(d::Dict) d_out[:z] = collect(d[:z]) else - error("Plotly: linetype $lt isn't supported.") + warn("Plotly: linetype $lt isn't supported.") + return Dict() end # add "marker" @@ -313,49 +427,95 @@ function get_series_html(d::Dict) ) end + # # for subplots, we need to add the xaxis/yaxis fields + # if plot_index != nothing + # d_out[:xaxis] = "x$(plot_index)" + # d_out[:yaxis] = "y$(plot_index)" + # end + d_out end # get a list of dictionaries, each representing the series params -function get_series_html(plt::Plot{PlotlyPackage}) - JSON.json(map(get_series_html, plt.seriesargs)) +function get_series_json(plt::Plot{PlotlyPackage}) + JSON.json(map(get_series_json, 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)) + end + end + JSON.json(ds) end # ---------------------------------------------------------------- -function html_head(plt::Plot{PlotlyPackage}) +function html_head(plt::PlottingObject{PlotlyPackage}) "" end -function html_body(plt::Plot{PlotlyPackage}) - w, h = plt.plotargs[:size] +function html_body(plt::Plot{PlotlyPackage}, style = nothing) + if style == nothing + w, h = plt.plotargs[:size] + style = "width:$(w)px;height:$(h)px;" + end + uuid = Base.Random.uuid4() """ -
+
""" end + +function html_body(subplt::Subplot{PlotlyPackage}) + w, h = subplt.plts[1].plotargs[:size] + html = ["
"] + nr = nrows(subplt.layout) + ph = h / nr + + for r in 1:nr + push!(html, "
") + + nc = ncols(subplt.layout, r) + pw = w / nc + + for c in 1:nc + plt = subplt[r,c] + push!(html, html_body(plt, "float:left; width:$(pw)px; height:$(ph)px;")) + end + + push!(html, "
") + end + push!(html, "
") + + join(html) +end + + # ---------------------------------------------------------------- function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{PlotlyPackage}) + isijulia() && return # TODO: write a png to io - println("png") + println("todo: png") end function Base.writemime(io::IO, ::MIME"text/html", plt::PlottingObject{PlotlyPackage}) - println("html") - html_head(plt) * html_body(plt) + write(io, html_head(plt) * html_body(plt)) end -function Base.display(::PlotsDisplay, plt::Plot{PlotlyPackage}) +function Base.display(::PlotsDisplay, plt::PlottingObject{PlotlyPackage}) standalone_html_window(plt) end -function Base.display(::PlotsDisplay, plt::Subplot{PlotlyPackage}) - # TODO: display/show the subplot -end +# function Base.display(::PlotsDisplay, plt::Subplot{PlotlyPackage}) +# # TODO: display/show the subplot +# end diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 15cc094a..d433eb49 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -121,6 +121,11 @@ getAxis(plt::Plot{PyPlotPackage}, axis::Symbol) = (axis == :right ? getRightAxis # left axis is PyPlot., right axis is "f.axes[0].twinx()." function getPyPlotFunction(plt::Plot, axis::Symbol, linetype::Symbol) + # # need to access mplot3d functions differently + # if linetype == :surface + # return mplot3d.pymember("Axes3D")[:plot_surface] + # end + # in the 2-axis case we need to get: [:] ax = getAxis(plt, axis) # ax[:set_ylabel](plt.plotargs[:yrightlabel]) @@ -134,6 +139,9 @@ function getPyPlotFunction(plt::Plot, axis::Symbol, linetype::Symbol) :scatter => :scatter, :contour => :contour, :scatter3d => :scatter, + :surface => :plot_surface, + :wireframe => :plot_wireframe, + # :surface => pycolors.pymember("LinearSegmentedColormap")[:from_list] ) return ax[get(fmap, linetype, :plot)] end @@ -269,6 +277,15 @@ function _add_series(pkg::PyPlotPackage, plt::Plot; kw...) extra_kwargs[:linestyles] = getPyPlotLineStyle(lt, d[:linestyle]) # TODO: will need to call contourf to fill in the contours + elseif lt in (:surface, :wireframe) + if lt == :surface + extra_kwargs[:cmap] = getPyPlotColorMap(d[:fillcolor], d[:fillalpha]) + end + extra_kwargs[:rstride] = 1 + extra_kwargs[:cstride] = 1 + extra_kwargs[:linewidth] = d[:linewidth] + extra_kwargs[:edgecolor] = getPyPlotColor(d[:linecolor], d[:linealpha]) + else extra_kwargs[:linestyle] = getPyPlotLineStyle(lt, d[:linestyle]) @@ -304,7 +321,7 @@ function _add_series(pkg::PyPlotPackage, plt::Plot; kw...) # end # set these for all types - if lt != :contour + if !(lt in (:contour,:surface,:wireframe)) if !(lt in (:scatter, :scatter3d)) extra_kwargs[:color] = color extra_kwargs[:linewidth] = d[:linewidth] @@ -326,6 +343,8 @@ function _add_series(pkg::PyPlotPackage, plt::Plot; kw...) handle = ax[:contourf](x, y, surf, d[:nlevels]; cmap = getPyPlotColorMap(d[:fillcolor], d[:fillalpha])) 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...) elseif lt in _3dTypes plotfunc(d[:x], d[:y], d[:z]; extra_kwargs...) elseif lt in (:scatter, :heatmap, :hexbin) @@ -504,7 +523,7 @@ end function applyPyPlotScale(ax, scaleType::Symbol, isx::Bool) func = ax[isx ? :set_xscale : :set_yscale] scaleType == :identity && return func("linear") - scaleType == :log && return func("log", basex = e, basey = e) + scaleType == :ln && return func("log", basex = e, basey = e) scaleType == :log2 && return func("log", basex = 2, basey = 2) scaleType == :log10 && return func("log", basex = 10, basey = 10) warn("Unhandled scaleType: ", scaleType) diff --git a/src/backends/supported.jl b/src/backends/supported.jl index c166be53..70253e10 100644 --- a/src/backends/supported.jl +++ b/src/backends/supported.jl @@ -82,7 +82,7 @@ supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppre, :steppost, :st :hline, :vline, :contour] supportedStyles(::GadflyPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] supportedMarkers(::GadflyPackage) = vcat(_allMarkers, Shape) -supportedScales(::GadflyPackage) = [:identity, :log, :log2, :log10, :asinh, :sqrt] +supportedScales(::GadflyPackage) = [:identity, :ln, :log2, :log10, :asinh, :sqrt] subplotSupported(::GadflyPackage) = true @@ -162,11 +162,11 @@ supportedArgs(::PyPlotPackage) = [ supportedAxes(::PyPlotPackage) = _allAxes supportedTypes(::PyPlotPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :density, :bar, - :hline, :vline, :contour, :path3d, :scatter3d] + :hline, :vline, :contour, :path3d, :scatter3d, :surface, :wireframe] supportedStyles(::PyPlotPackage) = [:auto, :solid, :dash, :dot, :dashdot] # supportedMarkers(::PyPlotPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :hexagon] supportedMarkers(::PyPlotPackage) = vcat(_allMarkers, Shape) -supportedScales(::PyPlotPackage) = [:identity, :log, :log2, :log10] +supportedScales(::PyPlotPackage) = [:identity, :ln, :log2, :log10] subplotSupported(::PyPlotPackage) = true @@ -419,14 +419,14 @@ supportedAxes(::BokehPackage) = [:auto, :left] supportedTypes(::BokehPackage) = [:none, :path, :scatter] #,:steppre, :steppost, :sticks, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour] supportedStyles(::BokehPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] supportedMarkers(::BokehPackage) = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5] #vcat(_allMarkers, Shape) -supportedScales(::BokehPackage) = [:identity, :log] #, :log, :log2, :log10, :asinh, :sqrt] +supportedScales(::BokehPackage) = [:identity, :ln] #, :ln, :log2, :log10, :asinh, :sqrt] subplotSupported(::BokehPackage) = false # -------------------------------------------------------------------------------------- supportedArgs(::PlotlyPackage) = [ - # :annotation, + :annotation, # :axis, :background_color, :color_palette, @@ -436,7 +436,7 @@ supportedArgs(::PlotlyPackage) = [ :foreground_color, :group, :label, - # :layout, + :layout, :legend, :linecolor, :linestyle, @@ -450,29 +450,29 @@ supportedArgs(::PlotlyPackage) = [ :markerstrokewidth, :markerstrokecolor, :markerstrokestyle, - # :n, + :n, :nbins, - # :nc, - # :nr, + :nc, + :nr, # :pos, # :smooth, - # :show, + :show, :size, :title, :windowtitle, :x, :xlabel, - # :xlims, - # :xticks, + :xlims, + :xticks, :y, :ylabel, - # :ylims, + :ylims, # :yrightlabel, - # :yticks, + :yticks, :xscale, :yscale, - # :xflip, - # :yflip, + :xflip, + :yflip, :z, :zcolor, :tickfont, @@ -482,13 +482,13 @@ supportedArgs(::PlotlyPackage) = [ :nlevels, ] supportedAxes(::PlotlyPackage) = [:auto, :left] -supportedTypes(::PlotlyPackage) = [:none, :path, :scatter, :steppre, :steppost, +supportedTypes(::PlotlyPackage) = [:none, :line, :path, :scatter, :steppre, :steppost, :heatmap, :hist, :density, :bar, :contour, :surface, :path3d, :scatter3d, :pie] #,, :sticks, :hexbin, :hline, :vline] supportedStyles(::PlotlyPackage) = [:auto, :solid, :dash, :dot, :dashdot] supportedMarkers(::PlotlyPackage) = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, - :pentagon, :hexagon, :octagon] #vcat(_allMarkers, Shape) -supportedScales(::PlotlyPackage) = [:identity, :log] #, :log, :log2, :log10, :asinh, :sqrt] -subplotSupported(::PlotlyPackage) = false + :pentagon, :hexagon, :octagon, :vline, :hline] #vcat(_allMarkers, Shape) +supportedScales(::PlotlyPackage) = [:identity, :log10] #, :ln, :log2, :log10, :asinh, :sqrt] +subplotSupported(::PlotlyPackage) = true stringsSupported(::PlotlyPackage) = true diff --git a/src/backends/template.jl b/src/backends/template.jl index 0c96cde1..450f264f 100644 --- a/src/backends/template.jl +++ b/src/backends/template.jl @@ -55,7 +55,7 @@ end # ---------------------------------------------------------------- -function _create_subplot(subplt::Subplot{[PkgName]Package}) +function _create_subplot(subplt::Subplot{[PkgName]Package}, isbefore::Bool) # TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example end diff --git a/src/colors.jl b/src/colors.jl index 0799e4a7..4e5a9195 100644 --- a/src/colors.jl +++ b/src/colors.jl @@ -335,6 +335,7 @@ function webcolor(c::TransparentColor) @sprintf("rgba(%d, %d, %d, %1.3f)", [make255(f(c)) for f in [red,green,blue]]..., alpha(c)) end webcolor(cs::ColorScheme) = webcolor(getColor(cs)) +webcolor(c) = webcolor(convertColor(c)) webcolor(c, α) = webcolor(convertColor(getColor(c), α)) # ---------------------------------------------------------------------------------- diff --git a/src/components.jl b/src/components.jl index 8eedaa57..f1b7114b 100644 --- a/src/components.jl +++ b/src/components.jl @@ -54,17 +54,19 @@ end const _shapes = @compat Dict( - :ellipse => makeshape(20), - :rect => makeshape(4, offset=-0.25), - :diamond => makeshape(4), - :utriangle => makeshape(3), - :dtriangle => makeshape(3, offset=0.5), - :pentagon => makeshape(5), - :hexagon => makeshape(6), - :heptagon => makeshape(7), - :octagon => makeshape(8), - :cross => makecross(offset=-0.25), - :xcross => makecross(), + :ellipse => makeshape(20), + :rect => makeshape(4, offset=-0.25), + :diamond => makeshape(4), + :utriangle => makeshape(3), + :dtriangle => makeshape(3, offset=0.5), + :pentagon => makeshape(5), + :hexagon => makeshape(6), + :heptagon => makeshape(7), + :octagon => makeshape(8), + :cross => makecross(offset=-0.25), + :xcross => makecross(), + :vline => Shape([(0,1),(0,-1)]), + :hline => Shape([(1,0),(-1,0)]), ) for n in [4,5,6,7,8] @@ -227,6 +229,8 @@ immutable Surface{M<:AMat} surf::M end +Surface(f::Function, x, y) = Surface(Float64[f(xi,yi) for xi in x, yi in y]) + # ----------------------------------------------------------------------- type OHLC{T<:Real} diff --git a/src/plot.jl b/src/plot.jl index e344abef..ea4e67f7 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -382,7 +382,7 @@ function createKWargsList{T<:Real}(plt::PlottingObject, x::AVec, y::AVec, zmat:: # surf = Array(Any,1,1) # surf[1,1] = convert(Matrix{Float64}, zmat) d = Dict(kw) - if !(get(d, :linetype, :none) in (:contour, :surface)) + if !(get(d, :linetype, :none) in (:contour, :surface, :wireframe)) d[:linetype] = :contour end createKWargsList(plt, x, y; d..., z = surf) @@ -392,6 +392,10 @@ 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 +function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, surf::Surface; kw...) + createKWargsList(plt, x, y, convert(Matrix{Float64}, surf.surf); kw...) +end + function createKWargsList(plt::PlottingObject, f::FuncOrFuncs; kw...) error("Can't pass a Function or Vector{Function} for y without also passing x") end diff --git a/src/plotter.jl b/src/plotter.jl index a5c22aec..20176fdb 100644 --- a/src/plotter.jl +++ b/src/plotter.jl @@ -98,41 +98,6 @@ CurrentBackend(sym::Symbol) = CurrentBackend(sym, backendInstance(sym)) # --------------------------------------------------------- -# function pickDefaultBackend() -# try -# if Pkg.installed("PyPlot") != nothing -# return CurrentBackend(:pyplot) -# end -# end -# try -# if Pkg.installed("Immerse") != nothing -# return CurrentBackend(:immerse) -# end -# end -# try -# if Pkg.installed("Qwt") != nothing -# return CurrentBackend(:qwt) -# end -# end -# try -# if Pkg.installed("Gadfly") != nothing -# return CurrentBackend(:gadfly) -# end -# end -# try -# if Pkg.installed("UnicodePlots") != nothing -# return CurrentBackend(:unicodeplots) -# end -# end -# try -# if Pkg.installed("Bokeh") != nothing -# return CurrentBackend(:bokeh) -# end -# end -# # warn("You don't have any of the supported backends installed! Chose from ", backends()) -# return CurrentBackend(:plotly) -# end - function pickDefaultBackend() for pkgstr in ("PyPlot", "Immerse", "Qwt", "Gadfly", "UnicodePlots", "Bokeh") if Pkg.installed(pkgstr) != nothing @@ -238,13 +203,31 @@ function backend() elseif currentBackendSymbol == :plotly try - # @eval include(joinpath(Pkg.dir("Plots"), "src", "backends", "web.jl")) - # @eval include(joinpath(Pkg.dir("Plots"), "src", "backends", "plotly.jl")) @eval begin import JSON JSON._print(io::IO, state::JSON.State, dt::Union{Date,DateTime}) = print(io, '"', dt, '"') - # JSON.json(dt::Union{Date,DateTime}) = string(dt) - # JSON.json{D<:Union{Date,DateTime}}(dts::AVec{D}) = map(string, dts) + + ############################ + # borrowed from https://github.com/spencerlyon2/Plotlyjs.jl/blob/master/src/display.jl + _js_path = joinpath(Pkg.dir("Plots"), "deps", "plotly-latest.min.js") + + # if we're in IJulia call setupnotebook to load js and css + if isijulia() + # the first script is some hack I needed to do in order for the notebook + # to not complain about Plotly being undefined + display("text/html", """ + + + """) + # display("text/html", "

Plotly javascript loaded.

") + end + # end borrowing (thanks :) + ########################### + end catch err warn("Couldn't setup Plotly") diff --git a/src/recipes.jl b/src/recipes.jl index d4481ab8..44ba5d85 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -17,6 +17,8 @@ plot!(plt::Plot, recipe::PlotRecipe, args...; kw...) = plot!(getRecipeXY(recipe) num_series(x::AMat) = size(x,2) num_series(x) = 1 +_apply_recipe(d::Dict; kw...) = () + # if it's not a recipe, just do nothing and return the args function _apply_recipe(d::Dict, args...; issubplot=false, kw...) if issubplot && !haskey(d, :n) && !haskey(d, :layout) diff --git a/src/subplot.jl b/src/subplot.jl index c668fc81..dee0a7cd 100644 --- a/src/subplot.jl +++ b/src/subplot.jl @@ -183,7 +183,7 @@ function subplot(args...; kw...) # create the object and do the plotting subplt = Subplot(nothing, plts, pkg, length(layout), 0, layout, d, false, false, false, (r,c) -> (nothing,nothing)) - subplot!(subplt, args...; kw...) + subplot!(subplt, args...; d...) subplt end diff --git a/src/utils.jl b/src/utils.jl index f253318b..167910b4 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -188,6 +188,7 @@ function fakedata(sz...) y end +isijulia() = isdefined(Main, :IJulia) && Main.IJulia.inited # ticksType{T<:Real,S<:Real}(ticks::@compat(Tuple{T,S})) = :limits