diff --git a/.travis.yml b/.travis.yml index 7288bdf7..b8ae53eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,4 +35,4 @@ notifications: script: - if [[ -a .git/shallow ]]; then git fetch --unshallow; fi - if [[ `uname` = "Linux" ]]; then TESTCMD="xvfb-run julia"; else TESTCMD="julia"; fi - - $TESTCMD -e 'using Pkg; Pkg.build(); Pkg.test(coverage=true)' + - $TESTCMD -e 'using Pkg; Pkg.pin(PackageSpec(name="FixedPointNumbers", version="0.7")); Pkg.build(); Pkg.test(coverage=true)' diff --git a/Project.toml b/Project.toml index f74bed5c..16ee61f2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Plots" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" author = ["Tom Breloff (@tbreloff)"] -version = "0.29.6" +version = "0.29.8" [deps] Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" diff --git a/appveyor.yml b/appveyor.yml index 02074c59..cfc27473 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -35,6 +35,7 @@ install: build_script: - echo "%JL_BUILD_SCRIPT%" - C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%" + - C:\julia\bin\julia -e "using Pkg; Pkg.pin(PackageSpec(name="FixedPointNumbers", version="0.7"))" test_script: - echo "%JL_TEST_SCRIPT%" diff --git a/src/backends/pgfplotsx.jl b/src/backends/pgfplotsx.jl index a75b0408..0171b743 100644 --- a/src/backends/pgfplotsx.jl +++ b/src/backends/pgfplotsx.jl @@ -75,7 +75,8 @@ function Base.push!(pgfx_plot::PGFPlotsXPlot, item) end function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend}) - if !pgfx_plot.is_created + if !pgfx_plot.is_created || pgfx_plot.was_shown + pgfx_sanitize_plot!(plt) the_plot = PGFPlotsX.TikzPicture(PGFPlotsX.Options()) bgc = plt.attr[:background_color_outside] == :match ? plt.attr[:background_color] : plt.attr[:background_color_outside] @@ -129,8 +130,7 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend}) ) => nothing, "fill" => cstr, "fill opacity" => a, - "text opacity" => - alpha(plot_color(sp[:legendfontcolor])), + "text opacity" => alpha(plot_color(sp[:legendfontcolor])), "font" => pgfx_font( sp[:legendfontsize], pgfx_thickness_scaling(sp), @@ -254,16 +254,13 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend}) end for (i, rng) in enumerate(segments) segment_opt = PGFPlotsX.Options() - if opt[:label] == "" - push!(segment_opt, "forget plot" => nothing) - end segment_opt = merge(segment_opt, pgfx_linestyle(opt, i)) if opt[:markershape] != :none marker = opt[:markershape] if marker isa Shape x = marker.x y = marker.y - scale_factor = 0.025 + scale_factor = 0.00125 mark_size = opt[:markersize] * scale_factor path = join( [ @@ -302,12 +299,11 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend}) rng, ) end - if i == 1 && sp[:legend] != :none && pgfx_should_add_to_legend(series) + if i == 1 && + sp[:legend] != :none && pgfx_should_add_to_legend(series) pgfx_filllegend!(series_opt, opt) end end - # series - # coordinates = pgfx_series_coordinates!(sp, series, segment_opt, opt, rng) segment_plot = @@ -339,15 +335,6 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend}) series_index, ) end - # add to legend? - if i == 1 && sp[:legend] != :none && pgfx_should_add_to_legend(series) - leg_opt = PGFPlotsX.Options() - if ribbon !== nothing - pgfx_filllegend!(axis.contents[end - 3].options, opt) - end - legend = PGFPlotsX.LegendEntry(leg_opt, opt[:label], false) - push!(axis, legend) - end # add series annotations anns = series[:series_annotations] for (xi, yi, str, fnt) in EachAnn(anns, series[:x], series[:y]) @@ -359,7 +346,31 @@ function (pgfx_plot::PGFPlotsXPlot)(plt::Plot{PGFPlotsXBackend}) pgfx_thickness_scaling(series), ) end - end + # add to legend? + if sp[:legend] != :none + leg_entry = if opt[:label] isa AVec + get(opt[:label], i, "") + elseif opt[:label] isa AbstractString + if i == 1 + get(opt, :label, "") + else + "" + end + else + throw(ArgumentError("Malformed label. label = $(opt[:label])")) + end + if leg_entry == "" || !pgfx_should_add_to_legend(series) + push!(axis.contents[end].options, "forget plot" => nothing) + else + leg_opt = PGFPlotsX.Options() + if ribbon !== nothing + pgfx_filllegend!(axis.contents[end - 3].options, opt) + end + legend = PGFPlotsX.LegendEntry(leg_opt, leg_entry, false) + push!(axis, legend) + end + end + end # for segments # add subplot annotations for ann in sp[:annotations] pgfx_add_annotation!( @@ -534,8 +545,7 @@ function pgfx_series_coordinates!( cs = join( [ - join(["($x, $y) [$(zs[j, i])]" for (j, x) in enumerate(xs)], " ") - for (i, y) in enumerate(ys) + join(["($x, $y) [$(zs[j, i])]" for (j, x) in enumerate(xs)], " ") for (i, y) in enumerate(ys) ], "\n\n", ) @@ -682,7 +692,7 @@ function pgfx_font(fontsize, thickness_scaling = 1, font = "\\selectfont") end function pgfx_should_add_to_legend(series::Series) - series.plotattributes[:primary] && series.plotattributes[:label] != "" && + series.plotattributes[:primary] && !( series.plotattributes[:seriestype] in ( :hexbin, @@ -726,8 +736,8 @@ function pgfx_marker(plotattributes, i = 1) "fill" => cstr, "fill opacity" => a, "line width" => - pgfx_thickness_scaling(plotattributes) * - _cycle(plotattributes[:markerstrokewidth], i), + pgfx_thickness_scaling(plotattributes) * + _cycle(plotattributes[:markerstrokewidth], i), "rotate" => if shape == :dtriangle 180 elseif shape == :rtriangle @@ -853,6 +863,48 @@ function pgfx_fillrange_args(fillrange, x, y, z) z_fill = [z; _cycle(fillrange, n:-1:1); z[1]] return PGFPlotsX.Coordiantes(x_fill, y_fill, z_fill) end + +function pgfx_sanitize_string(p::PlotText) + PlotText(pgfx_sanitize_string(p.str), p.font) +end +function pgfx_sanitize_string(s::AbstractString) + s = replace(s, r"\\?\#" => "\\#") + s = replace(s, r"\\?\%" => "\\%") + s = replace(s, r"\\?\_" => "\\_") + s = replace(s, r"\\?\&" => "\\&") +end +function pgfx_sanitize_plot!(plt) + for (key, value) in plt.attr + if value isa Union{AbstractString, AbstractVector{<:AbstractString}} + plt.attr[key] = pgfx_sanitize_string.(value) + end + end + for subplot in plt.subplots + for (key, value) in subplot.attr + if key == :annotations && subplot.attr[:annotations] !== nothing + old_ann = subplot.attr[key] + for i in eachindex(old_ann) + subplot.attr[key][i] = (old_ann[i][1], old_ann[i][2], pgfx_sanitize_string(old_ann[i][3])) + end + elseif value isa Union{AbstractString, AbstractVector{<:AbstractString}} + subplot.attr[key] = pgfx_sanitize_string.(value) + end + end + end + for series in plt.series_list + for (key, value) in series.plotattributes + if key == :series_annotations && series.plotattributes[:series_annotations] !== nothing + old_ann = series.plotattributes[key].strs + for i in eachindex(old_ann) + series.plotattributes[key].strs[i] = pgfx_sanitize_string(old_ann[i]) + end + elseif value isa Union{AbstractString, AbstractVector{<:AbstractString}} + series.plotattributes[key] = pgfx_sanitize_string.(value) + end + end + end + ## +end # -------------------------------------------------------------------------------------- function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter) axis = sp[Symbol(letter, :axis)] @@ -863,6 +915,13 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter) "scaled $(letter) ticks" => "false", string(letter, :label) => axis[:guide], ) + tick_color = plot_color(axis[:foreground_color_axis]) + push!(opt, + "$(letter) tick style" => PGFPlotsX.Options( + "color" => color(tick_color), + "opacity" => alpha(tick_color), + ), + ) # set to supported framestyle framestyle = pgfx_framestyle(sp[:framestyle] == false ? :none : sp[:framestyle]) @@ -882,8 +941,7 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter) opt, string(letter, "label style") => PGFPlotsX.Options( labelpos => nothing, - "font" => - pgfx_font(axis[:guidefontsize], pgfx_thickness_scaling(sp)), + "font" => pgfx_font(axis[:guidefontsize], pgfx_thickness_scaling(sp)), "color" => cstr, "draw opacity" => α, "rotate" => axis[:guidefontrotation], @@ -969,7 +1027,7 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter) opt, string(letter, "ticklabel style") => PGFPlotsX.Options( "font" => - pgfx_font(axis[:tickfontsize], pgfx_thickness_scaling(sp)), + pgfx_font(axis[:tickfontsize], pgfx_thickness_scaling(sp)), "color" => cstr, "draw opacity" => α, "rotate" => axis[:tickfontrotation], @@ -988,8 +1046,7 @@ function pgfx_axis!(opt::PGFPlotsX.Options, sp::Subplot, letter) # framestyle if framestyle in (:axes, :origin) - axispos = axis[:mirror] ? "right" : - framestyle == :axes ? "left" : "middle" + axispos = axis[:mirror] ? "right" : framestyle == :axes ? "left" : "middle" if axis[:draw_arrow] push!(opt, string("axis ", letter, " line") => axispos) @@ -1062,6 +1119,7 @@ for mime in ("application/pdf", "image/png", "image/svg+xml") mime::MIME{Symbol($mime)}, plt::Plot{PGFPlotsXBackend}, ) + plt.o.was_shown = true show(io, mime, plt.o.the_plot) end end @@ -1071,6 +1129,7 @@ function _show( mime::MIME{Symbol("application/x-tex")}, plt::Plot{PGFPlotsXBackend}, ) + plt.o.was_shown = true PGFPlotsX.print_tex( io, plt.o.the_plot, @@ -1079,5 +1138,6 @@ function _show( end function _display(plt::Plot{PGFPlotsXBackend}) + plt.o.was_shown = true display(PGFPlotsX.PGFPlotsXDisplay(), plt.o.the_plot) end diff --git a/src/examples.jl b/src/examples.jl index 72e2ee9f..9f65b913 100644 --- a/src/examples.jl +++ b/src/examples.jl @@ -800,7 +800,7 @@ const _examples = PlotExample[ plot( plot( 0:10; - ribbon = (LinRange(0, 2, 10), LinRange(0, 1, 10)), + ribbon = (LinRange(0, 2, 11), LinRange(0, 1, 11)), ), plot(0:10; ribbon = 0:0.5:5), plot(0:10; ribbon = sqrt), @@ -885,7 +885,13 @@ _backend_skips = Dict( :plotlyjs => [2, 21, 24, 25, 30, 31], :plotly => [2, 21, 24, 25, 30, 31], :pgfplots => [2, 5, 6, 10, 16, 20, 22, 23, 25, 28, 30, 31, 34, 37, 38, 39], -) + :pgfplotsx => [ 6, # images + 10, # histogram2d + 22, # contourf + 23, # pie + 32, # spy + 38, # histogram2d + ] ) diff --git a/test/test_pgfplotsx.jl b/test/test_pgfplotsx.jl index 91456fe3..c88ea2d7 100644 --- a/test/test_pgfplotsx.jl +++ b/test/test_pgfplotsx.jl @@ -1,166 +1,295 @@ using Plots, Test pgfplotsx() -function create_plot( args...; kwargs... ) - pgfx_plot = plot(args...; kwargs...) - return pgfx_plot, repr("application/x-tex", pgfx_plot) +function create_plot(args...; kwargs...) + pgfx_plot = plot(args...; kwargs...) + return pgfx_plot, repr("application/x-tex", pgfx_plot) end -function create_plot!( args...; kwargs... ) - pgfx_plot = plot!(args...; kwargs...) - return pgfx_plot, repr("application/x-tex", pgfx_plot) +function create_plot!(args...; kwargs...) + pgfx_plot = plot!(args...; kwargs...) + return pgfx_plot, repr("application/x-tex", pgfx_plot) end @testset "PGFPlotsX" begin - pgfx_plot = plot(1:5) - Plots._update_plot_object(pgfx_plot) - @test pgfx_plot.o.the_plot isa PGFPlotsX.TikzDocument - @test pgfx_plot.series_list[1].plotattributes[:quiver] === nothing - axis = Plots.pgfx_axes(pgfx_plot.o)[1] - @test count( x-> x isa PGFPlotsX.Plot, axis.contents ) == 1 - @test !haskey(axis.contents[1].options.dict, "fill") + pgfx_plot = plot(1:5) + Plots._update_plot_object(pgfx_plot) + @test pgfx_plot.o.the_plot isa PGFPlotsX.TikzDocument + @test pgfx_plot.series_list[1].plotattributes[:quiver] === nothing + axis = Plots.pgfx_axes(pgfx_plot.o)[1] + @test count(x -> x isa PGFPlotsX.Plot, axis.contents) == 1 + @test !haskey(axis.contents[1].options.dict, "fill") - @testset "3D docs example" begin - n = 100 - ts = range(0, stop=8π, length=n) - x = ts .* map(cos, ts) - y = (0.1ts) .* map(sin, ts) - z = 1:n - pl = plot(x, y, z, zcolor=reverse(z), m=(10, 0.8, :blues, Plots.stroke(0)), leg=false, cbar=true, w=5) - pgfx_plot = plot!(pl, zeros(n), zeros(n), 1:n, w=10) - Plots._update_plot_object(pgfx_plot) - if @test_nowarn(haskey(Plots.pgfx_axes(pgfx_plot.o)[1].options.dict, "colorbar") == true) - @test Plots.pgfx_axes(pgfx_plot.o)[1]["colorbar"] === nothing - end - end # testset - @testset "Color docs example" begin - y = rand(100) - plot(0:10:100, rand(11, 4), lab="lines", w=3, palette=:grays, fill=0, α=0.6) - pl = scatter!(y, zcolor=abs.(y .- 0.5), m=(:heat, 0.8, Plots.stroke(1, :green)), ms=10 * abs.(y .- 0.5) .+ 4, lab="grad") - Plots._update_plot_object(pl) - axis = Plots.pgfx_axes(pl.o)[1] - @test count( x->x isa PGFPlotsX.LegendEntry, axis.contents ) == 5 - @test count( x->x isa PGFPlotsX.Plot, axis.contents ) == 108 # each marker is its own plot, fillranges create 2 plot-objects - marker = axis.contents[15] - @test marker isa PGFPlotsX.Plot - @test marker.options["mark"] == "*" - @test marker.options["mark options"]["color"] == RGBA{Float64}( colorant"green", 0.8) - @test marker.options["mark options"]["line width"] == 1 - end # testset - @testset "Plot in pieces" begin - plot(rand(100) / 3, reg=true, fill=(0, :green)) - scatter!(rand(100), markersize=6, c=:orange) - end # testset - @testset "Marker types" begin - markers = filter((m->begin - m in Plots.supported_markers() - end), Plots._shape_keys) - markers = reshape(markers, 1, length(markers)) - n = length(markers) - x = (range(0, stop=10, length=n + 2))[2:end - 1] - y = repeat(reshape(reverse(x), 1, :), n, 1) - scatter(x, y, m=(8, :auto), lab=map(string, markers), bg=:linen, xlim=(0, 10), ylim=(0, 10)) - end # testset - @testset "Layout" begin - plot(Plots.fakedata(100, 10), layout=4, palette=[:grays :blues :heat :lightrainbow], bg_inside=[:orange :pink :darkblue :black]) - end # testset - @testset "Polar plots" begin - Θ = range(0, stop=1.5π, length=100) - r = abs.(0.1 * randn(100) + sin.(3Θ)) - plot(Θ, r, proj=:polar, m=2) - end # testset - @testset "Drawing shapes" begin - verts = [(-1.0, 1.0), (-1.28, 0.6), (-0.2, -1.4), (0.2, -1.4), (1.28, 0.6), (1.0, 1.0), (-1.0, 1.0), (-0.2, -0.6), (0.0, -0.2), (-0.4, 0.6), (1.28, 0.6), (0.2, -1.4), (-0.2, -1.4), (0.6, 0.2), (-0.2, 0.2), (0.0, -0.2), (0.2, 0.2), (-0.2, -0.6)] - x = 0.1:0.2:0.9 - y = 0.7 * rand(5) .+ 0.15 - plot(x, y, line=(3, :dash, :lightblue), marker=(Shape(verts), 30, RGBA(0, 0, 0, 0.2)), bg=:pink, fg=:darkblue, xlim=(0, 1), ylim=(0, 1), leg=false) - end # testset - @testset "Histogram 2D" begin - histogram2d(randn(10000), randn(10000), nbins=20) - end # testset - @testset "Heatmap-like" begin - xs = [string("x", i) for i = 1:10] - ys = [string("y", i) for i = 1:4] - z = float((1:4) * reshape(1:10, 1, :)) - pgfx_plot = heatmap(xs, ys, z, aspect_ratio=1) - Plots._update_plot_object(pgfx_plot) - if @test_nowarn(haskey(Plots.pgfx_axes(pgfx_plot.o)[1].options.dict, "colorbar") == true) - @test Plots.pgfx_axes(pgfx_plot.o)[1]["colorbar"] === nothing - @test Plots.pgfx_axes(pgfx_plot.o)[1]["colormap name"] == "plots1" - end + @testset "Legends" begin + legends_plot = plot( rand(5,2), lab = ["1" ""] ) + scatter!(legends_plot, rand(5) ) + Plots._update_plot_object(legends_plot) + axis_contents = Plots.pgfx_axes(legends_plot.o)[1].contents + leg_entries = filter( x -> x isa PGFPlotsX.LegendEntry, axis_contents ) + series = filter( x -> x isa PGFPlotsX.Plot, axis_contents ) + @test length(leg_entries) == 2 + @test !haskey(series[1].options.dict, "forget plot") + @test haskey(series[2].options.dict, "forget plot") + @test !haskey(series[3].options.dict, "forget plot") + end # testset - pgfx_plot = wireframe(xs, ys, z, aspect_ratio=1) - # TODO: clims are wrong - end # testset - @testset "Contours" begin - x = 1:0.5:20 - y = 1:0.5:10 - f(x, y) = begin - (3x + y ^ 2) * abs(sin(x) + cos(y)) - end - X = repeat(reshape(x, 1, :), length(y), 1) - Y = repeat(y, 1, length(x)) - Z = map(f, X, Y) - p2 = contour(x, y, Z) - p1 = contour(x, y, f, fill=true) - plot(p1, p2) - # TODO: colorbar for filled contours - end # testset - @testset "Varying colors" begin - t = range(0, stop=1, length=100) - θ = (6π) .* t - x = t .* cos.(θ) - y = t .* sin.(θ) - p1 = plot(x, y, line_z=t, linewidth=3, legend=false) - p2 = scatter(x, y, marker_z=((x, y)->begin - x + y - end), color=:bluesreds, legend=false) - plot(p1, p2) - end # testset - @testset "Framestyles" begin - scatter(fill(randn(10), 6), fill(randn(10), 6), framestyle=[:box :semi :origin :zerolines :grid :none], title=[":box" ":semi" ":origin" ":zerolines" ":grid" ":none"], color=permutedims(1:6), layout=6, label="", markerstrokewidth=0, ticks=-2:2) - # TODO: support :semi - end # testset - @testset "Quiver" begin - x = -2pi:0.2:2*pi - y = sin.(x) + @testset "3D docs example" begin + n = 100 + ts = range(0, stop = 8π, length = n) + x = ts .* map(cos, ts) + y = (0.1ts) .* map(sin, ts) + z = 1:n + pl = plot( + x, + y, + z, + zcolor = reverse(z), + m = (10, 0.8, :blues, Plots.stroke(0)), + leg = false, + cbar = true, + w = 5, + ) + pgfx_plot = plot!(pl, zeros(n), zeros(n), 1:n, w = 10) + Plots._update_plot_object(pgfx_plot) + if @test_nowarn( + haskey(Plots.pgfx_axes(pgfx_plot.o)[1].options.dict, "colorbar") == true + ) + @test Plots.pgfx_axes(pgfx_plot.o)[1]["colorbar"] === nothing + end + end # testset + @testset "Color docs example" begin + y = rand(100) + plot( + 0:10:100, + rand(11, 4), + lab = "lines", + w = 3, + palette = :grays, + fill = 0, + α = 0.6, + ) + pl = scatter!( + y, + zcolor = abs.(y .- 0.5), + m = (:heat, 0.8, Plots.stroke(1, :green)), + ms = 10 * abs.(y .- 0.5) .+ 4, + lab = ["grad", "", "ient"], + ) + Plots._update_plot_object(pl) + axis = Plots.pgfx_axes(pl.o)[1] + @test count(x -> x isa PGFPlotsX.LegendEntry, axis.contents) == 6 + @test count(x -> x isa PGFPlotsX.Plot, axis.contents) == 108 # each marker is its own plot, fillranges create 2 plot-objects + marker = axis.contents[15] + @test marker isa PGFPlotsX.Plot + @test marker.options["mark"] == "*" + @test marker.options["mark options"]["color"] == + RGBA{Float64}(colorant"green", 0.8) + @test marker.options["mark options"]["line width"] == 1 + end # testset + @testset "Plot in pieces" begin + pic = plot(rand(100) / 3, reg = true, fill = (0, :green)) + scatter!(pic, rand(100), markersize = 6, c = :orange) + Plots._update_plot_object(pic) + axis_contents = Plots.pgfx_axes(pic.o)[1].contents + leg_entries = filter( x -> x isa PGFPlotsX.LegendEntry, axis_contents ) + series = filter( x -> x isa PGFPlotsX.Plot, axis_contents ) + @test length(leg_entries) == 2 + @test length(series) == 4 + @test haskey(series[1].options.dict, "forget plot") + @test !haskey(series[2].options.dict, "forget plot") + @test haskey(series[3].options.dict, "forget plot") + @test !haskey(series[4].options.dict, "forget plot") + end # testset + @testset "Marker types" begin + markers = filter((m -> begin + m in Plots.supported_markers() + end), Plots._shape_keys) + markers = reshape(markers, 1, length(markers)) + n = length(markers) + x = (range(0, stop = 10, length = n + 2))[2:(end - 1)] + y = repeat(reshape(reverse(x), 1, :), n, 1) + scatter( + x, + y, + m = (8, :auto), + lab = map(string, markers), + bg = :linen, + xlim = (0, 10), + ylim = (0, 10), + ) + end # testset + @testset "Layout" begin + plot( + Plots.fakedata(100, 10), + layout = 4, + palette = [:grays :blues :heat :lightrainbow], + bg_inside = [:orange :pink :darkblue :black], + ) + end # testset + @testset "Polar plots" begin + Θ = range(0, stop = 1.5π, length = 100) + r = abs.(0.1 * randn(100) + sin.(3Θ)) + plot(Θ, r, proj = :polar, m = 2) + end # testset + @testset "Drawing shapes" begin + verts = [ + (-1.0, 1.0), + (-1.28, 0.6), + (-0.2, -1.4), + (0.2, -1.4), + (1.28, 0.6), + (1.0, 1.0), + (-1.0, 1.0), + (-0.2, -0.6), + (0.0, -0.2), + (-0.4, 0.6), + (1.28, 0.6), + (0.2, -1.4), + (-0.2, -1.4), + (0.6, 0.2), + (-0.2, 0.2), + (0.0, -0.2), + (0.2, 0.2), + (-0.2, -0.6), + ] + x = 0.1:0.2:0.9 + y = 0.7 * rand(5) .+ 0.15 + plot( + x, + y, + line = (3, :dash, :lightblue), + marker = (Shape(verts), 30, RGBA(0, 0, 0, 0.2)), + bg = :pink, + fg = :darkblue, + xlim = (0, 1), + ylim = (0, 1), + leg = false, + ) + end # testset + @testset "Histogram 2D" begin + histogram2d(randn(10000), randn(10000), nbins = 20) + end # testset + @testset "Heatmap-like" begin + xs = [string("x", i) for i = 1:10] + ys = [string("y", i) for i = 1:4] + z = float((1:4) * reshape(1:10, 1, :)) + pgfx_plot = heatmap(xs, ys, z, aspect_ratio = 1) + Plots._update_plot_object(pgfx_plot) + if @test_nowarn( + haskey(Plots.pgfx_axes(pgfx_plot.o)[1].options.dict, "colorbar") == true + ) + @test Plots.pgfx_axes(pgfx_plot.o)[1]["colorbar"] === nothing + @test Plots.pgfx_axes(pgfx_plot.o)[1]["colormap name"] == "plots1" + end - u = ones(length(x)) - v = cos.(x) - arrow_plot = plot( x, y, quiver = (u, v), arrow = true ) - # TODO: could adjust limits to fit arrows if too long, but how? - # TODO: get latex available on CI - # mktempdir() do path - # @test_nowarn savefig(arrow_plot, path*"arrow.pdf") - # end - end # testset - @testset "Annotations" begin - y = rand(10) - plot(y, annotations=(3, y[3], Plots.text("this is \\#3", :left)), leg=false) - annotate!([(5, y[5], Plots.text("this is \\#5", 16, :red, :center)), (10, y[10], Plots.text("this is \\#10", :right, 20, "courier"))]) - annotation_plot = scatter!(range(2, stop=8, length=6), rand(6), marker=(50, 0.2, :orange), series_annotations=["series", "annotations", "map", "to", "series", Plots.text("data", :green)]) - # mktempdir() do path - # @test_nowarn savefig(annotation_plot, path*"annotation.pdf") - # end - end # testset - @testset "Ribbon" begin - aa = rand(10) - bb = rand(10) - cc = rand(10) - conf = [aa-cc bb-cc] - ribbon_plot = plot(collect(1:10),fill(1,10), ribbon=(conf[:,1],conf[:,2])) - Plots._update_plot_object(ribbon_plot) - axis = Plots.pgfx_axes(ribbon_plot.o)[1] - plots = filter(x->x isa PGFPlotsX.Plot, axis.contents) - @test length(plots) == 4 - @test !haskey(plots[1].options.dict, "fill") - @test !haskey(plots[2].options.dict, "fill") - @test !haskey(plots[3].options.dict, "fill") - @test haskey(plots[4].options.dict, "fill") - @test ribbon_plot.o !== nothing - @test ribbon_plot.o.the_plot !== nothing - # mktempdir() do path - # @test_nowarn savefig(ribbon_plot, path*"ribbon.svg") - # end - end # testset - end # testset + pgfx_plot = wireframe(xs, ys, z, aspect_ratio = 1) + # TODO: clims are wrong + end # testset + @testset "Contours" begin + x = 1:0.5:20 + y = 1:0.5:10 + f(x, y) = begin + (3x + y^2) * abs(sin(x) + cos(y)) + end + X = repeat(reshape(x, 1, :), length(y), 1) + Y = repeat(y, 1, length(x)) + Z = map(f, X, Y) + p2 = contour(x, y, Z) + p1 = contour(x, y, f, fill = true) + plot(p1, p2) + # TODO: colorbar for filled contours + end # testset + @testset "Varying colors" begin + t = range(0, stop = 1, length = 100) + θ = (6π) .* t + x = t .* cos.(θ) + y = t .* sin.(θ) + p1 = plot(x, y, line_z = t, linewidth = 3, legend = false) + p2 = scatter( + x, + y, + marker_z = ((x, y) -> begin + x + y + end), + color = :bluesreds, + legend = false, + ) + plot(p1, p2) + end # testset + @testset "Framestyles" begin + scatter( + fill(randn(10), 6), + fill(randn(10), 6), + framestyle = [:box :semi :origin :zerolines :grid :none], + title = [":box" ":semi" ":origin" ":zerolines" ":grid" ":none"], + color = permutedims(1:6), + layout = 6, + label = "", + markerstrokewidth = 0, + ticks = -2:2, + ) + # TODO: support :semi + end # testset + @testset "Quiver" begin + x = (-2pi):0.2:(2 * pi) + y = sin.(x) + + u = ones(length(x)) + v = cos.(x) + arrow_plot = plot(x, y, quiver = (u, v), arrow = true) + # TODO: could adjust limits to fit arrows if too long, but how? + # TODO: get latex available on CI + # mktempdir() do path + # @test_nowarn savefig(arrow_plot, path*"arrow.pdf") + # end + end # testset + @testset "Annotations" begin + y = rand(10) + plot( + y, + annotations = (3, y[3], Plots.text("this is \\#3", :left)), + leg = false, + ) + annotate!([ + (5, y[5], Plots.text("this is \\#5", 16, :red, :center)), + (10, y[10], Plots.text("this is \\#10", :right, 20, "courier")), + ]) + annotation_plot = scatter!( + range(2, stop = 8, length = 6), + rand(6), + marker = (50, 0.2, :orange), + series_annotations = [ + "series", + "annotations", + "map", + "to", + "series", + Plots.text("data", :green), + ], + ) + # mktempdir() do path + # @test_nowarn savefig(annotation_plot, path*"annotation.pdf") + # end + end # testset + @testset "Ribbon" begin + aa = rand(10) + bb = rand(10) + cc = rand(10) + conf = [aa - cc bb - cc] + ribbon_plot = + plot(collect(1:10), fill(1, 10), ribbon = (conf[:, 1], conf[:, 2])) + Plots._update_plot_object(ribbon_plot) + axis = Plots.pgfx_axes(ribbon_plot.o)[1] + plots = filter(x -> x isa PGFPlotsX.Plot, axis.contents) + @test length(plots) == 4 + @test !haskey(plots[1].options.dict, "fill") + @test !haskey(plots[2].options.dict, "fill") + @test !haskey(plots[3].options.dict, "fill") + @test haskey(plots[4].options.dict, "fill") + @test ribbon_plot.o !== nothing + @test ribbon_plot.o.the_plot !== nothing + # mktempdir() do path + # @test_nowarn savefig(ribbon_plot, path*"ribbon.svg") + # end + end # testset +end # testset