Docs updated

This commit is contained in:
Giorgio Calderone 2020-04-16 22:53:47 +02:00
parent 4a0b6201c5
commit cb3bdb60ea
5 changed files with 101 additions and 78 deletions

View File

@ -182,17 +182,7 @@ Gnuplot.quitall()
``` ```
## Histograms ## Histograms
**Gnuplot.jl** provides facilities to compute (see [`hist()`](@ref) function) and display (see [Histogram recipes](@ref)) histograms. E.g., to quickly preview an histogram: **Gnuplot.jl** provides a facility to compute (see [`hist()`](@ref) function) an histogram. It allows to set the range to consider (`range=` keyword) and either the bin size (`bs=`) or the total number of bins (`nbins=`) in the histogram (see [`hist()`](@ref) documentation for further information) and return a [`Gnuplot.Histogram1D`](@ref) structure, whose content can be visualized as follows:
```@example abc
x = randn(1000);
@gp hist(x)
saveas("advanced013a") # hide
```
![](assets/advanced013a.png)
A finer control on the output is achieved by setting the range to consider (`range=` keyword) and either the bin size (`bs=`) or the total number of bins (`nbins=`) in the histogram. See [`hist()`](@ref) documentation for further information.
The [`hist()`](@ref) return a [`Gnuplot.Histogram1D`](@ref) structure, whose content can be exploited to customize histogram appearence, e.g.:
```@example abc ```@example abc
x = randn(1000); x = randn(1000);
h = hist(x, range=3 .* [-1,1], bs=0.5) h = hist(x, range=3 .* [-1,1], bs=0.5)
@ -201,18 +191,10 @@ saveas("advanced013b") # hide
``` ```
![](assets/advanced013b.png) ![](assets/advanced013b.png)
**Gnuplot.jl** also allows to compute 2D histograms by passing two vectors (with the same lengths) to [`hist()`](@ref). Again, a finer control can be achieved by specifying ranges, bin size or number of bins (along both dimensions) and by explicitly using the content of the returned [`Gnuplot.Histogram2D`](@ref) structure:
**Gnuplot.jl** also allows to compute 2D histograms by passing two vectors (with the same lengths) to [`hist()`](@ref). A quick preview is simply obtained by:
```@example abc ```@example abc
x = randn(10_000) x = randn(10_000)
y = randn(10_000) y = randn(10_000)
@gp "set size ratio -1" hist(x, y)
saveas("advanced014a") # hide
```
![](assets/advanced014a.png)
Again, a finer control can be achieved by specifying ranges, bin size or number of bins (along both dimensions) and by explicitly using the content of the returned [`Gnuplot.Histogram2D`](@ref) structure:
```@example abc
h = hist(x, y, bs1=0.25, nbins2=20, range1=[-3,3], range2=[-3,3]) h = hist(x, y, bs1=0.25, nbins2=20, range1=[-3,3], range2=[-3,3])
@gp "set size ratio -1" h.bins1 h.bins2 h.counts "w image notit" @gp "set size ratio -1" h.bins1 h.bins2 h.counts "w image notit"
saveas("advanced014b") # hide saveas("advanced014b") # hide
@ -229,6 +211,8 @@ saveas("advanced014c") # hide
``` ```
![](assets/advanced014c.png) ![](assets/advanced014c.png)
See also [Histogram recipes](@ref) for a quicker way to preview histogram plots.
## Contour lines ## Contour lines
Although gnuplot already handles contours by itself (with the `set contour` command), **Gnuplot.jl** provides a way to calculate contour lines paths before displaying them, using the [`contourlines()`](@ref) function. We may use it for, e.g., plot contour lines with customized widths and palette, according to their z level. Continuing with the previous example: Although gnuplot already handles contours by itself (with the `set contour` command), **Gnuplot.jl** provides a way to calculate contour lines paths before displaying them, using the [`contourlines()`](@ref) function. We may use it for, e.g., plot contour lines with customized widths and palette, according to their z level. Continuing with the previous example:

View File

@ -37,11 +37,16 @@ The following functions are not exported by the **Gnuplot.jl** package since the
In order to call these functions you should add the `Gnuplot.` prefix to the function name. In order to call these functions you should add the `Gnuplot.` prefix to the function name.
```@docs ```@docs
Gnuplot.Dataset
Gnuplot.DatasetEmpty
Gnuplot.DatasetText
Gnuplot.DatasetBin
Gnuplot.Histogram1D Gnuplot.Histogram1D
Gnuplot.Histogram2D Gnuplot.Histogram2D
Gnuplot.IsoContourLines Gnuplot.IsoContourLines
Gnuplot.Options Gnuplot.Options
Gnuplot.Path2d Gnuplot.Path2d
Gnuplot.PlotElement
Gnuplot.gpversion Gnuplot.gpversion
Gnuplot.quit Gnuplot.quit
Gnuplot.quitall Gnuplot.quitall

View File

@ -10,48 +10,91 @@ push!( Gnuplot.options.reset, linetypes(:Set1_5, lw=1.5, ps=1.5))
saveas(file) = save(term="pngcairo size 550,350 fontscale 0.8", output="assets/$(file).png") saveas(file) = save(term="pngcairo size 550,350 fontscale 0.8", output="assets/$(file).png")
``` ```
# Plot recipes # Plot recipes
A plot *recipe* is a quicklook visualization procedure aimed at reducing the amount of repetitive code needed to generate a plot. More specifically, a recipe is a function to convert data from the "Julia world" into a form suitable to be ingested in **Gnuplot.jl**. A plot *recipe* is a quicklook visualization procedure aimed at reducing the amount of repetitive code to generate a plot. More specifically, a recipe is a function that convert data from the "Julia world" into a form suitable to be ingested in **Gnuplot.jl**, namely a scalar (or a vector of) [`Gnuplot.PlotElement`](@ref) object(s). The latter contain informations on how to create a plot, or a part of it, and can be used directly as arguments in a `@gp` or `@gsp` call.
There are two kinds of recipes: There are two kinds of recipes:
- *explicit* recipe: a function which is explicitly invoked by the user. It can have any name and accept any number of arguments and keywords. It is typically used when the visualization of a data type requires some extra information, beside data itself. An example is the quicklook procedure for a `DataFrame` object (shown below); - *explicit* recipe: a function which is explicitly invoked by the user. It can have any name and accept any number of arguments and keywords. It is typically used when the visualization of a data type requires some extra information, beside data itself (e.g. to plot data from a `DataFrame` object, see [Explicit recipe (example)](@ref));
- *implicit* recipe: a function which is automatically called by **Gnuplot.jl**. It must extend the `Gnuplot.recipe` function, and accept exactly one mandatory argument. It is typically used when the visualization is completely determined by the data type itself. An example is the visualization of a `Matrix{ColorTypes.RGB}` object as an image. - *implicit* recipe: a function which is automatically called by **Gnuplot.jl**. It must extend the p`recipe()`](@ref) function, and accept exactly one mandatory argument. It is typically used when the visualization is completely determined by the data type itself (e.g. the visualization of a `Matrix{ColorTypes.RGB}` object as an image, see [Image recipes](@ref));
In both cases the recipe function must return a scalar, or a vector of, `PlotElements` object(s), containing all the informations to create a plot, or a part of it. An implicit recipe is invoked whenever the data type of an argument to `@gp` or `@gsp` is not among the allowed ones (see [`@gp()`](@ref) documentation). If a suitable recipe do not exists an error is raised. On the other hand, an explicit recipe needs to be invoked by the user, and the output passed directly to `@gp` or `@gsp`.
Although recipes provides very efficient tools for data exploration, their use typically hide the details of plot generation. As a consequence they provide less flexibility than the approaches described in [Basic usage](@ref) and [Advanced usage](@ref).
The `@gp` or `@gsp`. Currently, the **Gnuplot.jl** package provides no built-in explicit recipe. The implicit recipes are implemented in [recipes.jl](https://github.com/gcalderone/Gnuplot.jl/blob/master/src/recipes.jl).
In , and can be passed directly to `@gp` or `@gsp`.
## Explicit recipe (example)
To generate a plot using the data contained in a `DataFrame` object we need, beside the data itself, the name of the columns to use for the X and Y coordinates. The following example shows how to implement an explicit recipe to plot a `DataFrame` object:
```@example abc
using RDatasets, DataFrames, Gnuplot
import Gnuplot: PlotElement, DatasetText
function plotdf(df::DataFrame, colx::Symbol, coly::Symbol; group=nothing)
if isnothing(group)
return PlotElement(data=DatasetText(df[:, colx], df[:, coly]),
plot="w p notit",
xlab=string(colx), ylab=string(coly))
end
out = Vector{Gnuplot.PlotElement}()
push!(out, PlotElement(;xlab=string(colx), ylab=string(coly)))
for g in sort(unique(df[:, group]))
i = findall(df[:, group] .== g)
if length(i) > 0
push!(out, PlotElement(data=DatasetText(df[i, colx], df[i, coly]),
plot="w p t '$g'"))
end
end
return out
end
# Load a DataFrame and convert it to a PlotElement
iris = dataset("datasets", "iris")
@gp plotdf(iris, :SepalLength, :SepalWidth, group=:Species)
saveas("recipes001") # hide
```
![](assets/recipes001.png)
. The fields of the `PlotElements` structure are:
- `mid::Int`:: multiplot ID;
- `cmds::Vector{String}`: commands to set plot properties;
- `data::Vector{Dataset}`: data set(s);
- `plot::Vector{String}`: plot specifications for each `Dataset`;
where `Dataset` is an abstract type, the actual data sets are stored in the form of either a `DatasetText` object (a textual representation of the data) or a `DatasetBin` object (a binary file). Both `DatasetText` and `DatasetBin` structures provide a number of constructors accepting several types of input data.
As anticipated, a recipe can be explicitly called by the user and the output passed to `@gp` or `@gsp`.
All arguments to `@gp` or `@gsp` (except `Int`s, `String`s, `Tuple`s, `Array` of both numbers and strings) are scanned to check if an implicit recipe exists to handle them, and in this case it is
Although a recipe provides a very efficient mean for data exploration,
## Histogram recipes ## Histogram recipes
The object returned by the [`hist()`](@ref) function can be readily visualized by means of implicit recipes defined on the `Gnuplot.Histogram1D` and `Gnuplot.Histogram2D` types:
```@example abc
x = randn(1000);
@gp hist(x)
saveas("recipes002") # hide
```
![](assets/recipes002.png)
```@example abc
x = randn(1000);
y = randn(1000);
@gp hist(x, y)
saveas("recipes002a") # hide
```
![](assets/recipes002a.png)
## Image recipes ## Image recipes
If the orientation is not the correct one you may adjust it with the gnuplot `rotate=` keyword (the following example requires the `TestImages` package to be installed):
The **Gnuplot.jl** package provides implicit recipes to display images in the following formats:
- `Matrix{ColorTypes.RGB{T}}`;
- `Matrix{ColorTypes.RGBA{T}}`
- `Matrix{ColorTypes.Gray{T}}`;
- `Matrix{ColorTypes.GrayA{T}}`;
To use these recipes simply pass an image to `@gp`, e.g.:
```@example abc ```@example abc
using TestImages using TestImages
img = testimage("lighthouse"); img = testimage("lighthouse");
@ -61,13 +104,21 @@ saveas("recipes007b") # hide
![](assets/recipes007b.png) ![](assets/recipes007b.png)
To display a gray image use `with image` in place of `with rgbimage`, e.g.: All such recipes are defined as:
```julia
function recipe(M::Matrix{ColorTypes.RGB{T}}, opt="flipy")
...
end
```
with only one mandatory argument. In order to exploit the optional keyword we can explicitly invoke the recipe as follows:
```@example abc ```@example abc
img = testimage("walkbridge"); img = testimage("walkbridge");
@gp palette(:viridis) recipe(img, "flipy rot=15deg") @gp palette(:gray) recipe(img, "flipy rot=15deg")
saveas("recipes007c") # hide saveas("recipes007c") # hide
``` ```
![](assets/recipes007c.png) ![](assets/recipes007c.png)
Note that we used a custom palette (`:lapaz`, see [Palettes and line types](@ref)) and the rotation angle has been expressed in radians (`-0.5pi`). Note that we used both a palette (`:gray`, see [Palettes and line types](@ref)) and a custom rotation angle.
The `flipy` option is necessary for proper visualization (see discussion in [Plot matrix as images](@ref)).

View File

@ -12,6 +12,7 @@ export session_names, dataset_names, palette_names, linetypes, palette,
stats, @gp, @gsp, save, gpexec, stats, @gp, @gsp, save, gpexec,
boxxyerror, contourlines, hist, recipe, gpvars, gpmargins, gpranges boxxyerror, contourlines, hist, recipe, gpvars, gpmargins, gpranges
# ╭───────────────────────────────────────────────────────────────────╮ # ╭───────────────────────────────────────────────────────────────────╮
# │ TYPE DEFINITIONS │ # │ TYPE DEFINITIONS │
# │ User data representation │ # │ User data representation │
@ -1408,7 +1409,7 @@ The `@gp` macro, and its companion `@gsp` for 3D plots, allows to send data and
All Keyword names can be abbreviated as long as the resulting name is unambiguous. E.g. you can use `xr=[1,10]` in place of `xrange=[1,10]`. All Keyword names can be abbreviated as long as the resulting name is unambiguous. E.g. you can use `xr=[1,10]` in place of `xrange=[1,10]`.
- a `PlotElement` object is expanded in and its fields processed as one of the previous arguments; - a `PlotElement` object is expanded in its fields and processed as one of the previous arguments;
- any other data type is processed through an implicit recipe. If a suitable recipe do not exists an error is raised. - any other data type is processed through an implicit recipe. If a suitable recipe do not exists an error is raised.
""" """

View File

@ -5,7 +5,10 @@
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Histograms # Histograms
""" """
recipe() recipe(h::Histogram1D)
recipe(h::Histogram2D)
Implicit recipes to visualize 1D and 2D histograms.
""" """
recipe(h::Histogram1D) = recipe(h::Histogram1D) =
PlotElement(cmds="set grid", PlotElement(cmds="set grid",
@ -20,6 +23,14 @@ recipe(h::Histogram2D) =
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Images # Images
"""
recipe(M::Matrix{ColorTypes.RGB{T}}, opt="flipy")
recipe(M::Matrix{ColorTypes.RGBA{T}}, opt="flipy")
recipe(M::Matrix{ColorTypes.Gray{T}}, opt="flipy")
recipe(M::Matrix{ColorTypes.GrayA{T}}, opt="flipy")
Implicit recipes to show images.
"""
recipe(M::Matrix{ColorTypes.RGB{T}}, opt="flipy") where T = recipe(M::Matrix{ColorTypes.RGB{T}}, opt="flipy") where T =
PlotElement(cmds=["set autoscale fix", "set size ratio -1"], PlotElement(cmds=["set autoscale fix", "set size ratio -1"],
data=DatasetBin(256 .* getfield.(M, :r), data=DatasetBin(256 .* getfield.(M, :r),
@ -43,32 +54,3 @@ recipe(M::Matrix{ColorTypes.GrayA{T}}, opt="flipy") where T =
PlotElement(cmds=["set autoscale fix", "set size ratio -1"], PlotElement(cmds=["set autoscale fix", "set size ratio -1"],
data=DatasetBin(256 .* getfield.(M, :val)), data=DatasetBin(256 .* getfield.(M, :val)),
plot="$opt with image notit") plot="$opt with image notit")
# ╭───────────────────────────────────────────────────────────────────╮
# │ EXPLICIT RECIPES │
# ╰───────────────────────────────────────────────────────────────────╯
macro recipes_DataFrames()
return esc(:(
function plotdf(df::DataFrame, colx::Symbol, coly::Symbol; group=nothing);
if isnothing(group);
return Gnuplot.PlotElement(xlab=string(colx), ylab=string(coly),
data=Gnuplot.DatasetText(df[:, colx], df[:, coly]),
plot="w p notit");
end;
data = Vector{Gnuplot.Dataset}();
plot = Vector{String}();
for g in sort(unique(df[:, group]));
i = findall(df[:, group] .== g);
if length(i) > 0;
push!(data, Gnuplot.DatasetText(df[i, colx], df[i, coly]));
push!(plot, "w p t '$g'");
end;
end;
return Gnuplot.PlotElement(xlab=string(colx), ylab=string(coly),
data=data, plot=plot);
end
))
end