diff --git a/Project.toml b/Project.toml index cdcffb6..01b78d9 100644 --- a/Project.toml +++ b/Project.toml @@ -4,11 +4,13 @@ uuid = "dc211083-a33a-5b79-959f-2ff34033469d" [deps] ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" ReusePatterns = "a39b5e78-89b5-562b-97d8-70689129df0c" StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" StructC14N = "d2514e9c-36c4-5b8e-97e2-51e7675c221c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea" [compat] julia = "≥ 1.0.0" diff --git a/README.md b/README.md index 01bf53f..63dbe09 100644 --- a/README.md +++ b/README.md @@ -231,3 +231,24 @@ or push!(Gnuplot.options.init, "set term sixelgd") ``` Note that the latter requires Sixel graphics to be enabled (e.g. `xterm -ti vt340`). + + +## Palettes +The **Gnuplot.jl** package comes with all the [Gnuplot palettes](https://github.com/Gnuplotting/gnuplot-palettes)) readily available. +The whole list can be retrieved with `print(Gnuplot.palette_list())`. + +Individual palette can be accessed with `Gnuplot.palette()` and used as any other command, as in the following example: +```julia +pal1 = Gnuplot.palette("rdylgn") +pal2 = Gnuplot.palette("viridis") + +x = -8:0.25:8 +y = -8:0.25:8 +r = [x.^2 .+ y.^2 for x in x, y in y] +z = sin.(sqrt.(r)) ./ sqrt.(r) + +@gsp "set multiplot layout 1,2" "set pm3d depthorder" "set border 0" +@gsp :- "unset key" "unset xtics" "unset ytics" "unset ztics" "unset colorbox" +@gsp :- "set view 60, 30, 1.5, 0.9" +@gsp :- 1 title="rdylgn" pal1 x y z "w pm3d" 2 tit="viridis" pal2 x y z "w pm3d" +``` diff --git a/examples/hidden2.1.jl b/examples/hidden2.1.jl index e30ea6e..e30b054 100644 --- a/examples/hidden2.1.jl +++ b/examples/hidden2.1.jl @@ -7,7 +7,7 @@ x = LinRange(-10, 10, 25) y = LinRange(-10, 10, 25) @gsp "set xyplane at 0" -@gsp :- "unset key" +@gsp :- "unset key" :- @gsp :- "set palette rgbformulae 31,-11,32" @gsp :- "set style fill solid 0.5" @gsp :- "set cbrange [-1:1]" diff --git a/examples/hidden2.3.jl b/examples/hidden2.3.jl index 70fba8e..e14b361 100644 --- a/examples/hidden2.3.jl +++ b/examples/hidden2.3.jl @@ -7,35 +7,35 @@ using Gnuplot U = LinRange(-pi, pi, 100); # 50 V = LinRange(-pi, pi, 20); -@gsp :- "unset key" :- -@gsp :- "unset xtics" :- -@gsp :- "unset ytics" :- -@gsp :- "unset ztics" :- -@gsp :- "set border 0" :- -@gsp :- "set view 60, 30, 1.5, 0.9" :- -@gsp :- "unset colorbox" :- -@gsp :- "set colorbox vertical user origin 0.9, 0.15 size 0.02, 0.50" :- -@gsp :- "set format cb '%.1f'" :- +@gsp :- "unset key" +@gsp :- "unset xtics" +@gsp :- "unset ytics" +@gsp :- "unset ztics" +@gsp :- "set border 0" +@gsp :- "set view 60, 30, 1.5, 0.9" +@gsp :- "unset colorbox" +@gsp :- "set colorbox vertical user origin 0.9, 0.15 size 0.02, 0.50" +@gsp :- "set format cb '%.1f'" for loop in 1:2 if loop == 1 - @gsp :- 1 title="PM3D surface\\nno depth sorting" :- - @gsp :- "set origin -0.02,0.0" :- - @gsp :- "set size 0.55, 0.9" :- + @gsp :- 1 title="PM3D surface\\nno depth sorting" + @gsp :- "set origin -0.02,0.0" + @gsp :- "set size 0.55, 0.9" @gsp :- "set pm3d scansforward" :- # scansbackward else - @gsp :- 2 title="PM3D surface\\ndepth sorting" :- - @gsp :- "set origin 0.40,0.0" :- - @gsp :- "set size 0.55, 0.9" :- - @gsp :- "set pm3d depthorder" :- + @gsp :- 2 title="PM3D surface\\ndepth sorting" + @gsp :- "set origin 0.40,0.0" + @gsp :- "set size 0.55, 0.9" + @gsp :- "set pm3d depthorder" end - x = [cos(u) + .5 * cos(u) * cos(v) for u in U, v in V]; x = reshape(x, :) - y = [sin(u) + .5 * sin(u) * cos(v) for u in U, v in V]; y = reshape(y, :) - z = [.5 * sin(v) for u in U, v in V]; # Note: this must be a 2D array + x = [cos(u) + .5 * cos(u) * cos(v) for u in U, v in V] + y = [sin(u) + .5 * sin(u) * cos(v) for u in U, v in V] + z = [.5 * sin(v) for u in U, v in V] @gsp :- x y z "w pm3d" - x = [1 + cos(u) + .5 * cos(u) * cos(v) for u in U, v in V]; x = reshape(x, :) - y = [.5 * sin(v) for u in U, v in V]; y = reshape(y, :) - z = [sin(u) + .5 * sin(u) * cos(v) for u in U, v in V]; # Note: this must be a 2D array + x = [1 + cos(u) + .5 * cos(u) * cos(v) for u in U, v in V] + y = [.5 * sin(v) for u in U, v in V] + z = [sin(u) + .5 * sin(u) * cos(v) for u in U, v in V] @gsp :- x y z "w pm3d" end diff --git a/src/Gnuplot.jl b/src/Gnuplot.jl index 446cf15..ebb092e 100644 --- a/src/Gnuplot.jl +++ b/src/Gnuplot.jl @@ -1,6 +1,7 @@ module Gnuplot using StructC14N, ColorTypes, Printf, StatsBase, ReusePatterns, DataFrames +using Pkg.Artifacts, ZipFile import Base.reset import Base.println @@ -59,8 +60,7 @@ Base.@kwdef mutable struct Options end const sessions = Dict{Symbol, DrySession}() const options = Options() - - +const dpalettes = Dict{String, String}() # ╭───────────────────────────────────────────────────────────────────╮ # │ LOW LEVEL FUNCTIONS │ @@ -70,7 +70,40 @@ function string(c::ColorTypes.RGB) return string(float(c.r)*255) * " " * string(float(c.g)*255) * " " * string(float(c.b)*255) end +# --------------------------------------------------------------------- +palette_list() = keys(dpalettes) +function palette(choice="") + if length(dpalettes) == 0 + function path() + name = "gnuplot-palettes" + toml = joinpath(@__DIR__, "Artifacts.toml") + hash = artifact_hash(name, toml) + if hash == nothing || !artifact_exists(hash) + hash = create_artifact() do artifact_dir + download("https://github.com/Gnuplotting/gnuplot-palettes/archive/master.zip", joinpath(artifact_dir, name * ".zip")) + end + bind_artifact!(toml, name, hash) + end + return joinpath(artifact_path(hash), name * ".zip") + end + dir = ZipFile.Reader(path()) + out = Vector{String}() + for entry in dir.files + (_, file) = splitdir(entry.name) + (length(file) > 4) || continue + (file[end-3:end] == ".pal") || continue + file = file[1:end-4] + dpalettes[file] = join(Char.(read(entry))) + end + close(dir) + end + (choice in keys(dpalettes)) && (return dpalettes[choice]) + return " " +end +palette() # Populate dictionary + +# --------------------------------------------------------------------- """ # CheckGnuplotVersion @@ -202,7 +235,7 @@ function data2string(args...) return accum end - # Multidimensional, add independent indices + # Multidimensional, no independent indices if firstMultiDim == 1 #@info "Case 2" @assert minimum(lengths) == maximum(lengths) "Array size are incompatible" @@ -210,7 +243,7 @@ function data2string(args...) for CIndex in CartesianIndices(size(args[1])) indices = Tuple(CIndex) (i > 1) && (indices[end-1] == 1) && (push!(accum, "")) # blank line - v = " " * join(string.(getindex.(Ref(Tuple(indices)), 1:ndims(args[1]))), " ") + v = "" # * join(string.(getindex.(Ref(Tuple(indices)), 1:ndims(args[1]))), " ") for iarg in 1:length(args) d = args[iarg] v *= " " * string(d[i]) @@ -413,7 +446,7 @@ function println(gp::GPSession, d::DataSet) if options.verbose v = "" printstyled(color=:light_black, "GNUPLOT ($(gp.sid)) $(d.name) << EOD\n") - n = min(options.printlines, length(d.lines)) + n = min(options.datalines, length(d.lines)) for i in 1:n printstyled(color=:light_black, "GNUPLOT ($(gp.sid)) $(d.lines[i])\n") end @@ -563,9 +596,11 @@ function dump(gp::DrySession, stream; term::AbstractString="", output::AbstractS for j in 1:length(d.cmds) println(stream, d.cmds[j]) end - s = (d.flag3d ? "splot " : "plot ") * " \\\n " * - join(d.elems, ", \\\n ") - println(stream, s) + if length(d.elems) > 0 + s = (d.flag3d ? "splot " : "plot ") * " \\\n " * + join(d.elems, ", \\\n ") + println(stream, s) + end end (length(gp.plots) > 1) && println(stream, "unset multiplot") (output != "") && println(stream, "set output") @@ -637,7 +672,7 @@ function driver(args...; flag3d=false) if typeof(arg) == Symbol if arg == :- (loop == 1) && (iarg < length(args)) && (doReset = false) - (loop == 1) && (iarg > 1) && (doDump = false) + (loop == 1) && (iarg > 1 ) && (doDump = false) else (loop == 1) && (gp = getsession(arg)) end @@ -659,6 +694,7 @@ function driver(args...; flag3d=false) (loop == 2) && (@assert arg > 0) (loop == 2) && (dataplot = ""; dataCompleted()) (loop == 2) && setmulti(gp, arg) + (loop == 2) && (gp.plots[gp.curmid].flag3d = flag3d) elseif isa(arg, String) # Either a dataname, a plot or a command if loop == 2 @@ -669,9 +705,9 @@ function driver(args...; flag3d=false) dataplot = arg dataCompleted() else - (isPlot, flag3d, cmd) = isPlotCmd(arg) + (isPlot, is3d, cmd) = isPlotCmd(arg) if isPlot - gp.plots[gp.curmid].flag3d = flag3d + gp.plots[gp.curmid].flag3d = is3d newplot(gp, cmd) else newcmd(gp, arg) diff --git a/test/runtests.jl b/test/runtests.jl index 230dd53..b56b1c9 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -26,17 +26,17 @@ s = Gnuplot.data2string(x, y, x.+y) z = [X+Y for X in x, Y in y]; s = Gnuplot.data2string(z) -@test all(s .== [" 1 1 5" , - " 2 1 6" , - " 3 1 7" , - "" , - " 1 2 6" , - " 2 2 7" , - " 3 2 8" , - "" , - " 1 3 7" , - " 2 3 8" , - " 3 3 9" ]) +@test all(s .== [" 5" , + " 6" , + " 7" , + "" , + " 6" , + " 7" , + " 8" , + "" , + " 7" , + " 8" , + " 9" ]) s = Gnuplot.data2string(x, y, z)