From 9a4f6c5865d0a7b2fb97639168d647b978a1f331 Mon Sep 17 00:00:00 2001 From: "Tamas K. Papp" Date: Thu, 15 Feb 2018 14:44:32 +0100 Subject: [PATCH] Rewrite Plot and axis-like types. This is a step towards fixing #44 (almost there!). 1. New user-facing plot/plot3 constructor is ```julia Plot([incrementa], [options], data, trailing...) ``` and similarly for `Plot3`. `incremental` defaults to `false`, as this seems to be the most common use case. Some validation is done on `data` (checking for type). This removes the `label` kwarg, and allows us to close #16. Examples now recommend an explicit `\addlegendentry`. Docstrings are added for everything, and examples are rewritten accordingly. 2. Axis-like code cleaned up a bit with macros. Variations on log axes added. Explicitly document that strings are emitted as is. 3. GroupPlot rewritten, allow multiple plots and empty \nextgroupplot, two examples added, one from the manual and one for multiple plots. 4. Replaced random examples with deterministic ones, perhaps stick to this and close #63? Minor indentation issues fixed. 5. Minor fixes for testing framework. --- docs/make.jl | 1 + docs/src/examples/axislike.md | 37 ++++++++ docs/src/examples/coordinates.md | 6 +- docs/src/examples/gallery.md | 44 ++++++++- docs/src/examples/juliatypes.md | 76 ++++++++-------- docs/src/examples/tables.md | 10 +-- src/axiselements.jl | 147 +++++++++++++++++++----------- src/axislike.jl | 148 ++++++++++++++++--------------- test/test_build.jl | 34 +++---- test/test_elements.jl | 24 ++++- 10 files changed, 333 insertions(+), 194 deletions(-) create mode 100644 docs/src/examples/axislike.md diff --git a/docs/make.jl b/docs/make.jl index fddd835c..ba9d7c4a 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -19,6 +19,7 @@ makedocs( "Examples" => [ "examples/coordinates.md", "examples/tables.md", + "examples/axislike.md", "examples/gallery.md", "examples/juliatypes.md" ] diff --git a/docs/src/examples/axislike.md b/docs/src/examples/axislike.md new file mode 100644 index 00000000..fa2d8295 --- /dev/null +++ b/docs/src/examples/axislike.md @@ -0,0 +1,37 @@ +# Axis-like objects + +```@setup pgf +using PGFPlotsX +savefigs = (figname, obj) -> begin + PGFPlotsX.save(figname * ".pdf", obj) + run(`pdf2svg $(figname * ".pdf") $(figname * ".svg")`) + PGFPlotsX.save(figname * ".tex", obj); + return nothing +end +``` +------------------------ + +```@example pgf +x = linspace(0, 2*pi, 100) +@pgf GroupPlot( + { + group_style = + { + group_size="2 by 1", + xticklabels_at="edge bottom", + yticklabels_at="edge left" + }, + no_markers + }, + {}, + Plot(true, Table(x, sin.(x))), + Plot(true, Table(x, sin.(x .+ 0.5))), + {}, + Plot(true, Table(x, cos.(x))), + Plot(true, Table(x, cos.(x .+ 0.5)))) +savefigs("groupplot-multiple", ans) # hide +``` + +[\[.pdf\]](groupplot-multiple.pdf), [\[generated .tex\]](groupplot-multiple.tex) + +![](groupplot-multiple.svg) diff --git a/docs/src/examples/coordinates.md b/docs/src/examples/coordinates.md index 942003af..1a6b73c2 100644 --- a/docs/src/examples/coordinates.md +++ b/docs/src/examples/coordinates.md @@ -80,8 +80,7 @@ f(x, y) = (1 - x)^2 + 100*(y - x^2)^2 { surf, }, - Coordinates(x, y, f.(x, y')); - incremental = false + Coordinates(x, y, f.(x, y')) ) savefigs("coordinates-3d-matrix", ans) # hide ``` @@ -104,8 +103,7 @@ y = linspace(-0.5, 3, 50) surf, shader = "flat", }, - Coordinates(x, y, @. √(f(x, y'))); - incremental = false + Coordinates(x, y, @. √(f(x, y'))) ) ) savefigs("coordinates-3d-matrix-heatmap", ans) # hide diff --git a/docs/src/examples/gallery.md b/docs/src/examples/gallery.md index 7243c71c..1c8336da 100644 --- a/docs/src/examples/gallery.md +++ b/docs/src/examples/gallery.md @@ -77,8 +77,9 @@ savefigs("simple-expression", ans) # hide grid = "major", }, [ - Plot(Expression("-x^5 - 242"); label = "model") - Plot(Coordinates( + Plot(true, Expression("-x^5 - 242")), + raw"\addlegendentry{model}", + Plot(true, Coordinates( [ (-4.77778,2027.60977), (-3.55556,347.84069), @@ -89,8 +90,9 @@ savefigs("simple-expression", ans) # hide (2.55556,-341.40638), (3.77778,-1169.24780), (5.00000,-3269.56775), - ]; - ); label = "estimate") + ] + )), + raw"\addlegendentry{estimate}" ] ) savefigs("cost-gain", ans) # hide @@ -305,3 +307,37 @@ savefigs("mesh-scatter", ans) # hide ![](mesh-scatter.svg) +------------------------ + +```@example pgf +# this is an imitation of the figure in the manual, as we generate the data +x = linspace(0, 10, 100) +@pgf plot = Plot({very_thick}, Table(x = x, y = @. (sin(x * 8) + 1) * 4 * x)) +@pgf GroupPlot( + { + group_style = + { + group_size="2 by 2", + horizontal_sep="0pt", + vertical_sep="0pt", + xticklabels_at="edge bottom" + }, + xmin = 0, + ymin = 0, + height = "3.7cm", + width = "4cm", + no_markers + }, + nothing, + {xmin=5, xmax=10, ymin=50, ymax=100}, + plot, + {xmax=5, ymax=50}, + plot, + {xmin=5, xmax=10, ymax=50, yticklabels={}}, + plot) +savefigs("groupplot-nested", ans) # hide +``` + +[\[.pdf\]](groupplot-nested.pdf), [\[generated .tex\]](groupplot-nested.tex) + +![](groupplot-nested.svg) diff --git a/docs/src/examples/juliatypes.md b/docs/src/examples/juliatypes.md index 7987f1ac..408a4021 100644 --- a/docs/src/examples/juliatypes.md +++ b/docs/src/examples/juliatypes.md @@ -24,13 +24,14 @@ using Colors axis = Axis() @pgf for (i, col) in enumerate(distinguishable_colors(10)) offset = i * 50 - p = Plot(Expression("exp(-(x-$μ)^2 / (2 * $σ^2)) / ($σ * sqrt(2*pi)) + $offset"), - { - color = col, - domain = "-3*$σ:3*$σ", - style = { ultra_thick }, - samples = 50 - }; incremental = false) + p = Plot( + { + color = col, + domain = "-3*$σ:3*$σ", + style = { ultra_thick }, + samples = 50 + }, + Expression("exp(-(x-$μ)^2 / (2 * $σ^2)) / ($σ * sqrt(2*pi)) + $offset")) push!(axis, p) end axis @@ -45,15 +46,13 @@ Using a colormap ```@example pgf using Colors -@pgf begin -p = Plot3( - Expression("cos(deg(x)) * sin(deg(y))"), +p = @pgf Plot3( { surf, point_meta = "y", samples = 13 - }; - incremental = false + }, + Expression("cos(deg(x)) * sin(deg(y))") ) colormaps = ["Blues", "Greens", "Oranges", "Purples"] td = TikzDocument() @@ -63,13 +62,11 @@ end tp = TikzPicture("scale" => 0.5) push!(td, tp) -gp = GroupPlot({ group_style = {group_size = "2 by 2"}}) +gp = @pgf GroupPlot({ group_style = {group_size = "2 by 2"}}) push!(tp, gp) for cmap in colormaps - push!(gp, p, { colormap_name = cmap }) -end - + @pgf push!(gp, { colormap_name = cmap }, p) end savefigs("colormap", td) # hide ``` @@ -108,12 +105,13 @@ df = dataset("datasets", "iris") # load the dataset { x = "SepalLength", y = "SepalWidth", - meta = "Species" }, + meta = "Species" + }, df, # <--- Creating a Table from a DataFrame ) ), - Legend(["Setosa", "Versicolor", "Virginica"]) - ] + Legend(["Setosa", "Versicolor", "Virginica"]) + ] ) savefigs("dataframes", ans) # hide ``` @@ -133,11 +131,10 @@ x = 0.0:0.1:2π y = 0.0:0.1:2π f = (x,y) -> sin(x)*sin(y) @pgf Plot({ - contour_prepared, - very_thick - }, - Table(contours(x, y, f.(x, y'), 6)); - incremental = false) + contour_prepared, + very_thick + }, + Table(contours(x, y, f.(x, y'), 6))) savefigs("contour", ans) # hide ``` @@ -151,17 +148,18 @@ savefigs("contour", ans) # hide ```@example pgf using StatsBase: Histogram, fit -Axis(Plot(Table(fit(Histogram, randn(100), closed = :left)); - incremental = false), - @pgf { - "ybar interval", - "xticklabel interval boundaries", - xticklabel = raw"$[\pgfmathprintnumber\tick,\pgfmathprintnumber\nexttick)$", - "xticklabel style" = - { - font = raw"\tiny" - } - }) +@pgf Axis( + { + "ybar interval", + "xticklabel interval boundaries", + xmajorgrids = false, + xticklabel = raw"$[\pgfmathprintnumber\tick,\pgfmathprintnumber\nexttick)$", + "xticklabel style" = + { + font = raw"\tiny" + }, + }, + Plot(Table(fit(Histogram, linspace(0, 1, 100).^3, closed = :left)))) savefigs("histogram-1d", ans) # hide ``` @@ -171,7 +169,9 @@ savefigs("histogram-1d", ans) # hide ```@example pgf using StatsBase: Histogram, fit -h = fit(Histogram, (randn(1000), randn(1000)), closed = :left) +w = linspace(-1, 1, 100) .^ 3 +xy = vec(tuple.(w, w')) +h = fit(Histogram, (first.(xy), last.(xy)), closed = :left) @pgf Axis( { view = (0, 90), @@ -184,9 +184,7 @@ h = fit(Histogram, (randn(1000), randn(1000)), closed = :left) shader = "flat", }, - Table(h); - incremental = false - ) + Table(h)) ) savefigs("histogram-2d", ans) # hide ``` diff --git a/docs/src/examples/tables.md b/docs/src/examples/tables.md index 77b19787..a9049012 100644 --- a/docs/src/examples/tables.md +++ b/docs/src/examples/tables.md @@ -27,7 +27,7 @@ y = sin.(x) You can pass these coordinates in unnamed columns: ```@example pgf -Plot(Table([x, y]); incremental = false) +Plot(Table([x, y])) savefigs("table-unnamed-columns", ans) # hide ``` @@ -38,7 +38,7 @@ savefigs("table-unnamed-columns", ans) # hide or named columns: ```@example pgf -Plot(Table([:x => x, :y => y]); incremental = false) +Plot(Table([:x => x, :y => y])) savefigs("table-named-columns", ans) # hide ``` @@ -54,8 +54,7 @@ or rename using options: x = "a", y = "b", }, - Table([:a => x, :b => y]); - incremental = false) + Table([:a => x, :b => y])) savefigs("table-dict-rename", ans) # hide ``` @@ -79,8 +78,7 @@ z[z .≤ 0] .= -Inf surf, shader = "flat", }, - Table(x, x, z); - incremental = false + Table(x, x, z) ) ) savefigs("table-jump-3d", ans) # hide diff --git a/src/axiselements.jl b/src/axiselements.jl index 248bbfef..0dc4783b 100644 --- a/src/axiselements.jl +++ b/src/axiselements.jl @@ -1,55 +1,3 @@ -######## -# Plot # -######## - -struct Plot <: AxisElement - elements::AbstractVector{Any} - options::Options - label - incremental::Bool - _3d::Bool -end - -Base.push!(plot::Plot, element) = (push!(plot.elements, element); plot) -Base.append!(plot::Plot, element) = (append!(plot.elements, element); plot) - -function Plot(elements::AbstractVector, args::Vararg{PGFOption}; incremental = true, label = nothing) - Plot(elements, dictify(args), label, incremental, false) -end - -function Plot3(element::Vector, args::Vararg{PGFOption}; incremental = true, label = nothing) - Plot(element, dictify(args), label, incremental, true) -end - -Plot(options::Options, element; kwargs...) = Plot(element, options; kwargs...) -Plot(element, args...; kwargs...) = Plot([element], args...; kwargs...) -Plot3(element, args...; kwargs...) = Plot3([element], args...; kwargs...) -Plot3(options::Options, element; kwargs...) = Plot3(element, options; kwargs...) - -function save(filename::String, plot::Plot; kwargs...) - save(filename, Axis(plot); kwargs...) -end - -function print_tex(io_main::IO, p::Plot) - print_indent(io_main) do io - print(io, "\\addplot") - if p._3d - print(io, "3") - end - if p.incremental - print(io, "+") - end - print_options(io, p.options) - for element in p.elements - print_tex(io, element, p) - end - print(io, ";") - if p.label != nothing - print(io, "\n\\addlegendentry{$(p.label)}") - end - end -end - ############## # Expression # ############## @@ -534,6 +482,101 @@ function print_tex(io_main::IO, t::Graphics) end end +######## +# Plot # +######## + +""" +Default setting for the `incremental` flag of `Plot` and `Plot3`. +""" +const INCREMENTAL = false + +"Types accepted by `Plot` for the field `data`." +const PlotData = Union{Coordinates, Table, TableFile, Expression, Graphics} + +""" +$(TYPEDEF) + +Corresponds to the `\\addplot[3][+]` family of `pgfplot` commands. + +The 1-4+ argument outer constructors `Plot` and `Plot3` should be used in user +code. +""" +struct Plot <: OptionType + is3d::Bool + incremental::Bool + options::Options + data::PlotData + trailing::AbstractVector{Any} # FIXME can/should we be more specific? +end + +Plot(is3d::Bool, incremental::Bool, options::Options, data::PlotData, + trailing::Tuple) = Plot(is3d, incremental, options, data, collect(trailing)) + +Base.push!(plot::Plot, element) = (push!(plot.trailing, element); plot) +Base.append!(plot::Plot, element) = (append!(plot.trailing, element); plot) + +""" + Plot([incremental::Bool], [options::Options], data, trailing...) + +A plot with the given `data` (eg [`Coordinates`](@ref), [`Table`](@ref), +[`Expression`](@ref), …) and `options`, which is empty by default. + +When `incremental` (defaults to $(INCREMENTAL)), use the `\\addplot+` form, which +takes styles from the `cycle list` of `pgfplots`, otherwise `\\addplot`. + +`trailing` can be used to provide *trailing path commands* (eg `\\closedcycle`, +see the `pgfplots` manual), which are emitted using `print_tex`, before the +terminating `;`. +""" +Plot(incremental::Bool, options::Options, data::PlotData, trailing...) = + Plot(false, incremental, options, data, trailing) + +Plot(options::Options, data::PlotData, trailing...) = + Plot(false, INCREMENTAL, options, data, trailing) + +Plot(incremental::Bool, data::PlotData, trailing...) = + Plot(false, incremental, Options(), data, trailing) + +Plot(data::PlotData, trailing...) = + Plot(false, INCREMENTAL, Options(), data, trailing) + +""" + Plot3([incremental::Bool], [options::Options], data, trailing...) + +Same as [`Plot(::Bool, ::Options, ::PlotData, ...)`](@ref), but for 3D plots. +""" +Plot3(incremental::Bool, options::Options, data::PlotData, trailing...) = + Plot(true, incremental, options, data, trailing) + +Plot3(options::Options, data::PlotData, trailing...) = + Plot(true, INCREMENTAL, options, data, trailing) + +Plot3(incremental::Bool, data::PlotData, trailing...) = + Plot(true, incremental, Options(), data, trailing) + +Plot3(data::PlotData, trailing...) = + Plot(true, INCREMENTAL, Options(), data, trailing) + +function save(filename::String, plot::Plot; kwargs...) + save(filename, Axis(plot); kwargs...) +end + +function print_tex(io_main::IO, plot::Plot) + print_indent(io_main) do io + @unpack is3d, incremental, options, data, trailing = plot + print(io, "\\addplot") + is3d && print(io, "3") + incremental && print(io, "+") + print_options(io, options) + print_tex(io, data) + for t in trailing + print_tex(io, t) + end + print(io, ";") + end +end + struct Legend labels::Vector{String} end diff --git a/src/axislike.jl b/src/axislike.jl index de236530..4463f229 100644 --- a/src/axislike.jl +++ b/src/axislike.jl @@ -1,32 +1,41 @@ -abstract type AxisLike <: TikzElement end +""" +$(TYPEDEF) -Base.push!(axislike::AxisLike, plot) = (push!(axislike.plots, plot); axislike) -Base.append!(axislike::AxisLike, plot) = (append!(axislike.plots, plot); axislike) +An axis-like object that has `options` and `contents`. Each subtype `T` has the +constructor +```julia T([options], contents...) ``` -function (T::Type{<:AxisLike})(plots::AbstractVector, args::Vararg{PGFOption}) - T(plots, dictify(args)) -end +and supports [`axislike_environment(T)`](@ref). + +`contents` usually consists of `Plot` objects, but can also contain strings, +which are printed *as is* (use these for legends etc). Some subtypes have +special semantics, see their documentation. +""" +abstract type AxisLike <: TikzElement end -(T::Type{<:AxisLike})(plot, args::Vararg{PGFOption}) = T([plot], dictify(args)) -(T::Type{<:AxisLike})(options::Options, element) = T(element, options) +""" + axislike_environment(::Type{<: AxisLike}) -function (T::Type{<:AxisLike})(args::Vararg{PGFOption}) - T([], args...) -end +Return the corresponding LaTeX environment name. +""" +function axislike_environment end + +Base.push!(axislike::AxisLike, elt) = (push!(axislike.contents, elt); axislike) +Base.append!(axislike::AxisLike, elt) = (append!(axislike.contents, elt); axislike) -function print_tex(io_main::IO, axislike::AxisLike) +(T::Type{<:AxisLike})(contents...) = T(Options(), contents...) + +function print_tex(io_main::IO, axislike::T) where {T <: AxisLike} + @unpack options, contents = axislike + name = axislike_environment(T) print_indent(io_main) do io - print(io, "\\begin{", _tex_name(axislike), "}") - print_options(io, axislike.options) - for (i, plot) in enumerate(axislike.plots) - between = _in_between(axislike, i) - if !isempty(between) - print_tex(io, between) - end - print_tex(io, plot, axislike) + print(io, "\\begin{", name, "}") + print_options(io, options) + for elt in contents + print_tex(io, elt, axislike) end - print(io, "\\end{", _tex_name(axislike), "}") + print(io, "\\end{", name, "}") end end @@ -34,64 +43,63 @@ function save(filename::String, axislike::AxisLike; kwargs...) save(filename, TikzPicture(axislike); kwargs...) end -_in_between(::Any, ::Any) = "" +macro define_axislike(name, latex_environment) + @argcheck latex_environment isa String + _name = esc(name) + quote + Base.@__doc__ struct $(_name) <: AxisLike + options::Options + contents::Vector{Any} + function $(_name)(options::Options, contents...) + new(options, collect(contents)) + end + end + ($(esc(:axislike_environment)))(::Type{$(_name)}) = $(latex_environment) + end +end -######## -# Axis # -######## +@define_axislike Axis "axis" -struct Axis <: AxisLike - plots::Vector{Any} - options::Options +@define_axislike SemiLogXAxis "semilogxaxis" - # get rid of default constructor or ambiguities - Axis(v::Vector, o::Options) = new(v, o) -end +@define_axislike SemiLogYAxis "semilogyaxis" -_tex_name(::Axis) = "axis" +@define_axislike LogLogAxis "loglogaxis" -############# -# GroupPlot # -############# +@define_axislike PolarAxis "polaraxis" -struct GroupPlot <: AxisLike - plots::Vector{Any} - axisoptions::Vector{Options} - options::Options - # nextgroupplot::Vector{Options} # options for \nextgroupplot - # get rid of default constructor or ambiguities - GroupPlot(v::Vector, o::Options) = new(convert(Vector{Any}, v), [Options() for i in 1:length(v)], o) - GroupPlot(o::Options) = new(Any[], Options[], o) -end +""" + GroupPlot([options], contents...) -function print_tex(io::IO, v::Vector, gp::GroupPlot) - for p in v - print_tex(io, p, gp) - end -end +A group plot, using the `groupplots` library of `pgfplots`. -Base.push!(gp::GroupPlot, plot) = (push!(gp.plots, plot); push!(gp.axisoptions, Options()); gp) -Base.push!(gp::GroupPlot, plot, args...) = (push!(gp.plots, plot); push!(gp.axisoptions, dictify(args)); gp) +The `contents` after the global options are processed as follows: -_tex_name(::GroupPlot) = "groupplot" -#TODO Should these take IO instead? -function _in_between(gp::GroupPlot, i::Int) - io = IOBuffer() - print(io, "\\nextgroupplot") - print_options(io, gp.axisoptions[i]) - return String(take!(io)) -end +1. [`Options`](@ref) will emit a ``\\nextgroupplot` with the given options, -############# -# PolarAxis # -############# +2. `nothing` is emitted as a `\\nextgroupplot[group/empty plot]`, -struct PolarAxis <: AxisLike - plots::Vector{Any} - options::Options - # nextgroupplot::Vector{Options} # options for \nextgroupplot - # get rid of default constructor or ambiguities - PolarAxis(v::Vector, o::Options) = new(convert(Vector{Any}, v), o) -end +3. other values, eg `Plot` are emitted using [`print_tex`](@ref). +""" +@define_axislike GroupPlot "groupplot" -_tex_name(::PolarAxis) = "polaraxis" +function print_tex(io_main::IO, groupplot::GroupPlot) + @unpack options, contents = groupplot + print_indent(io_main) do io + print(io, "\\begin{groupplot}") + print_options(io, options) + for elt in contents + if elt isa Options + print(io, "\\nextgroupplot") + print_options(io, elt) + elseif elt isa Plot + print_tex(io, elt) + elseif elt isa Void + print(io, raw"\nextgroupplot[group/empty plot]") + else + print_tex(io, elt) + end + end + print(io, "\\end{groupplot}") + end +end diff --git a/test/test_build.jl b/test/test_build.jl index 077c76a8..eb02f5b2 100644 --- a/test/test_build.jl +++ b/test/test_build.jl @@ -83,22 +83,24 @@ end mktempdir() do dir cd(dir) do @pgf p = - Axis(Plot3(Expression(expr), - { - contour_gnuplot = { - number = 30, - labels = false}, - thick, - samples = 40, - }; incremental = false), - { - colorbar, - xlabel = "x", - ylabel = "y", - domain = 1:2, - y_domain = "74:87.9", - view = (0, 90), - }) + Axis( + { + colorbar, + xlabel = "x", + ylabel = "y", + domain = 1:2, + y_domain = "74:87.9", + view = (0, 90), + }, + Plot3( + { + contour_gnuplot = { + number = 30, + labels = false}, + thick, + samples = 40, + }, + Expression(expr))) PGFPlotsX.save(tmp_pdf, p) @test is_pdf_file(tmp_pdf) rm(tmp_pdf) diff --git a/test/test_elements.jl b/test/test_elements.jl index 4d10bbc8..9a6499b9 100644 --- a/test/test_elements.jl +++ b/test/test_elements.jl @@ -26,9 +26,9 @@ squashed_repr_tex(args...) = squash_whitespace(repr_tex(args...)) "A simple comparison of fields for unit tests." ≅(x, y) = x == y -function ≅(x::T, y::T) where T +function ≅(x::T, y::T) where T <: Union{PGFPlotsX.Coordinate, Coordinates, Table, Plot} for f in fieldnames(T) - getfield(x, f) == getfield(y, f) || return false + getfield(x, f) ≅ getfield(y, f) || return false end true end @@ -133,6 +133,24 @@ end path = "somefile.dat" _abspath = abspath(path) @test squashed_repr_tex(Table(@pgf({x = "a", y = "b"}), path)) == - "table [x={a}, y={b}]\n{$(_abspath)}" + "table [x={a}, y={b}]\n{$(_abspath)}" @test squashed_repr_tex(Table("somefile.dat")) == "table []\n{$(_abspath)}" end + +@testset "plot" begin + # sanity checks for constructors and printing, 2D + data2 = Table(x = 1:2, y = 3:4) + p2 = Plot(false, PGFPlotsX.INCREMENTAL, PGFPlotsX.Options(), data2, + [raw"\closedcycle"]) + @test squashed_repr_tex(p2) == + "\\addplot[]\ntable []\n{x y\n1 3\n2 4\n}\n\\closedcycle\n;" + @test Plot(PGFPlotsX.INCREMENTAL, @pgf({}), data2, raw"\closedcycle") ≅ p2 + @test Plot(@pgf({}), data2, raw"\closedcycle") ≅ p2 + @test Plot(PGFPlotsX.INCREMENTAL, data2, raw"\closedcycle") ≅ p2 + @test Plot(data2, raw"\closedcycle") ≅ p2 + # printing incremental w/ options, 2D and 3D + @test squashed_repr_tex(Plot(true, data2)) == + "\\addplot+[]\ntable []\n{x y\n1 3\n2 4\n}\n;" + @test squashed_repr_tex(Plot3(true, Table(x = 1:2, y = 3:4, z = 5:6))) == + "\\addplot3+[]\ntable []\n{x y z\n1 3 5\n2 4 6\n}\n;" +end