Minor changes
This commit is contained in:
parent
605ad0cfda
commit
5487e60222
103
README.md
103
README.md
@ -6,9 +6,9 @@
|
||||
**Gnuplot.jl** allows easy and fast use of [Gnuplot](http://gnuplot.info/) as a data visualization tool in Julia. Its main features are:
|
||||
|
||||
- transparent interface between Julia and Gnuplot to exploit all functionalities of the latter, both present and future ones;
|
||||
|
||||
|
||||
- fast data transmission to gnuplot through system pipes (no temporary files involved);
|
||||
|
||||
|
||||
- handles multiple Gnuplot process simultaneously;
|
||||
|
||||
- support for multiplots;
|
||||
@ -52,7 +52,7 @@ noise = randn(length(x))./2;
|
||||
e = 0.5 * fill(1., length(x));
|
||||
|
||||
@gp("set key horizontal", "set grid", title="My title",
|
||||
xrange=(-7,7), ylabel="Y label", xlab="X label",
|
||||
xrange=(-7,7), ylabel="Y label", xlab="X label",
|
||||
x, y, "w l t 'Real model' dt 2 lw 2 lc rgb 'red'",
|
||||
x, y+noise, e, "w errorbars t 'Data'")
|
||||
```
|
||||
@ -67,7 +67,7 @@ Note that this simple example already covers the vast majority of use cases, sin
|
||||
If you set the verbose option (`Gnuplot.setverbose(true)`, which is `false` by default) you'll be able to see all the communication taking place between the **Gnuplot.jl** package and the underlyng Gnuplot process. Repeating the last command:
|
||||
```Julia
|
||||
julia> @gp("set key horizontal", "set grid", title="My title",
|
||||
xrange=(-7,7), ylabel="Y label", xlab="X label",
|
||||
xrange=(-7,7), ylabel="Y label", xlab="X label",
|
||||
x, y, "w l t 'Real model' dt 2 lw 2 lc rgb 'red'",
|
||||
x, y+noise, e, "w errorbars t 'Data'")
|
||||
GNUPLOT (default) print GPVAL_TERM
|
||||
@ -150,57 +150,84 @@ or show an interactive 3D plots using the `@gsp` macro in place of `@gp`, e.g.:
|
||||
Further documentation for the `@gp` and `@gsp` macros is available in the REPL by means of the `@doc` macro or by typing `?` in the REPL followed by the macro name.
|
||||
|
||||
|
||||
### Export to image
|
||||
TODO
|
||||
|
||||
### Save a script file
|
||||
TODO
|
||||
|
||||
### Multiple gnuplot istances
|
||||
|
||||
The **Gnuplot.jl** package can handle multiple Gnuplot istances simultaneously, each idenitified by a unique session name (actually a Julia symbol). To use a specific session simply name it in a `@gp` or `@gsp` call. If the session is not yet created it will be automatically started:
|
||||
|
||||
``` Julia
|
||||
# Plot using session GP1
|
||||
# Plot using a session named GP1
|
||||
x = 1:10
|
||||
@gp :GP1 x x.^2
|
||||
|
||||
# Plot using session GP2
|
||||
# Plot using a session named GP2
|
||||
@gp x x.^2 :GP2
|
||||
|
||||
# Plot using default session
|
||||
# Plot using default session (i.e. do not specify any session name)
|
||||
@gp x x.^2
|
||||
```
|
||||
|
||||
### Customization
|
||||
|
||||
A custom command to start a Gnuplot process can be specified as follows
|
||||
``` Julia
|
||||
Gnuplot.state.cmd = "/path/to/gnuplot/executable"
|
||||
```
|
||||
|
||||
Also, the package may work in *dry* mode, i.e. without any underlying Gnuplot process:
|
||||
``` Julia
|
||||
Gnuplot.state.dry = true
|
||||
```
|
||||
The prupose is to create gnuplot scripts without running them, e.g:
|
||||
```Julia
|
||||
@gp x x.^2 "w l"
|
||||
save("test.gp")
|
||||
```
|
||||
The `test.gp` can then be loaded directly in gnuplot with:
|
||||
```
|
||||
gnuplot> load 'test.gp'
|
||||
```
|
||||
|
||||
|
||||
### Direct execution of gnuplot commands
|
||||
Both the `@gp` and `@gsp` macros store data and commands in the package state to allow using multiple statements for a single plot, or to save all data and commands on a script file. However the user may directly execute command on the underlying Gnuplot process using the `Gnuplot.exec` function. E.g., we can retrieve the values of the fitting parameters of the previous example:
|
||||
```Julia
|
||||
# Retrieve values fr a, b and c
|
||||
a = Meta.parse(Gnuplot.exec("print a"))
|
||||
b = Meta.parse(Gnuplot.exec("print b"))
|
||||
c = Meta.parse(Gnuplot.exec("print c"))
|
||||
```
|
||||
|
||||
### Terminating a session
|
||||
A session and the associated gnuplot process can be terminated by a call to `quit`, specifying the session name, e.g.:
|
||||
``` Julia
|
||||
julia> Gnuplot.quit(:GP1)
|
||||
```
|
||||
A call to `Gnuplot.quitall()` will terminate all active sessions.
|
||||
|
||||
|
||||
|
||||
## Direct execution of gnuplot commands
|
||||
Both the `@gp` and `@gsp` macros store data and commands in the package state to allow using multiple statements for a single plot, or to save all data and commands on a script file. However the user may directly execute command on the underlying Gnuplot process using the `Gnuplot.exec` function. E.g., we can retrieve the values of the fitting parameters of the previous example:
|
||||
```Julia
|
||||
# Retrieve values fr a, b and c
|
||||
a = Meta.parse(Gnuplot.exec("print a"))
|
||||
b = Meta.parse(Gnuplot.exec("print b"))
|
||||
c = Meta.parse(Gnuplot.exec("print c"))
|
||||
```
|
||||
|
||||
|
||||
## Customization
|
||||
|
||||
A custom command to start a Gnuplot process can be specified as follows
|
||||
``` Julia
|
||||
Gnuplot.options.cmd = "/path/to/gnuplot/executable"
|
||||
```
|
||||
|
||||
Also, the package may work in *dry* mode, i.e. without any underlying Gnuplot process:
|
||||
``` Julia
|
||||
Gnuplot.options.dry = true
|
||||
```
|
||||
The prupose is to create gnuplot scripts without running them, e.g:
|
||||
```Julia
|
||||
@gp x x.^2 "w l"
|
||||
save("test.gp")
|
||||
```
|
||||
The `test.gp` can then be loaded directly in gnuplot with:
|
||||
```
|
||||
gnuplot> load 'test.gp'
|
||||
```
|
||||
|
||||
Finally, you can specify initialising commands to be executed when the Gnuplot process starts, in the same way as you use `.gnuplotrc`. For instance, to set up a default terminal:
|
||||
```julia
|
||||
push!(Gnuplot.options.init, "set term sixelgd")
|
||||
```
|
||||
The above command should be executed *BEFORE* starting a new session. (use `Gnuplot.quitall()` will terminate all active sessions).
|
||||
|
||||
|
||||
## Plot in a terminal (no X11)
|
||||
Gnuplot supports displaying plot in a terminal application, with no need for X11 or other window frameworks. This is very useful when you run Julia on a remote shell through `ssh`, through a slow network link.
|
||||
|
||||
The Gnuplot terminals able to operate on "terminal" applications are `dumb` and `sixelgd`. You can use them as default with:
|
||||
```julia
|
||||
push!(Gnuplot.options.init, "set term dumb")
|
||||
```
|
||||
or
|
||||
```julia
|
||||
push!(Gnuplot.options.init, "set term sixelgd")
|
||||
```
|
||||
Note that the latter requires Sixel graphics to be enabled (e.g. `xterm -ti vt340`).
|
||||
|
||||
109
src/Gnuplot.jl
109
src/Gnuplot.jl
@ -49,18 +49,17 @@ end
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
mutable struct State
|
||||
sessions::Dict{Symbol, DrySession};
|
||||
dry::Bool
|
||||
cmd::String
|
||||
default::Symbol; # default session name
|
||||
init::Vector{String} # Commands to initialize the gnuplot session (e.g., to set default terminal)
|
||||
verbose::Bool; # verbosity level (true/false)
|
||||
printlines::Int; # How many data lines are printed in log
|
||||
State() = new(Dict{Symbol, DrySession}(), true, "gnuplot", :default, Vector{String}(), false, 4)
|
||||
Base.@kwdef mutable struct Options
|
||||
dry::Bool = false # Use "dry" sessions (i.e. without an underlying Gnuplot process)
|
||||
cmd::String = "gnuplot" # Customizable command to start the Gnuplot process
|
||||
default::Symbol = :default # Default session name
|
||||
init::Vector{String} = Vector{String}() # Commands to initialize the gnuplot session (e.g., to set default terminal)
|
||||
verbose::Bool = false # verbosity flag (true/false)
|
||||
datalines::Int = 4; # How many lines of a dataset are printed in log
|
||||
end
|
||||
const state = State()
|
||||
state.dry = false
|
||||
const sessions = Dict{Symbol, DrySession}()
|
||||
const options = Options()
|
||||
|
||||
|
||||
|
||||
# ╭───────────────────────────────────────────────────────────────────╮
|
||||
@ -281,17 +280,17 @@ end
|
||||
# ╰───────────────────────────────────────────────────────────────────╯
|
||||
# ---------------------------------------------------------------------
|
||||
function DrySession(sid::Symbol)
|
||||
global state
|
||||
(sid in keys(state.sessions)) && error("Gnuplot session $sid is already active")
|
||||
global options
|
||||
(sid in keys(sessions)) && error("Gnuplot session $sid is already active")
|
||||
out = DrySession(sid, Vector{DataSet}(), [SinglePlot()], 1)
|
||||
state.sessions[sid] = out
|
||||
sessions[sid] = out
|
||||
return out
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
function GPSession(sid::Symbol)
|
||||
function readTask(sid, stream, channel)
|
||||
global state
|
||||
global options
|
||||
saveOutput = false
|
||||
|
||||
while isopen(stream)
|
||||
@ -313,26 +312,26 @@ function GPSession(sid::Symbol)
|
||||
if line == "GNUPLOT_CAPTURE_BEGIN"
|
||||
saveOutput = true
|
||||
else
|
||||
if (line != "") && (line != "GNUPLOT_CAPTURE_END") && (state.verbose)
|
||||
if (line != "") && (line != "GNUPLOT_CAPTURE_END") && (options.verbose)
|
||||
printstyled(color=:cyan, "GNUPLOT ($sid) -> $line\n")
|
||||
end
|
||||
(saveOutput) && (put!(channel, line))
|
||||
(line == "GNUPLOT_CAPTURE_END") && (saveOutput = false)
|
||||
end
|
||||
end
|
||||
delete!(state.sessions, sid)
|
||||
delete!(sessions, sid)
|
||||
return nothing
|
||||
end
|
||||
|
||||
global state
|
||||
global options
|
||||
|
||||
CheckGnuplotVersion(state.cmd)
|
||||
CheckGnuplotVersion(options.cmd)
|
||||
session = DrySession(sid)
|
||||
|
||||
pin = Base.Pipe()
|
||||
pout = Base.Pipe()
|
||||
perr = Base.Pipe()
|
||||
proc = run(pipeline(`$(state.cmd)`, stdin=pin, stdout=pout, stderr=perr), wait=false)
|
||||
proc = run(pipeline(`$(options.cmd)`, stdin=pin, stdout=pout, stderr=perr), wait=false)
|
||||
chan = Channel{String}(32)
|
||||
|
||||
# Close unused sides of the pipes
|
||||
@ -348,7 +347,7 @@ function GPSession(sid::Symbol)
|
||||
|
||||
out = GPSession(getfield.(Ref(session), fieldnames(concretetype(DrySession)))...,
|
||||
pin, pout, perr, proc, chan)
|
||||
state.sessions[sid] = out
|
||||
sessions[sid] = out
|
||||
|
||||
# Set window title
|
||||
term = writeread(out, "print GPVAL_TERM")[1]
|
||||
@ -358,7 +357,7 @@ function GPSession(sid::Symbol)
|
||||
writeread(out, "set term $term $opts title 'Gnuplot.jl: $(out.sid)'")
|
||||
end
|
||||
end
|
||||
for l in state.init
|
||||
for l in options.init
|
||||
writeread(out, l)
|
||||
end
|
||||
|
||||
@ -367,16 +366,16 @@ end
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
function getsession(sid::Symbol=state.default)
|
||||
global state
|
||||
if !(sid in keys(state.sessions))
|
||||
if state.dry
|
||||
function getsession(sid::Symbol=options.default)
|
||||
global options
|
||||
if !(sid in keys(sessions))
|
||||
if options.dry
|
||||
DrySession(sid)
|
||||
else
|
||||
GPSession(sid)
|
||||
end
|
||||
end
|
||||
return state.sessions[sid]
|
||||
return sessions[sid]
|
||||
end
|
||||
|
||||
|
||||
@ -398,8 +397,8 @@ end
|
||||
"""
|
||||
println(gp::DrySession, str::AbstractString) = nothing
|
||||
function println(gp::GPSession, str::AbstractString)
|
||||
global state
|
||||
if state.verbose
|
||||
global options
|
||||
if options.verbose
|
||||
printstyled(color=:light_yellow, "GNUPLOT ($(gp.sid)) $str\n")
|
||||
end
|
||||
w = write(gp.pin, strip(str) * "\n")
|
||||
@ -411,10 +410,10 @@ end
|
||||
|
||||
println(gp::DrySession, d::DataSet) = nothing
|
||||
function println(gp::GPSession, d::DataSet)
|
||||
if state.verbose
|
||||
if options.verbose
|
||||
v = ""
|
||||
printstyled(color=:light_black, "GNUPLOT ($(gp.sid)) $(d.name) << EOD\n")
|
||||
n = min(state.printlines, length(d.lines))
|
||||
n = min(options.printlines, length(d.lines))
|
||||
for i in 1:n
|
||||
printstyled(color=:light_black, "GNUPLOT ($(gp.sid)) $(d.lines[i])\n")
|
||||
end
|
||||
@ -434,18 +433,18 @@ end
|
||||
# ---------------------------------------------------------------------
|
||||
writeread(gp::DrySession, str::AbstractString) = [""]
|
||||
function writeread(gp::GPSession, str::AbstractString)
|
||||
global state
|
||||
verbose = state.verbose
|
||||
global options
|
||||
verbose = options.verbose
|
||||
|
||||
state.verbose = false
|
||||
options.verbose = false
|
||||
println(gp, "print 'GNUPLOT_CAPTURE_BEGIN'")
|
||||
|
||||
state.verbose = verbose
|
||||
options.verbose = verbose
|
||||
println(gp, str)
|
||||
|
||||
state.verbose = false
|
||||
options.verbose = false
|
||||
println(gp, "print 'GNUPLOT_CAPTURE_END'")
|
||||
state.verbose = verbose
|
||||
options.verbose = verbose
|
||||
|
||||
out = Vector{String}()
|
||||
while true
|
||||
@ -517,8 +516,8 @@ end
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
function quit(gp::DrySession)
|
||||
global state
|
||||
delete!(state.sessions, gp.sid)
|
||||
global options
|
||||
delete!(sessions, gp.sid)
|
||||
return 0
|
||||
end
|
||||
|
||||
@ -882,8 +881,8 @@ end
|
||||
# Read/evaluate/print/loop
|
||||
# """
|
||||
# function repl(sid::Symbol)
|
||||
# verb = state.verbose
|
||||
# state.verbose = 0
|
||||
# verb = options.verbose
|
||||
# options.verbose = 0
|
||||
# gp = getsession(sid)
|
||||
# while true
|
||||
# line = readline(stdin)
|
||||
@ -893,12 +892,12 @@ end
|
||||
# println(line)
|
||||
# end
|
||||
# end
|
||||
# state.verbose = verb
|
||||
# options.verbose = verb
|
||||
# return nothing
|
||||
# end
|
||||
# function repl()
|
||||
# global state
|
||||
# return repl(state.default)
|
||||
# global options
|
||||
# return repl(options.default)
|
||||
# end
|
||||
|
||||
|
||||
@ -913,11 +912,11 @@ end
|
||||
Quit the session and the associated gnuplot process (if any).
|
||||
"""
|
||||
function quit(sid::Symbol)
|
||||
global state
|
||||
if !(sid in keys(state.sessions))
|
||||
global options
|
||||
if !(sid in keys(sessions))
|
||||
error("Gnuplot session $sid do not exists")
|
||||
end
|
||||
return quit(state.sessions[sid])
|
||||
return quit(sessions[sid])
|
||||
end
|
||||
|
||||
"""
|
||||
@ -926,8 +925,8 @@ end
|
||||
Quit all the sessions and the associated gnuplot processes.
|
||||
"""
|
||||
function quitall()
|
||||
global state
|
||||
for sid in keys(state.sessions)
|
||||
global options
|
||||
for sid in keys(sessions)
|
||||
quit(sid)
|
||||
end
|
||||
return nothing
|
||||
@ -947,7 +946,7 @@ exec("plot sin(x)")
|
||||
```
|
||||
"""
|
||||
function exec(sid::Symbol, s::Vector{String})
|
||||
global state
|
||||
global options
|
||||
gp = getsession(sid)
|
||||
answer = Vector{String}()
|
||||
for v in s
|
||||
@ -956,8 +955,8 @@ function exec(sid::Symbol, s::Vector{String})
|
||||
return join(answer, "\n")
|
||||
end
|
||||
function exec(s::String)
|
||||
global state
|
||||
exec(state.default, [s])
|
||||
global options
|
||||
exec(options.default, [s])
|
||||
end
|
||||
exec(sid::Symbol, s::String) = exec(sid, [s])
|
||||
|
||||
@ -969,8 +968,8 @@ exec(sid::Symbol, s::String) = exec(sid, [s])
|
||||
Set verbose flag to `true` or `false` (default: `false`).
|
||||
"""
|
||||
function setverbose(b::Bool)
|
||||
global state
|
||||
state.verbose = b
|
||||
global options
|
||||
options.verbose = b
|
||||
end
|
||||
|
||||
|
||||
@ -1076,7 +1075,7 @@ end
|
||||
function contourlines(args...; cntrparam="level auto 10")
|
||||
tmpfile = Base.Filesystem.tempname()
|
||||
sid = Symbol("j", Base.Libc.getpid())
|
||||
if !haskey(Gnuplot.state.sessions, sid)
|
||||
if !haskey(Gnuplot.sessions, sid)
|
||||
gp = getsession(sid)
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user