From 23b191231c19342e630592c391e0f85a1ac9b706 Mon Sep 17 00:00:00 2001 From: Simon Christ Date: Thu, 19 Mar 2020 11:57:10 +0100 Subject: [PATCH 1/3] more positions (#2490) * tick label styling * add title_location * add legend positions * fix commata --- src/backends/pgfplotsx.jl | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/backends/pgfplotsx.jl b/src/backends/pgfplotsx.jl index 2a4e337d..672636c6 100644 --- a/src/backends/pgfplotsx.jl +++ b/src/backends/pgfplotsx.jl @@ -117,14 +117,24 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend}) fg_alpha = alpha(plot_color(sp[:foreground_color_legend])) title_cstr = plot_color(sp[:titlefontcolor]) title_a = alpha(title_cstr) + title_loc = sp[:title_location] bgc_inside = plot_color(sp[:background_color_inside]) bgc_inside_a = alpha(bgc_inside) axis_opt = PGFPlotsX.Options( "title" => sp[:title], "title style" => PGFPlotsX.Options( - "font" => pgfx_font( - sp[:titlefontsize], - pgfx_thickness_scaling(sp), + "at" => if title_loc == :left + "{(0,1)}" + elseif title_loc == :right + "{(1,1)}" + elseif title_loc isa Tuple + "{$(string(title_loc))}" + else + "{(0.5,1)}" + end, + "font" => pgfx_font( + sp[:titlefontsize], + pgfx_thickness_scaling(sp), ), "color" => title_cstr, "draw opacity" => title_a, @@ -594,11 +604,22 @@ const _pgfplotsx_markers = KW( ) const _pgfplotsx_legend_pos = KW( + :top => "north", + :bottom => "south", + :left => "west", + :right => "east", :bottomleft => "south west", :bottomright => "south east", :topright => "north east", :topleft => "north west", + :outertop => "north", + :outerbottom => "outer south", + :outerleft => "outer west", + :outerright => "outer east", + :outerbottomleft => "outer south west", + :outerbottomright => "outer south east", :outertopright => "outer north east", + :outertopleft => "outer north west", ) const _pgfx_framestyles = [:box, :axes, :origin, :zerolines, :grid, :none] @@ -929,6 +950,14 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter) "opacity" => alpha(tick_color), ), ) + tick_label_color = plot_color(axis[:tickfontcolor]) + push!(opt, + "$(letter) tick label style" => PGFPlotsX.Options( + "color" => color(tick_color), + "opacity" => alpha(tick_color), + "rotate" => axis[:rotation] + ), + ) # set to supported framestyle framestyle = pgfx_framestyle(sp[:framestyle] == false ? :none : sp[:framestyle]) From fa8c1e3967684d72d29759b96bb0628aaf1fa410 Mon Sep 17 00:00:00 2001 From: MA Laforge Date: Thu, 19 Mar 2020 17:18:07 -0400 Subject: [PATCH 2/3] Fix broken hdf5 "backend". Add support for new Attr structure. --- src/backends/hdf5.jl | 102 ++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 36 deletions(-) diff --git a/src/backends/hdf5.jl b/src/backends/hdf5.jl index 07995e17..677d994e 100644 --- a/src/backends/hdf5.jl +++ b/src/backends/hdf5.jl @@ -83,6 +83,7 @@ if length(HDF5PLOT_MAP_TELEM2STR) < 1 "ARRAY" => Array, #Dict won't allow Array to be key in HDF5PLOT_MAP_TELEM2STR #Sub-structure types: + "ATTR" => Attr, "FONT" => Font, "BOUNDINGBOX" => BoundingBox, "GRIDLAYOUT" => GridLayout, @@ -109,7 +110,7 @@ _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, src) +function _hdf5_merge!(dest::AKW, src::AKW) for (k, v) in src if isa(v, Axis) _hdf5_merge!(dest[k].plotattributes, v.plotattributes) @@ -263,6 +264,15 @@ function _hdf5plot_gwrite(grp, k::String, v::Array{T}) where T<:Number #Default grp[k] = v _hdf5plot_writetype(grp, k, HDF5PlotNative) end +function _hdf5plot_gwrite(grp, k::String, v::Dict) +#= + tstr = string(Dict) + path = HDF5.name(grp) * "/" * k + @info("Type not supported: $tstr\npath: $path") +=# + #No support for structures with Dicts different than KW (plotattributes) +end + #= function _hdf5plot_gwrite(grp, k::String, v::Array{Any}) # @show grp, k @@ -295,7 +305,8 @@ function _hdf5plot_gwrite(grp, k::String, v::Tuple) end #NOTE: _hdf5plot_overwritetype overwrites "Array" type with "Tuple". end -function _hdf5plot_gwrite(grp, k::String, plotattributes::AKW) +function _hdf5plot_gwrite(grp, k::String, plotattributes::KW) + #NOTE: Can only write directly to group, not a subi-item # @warn("Cannot write dict: $k=$plotattributes") end function _hdf5plot_gwrite(grp, k::String, v::AbstractRange) @@ -376,13 +387,22 @@ function _hdf5plot_gwrite(grp, k::String, v::Subplot) _hdf5plot_writetype(grp, Subplot) return end -function _hdf5plot_write(grp, plotattributes::AKW) + +function _hdf5plot_write(grp, plotattributes::KW) for (k, v) in plotattributes kstr = string(k) _hdf5plot_gwrite(grp, kstr, v) end return end +function _hdf5plot_write(grp, plotattributes::Attr) + for (k, v) in plotattributes + kstr = string(k) + _hdf5plot_gwrite(grp, kstr, v) + end + _hdf5plot_writetype(grp, Attr) +end + # Write main plot structures: # ---------------------------------------------------------------- @@ -445,20 +465,14 @@ _hdf5plot_convert(T::Type{Extrema}, v) = Extrema(v[1], v[2]) # Read data structures: # ---------------------------------------------------------------- -function _hdf5plot_read(grp, k::String, T::Type, dtid) +function _hdf5plot_read(grp, k::String, T::Type) 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) +function _hdf5plot_read(grp, k::String, T::Type{Font}) grp = HDF5.g_open(grp, k) family = _hdf5plot_read(grp, "family") @@ -469,7 +483,7 @@ function _hdf5plot_read(grp, k::String, T::Type{Font}, dtid) color = _hdf5plot_read(grp, "color") return Font(family, pointsize, halign, valign, rotation, color) end -function _hdf5plot_read(grp, k::String, T::Type{Array}, dtid) #ANY +function _hdf5plot_read(grp, k::String, T::Type{Array}) #ANY grp = HDF5.g_open(grp, k) sz = _hdf5plot_read(grp, "dim") if [0] == sz; return []; end @@ -488,18 +502,18 @@ function _hdf5plot_read(grp, k::String, T::Type{Array}, dtid) #ANY result = [result[iter] for iter in eachindex(result)] #Potentially make more specific return reshape(result, sz) end -function _hdf5plot_read(grp, k::String, T::Type{HDF5CTuple}, dtid) - v = _hdf5plot_read(grp, k, Array, dtid) +function _hdf5plot_read(grp, k::String, T::Type{HDF5CTuple}) + v = _hdf5plot_read(grp, k, Array) return tuple(v...) end -function _hdf5plot_read(grp, k::String, T::Type{PlotText}, dtid) +function _hdf5plot_read(grp, k::String, T::Type{PlotText}) grp = HDF5.g_open(grp, k) str = _hdf5plot_read(grp, "str") font = _hdf5plot_read(grp, "font") return PlotText(str, font) end -function _hdf5plot_read(grp, k::String, T::Type{SeriesAnnotations}, dtid) +function _hdf5plot_read(grp, k::String, T::Type{SeriesAnnotations}) grp = HDF5.g_open(grp, k) strs = _hdf5plot_read(grp, "strs") @@ -508,29 +522,29 @@ function _hdf5plot_read(grp, k::String, T::Type{SeriesAnnotations}, dtid) scalefactor = _hdf5plot_read(grp, "scalefactor") return SeriesAnnotations(strs, font, baseshape, scalefactor) end -function _hdf5plot_read(grp, k::String, T::Type{Shape}, dtid) +function _hdf5plot_read(grp, k::String, T::Type{Shape}) grp = HDF5.g_open(grp, k) x = _hdf5plot_read(grp, "x") y = _hdf5plot_read(grp, "y") return Shape(x, y) end -function _hdf5plot_read(grp, k::String, T::Type{ColorGradient}, dtid) +function _hdf5plot_read(grp, k::String, T::Type{ColorGradient}) grp = HDF5.g_open(grp, k) colors = _hdf5plot_read(grp, "colors") values = _hdf5plot_read(grp, "values") return ColorGradient(colors, values) end -function _hdf5plot_read(grp, k::String, T::Type{BoundingBox}, dtid) +function _hdf5plot_read(grp, k::String, T::Type{BoundingBox}) grp = HDF5.g_open(grp, k) x0 = _hdf5plot_read(grp, "x0") a = _hdf5plot_read(grp, "a") return BoundingBox(x0, a) end -_hdf5plot_read(grp, k::String, T::Type{RootLayout}, dtid) = RootLayout() -function _hdf5plot_read(grp, k::String, T::Type{GridLayout}, dtid) +_hdf5plot_read(grp, k::String, T::Type{RootLayout}) = RootLayout() +function _hdf5plot_read(grp, k::String, T::Type{GridLayout}) grp = HDF5.g_open(grp, k) # parent = _hdf5plot_read(grp, "parent") @@ -544,22 +558,36 @@ parent = RootLayout() return GridLayout(parent, minpad, bbox, grid, widths, heights, attr) 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) +function _hdf5plot_read(grp, T::Type{Attr}) + attr = Attr(KW(), _plot_defaults) + v = _hdf5plot_read(grp, attr) + return attr end -function _hdf5plot_read(grp, k::String, T::Type{Surface}, dtid) +function _hdf5plot_read(grp, k::String, T::Type{Axis}) + grp = HDF5.g_open(grp, k) + plotattributes = Attr(KW(), _plot_defaults) + _hdf5plot_read(grp, plotattributes) + return Axis([], plotattributes) +end +function _hdf5plot_read(grp, k::String, T::Type{Surface}) grp = HDF5.g_open(grp, k) data2d = _hdf5plot_read(grp, "data2d") return Surface(data2d) end -function _hdf5plot_read(grp, k::String, T::Type{Subplot}, dtid) +function _hdf5plot_read(grp, k::String, T::Type{Subplot}) grp = HDF5.g_open(grp, k) idx = _hdf5plot_read(grp, "index") return HDF5PLOT_PLOTREF.ref.subplots[idx] end + +#Most types don't need dtid for read!!: +_hdf5plot_read(grp, k::String, T::Type, dtid) = _hdf5plot_read(grp, k, T) +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 function _hdf5plot_read(grp, k::String) dtid = HDF5.a_read(grp[k], _hdf5plot_datatypeid) T = _hdf5_map_str2telem(dtid) #expect exception @@ -567,7 +595,7 @@ function _hdf5plot_read(grp, k::String) end #Read in values in group to populate plotattributes: -function _hdf5plot_read(grp, plotattributes::AKW) +function _hdf5plot_readattr(grp, plotattributes::AbstractDict) gnames = names(grp) for k in gnames try @@ -581,6 +609,8 @@ function _hdf5plot_read(grp, plotattributes::AKW) end return end +_hdf5plot_read(grp, plotattributes::KW) = _hdf5plot_readattr(grp, plotattributes) +_hdf5plot_read(grp, plotattributes::Attr) = _hdf5plot_readattr(grp, plotattributes) # Read main plot structures: # ---------------------------------------------------------------- @@ -593,17 +623,17 @@ function _hdf5plot_read(sp::Subplot, subpath::String, f) 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].plotattributes, kwlist) + seriesinfo = Attr(KW(), _plot_defaults) + _hdf5plot_read(grp, seriesinfo) + plot!(sp, seriesinfo[:x], seriesinfo[:y]) #Add data & create data structures + _hdf5_merge!(sp.series_list[end].plotattributes, seriesinfo) end #Perform after adding series... otherwise values get overwritten: grp = HDF5.g_open(f, _hdf5_plotelempath("$subpath/attr")) - kwlist = KW() - _hdf5plot_read(grp, kwlist) - _hdf5_merge!(sp.attr, kwlist) + attr = Attr(KW(), _plot_defaults) + _hdf5plot_read(grp, attr) + _hdf5_merge!(sp.attr, attr) return end From 3fe013cd24092c11ad6abe3e7dd9b13b39bb639c Mon Sep 17 00:00:00 2001 From: MA Laforge Date: Fri, 20 Mar 2020 18:03:00 -0400 Subject: [PATCH 3/3] Add simple testset for HDF5 plots. --- Project.toml | 3 ++- test/runtests.jl | 1 + test/test_hdf5plots.jl | 21 +++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test/test_hdf5plots.jl diff --git a/Project.toml b/Project.toml index 251c71f7..f03c1ed2 100644 --- a/Project.toml +++ b/Project.toml @@ -59,6 +59,7 @@ LaTeXStrings = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433" OffsetArrays = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" PGFPlotsX = "8314cec4-20b6-5062-9cdb-752b83310925" +HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f" RDatasets = "ce6b1742-4840-55fa-b093-852dadbb1d8b" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" @@ -68,4 +69,4 @@ UnicodePlots = "b8865327-cd53-5732-bb35-84acbb429228" VisualRegressionTests = "34922c18-7c2a-561c-bac1-01e79b2c4c92" [targets] -test = ["FileIO", "GeometryTypes", "Gtk", "ImageMagick", "Images", "LaTeXStrings", "LibGit2", "OffsetArrays", "PGFPlotsX", "Random", "RDatasets", "StaticArrays", "StatsPlots", "Test", "UnicodePlots", "VisualRegressionTests"] +test = ["FileIO", "GeometryTypes", "Gtk", "ImageMagick", "Images", "LaTeXStrings", "LibGit2", "OffsetArrays", "PGFPlotsX", "HDF5", "Random", "RDatasets", "StaticArrays", "StatsPlots", "Test", "UnicodePlots", "VisualRegressionTests"] diff --git a/test/runtests.jl b/test/runtests.jl index 5ddc6818..9b36f097 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -9,6 +9,7 @@ using LibGit2 using GeometryTypes using Dates +include("test_hdf5plots.jl") include("test_pgfplotsx.jl") reference_dir(args...) = joinpath(homedir(), ".julia", "dev", "PlotReferenceImages", args...) diff --git a/test/test_hdf5plots.jl b/test/test_hdf5plots.jl new file mode 100644 index 00000000..2c106025 --- /dev/null +++ b/test/test_hdf5plots.jl @@ -0,0 +1,21 @@ +using Plots, HDF5 + + +@testset "HDF5_Plots" begin + fname = "tmpplotsave.hdf5" + hdf5() + + x = 1:10 + psrc=plot(x, x.*x); #Create some plot + Plots.hdf5plot_write(psrc, fname) + + #Read back file: + gr() #Choose some fast backend likely to work in test environment. + pread = Plots.hdf5plot_read(fname) + + #Make sure data made it through: + @test psrc.subplots[1].series_list[1][:x] == pread.subplots[1].series_list[1][:x] + @test psrc.subplots[1].series_list[1][:y] == pread.subplots[1].series_list[1][:y] + + #display(pread) #Don't display. Regression env might not support +end #testset