Get rid of the AbbrvKW dependency
This commit is contained in:
parent
0f827598fc
commit
c441a3ce99
97
README.md
97
README.md
@ -5,9 +5,7 @@
|
||||
|
||||
**Gnuplot.jl** allows easy and fast use
|
||||
of [Gnuplot](http://gnuplot.info/) as data visualization tool in
|
||||
Julia. It is mainly focused on
|
||||
|
||||
GnuplotFeatures:
|
||||
Julia. Its main features are:
|
||||
|
||||
- transparent interface between Julia and gnuplot to exploit all
|
||||
functionalities of the latter, both present and future ones;
|
||||
@ -15,15 +13,22 @@ GnuplotFeatures:
|
||||
- fast data transmission to gnuplot through system pipes (no temporary
|
||||
files involved);
|
||||
|
||||
- support for running multiple gnuplot istances simulatneously;
|
||||
- support for running multiple gnuplot process simulatneously;
|
||||
|
||||
- support for multiplots;
|
||||
|
||||
- extremely concise syntax (see Examples below) makes it ideal for
|
||||
interactive use and data exploration;
|
||||
- extremely concise syntax (see examples below), makes it ideal for
|
||||
interactive data exploration;
|
||||
|
||||
- very easy to use: if you know gnuplot you're ready to go.
|
||||
|
||||
|
||||
The purpose is similar to
|
||||
the [Gaston](https://github.com/mbaz/Gaston.jl) package, but
|
||||
**Gnuplot.jl** main focus is on on the syntax conciseness and ease of
|
||||
use.
|
||||
|
||||
|
||||
## Installation
|
||||
In the Julia REPL type:
|
||||
|
||||
@ -35,26 +40,68 @@ You'll also need gnuplot (ver. >= 4.7) installed on your system.
|
||||
|
||||
|
||||
## Quick start:
|
||||
Here we will show basic usage:
|
||||
Here we will show a very basic usage:
|
||||
|
||||
``` Julia
|
||||
using Gnuplot
|
||||
|
||||
# Create some noisy data
|
||||
# Create some noisy data...
|
||||
x = collect(linspace(-2pi, 2pi, 100))
|
||||
y = 1.5 * sin.(0.3 + 0.7x)
|
||||
noise = randn(length(x))./2
|
||||
e = 0.5 * ones(x)
|
||||
@gp("set key horizontal",
|
||||
x, y, "w l dt 1 lw 2 t 'Real model'",
|
||||
|
||||
# ...and show them using gnuplot.
|
||||
@gp("set key horizontal", "set grid",
|
||||
xrange=(-7,7), ylab="Y label",
|
||||
x, y, "w l t 'Real model' dt 2 lw 2 lc rgb 'red'",
|
||||
x, y+noise, e, "w errorbars t 'Data'")
|
||||
```
|
||||
That's it for the first plot. The syntax should be familitar to most
|
||||
gnuplot users.
|
||||
That's it for the first plot, the syntax should be familiar to most
|
||||
gnuplot users. With this code we:
|
||||
- set a few gnuplot properties (`key` and `grid`);
|
||||
- set the X axis range and Y axis label;
|
||||
- passed the data to gnuplot;
|
||||
- plot two data sets specifying a few details (style, line
|
||||
width, color, legend, etc...).
|
||||
|
||||
Note that this simple example already covers the vast majority of use
|
||||
cases, since the remaining details of the plot can be easily tweaked
|
||||
by adding the appropriate gnuplot command. Also note that you would
|
||||
barely recognize the Julia language by just looking at the `@gp` macro
|
||||
since **Gnuplot.jl** aims to be the mostly transparent: the user is
|
||||
supposed to focus only on the data and on the gnuplot commands, rather
|
||||
than the **Gnuplot.jl** package details.
|
||||
|
||||
Now some more advanced usage (fit the data and overplot the results):
|
||||
Before proceeding we will brief discuss the four symbols exported
|
||||
by the package:
|
||||
- `@gp`: the *swiss army knife* of the package, it allows to send
|
||||
command and data to gnuplot, and produce very complex plots;
|
||||
- `@gpi`: very similar to `@gp`, but it allows to build a plot in
|
||||
several calls, rather than a single `@gp` call;
|
||||
- `@gp_str`: run simple gnuplot commands
|
||||
using
|
||||
[non-standard string literal](https://docs.julialang.org/en/stable/manual/strings/#non-standard-string-literals-1),
|
||||
e.g.
|
||||
``` Julia
|
||||
gp"print GPVAL_TERM"
|
||||
```
|
||||
- `@gp_cmd`: load a gnuplot script file using a non-standard string literal, e.g.
|
||||
``` Julia
|
||||
gp`test.gp`
|
||||
```
|
||||
|
||||
The last two macros are supposed to be used only in the REPL, not in
|
||||
Julia function. As you can see there is not much more to know before
|
||||
starting *gnuplotting*!
|
||||
|
||||
Clearly, the **Gnuplot.jl** hides much more under the hood. The
|
||||
documentation for each of this function can be retrieved with the
|
||||
`@doc` macro or by typing `?` in the REPL followed by the function
|
||||
name.
|
||||
|
||||
Now let's discuss some more advanced usage: fit the data (with
|
||||
gnuplot) and overplot the results.
|
||||
``` Julia
|
||||
const gp = Gnuplot # use an alias for the package name to quickly
|
||||
# access non exported symbols.
|
||||
@ -72,8 +119,7 @@ gp.plot("f(x) w l lw 2 t 'Fit'")
|
||||
(a, b, c) = parse.(Float64, gp.getVal("a", "b", "c"))
|
||||
|
||||
# Add param. values in the title and the Y label
|
||||
gp.cmd(title="Fit param: " * @sprintf("a=%5.2f, b=%5.2f, c=%5.2f", a, b ,c),
|
||||
ylab="Y label")
|
||||
gp.cmd(title="Fit param: " * @sprintf("a=%5.2f, b=%5.2f, c=%5.2f", a, b ,c))
|
||||
|
||||
# Refresh the plot
|
||||
gp.dump()
|
||||
@ -92,7 +138,7 @@ gp.dump()
|
||||
m = a * sin.(b + c * x)
|
||||
|
||||
# Start a new gnuplot process and plot again using the @gp macro.
|
||||
@gp("set key horizontal",
|
||||
@gp("set key horizontal", "set grid",
|
||||
:multi, "layout 2,1",
|
||||
title="Fit param: " * @sprintf("a=%5.2f, b=%5.2f, c=%5.2f", a, b ,c),
|
||||
ylab="Y label",
|
||||
@ -114,22 +160,3 @@ any other program.
|
||||
|
||||
|
||||
|
||||
|
||||
similar to gaston
|
||||
Work in progress...
|
||||
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
Multiplot:
|
||||
|
||||
Multiple instaces:
|
||||
|
||||
Documentation:
|
||||
? at the repl or use the `@doc` macro
|
||||
|
||||
AbbrvKW (si puo scaricare la versione master?)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,10 +1,8 @@
|
||||
module Gnuplot
|
||||
|
||||
using AbbrvKW
|
||||
|
||||
include("GnuplotInternals.jl")
|
||||
importall .p_
|
||||
|
||||
import .p_.@AbbrvKW
|
||||
|
||||
######################################################################
|
||||
# Get/set options
|
||||
|
||||
@ -6,6 +6,156 @@ module p_
|
||||
importall Gnuplot
|
||||
const P_ = Gnuplot
|
||||
|
||||
|
||||
import StatsBase.countmap
|
||||
|
||||
|
||||
function findAbbrv(symLong::Vector{Symbol})
|
||||
if length(symLong) == 0
|
||||
return symLong
|
||||
end
|
||||
|
||||
out = Dict()
|
||||
for sym in symLong
|
||||
out[sym] = Vector{Symbol}()
|
||||
end
|
||||
|
||||
symAbbr = deepcopy(symLong)
|
||||
symStr = convert.(String, symLong)
|
||||
kwCount = length(symLong)
|
||||
|
||||
# Max length of string representation of keywords
|
||||
maxLen = maximum(length.(symStr))
|
||||
|
||||
# Identify all abbreviations
|
||||
for len in 1:maxLen
|
||||
for i in 1:kwCount
|
||||
s = symStr[i]
|
||||
if length(s) >= len
|
||||
s = s[1:len]
|
||||
push!(symLong, symLong[i])
|
||||
push!(symAbbr, convert(Symbol, s))
|
||||
push!(symStr , s)
|
||||
end
|
||||
end
|
||||
end
|
||||
symStr = nothing # no longer needed
|
||||
|
||||
# Identify unique abbreviations
|
||||
abbrCount = 0
|
||||
for (sym, count) in countmap(symAbbr)
|
||||
if count == 1
|
||||
i = find(symAbbr .== sym)
|
||||
@assert length(i) == 1
|
||||
i = i[1]
|
||||
if symLong[i] != symAbbr[i]
|
||||
push!(out[symLong[i]], symAbbr[i])
|
||||
abbrCount += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for (key, val) in out
|
||||
sort!(out[key])
|
||||
end
|
||||
|
||||
return (out, abbrCount)
|
||||
end
|
||||
|
||||
|
||||
macro AbbrvKW(func)
|
||||
@assert func.head == :function "Not a function"
|
||||
|
||||
if length(func.args[1].args) <= 1
|
||||
# Empty parameter list"
|
||||
return esc(func)
|
||||
end
|
||||
|
||||
if (typeof(func.args[1].args[2]) != Expr) ||
|
||||
(func.args[1].args[2].head != :parameters)
|
||||
# No keywords given
|
||||
return esc(func)
|
||||
end
|
||||
|
||||
sym = Vector{Symbol}() # Symbol, long version
|
||||
typ = Dict() # Data type
|
||||
splat = Symbol()
|
||||
splatFound = false
|
||||
for k in func.args[1].args[2].args
|
||||
@assert typeof(k) == Expr "Expr expected"
|
||||
@assert k.head in (:kw, :(...)) "Expected :kw or :..., got $(k.head)"
|
||||
|
||||
#dump(k)
|
||||
if k.head == :kw
|
||||
@assert typeof(k.args[1]) in (Expr, Symbol) "Expected Expr or Symbol"
|
||||
|
||||
if typeof(k.args[1]) == Symbol
|
||||
push!(sym, k.args[1])
|
||||
typ[sym[end]] = :Any
|
||||
elseif typeof(k.args[1]) == Expr
|
||||
@assert k.args[1].head == :(::) "Expected :(::), got $(k.args[1].head)"
|
||||
push!(sym, k.args[1].args[1])
|
||||
typ[sym[end]] = k.args[1].args[2]
|
||||
end
|
||||
elseif k.head == :(...)
|
||||
splat = k.args[1]
|
||||
splatFound = true
|
||||
end
|
||||
end
|
||||
|
||||
# Find abbreviations
|
||||
(abbr, count) = findAbbrv(sym)
|
||||
if count == 0
|
||||
# No abbreviations found
|
||||
return esc(func)
|
||||
end
|
||||
|
||||
# Add a splat variable if not present
|
||||
if !splatFound
|
||||
splat = :_abbrvkw_
|
||||
a = :($splat...)
|
||||
a = a.args[1]
|
||||
push!(func.args[1].args[2].args, a)
|
||||
a = nothing
|
||||
end
|
||||
|
||||
# Build output Expr
|
||||
expr = Expr(:block)
|
||||
push!(expr.args, :(_ii_ = 1))
|
||||
push!(expr.args, Expr(:while, :(_ii_ <= length($splat)), Expr(:block)))
|
||||
|
||||
for (sym, tup) in abbr
|
||||
length(tup) > 0 || continue
|
||||
tup = tuple(tup...)
|
||||
push!(expr.args[end].args[end].args,
|
||||
:(
|
||||
if $(splat)[_ii_][1] in $tup
|
||||
typeassert($(splat)[_ii_][2], $(typ[sym]))
|
||||
$(sym) = $(splat)[_ii_][2]
|
||||
deleteat!($splat, _ii_)
|
||||
continue
|
||||
end
|
||||
))
|
||||
end
|
||||
push!(expr.args[end].args[end].args, :(_ii_ += 1))
|
||||
push!(expr.args, :(_ii_ = nothing))
|
||||
|
||||
if !splatFound
|
||||
push!(expr.args, :(if length($splat) !=0 ;
|
||||
error("Unrecognized keyword abbreviation(s): " * string($splat))
|
||||
end))
|
||||
push!(expr.args, :($splat = nothing))
|
||||
end
|
||||
|
||||
@assert length(func.args) == 2 "Function Expr has " * string(length(func.args)) * " args"
|
||||
@assert func.args[2].head == :block "Function block is not a block, but " * string(func.args[2].head)
|
||||
|
||||
prepend!(func.args[2].args, [expr])
|
||||
#@show func
|
||||
return esc(func)
|
||||
end
|
||||
|
||||
|
||||
######################################################################
|
||||
# Structure definitions
|
||||
######################################################################
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user