From c250d7c073ac1c057e299f46f402a65f84be93ea Mon Sep 17 00:00:00 2001 From: Huckleberry Febbo Date: Thu, 19 Jan 2017 14:45:16 -0500 Subject: [PATCH 001/107] working on fixing pyplot issue for ubuntu --- src/backends/pyplot.jl | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 84ea6718..36d0d5f5 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -56,6 +56,34 @@ function add_backend_string(::PyPlotBackend) Pkg.build("PyPlot") end """ + if !Plots.is_installed("PyPlot") + Pkg.add("PyPlot") + end + withenv("PYTHON" => "") do + Pkg.build("PyPlot") + end + import Conda # TODO since this only known to occur on Ubuntu we could also check the user's OS here + Conda.add("qt=4.8.5") # run the old version of Conda + # TO AVOID: + # 1) Segfault when attempting to run pylplot + # caused by Conda update to Segfault with qt >=4.8.6 on Ubuntu https://github.com/JuliaPy/PyPlot.jl/issues/234 + # 2) precomilation issue after updating Plots.jl + #= + INFO: Recompiling stale cache file /home/febbo/.julia/lib/v0.5/Plots.ji for module Plots. + ERROR: LoadError: Declaring __precompile__(false) is not allowed in files that are being precompiled. + in __precompile__(::Bool) at ./loading.jl:300 + in include_from_node1(::String) at ./loading.jl:488 + in macro expansion; at ./none:2 [inlined] + in anonymous at ./:? + in eval(::Module, ::Any) at ./boot.jl:234 + in process_options(::Base.JLOptions) at ./client.jl:239 + in _start() at ./client.jl:318 + while loading /home/febbo/.julia/v0.5/Plots/src/Plots.jl, in expression starting on line 1 + ERROR: LoadError: Failed to precompile Plots to /home/febbo/.julia/lib/v0.5/Plots.ji. + in compilecache(::String) at ./loading.jl:593 + in require(::Symbol) at ./loading.jl:393 + in include_from_node1(::String) at ./loading.jl:488 + =# end function _initialize_backend(::PyPlotBackend) From cd8939fe0bd69a64f5b9d5d3dd85324304b4c3f3 Mon Sep 17 00:00:00 2001 From: Huckleberry Febbo Date: Thu, 19 Jan 2017 17:32:37 -0500 Subject: [PATCH 002/107] finished fixing segfault issue when qt>v4.8.5 on Ubuntu using pyplot --- src/backends/pyplot.jl | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 36d0d5f5..64ae74bd 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -56,34 +56,6 @@ function add_backend_string(::PyPlotBackend) Pkg.build("PyPlot") end """ - if !Plots.is_installed("PyPlot") - Pkg.add("PyPlot") - end - withenv("PYTHON" => "") do - Pkg.build("PyPlot") - end - import Conda # TODO since this only known to occur on Ubuntu we could also check the user's OS here - Conda.add("qt=4.8.5") # run the old version of Conda - # TO AVOID: - # 1) Segfault when attempting to run pylplot - # caused by Conda update to Segfault with qt >=4.8.6 on Ubuntu https://github.com/JuliaPy/PyPlot.jl/issues/234 - # 2) precomilation issue after updating Plots.jl - #= - INFO: Recompiling stale cache file /home/febbo/.julia/lib/v0.5/Plots.ji for module Plots. - ERROR: LoadError: Declaring __precompile__(false) is not allowed in files that are being precompiled. - in __precompile__(::Bool) at ./loading.jl:300 - in include_from_node1(::String) at ./loading.jl:488 - in macro expansion; at ./none:2 [inlined] - in anonymous at ./:? - in eval(::Module, ::Any) at ./boot.jl:234 - in process_options(::Base.JLOptions) at ./client.jl:239 - in _start() at ./client.jl:318 - while loading /home/febbo/.julia/v0.5/Plots/src/Plots.jl, in expression starting on line 1 - ERROR: LoadError: Failed to precompile Plots to /home/febbo/.julia/lib/v0.5/Plots.ji. - in compilecache(::String) at ./loading.jl:593 - in require(::Symbol) at ./loading.jl:393 - in include_from_node1(::String) at ./loading.jl:488 - =# end function _initialize_backend(::PyPlotBackend) @@ -109,7 +81,18 @@ function _initialize_backend(::PyPlotBackend) const pycollections = PyPlot.pywrap(PyPlot.pyimport("matplotlib.collections")) const pyart3d = PyPlot.pywrap(PyPlot.pyimport("mpl_toolkits.mplot3d.art3d")) end - + if is_linux() + @eval begin + # avoid Conda update that causes Segfault with qt >=4.8.6 on Ubuntu https://github.com/JuliaPy/PyPlot.jl/issues/234 + import Conda + kw = Conda._installed_packages_dict() + if (!haskey(kw,"qt") || (qt_version=get(kw,"qt",0)[1]!=v"4.8.5")) + print("\n Switching to qt v4.8.5!! \n") + Conda.add("qt=4.8.5") + error("\n Please RESTART julia to use qt v4.8.5!! \n If we did not error here, a Segmentation fault error would occur. \n \n") + end + end + end # we don't want every command to update the figure PyPlot.ioff() end From 43a213643bdb268050fbdaf4dcaf5e12b2f84eaa Mon Sep 17 00:00:00 2001 From: Huckleberry Febbo Date: Thu, 19 Jan 2017 18:04:09 -0500 Subject: [PATCH 003/107] changed code so it does not automatically change qt version --- src/backends/pyplot.jl | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 64ae74bd..c02a512f 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -55,6 +55,10 @@ function add_backend_string(::PyPlotBackend) withenv("PYTHON" => "") do Pkg.build("PyPlot") end + import Conda + Conda.add("qt=4.8.5") + + # now restart julia! """ end @@ -87,9 +91,8 @@ function _initialize_backend(::PyPlotBackend) import Conda kw = Conda._installed_packages_dict() if (!haskey(kw,"qt") || (qt_version=get(kw,"qt",0)[1]!=v"4.8.5")) - print("\n Switching to qt v4.8.5!! \n") - Conda.add("qt=4.8.5") - error("\n Please RESTART julia to use qt v4.8.5!! \n If we did not error here, a Segmentation fault error would occur. \n \n") + print("\n If the code has a Segmentation fault error switch to qt v4.8.5 by pasting the following code into julia: \n \n") + add_backend_string(backend()) end end end From 1a91eacdcb784ab778424266db95a9130edc7076 Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Fri, 20 Jan 2017 15:26:54 +0100 Subject: [PATCH 004/107] Enable histogram plotting in pgfplot --- src/backends/pgfplots.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index b42e8629..a1548b5e 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -32,7 +32,7 @@ const _pgfplots_attr = merge_with_base_supported([ :aspect_ratio, # :match_dimensions, ]) -const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour] +const _pgfplots_seriestype = [:path, :path3d, :scatter, :steppre, :stepmid, :steppost, :histogram2d, :ysticks, :xsticks, :contour, :shape] const _pgfplots_style = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] const _pgfplots_marker = [:none, :auto, :circle, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :pentagon] #vcat(_allMarkers, Shape) const _pgfplots_scale = [:identity, :ln, :log2, :log10] @@ -147,7 +147,7 @@ function pgf_series(sp::Subplot, series::Series) push!(style, pgf_linestyle(d)) push!(style, pgf_marker(d)) - if d[:fillrange] != nothing + if d[:fillcolor] != nothing push!(style, pgf_fillstyle(d)) end From 45b5922d015ddcb4ab5f5d75ad53e8483c3602a0 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Fri, 20 Jan 2017 19:07:20 +0100 Subject: [PATCH 005/107] dont rely on postempty, img transpose not necessary anymore --- src/backends/glvisualize.jl | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl index f1e40181..08a32443 100644 --- a/src/backends/glvisualize.jl +++ b/src/backends/glvisualize.jl @@ -1141,8 +1141,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true) vis = gl_bar(d, kw_args) elseif st == :image extract_extrema(d, kw_args) - z = transpose_z(series, d[:z].surf, false) - vis = GL.gl_image(z, kw_args) + vis = GL.gl_image(d[:z].surf, kw_args) elseif st == :boxplot extract_c(d, kw_args, :fill) vis = gl_boxplot(d, kw_args) @@ -1182,7 +1181,7 @@ function _display(plt::Plot{GLVisualizeBackend}, visible = true) if _3d GLAbstraction.center!(sp_screen) end - Reactive.post_empty() + GLAbstraction.post_empty() yield() end end From bcd5d9ef9087cbf9577ce5ff4710b5e56f750045 Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Sun, 22 Jan 2017 16:57:28 +0100 Subject: [PATCH 006/107] Fix issue where every series is plotted with a fillcolor --- src/backends/pgfplots.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index a1548b5e..754ebaa0 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -147,7 +147,7 @@ function pgf_series(sp::Subplot, series::Series) push!(style, pgf_linestyle(d)) push!(style, pgf_marker(d)) - if d[:fillcolor] != nothing + if d[:fillrange] != nothing || st in (:shape,) push!(style, pgf_fillstyle(d)) end From caf86686ddf8e7c190ffbf8ed8ae011fce89d3dd Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Mon, 23 Jan 2017 13:56:40 +0100 Subject: [PATCH 007/107] Fix yshift of subplots. Calculation of coordinate transformation from bb to pgf did not consider the height of the plot. --- src/backends/pgfplots.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index 754ebaa0..9ecc0ae4 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -249,8 +249,12 @@ end function _update_plot_object(plt::Plot{PGFPlotsBackend}) plt.o = PGFPlots.Axis[] + # Obtain the total height of the plot by extracting the maximal bottom + # coordinate from the bounding box. + # TODO: Maybe there is a better way to get the total height of the plot. + total_height = maximum([bottom(bbox(sp)) for sp in plt.subplots]) for sp in plt.subplots - # first build the PGFPlots.Axis object + # first build the PGFPlots.Axis object style = ["unbounded coords=jump"] kw = KW() @@ -268,7 +272,7 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend}) bb = bbox(sp) push!(style, """ xshift = $(left(bb).value)mm, - yshift = $((height(bb) - (bottom(bb))).value)mm, + yshift = $((total_height - (bottom(bb))).value)mm, axis background/.style={fill=$(pgf_color(sp[:background_color_inside])[1])} """) kw[:width] = "$(width(bb).value)mm" From f8b84185acb747cb827aed29ca59bf39825b2e33 Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Mon, 23 Jan 2017 14:28:26 +0100 Subject: [PATCH 008/107] Add rounding and obtain plot height from layout bbox --- src/backends/pgfplots.jl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index 9ecc0ae4..4feb46d0 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -251,8 +251,7 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend}) plt.o = PGFPlots.Axis[] # Obtain the total height of the plot by extracting the maximal bottom # coordinate from the bounding box. - # TODO: Maybe there is a better way to get the total height of the plot. - total_height = maximum([bottom(bbox(sp)) for sp in plt.subplots]) + total_height = bottom(bbox(plt.layout)) for sp in plt.subplots # first build the PGFPlots.Axis object style = ["unbounded coords=jump"] @@ -269,10 +268,12 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend}) # bounding box values are in mm # note: bb origin is top-left, pgf is bottom-left + # A round on 2 decimal places should be enough precision for 300 dpi + # plots. bb = bbox(sp) push!(style, """ xshift = $(left(bb).value)mm, - yshift = $((total_height - (bottom(bb))).value)mm, + yshift = $(round((total_height - (bottom(bb))).value,2))mm, axis background/.style={fill=$(pgf_color(sp[:background_color_inside])[1])} """) kw[:width] = "$(width(bb).value)mm" From fdadfa3a80edf3af58f818e1ae0cbd3446ecc56c Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Tue, 24 Jan 2017 02:42:20 +0100 Subject: [PATCH 009/107] small changes --- src/backends/glvisualize.jl | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl index 08a32443..3d48344b 100644 --- a/src/backends/glvisualize.jl +++ b/src/backends/glvisualize.jl @@ -1,4 +1,4 @@ -``#= +#= TODO * move all gl_ methods to GLPlot * integrate GLPlot UI @@ -7,7 +7,6 @@ TODO * polar plots * labes and axis * fix units in all visuals (e.g dotted lines, marker scale, surfaces) - * why is there so little unicode supported in the font!??!? =# const _glvisualize_attr = merge_with_base_supported([ @@ -134,11 +133,6 @@ function empty_screen!(screen) end nothing end -function poll_reactive() - # run_till_now blocks when message queue is empty! - Base.n_avail(Reactive._messages) > 0 && Reactive.run_till_now() -end - function get_plot_screen(list::Vector, name, result = []) for elem in list From ebf92d30332ea2e5d0ecd3eab83671e77694fc1b Mon Sep 17 00:00:00 2001 From: MA Laforge Date: Mon, 23 Jan 2017 21:25:55 -0500 Subject: [PATCH 010/107] Add support for layout & plot size. Also: Add basic support for polar plots. Add support for plot title & background color of entire figure. --- src/backends/inspectdr.jl | 61 ++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 11 deletions(-) diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl index fea44064..af95c76a 100644 --- a/src/backends/inspectdr.jl +++ b/src/backends/inspectdr.jl @@ -38,7 +38,7 @@ const _inspectdr_attr = merge_with_base_supported([ # :ribbon, :quiver, :arrow, # :orientation, :overwrite_figure, -# :polar, + :polar, # :normalize, :weights, # :contours, :aspect_ratio, :match_dimensions, @@ -66,6 +66,9 @@ const _inspectdr_scale = [:identity, :ln, :log2, :log10] is_marker_supported(::InspectDRBackend, shape::Shape) = true +_inspectdr_to_pixels(bb::BoundingBox) = + InspectDR.BoundingBox(to_pixels(left(bb)), to_pixels(right(bb)), to_pixels(top(bb)), to_pixels(bottom(bb))) + #Do we avoid Map to avoid possible pre-comile issues? function _inspectdr_mapglyph(s::Symbol) s == :rect && return :square @@ -237,6 +240,12 @@ function _series_added(plt::Plot{InspectDRBackend}, series::Series) _vectorize(v) = isa(v, Vector)? v: collect(v) #InspectDR only supports vectors x = _vectorize(series[:x]); y = _vectorize(series[:y]) + #No support for polar grid... but can still perform polar transformation: + if ispolar(sp) + Θ = x; r = y + x = r.*cos(Θ); y = r.*sin(Θ) + end + # doesn't handle mismatched x/y - wrap data (pyplot behaviour): nx = length(x); ny = length(y) if nx < ny @@ -338,6 +347,12 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend}) plot.axes = InspectDR.AxesRect(xscale, yscale) xmin, xmax = axis_limits(xaxis) ymin, ymax = axis_limits(yaxis) + if ispolar(sp) + #Plots.jl appears to give (xmin,xmax) ≜ (Θmin,Θmax) & (ymin,ymax) ≜ (rmin,rmax) + rmax = max(abs(ymin), abs(ymax)) + xmin, xmax = -rmax, rmax + ymin, ymax = -rmax, rmax + end plot.ext = InspectDR.PExtents2D() #reset plot.ext_full = InspectDR.PExtents2D(xmin, xmax, ymin, ymax) a = plot.annotation @@ -345,6 +360,7 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend}) a.xlabel = xaxis[:guide]; a.ylabel = yaxis[:guide] l = plot.layout + l.frame.fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot]) l.framedata.fillcolor = _inspectdr_mapcolor(sp[:background_color_inside]) l.framedata.line.color = _inspectdr_mapcolor(xaxis[:foreground_color_axis]) l.fnttitle = InspectDR.Font(sp[:titlefont].family, @@ -378,6 +394,13 @@ function _before_layout_calcs(plt::Plot{InspectDRBackend}) const mplot = _inspectdr_getmplot(plt.o) if nothing == mplot; return; end + mplot.title = plt[:plot_title] + if "" == mplot.title + #Don't use window_title... probably not what you want. + #mplot.title = plt[:window_title] + end + mplot.frame.fillcolor = _inspectdr_mapcolor(plt[:background_color_outside]) + resize!(mplot.subplots, length(plt.subplots)) nsubplots = length(plt.subplots) for (i, sp) in enumerate(plt.subplots) @@ -385,15 +408,15 @@ function _before_layout_calcs(plt::Plot{InspectDRBackend}) mplot.subplots[i] = InspectDR.Plot2D() end sp.o = mplot.subplots[i] + plot = sp.o _initialize_subplot(plt, sp) _inspectdr_setupsubplot(sp) - - sp.o.layout.frame.fillcolor = - _inspectdr_mapcolor(plt[:background_color_outside]) + graphbb = _inspectdr_to_pixels(plotarea(sp)) + plot.plotbb = InspectDR.plotbounds(plot.layout, graphbb) # add the annotations for ann in sp[:annotations] - _inspectdr_add_annotations(mplot.subplots[i], ann...) + _inspectdr_add_annotations(plot, ann...) end end @@ -422,8 +445,19 @@ end # Set the (left, top, right, bottom) minimum padding around the plot area # to fit ticks, tick labels, guides, colorbars, etc. function _update_min_padding!(sp::Subplot{InspectDRBackend}) - sp.minpad = (20mm, 5mm, 2mm, 10mm) - #TODO: Add support for padding. + plot = sp.o + if !isa(plot, InspectDR.Plot2D); return sp.minpad; end + #Computing plotbounds with 0-BoundingBox returns required padding: + bb = InspectDR.plotbounds(plot.layout, InspectDR.BoundingBox(0,0,0,0)) + #NOTE: plotbounds always pads for titles, legends, etc. even if not in use. + #TODO: possibly zero-out items not in use?? + + # add in the user-specified margin to InspectDR padding: + leftpad = abs(bb.xmin)*px + sp[:left_margin] + toppad = abs(bb.ymax)*px + sp[:top_margin] + rightpad = abs(bb.xmax)*px + sp[:right_margin] + bottompad = abs(bb.ymin)*px + sp[:bottom_margin] + sp.minpad = (leftpad, toppad, rightpad, bottompad) end # ---------------------------------------------------------------- @@ -432,6 +466,9 @@ end function _update_plot_object(plt::Plot{InspectDRBackend}) mplot = _inspectdr_getmplot(plt.o) if nothing == mplot; return; end + + #TODO: should plotbb be computed here?? + gplot = _inspectdr_getgui(plt.o) if nothing == gplot; return; end @@ -452,19 +489,21 @@ const _inspectdr_mimeformats_nodpi = Dict( # "application/postscript" => "ps", #TODO: support once Cairo supports PSSurface "application/pdf" => "pdf" ) -_inspectdr_show(io::IO, mime::MIME, ::Void) = +_inspectdr_show(io::IO, mime::MIME, ::Void, w, h) = throw(ErrorException("Cannot show(::IO, ...) plot - not yet generated")) -_inspectdr_show(io::IO, mime::MIME, mplot) = show(io, mime, mplot) +function _inspectdr_show(io::IO, mime::MIME, mplot, w, h) + InspectDR._show(io, mime, mplot, Float64(w), Float64(h)) +end for (mime, fmt) in _inspectdr_mimeformats_dpi @eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend}) dpi = plt[:dpi]#TODO: support - _inspectdr_show(io, mime, _inspectdr_getmplot(plt.o)) + _inspectdr_show(io, mime, _inspectdr_getmplot(plt.o), plt[:size]...) end end for (mime, fmt) in _inspectdr_mimeformats_nodpi @eval function _show(io::IO, mime::MIME{Symbol($mime)}, plt::Plot{InspectDRBackend}) - _inspectdr_show(io, mime, _inspectdr_getmplot(plt.o)) + _inspectdr_show(io, mime, _inspectdr_getmplot(plt.o), plt[:size]...) end end _show(io::IO, mime::MIME"text/plain", plt::Plot{InspectDRBackend}) = nothing #Don't show From caed94328ff67ce9a0807909461a51334b7d2f57 Mon Sep 17 00:00:00 2001 From: MA Laforge Date: Wed, 25 Jan 2017 11:40:47 -0500 Subject: [PATCH 011/107] Fix exception calling backend() in _initialize_backend(). --- src/backends/pyplot.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index c02a512f..68f45be9 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -92,7 +92,7 @@ function _initialize_backend(::PyPlotBackend) kw = Conda._installed_packages_dict() if (!haskey(kw,"qt") || (qt_version=get(kw,"qt",0)[1]!=v"4.8.5")) print("\n If the code has a Segmentation fault error switch to qt v4.8.5 by pasting the following code into julia: \n \n") - add_backend_string(backend()) + print(add_backend_string(PyPlotBackend())) end end end From 95a26f50809cad7b1bfe2c94648c1269130f2afa Mon Sep 17 00:00:00 2001 From: MA Laforge Date: Sat, 28 Jan 2017 11:47:10 -0500 Subject: [PATCH 012/107] Fix inversion in padding. --- src/backends/inspectdr.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl index af95c76a..4f6a57f9 100644 --- a/src/backends/inspectdr.jl +++ b/src/backends/inspectdr.jl @@ -454,9 +454,9 @@ function _update_min_padding!(sp::Subplot{InspectDRBackend}) # add in the user-specified margin to InspectDR padding: leftpad = abs(bb.xmin)*px + sp[:left_margin] - toppad = abs(bb.ymax)*px + sp[:top_margin] + toppad = abs(bb.ymin)*px + sp[:top_margin] rightpad = abs(bb.xmax)*px + sp[:right_margin] - bottompad = abs(bb.ymin)*px + sp[:bottom_margin] + bottompad = abs(bb.ymax)*px + sp[:bottom_margin] sp.minpad = (leftpad, toppad, rightpad, bottompad) end From 2e1c86c0c7315affa1432e8cc16492ebbcced102 Mon Sep 17 00:00:00 2001 From: John Rinehart Date: Tue, 31 Jan 2017 23:55:16 -0500 Subject: [PATCH 013/107] path spaces fix stolen from http://stackoverflow.com/a/13692919 Spaces in Windows paths resulted in improper DOS command. Fix designed according to the above-referenced StackOverflow post. --- src/backends/web.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/web.jl b/src/backends/web.jl index 2fd4ae6e..6781314e 100644 --- a/src/backends/web.jl +++ b/src/backends/web.jl @@ -27,7 +27,7 @@ function open_browser_window(filename::AbstractString) return run(`xdg-open $(filename)`) end @static if is_windows() - return run(`$(ENV["COMSPEC"]) /c start $(filename)`) + return run(`$(ENV["COMSPEC"]) /c start "" "$(filename)"`) end warn("Unknown OS... cannot open browser window.") end From d5eafad48ed0fff9b52fdad044f9bbfac7b5f370 Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Thu, 2 Feb 2017 16:05:17 +0100 Subject: [PATCH 014/107] Add annotations and series_annotations to pgfplots --- src/backends/pgfplots.jl | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index 4feb46d0..6d8be4ba 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -3,7 +3,7 @@ # significant contributions by: @pkofod const _pgfplots_attr = merge_with_base_supported([ - # :annotations, + :annotations, # :background_color_legend, :background_color_inside, # :background_color_outside, @@ -27,7 +27,7 @@ const _pgfplots_attr = merge_with_base_supported([ # :ribbon, :quiver, :arrow, # :orientation, # :overwrite_figure, - # :polar, + :polar, # :normalize, :weights, :contours, :aspect_ratio, # :match_dimensions, @@ -136,6 +136,20 @@ function pgf_marker(d::KW) }""" end +function pgf_add_annotation!(o,x,y,val) + # Construct the style string. + # Currently supports color and orientation + halign = val.font.halign == :hcenter ? "" : string(val.font.halign) + cstr,a = pgf_color(val.font.color) + push!(o, PGFPlots.Plots.Node(val.str, # Annotation Text + x, y, # x,y + style=""" + $halign, + color=$cstr, draw opacity=$(convert(Float16,a)), + rotate=$(val.font.rotation) + """)) +end + # -------------------------------------------------------------------------------------- function pgf_series(sp::Subplot, series::Series) @@ -298,14 +312,25 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend}) # add the series object to the PGFPlots.Axis for series in series_list(sp) push!(o, pgf_series(sp, series)) + + # add series annotations + anns = series[:series_annotations] + for (xi,yi,str,fnt) in EachAnn(anns, series[:x], series[:y]) + pgf_add_annotation!(o, xi, yi, PlotText(str, fnt)) + end end + # add the annotations + for ann in sp[:annotations] + pgf_add_annotation!(o,ann...) + end + + # add the PGFPlots.Axis to the list push!(plt.o, o) end end - function _show(io::IO, mime::MIME"image/svg+xml", plt::Plot{PGFPlotsBackend}) show(io, mime, plt.o) end From 48ff2fb8b80bd2477c0a6335d7909a725eb8ccea Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Thu, 2 Feb 2017 16:06:59 +0100 Subject: [PATCH 015/107] Merge branch 'master' of https://github.com/JuliaPlots/Plots.jl --- src/backends/inspectdr.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl index af95c76a..4f6a57f9 100644 --- a/src/backends/inspectdr.jl +++ b/src/backends/inspectdr.jl @@ -454,9 +454,9 @@ function _update_min_padding!(sp::Subplot{InspectDRBackend}) # add in the user-specified margin to InspectDR padding: leftpad = abs(bb.xmin)*px + sp[:left_margin] - toppad = abs(bb.ymax)*px + sp[:top_margin] + toppad = abs(bb.ymin)*px + sp[:top_margin] rightpad = abs(bb.xmax)*px + sp[:right_margin] - bottompad = abs(bb.ymin)*px + sp[:bottom_margin] + bottompad = abs(bb.ymax)*px + sp[:bottom_margin] sp.minpad = (leftpad, toppad, rightpad, bottompad) end From dd505fedccf89204c6a99021d4a7006fb4821c43 Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Thu, 2 Feb 2017 16:43:30 +0100 Subject: [PATCH 016/107] Add support for polar axis --- src/backends/pgfplots.jl | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index 6d8be4ba..c9bd9fba 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -307,7 +307,11 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend}) kw[:legendPos] = _pgfplots_legend_pos[legpos] end - o = PGFPlots.Axis(; style = style, kw...) + axisf = PGFPlots.Axis + if sp[:projection] == :polar + axisf = PGFPlots.PolarAxis + end + o = axisf(; style = style, kw...) # add the series object to the PGFPlots.Axis for series in series_list(sp) From 1111000217396f9bae5dd2c3db4e3b95156c73b0 Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Thu, 2 Feb 2017 17:39:34 +0100 Subject: [PATCH 017/107] Add support for ticks rotation --- src/backends/pgfplots.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index c9bd9fba..c45f9157 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -225,6 +225,9 @@ function pgf_axis(sp::Subplot, letter) # axis guide kw[Symbol(letter,:label)] = axis[:guide] + # ticks + push!(style, "$(letter)ticklabel style={rotate = $(axis[:rotation])}") + # flip/reverse? axis[:flip] && push!(style, "$letter dir=reverse") From 3ca39728d8a15cc25e723b7b5d7365e053dc47b3 Mon Sep 17 00:00:00 2001 From: MA Laforge Date: Thu, 2 Feb 2017 20:38:34 -0500 Subject: [PATCH 018/107] Make compatible with InspectDR v0.1.4. --- src/backends/inspectdr.jl | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl index 4f6a57f9..72034473 100644 --- a/src/backends/inspectdr.jl +++ b/src/backends/inspectdr.jl @@ -128,16 +128,17 @@ end # --------------------------------------------------------------------------- -function _inspectdr_getscale(s::Symbol) +function _inspectdr_getscale(s::Symbol, yaxis::Bool) #TODO: Support :asinh, :sqrt + kwargs = yaxis? (:tgtmajor=>8, :tgtminor=>2): () #More grid lines on y-axis if :log2 == s - return InspectDR.AxisScale(:log2) + return InspectDR.AxisScale(:log2; kwargs...) elseif :log10 == s - return InspectDR.AxisScale(:log10) + return InspectDR.AxisScale(:log10; kwargs...) elseif :ln == s - return InspectDR.AxisScale(:ln) + return InspectDR.AxisScale(:ln; kwargs...) else #identity - return InspectDR.AxisScale(:lin) + return InspectDR.AxisScale(:lin; kwargs...) end end @@ -337,14 +338,17 @@ end # --------------------------------------------------------------------------- function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend}) - const gridon = InspectDR.grid(vmajor=true, hmajor=true) - const gridoff = InspectDR.grid() + const gridon = InspectDR.GridRect(vmajor=true, hmajor=true) + const gridoff = InspectDR.GridRect() const plot = sp.o + const strip = plot.strips[1] #Only 1 strip supported with Plots.jl + + #No independent control of grid??? + strip.grid = sp[:grid]? gridon: gridoff xaxis = sp[:xaxis]; yaxis = sp[:yaxis] - xscale = _inspectdr_getscale(xaxis[:scale]) - yscale = _inspectdr_getscale(yaxis[:scale]) - plot.axes = InspectDR.AxesRect(xscale, yscale) + plot.xscale = _inspectdr_getscale(xaxis[:scale], false) + strip.yscale = _inspectdr_getscale(yaxis[:scale], true) xmin, xmax = axis_limits(xaxis) ymin, ymax = axis_limits(yaxis) if ispolar(sp) @@ -353,11 +357,13 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend}) xmin, xmax = -rmax, rmax ymin, ymax = -rmax, rmax end - plot.ext = InspectDR.PExtents2D() #reset - plot.ext_full = InspectDR.PExtents2D(xmin, xmax, ymin, ymax) + plot.xext = InspectDR.PExtents1D() #reset + strip.yext = InspectDR.PExtents1D() #reset + plot.xext_full = InspectDR.PExtents1D(xmin, xmax) + strip.yext_full = InspectDR.PExtents1D(ymin, ymax) a = plot.annotation a.title = sp[:title] - a.xlabel = xaxis[:guide]; a.ylabel = yaxis[:guide] + a.xlabel = xaxis[:guide]; a.ylabels = [yaxis[:guide]] l = plot.layout l.frame.fillcolor = _inspectdr_mapcolor(sp[:background_color_subplot]) @@ -376,8 +382,6 @@ function _inspectdr_setupsubplot(sp::Subplot{InspectDRBackend}) _inspectdr_mapptsize(xaxis[:tickfont].pointsize), color = _inspectdr_mapcolor(xaxis[:foreground_color_text]) ) - #No independent control of grid??? - l.grid = sp[:grid]? gridon: gridoff leg = l.legend leg.enabled = (sp[:legend] != :none) #leg.width = 150 #TODO: compute??? From d883274586c0774d51c5c64d50600e6faaeb9540 Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Fri, 3 Feb 2017 08:25:55 +0100 Subject: [PATCH 019/107] Fix comments --- src/backends/pgfplots.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index c45f9157..de4d4a6a 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -142,7 +142,7 @@ function pgf_add_annotation!(o,x,y,val) halign = val.font.halign == :hcenter ? "" : string(val.font.halign) cstr,a = pgf_color(val.font.color) push!(o, PGFPlots.Plots.Node(val.str, # Annotation Text - x, y, # x,y + x, y, style=""" $halign, color=$cstr, draw opacity=$(convert(Float16,a)), @@ -225,7 +225,7 @@ function pgf_axis(sp::Subplot, letter) # axis guide kw[Symbol(letter,:label)] = axis[:guide] - # ticks + # Add ticklabel rotations push!(style, "$(letter)ticklabel style={rotate = $(axis[:rotation])}") # flip/reverse? From 0880487be2eff61464b644cff6614533776c0fa0 Mon Sep 17 00:00:00 2001 From: YongHee Kim Date: Mon, 6 Feb 2017 21:29:41 +0900 Subject: [PATCH 020/107] enable standalone window for plotlyjs() backen --- src/backends/plotlyjs.jl | 12 +++++++++++- src/output.jl | 10 ++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/backends/plotlyjs.jl b/src/backends/plotlyjs.jl index 6d4ad145..0a2ad219 100644 --- a/src/backends/plotlyjs.jl +++ b/src/backends/plotlyjs.jl @@ -102,8 +102,18 @@ _show(io::IO, ::MIME"image/png", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hac _show(io::IO, ::MIME"application/pdf", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "pdf") _show(io::IO, ::MIME"image/eps", plt::Plot{PlotlyJSBackend}) = plotlyjs_save_hack(io, plt, "eps") +function write_temp_html(plt::Plot{PlotlyJSBackend}) + filename = string(tempname(), ".html") + savefig(plt, filename) + filename +end + function _display(plt::Plot{PlotlyJSBackend}) - display(plt.o) + if get(ENV, "PLOTS_USE_ATOM_PLOTPANE", true) in (true, 1, "1", "true", "yes") + display(plt.o) + else + standalone_html_window(plt) + end end diff --git a/src/output.jl b/src/output.jl index ee9972ab..f3efd812 100644 --- a/src/output.jl +++ b/src/output.jl @@ -302,6 +302,10 @@ function setup_atom() Media.render(pane, Atom.div(".fill", Atom.HTML(stringmime(MIME("text/html"), plt)))) plt[:size] = sz end + # special handling for PlotlyJS + function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyJSBackend}) + display(Plots.PlotsDisplay(), plt) + end else # function Media.render(pane::Atom.PlotPane, plt::Plot) @@ -317,11 +321,5 @@ function setup_atom() s = "PlotPane turned off. The plotly and plotlyjs backends cannot render in the PlotPane due to javascript issues." Media.render(pane, Atom.div(Atom.HTML(s))) end - - # special handling for PlotlyJS to pass through to that render method - function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyJSBackend}) - Plots.prepare_output(plt) - Media.render(pane, plt.o) - end end end From c93e2b80ca8209ef6f9704d2a91bdc9fdb971194 Mon Sep 17 00:00:00 2001 From: SimonDanisch Date: Tue, 7 Feb 2017 18:28:22 -0500 Subject: [PATCH 021/107] fixes for GLVisualize --- src/backends/glvisualize.jl | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/backends/glvisualize.jl b/src/backends/glvisualize.jl index 3d48344b..f053dfb7 100644 --- a/src/backends/glvisualize.jl +++ b/src/backends/glvisualize.jl @@ -149,19 +149,20 @@ function get_plot_screen(screen, name, result = []) end function create_window(plt::Plot{GLVisualizeBackend}, visible) - name = Symbol("Plots.jl") + name = Symbol("__Plots.jl") # make sure we have any screen open if isempty(GLVisualize.get_screens()) # create a fresh, new screen parent_screen = GLVisualize.glscreen( - "Plot", + "Plots", resolution = plt[:size], visible = visible ) @async GLWindow.waiting_renderloop(parent_screen) + GLVisualize.add_screen(parent_screen) end # now lets get ourselves a permanent Plotting screen - plot_screens = get_plot_screen(GLVisualize.get_screens(), name) + plot_screens = get_plot_screen(GLVisualize.current_screen(), name) screen = if isempty(plot_screens) # no screen with `name` parent = GLVisualize.current_screen() screen = GLWindow.Screen( @@ -177,7 +178,7 @@ function create_window(plt::Plot{GLVisualizeBackend}, visible) else # okay this is silly! Lets see if we can. There is an ID we could use # will not be fine for more than 255 screens though -.-. - error("multiple Plot screens. Please don't use any screen with the name Plots.jl") + error("multiple Plot screens. Please don't use any screen with the name $name") end # Since we own this window, we can do deep cleansing empty_screen!(screen) @@ -1415,6 +1416,8 @@ function label_scatter(d, w, ho) color = get(kw, :color, nothing) kw[:color] = isa(color, Array) ? first(color) : color end + strcolor = get(kw, :stroke_color, RGBA{Float32}(0,0,0,0)) + kw[:stroke_color] = isa(strcolor, Array) ? first(strcolor) : strcolor p = get(kw, :primitive, GeometryTypes.Circle) if isa(p, GLNormalMesh) bb = GeometryTypes.AABB{Float32}(GeometryTypes.vertices(p)) @@ -1429,6 +1432,9 @@ function label_scatter(d, w, ho) kw[:scale] = Vec3f0(w/2) delete!(kw, :offset) end + if isa(p, Array) + kw[:primitive] = GeometryTypes.Circle + end GL.gl_scatter(Point2f0[(w/2, ho)], kw) end From 51a47cb2b1d231b560d8363d9ece9b510b13d3d2 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Wed, 8 Feb 2017 23:51:15 +0100 Subject: [PATCH 022/107] Added basic support for searching attributes at the console --- src/Plots.jl | 5 ++++- src/plotattr.jl | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/plotattr.jl diff --git a/src/Plots.jl b/src/Plots.jl index c957ab8a..337880da 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -99,7 +99,9 @@ export center, P2, P3, - BezierCurve + BezierCurve, + + plotattr # --------------------------------------------------------- @@ -127,6 +129,7 @@ include("animation.jl") include("output.jl") include("examples.jl") include("arg_desc.jl") +include("plotattr.jl") # --------------------------------------------------------- diff --git a/src/plotattr.jl b/src/plotattr.jl new file mode 100644 index 00000000..0562a70c --- /dev/null +++ b/src/plotattr.jl @@ -0,0 +1,56 @@ + +const _attribute_defaults = Dict(:Series => Plots._series_defaults, + :Subplot => Plots._subplot_defaults, + :Plot => Plots._plot_defaults, + :Axis => Plots._axis_defaults) + +attrtypes() = join(keys(_attribute_defaults), ", ") +attributes(attrtype::Symbol) = sort(collect(keys(_attribute_defaults[attrtype]))) + +function lookup_aliases(attrtype, attribute) + attribute = Symbol(attribute) + attribute = in(attribute, keys(_keyAliases)) ? _keyAliases[attribute] : attribute + in(attribute, keys(_attribute_defaults[attrtype])) && return attribute + error("There is no attribute named $attribute in $attrtype") +end + +function plotattr() + println("Specify an attribute type to get a list of supported attributes. Options are $(attrtypes())") +end + +function plotattr(attrtype::Symbol) + in(attrtype, keys(_attribute_defaults)) || error("Viable options are $(attrtypes())") + println("Defined $attrtype attributes are:\n$(join(attributes(attrtype), ", "))") +end + +function plotattr(attribute::AbstractString) + attribute = Symbol(attribute) + attribute = in(attribute, keys(_keyAliases)) ? _keyAliases[attribute] : attribute + for (k, v) in _attribute_defaults + if in(attribute, keys(v)) + return plotattr(k, "$attribute") + end + end + error("There is no attribute named $attribute") +end + +function plotattr(attrtype::Symbol, attribute::AbstractString) + in(attrtype, keys(_attribute_defaults)) || ArgumentError("`attrtype` must match one of $(attrtypes())") + + attribute = Symbol(lookup_aliases(attrtype, attribute)) + + desc = get(_arg_desc, attribute, "") + first_period_idx = findfirst(desc, '.') + typedesc = desc[1:first_period_idx-1] + desc = strip(desc[first_period_idx+1:end]) + als = keys(filter((_,v)->v==attribute, _keyAliases)) |> collect |> sort + als = join(map(string,als), ", ") + + + # Looks up the different elements and plots them + println("$attribute ($attrtype attribute)") + println("Aliases: $als \n") + println("Default: $(_attribute_defaults[attrtype][attribute])\t(Type: $typedesc)\n") + println("Description: ") + println(desc) +end From 82161e60bcd8c5ea9726e9bf59ab69c2eb6ed4da Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Thu, 9 Feb 2017 00:12:16 +0100 Subject: [PATCH 023/107] removed unnecessary Plots qualifier --- src/plotattr.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plotattr.jl b/src/plotattr.jl index 0562a70c..4272990d 100644 --- a/src/plotattr.jl +++ b/src/plotattr.jl @@ -1,8 +1,8 @@ -const _attribute_defaults = Dict(:Series => Plots._series_defaults, - :Subplot => Plots._subplot_defaults, - :Plot => Plots._plot_defaults, - :Axis => Plots._axis_defaults) +const _attribute_defaults = Dict(:Series => _series_defaults, + :Subplot => _subplot_defaults, + :Plot => _plot_defaults, + :Axis => _axis_defaults) attrtypes() = join(keys(_attribute_defaults), ", ") attributes(attrtype::Symbol) = sort(collect(keys(_attribute_defaults[attrtype]))) From 35a56962fc2d087a4caabda90568821155d4fd1e Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Thu, 9 Feb 2017 10:40:08 +0100 Subject: [PATCH 024/107] more concise output --- src/plotattr.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/plotattr.jl b/src/plotattr.jl index 4272990d..b815adef 100644 --- a/src/plotattr.jl +++ b/src/plotattr.jl @@ -45,12 +45,12 @@ function plotattr(attrtype::Symbol, attribute::AbstractString) desc = strip(desc[first_period_idx+1:end]) als = keys(filter((_,v)->v==attribute, _keyAliases)) |> collect |> sort als = join(map(string,als), ", ") + def = _attribute_defaults[attrtype][attribute] # Looks up the different elements and plots them - println("$attribute ($attrtype attribute)") - println("Aliases: $als \n") - println("Default: $(_attribute_defaults[attrtype][attribute])\t(Type: $typedesc)\n") - println("Description: ") - println(desc) + println("$attribute ", typedesc == "" ? "" : "{$typedesc}") + als == "" || println("$als") + println("\n",desc) + println("$(attrtype) attribute, ", def == "" ? "" : " default: $def") end From d663267cde22d18e74fdc10d345073df83135c42 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Thu, 9 Feb 2017 11:12:46 +0100 Subject: [PATCH 025/107] improved println call --- src/plotattr.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/plotattr.jl b/src/plotattr.jl index b815adef..cc8d053b 100644 --- a/src/plotattr.jl +++ b/src/plotattr.jl @@ -49,8 +49,8 @@ function plotattr(attrtype::Symbol, attribute::AbstractString) # Looks up the different elements and plots them - println("$attribute ", typedesc == "" ? "" : "{$typedesc}") - als == "" || println("$als") - println("\n",desc) - println("$(attrtype) attribute, ", def == "" ? "" : " default: $def") + println("$attribute ", typedesc == "" ? "" : "{$typedesc}", "\n", + als == "" ? "" : "$als\n", + "\n$desc\n", + "$(attrtype) attribute, ", def == "" ? "" : " default: $def") end From 471b09bd6cb564c024dd5d0a99b4849299e1410f Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Fri, 10 Feb 2017 11:24:48 +0100 Subject: [PATCH 026/107] gr: added support for hexbin plots --- src/backends/gr.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index b092edd7..5b4a3eb8 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -33,7 +33,7 @@ const _gr_attr = merge_with_base_supported([ :arrow, ]) const _gr_seriestype = [ - :path, :scatter, + :path, :scatter, :hexbin, :heatmap, :pie, :image, :contour, :path3d, :scatter3d, :surface, :wireframe, :shape @@ -798,6 +798,9 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) gr_draw_markers(series, x, y) end + elseif st == :hexbin + GR.hexbin(x, y, nbins = series[:bins]) + elseif st == :contour zmin, zmax = gr_lims(zaxis, false) clims = sp[:clims] From eb7534d319afc07782277984460fb2ea0504cb9a Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Tue, 14 Feb 2017 09:55:46 +0100 Subject: [PATCH 027/107] gr: corrected alignment of rotated axes labels --- src/backends/gr.jl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 5b4a3eb8..f79258ab 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -33,7 +33,7 @@ const _gr_attr = merge_with_base_supported([ :arrow, ]) const _gr_seriestype = [ - :path, :scatter, :hexbin, + :path, :scatter, :heatmap, :pie, :image, :contour, :path3d, :scatter3d, :surface, :wireframe, :shape @@ -653,6 +653,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) flip = sp[:yaxis][:flip] mirror = sp[:xaxis][:mirror] gr_set_font(sp[:xaxis][:tickfont], + halign = (:left, :hcenter, :right)[sign(sp[:xaxis][:rotation]) + 2], valign = (mirror ? :bottom : :top), color = sp[:xaxis][:foreground_color_axis], rotation = sp[:xaxis][:rotation]) @@ -670,6 +671,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) mirror = sp[:yaxis][:mirror] gr_set_font(sp[:yaxis][:tickfont], halign = (mirror ? :left : :right), + valign = (:top, :vcenter, :bottom)[sign(sp[:yaxis][:rotation]) + 2], color = sp[:yaxis][:foreground_color_axis], rotation = sp[:yaxis][:rotation]) for (cv, dv) in zip(yticks...) @@ -798,9 +800,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) gr_draw_markers(series, x, y) end - elseif st == :hexbin - GR.hexbin(x, y, nbins = series[:bins]) - elseif st == :contour zmin, zmax = gr_lims(zaxis, false) clims = sp[:clims] From 5ae2044d02bc24785c999166bcefe246e165a392 Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Tue, 14 Feb 2017 21:04:13 +0100 Subject: [PATCH 028/107] Fix halign for annotations in pgfplots backend PGFPlot uses inverted right and left parameters. --- src/backends/pgfplots.jl | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index de4d4a6a..3a47295f 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -98,6 +98,12 @@ const _pgf_series_extrastyle = KW( :xsticks => "xcomb", ) +const _pgf_annotation_halign = KW( + :center => "", + :left => "right", + :right => "left" +) + # -------------------------------------------------------------------------------------- # takes in color,alpha, and returns color and alpha appropriate for pgf style @@ -139,12 +145,11 @@ end function pgf_add_annotation!(o,x,y,val) # Construct the style string. # Currently supports color and orientation - halign = val.font.halign == :hcenter ? "" : string(val.font.halign) cstr,a = pgf_color(val.font.color) push!(o, PGFPlots.Plots.Node(val.str, # Annotation Text x, y, style=""" - $halign, + $(get(_pgf_annotation_halign,val.font.halign,"")), color=$cstr, draw opacity=$(convert(Float16,a)), rotate=$(val.font.rotation) """)) From 2a350df5ebe80fe40e32deed9681f30117e56889 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Tue, 21 Feb 2017 22:44:32 +0100 Subject: [PATCH 029/107] plot recipe to show color libraries --- src/recipes.jl | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/recipes.jl b/src/recipes.jl index 156bda3e..7e0d4dde 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -802,3 +802,33 @@ abline!(args...; kw...) = abline!(current(), args...; kw...) seriestype --> :scatter real(cp.args[1]), imag(cp.args[1]) end + + +# -------------------------------------------------- +# Color Gradients + +@userplot ShowLibrary +@recipe function f(cl::ShowLibrary) + if !(length(cl.args) == 1 && isa(cl.args[1], Symbol)) + error("ShowLibrary takes the name of a color library as a Symbol") + end + + library = clibrary(cl.args[1]) + z = sqrt.((1:20)*(1:15)') + + seriestype := :heatmap + ticks := nothing + legend := false + + layout := length(library.lib) + + i = 0 + for grad in keys(library.lib) + @series begin + seriescolor := cgrad(grad, color_library = cl.args[1]) + title := grad + subplot := i += 1 + z + end + end +end From 4b2ce036e8642dae2c2cda622a938cfc347c199f Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Tue, 21 Feb 2017 22:49:15 +0100 Subject: [PATCH 030/107] change numbers --- src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index 7e0d4dde..fb452561 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -814,7 +814,7 @@ end end library = clibrary(cl.args[1]) - z = sqrt.((1:20)*(1:15)') + z = sqrt.((1:15)*(1:20)') seriestype := :heatmap ticks := nothing From d4b7bfbe1dab2d6705d7ce5b709848fde6f2f05f Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Wed, 22 Feb 2017 11:48:37 +0100 Subject: [PATCH 031/107] Added a recipe to show a single gradient --- src/recipes.jl | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index fb452561..152752a3 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -810,7 +810,7 @@ end @userplot ShowLibrary @recipe function f(cl::ShowLibrary) if !(length(cl.args) == 1 && isa(cl.args[1], Symbol)) - error("ShowLibrary takes the name of a color library as a Symbol") + error("showlibrary takes the name of a color library as a Symbol") end library = clibrary(cl.args[1]) @@ -832,3 +832,17 @@ end end end end + +@userplot ShowGradient +@recipe function f(grad::ShowGradient) + if !(length(grad.args) == 1 && isa(grad.args[1], Symbol)) + error("showgradient takes the name of a color gradient as a Symbol") + end + z = sqrt.((1:15)*(1:20)') + seriestype := :heatmap + ticks := nothing + legend := false + seriescolor := grad.args[1] + title := grad.args[1] + z +end From 28b026c9adebfbca231fc310eabb71e3c4aab7ee Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Wed, 22 Feb 2017 11:49:31 +0100 Subject: [PATCH 032/107] replaced boxes with symmetrical squares --- src/recipes.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 152752a3..60f5997f 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -814,7 +814,7 @@ end end library = clibrary(cl.args[1]) - z = sqrt.((1:15)*(1:20)') + z = (1:20).+(1:20)' seriestype := :heatmap ticks := nothing @@ -838,7 +838,7 @@ end if !(length(grad.args) == 1 && isa(grad.args[1], Symbol)) error("showgradient takes the name of a color gradient as a Symbol") end - z = sqrt.((1:15)*(1:20)') + z = (1:20).+(1:20)' seriestype := :heatmap ticks := nothing legend := false From b7536f129b3e3cf1876ed497c9d92dbc4098a16e Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Wed, 22 Feb 2017 11:52:54 +0100 Subject: [PATCH 033/107] Revert "replaced boxes with symmetrical squares" This reverts commit 28b026c9adebfbca231fc310eabb71e3c4aab7ee. --- src/recipes.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 60f5997f..152752a3 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -814,7 +814,7 @@ end end library = clibrary(cl.args[1]) - z = (1:20).+(1:20)' + z = sqrt.((1:15)*(1:20)') seriestype := :heatmap ticks := nothing @@ -838,7 +838,7 @@ end if !(length(grad.args) == 1 && isa(grad.args[1], Symbol)) error("showgradient takes the name of a color gradient as a Symbol") end - z = (1:20).+(1:20)' + z = sqrt.((1:15)*(1:20)') seriestype := :heatmap ticks := nothing legend := false From 5395b418525b753028e2c8e52d9aed18090b7e96 Mon Sep 17 00:00:00 2001 From: Leon Wabeke Date: Wed, 22 Feb 2017 15:57:41 +0200 Subject: [PATCH 034/107] Attempt to add support for clims to plotly backend Added support for clims, seems to work on heatmap, surface and contour. On surface zlims be still be set to be different from clims. --- src/backends/plotly.jl | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index bbdd29b9..85c69105 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -31,6 +31,7 @@ const _plotly_attr = merge_with_base_supported([ :hover, :inset_subplots, :bar_width, + :clims, ]) const _plotly_seriestype = [ @@ -438,6 +439,11 @@ function plotly_series(plt::Plot, series::Series) end end + clims = sp[:clims] + if is_2tuple(clims) + d_out[:zmin], d_out[:zmax] = clims + end + # set the "type" if st in (:path, :scatter, :scattergl) d_out[:type] = st==:scattergl ? "scattergl" : "scatter" From fd947ab8872727da7128063395802a7a990e7633 Mon Sep 17 00:00:00 2001 From: Josh Day Date: Wed, 22 Feb 2017 10:40:16 -0500 Subject: [PATCH 035/107] only one, smaller gr marker --- src/backends/gr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index f79258ab..c17df76e 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1017,7 +1017,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) end if series[:markershape] != :none - gr_draw_markers(series, xpos-[0.06,0.02], [ypos,ypos], 10, nothing) + gr_draw_markers(series, xpos - .035, ypos, 6, nothing) end if typeof(series[:label]) <: Array From 9e1d551173f8d2c967523c1a8448719ab2957d76 Mon Sep 17 00:00:00 2001 From: Leon Wabeke Date: Fri, 24 Feb 2017 12:19:20 +0200 Subject: [PATCH 036/107] Commit to address issue #681 Change to address issue #681 Untested change --- src/backends/web.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/web.jl b/src/backends/web.jl index 6781314e..b0be7a3e 100644 --- a/src/backends/web.jl +++ b/src/backends/web.jl @@ -23,7 +23,7 @@ function open_browser_window(filename::AbstractString) @static if is_apple() return run(`open $(filename)`) end - @static if is_linux() + @static if is_linux() || is_bsd() # is_bsd() addition is as yet untested, but based on suggestion in https://github.com/JuliaPlots/Plots.jl/issues/681 return run(`xdg-open $(filename)`) end @static if is_windows() From 9472c0c5e5f0939ee33409de9369b46559900ad9 Mon Sep 17 00:00:00 2001 From: Tom Breloff Date: Fri, 24 Feb 2017 15:19:41 -0500 Subject: [PATCH 037/107] skip pyplot image test --- test/runtests.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runtests.jl b/test/runtests.jl index ca7f5e3e..953ad8fe 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -23,7 +23,7 @@ facts("PyPlot") do @fact pyplot() --> Plots.PyPlotBackend() @fact backend() --> Plots.PyPlotBackend() - image_comparison_facts(:pyplot, skip=[25,30], eps=img_eps) + image_comparison_facts(:pyplot, skip=[6,25,30], eps=img_eps) end facts("GR") do From b0dabaafe896eaf79de0f311bbc0817f8df09e7e Mon Sep 17 00:00:00 2001 From: MA Laforge Date: Sat, 25 Feb 2017 11:33:24 -0500 Subject: [PATCH 038/107] InspectDR: Reflect changes to support delta markers. --- src/backends/inspectdr.jl | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl index 72034473..cb290d22 100644 --- a/src/backends/inspectdr.jl +++ b/src/backends/inspectdr.jl @@ -213,14 +213,10 @@ end # Set up the subplot within the backend object. function _initialize_subplot(plt::Plot{InspectDRBackend}, sp::Subplot{InspectDRBackend}) plot = sp.o - #Don't do anything without a "subplot" object: Will process later. if nothing == plot; return; end plot.data = [] - plot.markers = [] #Clear old markers - plot.atext = [] #Clear old annotation - plot.apline = [] #Clear old poly lines - + plot.userannot = [] #Clear old markers/text annotation/polyline "annotation" return plot end @@ -277,7 +273,7 @@ For st in :shape: apline = InspectDR.PolylineAnnotation( x[rng], y[rng], line=line, fillcolor=fillcolor ) - push!(plot.apline, apline) + InspectDR.add(plot, apline) end end From 24c27737c1b8ff816d394efe2f06c2d7c0512c54 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Sun, 26 Feb 2017 08:32:52 +0100 Subject: [PATCH 039/107] fix uneven bins --- src/recipes.jl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index 156bda3e..0585e488 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -410,6 +410,8 @@ function my_hist(v, bins; normed = false, weights = nothing) counts[idx] += (weights == nothing ? 1.0 : weights[i]) end + counts = isapprox(extrema(diff(edges))...) ? counts : counts ./ diff(edges) # for uneven bins, normalize to area. + # normalize by bar area? norm_denom = normed ? sum(diff(edges) .* counts) : 1.0 if norm_denom == 0 @@ -424,7 +426,8 @@ end edges, counts = my_hist(y, d[:bins], normed = d[:normalize], weights = d[:weights]) - x := edges + bar_width := diff(edges) + x := centers(edges) y := counts seriestype := :bar () From eab4cfdf2d4b4c5efe7e5daf285b0be2303da77e Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Sun, 26 Feb 2017 17:23:43 +0100 Subject: [PATCH 040/107] allow color libraries to be used in PlotThemes --- src/themes.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/themes.jl b/src/themes.jl index 3429585a..feb665d6 100644 --- a/src/themes.jl +++ b/src/themes.jl @@ -2,7 +2,8 @@ function theme(s::Symbol; kw...) # reset? if s == :none || s == :default - PlotUtils._default_gradient[] = :inferno + PlotUtils.set_clibrary(:matplotlib) + PlotUtils.cgraddefaults(:inferno) default(; bg = :white, bglegend = :match, @@ -23,7 +24,8 @@ function theme(s::Symbol; kw...) # update the default gradient and other defaults thm = PlotThemes._themes[s] if thm.gradient != nothing - PlotUtils._default_gradient[] = PlotThemes.gradient_name(s) + PlotUtils.set_clibrary(:plotthemes) + PlotUtils.cgraddefaults(PlotThemes.gradient_name(s)) end default(; bg = thm.bg_secondary, From 6c51982793c48d9dc24e4757a880ec0f2dbe566e Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Sun, 26 Feb 2017 20:43:04 +0100 Subject: [PATCH 041/107] fix theme default --- src/themes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/themes.jl b/src/themes.jl index feb665d6..442e67d0 100644 --- a/src/themes.jl +++ b/src/themes.jl @@ -25,7 +25,7 @@ function theme(s::Symbol; kw...) thm = PlotThemes._themes[s] if thm.gradient != nothing PlotUtils.set_clibrary(:plotthemes) - PlotUtils.cgraddefaults(PlotThemes.gradient_name(s)) + PlotUtils.cgraddefaults(default = PlotThemes.gradient_name(s)) end default(; bg = thm.bg_secondary, From b109025fac29835e5a37a6fe4e0581dc6355e189 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Mon, 27 Feb 2017 14:13:16 +0100 Subject: [PATCH 042/107] Fixed image bug --- src/backends/gr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index c17df76e..b4622145 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -944,7 +944,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) elseif st == :image z = transpose_z(series, series[:z].surf, true) - h, w = size(z) + w, h = size(z) if eltype(z) <: Colors.AbstractGray grey = round(UInt8, float(z) * 255) rgba = map(c -> UInt32( 0xff000000 + Int(c)<<16 + Int(c)<<8 + Int(c) ), grey) From 5465479e5772b60d4a19c6eae191f9fa3908b498 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Mon, 27 Feb 2017 21:47:12 +0100 Subject: [PATCH 043/107] Put themes in Plots library --- src/themes.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/themes.jl b/src/themes.jl index 442e67d0..70ee50db 100644 --- a/src/themes.jl +++ b/src/themes.jl @@ -2,7 +2,7 @@ function theme(s::Symbol; kw...) # reset? if s == :none || s == :default - PlotUtils.set_clibrary(:matplotlib) + PlotUtils.set_clibrary(:Plots) PlotUtils.cgraddefaults(:inferno) default(; bg = :white, @@ -24,7 +24,7 @@ function theme(s::Symbol; kw...) # update the default gradient and other defaults thm = PlotThemes._themes[s] if thm.gradient != nothing - PlotUtils.set_clibrary(:plotthemes) + PlotUtils.set_clibrary(:Plots) PlotUtils.cgraddefaults(default = PlotThemes.gradient_name(s)) end default(; From 6b94bbac2d9031dd41b711794855b29f82ef16af Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Mon, 27 Feb 2017 21:52:22 +0100 Subject: [PATCH 044/107] updated function names --- src/themes.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/themes.jl b/src/themes.jl index 70ee50db..c069a251 100644 --- a/src/themes.jl +++ b/src/themes.jl @@ -2,8 +2,8 @@ function theme(s::Symbol; kw...) # reset? if s == :none || s == :default - PlotUtils.set_clibrary(:Plots) - PlotUtils.cgraddefaults(:inferno) + PlotUtils.clibrary(:Plots) + PlotUtils.default_cgrad(:inferno) default(; bg = :white, bglegend = :match, @@ -24,8 +24,8 @@ function theme(s::Symbol; kw...) # update the default gradient and other defaults thm = PlotThemes._themes[s] if thm.gradient != nothing - PlotUtils.set_clibrary(:Plots) - PlotUtils.cgraddefaults(default = PlotThemes.gradient_name(s)) + PlotUtils.clibrary(:Plots) + PlotUtils.default_cgrad(default = PlotThemes.gradient_name(s)) end default(; bg = thm.bg_secondary, From cad96e652f1634acbc52f768666bf1275864327c Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Mon, 27 Feb 2017 22:45:14 +0100 Subject: [PATCH 045/107] fix error on gr --- src/recipes.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index c4bf60c4..d30b763f 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -816,7 +816,7 @@ end error("showlibrary takes the name of a color library as a Symbol") end - library = clibrary(cl.args[1]) + library = PlotUtils.color_libraries[cl.args[1]] z = sqrt.((1:15)*(1:20)') seriestype := :heatmap @@ -828,8 +828,8 @@ end i = 0 for grad in keys(library.lib) @series begin - seriescolor := cgrad(grad, color_library = cl.args[1]) - title := grad + seriescolor := cgrad(grad, cl.args[1]) + title := string(grad) subplot := i += 1 z end From 41e56b1f2e4350ca9676995e18cde0d6e6d3e710 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Tue, 28 Feb 2017 07:56:00 +0100 Subject: [PATCH 046/107] put PlotThemes in :misc --- src/themes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/themes.jl b/src/themes.jl index c069a251..702574e2 100644 --- a/src/themes.jl +++ b/src/themes.jl @@ -24,7 +24,7 @@ function theme(s::Symbol; kw...) # update the default gradient and other defaults thm = PlotThemes._themes[s] if thm.gradient != nothing - PlotUtils.clibrary(:Plots) + PlotUtils.clibrary(:hisc) PlotUtils.default_cgrad(default = PlotThemes.gradient_name(s)) end default(; From 7aca2b1584503c28dd9660d15f13630d9b690ef3 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Tue, 28 Feb 2017 09:15:32 +0100 Subject: [PATCH 047/107] fix set_axis_bgcolor --- src/backends/pyplot.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 68f45be9..e1003958 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1075,7 +1075,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) py_add_legend(plt, sp, ax) # this sets the bg color inside the grid - ax[:set_axis_bgcolor](py_color(sp[:background_color_inside])) + ax[:set_facecolor](py_color(sp[:background_color_inside])) end py_drawfig(fig) end From 1b468ba5d80348b232b3542d1a8837ab9e98a924 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Tue, 28 Feb 2017 12:35:08 +0100 Subject: [PATCH 048/107] fix gr.text on showgradient --- src/recipes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index d30b763f..1089ea10 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -846,6 +846,6 @@ end ticks := nothing legend := false seriescolor := grad.args[1] - title := grad.args[1] + title := string(grad.args[1]) z end From 6f8881b610d3908e5413e4abc5101e2b8ed5009f Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Tue, 28 Feb 2017 12:43:06 +0100 Subject: [PATCH 049/107] set defaults to sequential --- src/themes.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/themes.jl b/src/themes.jl index 702574e2..e7a39d02 100644 --- a/src/themes.jl +++ b/src/themes.jl @@ -3,7 +3,7 @@ function theme(s::Symbol; kw...) # reset? if s == :none || s == :default PlotUtils.clibrary(:Plots) - PlotUtils.default_cgrad(:inferno) + PlotUtils.default_cgrad(default = :sequential, sequential = :inferno) default(; bg = :white, bglegend = :match, @@ -24,8 +24,8 @@ function theme(s::Symbol; kw...) # update the default gradient and other defaults thm = PlotThemes._themes[s] if thm.gradient != nothing - PlotUtils.clibrary(:hisc) - PlotUtils.default_cgrad(default = PlotThemes.gradient_name(s)) + PlotUtils.clibrary(:misc) + PlotUtils.default_cgrad(default = :sequential, sequential = PlotThemes.gradient_name(s)) end default(; bg = thm.bg_secondary, From 7e41a2f40d6aeff6f086faa510f2e48308d1ec18 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Wed, 1 Mar 2017 22:18:34 +0100 Subject: [PATCH 050/107] sort colors --- src/recipes.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 1089ea10..3fa7a46e 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -823,10 +823,10 @@ end ticks := nothing legend := false - layout := length(library.lib) + layout --> length(library.lib) i = 0 - for grad in keys(library.lib) + for grad in sort(collect(keys(library.lib))) @series begin seriescolor := cgrad(grad, cl.args[1]) title := string(grad) From 37e2c18c3c01efe448720e49817c06e1afb008a6 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Fri, 3 Mar 2017 12:15:23 +0100 Subject: [PATCH 051/107] define default behaviour for symbol in gr_text --- src/backends/gr.jl | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index b4622145..27a0e2e3 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -172,6 +172,8 @@ function gr_polyline(x, y, func = GR.polyline; arrowside=:none) end end +gr_inqtext(x, y, s::Symbol) = gr_inqtext(x, y, string(s)) + function gr_inqtext(x, y, s) if length(s) >= 2 && s[1] == '$' && s[end] == '$' GR.inqtextext(x, y, s[2:end-1]) @@ -182,6 +184,8 @@ function gr_inqtext(x, y, s) end end +gr_text(x, y, s::Symbol) = gr_text(x, y, string(s)) + function gr_text(x, y, s) if length(s) >= 2 && s[1] == '$' && s[end] == '$' GR.mathtex(x, y, s[2:end-1]) From 5435ce20a935f4236ec8b2a31ebf6d7e690fe97e Mon Sep 17 00:00:00 2001 From: Andy Nowacki Date: Mon, 6 Mar 2017 10:25:21 +0000 Subject: [PATCH 052/107] Remove import of Base.scale(!); fixes #687 Base.scale and Base.scale! were deprecated in v0.5 and removed in v0.6-pre.alpha. Removing their import permits use on v0.6- and is fine since we REQUIRE v0.5 and above. --- src/components.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components.jl b/src/components.jl index bbb2f9c2..f660a149 100644 --- a/src/components.jl +++ b/src/components.jl @@ -174,7 +174,7 @@ function center(shape::Shape) Cx / 6A, Cy / 6A end -function Base.scale!(shape::Shape, x::Real, y::Real = x, c = center(shape)) +function scale!(shape::Shape, x::Real, y::Real = x, c = center(shape)) sx, sy = coords(shape) cx, cy = c for i=1:length(sx) @@ -184,7 +184,7 @@ function Base.scale!(shape::Shape, x::Real, y::Real = x, c = center(shape)) shape end -function Base.scale(shape::Shape, x::Real, y::Real = x, c = center(shape)) +function scale(shape::Shape, x::Real, y::Real = x, c = center(shape)) shapecopy = deepcopy(shape) scale!(shapecopy, x, y, c) end From f2235abf08cca48209954c7378075e55efd3f7f2 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 6 Mar 2017 23:52:59 +0100 Subject: [PATCH 053/107] Added logic to choose *round* DateTime tick positions --- src/axes.jl | 7 +++++++ src/recipes.jl | 7 +++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/axes.jl b/src/axes.jl index b9840e7a..dd36f824 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -156,6 +156,13 @@ function optimal_ticks_and_labels(axis::Axis, ticks = nothing) scale = axis[:scale] sf = scalefunc(scale) + # If the axis input was a Date or DateTime use a special logic to find + # "round" Date(Time)s as ticks + # TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime + if axis[:formatter] in (dateformatter, datetimeformatter) && scale == :identity + return optimize_datetime_ticks(amin, amax; k_min = 2, k_max = 4) + end + # get a list of well-laid-out ticks scaled_ticks = if ticks == nothing optimize_ticks( diff --git a/src/recipes.jl b/src/recipes.jl index 3fa7a46e..a4f576a3 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -792,8 +792,11 @@ abline!(args...; kw...) = abline!(current(), args...; kw...) # ------------------------------------------------- # Dates -@recipe f(::Type{Date}, dt::Date) = (dt -> convert(Int,dt), dt -> string(convert(Date,dt))) -@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int,dt), dt -> string(convert(DateTime,dt))) +dateformatter(dt) = string(convert(Date, convert(DateTime, dt))) +datetimeformatter(dt) = string(convert(DateTime, dt)) + +@recipe f(::Type{Date}, dt::Date) = (dt -> convert(Int, convert(DateTime, dt)), dateformatter) +@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int,dt), datetimeformatter) # ------------------------------------------------- # Complex Numbers From 7a0e03b3746ce8207d5572001a0b96b4d8a8e64e Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Tue, 7 Mar 2017 08:04:15 +0100 Subject: [PATCH 054/107] set dotted grid lines for pyplot --- src/backends/pyplot.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index e1003958..cdc44fb1 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1059,7 +1059,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) end if sp[:grid] fgcolor = py_color(sp[:foreground_color_grid]) - pyaxis[:grid](true, color = fgcolor) + pyaxis[:grid](true, color = fgcolor, linestyle = ":") ax[:set_axisbelow](true) end py_set_axis_colors(ax, axis) From fb2e12089f67a53fc92a70a3b53ee5f265a1006d Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Fri, 10 Mar 2017 23:53:00 +0100 Subject: [PATCH 055/107] remove density from like_histogram --- src/args.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/args.jl b/src/args.jl index 8f82fec0..0ede66a9 100644 --- a/src/args.jl +++ b/src/args.jl @@ -77,7 +77,7 @@ const _typeAliases = Dict{Symbol,Symbol}( add_non_underscore_aliases!(_typeAliases) -like_histogram(seriestype::Symbol) = seriestype in (:histogram, :density) +like_histogram(seriestype::Symbol) = seriestype == :histogram like_line(seriestype::Symbol) = seriestype in (:line, :path, :steppre, :steppost) like_surface(seriestype::Symbol) = seriestype in (:contour, :contourf, :contour3d, :heatmap, :surface, :wireframe, :image) From 76e1f4720bad7d956dfd076311430f244dd96990 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Mon, 13 Mar 2017 16:05:30 +0100 Subject: [PATCH 056/107] avoid ignoring ticks set by the user --- src/axes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/axes.jl b/src/axes.jl index dd36f824..d3893330 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -159,7 +159,7 @@ function optimal_ticks_and_labels(axis::Axis, ticks = nothing) # If the axis input was a Date or DateTime use a special logic to find # "round" Date(Time)s as ticks # TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime - if axis[:formatter] in (dateformatter, datetimeformatter) && scale == :identity + if axis[:formatter] in (dateformatter, datetimeformatter) && ticks == nothing && scale == :identity return optimize_datetime_ticks(amin, amax; k_min = 2, k_max = 4) end From ed102269e7eaa5e46ffdd74b09a92739d736a95b Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Tue, 14 Mar 2017 22:47:43 +0100 Subject: [PATCH 057/107] fix error on marker_z --- src/backends/plotly.jl | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 85c69105..e19759d2 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -409,6 +409,13 @@ plotly_surface_data(series::Series, a::AbstractVector) = a plotly_surface_data(series::Series, a::AbstractMatrix) = transpose_z(series, a, false) plotly_surface_data(series::Series, a::Surface) = plotly_surface_data(series, a.surf) +#ensures that a gradient is called if a single color is supplied where a gradient is needed (e.g. if a series recipe defines marker_z) +as_gradient(grad::ColorGradient, α) = grad +as_gradient(grad, α) = cgrad(alpha = α) + +# allows passing a ColorGradient where a single color is expected - the other backends allow this +PlotUtils.rgba_string(cg::ColorGradient) = rgba_string(cg[1]) + # get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict) function plotly_series(plt::Plot, series::Series) st = series[:seriestype] @@ -539,9 +546,10 @@ function plotly_series(plt::Plot, series::Series) rgba_string(series[:markercolor]) else # grad = ColorGradient(series[:markercolor], alpha=series[:markeralpha]) - grad = series[:markercolor] + grad = as_gradient(series[:markercolor], series[:markeralpha]) zmin, zmax = extrema(series[:marker_z]) - [rgba_string(grad[(zi - zmin) / (zmax - zmin)]) for zi in series[:marker_z]] + zrange = zmax == zmin ? 1 : zmax - zmin # if all marker_z values are the same, plot all markers same color (avoids division by zero in next line) + [rgba_string(grad[(zi - zmin) / zrange]) for zi in series[:marker_z]] end end From 57316484798535b747fceb0bb0695587b2b15df3 Mon Sep 17 00:00:00 2001 From: MA Laforge Date: Sat, 25 Mar 2017 17:51:33 -0400 Subject: [PATCH 058/107] Layout fix: Update plot.bb in _update_plot_object. --- src/backends/inspectdr.jl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/backends/inspectdr.jl b/src/backends/inspectdr.jl index cb290d22..c58ef884 100644 --- a/src/backends/inspectdr.jl +++ b/src/backends/inspectdr.jl @@ -411,8 +411,6 @@ function _before_layout_calcs(plt::Plot{InspectDRBackend}) plot = sp.o _initialize_subplot(plt, sp) _inspectdr_setupsubplot(sp) - graphbb = _inspectdr_to_pixels(plotarea(sp)) - plot.plotbb = InspectDR.plotbounds(plot.layout, graphbb) # add the annotations for ann in sp[:annotations] @@ -467,7 +465,11 @@ function _update_plot_object(plt::Plot{InspectDRBackend}) mplot = _inspectdr_getmplot(plt.o) if nothing == mplot; return; end - #TODO: should plotbb be computed here?? + for (i, sp) in enumerate(plt.subplots) + graphbb = _inspectdr_to_pixels(plotarea(sp)) + plot = mplot.subplots[i] + plot.plotbb = InspectDR.plotbounds(plot.layout, graphbb) + end gplot = _inspectdr_getgui(plt.o) if nothing == gplot; return; end From 06fd894f7945fe5f0e8200800522cef9ff36b5fb Mon Sep 17 00:00:00 2001 From: MA Laforge Date: Mon, 27 Mar 2017 10:04:30 -0400 Subject: [PATCH 059/107] Initial implementation for HDF5 plots. --- src/backends.jl | 1 + src/backends/hdf5.jl | 498 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 499 insertions(+) create mode 100644 src/backends/hdf5.jl diff --git a/src/backends.jl b/src/backends.jl index 779b91cc..5458a6c0 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -277,6 +277,7 @@ end @init_backend GLVisualize @init_backend PGFPlots @init_backend InspectDR +@init_backend HDF5 # --------------------------------------------------------- diff --git a/src/backends/hdf5.jl b/src/backends/hdf5.jl new file mode 100644 index 00000000..c7c8a126 --- /dev/null +++ b/src/backends/hdf5.jl @@ -0,0 +1,498 @@ +#HDF5 Plots: Save/replay plots to/from HDF5 +#------------------------------------------------------------------------------- + +#==Usage +=============================================================================== +Write to .hdf5 file using: + p = plot(...) + Plots.hdf5plot_write(p, "plotsave.hdf5") + +Read from .hdf5 file using: + pyplot() #Must first select backend + pread = Plots.hdf5plot_read("plotsave.hdf5") + display(pread) +==# + + +#==TODO +=============================================================================== + 1. Support more features + - SeriesAnnotations & GridLayout known to be missing. + 3. Improve error handling. + - Will likely crash if file format is off. + 2. Save data in a folder parallel to "plot". + - Will make it easier for users to locate data. + - Use HDF5 reference to link data? + 3. Develop an actual versioned file format. + - Should have some form of backward compatibility. + - Should be reliable for archival purposes. +==# + + +import FixedPointNumbers: N0f8 #In core Julia +immutable HDF5PlotNative; end #Dispatch type + + +#==Useful constants +===============================================================================# +const _hdf5_plotroot = "plot" +const _hdf5_dataroot = "data" #TODO: Eventually move data to different root (easier to locate)? +const _hdf5plot_datatypeid = "TYPE" #Attribute identifying type +const _hdf5plot_countid = "COUNT" #Attribute for storing count + +#Possible element types of high-level data types: +const HDF5PLOT_MAP_STR2TELEM = Dict{String, DataType}( + "NATIVE" => HDF5PlotNative, + "VOID" => Void, + "BOOL" => Bool, + "SYMBOL" => Symbol, + "TUPLE" => Tuple, + "RGBA" => ARGB{N0f8}, + "EXTREMA" => Extrema, + "LENGTH" => Length, + + #Sub-structure types: + "FONT" => Font, + "AXIS" => Axis, +) +const HDF5PLOT_MAP_TELEM2STR = Dict{DataType, String}(v=>k for (k,v) in HDF5PLOT_MAP_STR2TELEM) + + +#== +===============================================================================# + +const _hdf5_attr = merge_with_base_supported([ + :annotations, + :background_color_legend, :background_color_inside, :background_color_outside, + :foreground_color_grid, :foreground_color_legend, :foreground_color_title, + :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, + :label, + :linecolor, :linestyle, :linewidth, :linealpha, + :markershape, :markercolor, :markersize, :markeralpha, + :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, + :fillrange, :fillcolor, :fillalpha, + :bins, :bar_width, :bar_edges, :bar_position, + :title, :title_location, :titlefont, + :window_title, + :guide, :lims, :ticks, :scale, :flip, :rotation, + :tickfont, :guidefont, :legendfont, + :grid, :legend, :colorbar, + :marker_z, :line_z, :fill_z, + :levels, + :ribbon, :quiver, :arrow, + :orientation, + :overwrite_figure, + :polar, + :normalize, :weights, + :contours, :aspect_ratio, + :match_dimensions, + :clims, + :inset_subplots, + :dpi, + :colorbar_title, + ]) +const _hdf5_seriestype = [ + :path, :steppre, :steppost, :shape, + :scatter, :hexbin, #:histogram2d, :histogram, + # :bar, + :heatmap, :pie, :image, + :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe + ] +const _hdf5_style = [:auto, :solid, :dash, :dot, :dashdot] +const _hdf5_marker = vcat(_allMarkers, :pixel) +const _hdf5_scale = [:identity, :ln, :log2, :log10] +is_marker_supported(::HDF5Backend, shape::Shape) = true + +function add_backend_string(::HDF5Backend) + """ + if !Plots.is_installed("HDF5") + Pkg.add("HDF5") + end + """ +end + + +#==Helper functions +===============================================================================# + +_hdf5_plotelempath(subpath::String) = "$_hdf5_plotroot/$subpath" +_hdf5_datapath(subpath::String) = "$_hdf5_dataroot/$subpath" +_hdf5_map_str2telem(k::String) = HDF5PLOT_MAP_STR2TELEM[k] +_hdf5_map_str2telem(v::Vector) = HDF5PLOT_MAP_STR2TELEM[v[1]] + +function _hdf5_merge!(dest::Dict, src::Dict) + for (k, v) in src + if isa(v, Axis) + _hdf5_merge!(dest[k].d, v.d) + else + dest[k] = v + end + end + return +end + + +#== +===============================================================================# + +function _initialize_backend(::HDF5Backend) + @eval begin + import HDF5 + export HDF5 + end +end + +# --------------------------------------------------------------------------- + +# Create the window/figure for this backend. +function _create_backend_figure(plt::Plot{HDF5Backend}) + #Do nothing +end + +# --------------------------------------------------------------------------- + +# # this is called early in the pipeline, use it to make the plot current or something +# function _prepare_plot_object(plt::Plot{HDF5Backend}) +# end + +# --------------------------------------------------------------------------- + +# Set up the subplot within the backend object. +function _initialize_subplot(plt::Plot{HDF5Backend}, sp::Subplot{HDF5Backend}) + #Do nothing +end + +# --------------------------------------------------------------------------- + +# Add one series to the underlying backend object. +# Called once per series +# NOTE: Seems to be called when user calls plot()... even if backend +# plot, sp.o has not yet been constructed... +function _series_added(plt::Plot{HDF5Backend}, series::Series) + #Do nothing +end + +# --------------------------------------------------------------------------- + +# When series data is added/changed, this callback can do dynamic updates to the backend object. +# note: if the backend rebuilds the plot from scratch on display, then you might not do anything here. +function _series_updated(plt::Plot{HDF5Backend}, series::Series) + #Do nothing +end + +# --------------------------------------------------------------------------- + +# called just before updating layout bounding boxes... in case you need to prep +# for the calcs +function _before_layout_calcs(plt::Plot{HDF5Backend}) + #Do nothing +end + +# ---------------------------------------------------------------- + +# Set the (left, top, right, bottom) minimum padding around the plot area +# to fit ticks, tick labels, guides, colorbars, etc. +function _update_min_padding!(sp::Subplot{HDF5Backend}) + #Do nothing +end + +# ---------------------------------------------------------------- + +# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations]) +function _update_plot_object(plt::Plot{HDF5Backend}) + #Do nothing +end + +# ---------------------------------------------------------------- + +_show(io::IO, mime::MIME"text/plain", plt::Plot{HDF5Backend}) = nothing #Don't show + +# ---------------------------------------------------------------- + +# Display/show the plot (open a GUI window, or browser page, for example). +function _display(plt::Plot{HDF5Backend}) + msg = "HDF5 interface does not support `display()` function." + msg *= "\nUse `Plots.hdf5plot_write(::String)` method to write to .HDF5 \"plot\" file instead." + warn(msg) + return +end + + +#==HDF5 write functions +===============================================================================# + +function _hdf5plot_writetype(grp, k::String, tstr::Array{String}) + d = HDF5.d_open(grp, k) + HDF5.a_write(d, _hdf5plot_datatypeid, tstr) +end +function _hdf5plot_writetype(grp, k::String, T::Type) + tstr = HDF5PLOT_MAP_TELEM2STR[T] + d = HDF5.d_open(grp, k) + HDF5.a_write(d, _hdf5plot_datatypeid, tstr) +end +function _hdf5plot_writetype(grp, T::Type) #Write directly to group + tstr = HDF5PLOT_MAP_TELEM2STR[T] + HDF5.a_write(grp, _hdf5plot_datatypeid, tstr) +end +function _hdf5plot_writecount(grp, n::Int) #Write directly to group + HDF5.a_write(grp, _hdf5plot_countid, n) +end +function _hdf5plot_gwritefields(grp, k::String, v) + grp = HDF5.g_create(grp, k) + for _k in fieldnames(v) + _v = getfield(v, _k) + kstr = string(_k) + _hdf5plot_gwrite(grp, kstr, _v) + end + _hdf5plot_writetype(grp, typeof(v)) + return +end + +# Write data +# ---------------------------------------------------------------- + +function _hdf5plot_gwrite(grp, k::String, v) #Default + grp[k] = v + _hdf5plot_writetype(grp, k, HDF5PlotNative) +end +function _hdf5plot_gwrite(grp, k::String, v::Array{Any}) +# @show grp, k +# warn("Cannot write Array: $k=$v") +end +function _hdf5plot_gwrite(grp, k::String, v::Void) + grp[k] = 0 + _hdf5plot_writetype(grp, k, Void) +end +function _hdf5plot_gwrite(grp, k::String, v::Bool) + grp[k] = Int(v) + _hdf5plot_writetype(grp, k, Bool) +end +function _hdf5plot_gwrite(grp, k::String, v::Symbol) + grp[k] = string(v) + _hdf5plot_writetype(grp, k, Symbol) +end +function _hdf5plot_gwrite(grp, k::String, v::Tuple) + varr = [v...] + if isleaftype(eltype(varr)) + grp[k] = [v...] + _hdf5plot_writetype(grp, k, Tuple) + else + warn("Cannot write tuple: $k=$v") + end +end +function _hdf5plot_gwrite(grp, k::String, d::Dict) +# warn("Cannot write dict: $k=$d") +end +function _hdf5plot_gwrite(grp, k::String, v::Range) + _hdf5plot_gwrite(grp, k, collect(v)) #For now +end +function _hdf5plot_gwrite(grp, k::String, v::ARGB{N0f8}) + grp[k] = [v.r.i, v.g.i, v.b.i, v.alpha.i] + _hdf5plot_writetype(grp, k, ARGB{N0f8}) +end +function _hdf5plot_gwrite(grp, k::String, v::Colorant) + _hdf5plot_gwrite(grp, k, ARGB{N0f8}(v)) +end +function _hdf5plot_gwrite{T<:Colorant}(grp, k::String, v::Vector{T}) + #TODO +end +function _hdf5plot_gwrite(grp, k::String, v::Extrema) + grp[k] = [v.emin, v.emax] + _hdf5plot_writetype(grp, k, Extrema) +end +function _hdf5plot_gwrite{T}(grp, k::String, v::Length{T}) + grp[k] = v.value + _hdf5plot_writetype(grp, k, [HDF5PLOT_MAP_TELEM2STR[Length], string(T)]) +end + +# Write more complex structures: +# ---------------------------------------------------------------- + +function _hdf5plot_gwrite(grp, k::String, v::Union{Plot,Subplot}) +# @show :PLOTREF, k + #Don't write plot references +end +function _hdf5plot_gwrite(grp, k::String, v::Font) + _hdf5plot_gwritefields(grp, k, v) + return +end +function _hdf5plot_gwrite(grp, k::String, v::Axis) + grp = HDF5.g_create(grp, k) + for (_k, _v) in v.d + kstr = string(_k) + _hdf5plot_gwrite(grp, kstr, _v) + end + _hdf5plot_writetype(grp, Axis) + return +end + +function _hdf5plot_write(grp, d::Dict) + for (k, v) in d + kstr = string(k) + _hdf5plot_gwrite(grp, kstr, v) + end + return +end + +# Write main plot structures: +# ---------------------------------------------------------------- + +function _hdf5plot_write(sp::Subplot{HDF5Backend}, subpath::String, f) + f = f::HDF5.HDF5File #Assert + grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/attr")) + _hdf5plot_write(grp, sp.attr) + grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/series_list")) + _hdf5plot_writecount(grp, length(sp.series_list)) + for (i, series) in enumerate(sp.series_list) + grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/series_list/series$i")) + _hdf5plot_write(grp, series.d) + end + + return +end + +function _hdf5plot_write(plt::Plot{HDF5Backend}, f) + f = f::HDF5.HDF5File #Assert + + grp = HDF5.g_create(f, _hdf5_plotelempath("attr")) + _hdf5plot_write(grp, plt.attr) + + grp = HDF5.g_create(f, _hdf5_plotelempath("subplots")) + _hdf5plot_writecount(grp, length(plt.subplots)) + + for (i, sp) in enumerate(plt.subplots) + _hdf5plot_write(sp, "subplots/subplot$i", f) + end + + return +end +function hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString) + HDF5.h5open(path, "w") do file + _hdf5plot_write(plt, file) + end +end +hdf5plot_write(path::AbstractString) = hdf5plot_write(current(), path) + + +#==HDF5 playback (read) functions +===============================================================================# + +function _hdf5plot_readcount(grp) #Read directly from group + return HDF5.a_read(grp, _hdf5plot_countid) +end + +_hdf5plot_convert(T::Type{HDF5PlotNative}, v) = v +_hdf5plot_convert(T::Type{Void}, v) = nothing +_hdf5plot_convert(T::Type{Bool}, v) = (v!=0) +_hdf5plot_convert(T::Type{Symbol}, v) = Symbol(v) +_hdf5plot_convert(T::Type{Tuple}, v) = (v...) +function _hdf5plot_convert(T::Type{ARGB{N0f8}}, v) + r, g, b, a = reinterpret(N0f8, v) + return Colors.ARGB{N0f8}(r, g, b, a) +end +_hdf5plot_convert(T::Type{Extrema}, v) = Extrema(v[1], v[2]) + +# Read data structures: +# ---------------------------------------------------------------- + +function _hdf5plot_read(grp, k::String, T::Type, dtid) + v = HDF5.d_read(grp, k) + return _hdf5plot_convert(T, v) +end +function _hdf5plot_read(grp, k::String, T::Type{Length}, dtid::Vector) + v = HDF5.d_read(grp, k) + TU = Symbol(dtid[2]) + T = typeof(v) + return Length{TU,T}(v) +end + +# Read more complex data structures: +# ---------------------------------------------------------------- +function _hdf5plot_read(grp, k::String, T::Type{Font}, dtid) + grp = HDF5.g_open(grp, k) + + family = _hdf5plot_read(grp, "family") + pointsize = _hdf5plot_read(grp, "pointsize") + halign = _hdf5plot_read(grp, "halign") + valign = _hdf5plot_read(grp, "valign") + rotation = _hdf5plot_read(grp, "rotation") + color = _hdf5plot_read(grp, "color") + return Font(family, pointsize, halign, valign, rotation, color) +end +function _hdf5plot_read(grp, k::String, T::Type{Axis}, dtid) + grp = HDF5.g_open(grp, k) + kwlist = KW() + _hdf5plot_read(grp, kwlist) + return Axis([], kwlist) +end + +function _hdf5plot_read(grp, k::String) + dtid = HDF5.a_read(grp[k], _hdf5plot_datatypeid) + T = _hdf5_map_str2telem(dtid) #expect exception + return _hdf5plot_read(grp, k, T, dtid) +end + +#Read in values in group to populate d: +function _hdf5plot_read(grp, d::Dict) + gnames = names(grp) + for k in gnames + try + v = _hdf5plot_read(grp, k) + d[Symbol(k)] = v + catch + warn(k) + end + end + return +end + +# Read main plot structures: +# ---------------------------------------------------------------- + +function _hdf5plot_read(sp::Subplot, subpath::String, f) + f = f::HDF5.HDF5File #Assert + + grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/attr")) + kwlist = KW() + _hdf5plot_read(grp, kwlist) + _hdf5_merge!(sp.attr, kwlist) + + grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list")) + nseries = _hdf5plot_readcount(grp) + + for i in 1:nseries + grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list/series$i")) + kwlist = KW() + _hdf5plot_read(grp, kwlist) + plot!(sp, kwlist[:x], kwlist[:y]) #Add data & create data structures + _hdf5_merge!(sp.series_list[end].d, kwlist) + end + + return +end + +function _hdf5plot_read(plt::Plot, f) + f = f::HDF5.HDF5File #Assert + + grp = HDF5.g_open(f, _hdf5_plotelempath("attr")) + _hdf5plot_read(grp, plt.attr) + + for (i, sp) in enumerate(plt.subplots) + _hdf5plot_read(sp, "subplots/subplot$i", f) + end + + return +end + +function hdf5plot_read(path::AbstractString) + plt = nothing + HDF5.h5open(path, "r") do file + grp = HDF5.g_open(file, _hdf5_plotelempath("subplots")) + n = _hdf5plot_readcount(grp) + plt = plot(layout=n) #Get reference to a new plot + _hdf5plot_read(plt, file) + end + return plt +end + +#Last line From 034a1af649ca29efb1d293b85de7c711c629f421 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Wed, 29 Mar 2017 23:20:30 +0200 Subject: [PATCH 060/107] restore bar_width behavior for date x axis --- src/axes.jl | 21 +++++++++++++++++++-- src/recipes.jl | 6 +++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/axes.jl b/src/axes.jl index d3893330..7af2d7c5 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -158,9 +158,26 @@ function optimal_ticks_and_labels(axis::Axis, ticks = nothing) # If the axis input was a Date or DateTime use a special logic to find # "round" Date(Time)s as ticks + # This bypasses the rest of optimal_ticks_and_labels, because + # optimize_datetime_ticks returns ticks AND labels: the label format (Date + # or DateTime) is chosen based on the time span between amin and amax + # rather than on the input format # TODO: maybe: non-trivial scale (:ln, :log2, :log10) for date/datetime - if axis[:formatter] in (dateformatter, datetimeformatter) && ticks == nothing && scale == :identity - return optimize_datetime_ticks(amin, amax; k_min = 2, k_max = 4) + if ticks == nothing && scale == :identity + if axis[:formatter] == dateformatter + # optimize_datetime_ticks returns ticks and labels(!) based on + # integers/floats corresponding to the DateTime type. Thus, the axes + # limits, which resulted from converting the Date type to integers, + # are converted to 'DateTime integers' (actually floats) before + # being passed to optimize_datetime_ticks. + # (convert(Int, convert(DateTime, convert(Date, i))) == 87600000*i) + ticks, labels = optimize_datetime_ticks(864e5 * amin, 864e5 * amax; + k_min = 2, k_max = 4) + # Now the ticks are converted back to floats corresponding to Dates. + return ticks / 864e5, labels + elseif axis[:formatter] == datetimeformatter + return optimize_datetime_ticks(amin, amax; k_min = 2, k_max = 4) + end end # get a list of well-laid-out ticks diff --git a/src/recipes.jl b/src/recipes.jl index a4f576a3..3f63ea40 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -792,11 +792,11 @@ abline!(args...; kw...) = abline!(current(), args...; kw...) # ------------------------------------------------- # Dates -dateformatter(dt) = string(convert(Date, convert(DateTime, dt))) +dateformatter(dt) = string(convert(Date, dt)) datetimeformatter(dt) = string(convert(DateTime, dt)) -@recipe f(::Type{Date}, dt::Date) = (dt -> convert(Int, convert(DateTime, dt)), dateformatter) -@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int,dt), datetimeformatter) +@recipe f(::Type{Date}, dt::Date) = (dt -> convert(Int, dt), dateformatter) +@recipe f(::Type{DateTime}, dt::DateTime) = (dt -> convert(Int, dt), datetimeformatter) # ------------------------------------------------- # Complex Numbers From ffb9878893b75378f710fc5511c7e5518a0b9cdf Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Fri, 31 Mar 2017 16:26:29 +0200 Subject: [PATCH 061/107] gr: use correct colorbar() routine --- src/backends/gr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index b4622145..fc8d2700 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -421,7 +421,7 @@ end function gr_colorbar(sp::Subplot) if sp[:colorbar] != :none gr_set_viewport_cmap(sp) - GR.colormap() + GR.colorbar() gr_set_viewport_plotarea() end end From b4846bd5d55202bb6948fb3979f69705d2ef552f Mon Sep 17 00:00:00 2001 From: Michael Cawte Date: Thu, 6 Apr 2017 11:58:50 +1200 Subject: [PATCH 062/107] Added an animation with subplots example --- src/examples.jl | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/examples.jl b/src/examples.jl index 96872851..9f54509d 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -172,6 +172,24 @@ PlotExample("", end)] ), +PlotExample("Animation with subplots", + "The `layout` macro can be used to create an animation with subplots.", + [:(begin + l = @layout([[a; b] c]) + p = plot(plot([sin,cos],1,leg=false), + scatter([atan,cos],1,leg=false), + plot(log,1,xlims=(1,10π),ylims=(0,5),leg=false),layout=l) + + anim = Animation() + for x = linspace(1,10π,100) + plot(push!(p,x,Float64[sin(x),cos(x),atan(x),cos(x),log(x)])) + frame(anim) + end + end)] +), + + + PlotExample("Open/High/Low/Close", "Create an OHLC chart. Pass in a list of (open,high,low,close) tuples as your `y` argument. This uses recipes to first convert the tuples to OHLC objects, and subsequently create a :path series with the appropriate line segments.", [:(begin From 2d69fc39de7522770a53d9a9078314c8cebad37a Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Sat, 8 Apr 2017 13:14:41 +0200 Subject: [PATCH 063/107] add vectorfield alias to quiver --- src/args.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/args.jl b/src/args.jl index 0ede66a9..fa5a8e2f 100644 --- a/src/args.jl +++ b/src/args.jl @@ -65,6 +65,7 @@ const _typeAliases = Dict{Symbol,Symbol}( :polygon => :shape, :box => :boxplot, :velocity => :quiver, + :vectorfield => :quiver, :gradient => :quiver, :img => :image, :imshow => :image, @@ -445,7 +446,7 @@ add_aliases(:color_palette, :palette) add_aliases(:overwrite_figure, :clf, :clearfig, :overwrite, :reuse) add_aliases(:xerror, :xerr, :xerrorbar) add_aliases(:yerror, :yerr, :yerrorbar, :err, :errorbar) -add_aliases(:quiver, :velocity, :quiver2d, :gradient) +add_aliases(:quiver, :velocity, :quiver2d, :gradient, :vectorfield) add_aliases(:normalize, :norm, :normed, :normalized) add_aliases(:aspect_ratio, :aspectratio, :axis_ratio, :axisratio, :ratio) add_aliases(:match_dimensions, :transpose, :transpose_z) From dd3f65496ad98c8a393fd0f766dd81e0288b2de4 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Mon, 10 Apr 2017 12:54:57 +0200 Subject: [PATCH 064/107] gr: use correct marker size --- src/backends/gr.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index b4622145..33a41a34 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -283,7 +283,8 @@ end # draw ONE symbol marker function gr_draw_marker(xi, yi, msize::Number, shape::Symbol) GR.setmarkertype(gr_markertype[shape]) - GR.setmarkersize(0.3msize) + w, h = gr_plot_size + GR.setmarkersize(0.3msize / ((w + h) * 0.001)) GR.polymarker([xi], [yi]) end From ccb9df2a0870b9ff6307b6157f92114ac73917f6 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Mon, 10 Apr 2017 14:56:38 +0200 Subject: [PATCH 065/107] gr: use correct line width --- src/backends/gr.jl | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 0e021012..9eb16134 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -335,9 +335,10 @@ end # --------------------------------------------------------- -function gr_set_line(w, style, c) #, a) +function gr_set_line(lw, style, c) #, a) GR.setlinetype(gr_linetype[style]) - GR.setlinewidth(w) + w, h = gr_plot_size + GR.setlinewidth(max(1, lw / ((w + h) * 0.001))) gr_set_linecolor(c) #, a) end From 5d4f3182fc266347e8f529e708094cb40f91e65b Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Thu, 13 Apr 2017 10:51:03 +0200 Subject: [PATCH 066/107] gr: expand extrema for heatmap() axes --- src/backends/gr.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 9eb16134..24ddfd42 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -551,6 +551,10 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) end if st == :heatmap outside_ticks = true + x, y = heatmap_edges(series[:x]), heatmap_edges(series[:y]) + expand_extrema!(sp[:xaxis], x) + expand_extrema!(sp[:yaxis], y) + data_lims = gr_xy_axislims(sp) end end @@ -765,10 +769,6 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) # recompute data if typeof(z) <: Surface - # if st == :heatmap - # expand_extrema!(sp[:xaxis], (x[1]-0.5*(x[2]-x[1]), x[end]+0.5*(x[end]-x[end-1]))) - # expand_extrema!(sp[:yaxis], (y[1]-0.5*(y[2]-y[1]), y[end]+0.5*(y[end]-y[end-1]))) - # end z = vec(transpose_z(series, z.surf, false)) elseif ispolar(sp) if frng != nothing From 066ff96b5845599d860305b374f9dee4955857d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 13 Apr 2017 19:58:31 +0200 Subject: [PATCH 067/107] Use clims with :surface for PyPlot --- src/backends/pyplot.jl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index cdc44fb1..dcbd6461 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -683,6 +683,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) end z = transpose_z(series, z) if st == :surface + clims = sp[:clims] + if is_2tuple(clims) + isfinite(clims[1]) && (extrakw[:vmin] = clims[1]) + isfinite(clims[2]) && (extrakw[:vmax] = clims[2]) + end if series[:fill_z] != nothing # the surface colors are different than z-value extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf)) From 9a1efefbd45d882f2e8f247b0183825d6dc852ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 13 Apr 2017 22:17:34 +0200 Subject: [PATCH 068/107] Update Travis badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a47da192..b88fe561 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Plots -[![Build Status](https://travis-ci.org/tbreloff/Plots.jl.svg?branch=master)](https://travis-ci.org/tbreloff/Plots.jl) +[![Build Status](https://travis-ci.org/JuliaPlots/Plots.jl.svg?branch=master)](https://travis-ci.org/JuliaPlots/Plots.jl) [![Join the chat at https://gitter.im/tbreloff/Plots.jl](https://badges.gitter.im/tbreloff/Plots.jl.svg)](https://gitter.im/tbreloff/Plots.jl?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) From f11828075b2a8c46cb306d8c3deadaa0ed58a03d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 13 Apr 2017 22:20:03 +0200 Subject: [PATCH 069/107] Fix #770 --- src/components.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components.jl b/src/components.jl index f660a149..551fbee8 100644 --- a/src/components.jl +++ b/src/components.jl @@ -521,7 +521,7 @@ Base.Array(surf::Surface) = surf.surf for f in (:length, :size) @eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...) end -Base.copy(surf::Surface) = Surface{typeof(surf.surf)}(copy(surf.surf)) +Base.copy(surf::Surface) = Surface(copy(surf.surf)) Base.eltype{T}(surf::Surface{T}) = eltype(T) function expand_extrema!(a::Axis, surf::Surface) From 0d665c661f23a4248d2ecb76a723e4efbbd7a592 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Sat, 15 Apr 2017 13:14:14 -0700 Subject: [PATCH 070/107] complex recipe --- src/recipes.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/recipes.jl b/src/recipes.jl index 3f63ea40..83b3a8e8 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -809,6 +809,18 @@ datetimeformatter(dt) = string(convert(DateTime, dt)) real(cp.args[1]), imag(cp.args[1]) end +# Splits a complex matrix to its real and complex parts +# Reals defaults solid, imaginary defaults dashed +# Label defaults are changed to match the real-imaginary reference / indexing +@recipe function f{T<:Number,T2<:Number}(x::AbstractArray{T},y::Array{Complex{T2}}) + A = real.(y) + B = imag.(y) + _y = [!iseven(i) ? A[:,i÷2+1] : B[:,i÷2] for i in 1:2size(A,2)] + linestyle --> reshape([!iseven(i) ? :solid : :dash for i in 1:2size(A,2)],1,2size(A,2)) + label --> reshape([!iseven(i) ? "Re(y$(i÷2+1))" : "Im(y$(i÷2))" for i in 1:2size(A,2)],1,2size(A,2)) + x,_y +end + # -------------------------------------------------- # Color Gradients From 1852ba99b35b96c6b2a858c3744c1edcd32ed334 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Sat, 15 Apr 2017 13:16:40 -0700 Subject: [PATCH 071/107] force real x --- src/recipes.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 83b3a8e8..a22dc069 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -811,8 +811,8 @@ end # Splits a complex matrix to its real and complex parts # Reals defaults solid, imaginary defaults dashed -# Label defaults are changed to match the real-imaginary reference / indexing -@recipe function f{T<:Number,T2<:Number}(x::AbstractArray{T},y::Array{Complex{T2}}) +# Label defaults are changed to match the real-imaginary reference / indexing +@recipe function f{T<:Real,T2<:Number}(x::AbstractArray{T},y::Array{Complex{T2}}) A = real.(y) B = imag.(y) _y = [!iseven(i) ? A[:,i÷2+1] : B[:,i÷2] for i in 1:2size(A,2)] From 9a59df793dba43aed9104598b3d6ae591840d859 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Sat, 15 Apr 2017 17:00:00 -0700 Subject: [PATCH 072/107] coloring setup --- src/recipes.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/recipes.jl b/src/recipes.jl index a22dc069..984b4a0a 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -818,6 +818,7 @@ end _y = [!iseven(i) ? A[:,i÷2+1] : B[:,i÷2] for i in 1:2size(A,2)] linestyle --> reshape([!iseven(i) ? :solid : :dash for i in 1:2size(A,2)],1,2size(A,2)) label --> reshape([!iseven(i) ? "Re(y$(i÷2+1))" : "Im(y$(i÷2))" for i in 1:2size(A,2)],1,2size(A,2)) + color --> reshape([!iseven(i) ? i÷2+1 : i÷2 for i in 1:2size(A,2)],1,2size(A,2)) x,_y end From 7def4e8e7372cff8b6d046d8f578635964f173a9 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Sun, 16 Apr 2017 13:01:51 -0700 Subject: [PATCH 073/107] add transformation option --- src/recipes.jl | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 984b4a0a..1bef17c8 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -812,14 +812,30 @@ end # Splits a complex matrix to its real and complex parts # Reals defaults solid, imaginary defaults dashed # Label defaults are changed to match the real-imaginary reference / indexing -@recipe function f{T<:Real,T2<:Number}(x::AbstractArray{T},y::Array{Complex{T2}}) - A = real.(y) - B = imag.(y) - _y = [!iseven(i) ? A[:,i÷2+1] : B[:,i÷2] for i in 1:2size(A,2)] - linestyle --> reshape([!iseven(i) ? :solid : :dash for i in 1:2size(A,2)],1,2size(A,2)) - label --> reshape([!iseven(i) ? "Re(y$(i÷2+1))" : "Im(y$(i÷2))" for i in 1:2size(A,2)],1,2size(A,2)) - color --> reshape([!iseven(i) ? i÷2+1 : i÷2 for i in 1:2size(A,2)],1,2size(A,2)) - x,_y +@recipe function f{T<:Real,T2<:Number}(x::AbstractArray{T},y::Array{Complex{T2}}; + transformation=:split2D) + if transformation==:split2D + A = real.(y) + B = imag.(y) + _y = [!iseven(i) ? A[:,i÷2+1] : B[:,i÷2] for i in 1:2size(A,2)] + linestyle --> reshape([!iseven(i) ? :solid : :dash for i in 1:2size(A,2)],1,2size(A,2)) + label --> reshape([!iseven(i) ? "Re(y$(i÷2+1))" : "Im(y$(i÷2))" for i in 1:2size(A,2)],1,2size(A,2)) + color --> reshape([!iseven(i) ? i÷2+1 : i÷2 for i in 1:2size(A,2)],1,2size(A,2)) + retval = (x,_y) + elseif transformation==:split3D + A = real.(y) + B = imag.(y) + ylabel --> "Re(y)" + zlabel --> "Im(y)" + retval = (x,A,B) + elseif transformation==:modulus + _y = norm.(y) + label --> reshape(["||y$(i)||" for i in 1:size(_y,2)],1,size(_y,2)) + retval = (x,_y) + else + error("Transformation unknown. Please use :split2D, :split3D, or :modulus") + end + (retval...) end From 0be08242077129b3c40da812b793d746ac45f187 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Sun, 16 Apr 2017 13:14:12 -0700 Subject: [PATCH 074/107] (complex) type recipe --- src/recipes.jl | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 1bef17c8..48c201bf 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -801,12 +801,10 @@ datetimeformatter(dt) = string(convert(DateTime, dt)) # ------------------------------------------------- # Complex Numbers -@userplot ComplexPlot -@recipe function f(cp::ComplexPlot) - xguide --> "Real Part" - yguide --> "Imaginary Part" - seriestype --> :scatter - real(cp.args[1]), imag(cp.args[1]) +@recipe function f{T<:Number}(A::Array{Complex{T}}) + xguide --> "Re(x)" + yguide --> "Im(x)" + real.(A), imag.(A) end # Splits a complex matrix to its real and complex parts From 3e7dd9bb77cd51ac432aaae5c5e7bdfb481f3566 Mon Sep 17 00:00:00 2001 From: ChrisRackauckas Date: Mon, 17 Apr 2017 22:15:13 -0700 Subject: [PATCH 075/107] tone down recipe --- src/recipes.jl | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 48c201bf..5be5b6e0 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -810,30 +810,10 @@ end # Splits a complex matrix to its real and complex parts # Reals defaults solid, imaginary defaults dashed # Label defaults are changed to match the real-imaginary reference / indexing -@recipe function f{T<:Real,T2<:Number}(x::AbstractArray{T},y::Array{Complex{T2}}; - transformation=:split2D) - if transformation==:split2D - A = real.(y) - B = imag.(y) - _y = [!iseven(i) ? A[:,i÷2+1] : B[:,i÷2] for i in 1:2size(A,2)] - linestyle --> reshape([!iseven(i) ? :solid : :dash for i in 1:2size(A,2)],1,2size(A,2)) - label --> reshape([!iseven(i) ? "Re(y$(i÷2+1))" : "Im(y$(i÷2))" for i in 1:2size(A,2)],1,2size(A,2)) - color --> reshape([!iseven(i) ? i÷2+1 : i÷2 for i in 1:2size(A,2)],1,2size(A,2)) - retval = (x,_y) - elseif transformation==:split3D - A = real.(y) - B = imag.(y) - ylabel --> "Re(y)" - zlabel --> "Im(y)" - retval = (x,A,B) - elseif transformation==:modulus - _y = norm.(y) - label --> reshape(["||y$(i)||" for i in 1:size(_y,2)],1,size(_y,2)) - retval = (x,_y) - else - error("Transformation unknown. Please use :split2D, :split3D, or :modulus") - end - (retval...) +@recipe function f{T<:Real,T2}(x::AbstractArray{T},y::Array{Complex{T2}}) + ylabel --> "Re(y)" + zlabel --> "Im(y)" + x,real.(y),imag.(y) end From 5166d164062c93e0a0bab11829b4143c599e2c8d Mon Sep 17 00:00:00 2001 From: Jonathan Anderson Date: Tue, 18 Apr 2017 10:32:07 -0500 Subject: [PATCH 076/107] Update gr.jl inline display to match GR.jl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I wanted to switch from using GR directly to using Plots, but the inline plots were not working for me. The following change is sufficient to generate inline plots in iterm for me https://github.com/jheinen/GR.jl/blob/0f167b2be921a0014c405f760a1e1bc22b222751/src/GR.jl#L3014 julia> versioninfo() Julia Version 0.6.0-pre.beta.187 Commit 55c97fb* (2017-04-17 23:06 UTC) Platform Info: OS: Linux (x86_64-redhat-linux) CPU: Intel(R) Xeon(R) CPU E5-2670 v3 @ 2.30GHz WORD_SIZE: 64 BLAS: libopenblas (USE64BITINT DYNAMIC_ARCH NO_AFFINITY Haswell) LAPACK: libopenblas64_ LIBM: libopenlibm LLVM: libLLVM-3.9.1 (ORCJIT, haswell) julia> using TerminalExtensions julia> using Plots julia> gr(display_type=:inline); julia> z=[sin(sqrt(x^2+y^2)) for x in linspace(-2π,2π,50), y in linspace(-2π,2π,50)]; julia> contour(z) --- src/backends/gr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 24ddfd42..b8e3b460 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -1109,7 +1109,7 @@ function _display(plt::Plot{GRBackend}) ENV["GKS_FILEPATH"] = filepath gr_display(plt) GR.emergencyclosegks() - content = string("\033]1337;File=inline=1;preserveAspectRatio=0:", base64encode(open(readbytes, filepath)), "\a") + content = string("\033]1337;File=inline=1;preserveAspectRatio=0:", base64encode(open(read, filepath)), "\a") println(content) rm(filepath) else From ec6f75b59e8b67eef6ec04f3183cb87f609d8482 Mon Sep 17 00:00:00 2001 From: Michael Krabbe Borregaard Date: Wed, 19 Apr 2017 16:14:48 +0200 Subject: [PATCH 077/107] Revert "Initial implementation for HDF5 plots." --- src/backends.jl | 1 - src/backends/hdf5.jl | 498 ------------------------------------------- 2 files changed, 499 deletions(-) delete mode 100644 src/backends/hdf5.jl diff --git a/src/backends.jl b/src/backends.jl index 5458a6c0..779b91cc 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -277,7 +277,6 @@ end @init_backend GLVisualize @init_backend PGFPlots @init_backend InspectDR -@init_backend HDF5 # --------------------------------------------------------- diff --git a/src/backends/hdf5.jl b/src/backends/hdf5.jl deleted file mode 100644 index c7c8a126..00000000 --- a/src/backends/hdf5.jl +++ /dev/null @@ -1,498 +0,0 @@ -#HDF5 Plots: Save/replay plots to/from HDF5 -#------------------------------------------------------------------------------- - -#==Usage -=============================================================================== -Write to .hdf5 file using: - p = plot(...) - Plots.hdf5plot_write(p, "plotsave.hdf5") - -Read from .hdf5 file using: - pyplot() #Must first select backend - pread = Plots.hdf5plot_read("plotsave.hdf5") - display(pread) -==# - - -#==TODO -=============================================================================== - 1. Support more features - - SeriesAnnotations & GridLayout known to be missing. - 3. Improve error handling. - - Will likely crash if file format is off. - 2. Save data in a folder parallel to "plot". - - Will make it easier for users to locate data. - - Use HDF5 reference to link data? - 3. Develop an actual versioned file format. - - Should have some form of backward compatibility. - - Should be reliable for archival purposes. -==# - - -import FixedPointNumbers: N0f8 #In core Julia -immutable HDF5PlotNative; end #Dispatch type - - -#==Useful constants -===============================================================================# -const _hdf5_plotroot = "plot" -const _hdf5_dataroot = "data" #TODO: Eventually move data to different root (easier to locate)? -const _hdf5plot_datatypeid = "TYPE" #Attribute identifying type -const _hdf5plot_countid = "COUNT" #Attribute for storing count - -#Possible element types of high-level data types: -const HDF5PLOT_MAP_STR2TELEM = Dict{String, DataType}( - "NATIVE" => HDF5PlotNative, - "VOID" => Void, - "BOOL" => Bool, - "SYMBOL" => Symbol, - "TUPLE" => Tuple, - "RGBA" => ARGB{N0f8}, - "EXTREMA" => Extrema, - "LENGTH" => Length, - - #Sub-structure types: - "FONT" => Font, - "AXIS" => Axis, -) -const HDF5PLOT_MAP_TELEM2STR = Dict{DataType, String}(v=>k for (k,v) in HDF5PLOT_MAP_STR2TELEM) - - -#== -===============================================================================# - -const _hdf5_attr = merge_with_base_supported([ - :annotations, - :background_color_legend, :background_color_inside, :background_color_outside, - :foreground_color_grid, :foreground_color_legend, :foreground_color_title, - :foreground_color_axis, :foreground_color_border, :foreground_color_guide, :foreground_color_text, - :label, - :linecolor, :linestyle, :linewidth, :linealpha, - :markershape, :markercolor, :markersize, :markeralpha, - :markerstrokewidth, :markerstrokecolor, :markerstrokealpha, - :fillrange, :fillcolor, :fillalpha, - :bins, :bar_width, :bar_edges, :bar_position, - :title, :title_location, :titlefont, - :window_title, - :guide, :lims, :ticks, :scale, :flip, :rotation, - :tickfont, :guidefont, :legendfont, - :grid, :legend, :colorbar, - :marker_z, :line_z, :fill_z, - :levels, - :ribbon, :quiver, :arrow, - :orientation, - :overwrite_figure, - :polar, - :normalize, :weights, - :contours, :aspect_ratio, - :match_dimensions, - :clims, - :inset_subplots, - :dpi, - :colorbar_title, - ]) -const _hdf5_seriestype = [ - :path, :steppre, :steppost, :shape, - :scatter, :hexbin, #:histogram2d, :histogram, - # :bar, - :heatmap, :pie, :image, - :contour, :contour3d, :path3d, :scatter3d, :surface, :wireframe - ] -const _hdf5_style = [:auto, :solid, :dash, :dot, :dashdot] -const _hdf5_marker = vcat(_allMarkers, :pixel) -const _hdf5_scale = [:identity, :ln, :log2, :log10] -is_marker_supported(::HDF5Backend, shape::Shape) = true - -function add_backend_string(::HDF5Backend) - """ - if !Plots.is_installed("HDF5") - Pkg.add("HDF5") - end - """ -end - - -#==Helper functions -===============================================================================# - -_hdf5_plotelempath(subpath::String) = "$_hdf5_plotroot/$subpath" -_hdf5_datapath(subpath::String) = "$_hdf5_dataroot/$subpath" -_hdf5_map_str2telem(k::String) = HDF5PLOT_MAP_STR2TELEM[k] -_hdf5_map_str2telem(v::Vector) = HDF5PLOT_MAP_STR2TELEM[v[1]] - -function _hdf5_merge!(dest::Dict, src::Dict) - for (k, v) in src - if isa(v, Axis) - _hdf5_merge!(dest[k].d, v.d) - else - dest[k] = v - end - end - return -end - - -#== -===============================================================================# - -function _initialize_backend(::HDF5Backend) - @eval begin - import HDF5 - export HDF5 - end -end - -# --------------------------------------------------------------------------- - -# Create the window/figure for this backend. -function _create_backend_figure(plt::Plot{HDF5Backend}) - #Do nothing -end - -# --------------------------------------------------------------------------- - -# # this is called early in the pipeline, use it to make the plot current or something -# function _prepare_plot_object(plt::Plot{HDF5Backend}) -# end - -# --------------------------------------------------------------------------- - -# Set up the subplot within the backend object. -function _initialize_subplot(plt::Plot{HDF5Backend}, sp::Subplot{HDF5Backend}) - #Do nothing -end - -# --------------------------------------------------------------------------- - -# Add one series to the underlying backend object. -# Called once per series -# NOTE: Seems to be called when user calls plot()... even if backend -# plot, sp.o has not yet been constructed... -function _series_added(plt::Plot{HDF5Backend}, series::Series) - #Do nothing -end - -# --------------------------------------------------------------------------- - -# When series data is added/changed, this callback can do dynamic updates to the backend object. -# note: if the backend rebuilds the plot from scratch on display, then you might not do anything here. -function _series_updated(plt::Plot{HDF5Backend}, series::Series) - #Do nothing -end - -# --------------------------------------------------------------------------- - -# called just before updating layout bounding boxes... in case you need to prep -# for the calcs -function _before_layout_calcs(plt::Plot{HDF5Backend}) - #Do nothing -end - -# ---------------------------------------------------------------- - -# Set the (left, top, right, bottom) minimum padding around the plot area -# to fit ticks, tick labels, guides, colorbars, etc. -function _update_min_padding!(sp::Subplot{HDF5Backend}) - #Do nothing -end - -# ---------------------------------------------------------------- - -# Override this to update plot items (title, xlabel, etc), and add annotations (d[:annotations]) -function _update_plot_object(plt::Plot{HDF5Backend}) - #Do nothing -end - -# ---------------------------------------------------------------- - -_show(io::IO, mime::MIME"text/plain", plt::Plot{HDF5Backend}) = nothing #Don't show - -# ---------------------------------------------------------------- - -# Display/show the plot (open a GUI window, or browser page, for example). -function _display(plt::Plot{HDF5Backend}) - msg = "HDF5 interface does not support `display()` function." - msg *= "\nUse `Plots.hdf5plot_write(::String)` method to write to .HDF5 \"plot\" file instead." - warn(msg) - return -end - - -#==HDF5 write functions -===============================================================================# - -function _hdf5plot_writetype(grp, k::String, tstr::Array{String}) - d = HDF5.d_open(grp, k) - HDF5.a_write(d, _hdf5plot_datatypeid, tstr) -end -function _hdf5plot_writetype(grp, k::String, T::Type) - tstr = HDF5PLOT_MAP_TELEM2STR[T] - d = HDF5.d_open(grp, k) - HDF5.a_write(d, _hdf5plot_datatypeid, tstr) -end -function _hdf5plot_writetype(grp, T::Type) #Write directly to group - tstr = HDF5PLOT_MAP_TELEM2STR[T] - HDF5.a_write(grp, _hdf5plot_datatypeid, tstr) -end -function _hdf5plot_writecount(grp, n::Int) #Write directly to group - HDF5.a_write(grp, _hdf5plot_countid, n) -end -function _hdf5plot_gwritefields(grp, k::String, v) - grp = HDF5.g_create(grp, k) - for _k in fieldnames(v) - _v = getfield(v, _k) - kstr = string(_k) - _hdf5plot_gwrite(grp, kstr, _v) - end - _hdf5plot_writetype(grp, typeof(v)) - return -end - -# Write data -# ---------------------------------------------------------------- - -function _hdf5plot_gwrite(grp, k::String, v) #Default - grp[k] = v - _hdf5plot_writetype(grp, k, HDF5PlotNative) -end -function _hdf5plot_gwrite(grp, k::String, v::Array{Any}) -# @show grp, k -# warn("Cannot write Array: $k=$v") -end -function _hdf5plot_gwrite(grp, k::String, v::Void) - grp[k] = 0 - _hdf5plot_writetype(grp, k, Void) -end -function _hdf5plot_gwrite(grp, k::String, v::Bool) - grp[k] = Int(v) - _hdf5plot_writetype(grp, k, Bool) -end -function _hdf5plot_gwrite(grp, k::String, v::Symbol) - grp[k] = string(v) - _hdf5plot_writetype(grp, k, Symbol) -end -function _hdf5plot_gwrite(grp, k::String, v::Tuple) - varr = [v...] - if isleaftype(eltype(varr)) - grp[k] = [v...] - _hdf5plot_writetype(grp, k, Tuple) - else - warn("Cannot write tuple: $k=$v") - end -end -function _hdf5plot_gwrite(grp, k::String, d::Dict) -# warn("Cannot write dict: $k=$d") -end -function _hdf5plot_gwrite(grp, k::String, v::Range) - _hdf5plot_gwrite(grp, k, collect(v)) #For now -end -function _hdf5plot_gwrite(grp, k::String, v::ARGB{N0f8}) - grp[k] = [v.r.i, v.g.i, v.b.i, v.alpha.i] - _hdf5plot_writetype(grp, k, ARGB{N0f8}) -end -function _hdf5plot_gwrite(grp, k::String, v::Colorant) - _hdf5plot_gwrite(grp, k, ARGB{N0f8}(v)) -end -function _hdf5plot_gwrite{T<:Colorant}(grp, k::String, v::Vector{T}) - #TODO -end -function _hdf5plot_gwrite(grp, k::String, v::Extrema) - grp[k] = [v.emin, v.emax] - _hdf5plot_writetype(grp, k, Extrema) -end -function _hdf5plot_gwrite{T}(grp, k::String, v::Length{T}) - grp[k] = v.value - _hdf5plot_writetype(grp, k, [HDF5PLOT_MAP_TELEM2STR[Length], string(T)]) -end - -# Write more complex structures: -# ---------------------------------------------------------------- - -function _hdf5plot_gwrite(grp, k::String, v::Union{Plot,Subplot}) -# @show :PLOTREF, k - #Don't write plot references -end -function _hdf5plot_gwrite(grp, k::String, v::Font) - _hdf5plot_gwritefields(grp, k, v) - return -end -function _hdf5plot_gwrite(grp, k::String, v::Axis) - grp = HDF5.g_create(grp, k) - for (_k, _v) in v.d - kstr = string(_k) - _hdf5plot_gwrite(grp, kstr, _v) - end - _hdf5plot_writetype(grp, Axis) - return -end - -function _hdf5plot_write(grp, d::Dict) - for (k, v) in d - kstr = string(k) - _hdf5plot_gwrite(grp, kstr, v) - end - return -end - -# Write main plot structures: -# ---------------------------------------------------------------- - -function _hdf5plot_write(sp::Subplot{HDF5Backend}, subpath::String, f) - f = f::HDF5.HDF5File #Assert - grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/attr")) - _hdf5plot_write(grp, sp.attr) - grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/series_list")) - _hdf5plot_writecount(grp, length(sp.series_list)) - for (i, series) in enumerate(sp.series_list) - grp = HDF5.g_create(f, _hdf5_plotelempath("$subpath/series_list/series$i")) - _hdf5plot_write(grp, series.d) - end - - return -end - -function _hdf5plot_write(plt::Plot{HDF5Backend}, f) - f = f::HDF5.HDF5File #Assert - - grp = HDF5.g_create(f, _hdf5_plotelempath("attr")) - _hdf5plot_write(grp, plt.attr) - - grp = HDF5.g_create(f, _hdf5_plotelempath("subplots")) - _hdf5plot_writecount(grp, length(plt.subplots)) - - for (i, sp) in enumerate(plt.subplots) - _hdf5plot_write(sp, "subplots/subplot$i", f) - end - - return -end -function hdf5plot_write(plt::Plot{HDF5Backend}, path::AbstractString) - HDF5.h5open(path, "w") do file - _hdf5plot_write(plt, file) - end -end -hdf5plot_write(path::AbstractString) = hdf5plot_write(current(), path) - - -#==HDF5 playback (read) functions -===============================================================================# - -function _hdf5plot_readcount(grp) #Read directly from group - return HDF5.a_read(grp, _hdf5plot_countid) -end - -_hdf5plot_convert(T::Type{HDF5PlotNative}, v) = v -_hdf5plot_convert(T::Type{Void}, v) = nothing -_hdf5plot_convert(T::Type{Bool}, v) = (v!=0) -_hdf5plot_convert(T::Type{Symbol}, v) = Symbol(v) -_hdf5plot_convert(T::Type{Tuple}, v) = (v...) -function _hdf5plot_convert(T::Type{ARGB{N0f8}}, v) - r, g, b, a = reinterpret(N0f8, v) - return Colors.ARGB{N0f8}(r, g, b, a) -end -_hdf5plot_convert(T::Type{Extrema}, v) = Extrema(v[1], v[2]) - -# Read data structures: -# ---------------------------------------------------------------- - -function _hdf5plot_read(grp, k::String, T::Type, dtid) - v = HDF5.d_read(grp, k) - return _hdf5plot_convert(T, v) -end -function _hdf5plot_read(grp, k::String, T::Type{Length}, dtid::Vector) - v = HDF5.d_read(grp, k) - TU = Symbol(dtid[2]) - T = typeof(v) - return Length{TU,T}(v) -end - -# Read more complex data structures: -# ---------------------------------------------------------------- -function _hdf5plot_read(grp, k::String, T::Type{Font}, dtid) - grp = HDF5.g_open(grp, k) - - family = _hdf5plot_read(grp, "family") - pointsize = _hdf5plot_read(grp, "pointsize") - halign = _hdf5plot_read(grp, "halign") - valign = _hdf5plot_read(grp, "valign") - rotation = _hdf5plot_read(grp, "rotation") - color = _hdf5plot_read(grp, "color") - return Font(family, pointsize, halign, valign, rotation, color) -end -function _hdf5plot_read(grp, k::String, T::Type{Axis}, dtid) - grp = HDF5.g_open(grp, k) - kwlist = KW() - _hdf5plot_read(grp, kwlist) - return Axis([], kwlist) -end - -function _hdf5plot_read(grp, k::String) - dtid = HDF5.a_read(grp[k], _hdf5plot_datatypeid) - T = _hdf5_map_str2telem(dtid) #expect exception - return _hdf5plot_read(grp, k, T, dtid) -end - -#Read in values in group to populate d: -function _hdf5plot_read(grp, d::Dict) - gnames = names(grp) - for k in gnames - try - v = _hdf5plot_read(grp, k) - d[Symbol(k)] = v - catch - warn(k) - end - end - return -end - -# Read main plot structures: -# ---------------------------------------------------------------- - -function _hdf5plot_read(sp::Subplot, subpath::String, f) - f = f::HDF5.HDF5File #Assert - - grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/attr")) - kwlist = KW() - _hdf5plot_read(grp, kwlist) - _hdf5_merge!(sp.attr, kwlist) - - grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list")) - nseries = _hdf5plot_readcount(grp) - - for i in 1:nseries - grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/series_list/series$i")) - kwlist = KW() - _hdf5plot_read(grp, kwlist) - plot!(sp, kwlist[:x], kwlist[:y]) #Add data & create data structures - _hdf5_merge!(sp.series_list[end].d, kwlist) - end - - return -end - -function _hdf5plot_read(plt::Plot, f) - f = f::HDF5.HDF5File #Assert - - grp = HDF5.g_open(f, _hdf5_plotelempath("attr")) - _hdf5plot_read(grp, plt.attr) - - for (i, sp) in enumerate(plt.subplots) - _hdf5plot_read(sp, "subplots/subplot$i", f) - end - - return -end - -function hdf5plot_read(path::AbstractString) - plt = nothing - HDF5.h5open(path, "r") do file - grp = HDF5.g_open(file, _hdf5_plotelempath("subplots")) - n = _hdf5plot_readcount(grp) - plt = plot(layout=n) #Get reference to a new plot - _hdf5plot_read(plt, file) - end - return plt -end - -#Last line From 7a1dd0db29b3f181782842cfec4201282d736d28 Mon Sep 17 00:00:00 2001 From: Godisemo Date: Thu, 20 Apr 2017 17:40:05 +0200 Subject: [PATCH 078/107] Add colorbar_title attr to plotly(js) backends fixes issue #773 --- src/backends/plotly.jl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index e19759d2..43a1bb70 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -19,7 +19,7 @@ const _plotly_attr = merge_with_base_supported([ :window_title, :guide, :lims, :ticks, :scale, :flip, :rotation, :tickfont, :guidefont, :legendfont, - :grid, :legend, :colorbar, + :grid, :legend, :colorbar, :colorbar_title, :marker_z, :fill_z, :levels, :ribbon, :quiver, :orientation, @@ -446,6 +446,8 @@ function plotly_series(plt::Plot, series::Series) end end + d_out[:colorbar] = KW(:title => sp[:colorbar_title]) + clims = sp[:clims] if is_2tuple(clims) d_out[:zmin], d_out[:zmax] = clims From 6b250d1ab6d29cf1841573ae37ba68c6f0a8cdea Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Tue, 18 Apr 2017 17:46:38 +0200 Subject: [PATCH 079/107] Prevent inadvertent Conda ROOTENV initialization Conda._installed_packages_dict() always runs Conda._install_conda(), even when using an external conda installation (e.g. via Anaconda). --- src/backends/pyplot.jl | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index cdc44fb1..1fffcf04 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -89,10 +89,12 @@ function _initialize_backend(::PyPlotBackend) @eval begin # avoid Conda update that causes Segfault with qt >=4.8.6 on Ubuntu https://github.com/JuliaPy/PyPlot.jl/issues/234 import Conda - kw = Conda._installed_packages_dict() - if (!haskey(kw,"qt") || (qt_version=get(kw,"qt",0)[1]!=v"4.8.5")) - print("\n If the code has a Segmentation fault error switch to qt v4.8.5 by pasting the following code into julia: \n \n") - print(add_backend_string(PyPlotBackend())) + if isfile(Conda.conda) # Using Conda-internal conda (instead of an external conda) + kw = Conda._installed_packages_dict() + if (!haskey(kw,"qt") || (qt_version=get(kw,"qt",0)[1]!=v"4.8.5")) + print("\n If the code has a Segmentation fault error switch to qt v4.8.5 by pasting the following code into julia: \n \n") + print(add_backend_string(PyPlotBackend())) + end end end end From 5e5e1850ac39e7b83ea47f9658375a4b5bb19d20 Mon Sep 17 00:00:00 2001 From: Huckleberry Febbo Date: Mon, 1 May 2017 11:04:39 -0400 Subject: [PATCH 080/107] deleted old warning for conda --- src/backends/pyplot.jl | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index cdc44fb1..3adfa8a5 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -85,17 +85,7 @@ function _initialize_backend(::PyPlotBackend) const pycollections = PyPlot.pywrap(PyPlot.pyimport("matplotlib.collections")) const pyart3d = PyPlot.pywrap(PyPlot.pyimport("mpl_toolkits.mplot3d.art3d")) end - if is_linux() - @eval begin - # avoid Conda update that causes Segfault with qt >=4.8.6 on Ubuntu https://github.com/JuliaPy/PyPlot.jl/issues/234 - import Conda - kw = Conda._installed_packages_dict() - if (!haskey(kw,"qt") || (qt_version=get(kw,"qt",0)[1]!=v"4.8.5")) - print("\n If the code has a Segmentation fault error switch to qt v4.8.5 by pasting the following code into julia: \n \n") - print(add_backend_string(PyPlotBackend())) - end - end - end + # we don't want every command to update the figure PyPlot.ioff() end From 2e7329931c0faac4c4effbe5f82830bf39c21d7f Mon Sep 17 00:00:00 2001 From: Huckleberry Febbo Date: Mon, 1 May 2017 11:14:38 -0400 Subject: [PATCH 081/107] changed warning in imagemagick --- src/animation.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/animation.jl b/src/animation.jl index ee7428df..55a9fe53 100644 --- a/src/animation.jl +++ b/src/animation.jl @@ -80,7 +80,8 @@ function buildanimation(animdir::AbstractString, fn::AbstractString; catch err warn("""Tried to create gif using convert (ImageMagick), but got error: $err - ImageMagick can be installed by executing `Pkg.add("ImageMagick")` + ImageMagick can be installed by executing `Pkg.add("ImageMagick")`. + You may also need to install the imagemagick c++ library through your operating system. Will try ffmpeg, but it's lower quality...)""") # low quality From c4f3b93da56a26d8ac8a7734991ab32943c5c62e Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 2 May 2017 20:36:33 +0200 Subject: [PATCH 082/107] increase rightpad for colorbars --- src/backends/pyplot.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index cdc44fb1..251e7e61 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1107,7 +1107,7 @@ function _update_min_padding!(sp::Subplot{PyPlotBackend}) # optionally add the width of colorbar labels and colorbar to rightpad if haskey(sp.attr, :cbar_ax) bb = py_bbox(sp.attr[:cbar_handle][:ax][:get_yticklabels]()) - sp.attr[:cbar_width] = _cbar_width + width(bb) + 1mm + (sp[:colorbar_title] == "" ? 0px : 30px) + sp.attr[:cbar_width] = _cbar_width + width(bb) + 2.3mm + (sp[:colorbar_title] == "" ? 0px : 30px) rightpad = rightpad + sp.attr[:cbar_width] end From af072da0b05013c5e954c4171ca59f2ad565f561 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 2 May 2017 21:10:43 +0200 Subject: [PATCH 083/107] avoid auto-reduction of user-defined ticks --- src/axes.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/axes.jl b/src/axes.jl index 7af2d7c5..9a39ca2e 100644 --- a/src/axes.jl +++ b/src/axes.jl @@ -238,7 +238,7 @@ function get_ticks(axis::Axis) # @show ticks dvals cv dv # TODO: better/smarter cutoff values for sampling ticks - if length(cv) > 30 + if length(cv) > 30 && ticks == :auto rng = Int[round(Int,i) for i in linspace(1, length(cv), 15)] cv[rng], dv[rng] else From 0f837f3438fd4e7bf41075a83bcf604738feba22 Mon Sep 17 00:00:00 2001 From: Sebastian Pech Date: Wed, 3 May 2017 10:39:07 +0200 Subject: [PATCH 084/107] Add pgfplots support for zcolor and colorbar --- src/backends/pgfplots.jl | 55 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 51 insertions(+), 4 deletions(-) diff --git a/src/backends/pgfplots.jl b/src/backends/pgfplots.jl index 3a47295f..c44c10ae 100644 --- a/src/backends/pgfplots.jl +++ b/src/backends/pgfplots.jl @@ -22,8 +22,8 @@ const _pgfplots_attr = merge_with_base_supported([ :guide, :lims, :ticks, :scale, :flip, :rotation, :tickfont, :guidefont, :legendfont, :grid, :legend, - # :colorbar, - # :marker_z, :levels, + :colorbar, + :marker_z, #:levels, # :ribbon, :quiver, :arrow, # :orientation, # :overwrite_figure, @@ -98,6 +98,8 @@ const _pgf_series_extrastyle = KW( :xsticks => "xcomb", ) +# PGFPlots uses the anchors to define orientations for example to align left +# one needs to use the right edge as anchor const _pgf_annotation_halign = KW( :center => "", :left => "right", @@ -107,11 +109,24 @@ const _pgf_annotation_halign = KW( # -------------------------------------------------------------------------------------- # takes in color,alpha, and returns color and alpha appropriate for pgf style -function pgf_color(c) +function pgf_color(c::Colorant) cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", red(c), green(c), blue(c)) cstr, alpha(c) end +function pgf_color(grad::ColorGradient) + # Can't handle ColorGradient here, fallback to defaults. + cstr = @sprintf("{rgb,1:red,%.8f;green,%.8f;blue,%.8f}", 0.0, 0.60560316,0.97868012) + cstr, 1 +end + +# Generates a colormap for pgfplots based on a ColorGradient +function pgf_colormap(grad::ColorGradient) + join(map(grad.colors) do c + @sprintf("rgb=(%.8f,%.8f,%.8f)", red(c), green(c),blue(c)) + end,", ") +end + function pgf_fillstyle(d::KW) cstr,a = pgf_color(d[:fillcolor]) "fill = $cstr, fill opacity=$a" @@ -162,7 +177,6 @@ function pgf_series(sp::Subplot, series::Series) st = d[:seriestype] style = [] kw = KW() - push!(style, pgf_linestyle(d)) push!(style, pgf_marker(d)) @@ -182,6 +196,10 @@ function pgf_series(sp::Subplot, series::Series) d[:z].surf, d[:x], d[:y] elseif is3d(st) d[:x], d[:y], d[:z] + elseif d[:marker_z] != nothing + # If a marker_z is used pass it as third coordinate to a 2D plot. + # See "Scatter Plots" in PGFPlots documentation + d[:x], d[:y], d[:marker_z] else d[:x], d[:y] end @@ -274,6 +292,7 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend}) # Obtain the total height of the plot by extracting the maximal bottom # coordinate from the bounding box. total_height = bottom(bbox(plt.layout)) + for sp in plt.subplots # first build the PGFPlots.Axis object style = ["unbounded coords=jump"] @@ -319,6 +338,34 @@ function _update_plot_object(plt::Plot{PGFPlotsBackend}) if sp[:projection] == :polar axisf = PGFPlots.PolarAxis end + + # Search series for any gradient. In case one series uses a gradient set + # the colorbar and colomap. + # The reasoning behind doing this on the axis level is that pgfplots + # colorbar seems to only works on axis level and needs the proper colormap for + # correctly displaying it. + # It's also possible to assign the colormap to the series itself but + # then the colormap needs to be added twice, once for the axis and once for the + # series. + # As it is likely that all series within the same axis use the same + # colormap this should not cause any problem. + for series in series_list(sp) + for col in (:markercolor, :fillcolor) + if typeof(series.d[col]) == ColorGradient + push!(style,"colormap={plots}{$(pgf_colormap(series.d[col]))}") + + if sp[:colorbar] == :none + kw[:colorbar] = "false" + else + kw[:colorbar] = "true" + end + # goto is needed to break out of col and series for + @goto colorbar_end + end + end + end + @label colorbar_end + o = axisf(; style = style, kw...) # add the series object to the PGFPlots.Axis From 118823064174714f14698f819fa0e0616b403ce2 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Sat, 29 Apr 2017 17:48:11 +0200 Subject: [PATCH 085/107] Change histogram implementation, use StatsPlots, add new histogram styles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New series recipes for binned data: * barbins * scatterbins * stepbins New series recipes for histogram: * barhist (histogram is now an alias for this) * scatterhist * stephist Supports plotting 1D and 2D StatsBase histograms, seriestype can be set to bar(bins), scatter(bins) or step(bins). Also adds support for some common auto-binning modes: * :sturges, :auto - Sturges' formula * :sqrt - Square-root choice * :rice - Rice Rule * :scott - Scott's normal reference rule * :fd - Freedman–Diaconis rule Maybe these could be contributed to StatsBase at some point. Error bars currently don't work correctly for scatterbins and scatterhist, due to problem with manipulating error bars in a series recipe, but do work for "plot(h::StatsBase.Histogram, seriestype = :scatter)" (works around the problem by calling scatter directly, it seems that error bars can be manipulated correctly in a type recipe). --- REQUIRE | 1 + src/Plots.jl | 4 + src/arg_desc.jl | 4 +- src/args.jl | 8 +- src/pipeline.jl | 2 +- src/recipes.jl | 289 ++++++++++++++++++++++++++++++++++++------------ src/subplots.jl | 2 +- 7 files changed, 232 insertions(+), 78 deletions(-) diff --git a/REQUIRE b/REQUIRE index 67e5f781..14bcddc8 100644 --- a/REQUIRE +++ b/REQUIRE @@ -7,3 +7,4 @@ Reexport FixedSizeArrays Measures Showoff +StatsBase 0.14.0 diff --git a/src/Plots.jl b/src/Plots.jl index 337880da..113242e9 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -9,6 +9,7 @@ using Base.Meta @reexport using PlotUtils @reexport using PlotThemes import Showoff +import StatsBase export grid, @@ -148,6 +149,9 @@ end @shorthands bar @shorthands barh @shorthands histogram +@shorthands barhist +@shorthands stephist +@shorthands scatterhist @shorthands histogram2d @shorthands density @shorthands heatmap diff --git a/src/arg_desc.jl b/src/arg_desc.jl index 4efbf1af..b233d6d7 100644 --- a/src/arg_desc.jl +++ b/src/arg_desc.jl @@ -21,7 +21,7 @@ const _arg_desc = KW( :markerstrokewidth => "Number. Width of the marker stroke (border. in pixels)", :markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.", :markerstrokealpha => "Number in [0,1]. The alpha/opacity override for the marker stroke (border). `nothing` (the default) means it will take the alpha value of markerstrokecolor.", -:bins => "Integer, NTuple{2,Integer}, AbstractVector. For histogram-types, defines the number of bins, or the edges, of the histogram.", +:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. For histogram-types, defines the number of bins, or the edges, of the histogram, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd)", :smooth => "Bool. Add a regression line?", :group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.", :x => "Various. Input data. First Dimension", @@ -40,7 +40,7 @@ const _arg_desc = KW( :ribbon => "Number or AbstractVector. Creates a fillrange around the data points.", :quiver => "AbstractVector or 2-Tuple of vectors. The directional vectors U,V which specify velocity/gradient vectors for a quiver plot.", :arrow => "nothing (no arrows), Bool (if true, default arrows), Arrow object, or arg(s) that could be style or head length/widths. Defines arrowheads that should be displayed at the end of path line segments (just before a NaN and the last non-NaN point). Used in quiverplot, streamplot, or similar.", -:normalize => "Bool. Should normalize histogram types? Trying for area == 1.", +:normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a PDF with integral of 1) and :density (only normalize in respect to bin sizes).", :weights => "AbstractVector. Used in histogram types for weighted counts.", :contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.", :match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.", diff --git a/src/args.jl b/src/args.jl index fa5a8e2f..476ce0ea 100644 --- a/src/args.jl +++ b/src/args.jl @@ -35,7 +35,9 @@ const _3dTypes = [ ] const _allTypes = vcat([ :none, :line, :path, :steppre, :steppost, :sticks, :scatter, - :heatmap, :hexbin, :histogram, :histogram2d, :histogram3d, :density, :bar, :hline, :vline, + :heatmap, :hexbin, :barbins, :barhist, :histogram, :scatterbins, + :scatterhist, :stepbins, :stephist, :bins2d, :histogram2d, :histogram3d, + :density, :bar, :hline, :vline, :contour, :pie, :shape, :image ], _3dTypes) @@ -78,7 +80,7 @@ const _typeAliases = Dict{Symbol,Symbol}( add_non_underscore_aliases!(_typeAliases) -like_histogram(seriestype::Symbol) = seriestype == :histogram +like_histogram(seriestype::Symbol) = seriestype in (:histogram, :barhist, :barbins) like_line(seriestype::Symbol) = seriestype in (:line, :path, :steppre, :steppost) like_surface(seriestype::Symbol) = seriestype in (:contour, :contourf, :contour3d, :heatmap, :surface, :wireframe, :image) @@ -1261,7 +1263,7 @@ function _add_defaults!(d::KW, plt::Plot, sp::Subplot, commandIndex::Int) end # scatter plots don't have a line, but must have a shape - if d[:seriestype] in (:scatter, :scatter3d) + if d[:seriestype] in (:scatter, :scatterbins, :scatterhist, :scatter3d) d[:linewidth] = 0 if d[:markershape] == :none d[:markershape] = :circle diff --git a/src/pipeline.jl b/src/pipeline.jl index 6c2e05c3..46cd4bcf 100644 --- a/src/pipeline.jl +++ b/src/pipeline.jl @@ -357,7 +357,7 @@ function _expand_subplot_extrema(sp::Subplot, d::KW, st::Symbol) expand_extrema!(sp[:xaxis], (0,w)) expand_extrema!(sp[:yaxis], (0,h)) sp[:yaxis].d[:flip] = true - elseif !(st in (:pie, :histogram, :histogram2d)) + elseif !(st in (:pie, :histogram, :bins2d, :histogram2d)) expand_extrema!(sp, d) end end diff --git a/src/recipes.jl b/src/recipes.jl index 5be5b6e0..691a6e45 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -378,109 +378,256 @@ end end @deps bar shape + # --------------------------------------------------------------------------- # Histograms -# edges from number of bins -function calc_edges(v, bins::Integer) - vmin, vmax = extrema(v) - linspace(vmin, vmax, bins+1) +_bin_centers(v::AVec) = (v[1:end-1] + v[2:end]) / 2 + + +@recipe function f(::Type{Val{:barbins}}, x, y, z) + edge, weights = x, y + if (d[:bar_width] == nothing) + bar_width := diff(edge) + end + x := _bin_centers(edge) + y := weights + seriestype := :bar + () +end +@deps barbins bins + + +@recipe function f(::Type{Val{:scatterbins}}, x, y, z) + edge, weights = x, y + xerror := diff(edge)/2 + x := _bin_centers(edge) + y := weights + seriestype := :scatter + () +end +@deps scatterbins scatter + + +function _stepbins_path(edge, weights) + nbins = length(linearindices(weights)) + if length(linearindices(edge)) != nbins + 1 + error("Edge vector must be 1 longer than weight vector") + end + + it_e, it_w = start(edge), start(weights) + px, it_e = next(edge, it_e) + py = zero(eltype(weights)) + + npathpts = 2 * nbins + 2 + x = Vector{eltype(px)}(npathpts) + y = Vector{eltype(py)}(npathpts) + + x[1], y[1] = px, py + i = 2 + while (i < npathpts - 1) + py, it_w = next(weights, it_w) + x[i], y[i] = px, py + i += 1 + px, it_e = next(edge, it_e) + x[i], y[i] = px, py + i += 1 + end + assert(i == npathpts) + x[end], y[end] = px, zero(py) + + (x, y) end -# just pass through arrays -calc_edges(v, bins::AVec) = bins +@recipe function f(::Type{Val{:stepbins}}, x, y, z) + edge, weights = x, y -# find the bucket index of this value -function bucket_index(vi, edges) - for (i,e) in enumerate(edges) - if vi <= e - return max(1,i-1) + axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis] + + xpts, ypts = _stepbins_path(edge, weights) + if !Plots.isvertical(d) + xpts, ypts = ypts, xpts + end + + # create a secondary series for the markers + if d[:markershape] != :none + @series begin + seriestype := :scatter + x := Plots._bin_centers(edge) + y := weights + fillrange := nothing + label := "" + primary := false + () end + markershape := :none + xerror := :none + yerror := :none + end + + x := xpts + y := ypts + seriestype := :path + ylims --> [0, 1.1 * maximum(weights)] + () +end +Plots.@deps stepbins path + + +function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode::Symbol = :auto) + _cl(x) = max(ceil(Int, x), 1) + _iqr(v) = quantile(v, 0.75) - quantile(v, 0.25) + _span(v) = maximum(v) - minimum(v) + + n_samples = length(linearindices(first(vs))) + # Estimator for number of samples in one row/column of bins along each axis: + n = max(1, n_samples^(1/N)) + + v = vs[dim] + + if mode == :sqrt # Square-root choice + _cl(sqrt(n)) + elseif mode == :sturges || mode ==:auto # Sturges' formula + _cl(log2(n)) + 1 + elseif mode == :rice # Rice Rule + _cl(2 * n^(1/3)) + elseif mode == :scott # Scott's normal reference rule + _cl(_span(v) / (3.5 * std(v) / n^(1/3))) + elseif mode == :fd # Freedman–Diaconis rule + _cl(_span(v) / (2 * _iqr(v) / n^(1/3))) + else + error("Unknown auto-binning mode $mode") end - return length(edges)-1 end -function my_hist(v, bins; normed = false, weights = nothing) - edges = calc_edges(v, bins) - counts = zeros(length(edges)-1) +_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) = StatsBase.histrange(vs[dim], binning, :left) +_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Symbol) = _hist_edge(vs, dim, _auto_binning_nbins(vs, dim, mode = binning)) +_hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::AbstractVector) = binning - # add a weighted count - for (i,vi) in enumerate(v) - idx = bucket_index(vi, edges) - counts[idx] += (weights == nothing ? 1.0 : weights[i]) - end +_hist_edges{N}(vs::NTuple{N,AbstractVector}, binning::NTuple{N}) = + map(dim -> _hist_edge(vs, dim, binning[dim]), (1:N...)) - counts = isapprox(extrema(diff(edges))...) ? counts : counts ./ diff(edges) # for uneven bins, normalize to area. +_hist_edges{N}(vs::NTuple{N,AbstractVector}, binning::Union{Integer, Symbol, AbstractVector}) = + map(dim -> _hist_edge(vs, dim, binning), (1:N...)) - # normalize by bar area? - norm_denom = normed ? sum(diff(edges) .* counts) : 1.0 - if norm_denom == 0 - norm_denom = 1.0 - end +_hist_norm_mode(mode::Symbol) = mode +_hist_norm_mode(mode::Bool) = mode ? :pdf : :none - edges, counts ./ norm_denom +function _make_hist{N}(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) + edges = _hist_edges(vs, binning) + h = float( weights == nothing ? + StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) : + StatsBase.fit(StatsBase.Histogram, vs, weights, edges, closed = :left) + ) + normalize!(h, mode = _hist_norm_mode(normed)) end @recipe function f(::Type{Val{:histogram}}, x, y, z) - edges, counts = my_hist(y, d[:bins], - normed = d[:normalize], - weights = d[:weights]) - bar_width := diff(edges) - x := centers(edges) - y := counts - seriestype := :bar + seriestype := :barhist () end -@deps histogram bar +@deps histogram barhist + +@recipe function f(::Type{Val{:barhist}}, x, y, z) + h = _make_hist((y,), d[:bins], normed = d[:normalize], weights = d[:weights]) + x := h.edges[1] + y := h.weights + seriestype := :barbins + () +end +@deps barhist barbins + +@recipe function f(::Type{Val{:stephist}}, x, y, z) + h = _make_hist((y,), d[:bins], normed = d[:normalize], weights = d[:weights]) + x := h.edges[1] + y := h.weights + seriestype := :stepbins + () +end +@deps stephist stepbins + +@recipe function f(::Type{Val{:scatterhist}}, x, y, z) + h = _make_hist((y,), d[:bins], normed = d[:normalize], weights = d[:weights]) + x := h.edges[1] + y := h.weights + seriestype := :scatterbins + () +end +@deps scatterhist scatterbins + + +@recipe function f{T, E}(h::StatsBase.Histogram{T, 1, E}) + seriestype --> :barbins + + st_map = Dict( + :bar => :barbins, :scatter => :scatterbins, :step => :stepbins, + :steppost => :stepbins # :step can be mapped to :steppost in pre-processing + ) + seriestype := get(st_map, d[:seriestype], d[:seriestype]) + + if d[:seriestype] == :scatterbins + # Workaround, error bars currently not set correctly by scatterbins + xerror --> diff(h.edges[1])/2 + seriestype := :scatter + (Plots._bin_centers(h.edges[1]), h.weights) + else + (h.edges[1], h.weights) + end +end + + +@recipe function f{H <: StatsBase.Histogram}(hv::AbstractVector{H}) + for h in hv + @series begin + h + end + end +end + # --------------------------------------------------------------------------- # Histogram 2D -# if tuple, map out bins, otherwise use the same for both -calc_edges_2d(x, y, bins) = calc_edges(x, bins), calc_edges(y, bins) -calc_edges_2d{X,Y}(x, y, bins::Tuple{X,Y}) = calc_edges(x, bins[1]), calc_edges(y, bins[2]) +@recipe function f(::Type{Val{:bins2d}}, x, y, z) + edge_x, edge_y, weights = x, y, z.surf -# the 2D version -function my_hist_2d(x, y, bins; normed = false, weights = nothing) - xedges, yedges = calc_edges_2d(x, y, bins) - counts = zeros(length(yedges)-1, length(xedges)-1) - - # add a weighted count - for i=1:length(x) - r = bucket_index(y[i], yedges) - c = bucket_index(x[i], xedges) - counts[r,c] += (weights == nothing ? 1.0 : weights[i]) + float_weights = float(weights) + if is(float_weights, weights) + float_weights = deepcopy(float_weights) end - - # normalize to cubic area of the imaginary surface towers - norm_denom = normed ? sum((diff(yedges) * diff(xedges)') .* counts) : 1.0 - if norm_denom == 0 - norm_denom = 1.0 - end - - xedges, yedges, counts ./ norm_denom -end - -centers(v::AVec) = 0.5 * (v[1:end-1] + v[2:end]) - -@recipe function f(::Type{Val{:histogram2d}}, x, y, z) - xedges, yedges, counts = my_hist_2d(x, y, d[:bins], - normed = d[:normalize], - weights = d[:weights]) - for (i,c) in enumerate(counts) + for (i, c) in enumerate(float_weights) if c == 0 - counts[i] = NaN + float_weights[i] = NaN end end - x := centers(xedges) - y := centers(yedges) - z := Surface(counts) - linewidth := 0 + + x := Plots._bin_centers(edge_x) + y := Plots._bin_centers(edge_y) + z := Surface(float_weights) + + match_dimensions := true seriestype := :heatmap () end -@deps histogram2d heatmap +Plots.@deps bins2d heatmap + + +@recipe function f(::Type{Val{:histogram2d}}, x, y, z) + h = _make_hist((x, y), d[:bins], normed = d[:normalize], weights = d[:weights]) + x := h.edges[1] + y := h.edges[2] + z := Surface(h.weights) + seriestype := :bins2d + () +end +@deps histogram2d bins2d + + +@recipe function f{T, E}(h::StatsBase.Histogram{T, 2, E}) + seriestype --> :bins2d + (h.edges[1], h.edges[2], Surface(h.weights)) +end # --------------------------------------------------------------------------- diff --git a/src/subplots.jl b/src/subplots.jl index 3400874c..924cc6c0 100644 --- a/src/subplots.jl +++ b/src/subplots.jl @@ -39,7 +39,7 @@ series_list(sp::Subplot) = sp.series_list # filter(series -> series.d[:subplot] function should_add_to_legend(series::Series) series.d[:primary] && series.d[:label] != "" && !(series.d[:seriestype] in ( - :hexbin,:histogram2d,:hline,:vline, + :hexbin,:bins2d,:histogram2d,:hline,:vline, :contour,:contourf,:contour3d,:surface,:wireframe, :heatmap, :pie, :image )) From 56a9389023745db11308225cae2ecd0a21253f91 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Sat, 29 Apr 2017 17:53:37 +0200 Subject: [PATCH 086/107] Fix log-scale for 1D bar/bin/histogram series types --- src/args.jl | 2 + src/pipeline.jl | 7 +++ src/recipes.jl | 149 ++++++++++++++++++++++++++++++++++++------------ 3 files changed, 120 insertions(+), 38 deletions(-) diff --git a/src/args.jl b/src/args.jl index 476ce0ea..4f4bba59 100644 --- a/src/args.jl +++ b/src/args.jl @@ -156,6 +156,8 @@ const _markerAliases = Dict{Symbol,Symbol}( ) const _allScales = [:identity, :ln, :log2, :log10, :asinh, :sqrt] +const _logScales = [:ln, :log2, :log10] +const _logScaleBases = Dict(:ln => e, :log2 => 2.0, :log10 => 10.0) const _scaleAliases = Dict{Symbol,Symbol}( :none => :identity, :log => :log10, diff --git a/src/pipeline.jl b/src/pipeline.jl index 46cd4bcf..70644055 100644 --- a/src/pipeline.jl +++ b/src/pipeline.jl @@ -277,6 +277,13 @@ function _subplot_setup(plt::Plot, d::KW, kw_list::Vector{KW}) attr[Symbol(letter,k)] = v end end + for k in (:scale,), letter in (:x,:y,:z) + # Series recipes may need access to this information + lk = Symbol(letter,k) + if haskey(attr, lk) + kw[lk] = attr[lk] + end + end end sp_attrs[sp] = attr end diff --git a/src/recipes.jl b/src/recipes.jl index 691a6e45..cb89fbc0 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -323,10 +323,11 @@ end # create a bar plot as a filled step function @recipe function f(::Type{Val{:bar}}, x, y, z) - nx, ny = length(x), length(y) + procx, procy, xscale, yscale, baseline = _preprocess_binlike(d, x, y) + nx, ny = length(procx), length(procy) axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis] - cv = [discrete_value!(axis, xi)[1] for xi=x] - x = if nx == ny + cv = [discrete_value!(axis, xi)[1] for xi=procx] + procx = if nx == ny cv elseif nx == ny + 1 0.5diff(cv) + cv[1:end-1] @@ -337,9 +338,9 @@ end # compute half-width of bars bw = d[:bar_width] hw = if bw == nothing - 0.5mean(diff(x)) + 0.5mean(diff(procx)) else - Float64[0.5cycle(bw,i) for i=1:length(x)] + Float64[0.5cycle(bw,i) for i=1:length(procx)] end # make fillto a vector... default fills to 0 @@ -347,16 +348,21 @@ end if fillto == nothing fillto = 0 end + if (yscale in _logScales) && !all(_is_positive, fillto) + fillto = map(x -> _is_positive(x) ? typeof(baseline)(x) : baseline, fillto) + end # create the bar shapes by adding x/y segments xseg, yseg = Segments(), Segments() for i=1:ny - center = x[i] - hwi = cycle(hw,i) - yi = y[i] - fi = cycle(fillto,i) - push!(xseg, center-hwi, center-hwi, center+hwi, center+hwi, center-hwi) - push!(yseg, yi, fi, fi, yi, yi) + yi = procy[i] + if !isnan(yi) + center = procx[i] + hwi = cycle(hw,i) + fi = cycle(fillto,i) + push!(xseg, center-hwi, center-hwi, center+hwi, center+hwi, center-hwi) + push!(yseg, yi, fi, fi, yi, yi) + end end # widen limits out a bit @@ -384,9 +390,51 @@ end _bin_centers(v::AVec) = (v[1:end-1] + v[2:end]) / 2 +_is_positive(x) = (x > 0) && !(x ≈ 0) + +_positive_else_nan{T}(::Type{T}, x::Real) = _is_positive(x) ? T(x) : T(NaN) + +function _scale_adjusted_values{T<:AbstractFloat}(::Type{T}, V::AbstractVector, scale::Symbol) + if scale in _logScales + [_positive_else_nan(T, x) for x in V] + else + [T(x) for x in V] + end +end + +function _hist_ylim_lo{T<:Real}(ymin::T, yscale::Symbol) + if (yscale in _logScales) + ymin / T(_logScaleBases[yscale]^log10(2)) + else + zero(T) + end +end + +function _hist_ylim_hi{T<:Real}(ymax::T, yscale::Symbol) + if (yscale in _logScales) + ymax * T(_logScaleBases[yscale]^log10(2)) + else + ymax * T(1.1) + end +end + + +function _preprocess_binlike(d, x, y) + xscale = get(d, :xscale, :identity) + yscale = get(d, :yscale, :identity) + + T = float(promote_type(eltype(x), eltype(y))) + edge = map(T, x) + weights = _scale_adjusted_values(T, y, yscale) + w_min = minimum(weights) + baseline = _hist_ylim_lo(isnan(w_min) ? one(T) : w_min, yscale) + edge, weights, xscale, yscale, baseline +end + + @recipe function f(::Type{Val{:barbins}}, x, y, z) - edge, weights = x, y + edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) if (d[:bar_width] == nothing) bar_width := diff(edge) end @@ -395,11 +443,11 @@ _bin_centers(v::AVec) = (v[1:end-1] + v[2:end]) / 2 seriestype := :bar () end -@deps barbins bins +@deps barbins bar @recipe function f(::Type{Val{:scatterbins}}, x, y, z) - edge, weights = x, y + edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) xerror := diff(edge)/2 x := _bin_centers(edge) y := weights @@ -409,43 +457,65 @@ end @deps scatterbins scatter -function _stepbins_path(edge, weights) +function _stepbins_path(edge, weights, baseline::Real, xscale::Symbol, yscale::Symbol) + log_scale_x = xscale in _logScales + log_scale_y = yscale in _logScales + nbins = length(linearindices(weights)) if length(linearindices(edge)) != nbins + 1 error("Edge vector must be 1 longer than weight vector") end + x = eltype(edge)[] + y = eltype(weights)[] + it_e, it_w = start(edge), start(weights) - px, it_e = next(edge, it_e) - py = zero(eltype(weights)) + a, it_e = next(edge, it_e) + last_w = eltype(weights)(NaN) + i = 1 + while (!done(edge, it_e) && !done(edge, it_e)) + b, it_e = next(edge, it_e) + w, it_w = next(weights, it_w) - npathpts = 2 * nbins + 2 - x = Vector{eltype(px)}(npathpts) - y = Vector{eltype(py)}(npathpts) + if (log_scale_x && a ≈ 0) + a = b/_logScaleBases[xscale]^3 + end - x[1], y[1] = px, py - i = 2 - while (i < npathpts - 1) - py, it_w = next(weights, it_w) - x[i], y[i] = px, py - i += 1 - px, it_e = next(edge, it_e) - x[i], y[i] = px, py - i += 1 + if isnan(w) + if !isnan(last_w) + push!(x, a) + push!(y, baseline) + end + else + if isnan(last_w) + push!(x, a) + push!(y, baseline) + end + push!(x, a) + push!(y, w) + push!(x, b) + push!(y, w) + end + + a = b + last_w = w + end + if (last_w != baseline) + push!(x, a) + push!(y, baseline) end - assert(i == npathpts) - x[end], y[end] = px, zero(py) (x, y) end -@recipe function f(::Type{Val{:stepbins}}, x, y, z) - edge, weights = x, y +@recipe function f(::Type{Val{:stepbins}}, x, y, z) axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis] - xpts, ypts = _stepbins_path(edge, weights) - if !Plots.isvertical(d) + edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) + + xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale) + if !isvertical(d) xpts, ypts = ypts, xpts end @@ -453,7 +523,7 @@ end if d[:markershape] != :none @series begin seriestype := :scatter - x := Plots._bin_centers(edge) + x := _bin_centers(edge) y := weights fillrange := nothing label := "" @@ -468,7 +538,8 @@ end x := xpts y := ypts seriestype := :path - ylims --> [0, 1.1 * maximum(weights)] + + ylims --> [baseline, _hist_ylim_hi(maximum(weights), yscale)] () end Plots.@deps stepbins path @@ -568,9 +639,11 @@ end if d[:seriestype] == :scatterbins # Workaround, error bars currently not set correctly by scatterbins + edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, h.edges[1], h.weights) + info("xscale = $xscale, yscale = $yscale") xerror --> diff(h.edges[1])/2 seriestype := :scatter - (Plots._bin_centers(h.edges[1]), h.weights) + (Plots._bin_centers(edge), weights) else (h.edges[1], h.weights) end From c22a9e51a16b7e353137fc7a4b2e01648b9a788d Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Thu, 4 May 2017 13:15:05 +0200 Subject: [PATCH 087/107] Update News.md --- NEWS.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index c1c98498..8cd7a38e 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,7 +10,40 @@ --- -## 0.9 (current master/dev) +## 0.11 (current master/dev) + +#### 0.11.0 + +- julia 0.6 compatibility +- matplotlib 0.2.0 compatibility +- add inspectdr backend +- improved histogram functionality: +- added a `:stephist` and `:scatterhist` series type as well as ``:barhist` (the default) +- support for log scale axes with histograms +- support for plotting `StatsBase.Histogram` +- allowing bins to be specified as `:sturges`, `:rice`, `:scott` or :fd +- allow `normalization` to be specified as :density (for unequal bins) or :pdf (sum to 1) +- add a `plotattr` function to access documentation for Plots attribute +- add `fill_z` attribute for pyplot +- add colorbar_title to plotlyjs +- enable standalone window for plotlyjs +- improved support for pgfplots, ticks rotation, clims, series_annotations +- restore colorbars for GR +- better axis labels for heatmap in GR +- better marker sizes in GR +- fix color representation in GR +- update GR legend +- fix image bug on GR +- fix glvisualize dependencies +- set dotted grid lines for pyplot +- several improvements to inspectdr +- improved tick positions for TimeType x axes +- support for improved color gradient capability in PlotUtils +- add a showlibrary recipe to display color libraries +- add a showgradient recipe to display color gradients +- add `vectorfield` as an alias for `quiver` +- use `PlotUtils.adaptedgrid` for functions + #### 0.9.5 From c75e1df190f2aeafa1bb0572577adcc91674a877 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Thu, 4 May 2017 16:28:49 +0200 Subject: [PATCH 088/107] gr: fixed linewidth bug (lw=0) --- src/backends/gr.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 24ddfd42..c41c38ba 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -338,7 +338,7 @@ end function gr_set_line(lw, style, c) #, a) GR.setlinetype(gr_linetype[style]) w, h = gr_plot_size - GR.setlinewidth(max(1, lw / ((w + h) * 0.001))) + GR.setlinewidth(max(0, lw / ((w + h) * 0.001))) gr_set_linecolor(c) #, a) end From a523903c154a4c3d43c7ab0543b2b23ad519e911 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Sat, 6 May 2017 10:13:04 +0200 Subject: [PATCH 089/107] Remove remnant debugging output --- src/recipes.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/recipes.jl b/src/recipes.jl index cb89fbc0..37210363 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -640,7 +640,6 @@ end if d[:seriestype] == :scatterbins # Workaround, error bars currently not set correctly by scatterbins edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, h.edges[1], h.weights) - info("xscale = $xscale, yscale = $yscale") xerror --> diff(h.edges[1])/2 seriestype := :scatter (Plots._bin_centers(edge), weights) From 67b4157e254fdfe910132bea9b3fcb1a3f0f2a1d Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Sat, 6 May 2017 15:00:31 +0200 Subject: [PATCH 090/107] Improve data preprocessing for bar and histogram plots Fixes broken bar-plots with non-numeric a-axes --- src/recipes.jl | 68 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 37210363..ef37f184 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -323,7 +323,7 @@ end # create a bar plot as a filled step function @recipe function f(::Type{Val{:bar}}, x, y, z) - procx, procy, xscale, yscale, baseline = _preprocess_binlike(d, x, y) + procx, procy, xscale, yscale, baseline, wautolims = _preprocess_barlike(d, x, y) nx, ny = length(procx), length(procy) axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis] cv = [discrete_value!(axis, xi)[1] for xi=procx] @@ -380,6 +380,7 @@ end x := xseg.pts y := yseg.pts seriestype := :shape + ylims --> wautolims () end @deps bar shape @@ -402,39 +403,64 @@ function _scale_adjusted_values{T<:AbstractFloat}(::Type{T}, V::AbstractVector, end end -function _hist_ylim_lo{T<:Real}(ymin::T, yscale::Symbol) - if (yscale in _logScales) - ymin / T(_logScaleBases[yscale]^log10(2)) + +function _binbarlike_baseline{T<:Real}(min_value::T, scale::Symbol) + if (scale in _logScales) + !isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3) else zero(T) end end -function _hist_ylim_hi{T<:Real}(ymax::T, yscale::Symbol) - if (yscale in _logScales) - ymax * T(_logScaleBases[yscale]^log10(2)) +function _binbarlike_autolims{T<:Real}(min_value::T, max_value::T, scale::Symbol) + lo = if (scale in _logScales) + _binbarlike_baseline(min_value, scale) else - ymax * T(1.1) - end + min(min_value * T(1.1), zero(T)) + end::T + + hi = if !isnan(max_value) + if (scale in _logScales) + max_value * T(_logScaleBases[scale]^log10(2)) + else + max(max_value * T(1.1), zero(T)) + end + else + one(T) + end::T + + (lo, hi) end +function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol) + w_adj = _scale_adjusted_values(T, w, wscale) + w_min = minimum(w_adj) + w_max = maximum(w_adj) + baseline = _binbarlike_baseline(w_min, wscale) + autolims = _binbarlike_autolims(w_min, w_max,wscale) + w_adj, baseline, autolims +end + +function _preprocess_barlike(d, x, y) + xscale = get(d, :xscale, :identity) + yscale = get(d, :yscale, :identity) + weights, baseline, wautolims = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale) + x, weights, xscale, yscale, baseline, wautolims +end + function _preprocess_binlike(d, x, y) xscale = get(d, :xscale, :identity) yscale = get(d, :yscale, :identity) - T = float(promote_type(eltype(x), eltype(y))) - edge = map(T, x) - weights = _scale_adjusted_values(T, y, yscale) - w_min = minimum(weights) - baseline = _hist_ylim_lo(isnan(w_min) ? one(T) : w_min, yscale) - edge, weights, xscale, yscale, baseline + edge = T.(x) + weights, baseline, wautolims = _preprocess_binbarlike_weights(T, y, yscale) + edge, weights, xscale, yscale, baseline, wautolims end - @recipe function f(::Type{Val{:barbins}}, x, y, z) - edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) + edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y) if (d[:bar_width] == nothing) bar_width := diff(edge) end @@ -447,7 +473,7 @@ end @recipe function f(::Type{Val{:scatterbins}}, x, y, z) - edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) + edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y) xerror := diff(edge)/2 x := _bin_centers(edge) y := weights @@ -512,7 +538,7 @@ end @recipe function f(::Type{Val{:stepbins}}, x, y, z) axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis] - edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) + edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y) xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale) if !isvertical(d) @@ -539,7 +565,7 @@ end y := ypts seriestype := :path - ylims --> [baseline, _hist_ylim_hi(maximum(weights), yscale)] + ylims --> wautolims () end Plots.@deps stepbins path @@ -639,7 +665,7 @@ end if d[:seriestype] == :scatterbins # Workaround, error bars currently not set correctly by scatterbins - edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, h.edges[1], h.weights) + edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, h.edges[1], h.weights) xerror --> diff(h.edges[1])/2 seriestype := :scatter (Plots._bin_centers(edge), weights) From 784382110945b37e9d2acbbb1fe82a7b6ca2ac05 Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Mon, 8 May 2017 11:36:01 +0200 Subject: [PATCH 091/107] Change default for bins to :auto (meaning 30 bins) --- src/arg_desc.jl | 2 +- src/args.jl | 2 +- src/recipes.jl | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/arg_desc.jl b/src/arg_desc.jl index b233d6d7..cea77071 100644 --- a/src/arg_desc.jl +++ b/src/arg_desc.jl @@ -21,7 +21,7 @@ const _arg_desc = KW( :markerstrokewidth => "Number. Width of the marker stroke (border. in pixels)", :markerstrokecolor => "Color Type. Color of the marker stroke (border). `:match` will take the value from `:foreground_color_subplot`.", :markerstrokealpha => "Number in [0,1]. The alpha/opacity override for the marker stroke (border). `nothing` (the default) means it will take the alpha value of markerstrokecolor.", -:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. For histogram-types, defines the number of bins, or the edges, of the histogram, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd)", +:bins => "Integer, NTuple{2,Integer}, AbstractVector or Symbol. Default is :auto. For histogram-types, defines the number of bins, or the edges, of the histogram, or the auto-binning algorithm to use (:sturges, :sqrt, :rice, :scott or :fd)", :smooth => "Bool. Add a regression line?", :group => "AbstractVector. Data is split into a separate series, one for each unique value in `group`.", :x => "Various. Input data. First Dimension", diff --git a/src/args.jl b/src/args.jl index 4f4bba59..b93e2d98 100644 --- a/src/args.jl +++ b/src/args.jl @@ -185,7 +185,7 @@ const _series_defaults = KW( :markerstrokewidth => 1, :markerstrokecolor => :match, :markerstrokealpha => nothing, - :bins => 30, # number of bins for hists + :bins => :auto, # number of bins for hists :smooth => false, # regression line? :group => nothing, # groupby vector :x => nothing, diff --git a/src/recipes.jl b/src/recipes.jl index ef37f184..115ffa79 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -582,9 +582,11 @@ function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode v = vs[dim] - if mode == :sqrt # Square-root choice + if mode == :auto + 30 + elseif mode == :sqrt # Square-root choice _cl(sqrt(n)) - elseif mode == :sturges || mode ==:auto # Sturges' formula + elseif mode == :sturges # Sturges' formula _cl(log2(n)) + 1 elseif mode == :rice # Rice Rule _cl(2 * n^(1/3)) @@ -594,7 +596,7 @@ function _auto_binning_nbins{N}(vs::NTuple{N,AbstractVector}, dim::Integer; mode _cl(_span(v) / (2 * _iqr(v) / n^(1/3))) else error("Unknown auto-binning mode $mode") - end + end::Int end _hist_edge{N}(vs::NTuple{N,AbstractVector}, dim::Integer, binning::Integer) = StatsBase.histrange(vs[dim], binning, :left) @@ -611,6 +613,7 @@ _hist_norm_mode(mode::Symbol) = mode _hist_norm_mode(mode::Bool) = mode ? :pdf : :none function _make_hist{N}(vs::NTuple{N,AbstractVector}, binning; normed = false, weights = nothing) + info("binning = $binning") edges = _hist_edges(vs, binning) h = float( weights == nothing ? StatsBase.fit(StatsBase.Histogram, vs, edges, closed = :left) : From 698d583d1d261e01d0d17e364db16c1e9d0c1ab7 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Mon, 8 May 2017 15:16:21 -0500 Subject: [PATCH 092/107] Fix world-age problem with IJulia --- src/output.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/output.jl b/src/output.jl index f3efd812..84225e9b 100644 --- a/src/output.jl +++ b/src/output.jl @@ -271,7 +271,7 @@ function setup_ijulia() show(io, MIME("text/html"), plt) end end - set_ijulia_output("text/html") + @eval set_ijulia_output("text/html") end end From 10f214fbb4cb700e0ad800c96eee6bab38c51c02 Mon Sep 17 00:00:00 2001 From: David Sanders Date: Mon, 8 May 2017 15:20:21 -0500 Subject: [PATCH 093/107] Change typealias to const --- NEWS.md | 2 +- src/Plots.jl | 2 +- src/components.jl | 4 ++-- src/deprecated/series_args.jl | 2 +- src/series.jl | 2 +- src/types.jl | 8 ++++---- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8cd7a38e..dcf896a1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -364,7 +364,7 @@ - z-axis keywords - 3D indexing overhaul: `push!`, `append!` support - matplotlib colormap constants (`:inferno` is the new default colormap for Plots) -- `typealias KW Dict{Symbol,Any}` used in place of splatting in many places +- `const KW = Dict{Symbol,Any}` used in place of splatting in many places - png generation for plotly backend using wkhtmltoimage - `normalize` and `weights` keywords - background/foreground subcategories for fine-tuning of looks diff --git a/src/Plots.jl b/src/Plots.jl index 113242e9..7e630ad7 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -108,7 +108,7 @@ export import Measures import Measures: Length, AbsoluteLength, Measure, BoundingBox, mm, cm, inch, pt, width, height, w, h -typealias BBox Measures.Absolute2DBox +const BBox = Measures.Absolute2DBox export BBox, BoundingBox, mm, cm, inch, pt, px, pct, w, h # --------------------------------------------------------- diff --git a/src/components.jl b/src/components.jl index 551fbee8..b20eb3d0 100644 --- a/src/components.jl +++ b/src/components.jl @@ -1,7 +1,7 @@ -typealias P2 FixedSizeArrays.Vec{2,Float64} -typealias P3 FixedSizeArrays.Vec{3,Float64} +const P2 = FixedSizeArrays.Vec{2,Float64} +const P3 = FixedSizeArrays.Vec{3,Float64} nanpush!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); push!(a, b)) nanappend!(a::AbstractVector{P2}, b) = (push!(a, P2(NaN,NaN)); append!(a, b)) diff --git a/src/deprecated/series_args.jl b/src/deprecated/series_args.jl index 7d491290..2d7536f4 100644 --- a/src/deprecated/series_args.jl +++ b/src/deprecated/series_args.jl @@ -5,7 +5,7 @@ # This should cut down on boilerplate code and allow more focused dispatch on type # note: returns meta information... mainly for use with automatic labeling from DataFrames for now -typealias FuncOrFuncs @compat(Union{Function, AVec{Function}}) +const FuncOrFuncs = @compat(Union{Function, AVec{Function}}) all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none)) diff --git a/src/series.jl b/src/series.jl index f7233c1a..cf9756c5 100644 --- a/src/series.jl +++ b/src/series.jl @@ -6,7 +6,7 @@ # This should cut down on boilerplate code and allow more focused dispatch on type # note: returns meta information... mainly for use with automatic labeling from DataFrames for now -typealias FuncOrFuncs{F} Union{F, Vector{F}, Matrix{F}} +const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none)) diff --git a/src/types.jl b/src/types.jl index 0f1e4909..284b6534 100644 --- a/src/types.jl +++ b/src/types.jl @@ -2,9 +2,9 @@ # TODO: I declare lots of types here because of the lacking ability to do forward declarations in current Julia # I should move these to the relevant files when something like "extern" is implemented -typealias AVec AbstractVector -typealias AMat AbstractMatrix -typealias KW Dict{Symbol,Any} +const AVec = AbstractVector +const AMat = AbstractMatrix +const KW = Dict{Symbol,Any} immutable PlotsDisplay <: Display end @@ -62,7 +62,7 @@ Extrema() = Extrema(Inf, -Inf) # ----------------------------------------------------------- -typealias SubplotMap Dict{Any, Subplot} +const SubplotMap = Dict{Any, Subplot} # ----------------------------------------------------------- From 5e6a9da3ed5d6cd856ad499659b6a60eb2af8944 Mon Sep 17 00:00:00 2001 From: Josef Heinen Date: Mon, 8 May 2017 14:36:25 -0700 Subject: [PATCH 094/107] gr: use correct colorbar scaling --- src/backends/gr.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index c41c38ba..0566da5a 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -813,12 +813,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) isfinite(clims[1]) && (zmin = clims[1]) isfinite(clims[2]) && (zmax = clims[2]) end + GR.setspace(zmin, zmax, 0, 90) if typeof(series[:levels]) <: Array h = series[:levels] else h = linspace(zmin, zmax, series[:levels]) end - GR.setspace(zmin, zmax, 0, 90) if series[:fillrange] != nothing GR.surface(x, y, z, GR.OPTION_CELL_ARRAY) else @@ -856,6 +856,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) isfinite(clims[1]) && (zmin = clims[1]) isfinite(clims[2]) && (zmax = clims[2]) end + GR.setspace(zmin, zmax, 0, 90) grad = isa(series[:fillcolor], ColorGradient) ? series[:fillcolor] : cgrad() colors = [grad[clamp((zi-zmin) / (zmax-zmin), 0, 1)] for zi=z] rgba = map(c -> UInt32( round(Int, alpha(c) * 255) << 24 + From d893034f47ec38e2a3173aa0fcc999f433c362b3 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Tue, 9 May 2017 09:31:09 +0200 Subject: [PATCH 095/107] Amend news.md --- NEWS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index 8cd7a38e..f2d65ed4 100644 --- a/NEWS.md +++ b/NEWS.md @@ -3,8 +3,8 @@ #### notes on release changes, ongoing development, and future planned work -- All new development should target 0.9! -- Minor version 0.8 is the last one to support Julia 0.4!! +- All new development should target 0.12! +- Minor version 0.11 is the last one to support Julia 0.5!! - Critical bugfixes only - `backports` branch is for Julia 0.4 From b88d26ce77739a2a243bcbaac6e1c1d8ea2d2b87 Mon Sep 17 00:00:00 2001 From: fuzzybear3965 Date: Tue, 9 May 2017 12:29:35 -0400 Subject: [PATCH 096/107] increase bottom margin to 20px; fixes #810 --- src/backends/plotly.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 43a1bb70..1626d5e2 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -269,7 +269,7 @@ function plotly_layout(plt::Plot) w, h = plt[:size] d_out[:width], d_out[:height] = w, h d_out[:paper_bgcolor] = rgba_string(plt[:background_color_outside]) - d_out[:margin] = KW(:l=>0, :b=>0, :r=>0, :t=>20) + d_out[:margin] = KW(:l=>0, :b=>20, :r=>0, :t=>20) d_out[:annotations] = KW[] From ee15b2c166924cb1620094bcb3c5437ebc90442e Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Thu, 11 May 2017 00:31:30 -0700 Subject: [PATCH 097/107] Fix plotpane notice PlotlyJS actually plots to the plot pane, so the text was misleading. --- src/output.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/output.jl b/src/output.jl index f3efd812..ec424d54 100644 --- a/src/output.jl +++ b/src/output.jl @@ -318,7 +318,7 @@ function setup_atom() # special handling for plotly... use PlotsDisplay function Media.render(pane::Atom.PlotPane, plt::Plot{PlotlyBackend}) display(Plots.PlotsDisplay(), plt) - s = "PlotPane turned off. The plotly and plotlyjs backends cannot render in the PlotPane due to javascript issues." + s = "PlotPane turned off. The plotly backend cannot render in the PlotPane due to javascript issues. Plotlyjs is similar to plotly and is compatible with the plot pane." Media.render(pane, Atom.div(Atom.HTML(s))) end end From d5e50983d87d6a8d6c5a3a7517eac559c7e9f8b2 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Thu, 11 May 2017 13:40:10 +0200 Subject: [PATCH 098/107] Move rgba_string to PlotUtils requested by Tony Kelman --- src/backends/plotly.jl | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 1626d5e2..814e4775 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -413,9 +413,6 @@ plotly_surface_data(series::Series, a::Surface) = plotly_surface_data(series, a. as_gradient(grad::ColorGradient, α) = grad as_gradient(grad, α) = cgrad(alpha = α) -# allows passing a ColorGradient where a single color is expected - the other backends allow this -PlotUtils.rgba_string(cg::ColorGradient) = rgba_string(cg[1]) - # get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict) function plotly_series(plt::Plot, series::Series) st = series[:seriestype] From 8656fe002a51f5cfbe590f440930d898646c75e7 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Thu, 11 May 2017 13:40:39 +0200 Subject: [PATCH 099/107] Add minimum version numbers to PlotUtils and PlotThemes --- REQUIRE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/REQUIRE b/REQUIRE index 14bcddc8..26866772 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,8 +1,8 @@ julia 0.5 RecipesBase -PlotUtils -PlotThemes +PlotUtils 0.4 +PlotThemes 0.1.2 Reexport FixedSizeArrays Measures From 160b2bf03a3806805f925fa7e4410674bcd464c4 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Thu, 11 May 2017 14:00:29 +0200 Subject: [PATCH 100/107] Up minor version number --- REQUIRE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/REQUIRE b/REQUIRE index 26866772..5875b39d 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,8 +1,8 @@ julia 0.5 RecipesBase -PlotUtils 0.4 -PlotThemes 0.1.2 +PlotUtils 0.4.1 +PlotThemes 0.1.3 Reexport FixedSizeArrays Measures From b8c8c491761070f21e4200082390751607e1d5b2 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Thu, 11 May 2017 22:45:04 +0200 Subject: [PATCH 101/107] update version number for testing --- test/imgcomp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/imgcomp.jl b/test/imgcomp.jl index 71f94924..44264d71 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -24,7 +24,7 @@ default(size=(500,300)) # TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that # is referenced in a button press callback (the button clicked callback will call notify() on that condition) -const _current_plots_version = v"0.9.6" +const _current_plots_version = v"0.11.1" function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2) From d24f327342dca187634930b6d0f3f6467498c3c0 Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Fri, 12 May 2017 11:42:26 +0200 Subject: [PATCH 102/107] Switch off precompilation for release --- src/Plots.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plots.jl b/src/Plots.jl index 113242e9..785bbe24 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -1,4 +1,4 @@ -__precompile__(true) +__precompile__(false) module Plots From 4b8dc06ddb7ec487db0b31765defac63f9577b9d Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Fri, 12 May 2017 11:45:46 +0200 Subject: [PATCH 103/107] Switch precompilation back on --- src/Plots.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Plots.jl b/src/Plots.jl index 785bbe24..113242e9 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -1,4 +1,4 @@ -__precompile__(false) +__precompile__(true) module Plots From eced31e3d7e8dbcb06658c793089514f0033d6ad Mon Sep 17 00:00:00 2001 From: "Michael K. Borregaard" Date: Fri, 12 May 2017 11:46:51 +0200 Subject: [PATCH 104/107] Update version number in tests --- test/imgcomp.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/imgcomp.jl b/test/imgcomp.jl index 44264d71..890c374b 100644 --- a/test/imgcomp.jl +++ b/test/imgcomp.jl @@ -24,7 +24,7 @@ default(size=(500,300)) # TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that # is referenced in a button press callback (the button clicked callback will call notify() on that condition) -const _current_plots_version = v"0.11.1" +const _current_plots_version = v"0.11.2" function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2) From 0e6a02b8105a3f1190befb70d2a3da8047fee0bd Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Sat, 13 May 2017 23:46:29 +0200 Subject: [PATCH 105/107] make precompilation work on o.5 --- src/series.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/series.jl b/src/series.jl index cf9756c5..f7233c1a 100644 --- a/src/series.jl +++ b/src/series.jl @@ -6,7 +6,7 @@ # This should cut down on boilerplate code and allow more focused dispatch on type # note: returns meta information... mainly for use with automatic labeling from DataFrames for now -const FuncOrFuncs{F} = Union{F, Vector{F}, Matrix{F}} +typealias FuncOrFuncs{F} Union{F, Vector{F}, Matrix{F}} all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none)) From 746f96cdcd9243f2b5c5d83e1da0015fe8cceaee Mon Sep 17 00:00:00 2001 From: Oliver Schulz Date: Mon, 15 May 2017 23:26:30 +0200 Subject: [PATCH 106/107] Remove ylims default setting for bar and histogram plots Setting `ylims -> ...` doesn't play well with multiple series and cannot be properly overridden by user. --- src/recipes.jl | 44 ++++++++++---------------------------------- 1 file changed, 10 insertions(+), 34 deletions(-) diff --git a/src/recipes.jl b/src/recipes.jl index 115ffa79..1bc4cad5 100644 --- a/src/recipes.jl +++ b/src/recipes.jl @@ -323,7 +323,7 @@ end # create a bar plot as a filled step function @recipe function f(::Type{Val{:bar}}, x, y, z) - procx, procy, xscale, yscale, baseline, wautolims = _preprocess_barlike(d, x, y) + procx, procy, xscale, yscale, baseline = _preprocess_barlike(d, x, y) nx, ny = length(procx), length(procy) axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis] cv = [discrete_value!(axis, xi)[1] for xi=procx] @@ -380,7 +380,6 @@ end x := xseg.pts y := yseg.pts seriestype := :shape - ylims --> wautolims () end @deps bar shape @@ -412,41 +411,20 @@ function _binbarlike_baseline{T<:Real}(min_value::T, scale::Symbol) end end -function _binbarlike_autolims{T<:Real}(min_value::T, max_value::T, scale::Symbol) - lo = if (scale in _logScales) - _binbarlike_baseline(min_value, scale) - else - min(min_value * T(1.1), zero(T)) - end::T - - hi = if !isnan(max_value) - if (scale in _logScales) - max_value * T(_logScaleBases[scale]^log10(2)) - else - max(max_value * T(1.1), zero(T)) - end - else - one(T) - end::T - - (lo, hi) -end - function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol) w_adj = _scale_adjusted_values(T, w, wscale) w_min = minimum(w_adj) w_max = maximum(w_adj) baseline = _binbarlike_baseline(w_min, wscale) - autolims = _binbarlike_autolims(w_min, w_max,wscale) - w_adj, baseline, autolims + w_adj, baseline end function _preprocess_barlike(d, x, y) xscale = get(d, :xscale, :identity) yscale = get(d, :yscale, :identity) - weights, baseline, wautolims = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale) - x, weights, xscale, yscale, baseline, wautolims + weights, baseline = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale) + x, weights, xscale, yscale, baseline end function _preprocess_binlike(d, x, y) @@ -454,13 +432,13 @@ function _preprocess_binlike(d, x, y) yscale = get(d, :yscale, :identity) T = float(promote_type(eltype(x), eltype(y))) edge = T.(x) - weights, baseline, wautolims = _preprocess_binbarlike_weights(T, y, yscale) - edge, weights, xscale, yscale, baseline, wautolims + weights, baseline = _preprocess_binbarlike_weights(T, y, yscale) + edge, weights, xscale, yscale, baseline end @recipe function f(::Type{Val{:barbins}}, x, y, z) - edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y) + edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) if (d[:bar_width] == nothing) bar_width := diff(edge) end @@ -473,7 +451,7 @@ end @recipe function f(::Type{Val{:scatterbins}}, x, y, z) - edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y) + edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) xerror := diff(edge)/2 x := _bin_centers(edge) y := weights @@ -538,7 +516,7 @@ end @recipe function f(::Type{Val{:stepbins}}, x, y, z) axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis] - edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y) + edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y) xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale) if !isvertical(d) @@ -564,8 +542,6 @@ end x := xpts y := ypts seriestype := :path - - ylims --> wautolims () end Plots.@deps stepbins path @@ -668,7 +644,7 @@ end if d[:seriestype] == :scatterbins # Workaround, error bars currently not set correctly by scatterbins - edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, h.edges[1], h.weights) + edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, h.edges[1], h.weights) xerror --> diff(h.edges[1])/2 seriestype := :scatter (Plots._bin_centers(edge), weights) From 2fbc3c954ae2ecf85d1bdc6cbb2c0c585df68a59 Mon Sep 17 00:00:00 2001 From: Daniel Schwabeneder Date: Tue, 16 May 2017 07:32:14 +0200 Subject: [PATCH 107/107] fix filling stepstyle on pyplot --- src/backends/pyplot.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index cf9790aa..df426bbb 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -221,6 +221,12 @@ function py_stepstyle(seriestype::Symbol) return "default" end +function py_fillstepstyle(seriestype::Symbol) + seriestype == :steppost && return "post" + seriestype == :steppre && return "pre" + return nothing +end + # # untested... return a FontProperties object from a Plots.Font # function py_font(font::Font) # pyfont.pymember("FontProperties")( @@ -868,7 +874,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) dim1, expand_data(fillrange[1], n), expand_data(fillrange[2], n) end - handle = ax[f](args...; + handle = ax[f](args..., trues(n), false, py_fillstepstyle(st); zorder = series[:series_plotindex], facecolor = py_fillcolor(series), linewidths = 0