getting plotly/plotlyjs up to speed

This commit is contained in:
Thomas Breloff 2016-06-12 21:03:11 -04:00
parent 36a29357a3
commit 80e53adbd8
3 changed files with 68 additions and 168 deletions

View File

@ -756,7 +756,7 @@ function warnOnUnsupported_scales(pkg::AbstractBackend, d::KW)
v = d[k] v = d[k]
v = get(_scaleAliases, v, v) v = get(_scaleAliases, v, v)
if !(v in supported_scales(pkg)) if !(v in supported_scales(pkg))
warn("scale $(d[k]) is unsupported with $pkg. Choose from: $(supported_scales(pkg))") Base.warn_once("scale $(d[k]) is unsupported with $pkg. Choose from: $(supported_scales(pkg))")
end end
end end
end end

View File

@ -2,11 +2,13 @@
# https://plot.ly/javascript/getting-started # https://plot.ly/javascript/getting-started
supported_args(::PlotlyBackend) = [ supported_args(::PlotlyBackend) = [
:annotations, :annotations, :color_palette,
:background_color, :foreground_color, :color_palette, :background_color,
# :background_color_legend, :background_color_inside, :background_color_outside, :background_color_legend, :background_color_inside, :background_color_outside,
# :foreground_color_legend, :foreground_color_grid, :foreground_color_axis, :foreground_color,
# :foreground_color_text, :foreground_color_border, :foreground_color_legend, :foreground_color_guide,
# :foreground_color_grid, :foreground_color_axis,
:foreground_color_text, :foreground_color_border,
:group, :group,
:label, :label,
:seriestype, :seriestype,
@ -16,8 +18,7 @@ supported_args(::PlotlyBackend) = [
:markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :markerstrokewidth, :markerstrokecolor, :markerstrokealpha,
:fillrange, :fillcolor, :fillalpha, :fillrange, :fillcolor, :fillalpha,
:bins, :bins,
:n, :nc, :nr, :layout, :layout,
# :smooth,
:title, :window_title, :show, :size, :title, :window_title, :show, :size,
:x, :xguide, :xlims, :xticks, :xscale, :xflip, :xrotation, :x, :xguide, :xlims, :xticks, :xscale, :xflip, :xrotation,
:y, :yguide, :ylims, :yticks, :yscale, :yflip, :yrotation, :y, :yguide, :ylims, :yticks, :yscale, :yflip, :yrotation,
@ -31,16 +32,19 @@ supported_args(::PlotlyBackend) = [
:orientation, :orientation,
# :overwrite_figure, # :overwrite_figure,
:polar, :polar,
# :normalize, :weights, :contours, :aspect_ratio :normalize, :weights,
# :contours, :aspect_ratio
] ]
supported_types(::PlotlyBackend) = [:none, :line, :path, :scatter, :steppre, :steppost, supported_types(::PlotlyBackend) = [
:histogram2d, :histogram, :density, :bar, :path, :scatter, :bar, :pie, :heatmap,
:contour, :surface, :path3d, :scatter3d, :contour, :surface, :path3d, :scatter3d
:pie, :heatmap] ]
supported_styles(::PlotlyBackend) = [:auto, :solid, :dash, :dot, :dashdot] supported_styles(::PlotlyBackend) = [:auto, :solid, :dash, :dot, :dashdot]
supported_markers(::PlotlyBackend) = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, supported_markers(::PlotlyBackend) = [
:pentagon, :hexagon, :octagon, :vline, :hline] :none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle,
:cross, :xcross, :pentagon, :hexagon, :octagon, :vline, :hline
]
supported_scales(::PlotlyBackend) = [:identity, :log10] supported_scales(::PlotlyBackend) = [:identity, :log10]
is_subplot_supported(::PlotlyBackend) = true is_subplot_supported(::PlotlyBackend) = true
is_string_supported(::PlotlyBackend) = true is_string_supported(::PlotlyBackend) = true
@ -85,7 +89,7 @@ end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
function plotlyfont(font::Font, color = font.color) function plotly_font(font::Font, color = font.color)
KW( KW(
:family => font.family, :family => font.family,
:size => round(Int, font.pointsize*1.4), :size => round(Int, font.pointsize*1.4),
@ -93,7 +97,7 @@ function plotlyfont(font::Font, color = font.color)
) )
end end
function get_annotation_dict(x, y, val) function plotly_annotation_dict(x, y, val)
KW( KW(
:text => val, :text => val,
:xref => "x", :xref => "x",
@ -104,9 +108,9 @@ function get_annotation_dict(x, y, val)
) )
end end
function get_annotation_dict(x, y, ptxt::PlotText) function plotly_annotation_dict(x, y, ptxt::PlotText)
merge(get_annotation_dict(x, y, ptxt.str), KW( merge(plotly_annotation_dict(x, y, ptxt.str), KW(
:font => plotlyfont(ptxt.font), :font => plotly_font(ptxt.font),
:xanchor => ptxt.font.halign == :hcenter ? :center : ptxt.font.halign, :xanchor => ptxt.font.halign == :hcenter ? :center : ptxt.font.halign,
:yanchor => ptxt.font.valign == :vcenter ? :middle : ptxt.font.valign, :yanchor => ptxt.font.valign == :vcenter ? :middle : ptxt.font.valign,
:rotation => ptxt.font.rotation, :rotation => ptxt.font.rotation,
@ -136,7 +140,7 @@ end
# ) # )
# end # end
function plotlyscale(scale::Symbol) function plotly_scale(scale::Symbol)
if scale == :log10 if scale == :log10
"log" "log"
else else
@ -144,8 +148,6 @@ function plotlyscale(scale::Symbol)
end end
end end
use_axis_field(ticks) = !(ticks in (nothing, :none))
# this method gets the start/end in percentage of the canvas for this axis direction # this method gets the start/end in percentage of the canvas for this axis direction
function plotly_domain(sp::Subplot, letter) function plotly_domain(sp::Subplot, letter)
figw, figh = sp.plt[:size] figw, figh = sp.plt[:size]
@ -157,19 +159,12 @@ end
function plotly_axis(axis::Axis, sp::Subplot) function plotly_axis(axis::Axis, sp::Subplot)
letter = axis[:letter] letter = axis[:letter]
# d = axis.d
ax = KW( ax = KW(
:title => axis[:guide], :title => axis[:guide],
:showgrid => sp[:grid], :showgrid => sp[:grid],
:zeroline => false, :zeroline => false,
) )
# fgcolor = webcolor(axis[:foreground_color])
# tsym = tickssym(letter)
# spidx = sp[:subplot_index]
# d_out[:xaxis] = "x$spidx"
# d_out[:yaxis] = "y$spidx"
if letter in (:x,:y) if letter in (:x,:y)
ax[:domain] = plotly_domain(sp, letter) ax[:domain] = plotly_domain(sp, letter)
ax[:anchor] = "$(letter==:x ? :y : :x)$(plotly_subplot_index(sp))" ax[:anchor] = "$(letter==:x ? :y : :x)$(plotly_subplot_index(sp))"
@ -180,10 +175,10 @@ function plotly_axis(axis::Axis, sp::Subplot)
ax[:tickangle] = rot ax[:tickangle] = rot
end end
if use_axis_field(axis[:ticks]) if !(axis[:ticks] in (nothing, :none))
ax[:titlefont] = plotlyfont(axis[:guidefont], webcolor(axis[:foreground_color_guide])) ax[:titlefont] = plotly_font(axis[:guidefont], axis[:foreground_color_guide])
ax[:type] = plotlyscale(axis[:scale]) ax[:type] = plotly_scale(axis[:scale])
ax[:tickfont] = plotlyfont(axis[:tickfont], webcolor(axis[:foreground_color_text])) ax[:tickfont] = plotly_font(axis[:tickfont], axis[:foreground_color_text])
ax[:tickcolor] = webcolor(axis[:foreground_color_border]) ax[:tickcolor] = webcolor(axis[:foreground_color_border])
ax[:linecolor] = webcolor(axis[:foreground_color_border]) ax[:linecolor] = webcolor(axis[:foreground_color_border])
@ -239,7 +234,7 @@ function plotly_layout(plt::Plot)
# set the fields for the plot # set the fields for the plot
d_out[:title] = sp[:title] d_out[:title] = sp[:title]
d_out[:titlefont] = plotlyfont(sp[:titlefont], webcolor(sp[:foreground_color_title])) d_out[:titlefont] = plotly_font(sp[:titlefont], sp[:foreground_color_title])
# # TODO: use subplot positioning logic # # TODO: use subplot positioning logic
# d_out[:margin] = KW(:l=>35, :b=>30, :r=>8, :t=>20) # d_out[:margin] = KW(:l=>35, :b=>30, :r=>8, :t=>20)
@ -267,17 +262,12 @@ function plotly_layout(plt::Plot)
d_out[:legend] = KW( d_out[:legend] = KW(
:bgcolor => webcolor(sp[:background_color_legend]), :bgcolor => webcolor(sp[:background_color_legend]),
:bordercolor => webcolor(sp[:foreground_color_legend]), :bordercolor => webcolor(sp[:foreground_color_legend]),
:font => plotlyfont(sp[:legendfont]), :font => plotly_font(sp[:legendfont], sp[:foreground_color_legend]),
) )
end end
# annotations # annotations
anns = sp[:annotations] d_out[:annotations] = KW[plotly_annotation_dict(ann...) for ann in sp[:annotations]]
d_out[:annotations] = if isempty(anns)
KW[]
else
KW[get_annotation_dict(ann...) for ann in anns]
end
# # arrows # # arrows
# for sargs in seriesargs # for sargs in seriesargs
@ -346,7 +336,7 @@ function plotly_series(plt::Plot, series::Series)
hasline = !isscatter hasline = !isscatter
# set the "type" # set the "type"
if st in (:line, :path, :scatter, :steppre, :steppost) if st in (:path, :scatter)
d_out[:type] = "scatter" d_out[:type] = "scatter"
d_out[:mode] = if hasmarker d_out[:mode] = if hasmarker
hasline ? "lines+markers" : "markers" hasline ? "lines+markers" : "markers"
@ -364,39 +354,36 @@ function plotly_series(plt::Plot, series::Series)
elseif st == :bar elseif st == :bar
d_out[:type] = "bar" d_out[:type] = "bar"
d_out[:x], d_out[:y] = x, y d_out[:x], d_out[:y] = x, y
d_out[:orientation] = isvertical(d) ? "v" : "h"
elseif st == :histogram2d # elseif st == :histogram2d
d_out[:type] = "histogram2d" # d_out[:type] = "histogram2d"
d_out[:x], d_out[:y] = x, y # d_out[:x], d_out[:y] = x, y
if isa(d[:bins], Tuple) # if isa(d[:bins], Tuple)
xbins, ybins = d[:bins] # xbins, ybins = d[:bins]
else # else
xbins = ybins = d[:bins] # xbins = ybins = d[:bins]
end # end
d_out[:nbinsx] = xbins # d_out[:nbinsx] = xbins
d_out[:nbinsy] = ybins # d_out[:nbinsy] = ybins
d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha]) # d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha])
elseif st in (:histogram, :density) # elseif st in (:histogram, :density)
d_out[:type] = "histogram" # d_out[:type] = "histogram"
isvert = isvertical(d) # isvert = isvertical(d)
d_out[isvert ? :x : :y] = y # d_out[isvert ? :x : :y] = y
d_out[isvert ? :nbinsx : :nbinsy] = d[:bins] # d_out[isvert ? :nbinsx : :nbinsy] = d[:bins]
if st == :density # if st == :density
d_out[:histogramnorm] = "probability density" # d_out[:histogramnorm] = "probability density"
end # end
elseif st == :heatmap elseif st == :heatmap
d_out[:type] = "heatmap" d_out[:type] = "heatmap"
# d_out[:x], d_out[:y] = x, y
# d_out[:z] = d[:z].surf
d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false) d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false)
d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha]) d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha])
elseif st == :contour elseif st == :contour
d_out[:type] = "contour" d_out[:type] = "contour"
# d_out[:x], d_out[:y] = x, y
# d_out[:z] = d[:z].surf
d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false) d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false)
# d_out[:showscale] = d[:colorbar] != :none # d_out[:showscale] = d[:colorbar] != :none
d_out[:ncontours] = d[:levels] d_out[:ncontours] = d[:levels]
@ -405,8 +392,6 @@ function plotly_series(plt::Plot, series::Series)
elseif st in (:surface, :wireframe) elseif st in (:surface, :wireframe)
d_out[:type] = "surface" d_out[:type] = "surface"
# d_out[:x], d_out[:y] = x, y
# d_out[:z] = d[:z].surf
d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false) d_out[:x], d_out[:y], d_out[:z] = d[:x], d[:y], transpose_z(d, d[:z].surf, false)
d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha]) d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha])
@ -527,7 +512,6 @@ function _writemime(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyBackend})
write(io, html_head(plt) * html_body(plt)) write(io, html_head(plt) * html_body(plt))
end end
# function Base.display(::PlotsDisplay, plt::Plot{PlotlyBackend})
function _display(plt::Plot{PlotlyBackend}) function _display(plt::Plot{PlotlyBackend})
standalone_html_window(plt) standalone_html_window(plt)
end end

View File

@ -1,76 +1,10 @@
# https://github.com/spencerlyon2/PlotlyJS.jl # https://github.com/spencerlyon2/PlotlyJS.jl
supported_args(::PlotlyJSBackend) = [ supported_args(::PlotlyJSBackend) = supported_args(PlotlyBackend())
:annotation, supported_types(::PlotlyJSBackend) = supported_types(PlotlyBackend())
# :axis, supported_styles(::PlotlyJSBackend) = supported_styles(PlotlyBackend())
:background_color, supported_markers(::PlotlyJSBackend) = supported_markers(PlotlyBackend())
:color_palette,
:fillrange,
:fillcolor,
:fillalpha,
:foreground_color,
:group,
:label,
:layout,
:legend,
:seriescolor, :seriesalpha,
:linecolor,
:linestyle,
:seriestype,
:linewidth,
:linealpha,
:markershape,
:markercolor,
:markersize,
:markeralpha,
:markerstrokewidth,
:markerstrokecolor,
:markerstrokestyle,
:n,
:bins,
:nc,
:nr,
# :pos,
# :smooth,
:show,
:size,
:title,
:window_title,
:x,
:xguide,
:xlims,
:xticks,
:y,
:yguide,
:ylims,
# :yrightlabel,
:yticks,
:xscale,
:yscale,
:xflip,
:yflip,
:z,
:marker_z,
:tickfont,
:guidefont,
:legendfont,
:grid,
:levels,
:xerror,
:yerror,
:ribbon,
:quiver,
:orientation,
:polar,
]
supported_types(::PlotlyJSBackend) = [:none, :line, :path, :scatter, :steppre, :steppost,
:histogram2d, :histogram, :density, :bar, :contour, :surface, :path3d, :scatter3d,
:pie, :heatmap]
supported_styles(::PlotlyJSBackend) = [:auto, :solid, :dash, :dot, :dashdot]
supported_markers(::PlotlyJSBackend) = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross,
:pentagon, :hexagon, :octagon, :vline, :hline]
supported_scales(::PlotlyJSBackend) = [:identity, :log10]
is_subplot_supported(::PlotlyJSBackend) = true is_subplot_supported(::PlotlyJSBackend) = true
is_string_supported(::PlotlyJSBackend) = true is_string_supported(::PlotlyJSBackend) = true
@ -82,30 +16,19 @@ function _initialize_backend(::PlotlyJSBackend; kw...)
export PlotlyJS export PlotlyJS
end end
for (mime, fmt) in PlotlyJS._mimeformats # for (mime, fmt) in PlotlyJS._mimeformats
# mime == "image/png" && continue # don't use plotlyjs's writemime for png # # mime == "image/png" && continue # don't use plotlyjs's writemime for png
@eval Base.writemime(io::IO, m::MIME{Symbol($mime)}, p::Plot{PlotlyJSBackend}) = writemime(io, m, p.o) # @eval Base.writemime(io::IO, m::MIME{Symbol($mime)}, p::Plot{PlotlyJSBackend}) = writemime(io, m, p.o)
end # end
# override IJulia inline display # # override IJulia inline display
if isijulia() # if isijulia()
IJulia.display_dict(plt::AbstractPlot{PlotlyJSBackend}) = IJulia.display_dict(plt.o) # IJulia.display_dict(plt::AbstractPlot{PlotlyJSBackend}) = IJulia.display_dict(plt.o)
end # end
end end
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# function _create_plot(pkg::PlotlyJSBackend, d::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(PlotlyJS.GenericTrace[], PlotlyJS.Layout(),
# # Base.Random.uuid4(), PlotlyJS.ElectronDisplay())
# # T = isijulia() ? PlotlyJS.JupyterPlot : PlotlyJS.ElectronPlot
# # o = T(PlotlyJS.Plot())
# o = PlotlyJS.plot()
#
# Plot(o, pkg, 0, d, KW[])
# end
function _create_backend_figure(plt::Plot{PlotlyJSBackend}) function _create_backend_figure(plt::Plot{PlotlyJSBackend})
PlotlyJS.plot() PlotlyJS.plot()
@ -137,7 +60,6 @@ function _update_plot_object(plt::Plot{PlotlyJSBackend})
pdict = plotly_layout(plt) pdict = plotly_layout(plt)
syncplot = plt.o syncplot = plt.o
w,h = plt[:size] w,h = plt[:size]
# DD(pdict)
PlotlyJS.relayout!(syncplot, pdict, width = w, height = h) PlotlyJS.relayout!(syncplot, pdict, width = w, height = h)
end end
@ -165,14 +87,9 @@ end
# ---------------------------------------------------------------- # ----------------------------------------------------------------
# function _update_min_padding!(sp::Subplot{PlotlyBackend}) function _writemime(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend})
# sp.minpad = plotly_minpad(sp) writemime(io, MIME("text/html"), plt.o)
# end end
# function plotlyjs_finalize(plt::Plot)
# plotly_finalize(plt)
# PlotlyJS.relayout!(plt.o, plotly_layout(plt))
# end
function _writemime(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) function _writemime(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend})
tmpfn = tempname() * "png" tmpfn = tempname() * "png"
@ -181,6 +98,5 @@ function _writemime(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend})
end end
function _display(plt::Plot{PlotlyJSBackend}) function _display(plt::Plot{PlotlyJSBackend})
# plotlyjs_finalize(plt)
display(plt.o) display(plt.o)
end end