Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9ea98bcb56 | |||
| 4f9804d24e | |||
| 0a88518188 | |||
| ccae6373be | |||
| 31e5d07a45 | |||
| 056fee4b28 | |||
| 5a47864d73 | |||
| 1c7da432f1 | |||
| 3d3ceacaab | |||
| 35df39a44b | |||
| c23d6d62e7 | |||
| 243d4a7ac3 | |||
| 50254d06d7 | |||
| 475b46f516 | |||
| f4573f7e87 | |||
| 7fb1a4ec0f | |||
| 4299aa0ff8 | |||
| 4eb7e3810e | |||
| 3e7e7e9ac0 | |||
| 9e1058ec0a | |||
| 426a9eb6d3 | |||
| f322b9ac1c | |||
| e13fec08ca |
@@ -2,39 +2,49 @@
|
||||
|
||||
[](https://travis-ci.org/tbreloff/Plots.jl)
|
||||
|
||||
#### Author: Thomas Breloff (@tbreloff)
|
||||
|
||||
Plotting interface and wrapper for several plotting packages.
|
||||
|
||||
Please add wishlist items, bugs, or any other comments/questions to the issues list.
|
||||
|
||||
## Examples
|
||||
## Examples for each implemented backend:
|
||||
|
||||
- [Qwt.jl](docs/qwt_examples.md)
|
||||
- [Gadfly.jl](docs/gadfly_examples.md)
|
||||
- [UnicodePlots.jl](docs/unicodeplots_examples.md)
|
||||
|
||||
## Installation
|
||||
|
||||
First, clone the package, and get any plotting packages you need:
|
||||
First, clone the package
|
||||
|
||||
```
|
||||
```julia
|
||||
Pkg.clone("https://github.com/tbreloff/Plots.jl.git")
|
||||
```
|
||||
|
||||
then get any plotting packages you need (obviously, you should get at least one backend):
|
||||
|
||||
```julia
|
||||
Pkg.add("Gadfly") # [optional]
|
||||
Pkg.clone("https://github.com/tbreloff/Qwt.jl.git") # [optional] requires pyqt and pyqwt
|
||||
Pkg.add("UnicodePlots") # [optional]
|
||||
```
|
||||
|
||||
## Use
|
||||
|
||||
Load it in. The underlying plotting backends are not imported until `plotter()` is called (which happens
|
||||
on your first call to `plot`). This means that you don't need any backends to be installed when you call `using Plots`.
|
||||
For now, the default backend is Gadfly.
|
||||
on your first call to `plot` or `subplot`). This means that you don't need any backends to be installed when you call `using Plots`.
|
||||
Plots will try to figure out a good default backend for you automatically based on what backends are installed.
|
||||
|
||||
```
|
||||
```julia
|
||||
using Plots
|
||||
```
|
||||
|
||||
Do a plot in Gadfly, then save a png:
|
||||
|
||||
```
|
||||
plot(rand(10,2); marker = :rect)
|
||||
```julia
|
||||
gadfly!()
|
||||
plot(rand(10,2); marker = :rect) # this will bring up a browser window with the plot, set show=false if you don't want that
|
||||
savepng(Plots.IMG_DIR * "gadfly1.png")
|
||||
```
|
||||
|
||||
@@ -42,153 +52,188 @@ which saves:
|
||||
|
||||

|
||||
|
||||
See the examples pages for lots of ways to plot in every supported backend.
|
||||
|
||||
Do a plot in Qwt, then save a png:
|
||||
## API
|
||||
|
||||
```
|
||||
plotter!(:qwt) # switches the backend to Qwt
|
||||
plot(rand(10,2); marker = :rect)
|
||||
savepng(Plots.IMG_DIR * "qwt1.png")
|
||||
```
|
||||
Call `plotter!(backend::Symbol)` or the shorthands (`gadfly!()`, `qwt!()`, `unicodeplots!()`, etc) to set the current plotting backend.
|
||||
Subsequent commands are converted into the relevant plotting commands for that package:
|
||||
|
||||
which saves:
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## plot and plotter! interface (WIP)
|
||||
|
||||
The main plot command. Call `plotter!(:module)` to set the current plotting backend.
|
||||
Commands are converted into the relevant plotting commands for that package:
|
||||
|
||||
```
|
||||
plotter!(:gadfly)
|
||||
plot(1:10) # this effectively calls `y = 1:10; Gadfly.plot(x=1:length(y), y=y)`
|
||||
plotter!(:qwt)
|
||||
plot(1:10) # this effectively calls `Qwt.plot(1:10)`
|
||||
```julia
|
||||
gadfly!()
|
||||
plot(1:10) # this effectively calls `y = 1:10; Gadfly.plot(x=1:length(y), y=y)`
|
||||
qwt!()
|
||||
plot(1:10) # this effectively calls `Qwt.plot(1:10)`
|
||||
```
|
||||
|
||||
Use `plot` to create a new plot object, and `plot!` to add to an existing one:
|
||||
|
||||
```
|
||||
plot(args...; kw...) # creates a new plot window, and sets it to be the `currentPlot`
|
||||
plot!(args...; kw...) # adds to the `currentPlot`
|
||||
plot!(plotobj, args...; kw...) # adds to the plot `plotobj`
|
||||
```julia
|
||||
plot(args...; kw...) # creates a new plot window, and sets it to be the `currentPlot`
|
||||
plot!(args...; kw...) # adds to the `currentPlot`
|
||||
plot!(plotobj, args...; kw...) # adds to the plot `plotobj`
|
||||
```
|
||||
|
||||
Now that you know which plot object you're updating (new, current, or other), I'll leave it off for simplicity.
|
||||
Here are some various args to supply, and the implicit mapping (AVec == AbstractVector and AMat == AbstractMatrix):
|
||||
|
||||
```
|
||||
plot(y::AVec; kw...) # one line... x = 1:length(y)
|
||||
plot(x::AVec, y::AVec; kw...) # one line (will assert length(x) == length(y))
|
||||
plot(y::AMat; kw...) # multiple lines (one per column of x), all sharing x = 1:size(y,1)
|
||||
plot(x::AVec, y::AMat; kw...) # multiple lines (one per column of x), all sharing x (will assert length(x) == size(y,1))
|
||||
plot(x::AMat, y::AMat; kw...) # multiple lines (one per column of x/y... will assert size(x) == size(y))
|
||||
plot(x::AVec, f::Function; kw...) # one line, y = f(x)
|
||||
plot(x::AMat, f::Function; kw...) # multiple lines, yᵢⱼ = f(xᵢⱼ)
|
||||
plot(x::AVec, fs::AVec{Function}; kw...) # multiple lines, yᵢⱼ = fⱼ(xᵢ)
|
||||
plot(y::AVec{AVec}; kw...) # multiple lines, each with x = 1:length(y[i])
|
||||
plot(x::AVec, y::AVec{AVec}; kw...) # multiple lines, will assert length(x) == length(y[i])
|
||||
plot(x::AVec{AVec}, y::AVec{AVec}; kw...) # multiple lines, will assert length(x[i]) == length(y[i])
|
||||
plot(n::Integer; kw...) # n lines, all empty (for updating plots)
|
||||
```julia
|
||||
# one line... x = 1:length(y)
|
||||
plot(y::AVec; kw...)
|
||||
|
||||
# TODO: how do we handle NA values in dataframes?
|
||||
plot(df::DataFrame; kw...) # one line per DataFrame column, labels == names(df)
|
||||
plot(df::DataFrame, columns; kw...) # one line per column, but on a subset of column names
|
||||
# one line (will assert length(x) == length(y))
|
||||
plot(x::AVec, y::AVec; kw...)
|
||||
|
||||
# multiple lines (one per column of x), all sharing x = 1:size(y,1)
|
||||
plot(y::AMat; kw...)
|
||||
|
||||
# multiple lines (one per column of x), all sharing x (will assert length(x) == size(y,1))
|
||||
plot(x::AVec, y::AMat; kw...)
|
||||
|
||||
# multiple lines (one per column of x/y... will assert size(x) == size(y))
|
||||
plot(x::AMat, y::AMat; kw...)
|
||||
|
||||
# one line, map function for range [xmin,xmax]
|
||||
plot(f::Function, xmin::Real, xmax::Real; kw...)
|
||||
|
||||
# multiple lines, map functions for range [xmin,xmax]
|
||||
plot(f::AVec{Function}, xmin::Real, xmax::Real; kw...)
|
||||
|
||||
# parametric plot... x = fx(u), y = fy(u)
|
||||
plot(fx::Function, fy::Function, umin::Real, umax::Real; kw...)
|
||||
|
||||
# one line, y = f(x)... can swap x and f
|
||||
plot(x::AVec, f::Function; kw...)
|
||||
|
||||
# multiple lines, yᵢⱼ = f(xᵢⱼ)... can swap f and x
|
||||
plot(x::AMat, f::Function; kw...)
|
||||
|
||||
# multiple lines, yᵢⱼ = fⱼ(xᵢ)
|
||||
plot(x::AVec, fs::AVec{Function}; kw...)
|
||||
|
||||
# multiple lines, each with x = 1:length(y[i])
|
||||
plot(y::AVec{AVec}; kw...)
|
||||
|
||||
# multiple lines, will assert length(x) == length(y[i])
|
||||
plot(x::AVec, y::AVec{AVec}; kw...)
|
||||
|
||||
# multiple lines, will assert length(x[i]) == length(y[i])
|
||||
plot(x::AVec{AVec}, y::AVec{AVec}; kw...)
|
||||
|
||||
# n lines, all empty (for updating plots)
|
||||
plot(n::Integer; kw...)
|
||||
|
||||
# TODO: DataFrames, categorical values
|
||||
```
|
||||
|
||||
[TODO] You can swap out `plot` for `subplot`. Each line will go into a separate plot. Use the layout keyword:
|
||||
With `subplot`, create multiple plots at once, with flexible layout options:
|
||||
|
||||
```julia
|
||||
y = rand(100,3)
|
||||
subplot(y; n = 3) # create an automatic grid, and let it figure out the shape
|
||||
subplot(y; n = 3, nr = 1) # create an automatic grid, but fix the number of rows
|
||||
subplot(y; n = 3, nc = 1) # create an automatic grid, but fix the number of columns
|
||||
subplot(y; layout = [1, 2]) # explicit layout. Lists the number of plots in each row
|
||||
```
|
||||
y = rand(100,3)
|
||||
subplot(y; layout=(2,2), kw...) # creates 3 lines going into 3 separate plots, laid out on a 2x2 grid (last row is filled with plot #3)
|
||||
subplot(y; layout=(1,3), kw...) # again 3 plots, all in the same row
|
||||
subplot(y; layout=[1,[2,3]]) # pass a nested Array to fully specify the layout. here the first plot will take up the first row,
|
||||
# and the others will share the second row
|
||||
```
|
||||
|
||||
__Tip__: You can call `subplot!(args...; kw...)` to add to an existing subplot.
|
||||
|
||||
__Tip__: Calling `subplot!` on a `Plot` object, or `plot!` on a `Subplot` object will throw an error.
|
||||
|
||||
Shorthands:
|
||||
|
||||
```
|
||||
scatter(args...; kw...) = plot(args...; kw..., linetype = :none, marker = :hexagon)
|
||||
scatter!(args...; kw...) = plot!(args...; kw..., linetype = :none, marker = :hexagon)
|
||||
bar(args...; kw...) = plot(args...; kw..., linetype = :bar)
|
||||
bar!(args...; kw...) = plot!(args...; kw..., linetype = :bar)
|
||||
histogram(args...; kw...) = plot(args...; kw..., linetype = :hist)
|
||||
histogram!(args...; kw...) = plot!(args...; kw..., linetype = :hist)
|
||||
heatmap(args...; kw...) = plot(args...; kw..., linetype = :heatmap)
|
||||
heatmap!(args...; kw...) = plot!(args...; kw..., linetype = :heatmap)
|
||||
```julia
|
||||
scatter(args...; kw...) = plot(args...; kw..., linetype = :none, marker = :hexagon)
|
||||
scatter!(args...; kw...) = plot!(args...; kw..., linetype = :none, marker = :hexagon)
|
||||
bar(args...; kw...) = plot(args...; kw..., linetype = :bar)
|
||||
bar!(args...; kw...) = plot!(args...; kw..., linetype = :bar)
|
||||
histogram(args...; kw...) = plot(args...; kw..., linetype = :hist)
|
||||
histogram!(args...; kw...) = plot!(args...; kw..., linetype = :hist)
|
||||
heatmap(args...; kw...) = plot(args...; kw..., linetype = :heatmap)
|
||||
heatmap!(args...; kw...) = plot!(args...; kw..., linetype = :heatmap)
|
||||
```
|
||||
|
||||
Some keyword arguments you can set:
|
||||
|
||||
```
|
||||
axis # :left or :right
|
||||
color # can be a string ("red") or a symbol (:red) or a ColorsTypes.jl Colorant (RGB(1,0,0)) or :auto (which lets the package pick)
|
||||
label # string or symbol, applies to that line, may go in a legend
|
||||
width # width of a line
|
||||
linetype # :line, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hexbin, :hist, :bar
|
||||
linestyle # :solid, :dash, :dot, :dashdot, :dashdotdot
|
||||
marker # :none, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :star2, :hexagon
|
||||
markercolor # same choices as `color`, or :match will set the color to be the same as `color`
|
||||
markersize # size of the marker
|
||||
nbins # number of bins for heatmap/hexbin and histograms
|
||||
heatmap_c # color cutoffs for Qwt heatmaps
|
||||
fillto # fillto value for area plots
|
||||
title # string or symbol, title of the plot
|
||||
xlabel # string or symbol, label on the bottom (x) axis
|
||||
ylabel # string or symbol, label on the left (y) axis
|
||||
yrightlabel # string or symbol, label on the right (y) axis
|
||||
reg # true or false, add a regression line for each line
|
||||
size # (Int,Int), resize the enclosing window
|
||||
pos # (Int,Int), move the enclosing window to this position
|
||||
windowtitle # string or symbol, set the title of the enclosing windowtitle
|
||||
screen # Integer, move enclosing window to this screen number (for multiscreen desktops)
|
||||
show # true or false, show the plot (in case you don't want the window to pop up right away)
|
||||
axis # :left or :right
|
||||
color # can be a string ("red") or a symbol (:red) or a ColorsTypes.jl
|
||||
# Colorant (RGB(1,0,0)) or :auto (which lets the package pick)
|
||||
label # string or symbol, applies to that line, may go in a legend
|
||||
width # width of a line
|
||||
linetype # :line, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hexbin, :hist, :bar
|
||||
linestyle # :solid, :dash, :dot, :dashdot, :dashdotdot
|
||||
marker # :none, :ellipse, :rect, :diamond, :utriangle, :dtriangle,
|
||||
# :cross, :xcross, :star1, :star2, :hexagon
|
||||
markercolor # same choices as `color`, or :match will set the color to be the same as `color`
|
||||
markersize # size of the marker
|
||||
nbins # number of bins for heatmap/hexbin and histograms
|
||||
heatmap_c # color cutoffs for Qwt heatmaps
|
||||
fillto # fillto value for area plots
|
||||
title # string or symbol, title of the plot
|
||||
xlabel # string or symbol, label on the bottom (x) axis
|
||||
ylabel # string or symbol, label on the left (y) axis
|
||||
yrightlabel # string or symbol, label on the right (y) axis
|
||||
reg # true or false, add a regression line for each line
|
||||
size # (Int,Int), resize the enclosing window
|
||||
pos # (Int,Int), move the enclosing window to this position
|
||||
windowtitle # string or symbol, set the title of the enclosing windowtitle
|
||||
screen # Integer, move enclosing window to this screen number (for multiscreen desktops)
|
||||
show # true or false, show the plot (in case you don't want the window to pop up right away)
|
||||
```
|
||||
|
||||
Note that not every backend supports all options.
|
||||
|
||||
If you don't include a keyword argument, these are the defaults:
|
||||
|
||||
```
|
||||
axis = :left
|
||||
color = :auto
|
||||
label = automatically generated (y1, y2, ...., or y1 (R), y2 (R) for the right axis)
|
||||
width = 1
|
||||
linetype = :line
|
||||
linestype = :solid
|
||||
marker = :none
|
||||
markercolor = :match
|
||||
markersize = 3
|
||||
nbins = 100
|
||||
heatmap_c = (0.15, 0.5)
|
||||
fillto = nothing
|
||||
title = ""
|
||||
xlabel = ""
|
||||
ylabel = ""
|
||||
yrightlabel = ""
|
||||
reg = false
|
||||
size = (800,600)
|
||||
pos = (0,0)
|
||||
windowtitle = ""
|
||||
screen = 1
|
||||
show = true
|
||||
axis = :left
|
||||
color = :auto
|
||||
label = automatically generated (y1, y2, ...., or y1 (R), y2 (R) for the right axis)
|
||||
width = 1
|
||||
linetype = :line
|
||||
linestype = :solid
|
||||
marker = :none
|
||||
markercolor = :match
|
||||
markersize = 3
|
||||
nbins = 100
|
||||
heatmap_c = (0.15, 0.5)
|
||||
fillto = nothing
|
||||
title = ""
|
||||
xlabel = ""
|
||||
ylabel = ""
|
||||
yrightlabel = ""
|
||||
reg = false
|
||||
size = (800,600)
|
||||
pos = (0,0)
|
||||
windowtitle = ""
|
||||
screen = 1
|
||||
show = true
|
||||
```
|
||||
|
||||
When plotting multiple lines, you can give every line the same trait by using the singular, or add an "s" to pluralize.
|
||||
(yes I know it's not gramatically correct, but it's easy to use and implement)
|
||||
__Tip__: You can see the default value for a given argument with `plotDefault(arg::Symbol)`, and set the default value with `plotDefault!(arg::Symbol, value)`
|
||||
|
||||
```
|
||||
plot(rand(100,2); colors = [:red, RGB(.5,.5,0)], axiss = [:left, :right], width = 5) # note the width=5 is applied to both lines
|
||||
__Tip__: When plotting multiple lines, you can give every line the same trait by using the singular, or add an "s" to pluralize.
|
||||
(yes I know it's not gramatically correct, but it's easy to use and implement)
|
||||
|
||||
```julia
|
||||
# Note: The same width is applied to both lines, whereas
|
||||
# each line gets different color and axis.
|
||||
plot(rand(100,2); colors = [:red, RGB(.5,.5,0)],
|
||||
axiss = [:left, :right],
|
||||
width = 5)
|
||||
```
|
||||
|
||||
# TODO
|
||||
|
||||
- [x] Plot vectors/matrices/functions
|
||||
- [ ] Plot DataFrames
|
||||
- [ ] Subplots
|
||||
- [ ] Histograms
|
||||
- [ ] Scales
|
||||
- [ ] Categorical Inputs (strings, etc... for hist, bar? or can split one series into multiple?)
|
||||
- [ ] Custom markers
|
||||
- [ ] Special plots (boxplot, ohlc?)
|
||||
- [x] Subplots
|
||||
- [x] Histograms
|
||||
- [ ] 3D plotting
|
||||
- [ ] Scenes/Drawing
|
||||
- [ ] Graphs
|
||||
@@ -207,18 +252,15 @@ When plotting multiple lines, you can give every line the same trait by using th
|
||||
- [ ] TextPlots.jl
|
||||
- [ ] ASCIIPlots.jl
|
||||
- [ ] Sparklines.jl
|
||||
- [ ] UnicodePlots.jl
|
||||
- [x] UnicodePlots.jl
|
||||
- [ ] Hinton.jl
|
||||
- [ ] ImageTerm.jl
|
||||
- [ ] GraphViz.jl
|
||||
- [ ] TikzGraphs.jl
|
||||
- [ ] GraphLayout.jl
|
||||
|
||||
# Backends
|
||||
# More information on backends (both supported and unsupported)
|
||||
|
||||
See the wiki at: https://github.com/JuliaPlot/juliaplot_docs/wiki
|
||||
|
||||
# Author
|
||||
|
||||
Thomas Breloff (@tbreloff)
|
||||
|
||||
|
||||
@@ -23,8 +23,14 @@ const examples = PlotExample[
|
||||
"A simple line plot of the 3 columns.",
|
||||
[:(plot(rand(100,3)))]),
|
||||
PlotExample("Functions",
|
||||
"Plot multiple functions",
|
||||
"Plot multiple functions.",
|
||||
[:(plot(0:0.01:4π, [sin,cos]))]),
|
||||
PlotExample("",
|
||||
"You can also call it with plot(f, xmin, xmax).",
|
||||
[:(plot([sin,cos], 0, 4π))]),
|
||||
PlotExample("",
|
||||
"Or make a parametric plot with plot(fx, fy, umin, umax).",
|
||||
[:(plot(sin, x->sin(2x), 0, 2π))]),
|
||||
PlotExample("Global",
|
||||
"Change the guides/background without a separate call.",
|
||||
[:(plot(rand(10); title="TITLE", xlabel="XLABEL", ylabel="YLABEL", background_color = RGB(0.5,0.5,0.5)))]),
|
||||
@@ -45,7 +51,7 @@ const examples = PlotExample[
|
||||
[:(heatmap(randn(10000),randn(10000); nbins=200))]),
|
||||
PlotExample("Lots of line types",
|
||||
"Options: (:line, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hexbin, :hist, :bar) \nNote: some may not work with all backends",
|
||||
[:(plot(rand(20,4); linetypes=[:line, :step, :sticks, :dots]))]),
|
||||
[:(plot(rand(20,4); linetypes=[:line, :step, :sticks, :dots], labels=["line","step","sticks","dots"]))]),
|
||||
PlotExample("Bar",
|
||||
"x is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)",
|
||||
[:(bar(randn(1000)))]),
|
||||
@@ -78,6 +84,11 @@ function generate_markdown(pkgname::Symbol)
|
||||
plotter!(pkgname)
|
||||
plotDefault!(:show, false)
|
||||
|
||||
# mkdir if necessary
|
||||
try
|
||||
mkdir("$IMGDIR/$pkgname")
|
||||
end
|
||||
|
||||
# open the markdown file
|
||||
md = open("$DOCDIR/$(pkgname)_examples.md", "w")
|
||||
|
||||
@@ -90,13 +101,13 @@ function generate_markdown(pkgname::Symbol)
|
||||
|
||||
# save the png
|
||||
imgname = "$(pkgname)_example_$i.png"
|
||||
savepng("$IMGDIR/$imgname")
|
||||
savepng("$IMGDIR/$pkgname/$imgname")
|
||||
|
||||
# write out the header, description, code block, and image link
|
||||
write(md, "### $(example.header)\n\n")
|
||||
write(md, "$(example.desc)\n\n")
|
||||
write(md, "```julia\n$(join(map(string, example.exprs), "\n"))\n```\n\n")
|
||||
write(md, "\n\n")
|
||||
write(md, "\n\n")
|
||||
|
||||
catch ex
|
||||
# TODO: put error info into markdown?
|
||||
@@ -111,7 +122,10 @@ function generate_markdown(pkgname::Symbol)
|
||||
end
|
||||
|
||||
# run it!
|
||||
map(generate_markdown, (:qwt, :gadfly))
|
||||
# note: generate separately so it's easy to comment out
|
||||
generate_markdown(:qwt)
|
||||
generate_markdown(:gadfly)
|
||||
generate_markdown(:unicodeplots)
|
||||
|
||||
|
||||
end # module
|
||||
|
||||
@@ -6,17 +6,39 @@ A simple line plot of the 3 columns.
|
||||
plot(rand(100,3))
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Functions
|
||||
|
||||
Plot multiple functions
|
||||
Plot multiple functions.
|
||||
|
||||
```julia
|
||||
plot(0:0.01:4π,[sin,cos])
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
###
|
||||
|
||||
You can also call it with plot(f, xmin, xmax).
|
||||
|
||||
```julia
|
||||
plot([sin,cos],0,4π)
|
||||
```
|
||||
|
||||

|
||||
|
||||
###
|
||||
|
||||
Or make a parametric plot with plot(fx, fy, umin, umax).
|
||||
|
||||
```julia
|
||||
plot(sin,(x->begin # /Users/tom/.julia/v0.4/Plots/docs/example_generation.jl, line 33:
|
||||
sin(2x)
|
||||
end),0,2π)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Global
|
||||
|
||||
@@ -26,7 +48,7 @@ Change the guides/background without a separate call.
|
||||
plot(rand(10); title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.5,0.5,0.5))
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Two-axis
|
||||
|
||||
@@ -38,7 +60,7 @@ Note: This is only supported with Qwt right now
|
||||
plot(Vector[randn(100),randn(100) * 100]; axiss=[:left,:right])
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Vectors w/ pluralized args
|
||||
|
||||
@@ -48,7 +70,7 @@ Plot multiple series with different numbers of points. Mix arguments that apply
|
||||
plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,colors=[:red,:blue])
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Build plot in pieces
|
||||
|
||||
@@ -58,7 +80,7 @@ Start with a base plot...
|
||||
plot(rand(100) / 3; reg=true,fillto=0)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
###
|
||||
|
||||
@@ -68,7 +90,7 @@ and add to it later.
|
||||
scatter!(rand(100); markersize=6,color=:blue)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Heatmaps
|
||||
|
||||
@@ -78,7 +100,7 @@ scatter!(rand(100); markersize=6,color=:blue)
|
||||
heatmap(randn(10000),randn(10000); nbins=200)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Lots of line types
|
||||
|
||||
@@ -86,10 +108,10 @@ Options: (:line, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hexbin,
|
||||
Note: some may not work with all backends
|
||||
|
||||
```julia
|
||||
plot(rand(20,4); linetypes=[:line,:step,:sticks,:dots])
|
||||
plot(rand(20,4); linetypes=[:line,:step,:sticks,:dots],labels=["line","step","sticks","dots"])
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Bar
|
||||
|
||||
@@ -99,7 +121,7 @@ x is the midpoint of the bar. (todo: allow passing of edges instead of midpoints
|
||||
bar(randn(1000))
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Histogram
|
||||
|
||||
@@ -109,7 +131,7 @@ note: fillto isn't supported on all backends
|
||||
histogram(randn(1000); nbins=50,fillto=20)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Subplots
|
||||
|
||||
@@ -124,7 +146,7 @@ histogram(randn(1000); nbins=50,fillto=20)
|
||||
subplot(randn(100,5); layout=[1,1,3],linetypes=[:line,:hist,:dots,:step,:bar],nbins=10,legend=false)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Adding to subplots
|
||||
|
||||
@@ -134,7 +156,7 @@ Note here the automatic grid layout, as well as the order in which new series ar
|
||||
subplot(randn(100,5); n=4)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
###
|
||||
|
||||
@@ -144,5 +166,5 @@ subplot(randn(100,5); n=4)
|
||||
subplot!(randn(100,3))
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
@@ -6,17 +6,39 @@ A simple line plot of the 3 columns.
|
||||
plot(rand(100,3))
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Functions
|
||||
|
||||
Plot multiple functions
|
||||
Plot multiple functions.
|
||||
|
||||
```julia
|
||||
plot(0:0.01:4π,[sin,cos])
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
###
|
||||
|
||||
You can also call it with plot(f, xmin, xmax).
|
||||
|
||||
```julia
|
||||
plot([sin,cos],0,4π)
|
||||
```
|
||||
|
||||

|
||||
|
||||
###
|
||||
|
||||
Or make a parametric plot with plot(fx, fy, umin, umax).
|
||||
|
||||
```julia
|
||||
plot(sin,(x->begin # /Users/tom/.julia/v0.4/Plots/docs/example_generation.jl, line 33:
|
||||
sin(2x)
|
||||
end),0,2π)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Global
|
||||
|
||||
@@ -26,7 +48,7 @@ Change the guides/background without a separate call.
|
||||
plot(rand(10); title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.5,0.5,0.5))
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Two-axis
|
||||
|
||||
@@ -38,7 +60,7 @@ Note: This is only supported with Qwt right now
|
||||
plot(Vector[randn(100),randn(100) * 100]; axiss=[:left,:right])
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Vectors w/ pluralized args
|
||||
|
||||
@@ -48,7 +70,7 @@ Plot multiple series with different numbers of points. Mix arguments that apply
|
||||
plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,colors=[:red,:blue])
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Build plot in pieces
|
||||
|
||||
@@ -58,7 +80,7 @@ Start with a base plot...
|
||||
plot(rand(100) / 3; reg=true,fillto=0)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
###
|
||||
|
||||
@@ -68,7 +90,7 @@ and add to it later.
|
||||
scatter!(rand(100); markersize=6,color=:blue)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Heatmaps
|
||||
|
||||
@@ -78,7 +100,7 @@ scatter!(rand(100); markersize=6,color=:blue)
|
||||
heatmap(randn(10000),randn(10000); nbins=200)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Lots of line types
|
||||
|
||||
@@ -86,10 +108,10 @@ Options: (:line, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hexbin,
|
||||
Note: some may not work with all backends
|
||||
|
||||
```julia
|
||||
plot(rand(20,4); linetypes=[:line,:step,:sticks,:dots])
|
||||
plot(rand(20,4); linetypes=[:line,:step,:sticks,:dots],labels=["line","step","sticks","dots"])
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Bar
|
||||
|
||||
@@ -99,7 +121,7 @@ x is the midpoint of the bar. (todo: allow passing of edges instead of midpoints
|
||||
bar(randn(1000))
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Histogram
|
||||
|
||||
@@ -109,7 +131,7 @@ note: fillto isn't supported on all backends
|
||||
histogram(randn(1000); nbins=50,fillto=20)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Subplots
|
||||
|
||||
@@ -124,7 +146,7 @@ histogram(randn(1000); nbins=50,fillto=20)
|
||||
subplot(randn(100,5); layout=[1,1,3],linetypes=[:line,:hist,:dots,:step,:bar],nbins=10,legend=false)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
### Adding to subplots
|
||||
|
||||
@@ -134,7 +156,7 @@ Note here the automatic grid layout, as well as the order in which new series ar
|
||||
subplot(randn(100,5); n=4)
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
###
|
||||
|
||||
@@ -144,5 +166,5 @@ subplot(randn(100,5); n=4)
|
||||
subplot!(randn(100,3))
|
||||
```
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
### Lines
|
||||
|
||||
A simple line plot of the 3 columns.
|
||||
|
||||
```julia
|
||||
plot(rand(100,3))
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Functions
|
||||
|
||||
Plot multiple functions.
|
||||
|
||||
```julia
|
||||
plot(0:0.01:4π,[sin,cos])
|
||||
```
|
||||
|
||||

|
||||
|
||||
###
|
||||
|
||||
You can also call it with plot(f, xmin, xmax).
|
||||
|
||||
```julia
|
||||
plot([sin,cos],0,4π)
|
||||
```
|
||||
|
||||

|
||||
|
||||
###
|
||||
|
||||
Or make a parametric plot with plot(fx, fy, umin, umax).
|
||||
|
||||
```julia
|
||||
plot(sin,(x->begin # /Users/tom/.julia/v0.4/Plots/docs/example_generation.jl, line 33:
|
||||
sin(2x)
|
||||
end),0,2π)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Global
|
||||
|
||||
Change the guides/background without a separate call.
|
||||
|
||||
```julia
|
||||
plot(rand(10); title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.5,0.5,0.5))
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Two-axis
|
||||
|
||||
Use the `axis` or `axiss` arguments.
|
||||
|
||||
Note: This is only supported with Qwt right now
|
||||
|
||||
```julia
|
||||
plot(Vector[randn(100),randn(100) * 100]; axiss=[:left,:right])
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Vectors w/ pluralized args
|
||||
|
||||
Plot multiple series with different numbers of points. Mix arguments that apply to all series (singular... see `marker`) with arguments unique to each series (pluralized... see `colors`).
|
||||
|
||||
```julia
|
||||
plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,colors=[:red,:blue])
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Build plot in pieces
|
||||
|
||||
Start with a base plot...
|
||||
|
||||
```julia
|
||||
plot(rand(100) / 3; reg=true,fillto=0)
|
||||
```
|
||||
|
||||

|
||||
|
||||
###
|
||||
|
||||
and add to it later.
|
||||
|
||||
```julia
|
||||
scatter!(rand(100); markersize=6,color=:blue)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Lots of line types
|
||||
|
||||
Options: (:line, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hexbin, :hist, :bar)
|
||||
Note: some may not work with all backends
|
||||
|
||||
```julia
|
||||
plot(rand(20,4); linetypes=[:line,:step,:sticks,:dots],labels=["line","step","sticks","dots"])
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Bar
|
||||
|
||||
x is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)
|
||||
|
||||
```julia
|
||||
bar(randn(1000))
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Histogram
|
||||
|
||||
note: fillto isn't supported on all backends
|
||||
|
||||
```julia
|
||||
histogram(randn(1000); nbins=50,fillto=20)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Subplots
|
||||
|
||||
subplot and subplot! are distinct commands which create many plots and add series to them in a circular fashion.
|
||||
You can define the layout with keyword params... either set the number of plots `n` (and optionally number of rows `nr` or
|
||||
number of columns `nc`), or you can set the layout directly with `layout`.
|
||||
|
||||
Note: Gadfly is not very friendly here, and although you can create a plot and save a PNG, I haven't been able to actually display it.
|
||||
|
||||
|
||||
```julia
|
||||
subplot(randn(100,5); layout=[1,1,3],linetypes=[:line,:hist,:dots,:step,:bar],nbins=10,legend=false)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Adding to subplots
|
||||
|
||||
Note here the automatic grid layout, as well as the order in which new series are added to the plots.
|
||||
|
||||
```julia
|
||||
subplot(randn(100,5); n=4)
|
||||
```
|
||||
|
||||

|
||||
|
||||
###
|
||||
|
||||
|
||||
|
||||
```julia
|
||||
subplot!(randn(100,3))
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 103 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 113 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 142 KiB |
|
After Width: | Height: | Size: 89 KiB |
|
After Width: | Height: | Size: 101 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 59 KiB |
|
After Width: | Height: | Size: 61 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
After Width: | Height: | Size: 74 KiB |
|
After Width: | Height: | Size: 55 KiB |
@@ -27,7 +27,12 @@ export
|
||||
histogram!,
|
||||
heatmap!,
|
||||
|
||||
savepng
|
||||
savepng,
|
||||
|
||||
backends,
|
||||
qwt!,
|
||||
gadfly!,
|
||||
unicodeplots!
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
@@ -39,15 +44,7 @@ const IMG_DIR = Pkg.dir("Plots") * "/img/"
|
||||
|
||||
include("types.jl")
|
||||
include("utils.jl")
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
include("qwt.jl")
|
||||
include("gadfly.jl")
|
||||
include("plotter.jl")
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
include("args.jl")
|
||||
include("plot.jl")
|
||||
include("subplot.jl")
|
||||
|
||||
@@ -96,8 +96,6 @@ function getPlotKeywordArgs(kw, idx::Int, n::Int)
|
||||
# fill in d with either 1) plural value, 2) value, 3) default
|
||||
for k in keys(PLOT_DEFAULTS)
|
||||
plural = makeplural(k)
|
||||
# if haskey(d, plural)
|
||||
# d[k] = d[plural][idx]
|
||||
if !haskey(d, k)
|
||||
if n == 0 || k != :size
|
||||
d[k] = haskey(d, plural) ? d[plural][idx] : PLOT_DEFAULTS[k]
|
||||
@@ -125,7 +123,11 @@ function getPlotKeywordArgs(kw, idx::Int, n::Int)
|
||||
|
||||
# set label
|
||||
label = d[:label]
|
||||
d[:label] = string(label == "AUTO" ? "y_$n" : label, d[:axis] == :left ? "" : " (R)")
|
||||
label = (label == "AUTO" ? "y_$n" : label)
|
||||
if d[:axis] == :right && length(label) >= 4 && label[end-3:end] != " (R)"
|
||||
label = string(label, " (R)")
|
||||
end
|
||||
d[:label] = label
|
||||
end
|
||||
|
||||
d
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
immutable GadflyPackage <: PlottingPackage end
|
||||
|
||||
gadfly!() = plotter!(:gadfly)
|
||||
|
||||
|
||||
# create a blank Gadfly.Plot object
|
||||
function plot(pkg::GadflyPackage; kw...)
|
||||
@@ -27,7 +29,7 @@ function plot(pkg::GadflyPackage; kw...)
|
||||
|
||||
plt.theme = Gadfly.Theme(background_color = (haskey(d, :background_color) ? d[:background_color] : colorant"white"))
|
||||
|
||||
Plot(plt, pkg, 0)
|
||||
Plot(plt, pkg, 0, d, Dict[])
|
||||
end
|
||||
|
||||
function getGeomFromLineType(linetype::Symbol, nbins::Int)
|
||||
@@ -95,6 +97,9 @@ function plot!(::GadflyPackage, plt::Plot; kw...)
|
||||
warn("Gadly only supports one y axis")
|
||||
end
|
||||
|
||||
# save the kw args
|
||||
push!(plt.seriesargs, d)
|
||||
|
||||
# add the layer to the Gadfly.Plot
|
||||
prepend!(plt.o.layers, Gadfly.layer(unique(gfargs)...; x = x, y = d[:y]))
|
||||
plt
|
||||
@@ -115,9 +120,7 @@ end
|
||||
|
||||
# -------------------------------
|
||||
|
||||
# # create the underlying object (each backend will do this differently)
|
||||
# o = buildSubplotObject(plts, pkg, layout)
|
||||
|
||||
# create the underlying object (each backend will do this differently)
|
||||
function buildSubplotObject!(::GadflyPackage, subplt::Subplot)
|
||||
i = 0
|
||||
rows = []
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
immutable QwtPackage <: PlottingPackage end
|
||||
|
||||
qwt!() = plotter!(:qwt)
|
||||
|
||||
# -------------------------------
|
||||
|
||||
function adjustQwtKeywords(iscreating::Bool; kw...)
|
||||
@@ -24,13 +26,16 @@ end
|
||||
|
||||
function plot(pkg::QwtPackage; kw...)
|
||||
kw = adjustQwtKeywords(true; kw...)
|
||||
plt = Plot(Qwt.plot(zeros(0,0); kw..., show=false), pkg, 0)
|
||||
o = Qwt.plot(zeros(0,0); kw..., show=false)
|
||||
plt = Plot(o, pkg, 0, kw, Dict[])
|
||||
plt
|
||||
end
|
||||
|
||||
function plot!(::QwtPackage, plt::Plot; kw...)
|
||||
kw = adjustQwtKeywords(false; kw...)
|
||||
Qwt.oplot(plt.o; kw...)
|
||||
push!(plt.seriesargs, kw)
|
||||
plt
|
||||
end
|
||||
|
||||
function Base.display(::QwtPackage, plt::Plot)
|
||||
@@ -44,9 +49,7 @@ savepng(::QwtPackage, plt::PlottingObject, fn::String, args...) = Qwt.savepng(pl
|
||||
|
||||
# -------------------------------
|
||||
|
||||
# # create the underlying object (each backend will do this differently)
|
||||
# o = buildSubplotObject(plts, pkg, layout)
|
||||
|
||||
# create the underlying object (each backend will do this differently)
|
||||
function buildSubplotObject!(::QwtPackage, subplt::Subplot)
|
||||
i = 0
|
||||
rows = []
|
||||
@@ -0,0 +1,161 @@
|
||||
|
||||
# https://github.com/Evizero/UnicodePlots.jl
|
||||
|
||||
immutable UnicodePlotsPackage <: PlottingPackage end
|
||||
|
||||
unicodeplots!() = plotter!(:unicodeplots)
|
||||
|
||||
# -------------------------------
|
||||
|
||||
function expandLimits!(lims, x)
|
||||
e1, e2 = extrema(x)
|
||||
lims[1] = min(lims[1], e1)
|
||||
lims[2] = max(lims[2], e2)
|
||||
nothing
|
||||
end
|
||||
|
||||
|
||||
# do all the magic here... build it all at once, since we need to know about all the series at the very beginning
|
||||
function rebuildUnicodePlot!(plt::Plot)
|
||||
|
||||
# figure out the plotting area xlim = [xmin, xmax] and ylim = [ymin, ymax]
|
||||
sargs = plt.seriesargs
|
||||
xlim = [Inf, -Inf]
|
||||
ylim = [Inf, -Inf]
|
||||
for d in sargs
|
||||
expandLimits!(xlim, d[:x])
|
||||
expandLimits!(ylim, d[:y])
|
||||
end
|
||||
x = Float64[xlim[1]]
|
||||
y = Float64[ylim[1]]
|
||||
|
||||
# create a plot window with xlim/ylim set, but the X/Y vectors are outside the bounds
|
||||
iargs = plt.initargs
|
||||
width, height = iargs[:size]
|
||||
o = UnicodePlots.createPlotWindow(x, y; width = width,
|
||||
height = height,
|
||||
title = iargs[:title],
|
||||
# labels = iargs[:legend],
|
||||
xlim = xlim,
|
||||
ylim = ylim)
|
||||
|
||||
# set the axis labels
|
||||
UnicodePlots.xlabel!(o, iargs[:xlabel])
|
||||
UnicodePlots.ylabel!(o, iargs[:ylabel])
|
||||
|
||||
# now use the ! functions to add to the plot
|
||||
for d in sargs
|
||||
addUnicodeSeries!(o, d, iargs[:legend])
|
||||
end
|
||||
|
||||
# save the object
|
||||
plt.o = o
|
||||
end
|
||||
|
||||
|
||||
# add a single series
|
||||
function addUnicodeSeries!(o, d::Dict, addlegend::Bool)
|
||||
|
||||
# get the function, or special handling for step/bar/hist
|
||||
lt = d[:linetype]
|
||||
stepstyle = :post
|
||||
if lt == :line
|
||||
func = UnicodePlots.lineplot!
|
||||
elseif lt == :dots || d[:marker] != :none
|
||||
func = UnicodePlots.scatterplot!
|
||||
elseif lt == :step
|
||||
func = UnicodePlots.stairs!
|
||||
elseif lt == :stepinverted
|
||||
func = UnicodePlots.stairs!
|
||||
stepstyle = :pre
|
||||
else
|
||||
error("Linestyle $lt not supported by UnicodePlots")
|
||||
end
|
||||
|
||||
# get the series data and label
|
||||
x, y = [collect(float(d[s])) for s in (:x, :y)]
|
||||
label = addlegend ? d[:label] : ""
|
||||
|
||||
# if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide
|
||||
color = d[:color] in UnicodePlots.autoColors ? d[:color] : :auto
|
||||
|
||||
# add the series
|
||||
func(o, x, y; color = color, name = label, style = stepstyle)
|
||||
end
|
||||
|
||||
|
||||
# -------------------------------
|
||||
|
||||
|
||||
function plot(pkg::UnicodePlotsPackage; kw...)
|
||||
plt = Plot(nothing, pkg, 0, Dict(kw), Dict[])
|
||||
|
||||
# do we want to give a new default size?
|
||||
if !haskey(plt.initargs, :size) || plt.initargs[:size] == PLOT_DEFAULTS[:size]
|
||||
plt.initargs[:size] = (60,20)
|
||||
end
|
||||
|
||||
plt
|
||||
end
|
||||
|
||||
function plot!(::UnicodePlotsPackage, plt::Plot; kw...)
|
||||
d = Dict(kw)
|
||||
if d[:linetype] in (:sticks, :bar)
|
||||
d = barHack(; d...)
|
||||
elseif d[:linetype] == :hist
|
||||
d = barHack(; histogramHack(; d...)...)
|
||||
end
|
||||
push!(plt.seriesargs, d)
|
||||
plt
|
||||
end
|
||||
|
||||
function Base.display(::UnicodePlotsPackage, plt::Plot)
|
||||
rebuildUnicodePlot!(plt)
|
||||
show(plt.o)
|
||||
end
|
||||
|
||||
# -------------------------------
|
||||
|
||||
function savepng(::UnicodePlotsPackage, plt::PlottingObject, fn::String, args...)
|
||||
|
||||
# make some whitespace and show the plot
|
||||
println("\n\n\n\n\n\n")
|
||||
display(plt)
|
||||
|
||||
@osx_only begin
|
||||
# BEGIN HACK
|
||||
|
||||
# wait while the plot gets drawn
|
||||
sleep(0.5)
|
||||
|
||||
# use osx screen capture when my terminal is maximized and cursor starts at the bottom (I know, right?)
|
||||
# TODO: compute size of plot to adjust these numbers (or maybe implement something good??)
|
||||
run(`screencapture -R50,600,700,420 $fn`)
|
||||
|
||||
# # some other attempts:
|
||||
# run(`screencapture -w $fn`)
|
||||
# using PyCall
|
||||
# @pyimport pyscreenshot as pss
|
||||
|
||||
# END HACK (phew)
|
||||
return
|
||||
end
|
||||
|
||||
error("Can only savepng on osx with UnicodePlots (though even then I wouldn't do it)")
|
||||
end
|
||||
|
||||
# -------------------------------
|
||||
|
||||
# we don't do very much for subplots... just stack them vertically
|
||||
|
||||
function buildSubplotObject!(::UnicodePlotsPackage, subplt::Subplot)
|
||||
nothing
|
||||
end
|
||||
|
||||
|
||||
function Base.display(::UnicodePlotsPackage, subplt::Subplot)
|
||||
for plt in subplt.plts
|
||||
display(UnicodePlotsPackage(), plt)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -104,14 +104,6 @@ end
|
||||
# this adds to a specific plot... most plot commands will flow through here
|
||||
function plot!(plt::Plot, args...; kw...)
|
||||
|
||||
# # increment n if we're going directly to the package's plot method
|
||||
# if length(args) == 0
|
||||
# plt.n += 1
|
||||
# end
|
||||
|
||||
# plot!(plt.plotter, plt, args...; kw...)
|
||||
|
||||
|
||||
kwList = createKWargsList(plt, args...; kw...)
|
||||
for (i,d) in enumerate(kwList)
|
||||
plt.n += 1
|
||||
@@ -150,6 +142,12 @@ function createKWargsList(plt::PlottingObject; kw...)
|
||||
[getPlotKeywordArgs(d, 1, plt.n + 1)]
|
||||
end
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Arrays of numbers
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# create one series where y is vectors of numbers
|
||||
function createKWargsList{T<:Real}(plt::PlottingObject, y::AVec{T}; kw...)
|
||||
d = getPlotKeywordArgs(kw, 1, plt.n + 1)
|
||||
@@ -208,6 +206,45 @@ function createKWargsList(plt::PlottingObject, x::AMat, y::AMat; kw...)
|
||||
ret
|
||||
end
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Functions
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# create 1 series, y = f(x), x ∈ [xmin, xmax]
|
||||
function createKWargsList(plt::PlottingObject, f::Function, xmin::Real, xmax::Real; kw...)
|
||||
d = getPlotKeywordArgs(kw, 1, plt.n + 1)
|
||||
width = plt.initargs[:size][1]
|
||||
d[:x] = collect(linspace(xmin, xmax, width)) # we don't need more than the width
|
||||
d[:y] = map(f, d[:x])
|
||||
[d]
|
||||
end
|
||||
|
||||
# create m series, yᵢ = fᵢ(x), x ∈ [xmin, xmax]
|
||||
function createKWargsList(plt::PlottingObject, fs::Vector{Function}, xmin::Real, xmax::Real; kw...)
|
||||
m = length(fs)
|
||||
ret = []
|
||||
width = plt.initargs[:size][1]
|
||||
x = collect(linspace(xmin, xmax, width)) # we don't need more than the width
|
||||
for i in 1:m
|
||||
d = getPlotKeywordArgs(kw, i, plt.n + i)
|
||||
d[:x] = x
|
||||
d[:y] = map(fs[i], x)
|
||||
push!(ret, d)
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
# create 1 series, x = fx(u), y = fy(u); u ∈ [umin, umax]
|
||||
function createKWargsList(plt::PlottingObject, fx::Function, fy::Function, umin::Real, umax::Real; kw...)
|
||||
d = getPlotKeywordArgs(kw, 1, plt.n + 1)
|
||||
width = plt.initargs[:size][1]
|
||||
u = collect(linspace(umin, umax, width)) # we don't need more than the width
|
||||
d[:x] = map(fx, u)
|
||||
d[:y] = map(fy, u)
|
||||
[d]
|
||||
end
|
||||
|
||||
# create 1 series, y = f(x)
|
||||
function createKWargsList(plt::PlottingObject, x::AVec, f::Function; kw...)
|
||||
d = getPlotKeywordArgs(kw, 1, plt.n + 1)
|
||||
@@ -215,6 +252,7 @@ function createKWargsList(plt::PlottingObject, x::AVec, f::Function; kw...)
|
||||
d[:y] = map(f, x)
|
||||
[d]
|
||||
end
|
||||
createKWargsList(plt::PlottingObject, f::Function, x::AVec; kw...) = createKWargsList(plt, x, f; kw...)
|
||||
|
||||
# create m series, y = f(x), 1 for each column of x
|
||||
function createKWargsList(plt::PlottingObject, x::AMat, f::Function; kw...)
|
||||
@@ -228,6 +266,13 @@ function createKWargsList(plt::PlottingObject, x::AMat, f::Function; kw...)
|
||||
end
|
||||
ret
|
||||
end
|
||||
createKWargsList(plt::PlottingObject, f::Function, x::AMat; kw...) = createKWargsList(plt, x, f; kw...)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Other combinations... lists of vectors, etc
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# create m series, 1 for each item in y (assumes vectors of something other than numbers... functions? vectors?)
|
||||
function createKWargsList(plt::PlottingObject, y::AVec; kw...)
|
||||
@@ -292,123 +337,3 @@ end
|
||||
|
||||
# -------------------------
|
||||
|
||||
# # most calls should flow through here now... we create a Dict with the keyword args for each series, and plot them
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, args...; kw...)
|
||||
# kwList = createKWargsList(plt, args...; kw...)
|
||||
# for (i,d) in enumerate(kwList)
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; d...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# -------------------------
|
||||
|
||||
# # These methods are various ways to add to an existing plot
|
||||
|
||||
# function plot!{T<:Real}(pkg::PlottingPackage, plt::Plot, y::AVec{T}; kw...)
|
||||
# plt.n += 1
|
||||
# # plot!(pkg, plt; x = 1:length(y), y = y, getPlotKeywordArgs(kw, 1, plt)...)
|
||||
# end
|
||||
|
||||
# function plot!{T<:Real,S<:Real}(pkg::PlottingPackage, plt::Plot, x::AVec{T}, y::AVec{S}; kw...) # one line (will assert length(x) == length(y))
|
||||
# @assert length(x) == length(y)
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x=x, y=y, getPlotKeywordArgs(kw, 1, plt)...)
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, y::AMat; kw...) # multiple lines (one per column of x), all sharing x = 1:size(y,1)
|
||||
# n,m = size(y)
|
||||
# for i in 1:m
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = 1:n, y = y[:,i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, y::AMat; kw...) # multiple lines (one per column of x), all sharing x (will assert length(x) == size(y,1))
|
||||
# n,m = size(y)
|
||||
# for i in 1:m
|
||||
# @assert length(x) == n
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x, y = y[:,i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, x::AMat, y::AMat; kw...) # multiple lines (one per column of x/y... will assert size(x) == size(y))
|
||||
# @assert size(x) == size(y)
|
||||
# for i in 1:size(x,2)
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x[:,i], y = y[:,i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, f::Function; kw...) # one line, y = f(x)
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x, y = map(f,x), getPlotKeywordArgs(kw, 1, plt)...)
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, x::AMat, f::Function; kw...) # multiple lines, yᵢⱼ = f(xᵢⱼ)
|
||||
# for i in 1:size(x,2)
|
||||
# xi = x[:,i]
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = xi, y = map(f, xi), getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# # function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, fs::AVec{Function}; kw...) # multiple lines, yᵢⱼ = fⱼ(xᵢ)
|
||||
# # for i in 1:length(fs)
|
||||
# # plt.n += 1
|
||||
# # plot!(pkg, plt; x = x, y = map(fs[i], x), getPlotKeywordArgs(kw, i, plt)...)
|
||||
# # end
|
||||
# # plt
|
||||
# # end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, y::AVec; kw...) # multiple lines, each with x = 1:length(y[i])
|
||||
# for i in 1:length(y)
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = 1:length(y[i]), y = y[i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!{T<:Real}(pkg::PlottingPackage, plt::Plot, x::AVec{T}, y::AVec; kw...) # multiple lines, will assert length(x) == length(y[i])
|
||||
# for i in 1:length(y)
|
||||
# if typeof(y[i]) <: AbstractVector
|
||||
# @assert length(x) == length(y[i])
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x, y = y[i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# elseif typeof(y[i]) == Function
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x, y = map(y[i], x), getPlotKeywordArgs(kw, 1, plt)...)
|
||||
# end
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, x::AVec, y::AVec; kw...) # multiple lines, will assert length(x[i]) == length(y[i])
|
||||
# @assert length(x) == length(y)
|
||||
# for i in 1:length(x)
|
||||
# @assert length(x[i]) == length(y[i])
|
||||
# plt.n += 1
|
||||
# plot!(pkg, plt; x = x[i], y = y[i], getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# plt
|
||||
# end
|
||||
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot, n::Integer; kw...) # n lines, all empty (for updating plots)
|
||||
# for i in 1:n
|
||||
# plt.n += 1
|
||||
# plot(pkg, plt, x = zeros(0), y = zeros(0), getPlotKeywordArgs(kw, i, plt)...)
|
||||
# end
|
||||
# end
|
||||
|
||||
# -------------------------
|
||||
|
||||
# # this is the core method... add to a plot object using kwargs, with args already converted into kwargs
|
||||
# function plot!(pkg::PlottingPackage, plt::Plot; kw...)
|
||||
# plot!(pl, plt; kw...)
|
||||
# end
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
|
||||
|
||||
include("backends/qwt.jl")
|
||||
include("backends/gadfly.jl")
|
||||
include("backends/unicodeplots.jl")
|
||||
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
plot(pkg::PlottingPackage; kw...) = error("plot($pkg; kw...) is not implemented")
|
||||
plot!(pkg::PlottingPackage, plt::Plot; kw...) = error("plot!($pkg, plt; kw...) is not implemented")
|
||||
Base.display(pkg::PlottingPackage, plt::Plot) = error("display($pkg, plt) is not implemented")
|
||||
@@ -7,15 +15,35 @@ Base.display(pkg::PlottingPackage, plt::Plot) = error("display($pkg, plt) is not
|
||||
# ---------------------------------------------------------
|
||||
|
||||
|
||||
const AVAILABLE_PACKAGES = [:qwt, :gadfly]
|
||||
const AVAILABLE_PACKAGES = [:qwt, :gadfly, :unicodeplots]
|
||||
const INITIALIZED_PACKAGES = Set{Symbol}()
|
||||
backends() = AVAILABLE_PACKAGES
|
||||
|
||||
|
||||
type CurrentPackage
|
||||
sym::Symbol
|
||||
pkg::PlottingPackage
|
||||
end
|
||||
# const CURRENT_PACKAGE = CurrentPackage(:qwt, QwtPackage())
|
||||
const CURRENT_PACKAGE = CurrentPackage(:gadfly, GadflyPackage())
|
||||
|
||||
function pickDefaultBackend()
|
||||
try
|
||||
Pkg.installed("Qwt")
|
||||
return CurrentPackage(:qwt, QwtPackage())
|
||||
end
|
||||
try
|
||||
Pkg.installed("Gadfly")
|
||||
return CurrentPackage(:gadfly, GadflyPackage())
|
||||
end
|
||||
try
|
||||
Pkg.installed("UnicodePlots")
|
||||
return CurrentPackage(:unicodeplots, UnicodePlotsPackage())
|
||||
end
|
||||
warn("You don't have any of the supported backends installed! Chose from ", backends())
|
||||
return CurrentPackage(:gadfly, GadflyPackage())
|
||||
end
|
||||
const CURRENT_PACKAGE = pickDefaultBackend()
|
||||
println("[Plots.jl] Default backend: ", CURRENT_PACKAGE.sym)
|
||||
# const CURRENT_PACKAGE = CurrentPackage(:gadfly, GadflyPackage())
|
||||
|
||||
|
||||
doc"""
|
||||
@@ -27,23 +55,37 @@ function plotter()
|
||||
if !(currentPackageSymbol in INITIALIZED_PACKAGES)
|
||||
|
||||
# initialize
|
||||
print("[Plots.jl] Initializing package: $CURRENT_PACKAGE... ")
|
||||
println("[Plots.jl] Initializing package: ", CURRENT_PACKAGE.sym)
|
||||
if currentPackageSymbol == :qwt
|
||||
@eval import Qwt
|
||||
try
|
||||
@eval import Qwt
|
||||
catch
|
||||
error("Couldn't import Qwt. Install it with: Pkg.clone(\"https://github.com/tbreloff/Qwt.jl.git\")\n (Note: also requires pyqt and pyqwt)")
|
||||
end
|
||||
elseif currentPackageSymbol == :gadfly
|
||||
@eval import Gadfly
|
||||
try
|
||||
@eval import Gadfly
|
||||
catch
|
||||
error("Couldn't import Gadfly. Install it with: Pkg.add(\"Gadfly\")")
|
||||
end
|
||||
elseif currentPackageSymbol == :unicodeplots
|
||||
try
|
||||
@eval import UnicodePlots
|
||||
catch
|
||||
error("Couldn't import UnicodePlots. Install it with: Pkg.add(\"UnicodePlots\")")
|
||||
end
|
||||
else
|
||||
error("Unknown plotter $currentPackageSymbol. Choose from: $AVAILABLE_PACKAGES")
|
||||
end
|
||||
push!(INITIALIZED_PACKAGES, currentPackageSymbol)
|
||||
println("done.")
|
||||
println("[Plots.jl] done.")
|
||||
|
||||
end
|
||||
CURRENT_PACKAGE.pkg
|
||||
end
|
||||
|
||||
doc"""
|
||||
Set the plot backend. Choose from: :qwt, :gadfly
|
||||
Set the plot backend. Choose from: :qwt, :gadfly, :unicodeplots
|
||||
"""
|
||||
function plotter!(modname)
|
||||
|
||||
@@ -52,6 +94,8 @@ function plotter!(modname)
|
||||
CURRENT_PACKAGE.pkg = QwtPackage()
|
||||
elseif modname == :gadfly
|
||||
CURRENT_PACKAGE.pkg = GadflyPackage()
|
||||
elseif modname == :unicodeplots
|
||||
CURRENT_PACKAGE.pkg = UnicodePlotsPackage()
|
||||
else
|
||||
error("Unknown plotter $modname. Choose from: $AVAILABLE_PACKAGES")
|
||||
end
|
||||
|
||||
@@ -8,7 +8,11 @@ abstract PlottingPackage
|
||||
type Plot <: PlottingObject
|
||||
o # the underlying object
|
||||
plotter::PlottingPackage
|
||||
n::Int # number of series
|
||||
n::Int # number of series
|
||||
|
||||
# store these just in case
|
||||
initargs::Dict
|
||||
seriesargs::Vector{Dict} # args for each series
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ try
|
||||
facts("Gadfly") do
|
||||
@fact plotter!(:gadfly) --> Plots.GadflyPackage()
|
||||
@fact plotter() --> Plots.GadflyPackage()
|
||||
@fact typeof(plot(1:10)) --> Plot
|
||||
@fact typeof(plot(1:10)) --> Plots.Plot
|
||||
|
||||
|
||||
# plot(x::AVec, y::AVec; kw...) # one line (will assert length(x) == length(y))
|
||||
@@ -43,7 +43,7 @@ try
|
||||
facts("Qwt") do
|
||||
@fact plotter!(:qwt) --> Plots.QwtPackage()
|
||||
@fact plotter() --> Plots.QwtPackage()
|
||||
@fact typeof(plot(1:10)) --> Plot
|
||||
@fact typeof(plot(1:10)) --> Plots.Plot
|
||||
|
||||
# plot(y::AVec; kw...) # one line... x = 1:length(y)
|
||||
@fact plot(1:10) --> not(nothing)
|
||||
|
||||