diff --git a/src/args.jl b/src/args.jl index 706cbfa5..00f5e4e3 100644 --- a/src/args.jl +++ b/src/args.jl @@ -756,7 +756,7 @@ function warnOnUnsupported_scales(pkg::AbstractBackend, d::KW) v = d[k] v = get(_scaleAliases, v, v) 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 diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index c1fc0811..83861bef 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -2,11 +2,13 @@ # https://plot.ly/javascript/getting-started supported_args(::PlotlyBackend) = [ - :annotations, - :background_color, :foreground_color, :color_palette, - # :background_color_legend, :background_color_inside, :background_color_outside, - # :foreground_color_legend, :foreground_color_grid, :foreground_color_axis, - # :foreground_color_text, :foreground_color_border, + :annotations, :color_palette, + :background_color, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color, + :foreground_color_legend, :foreground_color_guide, + # :foreground_color_grid, :foreground_color_axis, + :foreground_color_text, :foreground_color_border, :group, :label, :seriestype, @@ -16,8 +18,7 @@ supported_args(::PlotlyBackend) = [ :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, :fillrange, :fillcolor, :fillalpha, :bins, - :n, :nc, :nr, :layout, - # :smooth, + :layout, :title, :window_title, :show, :size, :x, :xguide, :xlims, :xticks, :xscale, :xflip, :xrotation, :y, :yguide, :ylims, :yticks, :yscale, :yflip, :yrotation, @@ -31,16 +32,19 @@ supported_args(::PlotlyBackend) = [ :orientation, # :overwrite_figure, :polar, - # :normalize, :weights, :contours, :aspect_ratio + :normalize, :weights, + # :contours, :aspect_ratio ] -supported_types(::PlotlyBackend) = [:none, :line, :path, :scatter, :steppre, :steppost, - :histogram2d, :histogram, :density, :bar, - :contour, :surface, :path3d, :scatter3d, - :pie, :heatmap] +supported_types(::PlotlyBackend) = [ + :path, :scatter, :bar, :pie, :heatmap, + :contour, :surface, :path3d, :scatter3d +] supported_styles(::PlotlyBackend) = [:auto, :solid, :dash, :dot, :dashdot] -supported_markers(::PlotlyBackend) = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, - :pentagon, :hexagon, :octagon, :vline, :hline] +supported_markers(::PlotlyBackend) = [ + :none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, + :cross, :xcross, :pentagon, :hexagon, :octagon, :vline, :hline +] supported_scales(::PlotlyBackend) = [:identity, :log10] is_subplot_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( :family => font.family, :size => round(Int, font.pointsize*1.4), @@ -93,7 +97,7 @@ function plotlyfont(font::Font, color = font.color) ) end -function get_annotation_dict(x, y, val) +function plotly_annotation_dict(x, y, val) KW( :text => val, :xref => "x", @@ -104,9 +108,9 @@ function get_annotation_dict(x, y, val) ) end -function get_annotation_dict(x, y, ptxt::PlotText) - merge(get_annotation_dict(x, y, ptxt.str), KW( - :font => plotlyfont(ptxt.font), +function plotly_annotation_dict(x, y, ptxt::PlotText) + merge(plotly_annotation_dict(x, y, ptxt.str), KW( + :font => plotly_font(ptxt.font), :xanchor => ptxt.font.halign == :hcenter ? :center : ptxt.font.halign, :yanchor => ptxt.font.valign == :vcenter ? :middle : ptxt.font.valign, :rotation => ptxt.font.rotation, @@ -136,7 +140,7 @@ end # ) # end -function plotlyscale(scale::Symbol) +function plotly_scale(scale::Symbol) if scale == :log10 "log" else @@ -144,8 +148,6 @@ function plotlyscale(scale::Symbol) 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 function plotly_domain(sp::Subplot, letter) figw, figh = sp.plt[:size] @@ -157,19 +159,12 @@ end function plotly_axis(axis::Axis, sp::Subplot) letter = axis[:letter] - # d = axis.d ax = KW( :title => axis[:guide], :showgrid => sp[:grid], :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) ax[:domain] = plotly_domain(sp, letter) ax[:anchor] = "$(letter==:x ? :y : :x)$(plotly_subplot_index(sp))" @@ -180,10 +175,10 @@ function plotly_axis(axis::Axis, sp::Subplot) ax[:tickangle] = rot end - if use_axis_field(axis[:ticks]) - ax[:titlefont] = plotlyfont(axis[:guidefont], webcolor(axis[:foreground_color_guide])) - ax[:type] = plotlyscale(axis[:scale]) - ax[:tickfont] = plotlyfont(axis[:tickfont], webcolor(axis[:foreground_color_text])) + if !(axis[:ticks] in (nothing, :none)) + ax[:titlefont] = plotly_font(axis[:guidefont], axis[:foreground_color_guide]) + ax[:type] = plotly_scale(axis[:scale]) + ax[:tickfont] = plotly_font(axis[:tickfont], axis[:foreground_color_text]) ax[:tickcolor] = 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 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 # 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( :bgcolor => webcolor(sp[:background_color_legend]), :bordercolor => webcolor(sp[:foreground_color_legend]), - :font => plotlyfont(sp[:legendfont]), + :font => plotly_font(sp[:legendfont], sp[:foreground_color_legend]), ) end # annotations - anns = sp[:annotations] - d_out[:annotations] = if isempty(anns) - KW[] - else - KW[get_annotation_dict(ann...) for ann in anns] - end + d_out[:annotations] = KW[plotly_annotation_dict(ann...) for ann in sp[:annotations]] # # arrows # for sargs in seriesargs @@ -346,7 +336,7 @@ function plotly_series(plt::Plot, series::Series) hasline = !isscatter # set the "type" - if st in (:line, :path, :scatter, :steppre, :steppost) + if st in (:path, :scatter) d_out[:type] = "scatter" d_out[:mode] = if hasmarker hasline ? "lines+markers" : "markers" @@ -364,39 +354,36 @@ function plotly_series(plt::Plot, series::Series) elseif st == :bar d_out[:type] = "bar" d_out[:x], d_out[:y] = x, y + d_out[:orientation] = isvertical(d) ? "v" : "h" - elseif st == :histogram2d - d_out[:type] = "histogram2d" - d_out[:x], d_out[:y] = x, y - if isa(d[:bins], Tuple) - xbins, ybins = d[:bins] - else - xbins = ybins = d[:bins] - end - d_out[:nbinsx] = xbins - d_out[:nbinsy] = ybins - d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha]) + # elseif st == :histogram2d + # d_out[:type] = "histogram2d" + # d_out[:x], d_out[:y] = x, y + # if isa(d[:bins], Tuple) + # xbins, ybins = d[:bins] + # else + # xbins = ybins = d[:bins] + # end + # d_out[:nbinsx] = xbins + # d_out[:nbinsy] = ybins + # d_out[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha]) - elseif st in (:histogram, :density) - d_out[:type] = "histogram" - isvert = isvertical(d) - d_out[isvert ? :x : :y] = y - d_out[isvert ? :nbinsx : :nbinsy] = d[:bins] - if st == :density - d_out[:histogramnorm] = "probability density" - end + # elseif st in (:histogram, :density) + # d_out[:type] = "histogram" + # isvert = isvertical(d) + # d_out[isvert ? :x : :y] = y + # d_out[isvert ? :nbinsx : :nbinsy] = d[:bins] + # if st == :density + # d_out[:histogramnorm] = "probability density" + # end elseif st == :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[:colorscale] = plotly_colorscale(d[:fillcolor], d[:fillalpha]) elseif st == :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[:showscale] = d[:colorbar] != :none d_out[:ncontours] = d[:levels] @@ -405,8 +392,6 @@ function plotly_series(plt::Plot, series::Series) elseif st in (:surface, :wireframe) 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[: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)) end -# function Base.display(::PlotsDisplay, plt::Plot{PlotlyBackend}) function _display(plt::Plot{PlotlyBackend}) standalone_html_window(plt) end diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index c341232e..10b3e4f6 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -1,76 +1,10 @@ # https://github.com/spencerlyon2/PlotlyJS.jl -supported_args(::PlotlyJSBackend) = [ - :annotation, - # :axis, - :background_color, - :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] +supported_args(::PlotlyJSBackend) = supported_args(PlotlyBackend()) +supported_types(::PlotlyJSBackend) = supported_types(PlotlyBackend()) +supported_styles(::PlotlyJSBackend) = supported_styles(PlotlyBackend()) +supported_markers(::PlotlyJSBackend) = supported_markers(PlotlyBackend()) is_subplot_supported(::PlotlyJSBackend) = true is_string_supported(::PlotlyJSBackend) = true @@ -82,30 +16,19 @@ function _initialize_backend(::PlotlyJSBackend; kw...) export PlotlyJS end - for (mime, fmt) in PlotlyJS._mimeformats - # 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) - end + # for (mime, fmt) in PlotlyJS._mimeformats + # # 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) + # end - # override IJulia inline display - if isijulia() - IJulia.display_dict(plt::AbstractPlot{PlotlyJSBackend}) = IJulia.display_dict(plt.o) - end + # # override IJulia inline display + # if isijulia() + # IJulia.display_dict(plt::AbstractPlot{PlotlyJSBackend}) = IJulia.display_dict(plt.o) + # 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}) PlotlyJS.plot() @@ -137,7 +60,6 @@ function _update_plot_object(plt::Plot{PlotlyJSBackend}) pdict = plotly_layout(plt) syncplot = plt.o w,h = plt[:size] - # DD(pdict) PlotlyJS.relayout!(syncplot, pdict, width = w, height = h) end @@ -165,14 +87,9 @@ end # ---------------------------------------------------------------- -# function _update_min_padding!(sp::Subplot{PlotlyBackend}) -# sp.minpad = plotly_minpad(sp) -# end - -# function plotlyjs_finalize(plt::Plot) -# plotly_finalize(plt) -# PlotlyJS.relayout!(plt.o, plotly_layout(plt)) -# end +function _writemime(io::IO, ::MIME"image/svg+xml", plt::Plot{PlotlyJSBackend}) + writemime(io, MIME("text/html"), plt.o) +end function _writemime(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) tmpfn = tempname() * "png" @@ -181,6 +98,5 @@ function _writemime(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) end function _display(plt::Plot{PlotlyJSBackend}) - # plotlyjs_finalize(plt) display(plt.o) end