This commit is contained in:
Thomas Breloff 2015-09-10 13:43:24 -04:00
parent 341f671c7c
commit a504e9bc02
7 changed files with 64 additions and 137 deletions

View File

@ -10,11 +10,14 @@ First, clone the package, and get any plotting packages you need:
```
Pkg.clone("https://github.com/JuliaPlot/Plots.jl.git")
Pkg.clone("https://github.com/tbreloff/Qwt.jl.git") # requires pyqt and pyqwt
Pkg.add("Gadfly") # might also need to Pkg.checkout("Gadfly") and maybe Colors/Compose... I had trouble with it
Pkg.clone("https://github.com/tbreloff/Qwt.jl.git") # [optional] requires pyqt and pyqwt
Pkg.add("Gadfly") # [optional] might also need to Pkg.checkout("Gadfly")
# and maybe Colors/Compose... I had trouble with it
```
Now load it in:
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 Qwt.
```
using Plots
@ -23,8 +26,7 @@ using Plots
Do a plot in Qwt, then save a png:
```
plotter!(:qwt)
plot(1:10)
plot(rand(10,2); marker = :rect)
savepng(ans, Plots.IMG_DIR * "qwt1.png")
```
@ -36,9 +38,9 @@ which saves:
Do a plot in Gadfly, then save a png:
```
plotter!(:gadfly)
plot(1:10)
savepng(ans, Plots.IMG_DIR * "gadfly1.png", 6Gadfly.inch, 4Gadfly.inch)
plotter!(:gadfly) # switches the backend to Gadfly
plot(rand(10,2); marker = :rect)
savepng(ans, Plots.IMG_DIR * "gadfly1.png", 6 * Gadfly.inch, 4 * Gadfly.inch)
```
which saves:
@ -46,23 +48,10 @@ which saves:
![gadfly_plt](img/gadfly1.png)
Note that you do not need all underlying packages to use this. I use Requires.jl to
perform lazy loading of the modules, so there's no initialization until you call `plotter!()`.
This has an added benefit that you can call `using Plots` and it should return quickly...
no more waiting for a plotting package to load when you don't even use it. :)
```
julia> tic(); using Plots; toc();
elapsed time: 0.356158445 seconds
# plot and plotter! interface (WIP)
julia> tic(); using Gadfly; toc();
WARNING: using Gadfly.Plots in module Main conflicts with an existing identifier.
elapsed time: 3.1334697 seconds
```
# plot and plotter! (proposal)
The main plot command. You must call `plotter!(:ModuleName)` to set the current plotting environment first.
The main plot command. Call `plotter!(:module)` to set the current plotting backend.
Commands are converted into the relevant plotting commands for that package:
```
@ -102,7 +91,7 @@ Here are some various args to supply, and the implicit mapping (AVec == Abstract
plot(df::DataFrame, columns; kw...) # one line per column, but on a subset of column names
```
You can swap out `plot` for `subplot`. Each line will go into a separate plot. Use the layout keyword:
[TODO] You can swap out `plot` for `subplot`. Each line will go into a separate plot. Use the layout keyword:
```
y = rand(100,3)
@ -112,12 +101,17 @@ You can swap out `plot` for `subplot`. Each line will go into a separate plot.
# and the others will share the second row
```
Other potential shorthands:
Shorthands:
```
hist(args..., kw...)
scatter(args..., kw...)
heatmap(args..., kw...)
scatter(args...; kw...) = plot(args...; kw..., linetype = :none, marker = :rect)
scatter!(args...; kw...) = plot!(args...; kw..., linetype = :none, marker = :rect)
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:
@ -127,11 +121,14 @@ Some keyword arguments you can set:
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
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`
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
@ -150,12 +147,15 @@ 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 = 2
width = 1
linetype = :line
linestype = :solid
marker = :none
markercolor = :auto
markersize = 5
markercolor = :match
markersize = 3
nbins = 100
heatmap_c = (0.15, 0.5)
fillto = nothing
title = ""
xlabel = ""
ylabel = ""
@ -177,20 +177,20 @@ When plotting multiple lines, you can give every line the same trait by using th
# TODO
- [ ] Plot vectors/matrices
- [x] Plot vectors/matrices/functions
- [ ] Plot DataFrames
- [ ] Subplots
- [ ] Histograms
- [x] Histograms
- [ ] 3D plotting
- [ ] Scenes/Drawing
- [ ] Graphs
- [ ] Interactivity (GUIs)
- [ ] Gadfly.jl
- [x] Gadfly.jl
- [ ] PyPlot.jl
- [ ] Winston.jl
- [ ] Gaston.jl
- [ ] GLPlot.jl
- [ ] Qwt.jl
- [x] Qwt.jl
- [ ] Bokeh.jl
- [ ] Plotly.jl
- [ ] GoogleCharts.jl

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -10,7 +10,7 @@ export
plotDefault,
scatter,
bar,
hist,
histogram,
heatmap,
plotter!,
@ -19,7 +19,7 @@ export
plotDefault!,
scatter!,
bar!,
hist!,
histogram!,
heatmap!,
savepng
@ -77,14 +77,14 @@ include("plot.jl")
# const LINE_TYPES = (:line, :step, :stepinverted, :sticks, :dots, :none, :heatmap, :hist, :bar)
scatter(args...; kw...) = plot(args...; kw..., linetype = :dots)
scatter!(args...; kw...) = plot!(args...; kw..., linetype = :dots)
bar(args...; kw...) = plot(args...; kw..., linetype = :bar)
bar!(args...; kw...) = plot!(args...; kw..., linetype = :bar)
hist(args...; kw...) = plot(args...; kw..., linetype = :hist)
hist!(args...; kw...) = plot!(args...; kw..., linetype = :hist)
heatmap(args...; kw...) = plot(args...; kw..., linetype = :heatmap)
heatmap!(args...; kw...) = plot!(args...; kw..., linetype = :heatmap)
scatter(args...; kw...) = plot(args...; kw..., linetype = :none, marker = :rect)
scatter!(args...; kw...) = plot!(args...; kw..., linetype = :none, marker = :rect)
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)
# ---------------------------------------------------------

View File

@ -28,6 +28,7 @@ function getGeomFromLineType(linetype::Symbol)
linetype == :bar && return Gadfly.Geom.bar
linetype == :step && return Gadfly.Geom.step
linetype == :hist && return Gadfly.Geom.hist
linetype == :none && return Gadfly.Geom.point # change this? are we usually pairing no line with scatterplots?
error("linetype $linetype not currently supported with Gadfly")
end
@ -59,7 +60,6 @@ function plot!(::GadflyPackage, plt::Plot; kw...)
gfargs = []
# add the Geoms
println(d)
append!(gfargs, getGeoms(d[:linetype], d[:marker], d[:nbins]))
# set color, line width, and point size

View File

@ -1,14 +1,14 @@
doc"""
The main plot command. You must call `plotter!(:ModuleName)` to set the current plotting environment first.
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 calls `y = 1:10; Gadfly.plot(x=1:length(y), y=y)`
plot(1:10) # this effectively calls `y = 1:10; Gadfly.plot(x=1:length(y), y=y)`
plotter!(:qwt)
plot(1:10) # this calls `Qwt.plot(1:10)`
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:
@ -19,39 +19,8 @@ Use `plot` to create a new plot object, and `plot!` to add to an existing one:
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)
# 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
```
TODO: DataFrames
You can swap out `plot` for `subplot`. Each line will go into a separate plot. Use the layout keyword:
```
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
```
There are lots of ways to pass in data... just try it and it will likely work as expected.
When you pass in matrices, it splits by columns. See the documentation for more info.
Some keyword arguments you can set:
@ -65,6 +34,9 @@ Some keyword arguments you can set:
marker # :none, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :star2, :hexagon
markercolor # same choices 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
@ -77,30 +49,6 @@ Some keyword arguments you can set:
show # true or false, show the plot (in case you don't want the window to pop up right away)
```
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 = 2
linetype = :line
linestype = :solid
marker = :none
markercolor = :auto
markersize = 5
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)

View File

@ -11,25 +11,22 @@ const AVAILABLE_PACKAGES = [:qwt, :gadfly]
const INITIALIZED_PACKAGES = Set{Symbol}()
type CurrentPackage
# pkg::Nullable{PlottingPackage}
sym::Symbol
pkg::PlottingPackage
end
# const CURRENT_PACKAGE = CurrentPackage(Nullable{PlottingPackage}())
const CURRENT_PACKAGE = CurrentPackage(:qwt, QwtPackage())
doc"""
Returns the current plotting package name. Initializes package on first use.
Returns the current plotting package name. Initializes package on first call.
"""
function plotter()
# if isnull(CURRENT_PACKAGE.pkg)
# error("Must choose a plotter. Example: `plotter!(:qwt)`")
# end
currentPackageSymbol = CURRENT_PACKAGE.sym
if !(currentPackageSymbol in INITIALIZED_PACKAGES)
# initialize
print("Initializing package: $CURRENT_PACKAGE... ")
if currentPackageSymbol == :qwt
@eval import Qwt
elseif currentPackageSymbol == :gadfly
@ -38,11 +35,9 @@ function plotter()
error("Unknown plotter $currentPackageSymbol. Choose from: $AVAILABLE_PACKAGES")
end
push!(INITIALIZED_PACKAGES, currentPackageSymbol)
# plotter!(CURRENT_PACKAGE.sym)
println("done.")
end
# get(CURRENT_PACKAGE.pkg)
println("Current package: $CURRENT_PACKAGE")
CURRENT_PACKAGE.pkg
end
@ -51,34 +46,18 @@ Set the plot backend. Choose from: :qwt, :gadfly
"""
function plotter!(modname)
# set the PlottingPackage
if modname == :qwt
# if !(modname in INITIALIZED_PACKAGES)
# # qwt()
# @eval import Qwt
# push!(INITIALIZED_PACKAGES, modname)
# end
# global Qwt = Main.Qwt
# CURRENT_PACKAGE.sym = modname
# CURRENT_PACKAGE.pkg = Nullable(QwtPackage())
CURRENT_PACKAGE.pkg = QwtPackage()
# return
elseif modname == :gadfly
# if !(modname in INITIALIZED_PACKAGES)
# # gadfly()
# @eval import Gadfly
# push!(INITIALIZED_PACKAGES, modname)
# end
# global Gadfly = Main.Gadfly
# CURRENT_PACKAGE.sym = modname
# CURRENT_PACKAGE.pkg = Nullable(GadflyPackage())
CURRENT_PACKAGE.pkg = GadflyPackage()
# return
else
error("Unknown plotter $modname. Choose from: $AVAILABLE_PACKAGES")
end
# update the symbol
CURRENT_PACKAGE.sym = modname
# return the package
CURRENT_PACKAGE.pkg
end