Compare commits
43 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea8b71898b | ||
|
|
4bdee5f6af | ||
|
|
bbbd899c19 | ||
|
|
abcb73b70f | ||
|
|
9001d5f385 | ||
|
|
919068e797 | ||
|
|
23c3d663e8 | ||
|
|
3f40e38d72 | ||
|
|
443ef0edf7 | ||
|
|
ab927d0622 | ||
|
|
622597c589 | ||
|
|
ce00617796 | ||
|
|
e70c30dd13 | ||
|
|
799154f53c | ||
|
|
d02c211e99 | ||
|
|
67c8781f2b | ||
|
|
db8dcfc433 | ||
|
|
04484adc22 | ||
|
|
658e5f422c | ||
|
|
9327492aa1 | ||
|
|
0567acc60e | ||
|
|
74e195f290 | ||
|
|
875773fd3d | ||
|
|
53159f89e1 | ||
|
|
54db30cc32 | ||
|
|
364e5281bd | ||
|
|
e8a6b21df6 | ||
|
|
6c6b889df6 | ||
|
|
5c46e35fea | ||
|
|
34af493921 | ||
|
|
f2ef5373b0 | ||
|
|
bc74aa0db4 | ||
|
|
b7a15290d3 | ||
|
|
f62b569560 | ||
|
|
584144e2ec | ||
|
|
03953c0ad6 | ||
|
|
084dd63059 | ||
|
|
50141d1b0e | ||
|
|
83c59ae682 | ||
|
|
1877deef7f | ||
|
|
67a5583c29 | ||
|
|
69644f99ba | ||
|
|
2713f8517e |
10
.travis.yml
10
.travis.yml
@ -6,15 +6,15 @@ os:
|
||||
# - osx
|
||||
|
||||
julia:
|
||||
- 1.2
|
||||
- nightly
|
||||
- 1.5
|
||||
# - nightly
|
||||
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- julia: nightly
|
||||
#matrix:
|
||||
# allow_failures:
|
||||
# - julia: nightly
|
||||
|
||||
addons:
|
||||
apt:
|
||||
|
||||
34
ChangeLog.md
34
ChangeLog.md
@ -1,6 +1,38 @@
|
||||
# Version 1.3.0 (released on: Apr. 28, 2020)
|
||||
# Version 1.4.1 (released on: )
|
||||
- New features:
|
||||
* Implicit recipes can now returns a `Vector{PlotElement}`;
|
||||
|
||||
* Allow using single quotes in output file names (#52);
|
||||
|
||||
* New function: `palette_levels()` can be used to modify palette levels before passing them to gnuplot;
|
||||
|
||||
- Bugfix:
|
||||
* Fixed `BoundsErrors` in `hist()` (#49);
|
||||
|
||||
* Fixed problem when generating documentation (#51);
|
||||
|
||||
|
||||
# Version 1.4.0 (released on: May 5, 2021)
|
||||
- New features:
|
||||
* Missing values are accepted if the input arrays have `eltype <:
|
||||
AbstractFloat`;
|
||||
|
||||
* Missing values are also accepted in calls to `hist`;
|
||||
|
||||
* VSCode and Pluto sessions are now properly handled (#35 and #43);
|
||||
|
||||
- Bugfix:
|
||||
* Multiplot were not displayed in Jupyter (#25);
|
||||
|
||||
* `gpvars()` fails if gnuplot character encoding is utf8
|
||||
(#24);
|
||||
|
||||
|
||||
# Version 1.3.0 (released on: Apr. 29, 2020)
|
||||
|
||||
- New features:
|
||||
* The new `dgrid3d()` allows to interpolate scattered 2D data on a
|
||||
2D regular grid;
|
||||
|
||||
* The `Options` structure features a new `mime` field containing a
|
||||
dictionary to map a MIME type to gnuplot terminals;
|
||||
|
||||
10
Project.toml
10
Project.toml
@ -1,6 +1,6 @@
|
||||
name = "Gnuplot"
|
||||
uuid = "dc211083-a33a-5b79-959f-2ff34033469d"
|
||||
version = "1.3.0"
|
||||
version = "1.4.1"
|
||||
|
||||
[deps]
|
||||
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
|
||||
@ -14,11 +14,11 @@ StructC14N = "d2514e9c-36c4-5b8e-97e2-51e7675c221c"
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
||||
[compat]
|
||||
ColorSchemes = "^3.5"
|
||||
ColorTypes = "^0.10"
|
||||
ColorSchemes = "^3.12"
|
||||
ColorTypes = "^0.11"
|
||||
Colors = "^0.12"
|
||||
DataStructures = "^0.17"
|
||||
DataStructures = "^0.18"
|
||||
ReplMaker = "^0.2"
|
||||
StatsBase = "^0.33"
|
||||
StructC14N = "^0.3"
|
||||
julia = "^1.2"
|
||||
julia = "^1.6"
|
||||
|
||||
10
README.md
10
README.md
@ -3,10 +3,10 @@
|
||||
|
||||
[](https://travis-ci.org/gcalderone/Gnuplot.jl)
|
||||
[](LICENSE.md)
|
||||
[](https://gcalderone.github.io/Gnuplot.jl/v1.3.0/)
|
||||
[](https://gcalderone.github.io/Gnuplot.jl/v1.4.0/index.html)
|
||||
|
||||
|
||||
**Gnuplot.jl** is a simple package able to send both data and commands from Julia to an underlying [gnuplot](http://gnuplot.sourceforge.net/) process. Its main purpose it to provide a fast and powerful data visualization framework, using an extremely concise Julia syntax.
|
||||
**Gnuplot.jl** is a simple package able to send both data and commands from Julia to an underlying [gnuplot](http://gnuplot.sourceforge.net/) process. Its main purpose it to provide a fast and powerful data visualization framework, using an extremely concise Julia syntax. It also has automatic display of plots in Jupyter, Juno and VS Code.
|
||||
|
||||
|
||||
## Installation
|
||||
@ -21,9 +21,9 @@ You may check the installed **Gnuplot.jl** version with:
|
||||
```julia
|
||||
]st Gnuplot
|
||||
```
|
||||
If the displayed version is not v1.3.0 you are probably having a dependency conflict. In this case try forcing installation of the latest version with:
|
||||
If the displayed version is not v1.4.0 you are probably having a dependency conflict. In this case try forcing installation of the latest version with:
|
||||
```julia
|
||||
]add Gnuplot@1.3.0
|
||||
]add Gnuplot@1.4.0
|
||||
```
|
||||
and check which package is causing the conflict.
|
||||
|
||||
@ -37,7 +37,7 @@ test_terminal()
|
||||
|
||||
|
||||
## Quick start
|
||||
The following examples are supposed to be self-explaining. See [documentation](https://gcalderone.github.io/Gnuplot.jl/v1.3.0/) for further informations.
|
||||
The following examples are supposed to be self-explaining. See [documentation](https://gcalderone.github.io/Gnuplot.jl/v1.4.0/) for further informations.
|
||||
|
||||
### A simple parabola
|
||||
```julia
|
||||
|
||||
@ -21,6 +21,7 @@ gpvars
|
||||
hist
|
||||
linetypes
|
||||
palette
|
||||
palette_levels
|
||||
palette_names
|
||||
recipe
|
||||
save
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 38 KiB |
@ -210,6 +210,16 @@ saveas("basic008a") # hide
|
||||
```
|
||||

|
||||
|
||||
The palette levels may be easily stretched by using the [`palette_levels()`](@ref) and modifying the numeric levels, e.g.:
|
||||
```@example abc
|
||||
x = 0:0.1:10pi
|
||||
v, l, n = palette_levels(:viridis)
|
||||
@gsp palette(v.^0.25, l, n) cbr=[-1,1].*30 :-
|
||||
@gsp :- x x.*sin.(x) x.*cos.(x) x./20 "w p pt 7 ps var lc pal"
|
||||
saveas("basic008b") # hide
|
||||
```
|
||||

|
||||
|
||||
The list of all available palette can be retrieved with [`palette_names()`](@ref):
|
||||
```@repl abc
|
||||
palette_names()
|
||||
|
||||
@ -19,11 +19,11 @@ Check **Gnuplot.jl** version with:
|
||||
```julia-repl
|
||||
julia> ]st Gnuplot
|
||||
Status `~/.julia/environments/v1.4/Project.toml`
|
||||
[dc211083] Gnuplot v1.3.0
|
||||
[dc211083] Gnuplot v1.4.1
|
||||
```
|
||||
If the displayed version is not `v1.3.0` you are probably having a dependency conflict. In this case try forcing installation of the latest version with:
|
||||
If the displayed version is not `v1.4.1` you are probably having a dependency conflict. In this case try forcing installation of the latest version with:
|
||||
```julia-repl
|
||||
julia> ]add Gnuplot@1.3.0
|
||||
julia> ]add Gnuplot@1.4.1
|
||||
```
|
||||
and check which package is causing the conflict.
|
||||
|
||||
|
||||
@ -70,12 +70,11 @@ Each line reports the package name (`GNUPLOT`), the session name (`default`), th
|
||||
|
||||
## Package initialization
|
||||
|
||||
If you use **Gnuplot.jl** frequently you may find convenient to collect all the package settings ([Options](@ref)) in a single place, to quickly recall them in a Julia session. A possibility is to put the following code in the `~/.julia/config/startup.jl` initialization file (further info [here](https://docs.julialang.org/en/v1/stdlib/REPL/)):
|
||||
If you use **Gnuplot.jl** frequently you may find convenient to automatically apply the package settings ([Options](@ref)) whenever the package is loaded. A possibility is to use [Requires.jl](https://github.com/JuliaPackaging/Requires.jl) and put the following code in the `~/.julia/config/startup.jl` initialization file (further info [here](https://docs.julialang.org/en/v1/stdlib/REPL/)):
|
||||
```julia
|
||||
macro gnuplotrc()
|
||||
return :(
|
||||
using Gnuplot;
|
||||
|
||||
using Requires
|
||||
@require Gnuplot="dc211083-a33a-5b79-959f-2ff34033469d" begin
|
||||
@info "Custom Gnuplot initialization"
|
||||
# Uncomment the following if you don't have the gnuplot
|
||||
# executable installed on your platform:
|
||||
#Gnuplot.options.dry = true;
|
||||
@ -103,17 +102,13 @@ macro gnuplotrc()
|
||||
|
||||
# Set the default linetypes
|
||||
empty!(Gnuplot.options.init);
|
||||
push!(Gnuplot.options.init, linetypes(:Set1_5, lw=1.5, ps=1.5));
|
||||
push!(Gnuplot.options.init, Gnuplot.linetypes(:Set1_5, lw=1.5, ps=1.5));
|
||||
|
||||
# Initialize the gnuplot REPL using the provided `start_key`.
|
||||
if Gnuplot.options.gpviewer;
|
||||
Gnuplot.repl_init(start_key='>');
|
||||
end;
|
||||
)
|
||||
end
|
||||
```
|
||||
At the Julia prompt you may load the package and the associated settings by typing:
|
||||
```julia
|
||||
julia> @gnuplotrc
|
||||
```
|
||||
and you're ready to go.
|
||||
|
||||
The above code will be automatically when you first load the package with `using Gnuplot`.
|
||||
|
||||
@ -125,7 +125,7 @@ end
|
||||
with only one mandatory argument. In order to exploit the optional keyword we can explicitly invoke the recipe as follows:
|
||||
```@example abc
|
||||
img = testimage("walkbridge");
|
||||
@gp palette(:gray) recipe(img, "flipy rot=15deg")
|
||||
@gp palette(:gray1) recipe(img, "flipy rot=15deg")
|
||||
saveas("recipes007c") # hide
|
||||
```
|
||||

|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Style Guide
|
||||
|
||||
The **Gnuplot.jl** loose syntax allows to create a plot using very different approaches. While this was one of the initial purposes for the package, it may lead to decreased code readability if not used judiciously.
|
||||
The **Gnuplot.jl** loose syntax allows to create a plot using very different approaches. While this was one of the initial purposes for the package, it may lead to a reduced code readability if not used judiciously.
|
||||
|
||||
Here I will summarize a few, non-mandatory, guidelines which allows to maintain a neat syntax and a high readability:
|
||||
|
||||
|
||||
@ -4,11 +4,7 @@ Gnuplot provides dozens of terminals to display plots or export them into files
|
||||
|
||||
To use a specific terminal for interactive use you may either set it as initialization command for all new session with (see [Options](@ref)):
|
||||
```julia
|
||||
Gnuplot.options.term = "wxt")
|
||||
```
|
||||
or directly send the command to a specific session (see [Direct command execution](@ref))
|
||||
```julia
|
||||
gpexec("set term wxt")
|
||||
Gnuplot.options.term = "wxt"
|
||||
```
|
||||
See official [gnuplot documentation](http://gnuplot.sourceforge.net/documentation.html) for further info on terminals and their options.
|
||||
|
||||
@ -16,13 +12,13 @@ See official [gnuplot documentation](http://gnuplot.sourceforge.net/documentatio
|
||||
## Interactive terminals (`wxt` and `qt`)
|
||||
The multiplatform `wxt` and `qt` terminals are among the most widely used ones for their nicely looking outputs on display and for their interactive capabilities.
|
||||
|
||||
You may set them as terminal with:
|
||||
You may use such terminals with:
|
||||
```
|
||||
"set term wxt size 800,600"
|
||||
Gnuplot.options.term = "wxt size 800,600"
|
||||
```
|
||||
or
|
||||
```
|
||||
"set term qt size 800,600"
|
||||
Gnuplot.options.term = "qt size 800,600"
|
||||
```
|
||||
(the `size 800,600` is optional and can be omitted).
|
||||
|
||||
@ -30,9 +26,35 @@ Press the `h` key on the window to display an help message with all available ke
|
||||
|
||||
|
||||
## Plot in a terminal application (`dumb`, `sixel` and `sixelgd`)
|
||||
Gnuplot supports plotting in a terminal application, with no need for X11 or other GUI support, via the `dumb`, `sixel` and `sixelgd` terminals. These are extremely useful when you run Julia on a remote shell through `ssh`, with no X11 forwarding.
|
||||
Gnuplot supports plotting in a terminal application, with no need for X11 or other GUI support, via the `dumb`, `sixel` and `sixelgd` terminals. These are extremely useful when you run Julia on a remote shell through `ssh`, with no X11 forwarding. The `dumb` terminal uses ASCII characters to draw a plot, while `sixel` and `sixelgd` actually use bitmaps (but require Sixel support to be enabled in the terminal, e.g. `xterm -ti vt340`).
|
||||
|
||||
The `dumb` terminal uses ASCII characters to draw a plot, while `sixel` and `sixelgd` actually use bitmaps (but require Sixel support to be enabled in the terminal, e.g. `xterm -ti vt340`). A sixel plot on `xterm` looks as follows:
|
||||
Dumb terminal can be used as follows:
|
||||
|
||||
```jldoctest; setup = :(using Gnuplot)
|
||||
julia> origterm = Gnuplot.options.term;
|
||||
|
||||
julia> Gnuplot.options.term = "dumb size 60,15";
|
||||
|
||||
julia> @gp "plot sin(x)"
|
||||
|
||||
1 +-------------------------------------------------+
|
||||
0.8 |-+ *+ * + ** ** + * * +-|
|
||||
0.6 |-+ * ** * * sin(x) *******-|
|
||||
0.4 |*+ * * * * * *+-|
|
||||
0.2 |*+ * * * * * *-|
|
||||
0 |*+ * * * * * *-|
|
||||
| * * * * * * *|
|
||||
-0.2 |-* * * * * * +*|
|
||||
-0.4 |-+* * * * * * +*|
|
||||
-0.6 |-+* * * * ** * +-|
|
||||
-0.8 |-+ * * + ** ** + * * +-|
|
||||
-1 +-------------------------------------------------+
|
||||
-10 -5 0 5 10
|
||||
|
||||
julia> Gnuplot.options.term = origterm;
|
||||
|
||||
```
|
||||
A sixel plot on `xterm` looks as follows:
|
||||

|
||||
|
||||
The above terminals are available if gnuplot has been compiled with the `--with-bitmap-terminals` option enabled and Libgd (only for `sixelgd`).
|
||||
@ -58,7 +80,7 @@ Gnuplot is also able to export vector (i.e. non-raster) plots through the `svg`
|
||||
The `cairolatex` terminal allows to produce high quality plots by splitting the output into a PDF file (containing a rasterized image of a plot) and a `.tex` file (containing all the text as ``\LaTeX`` code). The following example shows how to write plot tics and an equation in ``\LaTeX``:
|
||||
```julia
|
||||
x = LinRange(-2pi, 2pi, 1000)
|
||||
@gp t="Polynomial approximation of sin(x)" "set style fill transparent solid 0.6 noborder"
|
||||
@gp tit="Polynomial approximation of sin(x)" "set style fill transparent solid 0.6 noborder"
|
||||
@gp :- raw"""set xtics ('$-\pi$' -pi, '$-\pi/2$' -pi/2, 0, '$\pi/2$' pi/2, '$\pi$' pi)"""
|
||||
@gp :- xr=3.8.*[-1, 1] yr=[-1.5,1.5] key="box opaque left horiz" linetypes(:Blues_3) "set grid front"
|
||||
latex = raw"""\begin{minipage}[c]{\textwidth}\begin{equation*}""" *
|
||||
|
||||
192
src/Gnuplot.jl
192
src/Gnuplot.jl
@ -7,7 +7,7 @@ import Base.reset
|
||||
import Base.write
|
||||
import Base.show
|
||||
|
||||
export session_names, dataset_names, palette_names, linetypes, palette,
|
||||
export session_names, dataset_names, palette_names, linetypes, palette_levels, palette,
|
||||
terminal, terminals, test_terminal,
|
||||
stats, @gp, @gsp, save, gpexec,
|
||||
boxxy, contourlines, dgrid3d, hist, recipe, gpvars, gpmargins, gpranges
|
||||
@ -236,12 +236,18 @@ const sessions = OrderedDict{Symbol, Session}()
|
||||
const options = Options()
|
||||
|
||||
function __init__()
|
||||
# Check whether we are running in a IJulia or Juno session.
|
||||
# Check whether we are running in an IJulia, Juno, VSCode or Pluto session.
|
||||
# (copied from Gaston.jl).
|
||||
options.gpviewer = !(
|
||||
((isdefined(Main, :IJulia) && Main.IJulia.inited) ||
|
||||
(isdefined(Main, :Juno) && Main.Juno.isactive()))
|
||||
(isdefined(Main, :Juno) && Main.Juno.isactive()) ||
|
||||
(isdefined(Main, :VSCodeServer)) ||
|
||||
(isdefined(Main, :PlutoRunner)) )
|
||||
)
|
||||
if isdefined(Main, :VSCodeServer)
|
||||
# VS Code shows "dynamic" plots with fixed and small size :-(
|
||||
options.mime[MIME"image/svg+xml"] = replace(options.mime[MIME"image/svg+xml"], "dynamic" => "")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -277,11 +283,11 @@ function parseKeywords(; kwargs...)
|
||||
ismissing(kw.zrange ) || (push!(out, replace("set zrange [" * join(kw.zrange , ":") * "]", "NaN"=>"*")))
|
||||
ismissing(kw.cbrange) || (push!(out, replace("set cbrange [" * join(kw.cbrange, ":") * "]", "NaN"=>"*")))
|
||||
ismissing(kw.key ) || (push!(out, "set key " * kw.key * ""))
|
||||
ismissing(kw.title ) || (push!(out, "set title \"" * kw.title * "\""))
|
||||
ismissing(kw.xlabel ) || (push!(out, "set xlabel \"" * kw.xlabel * "\""))
|
||||
ismissing(kw.ylabel ) || (push!(out, "set ylabel \"" * kw.ylabel * "\""))
|
||||
ismissing(kw.zlabel ) || (push!(out, "set zlabel \"" * kw.zlabel * "\""))
|
||||
ismissing(kw.cblabel) || (push!(out, "set cblabel \"" * kw.cblabel * "\""))
|
||||
ismissing(kw.title ) || (push!(out, "set title '" * kw.title * "'"))
|
||||
ismissing(kw.xlabel ) || (push!(out, "set xlabel '" * kw.xlabel * "'"))
|
||||
ismissing(kw.ylabel ) || (push!(out, "set ylabel '" * kw.ylabel * "'"))
|
||||
ismissing(kw.zlabel ) || (push!(out, "set zlabel '" * kw.zlabel * "'"))
|
||||
ismissing(kw.cblabel) || (push!(out, "set cblabel '" * kw.cblabel * "'"))
|
||||
ismissing(kw.xlog ) || (push!(out, (kw.xlog ? "" : "un") * "set logscale x"))
|
||||
ismissing(kw.ylog ) || (push!(out, (kw.ylog ? "" : "un") * "set logscale y"))
|
||||
ismissing(kw.zlog ) || (push!(out, (kw.zlog ? "" : "un") * "set logscale z"))
|
||||
@ -298,7 +304,6 @@ function parseKeywords(; kwargs...)
|
||||
ismissing(kw.rmargin) || push!(out, (kw.rmargin == "" ? "unset rmargin" : "set rmargin at screen $(kw.rmargin)"))
|
||||
ismissing(kw.bmargin) || push!(out, (kw.bmargin == "" ? "unset bmargin" : "set bmargin at screen $(kw.bmargin)"))
|
||||
ismissing(kw.tmargin) || push!(out, (kw.tmargin == "" ? "unset tmargin" : "set tmargin at screen $(kw.tmargin)"))
|
||||
|
||||
return join(out, ";\n")
|
||||
end
|
||||
|
||||
@ -514,7 +519,6 @@ function readTask(gp::GPSession)
|
||||
delete!(sessions, gp.sid)
|
||||
end
|
||||
|
||||
|
||||
function GPSession(sid::Symbol)
|
||||
session = DrySession(sid)
|
||||
if !options.dry
|
||||
@ -529,13 +533,16 @@ function GPSession(sid::Symbol)
|
||||
end
|
||||
|
||||
pin = Base.Pipe()
|
||||
pout = Base.Pipe()
|
||||
perr = Base.Pipe()
|
||||
proc = run(pipeline(`$(options.cmd)`, stdin=pin, stdout=stdout, 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
|
||||
Base.close(pout.in)
|
||||
Base.close(perr.in)
|
||||
Base.close(pin.out)
|
||||
Base.start_reading(pout.out)
|
||||
Base.start_reading(perr.out)
|
||||
|
||||
out = GPSession(getfield.(Ref(session), fieldnames(DrySession))...,
|
||||
@ -544,11 +551,19 @@ function GPSession(sid::Symbol)
|
||||
|
||||
# Start reading tasks
|
||||
@async readTask(out)
|
||||
@async while !eof(pout) # see PR #51
|
||||
write(stdout, readavailable(pout))
|
||||
end
|
||||
|
||||
# Read gnuplot default terminal
|
||||
if options.term == ""
|
||||
options.term = terminal()
|
||||
end
|
||||
|
||||
# The stderr of the gnuplot process goes to Julia which can parse
|
||||
# UTF8 characters (regardless of the terminal).
|
||||
gpexec("set encoding utf8")
|
||||
|
||||
return out
|
||||
end
|
||||
|
||||
@ -698,7 +713,7 @@ end
|
||||
function DatasetBin(cols::Vararg{AbstractVector, N}) where N
|
||||
source = "binary record=$(length(cols[1])) format='"
|
||||
types = Vector{DataType}()
|
||||
(length(cols) == 1) && (source *= "%int")
|
||||
#(length(cols) == 1) && (source *= "%int")
|
||||
for i in 1:length(cols)
|
||||
@assert length(cols[1]) == length(cols[i])
|
||||
if isa(cols[i][1], Int32); push!(types, Int32); source *= "%int"
|
||||
@ -715,7 +730,7 @@ function DatasetBin(cols::Vararg{AbstractVector, N}) where N
|
||||
(path, io) = mktemp()
|
||||
source = " '$path' $source"
|
||||
for row in 1:length(cols[1])
|
||||
(length(cols) == 1) && (write(io, convert(Int32, row)))
|
||||
#(length(cols) == 1) && (write(io, convert(Int32, row)))
|
||||
for col in 1:length(cols)
|
||||
write(io, convert(types[col], cols[col][row]))
|
||||
end
|
||||
@ -803,7 +818,7 @@ function useBinaryMethod(args...)
|
||||
elseif options.preferred_format == :auto
|
||||
if (length(args) == 1) && isa(args[1], AbstractMatrix)
|
||||
binary = true
|
||||
elseif all(ndims.(args) .== 1)
|
||||
elseif all(ndims.(args) .== 1) && all(Base.:<:.(eltype.(args), Real))
|
||||
s = sum(length.(args))
|
||||
if s > 1e4
|
||||
binary = true
|
||||
@ -911,9 +926,10 @@ function execall(gp::GPSession; term::AbstractString="", output::AbstractString=
|
||||
if term != ""
|
||||
former_term = writeread(gp, "print GPVAL_TERM")[1]
|
||||
former_opts = writeread(gp, "print GPVAL_TERMOPTIONS")[1]
|
||||
gpexec(gp, "unset multiplot")
|
||||
gpexec(gp, "set term $term")
|
||||
end
|
||||
(output != "") && gpexec(gp, "set output '$output'")
|
||||
(output != "") && gpexec(gp, "set output '$(replace(output, "'" => "''"))'")
|
||||
|
||||
# printstyled("Plotting with terminal: " * terminal() * "\n", color=:blue, bold=true)
|
||||
|
||||
@ -1105,15 +1121,24 @@ function parseArguments(_args...)
|
||||
end
|
||||
insert!(args, pos, string(strip(arg[1])) => nothing)
|
||||
elseif isa(arg, AbstractArray) && # ==> a dataset column
|
||||
((valtype(arg) <: Real) ||
|
||||
(valtype(arg) <: AbstractString)) ;
|
||||
((nonmissingtype(eltype(arg)) <: Real) ||
|
||||
(nonmissingtype(eltype(arg)) <: AbstractString)) ;
|
||||
elseif isa(arg, Real) # ==> a dataset column with only one row
|
||||
args[pos] = [arg]
|
||||
elseif isa(arg, Dataset) ; # ==> a Dataset object
|
||||
elseif hasmethod(recipe, tuple(typeof(arg))) # ==> implicit recipe
|
||||
# @info which(recipe, tuple(typeof(arg))) # debug
|
||||
deleteat!(args, pos)
|
||||
insert!(args, pos, recipe(arg))
|
||||
pe = recipe(arg)
|
||||
if isa(pe, PlotElement)
|
||||
insert!(args, pos, pe)
|
||||
elseif isa(pe, Vector{PlotElement})
|
||||
for i in 1:length(pe)
|
||||
insert!(args, pos, pe[i])
|
||||
end
|
||||
else
|
||||
error("Recipe must return a PlotElement or Vector{PlotElement}")
|
||||
end
|
||||
continue
|
||||
elseif isa(arg, Vector{PlotElement}) # ==> explicit recipe (vector)
|
||||
deleteat!(args, pos)
|
||||
@ -1128,40 +1153,54 @@ function parseArguments(_args...)
|
||||
pos += 1
|
||||
end
|
||||
|
||||
# Third pass: convert data into Dataset objetcs
|
||||
# Third pass: convert data into Dataset objects
|
||||
pos = 1
|
||||
accum = Vector{AbstractArray}()
|
||||
while pos <= length(args)
|
||||
arg = args[pos]
|
||||
if isa(arg, AbstractArray) && # ==> beginning of a dataset
|
||||
((valtype(arg) <: Real) ||
|
||||
(valtype(arg) <: AbstractString))
|
||||
taken = false
|
||||
|
||||
# Collect all data
|
||||
accum = Vector{AbstractArray}()
|
||||
while isa(arg, AbstractArray) &&
|
||||
((valtype(arg) <: Real) ||
|
||||
(valtype(arg) <: AbstractString))
|
||||
if isa(arg, AbstractArray)
|
||||
if nonmissingtype(eltype(arg)) != eltype(arg)
|
||||
@assert nonmissingtype(eltype(arg)) <: AbstractFloat "Missing values are supported only on arrays of floats"
|
||||
arg = replace(arg, missing => NaN)
|
||||
end
|
||||
tt = eltype(arg)
|
||||
|
||||
# Try to convert into Int, Float64 and String
|
||||
if (tt <: Integer) && !(tt <: Int)
|
||||
arg = convert(Array{Int}, arg)
|
||||
elseif (tt <: AbstractFloat) && !(tt <: Float64)
|
||||
arg = convert(Array{Float64}, arg)
|
||||
elseif (tt <: AbstractString) && !(tt <: String)
|
||||
arg = convert(Array{String}, arg)
|
||||
end
|
||||
|
||||
tt = eltype(arg)
|
||||
if (tt <: Real) ||
|
||||
(tt <: AbstractString)
|
||||
push!(accum, arg)
|
||||
deleteat!(args, pos)
|
||||
if pos <= length(args)
|
||||
arg = args[pos]
|
||||
else
|
||||
break
|
||||
taken = true
|
||||
end
|
||||
end
|
||||
|
||||
if !taken || (pos > length(args))
|
||||
if length(accum) > 0
|
||||
mm = extrema(length.(accum))
|
||||
if mm[1] == 0
|
||||
# empty Dataset
|
||||
if mm[1] == 0 # empty Dataset
|
||||
@assert mm[1] == mm[2] "At least one input array is empty, while other(s) are not"
|
||||
d = DatasetEmpty()
|
||||
else
|
||||
d = Dataset(accum)
|
||||
end
|
||||
insert!(args, pos, d)
|
||||
empty!(accum)
|
||||
end
|
||||
|
||||
pos += 1
|
||||
end
|
||||
end
|
||||
|
||||
# Fourth pass: collect PlotElement objects
|
||||
mid = 0
|
||||
@ -1321,7 +1360,7 @@ end
|
||||
|
||||
Return the **Gnuplot.jl** package version.
|
||||
"""
|
||||
version() = v"1.3.0"
|
||||
version() = v"1.4.1"
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
"""
|
||||
@ -1672,6 +1711,34 @@ function linetypes(cmap::ColorScheme; lw=1, ps=1, dashed=false, rev=false)
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
palette_levels(cmap::ColorScheme; rev=false, smooth=false)
|
||||
palette_levels(s::Symbol; rev=false, smooth=false)
|
||||
|
||||
Convert a `ColorScheme` object into a `Tuple{Vector{Float64}, Vector{String}, Int}` containing:
|
||||
- the numeric levels (between 0 and 1 included) corresponding to colors in the palette;
|
||||
- the corresponding colors (as hex strings);
|
||||
- the total number of different colors in the palette.
|
||||
|
||||
If the argument is a `Symbol` it is interpreted as the name of one of the predefined schemes in [ColorSchemes](https://juliagraphics.github.io/ColorSchemes.jl/stable/basics/#Pre-defined-schemes-1).
|
||||
|
||||
If `rev=true` the palette is reversed. If `smooth=true` the palette is interpolated in 256 levels.
|
||||
"""
|
||||
palette_levels(s::Symbol; kwargs...) = palette_levels(colorschemes[s]; kwargs...)
|
||||
function palette_levels(cmap::ColorScheme; rev=false, smooth=false)
|
||||
levels = OrderedDict{Float64, String}()
|
||||
for x in LinRange(0, 1, (smooth ? 256 : length(cmap.colors)))
|
||||
if rev
|
||||
color = get(cmap, 1-x)
|
||||
else
|
||||
color = get(cmap, x)
|
||||
end
|
||||
levels[x] = "#" * Colors.hex(color)
|
||||
end
|
||||
return (collect(keys(levels)), collect(values(levels)), length(cmap.colors))
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
palette(cmap::ColorScheme; rev=false, smooth=false)
|
||||
palette(s::Symbol; rev=false, smooth=false)
|
||||
@ -1682,19 +1749,13 @@ If the argument is a `Symbol` it is interpreted as the name of one of the predef
|
||||
|
||||
If `rev=true` the palette is reversed. If `smooth=true` the palette is interpolated in 256 levels.
|
||||
"""
|
||||
function palette(values::Vector{Float64}, levels::Vector{String}, ncolors::Int)
|
||||
str = string.(values) .* " '" .* levels .* "'"
|
||||
return "set palette defined (" * join(str, ", ") * ")\nset palette maxcol $(ncolors)\n"
|
||||
end
|
||||
palette(s::Symbol; kwargs...) = palette(colorschemes[s]; kwargs...)
|
||||
function palette(cmap::ColorScheme; rev=false, smooth=false)
|
||||
levels = Vector{String}()
|
||||
for x in LinRange(0, 1, (smooth ? 256 : length(cmap.colors)))
|
||||
if rev
|
||||
color = get(cmap, 1-x)
|
||||
else
|
||||
color = get(cmap, x)
|
||||
end
|
||||
push!(levels, "$x '#" * Colors.hex(color) * "'")
|
||||
end
|
||||
return "set palette defined (" * join(levels, ", ") * ")\nset palette maxcol $(length(cmap.colors))\n"
|
||||
end
|
||||
palette(cmap::ColorScheme; kwargs...) =
|
||||
palette(palette_levels(cmap; kwargs...)...)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
@ -1820,16 +1881,20 @@ function hist(v::Vector{T}; range=[NaN,NaN], bs=NaN, nbins=0, pad=true) where T
|
||||
if sum(hh.weights) < length(i)
|
||||
j = findall(v[i] .== range[2])
|
||||
@assert length(j) == (length(i) - sum(hh.weights))
|
||||
if length(hh.weights) > 0
|
||||
hh.weights[end] += length(j)
|
||||
else
|
||||
push!(hh.weights, length(j))
|
||||
end
|
||||
end
|
||||
else
|
||||
hh = fit(Histogram, v[i], closed=:left)
|
||||
end
|
||||
@assert sum(hh.weights) == length(i)
|
||||
x = collect(hh.edges[1])
|
||||
x = (x[1:end-1] .+ x[2:end]) ./ 2
|
||||
binsize = isfinite(bs) ? bs : x[2] - x[1]
|
||||
length(x) > 1 && (x = (x[1:end-1] .+ x[2:end]) ./ 2)
|
||||
h = hh.weights
|
||||
binsize = x[2] - x[1]
|
||||
if pad
|
||||
x = [x[1]-binsize, x..., x[end]+binsize]
|
||||
h = [0, h..., 0]
|
||||
@ -1893,6 +1958,35 @@ function hist(v1::Vector{T1}, v2::Vector{T2};
|
||||
return Histogram2D(x1, x2, hh.weights, binsize1, binsize2)
|
||||
end
|
||||
|
||||
# Allow missing values in input
|
||||
function hist(v::Vector{Union{Missing,T}}; kw...) where T <: Real
|
||||
ii = findall(.!ismissing.(v))
|
||||
@info "Neglecting missing values ($(length(v) - length(ii)))"
|
||||
hist(convert(Vector{T}, v[ii]); kw...)
|
||||
end
|
||||
|
||||
function hist(v1::Vector{Union{Missing,T1}}, v2::Vector{T2}; kw...) where {T1 <: Real, T2 <: Real}
|
||||
ii = findall(.!ismissing.(v1) .&
|
||||
.!ismissing.(v2) )
|
||||
@info "Neglecting missing values ($(length(v1) - length(ii)))"
|
||||
hist(convert(Vector{T1}, v1[ii]), convert(Vector{T2}, v2[ii]), kw...)
|
||||
end
|
||||
|
||||
function hist(v1::Vector{T1}, v2::Vector{Union{Missing, T2}}; kw...) where {T1 <: Real, T2 <: Real}
|
||||
ii = findall(.!ismissing.(v1) .&
|
||||
.!ismissing.(v2) )
|
||||
@info "Neglecting missing values ($(length(v1) - length(ii)))"
|
||||
hist(convert(Vector{T1}, v1[ii]), convert(Vector{T2}, v2[ii]), kw...)
|
||||
end
|
||||
|
||||
function hist(v1::Vector{Union{Missing,T1}}, v2::Vector{Union{Missing,T2}}; kw...) where {T1 <: Real, T2 <: Real}
|
||||
ii = findall(.!ismissing.(v1) .&
|
||||
.!ismissing.(v2) )
|
||||
@info "Neglecting missing values ($(length(v1) - length(ii)))"
|
||||
hist(convert(Vector{T1}, v1[ii]), convert(Vector{T2}, v2[ii]), kw...)
|
||||
end
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
"""
|
||||
@ -2254,7 +2348,7 @@ function gpvars(sid::Symbol)
|
||||
if length(s) == 2
|
||||
key = Symbol(s[1])
|
||||
if s[2][1] == '"'
|
||||
out[key] = s[2][2:end-1]
|
||||
out[key] = s[2][2:prevind(s[2], end, 1)]
|
||||
else
|
||||
try
|
||||
out[key] = Meta.parse(s[2])
|
||||
|
||||
@ -286,4 +286,8 @@ Gnuplot.quit(:default)
|
||||
Gnuplot.options.dry = true
|
||||
@gp hist(randn(1000))
|
||||
|
||||
# Various hist() corner cases
|
||||
@gp hist([1,2,3], bs=2)
|
||||
@gp hist([1,1,1], bs=1)
|
||||
|
||||
Gnuplot.quitall()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user