Compare commits

...

20 Commits

Author SHA1 Message Date
mantaohuang
ea8b71898b fix stuff 2022-03-26 18:55:18 -04:00
mantaohuang
4bdee5f6af testing out 2022-03-26 18:37:03 -04:00
mantaohuang
bbbd899c19 testing out 2022-03-26 18:33:43 -04:00
mantaohuang
abcb73b70f Use raw expressions for xlabel, ylabels etc 2022-03-26 18:27:20 -04:00
Giorgio Calderone
9001d5f385 Minor changes in preparation of v1.4.1 2022-01-04 12:06:01 +01:00
Giorgio Calderone
919068e797 Merge branch 'master' of https://github.com/gcalderone/Gnuplot.jl 2022-01-03 13:34:33 +01:00
gcalderone
23c3d663e8
Merge pull request #51 from wentasah/stdout-via-pipe
Don't run gnuplot process connected to stdout
2022-01-03 13:34:25 +01:00
Giorgio Calderone
3f40e38d72 Merge branch 'master' of https://github.com/gcalderone/Gnuplot.jl 2022-01-03 12:41:12 +01:00
gcalderone
443ef0edf7
Merge pull request #49 from wentasah/hist-bounds
Fix BoundsErrors in hist()
2022-01-03 12:40:40 +01:00
gcalderone
ab927d0622
Merge pull request #52 from wentasah/escape-output
Allow using single quotes in output file names
2022-01-03 10:45:19 +01:00
Giorgio Calderone
622597c589 Merge branch 'master' of https://github.com/gcalderone/Gnuplot.jl 2022-01-03 10:39:40 +01:00
Michal Sojka
ce00617796 Allow using single quotes in output file names
Gnuplot single-quoted strings have to escape single-quote characters
by doubling them.
2021-12-13 18:58:24 +01:00
Giorgio Calderone
e70c30dd13 Handle the case where an implicit recipe returns a Vector{PlotElement} 2021-12-05 15:59:48 +01:00
Michal Sojka
799154f53c Add doctest of dumb terminal
This serves two purposes:

1. It demonstrates the functionality of the dumb terminal.
2. It checks that the previous commit works.
2021-12-05 11:53:30 +01:00
Michal Sojka
d02c211e99 Don't run gnuplot process connected to stdout
This change fixes incompatibility of Gnuplot.jl with Documenter.jl
versions 0.27.0 and above. Without this change, Gnuplot.jl has at
least these problems:

1. When building Gnuplot.jl documentation, the process blocks and
   never finishes.

2. When using Gnuplot.jl in docstrings in other code, running
   `doctest` blocks and never finishes.

The reason is that Documenter uses a new version of IOCapture.jl,
which contains this commit:
6cb4cdff34.

Documenter evaluates code snippets from the documentation with
`stdout` redirected to a pipe to show the command's output. The
mentioned commit changes the behavior so that now capturing waits
until the pipe is closed. The problem with Gnuplot.jl is that when the
gnuplot process is started as a part of the execution of documentation
code snippet, its `stdout` is bound to Documenter's pipe. The pipe is
not closed until the gnuplot process exits, which does not happen
unless the code snippet calls `Gnuplot.quit` explicitly. Therefore
Documenter blocks indefinitely.

This can be demonstrated by storing the following code in `test.jl`

    module GnuplotDocTest
    """
    ```jldoctest; setup = :(using Gnuplot)
    julia> @gp rand(100)

    ```
    """
    test() = nothing
    end

    using Documenter
    doctest(pwd(), [GnuplotDocTest])

and running `julia test.jl`.

To fix this problem, we run the gnuplot process with stdout redirected
to a pipe and create an asynchronous task, which reads the gnuplot's
stdout and writes it to Julia's current stdout.

Correctness of this approach can be verified by running:

    using Gnuplot
    Gnuplot.options.term = "dumb"
    @gp "plot sin(x)"

Dumb terminal prints to stdout and the above command shows the graph
on Julia's stdout too. In the next commit, we add the above code as a
doctest.
2021-12-05 11:51:29 +01:00
Michal Sojka
67c8781f2b Fix another hist BoundsError
This fixes the error with `hist([1,1,1], bs=1)`:

    ERROR: BoundsError: attempt to access 0-element Vector{Int64} at index [0]
    Stacktrace:
     [1] getindex
       @ ./array.jl:801 [inlined]
     [2] hist(v::Vector{Int64}; range::Vector{Float64}, bs::Int64, nbins::Int64, pad::Bool)
       @ Gnuplot ~/.julia/dev/Gnuplot/src/Gnuplot.jl:1864
     [3] top-level scope
       @ REPL[50]:1
2021-09-06 16:53:40 +02:00
Michal Sojka
db8dcfc433 Fix bounds error in hist recipe
When running hist([1,2,3], bs=2), the following error is produced:

ERROR: BoundsError: attempt to access 1-element Vector{Float64} at index [2]
Stacktrace:
 [1] getindex
   @ ./array.jl:801 [inlined]
 [2] hist(v::Vector{Int64}; range::Vector{Float64}, bs::Int64, nbins::Int64, pad::Bool)
   @ Gnuplot ~/.julia/dev/Gnuplot/src/Gnuplot.jl:1873
 [3] top-level scope
   @ REPL[25]:1
2021-09-06 16:53:40 +02:00
gcalderone
04484adc22
Merge pull request #44 from wentasah/requires-jl
docs: Suggest using Requires.jl for automatic settings of package options
2021-05-25 16:04:11 +02:00
Michal Sojka
658e5f422c docs: Suggest using Requires.jl for automatic settings of package options
Using the @gnuplotrc macro for collecting user's preferred setup works
well, but it is a bit annoying when Julia needs to be restarted
often (e.g. due to crashes). Using Requires.jl allows the user to
forget about calling @gnuplotrc; the initialization happens
automatically, whenever the Gnuplot package is loaded.
2021-05-25 15:01:45 +02:00
Giorgio Calderone
9327492aa1 Updated 2021-05-06 00:14:01 +02:00
11 changed files with 136 additions and 47 deletions

View File

@ -1,3 +1,17 @@
# 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) # Version 1.4.0 (released on: May 5, 2021)
- New features: - New features:
* Missing values are accepted if the input arrays have `eltype <: * Missing values are accepted if the input arrays have `eltype <:

View File

@ -1,6 +1,6 @@
name = "Gnuplot" name = "Gnuplot"
uuid = "dc211083-a33a-5b79-959f-2ff34033469d" uuid = "dc211083-a33a-5b79-959f-2ff34033469d"
version = "1.4.0" version = "1.4.1"
[deps] [deps]
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4" ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
@ -21,4 +21,4 @@ DataStructures = "^0.18"
ReplMaker = "^0.2" ReplMaker = "^0.2"
StatsBase = "^0.33" StatsBase = "^0.33"
StructC14N = "^0.3" StructC14N = "^0.3"
julia = "^1.5" julia = "^1.6"

View File

@ -3,7 +3,7 @@
[![Build Status](https://travis-ci.org/gcalderone/Gnuplot.jl.svg?branch=master)](https://travis-ci.org/gcalderone/Gnuplot.jl) [![Build Status](https://travis-ci.org/gcalderone/Gnuplot.jl.svg?branch=master)](https://travis-ci.org/gcalderone/Gnuplot.jl)
[![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md) [![License](http://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat)](LICENSE.md)
[![DocumentationStatus](https://img.shields.io/badge/docs-stable-blue.svg?style=flat)](https://gcalderone.github.io/Gnuplot.jl/v1.4.0/) [![DocumentationStatus](https://img.shields.io/badge/docs-stable-blue.svg?style=flat)](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. It also has automatic display of plots in Jupyter, Juno and VS Code. **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.

View File

@ -21,6 +21,7 @@ gpvars
hist hist
linetypes linetypes
palette palette
palette_levels
palette_names palette_names
recipe recipe
save save

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -210,6 +210,16 @@ saveas("basic008a") # hide
``` ```
![](assets/basic008a.png) ![](assets/basic008a.png)
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
```
![](assets/basic008b.png)
The list of all available palette can be retrieved with [`palette_names()`](@ref): The list of all available palette can be retrieved with [`palette_names()`](@ref):
```@repl abc ```@repl abc
palette_names() palette_names()

View File

@ -19,11 +19,11 @@ Check **Gnuplot.jl** version with:
```julia-repl ```julia-repl
julia> ]st Gnuplot julia> ]st Gnuplot
Status `~/.julia/environments/v1.4/Project.toml` Status `~/.julia/environments/v1.4/Project.toml`
[dc211083] Gnuplot v1.4.0 [dc211083] Gnuplot v1.4.1
``` ```
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: 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-repl
julia> ]add Gnuplot@1.4.0 julia> ]add Gnuplot@1.4.1
``` ```
and check which package is causing the conflict. and check which package is causing the conflict.

View File

@ -70,12 +70,11 @@ Each line reports the package name (`GNUPLOT`), the session name (`default`), th
## Package initialization ## 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 ```julia
macro gnuplotrc() using Requires
return :( @require Gnuplot="dc211083-a33a-5b79-959f-2ff34033469d" begin
using Gnuplot; @info "Custom Gnuplot initialization"
# Uncomment the following if you don't have the gnuplot # Uncomment the following if you don't have the gnuplot
# executable installed on your platform: # executable installed on your platform:
#Gnuplot.options.dry = true; #Gnuplot.options.dry = true;
@ -103,17 +102,13 @@ macro gnuplotrc()
# Set the default linetypes # Set the default linetypes
empty!(Gnuplot.options.init); 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`. # Initialize the gnuplot REPL using the provided `start_key`.
if Gnuplot.options.gpviewer; if Gnuplot.options.gpviewer;
Gnuplot.repl_init(start_key='>'); Gnuplot.repl_init(start_key='>');
end; end;
)
end end
``` ```
At the Julia prompt you may load the package and the associated settings by typing:
```julia The above code will be automatically when you first load the package with `using Gnuplot`.
julia> @gnuplotrc
```
and you're ready to go.

View File

@ -26,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`) ## 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:
![](assets/sixelgd.png) ![](assets/sixelgd.png)
The above terminals are available if gnuplot has been compiled with the `--with-bitmap-terminals` option enabled and Libgd (only for `sixelgd`). The above terminals are available if gnuplot has been compiled with the `--with-bitmap-terminals` option enabled and Libgd (only for `sixelgd`).

View File

@ -7,7 +7,7 @@ import Base.reset
import Base.write import Base.write
import Base.show 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, terminal, terminals, test_terminal,
stats, @gp, @gsp, save, gpexec, stats, @gp, @gsp, save, gpexec,
boxxy, contourlines, dgrid3d, hist, recipe, gpvars, gpmargins, gpranges boxxy, contourlines, dgrid3d, hist, recipe, gpvars, gpmargins, gpranges
@ -283,11 +283,11 @@ function parseKeywords(; kwargs...)
ismissing(kw.zrange ) || (push!(out, replace("set zrange [" * join(kw.zrange , ":") * "]", "NaN"=>"*"))) 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.cbrange) || (push!(out, replace("set cbrange [" * join(kw.cbrange, ":") * "]", "NaN"=>"*")))
ismissing(kw.key ) || (push!(out, "set key " * kw.key * "")) ismissing(kw.key ) || (push!(out, "set key " * kw.key * ""))
ismissing(kw.title ) || (push!(out, "set title \"" * kw.title * "\"")) ismissing(kw.title ) || (push!(out, "set title '" * kw.title * "'"))
ismissing(kw.xlabel ) || (push!(out, "set xlabel \"" * kw.xlabel * "\"")) ismissing(kw.xlabel ) || (push!(out, "set xlabel '" * kw.xlabel * "'"))
ismissing(kw.ylabel ) || (push!(out, "set ylabel \"" * kw.ylabel * "\"")) ismissing(kw.ylabel ) || (push!(out, "set ylabel '" * kw.ylabel * "'"))
ismissing(kw.zlabel ) || (push!(out, "set zlabel \"" * kw.zlabel * "\"")) ismissing(kw.zlabel ) || (push!(out, "set zlabel '" * kw.zlabel * "'"))
ismissing(kw.cblabel) || (push!(out, "set cblabel \"" * kw.cblabel * "\"")) ismissing(kw.cblabel) || (push!(out, "set cblabel '" * kw.cblabel * "'"))
ismissing(kw.xlog ) || (push!(out, (kw.xlog ? "" : "un") * "set logscale x")) ismissing(kw.xlog ) || (push!(out, (kw.xlog ? "" : "un") * "set logscale x"))
ismissing(kw.ylog ) || (push!(out, (kw.ylog ? "" : "un") * "set logscale y")) ismissing(kw.ylog ) || (push!(out, (kw.ylog ? "" : "un") * "set logscale y"))
ismissing(kw.zlog ) || (push!(out, (kw.zlog ? "" : "un") * "set logscale z")) ismissing(kw.zlog ) || (push!(out, (kw.zlog ? "" : "un") * "set logscale z"))
@ -304,7 +304,6 @@ function parseKeywords(; kwargs...)
ismissing(kw.rmargin) || push!(out, (kw.rmargin == "" ? "unset rmargin" : "set rmargin at screen $(kw.rmargin)")) 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.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)")) ismissing(kw.tmargin) || push!(out, (kw.tmargin == "" ? "unset tmargin" : "set tmargin at screen $(kw.tmargin)"))
return join(out, ";\n") return join(out, ";\n")
end end
@ -520,7 +519,6 @@ function readTask(gp::GPSession)
delete!(sessions, gp.sid) delete!(sessions, gp.sid)
end end
function GPSession(sid::Symbol) function GPSession(sid::Symbol)
session = DrySession(sid) session = DrySession(sid)
if !options.dry if !options.dry
@ -535,13 +533,16 @@ function GPSession(sid::Symbol)
end end
pin = Base.Pipe() pin = Base.Pipe()
pout = Base.Pipe()
perr = 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) chan = Channel{String}(32)
# Close unused sides of the pipes # Close unused sides of the pipes
Base.close(pout.in)
Base.close(perr.in) Base.close(perr.in)
Base.close(pin.out) Base.close(pin.out)
Base.start_reading(pout.out)
Base.start_reading(perr.out) Base.start_reading(perr.out)
out = GPSession(getfield.(Ref(session), fieldnames(DrySession))..., out = GPSession(getfield.(Ref(session), fieldnames(DrySession))...,
@ -550,6 +551,9 @@ function GPSession(sid::Symbol)
# Start reading tasks # Start reading tasks
@async readTask(out) @async readTask(out)
@async while !eof(pout) # see PR #51
write(stdout, readavailable(pout))
end
# Read gnuplot default terminal # Read gnuplot default terminal
if options.term == "" if options.term == ""
@ -925,7 +929,7 @@ function execall(gp::GPSession; term::AbstractString="", output::AbstractString=
gpexec(gp, "unset multiplot") gpexec(gp, "unset multiplot")
gpexec(gp, "set term $term") gpexec(gp, "set term $term")
end end
(output != "") && gpexec(gp, "set output '$output'") (output != "") && gpexec(gp, "set output '$(replace(output, "'" => "''"))'")
# printstyled("Plotting with terminal: " * terminal() * "\n", color=:blue, bold=true) # printstyled("Plotting with terminal: " * terminal() * "\n", color=:blue, bold=true)
@ -1125,7 +1129,16 @@ function parseArguments(_args...)
elseif hasmethod(recipe, tuple(typeof(arg))) # ==> implicit recipe elseif hasmethod(recipe, tuple(typeof(arg))) # ==> implicit recipe
# @info which(recipe, tuple(typeof(arg))) # debug # @info which(recipe, tuple(typeof(arg))) # debug
deleteat!(args, pos) 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 continue
elseif isa(arg, Vector{PlotElement}) # ==> explicit recipe (vector) elseif isa(arg, Vector{PlotElement}) # ==> explicit recipe (vector)
deleteat!(args, pos) deleteat!(args, pos)
@ -1347,7 +1360,7 @@ end
Return the **Gnuplot.jl** package version. Return the **Gnuplot.jl** package version.
""" """
version() = v"1.4.0" version() = v"1.4.1"
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
""" """
@ -1698,6 +1711,34 @@ function linetypes(cmap::ColorScheme; lw=1, ps=1, dashed=false, rev=false)
end 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(cmap::ColorScheme; rev=false, smooth=false)
palette(s::Symbol; rev=false, smooth=false) palette(s::Symbol; rev=false, smooth=false)
@ -1708,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. If `rev=true` the palette is reversed. If `smooth=true` the palette is interpolated in 256 levels.
""" """
palette(s::Symbol; kwargs...) = palette(colorschemes[s]; kwargs...) function palette(values::Vector{Float64}, levels::Vector{String}, ncolors::Int)
function palette(cmap::ColorScheme; rev=false, smooth=false) str = string.(values) .* " '" .* levels .* "'"
levels = Vector{String}() return "set palette defined (" * join(str, ", ") * ")\nset palette maxcol $(ncolors)\n"
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 end
palette(s::Symbol; kwargs...) = palette(colorschemes[s]; kwargs...)
palette(cmap::ColorScheme; kwargs...) =
palette(palette_levels(cmap; kwargs...)...)
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -1846,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) if sum(hh.weights) < length(i)
j = findall(v[i] .== range[2]) j = findall(v[i] .== range[2])
@assert length(j) == (length(i) - sum(hh.weights)) @assert length(j) == (length(i) - sum(hh.weights))
if length(hh.weights) > 0
hh.weights[end] += length(j) hh.weights[end] += length(j)
else
push!(hh.weights, length(j))
end
end end
else else
hh = fit(Histogram, v[i], closed=:left) hh = fit(Histogram, v[i], closed=:left)
end end
@assert sum(hh.weights) == length(i) @assert sum(hh.weights) == length(i)
x = collect(hh.edges[1]) 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 h = hh.weights
binsize = x[2] - x[1]
if pad if pad
x = [x[1]-binsize, x..., x[end]+binsize] x = [x[1]-binsize, x..., x[end]+binsize]
h = [0, h..., 0] h = [0, h..., 0]

View File

@ -286,4 +286,8 @@ Gnuplot.quit(:default)
Gnuplot.options.dry = true Gnuplot.options.dry = true
@gp hist(randn(1000)) @gp hist(randn(1000))
# Various hist() corner cases
@gp hist([1,2,3], bs=2)
@gp hist([1,1,1], bs=1)
Gnuplot.quitall() Gnuplot.quitall()