Compare commits

..

52 Commits

Author SHA1 Message Date
Thomas Breloff 3fc5f87388 added better error for Winston output_surface 2015-10-04 09:41:42 -05:00
Thomas Breloff 623ca1effc winston log10 scale 2015-10-03 17:18:58 -05:00
Thomas Breloff da05e7fe5e qwt log10 scale 2015-10-03 17:03:13 -05:00
Thomas Breloff f3734d4c64 added pyplot scales 2015-10-03 09:46:02 -05:00
Thomas Breloff 9ab458e109 switched gadfly heatmap to Geom.histogram2d 2015-10-01 12:55:05 -05:00
Thomas Breloff d4c72e6f78 gadfly ribbon 2015-09-30 10:36:00 -04:00
Thomas Breloff 1f58ef5140 don't error on savefig without an ext, use default; closes #32 2015-09-30 09:55:07 -04:00
Thomas Breloff 69d574c587 added scales globally and to gadfly/immerse 2015-09-30 09:18:16 -04:00
Thomas Breloff a027fdded7 autoload dataframes 2015-09-29 14:40:11 -04:00
Thomas Breloff 443df0501d supported graphs 2015-09-29 14:27:18 -04:00
Thomas Breloff d68fe5f80d supported readme 2015-09-29 14:14:13 -04:00
Thomas Breloff ebf868bae3 supported readme 2015-09-29 14:13:46 -04:00
Thomas Breloff 8a9b3286e9 supportedGraphs utils and pngs; removed args/kwargs from defaults 2015-09-29 14:05:24 -04:00
Thomas Breloff a0455561b6 unicode hline/vline; supportGraph utils 2015-09-29 13:46:31 -04:00
Thomas Breloff 518ccf5a74 pyplot hline/vline 2015-09-29 12:20:58 -04:00
Thomas Breloff 54f09c58cb unicodeplots lims 2015-09-29 12:00:48 -04:00
Thomas Breloff 029ad1045a qwt lims/ticks 2015-09-29 11:50:02 -04:00
Thomas Breloff 2f55fb4d84 winston lims 2015-09-29 10:40:46 -04:00
Thomas Breloff add724eee9 working on gadfly ticks 2015-09-29 09:50:53 -04:00
Thomas Breloff 07324ae892 working on gadfly ticks 2015-09-29 09:49:58 -04:00
Thomas Breloff ffc05e971f working on ticks 2015-09-28 23:49:03 -04:00
Thomas Breloff 30f42fd1d4 added lims/ticks for pyplot 2015-09-28 22:49:46 -04:00
Thomas Breloff f284857438 added qwt hline/vline; working on setTicksFromStringVector 2015-09-28 17:56:32 -04:00
Thomas Breloff 06ab514472 qwt annotations and examples 2015-09-28 17:11:43 -04:00
Thomas Breloff 85b65acbe0 readme 2015-09-28 16:48:32 -04:00
Thomas Breloff 4d1d9de22f gitignore 2015-09-28 16:43:04 -04:00
Thomas Breloff a68ec9b191 savefig and png 2015-09-28 16:42:02 -04:00
Thomas Breloff e386636d66 readme 2015-09-28 16:01:48 -04:00
Thomas Breloff cc3311b8eb examples 2015-09-28 15:49:46 -04:00
Thomas Breloff d3d1181769 examples and readme 2015-09-28 15:44:50 -04:00
Thomas Breloff 001abf684c examples 2015-09-28 15:35:45 -04:00
Thomas Breloff 92a65296b5 redid supportedArgs 2015-09-28 15:21:45 -04:00
Thomas Breloff 3a7887d003 working on massive naming overhaul and fixes 2015-09-28 14:58:56 -04:00
Thomas Breloff 3334c4a87a winston annotations 2015-09-28 12:52:44 -04:00
Thomas Breloff 228ce768e0 pyplot annotations and ioff fix 2015-09-28 12:09:52 -04:00
Thomas Breloff eafc1a784c working on annotations 2015-09-28 11:09:45 -04:00
Thomas Breloff fd3a4d0a0e working on annotations 2015-09-28 10:46:53 -04:00
Thomas Breloff 77d679b63b working on handling string input data 2015-09-27 23:46:42 -04:00
Thomas Breloff 730d764c6e gadfly color group 2015-09-25 17:03:57 -04:00
Thomas Breloff 6f1ef82e89 gadfly color groups for line segments 2015-09-25 16:47:17 -04:00
Thomas Breloff d4da910f19 call Gadfly.get_stroke_vector; added getindex/setindex to qwt 2015-09-25 13:33:06 -04:00
Thomas Breloff a0a0773bd2 fix push warning 2015-09-25 09:42:16 -04:00
Thomas Breloff 9ce8d138d5 working on data updating and notebooks 2015-09-25 01:00:22 -04:00
Thomas Breloff 0041b034e0 working on various things 2015-09-24 16:47:30 -04:00
Thomas Breloff d781c437de started real time updates; fixes #29 (pyplot ijulia display) 2015-09-24 13:01:31 -04:00
Thomas Breloff 2fe21b8547 fixes, gadfly star shape, readme example 2015-09-24 00:35:18 -04:00
Thomas Breloff dbc90c9417 working on groups and iris notebook 2015-09-23 23:34:54 -04:00
Thomas Breloff 431d60a58a working on groups and iris notebook 2015-09-23 23:15:15 -04:00
Thomas Breloff fcfcc9a94a working on groups and iris notebook 2015-09-23 17:13:20 -04:00
Thomas Breloff 870fb4e2df working on groups and iris notebook 2015-09-23 17:12:26 -04:00
Thomas Breloff e3612b973f working on groups and iris notebook 2015-09-23 16:48:49 -04:00
Thomas Breloff 75f4ca928f working on auto-labels from dataframes meta info, and started group arg 2015-09-23 15:34:42 -04:00
61 changed files with 2693 additions and 518 deletions
+2 -1
View File
@@ -1,4 +1,5 @@
*.jl.cov
*.jl.*.cov
*.jl.mem
.DS_Store
.DS_Store
examples/.ipynb_checkpoints/*
+39 -25
View File
@@ -13,6 +13,8 @@ Plots is a plotting interface and wrapper for several plotting packages. My goa
Please add wishlist items, bugs, or any other comments/questions to the issues list.
Check out the [summary graphs](img/supported/supported.md) for the features that each backend supports.
## Examples for each implemented backend:
- [Qwt.jl](docs/qwt_examples.md)
@@ -43,7 +45,7 @@ Pkg.add("Winston")
## Use
Load it in. The underlying plotting backends are not imported until `plotter()` is called (which happens
Load it in. The underlying plotting backends are not imported until `backend()` is called (which happens
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.
@@ -51,42 +53,45 @@ Plots will try to figure out a good default backend for you automatically based
using Plots
```
Do a plot in Gadfly, then save a png:
Do a plot in Gadfly (inspired by [this example](http://gadflyjl.org/geom_point.html)), then save a png:
```julia
# switch to Gadfly as a backend
gadfly!()
gadfly() # switch to Gadfly as a backend
dataframes() # turn on support for DataFrames inputs
# load some data
using RDatasets
iris = dataset("datasets", "iris");
# This will bring up a browser window with the plot. Add a semicolon at the end to skip display.
plot(rand(10,2); marker = :rect, markersize = [10,30], style = :auto)
scatter(iris, :SepalLength, :SepalWidth, group=:Species, ms=12, m=[:+,:d,:s])
# save it as a PNG
savepng(Plots.IMG_DIR * "gadfly1.png")
# save a png (equivalent to png("gadfly1.png") and savefig("gadfly1.png"))
png("gadfly1")
```
which saves:
![gadfly_plt](img/gadfly1.png)
See the examples pages for lots of examples of plots, and what those commands produce for each supported backend.
See the examples pages for lots of examples of plots, and what those commands produce for each supported backend.
Also check out the [IJulia notebooks](examples) and see how it works interactively.
## API
Call `plotter!(backend::Symbol)` or the shorthands (`gadfly!()`, `qwt!()`, `unicodeplots!()`, etc) to set the current plotting backend.
Call `backend(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:
```julia
gadfly!()
gadfly()
plot(1:10) # this effectively calls `y = 1:10; Gadfly.plot(x=1:length(y), y=y)`
qwt!()
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:
```julia
plot(args...; kw...) # creates a new plot window, and sets it to be the `currentPlot`
plot!(args...; kw...) # adds to the `currentPlot`
plot(args...; kw...) # creates a new plot window, and sets it to be the `current`
plot!(args...; kw...) # adds to the `current`
plot!(plotobj, args...; kw...) # adds to the plot `plotobj`
```
@@ -98,13 +103,13 @@ There are many ways to pass in data to the plot functions... some examples:
- Vectors of Vectors
- Functions
- Vectors of Functions
- DataFrames with column symbols (initialize with `dataframes!()`)
- DataFrames with column symbols (initialize with `dataframes()`)
In general, you can pass in a `y` only, or an `x` and `y`, both of whatever type(s) you want, and Plots will slice up the data as needed.
For matrices, data is split by columns. For functions, data is mapped. For DataFrames, a Symbol/Symbols in place of x/y will map to
the relevant column(s).
Here are some example usages... remember you can always use `plot!` to update an existing plot, and that, unless specified, you will update the `currentPlot()`.
Here are some example usages... remember you can always use `plot!` to update an existing plot, and that, unless specified, you will update the `current()`.
```julia
plot() # empty plot object
@@ -118,7 +123,7 @@ plot(rand(10), sin) # same... y = sin(x)
plot([sin,cos], 0:0.1:π) # plot 2 series, sin(x) and cos(x)
plot([sin,cos], 0, π) # plot sin and cos on the range [0, π]
plot(1:10, Any[rand(10), sin]) # plot 2 series, y = rand(10) for the first, y = sin(x) for the second... x = 1:10 for both
plot(dataset("Ecdat", "Airline"), :Cost) # plot from a DataFrame (call `dataframes!()` first to import DataFrames and initialize)
plot(dataset("Ecdat", "Airline"), :Cost) # plot from a DataFrame (call `dataframes()` first to import DataFrames and initialize)
```
You can update certain plot settings after plot creation (not supported on all backends):
@@ -169,42 +174,49 @@ xlims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(xlims = lims)
ylims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(ylims = lims)
xticks!{T<:Real}(v::AVec{T}) = plot!(xticks = v)
yticks!{T<:Real}(v::AVec{T}) = plot!(yticks = v)
annotate!(anns) = plot!(annotation = anns)
```
Some keyword arguments you can set:
Keyword | Default | Type | Aliases
---- | ---- | ---- | ----
`:args` | `Any[]` | Series | `:argss`
`:annotation` | `nothing` | Series | `:ann`, `:annotate`, `:annotations`, `:anns`
`:axis` | `left` | Series | `:axiss`
`:color` | `auto` | Series | `:c`, `:colors`
`:fillto` | `nothing` | Series | `:area`, `:fill`, `:filltos`
`:group` | `nothing` | Series | `:g`, `:groups`
`:heatmap_c` | `(0.15,0.5)` | Series | `:heatmap_cs`
`:kwargs` | `Any[]` | Series | `:kwargss`
`:label` | `AUTO` | Series | `:lab`, `:labels`
`:linestyle` | `solid` | Series | `:linestyles`, `:ls`, `:s`, `:style`
`:linetype` | `path` | Series | `:linetypes`, `:lt`, `:t`, `:type`
`:marker` | `none` | Series | `:m`, `:markers`
`:marker` | `none` | Series | `:m`, `:markers`, `:shape`
`:markercolor` | `match` | Series | `:markercolors`, `:mc`, `:mcolor`
`:markersize` | `6` | Series | `:markersizes`, `:ms`, `:msize`
`:nbins` | `100` | Series | `:nb`, `:nbin`, `:nbinss`
`:reg` | `false` | Series | `:regs`
`:ribbon` | `nothing` | Series | `:r`, `:ribbons`
`:reg` | `false` | Series | `:regression`, `:regs`
`:ribbon` | `nothing` | Series | `:rib`, `:ribbons`
`:width` | `1` | Series | `:linewidth`, `:w`, `:widths`
`:background_color` | `RGB{U8}(1.0,1.0,1.0)` | Plot | `:background`, `:bg`, `:bg_color`, `:bgcolor`
`:foreground_color` | `auto` | Plot | `:fg`, `:fg_color`, `:fgcolor`, `:foreground`
`:layout` | `nothing` | Plot |
`:legend` | `true` | Plot | `:leg`
`:show` | `false` | Plot | `:display`
`:n` | `-1` | Plot |
`:nc` | `-1` | Plot |
`:nr` | `-1` | Plot |
`:pos` | `(0,0)` | Plot |
`:show` | `false` | Plot | `:display`, `:gui`
`:size` | `(800,600)` | Plot | `:windowsize`, `:wsize`
`:title` | `` | Plot |
`:windowtitle` | `Plots.jl` | Plot | `:wtitle`
`:xlabel` | `` | Plot | `:xlab`
`:xlims` | `auto` | Plot | `:xlim`, `:xlimit`, `:xlimits`
`:xscale` | `identity` | Plot |
`:xticks` | `auto` | Plot | `:xtick`
`:ylabel` | `` | Plot | `:ylab`
`:ylims` | `auto` | Plot | `:ylim`, `:ylimit`, `:ylimits`
`:yrightlabel` | `` | Plot | `:y2lab`, `:y2label`, `:ylab2`, `:ylabel2`, `:ylabelright`, `:ylabr`, `:yrlab`
`:yscale` | `identity` | Plot |
`:yticks` | `auto` | Plot | `:ytick`
@@ -260,7 +272,7 @@ Type | Aliases
__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)`
__Tip__: You can see the default value for a given argument with `default(arg::Symbol)`, and set the default value with `default(arg::Symbol, value)` or `default(; kw...)`. For example set the default window size and whether we should show a legend with `default(size=(600,400), leg=false)`.
__Tip__: When plotting multiple lines, you can set all series to use the same value, or pass in an array to cycle through values. Example:
@@ -278,6 +290,8 @@ __Tip__: Call `gui()` to display the plot in a window. Interactivity depends on
- [x] Plot vectors/matrices/functions
- [x] Plot DataFrames
- [x] Grouping
- [ ] Annotations
- [ ] Scales
- [ ] Categorical Inputs (strings, etc... for hist, bar? or can split one series into multiple?)
- [ ] Custom markers
+38 -31
View File
@@ -20,7 +20,7 @@ end
# the examples we'll run for each
const examples = PlotExample[
PlotExample("Lines",
"A simple line plot of the 3 columns.",
"A simple line plot of the columns.",
[:(plot(rand(50,5), w=3))]),
PlotExample("Functions",
"Plot multiple functions. You can also put the function first.",
@@ -32,61 +32,65 @@ const examples = PlotExample[
"Or make a parametric plot (i.e. plot: (fx(u), fy(u))) with plot(fx, fy, umin, umax).",
[:(plot(sin, x->sin(2x), 0, 2π, legend=false, fillto=0))]),
PlotExample("Global",
"Change the guides/background without a separate call.",
[:(plot(rand(10); title="TITLE", xlabel="XLABEL", ylabel="YLABEL", background_color = RGB(0.2,0.2,0.2)))]),
"Change the guides/background/limits/ticks. You can also use shorthand functions: `title!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!`",
[:(plot(rand(10), title="TITLE", xlabel="XLABEL", ylabel="YLABEL", background_color = RGB(0.2,0.2,0.2), xlim=(-3,13), yticks=0:0.1:1))]),
PlotExample("Two-axis",
"Use the `axis` or `axiss` arguments.\n\nNote: Currently only supported with Qwt and PyPlot",
"Use the `axis` arguments.\n\nNote: Currently only supported with Qwt and PyPlot",
[:(plot(Vector[randn(100), randn(100)*100]; axis = [:l,:r], ylabel="LEFT", yrightlabel="RIGHT"))]),
PlotExample("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`).",
[:(plot(Vector[rand(10), rand(20)]; marker=:ellipse, markersize=8, colors=[:red,:blue]))]),
"Plot multiple series with different numbers of points. Mix arguments that apply to all series (marker/markersize) with arguments unique to each series (colors).",
[:(plot(Vector[rand(10), rand(20)]; marker=:ellipse, markersize=8, c=[:red,:blue]))]),
PlotExample("Build plot in pieces",
"Start with a base plot...",
[:(plot(rand(100)/3; reg=true, fillto=0))]),
[:(plot(rand(100)/3, reg=true, fillto=0))]),
PlotExample("",
"and add to it later.",
[:(scatter!(rand(100); markersize=6, c=:blue))]),
[:(scatter!(rand(100), markersize=6, c=:blue))]),
PlotExample("Heatmaps",
"",
[:(heatmap(randn(10000),randn(10000); nbins=100))]),
[:(heatmap(randn(10000),randn(10000), nbins=100))]),
PlotExample("Line types",
"",
[:(types = intersect(supportedTypes(), [:line, :path, :steppre, :steppost, :sticks, :scatter])),
:(n = length(types)),
:(x = Vector[sort(rand(20)) for i in 1:n]),
:(y = rand(20,n)),
:(plot(x, y; t=types, lab=map(string,types)))]),
:(plot(x, y, t=types, lab=map(string,types)))]),
PlotExample("Line styles",
"",
[:(styles = setdiff(supportedStyles(), [:auto])), :(plot(cumsum(randn(20,length(styles)),1); style=:auto, label=map(string,styles), w=5))]),
PlotExample("Marker types",
"",
[:(markers = setdiff(supportedMarkers(), [:none,:auto])), :(scatter(0.5:9.5, [fill(i-0.5,10) for i=length(markers):-1:1]; marker=:auto, label=map(string,markers), markersize=10))]),
[:(markers = setdiff(supportedMarkers(), [:none,:auto])), :(scatter(0.5:9.5, [fill(i-0.5,10) for i=length(markers):-1:1]; marker=:auto, label=map(string,markers), ms=10))]),
PlotExample("Bar",
"x is the midpoint of the bar. (todo: allow passing of edges instead of midpoints)",
[:(bar(randn(1000)))]),
PlotExample("Histogram",
"",
[:(histogram(randn(1000); nbins=50))]),
[:(histogram(randn(1000), nbins=50))]),
PlotExample("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.
number of columns `nc`), or you can set the layout directly with `layout`.
""",
[:(subplot(randn(100,5); layout=[1,1,3], linetypes=[:line,:hist,:scatter,:step,:bar], nbins=10, legend=false))]),
[:(subplot(randn(100,5), layout=[1,1,3], t=[:line,:hist,:scatter,:step,:bar], nbins=10, leg=false))]),
PlotExample("Adding to subplots",
"Note here the automatic grid layout, as well as the order in which new series are added to the plots.",
[:(subplot(randn(100,5); n=4))]),
[:(subplot(randn(100,5), n=4))]),
PlotExample("",
"",
[:(subplot!(randn(100,3)))]),
PlotExample("Open/High/Low/Close",
"Create an OHLC chart. Pass in a vector of 4-tuples as your `y` argument. Adjust the tick width with arg `markersize`.",
"Create an OHLC chart. Pass in a vector of OHLC objects as your `y` argument. Adjust the tick width with arg `markersize`.",
[:(n=20), :(hgt=rand(n)+1), :(bot=randn(n)), :(openpct=rand(n)), :(closepct=rand(n)), :(y = [OHLC(openpct[i]*hgt[i]+bot[i], bot[i]+hgt[i], bot[i], closepct[i]*hgt[i]+bot[i]) for i in 1:n]), :(ohlc(y; markersize=8))]),
PlotExample("Annotations",
"Currently only text annotations are supported. Pass in a tuple or vector-of-tuples: (x,y,text). `annotate!(ann)` is shorthand for `plot!(; annotation=ann)`",
[
:(y = rand(10)),
:(plot(y, ann=(3,y[3],"this is #3"))),
:(annotate!([(5,y[5],"this is #5"),(9,y[10],"this is #10")]))
]),
]
@@ -99,9 +103,9 @@ createStringOfMarkDownSymbols(arr) = isempty(arr) ? "" : createStringOfMarkDownC
function generate_markdown(pkgname::Symbol)
# set up the plotter, and don't show the plots by default
pkg = plotter!(pkgname)
# plotDefault!(:show, false)
# set up the backend, and don't show the plots by default
pkg = backend(pkgname)
# default(:show, false)
# mkdir if necessary
try
@@ -119,7 +123,7 @@ function generate_markdown(pkgname::Symbol)
write(md, "- Supported values for marker: $(createStringOfMarkDownSymbols(supportedMarkers(pkg)))\n")
write(md, "- Is `subplot`/`subplot!` supported? $(subplotSupported(pkg) ? "Yes" : "No")\n\n")
write(md, "### Initialize\n\n```julia\nusing Plots\n$(pkgname)!()\n```\n\n")
write(md, "### Initialize\n\n```julia\nusing Plots\n$(pkgname)()\n```\n\n")
for (i,example) in enumerate(examples)
@@ -136,7 +140,7 @@ function generate_markdown(pkgname::Symbol)
imgname = "$(pkgname)_example_$i.png"
# NOTE: uncomment this to overwrite the images as well
savepng("$IMGDIR/$pkgname/$imgname")
png("$IMGDIR/$pkgname/$imgname")
# write out the header, description, code block, and image link
write(md, "### $(example.header)\n\n")
@@ -160,11 +164,11 @@ end
# make and display one plot
function test_example(pkgname::Symbol, idx::Int)
println("Testing plot: $pkgname:$idx:$(examples[idx].header)")
plotter!(pkgname)
plotter()
backend(pkgname)
backend()
map(eval, examples[idx].exprs)
plt = currentPlot()
display(plt)
plt = current()
gui(plt)
plt
end
@@ -172,9 +176,9 @@ end
function test_all_examples(pkgname::Symbol)
plts = Dict()
for i in 1:length(examples)
if examples[i].header == "Subplots" && !subplotSupported()
break
end
# if examples[i].header == "Subplots" && !subplotSupported()
# break
# end
try
plt = test_example(pkgname, i)
@@ -271,6 +275,9 @@ function buildReadme()
f = open(readme_fn, "w")
write(f, readme)
close(f)
gadfly()
Plots.dumpSupportGraphs()
end
# run it!
+29 -19
View File
@@ -1,6 +1,6 @@
# Examples for backend: gadfly
- Supported arguments: `args`, `axis`, `background_color`, `color`, `fillto`, `foreground_color`, `group`, `kwargs`, `label`, `legend`, `linestyle`, `linetype`, `marker`, `markercolor`, `markersize`, `nbins`, `reg`, `ribbon`, `show`, `size`, `title`, `width`, `windowtitle`, `xlabel`, `xticks`, `ylabel`, `yrightlabel`, `yticks`
- Supported arguments: `annotation`, `args`, `background_color`, `color`, `fillto`, `group`, `kwargs`, `label`, `layout`, `legend`, `linestyle`, `linetype`, `marker`, `markercolor`, `markersize`, `n`, `nbins`, `nc`, `nr`, `reg`, `show`, `size`, `title`, `width`, `windowtitle`, `x`, `xlabel`, `xlims`, `xticks`, `y`, `ylabel`, `ylims`, `yticks`
- Supported values for axis: `:auto`, `:left`
- Supported values for linetype: `:none`, `:line`, `:path`, `:steppost`, `:sticks`, `:scatter`, `:heatmap`, `:hexbin`, `:hist`, `:bar`, `:hline`, `:vline`, `:ohlc`
- Supported values for linestyle: `:auto`, `:solid`, `:dash`, `:dot`, `:dashdot`, `:dashdotdot`
@@ -11,12 +11,12 @@
```julia
using Plots
gadfly!()
gadfly()
```
### Lines
A simple line plot of the 3 columns.
A simple line plot of the columns.
```julia
plot(rand(50,5),w=3)
@@ -58,17 +58,17 @@ plot(sin,(x->begin # /home/tom/.julia/v0.4/Plots/docs/example_generation.jl, li
### Global
Change the guides/background without a separate call.
Change the guides/background/limits/ticks. You can also use shorthand functions: `title!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!`
```julia
plot(rand(10); title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.2,0.2,0.2))
plot(rand(10),title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.2,0.2,0.2),xlim=(-3,13),yticks=0:0.1:1)
```
![](../img/gadfly/gadfly_example_5.png)
### Two-axis
Use the `axis` or `axiss` arguments.
Use the `axis` arguments.
Note: Currently only supported with Qwt and PyPlot
@@ -83,7 +83,7 @@ plot(Vector[randn(100),randn(100) * 100]; axis=[:l,:r],ylabel="LEFT",yrightlabel
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])
plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,c=[:red,:blue])
```
![](../img/gadfly/gadfly_example_7.png)
@@ -93,7 +93,7 @@ plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,colors=[:red,:blue]
Start with a base plot...
```julia
plot(rand(100) / 3; reg=true,fillto=0)
plot(rand(100) / 3,reg=true,fillto=0)
```
![](../img/gadfly/gadfly_example_8.png)
@@ -103,7 +103,7 @@ plot(rand(100) / 3; reg=true,fillto=0)
and add to it later.
```julia
scatter!(rand(100); markersize=6,c=:blue)
scatter!(rand(100),markersize=6,c=:blue)
```
![](../img/gadfly/gadfly_example_9.png)
@@ -113,7 +113,7 @@ scatter!(rand(100); markersize=6,c=:blue)
```julia
heatmap(randn(10000),randn(10000); nbins=100)
heatmap(randn(10000),randn(10000),nbins=100)
```
![](../img/gadfly/gadfly_example_10.png)
@@ -127,7 +127,7 @@ types = intersect(supportedTypes(),[:line,:path,:steppre,:steppost,:sticks,:scat
n = length(types)
x = Vector[sort(rand(20)) for i = 1:n]
y = rand(20,n)
plot(x,y; t=types,lab=map(string,types))
plot(x,y,t=types,lab=map(string,types))
```
![](../img/gadfly/gadfly_example_11.png)
@@ -149,7 +149,7 @@ plot(cumsum(randn(20,length(styles)),1); style=:auto,label=map(string,styles),w=
```julia
markers = setdiff(supportedMarkers(),[:none,:auto])
scatter(0.5:9.5,[fill(i - 0.5,10) for i = length(markers):-1:1]; marker=:auto,label=map(string,markers),markersize=10)
scatter(0.5:9.5,[fill(i - 0.5,10) for i = length(markers):-1:1]; marker=:auto,label=map(string,markers),ms=10)
```
![](../img/gadfly/gadfly_example_13.png)
@@ -169,7 +169,7 @@ bar(randn(1000))
```julia
histogram(randn(1000); nbins=50)
histogram(randn(1000),nbins=50)
```
![](../img/gadfly/gadfly_example_15.png)
@@ -178,13 +178,11 @@ histogram(randn(1000); nbins=50)
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.
number of columns `nc`), or you can set the layout directly with `layout`.
```julia
subplot(randn(100,5); layout=[1,1,3],linetypes=[:line,:hist,:scatter,:step,:bar],nbins=10,legend=false)
subplot(randn(100,5),layout=[1,1,3],t=[:line,:hist,:scatter,:step,:bar],nbins=10,leg=false)
```
![](../img/gadfly/gadfly_example_16.png)
@@ -194,7 +192,7 @@ subplot(randn(100,5); layout=[1,1,3],linetypes=[:line,:hist,:scatter,:step,:bar]
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)
subplot(randn(100,5),n=4)
```
![](../img/gadfly/gadfly_example_17.png)
@@ -211,7 +209,7 @@ subplot!(randn(100,3))
### Open/High/Low/Close
Create an OHLC chart. Pass in a vector of 4-tuples as your `y` argument. Adjust the tick width with arg `markersize`.
Create an OHLC chart. Pass in a vector of OHLC objects as your `y` argument. Adjust the tick width with arg `markersize`.
```julia
n = 20
@@ -225,3 +223,15 @@ ohlc(y; markersize=8)
![](../img/gadfly/gadfly_example_19.png)
### Annotations
Currently only text annotations are supported. Pass in a tuple or vector-of-tuples: (x,y,text). `annotate!(ann)` is shorthand for `plot!(; annotation=ann)`
```julia
y = rand(10)
plot(y,ann=(3,y[3],"this is #3"))
annotate!([(5,y[5],"this is #5"),(9,y[10],"this is #10")])
```
![](../img/gadfly/gadfly_example_20.png)
+29 -19
View File
@@ -1,6 +1,6 @@
# Examples for backend: immerse
- Supported arguments: `args`, `axis`, `background_color`, `color`, `fillto`, `foreground_color`, `group`, `kwargs`, `label`, `legend`, `linestyle`, `linetype`, `marker`, `markercolor`, `markersize`, `nbins`, `reg`, `ribbon`, `show`, `size`, `title`, `width`, `windowtitle`, `xlabel`, `xticks`, `ylabel`, `yrightlabel`, `yticks`
- Supported arguments: `annotation`, `args`, `background_color`, `color`, `fillto`, `group`, `kwargs`, `label`, `layout`, `legend`, `linestyle`, `linetype`, `marker`, `markercolor`, `markersize`, `n`, `nbins`, `nc`, `nr`, `reg`, `show`, `size`, `title`, `width`, `windowtitle`, `x`, `xlabel`, `xlims`, `xticks`, `y`, `ylabel`, `ylims`, `yticks`
- Supported values for axis: `:auto`, `:left`
- Supported values for linetype: `:none`, `:line`, `:path`, `:steppost`, `:sticks`, `:scatter`, `:heatmap`, `:hexbin`, `:hist`, `:bar`, `:hline`, `:vline`, `:ohlc`
- Supported values for linestyle: `:auto`, `:solid`, `:dash`, `:dot`, `:dashdot`, `:dashdotdot`
@@ -11,12 +11,12 @@
```julia
using Plots
immerse!()
immerse()
```
### Lines
A simple line plot of the 3 columns.
A simple line plot of the columns.
```julia
plot(rand(50,5),w=3)
@@ -58,17 +58,17 @@ plot(sin,(x->begin # /home/tom/.julia/v0.4/Plots/docs/example_generation.jl, li
### Global
Change the guides/background without a separate call.
Change the guides/background/limits/ticks. You can also use shorthand functions: `title!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!`
```julia
plot(rand(10); title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.2,0.2,0.2))
plot(rand(10),title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.2,0.2,0.2),xlim=(-3,13),yticks=0:0.1:1)
```
![](../img/immerse/immerse_example_5.png)
### Two-axis
Use the `axis` or `axiss` arguments.
Use the `axis` arguments.
Note: Currently only supported with Qwt and PyPlot
@@ -83,7 +83,7 @@ plot(Vector[randn(100),randn(100) * 100]; axis=[:l,:r],ylabel="LEFT",yrightlabel
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])
plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,c=[:red,:blue])
```
![](../img/immerse/immerse_example_7.png)
@@ -93,7 +93,7 @@ plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,colors=[:red,:blue]
Start with a base plot...
```julia
plot(rand(100) / 3; reg=true,fillto=0)
plot(rand(100) / 3,reg=true,fillto=0)
```
![](../img/immerse/immerse_example_8.png)
@@ -103,7 +103,7 @@ plot(rand(100) / 3; reg=true,fillto=0)
and add to it later.
```julia
scatter!(rand(100); markersize=6,c=:blue)
scatter!(rand(100),markersize=6,c=:blue)
```
![](../img/immerse/immerse_example_9.png)
@@ -113,7 +113,7 @@ scatter!(rand(100); markersize=6,c=:blue)
```julia
heatmap(randn(10000),randn(10000); nbins=100)
heatmap(randn(10000),randn(10000),nbins=100)
```
![](../img/immerse/immerse_example_10.png)
@@ -127,7 +127,7 @@ types = intersect(supportedTypes(),[:line,:path,:steppre,:steppost,:sticks,:scat
n = length(types)
x = Vector[sort(rand(20)) for i = 1:n]
y = rand(20,n)
plot(x,y; t=types,lab=map(string,types))
plot(x,y,t=types,lab=map(string,types))
```
![](../img/immerse/immerse_example_11.png)
@@ -149,7 +149,7 @@ plot(cumsum(randn(20,length(styles)),1); style=:auto,label=map(string,styles),w=
```julia
markers = setdiff(supportedMarkers(),[:none,:auto])
scatter(0.5:9.5,[fill(i - 0.5,10) for i = length(markers):-1:1]; marker=:auto,label=map(string,markers),markersize=10)
scatter(0.5:9.5,[fill(i - 0.5,10) for i = length(markers):-1:1]; marker=:auto,label=map(string,markers),ms=10)
```
![](../img/immerse/immerse_example_13.png)
@@ -169,7 +169,7 @@ bar(randn(1000))
```julia
histogram(randn(1000); nbins=50)
histogram(randn(1000),nbins=50)
```
![](../img/immerse/immerse_example_15.png)
@@ -178,13 +178,11 @@ histogram(randn(1000); nbins=50)
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.
number of columns `nc`), or you can set the layout directly with `layout`.
```julia
subplot(randn(100,5); layout=[1,1,3],linetypes=[:line,:hist,:scatter,:step,:bar],nbins=10,legend=false)
subplot(randn(100,5),layout=[1,1,3],t=[:line,:hist,:scatter,:step,:bar],nbins=10,leg=false)
```
![](../img/immerse/immerse_example_16.png)
@@ -194,7 +192,7 @@ subplot(randn(100,5); layout=[1,1,3],linetypes=[:line,:hist,:scatter,:step,:bar]
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)
subplot(randn(100,5),n=4)
```
![](../img/immerse/immerse_example_17.png)
@@ -211,7 +209,7 @@ subplot!(randn(100,3))
### Open/High/Low/Close
Create an OHLC chart. Pass in a vector of 4-tuples as your `y` argument. Adjust the tick width with arg `markersize`.
Create an OHLC chart. Pass in a vector of OHLC objects as your `y` argument. Adjust the tick width with arg `markersize`.
```julia
n = 20
@@ -225,3 +223,15 @@ ohlc(y; markersize=8)
![](../img/immerse/immerse_example_19.png)
### Annotations
Currently only text annotations are supported. Pass in a tuple or vector-of-tuples: (x,y,text). `annotate!(ann)` is shorthand for `plot!(; annotation=ann)`
```julia
y = rand(10)
plot(y,ann=(3,y[3],"this is #3"))
annotate!([(5,y[5],"this is #5"),(9,y[10],"this is #10")])
```
![](../img/immerse/immerse_example_20.png)
+25 -13
View File
@@ -1,6 +1,6 @@
# Examples for backend: pyplot
- Supported arguments: `args`, `axis`, `background_color`, `color`, `foreground_color`, `group`, `kwargs`, `label`, `legend`, `linestyle`, `linetype`, `marker`, `markercolor`, `markersize`, `nbins`, `ribbon`, `show`, `size`, `title`, `width`, `windowtitle`, `xlabel`, `xticks`, `ylabel`, `yrightlabel`, `yticks`
- Supported arguments: `annotation`, `args`, `axis`, `background_color`, `color`, `foreground_color`, `group`, `kwargs`, `label`, `layout`, `legend`, `linestyle`, `linetype`, `marker`, `markercolor`, `markersize`, `n`, `nbins`, `nc`, `nr`, `show`, `size`, `title`, `width`, `windowtitle`, `x`, `xlabel`, `y`, `ylabel`, `yrightlabel`
- Supported values for axis: `:auto`, `:left`, `:right`
- Supported values for linetype: `:none`, `:line`, `:path`, `:step`, `:stepinverted`, `:sticks`, `:scatter`, `:heatmap`, `:hexbin`, `:hist`, `:bar`
- Supported values for linestyle: `:auto`, `:solid`, `:dash`, `:dot`, `:dashdot`
@@ -11,12 +11,12 @@
```julia
using Plots
pyplot!()
pyplot()
```
### Lines
A simple line plot of the 3 columns.
A simple line plot of the columns.
```julia
plot(rand(50,5),w=3)
@@ -58,17 +58,17 @@ plot(sin,(x->begin # /home/tom/.julia/v0.4/Plots/docs/example_generation.jl, li
### Global
Change the guides/background without a separate call.
Change the guides/background/limits/ticks. You can also use shorthand functions: `title!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!`
```julia
plot(rand(10); title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.2,0.2,0.2))
plot(rand(10),title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.2,0.2,0.2),xlim=(-3,13),yticks=0:0.1:1)
```
![](../img/pyplot/pyplot_example_5.png)
### Two-axis
Use the `axis` or `axiss` arguments.
Use the `axis` arguments.
Note: Currently only supported with Qwt and PyPlot
@@ -83,7 +83,7 @@ plot(Vector[randn(100),randn(100) * 100]; axis=[:l,:r],ylabel="LEFT",yrightlabel
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])
plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,c=[:red,:blue])
```
![](../img/pyplot/pyplot_example_7.png)
@@ -93,7 +93,7 @@ plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,colors=[:red,:blue]
Start with a base plot...
```julia
plot(rand(100) / 3; reg=true,fillto=0)
plot(rand(100) / 3,reg=true,fillto=0)
```
![](../img/pyplot/pyplot_example_8.png)
@@ -103,7 +103,7 @@ plot(rand(100) / 3; reg=true,fillto=0)
and add to it later.
```julia
scatter!(rand(100); markersize=6,c=:blue)
scatter!(rand(100),markersize=6,c=:blue)
```
![](../img/pyplot/pyplot_example_9.png)
@@ -113,7 +113,7 @@ scatter!(rand(100); markersize=6,c=:blue)
```julia
heatmap(randn(10000),randn(10000); nbins=100)
heatmap(randn(10000),randn(10000),nbins=100)
```
![](../img/pyplot/pyplot_example_10.png)
@@ -127,7 +127,7 @@ types = intersect(supportedTypes(),[:line,:path,:steppre,:steppost,:sticks,:scat
n = length(types)
x = Vector[sort(rand(20)) for i = 1:n]
y = rand(20,n)
plot(x,y; t=types,lab=map(string,types))
plot(x,y,t=types,lab=map(string,types))
```
![](../img/pyplot/pyplot_example_11.png)
@@ -149,7 +149,7 @@ plot(cumsum(randn(20,length(styles)),1); style=:auto,label=map(string,styles),w=
```julia
markers = setdiff(supportedMarkers(),[:none,:auto])
scatter(0.5:9.5,[fill(i - 0.5,10) for i = length(markers):-1:1]; marker=:auto,label=map(string,markers),markersize=10)
scatter(0.5:9.5,[fill(i - 0.5,10) for i = length(markers):-1:1]; marker=:auto,label=map(string,markers),ms=10)
```
![](../img/pyplot/pyplot_example_13.png)
@@ -169,8 +169,20 @@ bar(randn(1000))
```julia
histogram(randn(1000); nbins=50)
histogram(randn(1000),nbins=50)
```
![](../img/pyplot/pyplot_example_15.png)
### Annotations
Currently only text annotations are supported. Pass in a tuple or vector-of-tuples: (x,y,text). `annotate!(ann)` is shorthand for `plot!(; annotation=ann)`
```julia
y = rand(10)
plot(y,ann=(3,y[3],"this is #3"))
annotate!([(5,y[5],"this is #5"),(9,y[10],"this is #10")])
```
![](../img/pyplot/pyplot_example_20.png)
+29 -19
View File
@@ -1,6 +1,6 @@
# Examples for backend: qwt
- Supported arguments: `args`, `axis`, `background_color`, `color`, `fillto`, `foreground_color`, `group`, `heatmap_c`, `kwargs`, `label`, `legend`, `linestyle`, `linetype`, `marker`, `markercolor`, `markersize`, `nbins`, `reg`, `ribbon`, `show`, `size`, `title`, `width`, `windowtitle`, `xlabel`, `xticks`, `ylabel`, `yrightlabel`, `yticks`
- Supported arguments: `annotation`, `args`, `axis`, `background_color`, `color`, `fillto`, `foreground_color`, `group`, `heatmap_c`, `kwargs`, `label`, `layout`, `legend`, `linestyle`, `linetype`, `marker`, `markercolor`, `markersize`, `n`, `nbins`, `nc`, `nr`, `pos`, `reg`, `show`, `size`, `title`, `width`, `windowtitle`, `x`, `xlabel`, `y`, `ylabel`, `yrightlabel`
- Supported values for axis: `:auto`, `:left`, `:right`
- Supported values for linetype: `:none`, `:line`, `:path`, `:steppre`, `:steppost`, `:sticks`, `:scatter`, `:heatmap`, `:hexbin`, `:hist`, `:bar`
- Supported values for linestyle: `:auto`, `:solid`, `:dash`, `:dot`, `:dashdot`, `:dashdotdot`
@@ -11,12 +11,12 @@
```julia
using Plots
qwt!()
qwt()
```
### Lines
A simple line plot of the 3 columns.
A simple line plot of the columns.
```julia
plot(rand(50,5),w=3)
@@ -58,17 +58,17 @@ plot(sin,(x->begin # /home/tom/.julia/v0.4/Plots/docs/example_generation.jl, li
### Global
Change the guides/background without a separate call.
Change the guides/background/limits/ticks. You can also use shorthand functions: `title!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!`
```julia
plot(rand(10); title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.2,0.2,0.2))
plot(rand(10),title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.2,0.2,0.2),xlim=(-3,13),yticks=0:0.1:1)
```
![](../img/qwt/qwt_example_5.png)
### Two-axis
Use the `axis` or `axiss` arguments.
Use the `axis` arguments.
Note: Currently only supported with Qwt and PyPlot
@@ -80,10 +80,10 @@ plot(Vector[randn(100),randn(100) * 100]; axis=[:l,:r],ylabel="LEFT",yrightlabel
### 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`).
Plot multiple series with different numbers of points. Mix arguments that apply to all series (marker/markersize) with arguments unique to each series (colors).
```julia
plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,colors=[:red,:blue])
plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,c=[:red,:blue])
```
![](../img/qwt/qwt_example_7.png)
@@ -93,7 +93,7 @@ plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,colors=[:red,:blue]
Start with a base plot...
```julia
plot(rand(100) / 3; reg=true,fillto=0)
plot(rand(100) / 3,reg=true,fillto=0)
```
![](../img/qwt/qwt_example_8.png)
@@ -103,7 +103,7 @@ plot(rand(100) / 3; reg=true,fillto=0)
and add to it later.
```julia
scatter!(rand(100); markersize=6,c=:blue)
scatter!(rand(100),markersize=6,c=:blue)
```
![](../img/qwt/qwt_example_9.png)
@@ -113,7 +113,7 @@ scatter!(rand(100); markersize=6,c=:blue)
```julia
heatmap(randn(10000),randn(10000); nbins=100)
heatmap(randn(10000),randn(10000),nbins=100)
```
![](../img/qwt/qwt_example_10.png)
@@ -127,7 +127,7 @@ types = intersect(supportedTypes(),[:line,:path,:steppre,:steppost,:sticks,:scat
n = length(types)
x = Vector[sort(rand(20)) for i = 1:n]
y = rand(20,n)
plot(x,y; t=types,lab=map(string,types))
plot(x,y,t=types,lab=map(string,types))
```
![](../img/qwt/qwt_example_11.png)
@@ -149,7 +149,7 @@ plot(cumsum(randn(20,length(styles)),1); style=:auto,label=map(string,styles),w=
```julia
markers = setdiff(supportedMarkers(),[:none,:auto])
scatter(0.5:9.5,[fill(i - 0.5,10) for i = length(markers):-1:1]; marker=:auto,label=map(string,markers),markersize=10)
scatter(0.5:9.5,[fill(i - 0.5,10) for i = length(markers):-1:1]; marker=:auto,label=map(string,markers),ms=10)
```
![](../img/qwt/qwt_example_13.png)
@@ -169,7 +169,7 @@ bar(randn(1000))
```julia
histogram(randn(1000); nbins=50)
histogram(randn(1000),nbins=50)
```
![](../img/qwt/qwt_example_15.png)
@@ -178,13 +178,11 @@ histogram(randn(1000); nbins=50)
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.
number of columns `nc`), or you can set the layout directly with `layout`.
```julia
subplot(randn(100,5); layout=[1,1,3],linetypes=[:line,:hist,:scatter,:step,:bar],nbins=10,legend=false)
subplot(randn(100,5),layout=[1,1,3],t=[:line,:hist,:scatter,:step,:bar],nbins=10,leg=false)
```
![](../img/qwt/qwt_example_16.png)
@@ -194,7 +192,7 @@ subplot(randn(100,5); layout=[1,1,3],linetypes=[:line,:hist,:scatter,:step,:bar]
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)
subplot(randn(100,5),n=4)
```
![](../img/qwt/qwt_example_17.png)
@@ -209,3 +207,15 @@ subplot!(randn(100,3))
![](../img/qwt/qwt_example_18.png)
### Annotations
Currently only text annotations are supported. Pass in a tuple or vector-of-tuples: (x,y,text). `annotate!(ann)` is shorthand for `plot!(; annotation=ann)`
```julia
y = rand(10)
plot(y,ann=(3,y[3],"this is #3"))
annotate!([(5,y[5],"this is #5"),(9,y[10],"this is #10")])
```
![](../img/qwt/qwt_example_20.png)
+27 -19
View File
@@ -13,6 +13,8 @@ Plots is a plotting interface and wrapper for several plotting packages. My goa
Please add wishlist items, bugs, or any other comments/questions to the issues list.
Check out the [summary graphs](img/supported/supported.md) for the features that each backend supports.
## Examples for each implemented backend:
- [Qwt.jl](docs/qwt_examples.md)
@@ -43,7 +45,7 @@ Pkg.add("Winston")
## Use
Load it in. The underlying plotting backends are not imported until `plotter()` is called (which happens
Load it in. The underlying plotting backends are not imported until `backend()` is called (which happens
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.
@@ -51,42 +53,45 @@ Plots will try to figure out a good default backend for you automatically based
using Plots
```
Do a plot in Gadfly, then save a png:
Do a plot in Gadfly (inspired by [this example](http://gadflyjl.org/geom_point.html)), then save a png:
```julia
# switch to Gadfly as a backend
gadfly!()
gadfly() # switch to Gadfly as a backend
dataframes() # turn on support for DataFrames inputs
# load some data
using RDatasets
iris = dataset("datasets", "iris");
# This will bring up a browser window with the plot. Add a semicolon at the end to skip display.
plot(rand(10,2); marker = :rect, markersize = [10,30], style = :auto)
scatter(iris, :SepalLength, :SepalWidth, group=:Species, ms=12, m=[:+,:d,:s])
# save it as a PNG
savepng(Plots.IMG_DIR * "gadfly1.png")
# save a png (equivalent to png("gadfly1.png") and savefig("gadfly1.png"))
png("gadfly1")
```
which saves:
![gadfly_plt](img/gadfly1.png)
See the examples pages for lots of examples of plots, and what those commands produce for each supported backend.
See the examples pages for lots of examples of plots, and what those commands produce for each supported backend.
Also check out the [IJulia notebooks](examples) and see how it works interactively.
## API
Call `plotter!(backend::Symbol)` or the shorthands (`gadfly!()`, `qwt!()`, `unicodeplots!()`, etc) to set the current plotting backend.
Call `backend(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:
```julia
gadfly!()
gadfly()
plot(1:10) # this effectively calls `y = 1:10; Gadfly.plot(x=1:length(y), y=y)`
qwt!()
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:
```julia
plot(args...; kw...) # creates a new plot window, and sets it to be the `currentPlot`
plot!(args...; kw...) # adds to the `currentPlot`
plot(args...; kw...) # creates a new plot window, and sets it to be the `current`
plot!(args...; kw...) # adds to the `current`
plot!(plotobj, args...; kw...) # adds to the plot `plotobj`
```
@@ -98,13 +103,13 @@ There are many ways to pass in data to the plot functions... some examples:
- Vectors of Vectors
- Functions
- Vectors of Functions
- DataFrames with column symbols (initialize with `dataframes!()`)
- DataFrames with column symbols (initialize with `dataframes()`)
In general, you can pass in a `y` only, or an `x` and `y`, both of whatever type(s) you want, and Plots will slice up the data as needed.
For matrices, data is split by columns. For functions, data is mapped. For DataFrames, a Symbol/Symbols in place of x/y will map to
the relevant column(s).
Here are some example usages... remember you can always use `plot!` to update an existing plot, and that, unless specified, you will update the `currentPlot()`.
Here are some example usages... remember you can always use `plot!` to update an existing plot, and that, unless specified, you will update the `current()`.
```julia
plot() # empty plot object
@@ -118,7 +123,7 @@ plot(rand(10), sin) # same... y = sin(x)
plot([sin,cos], 0:0.1:π) # plot 2 series, sin(x) and cos(x)
plot([sin,cos], 0, π) # plot sin and cos on the range [0, π]
plot(1:10, Any[rand(10), sin]) # plot 2 series, y = rand(10) for the first, y = sin(x) for the second... x = 1:10 for both
plot(dataset("Ecdat", "Airline"), :Cost) # plot from a DataFrame (call `dataframes!()` first to import DataFrames and initialize)
plot(dataset("Ecdat", "Airline"), :Cost) # plot from a DataFrame (call `dataframes()` first to import DataFrames and initialize)
```
You can update certain plot settings after plot creation (not supported on all backends):
@@ -169,6 +174,7 @@ xlims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(xlims = lims)
ylims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(ylims = lims)
xticks!{T<:Real}(v::AVec{T}) = plot!(xticks = v)
yticks!{T<:Real}(v::AVec{T}) = plot!(yticks = v)
annotate!(anns) = plot!(annotation = anns)
```
Some keyword arguments you can set:
@@ -188,7 +194,7 @@ Markers:
[[MARKERS_TABLE]]
__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)`
__Tip__: You can see the default value for a given argument with `default(arg::Symbol)`, and set the default value with `default(arg::Symbol, value)` or `default(; kw...)`. For example set the default window size and whether we should show a legend with `default(size=(600,400), leg=false)`.
__Tip__: When plotting multiple lines, you can set all series to use the same value, or pass in an array to cycle through values. Example:
@@ -206,6 +212,8 @@ __Tip__: Call `gui()` to display the plot in a window. Interactivity depends on
- [x] Plot vectors/matrices/functions
- [x] Plot DataFrames
- [x] Grouping
- [ ] Annotations
- [ ] Scales
- [ ] Categorical Inputs (strings, etc... for hist, bar? or can split one series into multiple?)
- [ ] Custom markers
+1 -1
View File
@@ -11,7 +11,7 @@
```julia
using Plots
unicodeplots!()
unicodeplots()
```
### Lines
+24 -12
View File
@@ -1,6 +1,6 @@
# Examples for backend: winston
- Supported arguments: `args`, `axis`, `color`, `foreground_color`, `group`, `kwargs`, `label`, `legend`, `linestyle`, `linetype`, `marker`, `markersize`, `nbins`, `reg`, `ribbon`, `show`, `size`, `title`, `width`, `windowtitle`, `xlabel`, `xticks`, `ylabel`, `yrightlabel`, `yticks`
- Supported arguments: `annotation`, `color`, `fillto`, `group`, `label`, `legend`, `linestyle`, `linetype`, `marker`, `markercolor`, `markersize`, `nbins`, `reg`, `show`, `size`, `title`, `width`, `windowtitle`, `x`, `xlabel`, `y`, `ylabel`
- Supported values for axis: `:auto`, `:left`
- Supported values for linetype: `:none`, `:line`, `:path`, `:sticks`, `:scatter`, `:hist`, `:bar`
- Supported values for linestyle: `:solid`, `:dash`, `:dot`, `:dashdot`
@@ -11,12 +11,12 @@
```julia
using Plots
winston!()
winston()
```
### Lines
A simple line plot of the 3 columns.
A simple line plot of the columns.
```julia
plot(rand(50,5),w=3)
@@ -58,17 +58,17 @@ plot(sin,(x->begin # /home/tom/.julia/v0.4/Plots/docs/example_generation.jl, li
### Global
Change the guides/background without a separate call.
Change the guides/background/limits/ticks. You can also use shorthand functions: `title!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!`
```julia
plot(rand(10); title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.2,0.2,0.2))
plot(rand(10),title="TITLE",xlabel="XLABEL",ylabel="YLABEL",background_color=RGB(0.2,0.2,0.2),xlim=(-3,13),yticks=0:0.1:1)
```
![](../img/winston/winston_example_5.png)
### Two-axis
Use the `axis` or `axiss` arguments.
Use the `axis` arguments.
Note: Currently only supported with Qwt and PyPlot
@@ -83,7 +83,7 @@ plot(Vector[randn(100),randn(100) * 100]; axis=[:l,:r],ylabel="LEFT",yrightlabel
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])
plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,c=[:red,:blue])
```
![](../img/winston/winston_example_7.png)
@@ -93,7 +93,7 @@ plot(Vector[rand(10),rand(20)]; marker=:ellipse,markersize=8,colors=[:red,:blue]
Start with a base plot...
```julia
plot(rand(100) / 3; reg=true,fillto=0)
plot(rand(100) / 3,reg=true,fillto=0)
```
![](../img/winston/winston_example_8.png)
@@ -103,7 +103,7 @@ plot(rand(100) / 3; reg=true,fillto=0)
and add to it later.
```julia
scatter!(rand(100); markersize=6,c=:blue)
scatter!(rand(100),markersize=6,c=:blue)
```
![](../img/winston/winston_example_9.png)
@@ -117,7 +117,7 @@ types = intersect(supportedTypes(),[:line,:path,:steppre,:steppost,:sticks,:scat
n = length(types)
x = Vector[sort(rand(20)) for i = 1:n]
y = rand(20,n)
plot(x,y; t=types,lab=map(string,types))
plot(x,y,t=types,lab=map(string,types))
```
![](../img/winston/winston_example_11.png)
@@ -139,7 +139,7 @@ plot(cumsum(randn(20,length(styles)),1); style=:auto,label=map(string,styles),w=
```julia
markers = setdiff(supportedMarkers(),[:none,:auto])
scatter(0.5:9.5,[fill(i - 0.5,10) for i = length(markers):-1:1]; marker=:auto,label=map(string,markers),markersize=10)
scatter(0.5:9.5,[fill(i - 0.5,10) for i = length(markers):-1:1]; marker=:auto,label=map(string,markers),ms=10)
```
![](../img/winston/winston_example_13.png)
@@ -159,8 +159,20 @@ bar(randn(1000))
```julia
histogram(randn(1000); nbins=50)
histogram(randn(1000),nbins=50)
```
![](../img/winston/winston_example_15.png)
### Annotations
Currently only text annotations are supported. Pass in a tuple or vector-of-tuples: (x,y,text). `annotate!(ann)` is shorthand for `plot!(; annotation=ann)`
```julia
y = rand(10)
plot(y,ann=(3,y[3],"this is #3"))
annotate!([(5,y[5],"this is #5"),(9,y[10],"this is #10")])
```
![](../img/winston/winston_example_20.png)
File diff suppressed because one or more lines are too long
+232
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 67 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

+23
View File
@@ -0,0 +1,23 @@
## Supported keyword arguments
![args](Plots.supportGraphArgs.png)
## Supported plot types
![types](Plots.supportGraphTypes.png)
## Supported markers
![markers](Plots.supportGraphMarkers.png)
## Supported line styles
![styles](Plots.supportGraphStyles.png)
## Supported scales
![scales](Plots.supportGraphScales.png)
## Supported axes
![axes](Plots.supportGraphAxes.png)
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

+103 -27
View File
@@ -6,19 +6,16 @@ using Reexport
@reexport using Colors
export
plotter,
plotter!,
plot,
plot!,
plot_display,
plot_display!,
# plot_display,
# plot_display!,
subplot,
subplot!,
currentPlot,
currentPlot!,
plotDefault,
plotDefault!,
current,
default,
scatter,
scatter!,
bar,
@@ -43,13 +40,16 @@ export
ylims!,
xticks!,
yticks!,
annotate!,
savepng,
savefig,
png,
gui,
backend,
backends,
aliases,
dataframes!,
dataframes,
OHLC,
supportedArgs,
@@ -96,43 +96,119 @@ ohlc(args...; kw...) = plot(args...; kw..., linetype = :ohlc)
ohlc!(args...; kw...) = plot!(args...; kw..., linetype = :ohlc)
title!(s::AbstractString) = plot!(title = s)
xlabel!(s::AbstractString) = plot!(xlabel = s)
ylabel!(s::AbstractString) = plot!(ylabel = s)
title!(s::AbstractString) = plot!(title = s)
xlabel!(s::AbstractString) = plot!(xlabel = s)
ylabel!(s::AbstractString) = plot!(ylabel = s)
xlims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(xlims = lims)
ylims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(ylims = lims)
xticks!{T<:Real}(v::AVec{T}) = plot!(xticks = v)
yticks!{T<:Real}(v::AVec{T}) = plot!(yticks = v)
xlims!(xmin::Real, xmax::Real) = plot!(xlims = (xmin,xmax))
ylims!(ymin::Real, ymax::Real) = plot!(ylims = (ymin,ymax))
xticks!{T<:Real}(v::AVec{T}) = plot!(xticks = v)
yticks!{T<:Real}(v::AVec{T}) = plot!(yticks = v)
xticks!{T<:Real,S<:AbstractString}(ticks::AVec{T}, labels::AVec{S}) = plot!(xticks = (ticks,labels))
yticks!{T<:Real,S<:AbstractString}(ticks::AVec{T}, labels::AVec{S}) = plot!(yticks = (ticks,labels))
annotate!(anns) = plot!(annotation = anns)
title!(plt::Plot, s::AbstractString) = plot!(plt; title = s)
xlabel!(plt::Plot, s::AbstractString) = plot!(plt; xlabel = s)
ylabel!(plt::Plot, s::AbstractString) = plot!(plt; ylabel = s)
xlims!{T<:Real,S<:Real}(plt::Plot, lims::Tuple{T,S}) = plot!(plt; xlims = lims)
ylims!{T<:Real,S<:Real}(plt::Plot, lims::Tuple{T,S}) = plot!(plt; ylims = lims)
xticks!{T<:Real}(plt::Plot, v::AVec{T}) = plot!(plt; xticks = v)
yticks!{T<:Real}(plt::Plot, v::AVec{T}) = plot!(plt; yticks = v)
title!(plt::Plot, s::AbstractString) = plot!(plt; title = s)
xlabel!(plt::Plot, s::AbstractString) = plot!(plt; xlabel = s)
ylabel!(plt::Plot, s::AbstractString) = plot!(plt; ylabel = s)
xlims!{T<:Real,S<:Real}(plt::Plot, lims::Tuple{T,S}) = plot!(plt; xlims = lims)
ylims!{T<:Real,S<:Real}(plt::Plot, lims::Tuple{T,S}) = plot!(plt; ylims = lims)
xlims!(plt::Plot, xmin::Real, xmax::Real) = plot!(plt; xlims = (xmin,xmax))
ylims!(plt::Plot, ymin::Real, ymax::Real) = plot!(plt; ylims = (ymin,ymax))
xticks!{T<:Real}(plt::Plot, ticks::AVec{T}) = plot!(plt; xticks = ticks)
yticks!{T<:Real}(plt::Plot, ticks::AVec{T}) = plot!(plt; yticks = ticks)
xticks!{T<:Real,S<:AbstractString}(plt::Plot, ticks::AVec{T}, labels::AVec{S}) = plot!(plt; xticks = (ticks,labels))
yticks!{T<:Real,S<:AbstractString}(plt::Plot, ticks::AVec{T}, labels::AVec{S}) = plot!(plt; yticks = (ticks,labels))
annotate!(plt::Plot, anns) = plot!(plt; annotation = anns)
# ---------------------------------------------------------
savepng(args...; kw...) = savepng(currentPlot(), args...; kw...)
savepng(plt::PlottingObject, fn::AbstractString; kw...) = (io = open(fn, "w"); writemime(io, MIME("image/png"), plt); close(io))
# savepng(plt::PlottingObject, args...; kw...) = savepng(plt.plotter, plt, args...; kw...)
# savepng(::PlottingPackage, plt::PlottingObject, fn::AbstractString, args...) = error("unsupported") # fallback so multiple dispatch doesn't get confused if it's missing
defaultOutputFormat(plt::PlottingObject) = "png"
function png(plt::PlottingObject, fn::AbstractString)
fn = addExtension(fn, "png")
io = open(fn, "w")
writemime(io, MIME("image/png"), plt)
close(io)
end
png(fn::AbstractString) = png(current(), fn)
gui(plt::PlottingObject = currentPlot()) = display(PlotsDisplay(), plt)
const _savemap = Dict(
"png" => png,
)
function getExtension(fn::AbstractString)
pieces = split(fn, ".")
length(pieces) > 1 || error("Can't extract file extension: ", fn)
ext = pieces[end]
haskey(_savemap, ext) || error("Invalid file extension: ", fn)
ext
end
function addExtension(fn::AbstractString, ext::AbstractString)
try
oldext = getExtension(fn)
if oldext == ext
return fn
else
return "$fn.$ext"
end
catch
return "$fn.$ext"
end
end
function savefig(plt::PlottingObject, fn::AbstractString)
# get the extension
local ext
try
ext = getExtension(fn)
catch
# if we couldn't extract the extension, add the default
ext = defaultOutputFormat(plt)
fn = addExtension(fn, ext)
end
# save it
func = get(_savemap, ext) do
error("Unsupported extension $ext with filename ", fn)
end
func(plt, fn)
end
savefig(fn::AbstractString) = savefig(current(), fn)
# savepng(args...; kw...) = savepng(current(), args...; kw...)
# savepng(plt::PlottingObject, fn::AbstractString; kw...) = (io = open(fn, "w"); writemime(io, MIME("image/png"), plt); close(io))
# ---------------------------------------------------------
gui(plt::PlottingObject = current()) = display(PlotsDisplay(), plt)
# override the REPL display to open a gui window
Base.display(::Base.REPL.REPLDisplay, ::MIME"text/plain", plt::PlottingObject) = gui(plt)
# ---------------------------------------------------------
function __init__()
global const CURRENT_BACKEND = pickDefaultBackend()
println("[Plots.jl] Default backend: ", CURRENT_BACKEND.sym)
# auto init dataframes if the import statement doesn't error out
try
@eval import DataFrames
dataframes()
end
end
# ---------------------------------------------------------
+88 -108
View File
@@ -73,17 +73,25 @@ const _markerAliases = Dict(
:oct => :octagon,
)
const _allScales = [:identity, :log, :log2, :log10, :asinh, :sqrt]
const _scaleAliases = Dict(
:none => :identity,
:ln => :log,
)
supportedAxes(::PlottingPackage) = _allAxes
supportedTypes(::PlottingPackage) = _allTypes
supportedStyles(::PlottingPackage) = _allStyles
supportedMarkers(::PlottingPackage) = _allMarkers
supportedScales(::PlottingPackage) = _allScales
subplotSupported(::PlottingPackage) = true
supportedAxes() = supportedAxes(plotter())
supportedTypes() = supportedTypes(plotter())
supportedStyles() = supportedStyles(plotter())
supportedMarkers() = supportedMarkers(plotter())
subplotSupported() = subplotSupported(plotter())
supportedAxes() = supportedAxes(backend())
supportedTypes() = supportedTypes(backend())
supportedStyles() = supportedStyles(backend())
supportedMarkers() = supportedMarkers(backend())
supportedScales() = supportedScales(backend())
subplotSupported() = subplotSupported(backend())
# -----------------------------------------------------------------------------
@@ -105,9 +113,10 @@ _seriesDefaults[:fillto] = nothing # fills in the area
_seriesDefaults[:reg] = false # regression line?
_seriesDefaults[:group] = nothing
_seriesDefaults[:ribbon] = nothing
_seriesDefaults[:args] = [] # additional args to pass to the backend
_seriesDefaults[:kwargs] = [] # additional keyword args to pass to the backend
# note: can be Vector{Dict} or Vector{Tuple}
_seriesDefaults[:annotation] = nothing
# _seriesDefaults[:args] = [] # additional args to pass to the backend
# _seriesDefaults[:kwargs] = [] # additional keyword args to pass to the backend
# # note: can be Vector{Dict} or Vector{Tuple}
const _plotDefaults = Dict{Symbol, Any}()
@@ -120,13 +129,20 @@ _plotDefaults[:yrightlabel] = ""
_plotDefaults[:legend] = true
_plotDefaults[:background_color] = colorant"white"
_plotDefaults[:foreground_color] = :auto
_plotDefaults[:xlims] = :auto
_plotDefaults[:ylims] = :auto
_plotDefaults[:xlims] = :auto
_plotDefaults[:ylims] = :auto
_plotDefaults[:xticks] = :auto
_plotDefaults[:yticks] = :auto
_plotDefaults[:xscale] = :identity
_plotDefaults[:yscale] = :identity
_plotDefaults[:size] = (800,600)
_plotDefaults[:pos] = (0,0)
_plotDefaults[:windowtitle] = "Plots.jl"
_plotDefaults[:show] = false
_plotDefaults[:layout] = nothing
_plotDefaults[:n] = -1
_plotDefaults[:nr] = -1
_plotDefaults[:nc] = -1
@@ -134,7 +150,7 @@ _plotDefaults[:show] = false
const _allArgs = sort(collect(union(keys(_seriesDefaults), keys(_plotDefaults))))
supportedArgs(::PlottingPackage) = _allArgs
supportedArgs() = supportedArgs(plotter())
supportedArgs() = supportedArgs(backend())
# -----------------------------------------------------------------------------
@@ -176,6 +192,7 @@ const _keyAliases = Dict(
:s => :linestyle,
:ls => :linestyle,
:m => :marker,
:shape => :marker,
:mc => :markercolor,
:mcolor => :markercolor,
:ms => :markersize,
@@ -185,7 +202,11 @@ const _keyAliases = Dict(
:fill => :fillto,
:area => :fillto,
:g => :group,
:r => :ribbon,
:rib => :ribbon,
:ann => :annotation,
:anns => :annotation,
:annotate => :annotation,
:annotations => :annotation,
:xlab => :xlabel,
:ylab => :ylabel,
:yrlab => :yrightlabel,
@@ -204,6 +225,7 @@ const _keyAliases = Dict(
:fgcolor => :foreground_color,
:fg_color => :foreground_color,
:foreground => :foreground_color,
:regression => :reg,
:xlim => :xlims,
:xlimit => :xlims,
:xlimits => :xlims,
@@ -215,6 +237,7 @@ const _keyAliases = Dict(
:windowsize => :size,
:wsize => :size,
:wtitle => :windowtitle,
:gui => :show,
:display => :show,
)
@@ -229,7 +252,14 @@ end
# update the defaults globally
function plotDefault(k::Symbol)
"""
`default(key)` returns the current default value for that key
`default(key, value)` sets the current default value for that key
`default(; kw...)` will set the current default value for each key/value pair
"""
function default(k::Symbol)
k = get(_keyAliases, k, k)
if haskey(_seriesDefaults, k)
return _seriesDefaults[k]
elseif haskey(_plotDefaults, k)
@@ -239,7 +269,8 @@ function plotDefault(k::Symbol)
end
end
function plotDefault!(k::Symbol, v)
function default(k::Symbol, v)
k = get(_keyAliases, k, k)
if haskey(_seriesDefaults, k)
_seriesDefaults[k] = v
elseif haskey(_plotDefaults, k)
@@ -249,11 +280,47 @@ function plotDefault!(k::Symbol, v)
end
end
function default(; kw...)
for (k,v) in kw
default(k, v)
end
end
# -----------------------------------------------------------------------------
"A special type that will break up incoming data into groups, and allow for easier creation of grouped plots"
type GroupBy
groupLabels::Vector{UTF8String} # length == numGroups
groupIds::Vector{Vector{Int}} # list of indices for each group
end
# this is when given a vector-type of values to group by
function extractGroupArgs(v::AVec, args...)
groupLabels = sort(collect(unique(v)))
n = length(groupLabels)
if n > 20
error("Too many group labels. n=$n Is that intended?")
end
groupIds = Vector{Int}[filter(i -> v[i] == glab, 1:length(v)) for glab in groupLabels]
GroupBy(groupLabels, groupIds)
end
# expecting a mapping of "group label" to "group indices"
function extractGroupArgs{T, V<:AVec{Int}}(idxmap::Dict{T,V}, args...)
groupLabels = sortedkeys(idxmap)
groupIds = VecI[collect(idxmap[k]) for k in groupLabels]
GroupBy(groupLabels, groupIds)
end
# -----------------------------------------------------------------------------
function warnOnUnsupportedArgs(pkg::PlottingPackage, d::Dict)
for k in sortedkeys(d)
if !(k in supportedArgs(pkg))
if !(k in supportedArgs(pkg)) && d[k] != default(k)
warn("Keyword argument $k not supported with $pkg. Choose from: $(supportedArgs(pkg))")
end
end
@@ -285,6 +352,12 @@ function getPlotArgs(pkg::PlottingPackage, kw, idx::Int)
end
end
for k in (:xscale, :yscale)
if haskey(_scaleAliases, d[k])
d[k] = _scaleAliases[d[k]]
end
end
# convert color
handlePlotColors(pkg, d)
# d[:background_color] = getBackgroundRGBColor(d[:background_color], d)
@@ -346,96 +419,3 @@ function getSeriesArgs(pkg::PlottingPackage, initargs::Dict, kw, commandIndex::I
end
# # note: idx is the index of this series within this call, n is the index of the series from all calls to plot/subplot
# function getPlotKeywordArgs(pkg::PlottingPackage, kw, idx::Int, n::Int)
# d = Dict(kw)
# # # replace alternate names
# # for tup in kw
# # if haskey(ALT_ARG_NAMES, tup)
# # d[tup[1]] = ALT_ARG_NAMES[tup]
# # end
# # end
# # default to a white background, but only on the initial call (so we don't change the background automatically)
# if haskey(d, :background_color)
# d[:background_color] = getRGBColor(d[:background_color])
# elseif n == 0
# d[:background_color] = colorant"white"
# end
# # fill in d with either 1) plural value, 2) value, 3) default
# for k in keys(PLOT_DEFAULTS)
# plural = makeplural(k)
# if !haskey(d, k)
# if n == 0 || k != :size
# d[k] = haskey(d, plural) ? autopick(d[plural], idx) : PLOT_DEFAULTS[k]
# end
# end
# delete!(d, plural)
# end
# # auto-pick
# if n > 0
# if d[:axis] == :auto
# d[:axis] = autopick_ignore_none_auto(supportedAxes(pkg), n)
# end
# # if d[:linetype] == :auto
# # d[:linetype] = autopick_ignore_none_auto(supportedTypes(pkg), n)
# # end
# if d[:linestyle] == :auto
# d[:linestyle] = autopick_ignore_none_auto(supportedStyles(pkg), n)
# end
# if d[:marker] == :auto
# d[:marker] = autopick_ignore_none_auto(supportedMarkers(pkg), n)
# end
# end
# # # swap out dots for no line and a marker
# # if haskey(d, :linetype) && d[:linetype] == :scatter
# # d[:linetype] = :none
# # if d[:marker] == :none
# # d[:marker] = :ellipse
# # end
# # end
# # handle plot initialization differently
# if n == 0
# delete!(d, :x)
# delete!(d, :y)
# else
# # once the plot is created, we can get line/marker colors
# # update color
# d[:color] = getRGBColor(d[:color], n)
# # update markercolor
# mc = d[:markercolor]
# mc = (mc == :match ? d[:color] : getRGBColor(mc, n))
# d[:markercolor] = mc
# # set label
# label = d[:label]
# 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
# warnOnUnsupported(pkg, d)
# end
# d
# end
# -----------------------------------------------------------------------------
# TODO: arg aliases
+246 -54
View File
@@ -3,15 +3,59 @@
immutable GadflyPackage <: PlottingPackage end
export gadfly!
gadfly!() = plotter!(:gadfly)
export gadfly
gadfly() = backend(:gadfly)
supportedArgs(::GadflyPackage) = setdiff(_allArgs, [:heatmap_c, :pos, :screen, :yrightlabel])
supportedAxes(::GadflyPackage) = setdiff(_allAxes, [:right])
# supportedArgs(::GadflyPackage) = setdiff(_allArgs, [:heatmap_c, :pos, :screen, :yrightlabel])
supportedArgs(::GadflyPackage) = [
:annotation,
# :args,
# :axis,
:background_color,
:color,
:fillto,
# :foreground_color,
:group,
# :heatmap_c,
# :kwargs,
:label,
:layout,
:legend,
:linestyle,
:linetype,
:marker,
:markercolor,
:markersize,
:n,
:nbins,
:nc,
:nr,
# :pos,
:reg,
:ribbon,
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
:yticks,
:xscale,
:yscale,
]
supportedAxes(::GadflyPackage) = [:auto, :left]
supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :ohlc]
supportedStyles(::GadflyPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::GadflyPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :star2, :hexagon, :octagon]
supportedScales(::GadflyPackage) = [:identity, :log, :log2, :log10, :asinh, :sqrt]
include("gadfly_shapes.jl")
@@ -43,16 +87,17 @@ end
# function getGeoms(linetype::Symbol, marker::Symbol, markercolor::Colorant, nbins::Int)
function getLineGeoms(d::Dict)
lt = d[:linetype]
lt in (:heatmap,:hexbin) && return [Gadfly.Geom.hexbin(xbincount = d[:nbins], ybincount = d[:nbins])]
lt == :hexbin && return [Gadfly.Geom.hexbin(xbincount = d[:nbins], ybincount = d[:nbins])]
lt == :heatmap && return [Gadfly.Geom.histogram2d(xbincount = d[:nbins], ybincount = d[:nbins])]
lt == :hist && return [Gadfly.Geom.histogram(bincount = d[:nbins])]
# lt == :none && return [Gadfly.Geom.path]
lt == :path && return [Gadfly.Geom.path]
lt == :scatter && return [Gadfly.Geom.point]
# lt == :scatter && return [Gadfly.Geom.point]
lt == :bar && return [Gadfly.Geom.bar]
lt == :steppost && return [Gadfly.Geom.step]
# NOTE: we won't actually show this (we'll set width to 0 later), but we need a geom so that Gadfly doesn't complain
if lt in (:none, :ohlc)
if lt in (:none, :ohlc, :scatter)
return [Gadfly.Geom.path]
end
@@ -90,19 +135,51 @@ function addGadflyFixedLines!(gplt, d::Dict, theme)
end
function getGadflyStrokeVector(linestyle::Symbol)
dash = 12 * Compose.mm
dot = 3 * Compose.mm
gap = 2 * Compose.mm
linestyle == :solid && return nothing
linestyle == :dash && return [dash, gap]
linestyle == :dot && return [dot, gap]
linestyle == :dashdot && return [dash, gap, dot, gap]
linestyle == :dashdotdot && return [dash, gap, dot, gap, dot, gap]
error("unsupported linestyle: ", linestyle)
end
# # const x_continuous = continuous_scale_partial(x_vars, identity_transform)
# # const y_continuous = continuous_scale_partial(y_vars, identity_transform)
# # const x_log10 = continuous_scale_partial(x_vars, log10_transform)
# # const y_log10 = continuous_scale_partial(y_vars, log10_transform)
# # const x_log2 = continuous_scale_partial(x_vars, log2_transform)
# # const y_log2 = continuous_scale_partial(y_vars, log2_transform)
# # const x_log = continuous_scale_partial(x_vars, ln_transform)
# # const y_log = continuous_scale_partial(y_vars, ln_transform)
# # const x_asinh = continuous_scale_partial(x_vars, asinh_transform)
# # const y_asinh = continuous_scale_partial(y_vars, asinh_transform)
# # const x_sqrt = continuous_scale_partial(x_vars, sqrt_transform)
# # const y_sqrt = continuous_scale_partial(y_vars, sqrt_transform)
# function addGadflyScales(gplt, d::Dict)
# for k in (:xscale, :yscale)
# isx = k == :xscale
# scale = d[k]
# if scale == :log
# push!(gplt.scales, isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log)
# elseif scale == :log2
# push!(gplt.scales, isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log2)
# elseif scale == :log10
# push!(gplt.scales, isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log10)
# elseif scale == :asinh
# push!(gplt.scales, isx ? Gadfly.Scale.x_asinh : Gadfly.Scale.y_asinh)
# elseif scale == :sqrt
# push!(gplt.scales, isx ? Gadfly.Scale.x_sqrt : Gadfly.Scale.y_sqrt)
# end
# end
# end
# function getGadflyStrokeVector(linestyle::Symbol)
# dash = 12 * Compose.mm
# dot = 3 * Compose.mm
# gap = 2 * Compose.mm
# linestyle == :solid && return nothing
# linestyle == :dash && return [dash, gap]
# linestyle == :dot && return [dot, gap]
# linestyle == :dashdot && return [dash, gap, dot, gap]
# linestyle == :dashdotdot && return [dash, gap, dot, gap, dot, gap]
# error("unsupported linestyle: ", linestyle)
# end
createSegments(z) = collect(repmat(z',2,1))[2:end]
Base.first(c::Colorant) = c
function addGadflySeries!(gplt, d::Dict, initargs::Dict)
@@ -111,8 +188,8 @@ function addGadflySeries!(gplt, d::Dict, initargs::Dict)
# if my PR isn't present, don't set the line_style
local extra_theme_args
try
Gadfly.getStrokeVector(:solid)
extra_theme_args = [(:line_style, getGadflyStrokeVector(d[:linestyle]))]
extra_theme_args = [(:line_style, Gadfly.get_stroke_vector(d[:linestyle]))]
# extra_theme_args = [(:line_style, getGadflyStrokeVector(d[:linestyle]))]
catch
extra_theme_args = []
end
@@ -120,9 +197,10 @@ function addGadflySeries!(gplt, d::Dict, initargs::Dict)
# line_style = getGadflyStrokeVector(d[:linestyle])
# set theme: color, line width, and point size
line_width = d[:width] * (d[:linetype] in (:none, :ohlc) ? 0 : 1) * Gadfly.px # 0 width when we don't show a line
line_width = d[:width] * (d[:linetype] in (:none, :ohlc, :scatter) ? 0 : 1) * Gadfly.px # 0 width when we don't show a line
line_color = isa(d[:color], AbstractVector) ? colorant"black" : d[:color]
# fg = initargs[:foreground_color]
theme = Gadfly.Theme(; default_color = d[:color],
theme = Gadfly.Theme(; default_color = line_color,
line_width = line_width,
default_point_size = 0.5 * d[:markersize] * Gadfly.px,
# grid_color = fg,
@@ -134,7 +212,7 @@ function addGadflySeries!(gplt, d::Dict, initargs::Dict)
# line_style = line_style)
push!(gfargs, theme)
# first things first... lets so the sticks hack
# first things first... lets do the sticks hack
if d[:linetype] == :sticks
d, dScatter = sticksHack(;d...)
@@ -149,20 +227,55 @@ function addGadflySeries!(gplt, d::Dict, initargs::Dict)
end
if d[:linetype] == :scatter
d[:linetype] = :none
if d[:marker] == :none
d[:marker] = :ellipse
end
end
# add the Geoms
append!(gfargs, getLineGeoms(d))
# fillto
if d[:fillto] == nothing
yminmax = []
# colorgroup
if isa(d[:color], AbstractVector)
# create a color scale, and set the color group to the index of the color
push!(gplt.scales, Gadfly.Scale.color_discrete_manual(d[:color]...))
# this is super weird, but... oh well... for some reason this creates n separate line segments...
# create a list of vertices that go: [x1,x2,x2,x3,x3, ... ,xi,xi, ... xn,xn] (same for y)
# then the vector passed to the "color" keyword should be a vector: [1,1,2,2,3,3,4,4, ..., i,i, ... , n,n]
csindices = Int[mod1(i,length(d[:color])) for i in 1:length(d[:y])]
cs = collect(repmat(csindices', 2, 1))[1:end-1]
grp = collect(repmat((1:length(d[:y]))', 2, 1))[1:end-1]
d[:x], d[:y] = map(createSegments, (d[:x], d[:y]))
colorgroup = [(:color, cs), (:group, grp)]
else
fillto = makevec(d[:fillto])
colorgroup = []
end
# fillto and ribbon
yminmax = []
fillto, ribbon = d[:fillto], d[:ribbon]
if fillto != nothing
if ribbon != nothing
warn("Ignoring ribbon arg since fillto is set!")
end
fillto = makevec(fillto)
n = length(fillto)
yminmax = [
(:ymin, Float64[min(y, fillto[mod1(i,n)]) for (i,y) in enumerate(d[:y])]),
(:ymax, Float64[max(y, fillto[mod1(i,n)]) for (i,y) in enumerate(d[:y])])
]
push!(yminmax, (:ymin, Float64[min(y, fillto[mod1(i,n)]) for (i,y) in enumerate(d[:y])]))
push!(yminmax, (:ymax, Float64[max(y, fillto[mod1(i,n)]) for (i,y) in enumerate(d[:y])]))
push!(gfargs, Gadfly.Geom.ribbon)
elseif ribbon != nothing
ribbon = makevec(ribbon)
n = length(ribbon)
@show ribbon
push!(yminmax, (:ymin, Float64[y - ribbon[mod1(i,n)] for (i,y) in enumerate(d[:y])]))
push!(yminmax, (:ymax, Float64[y + ribbon[mod1(i,n)] for (i,y) in enumerate(d[:y])]))
push!(gfargs, Gadfly.Geom.ribbon)
end
# handle markers
@@ -170,6 +283,9 @@ function addGadflySeries!(gplt, d::Dict, initargs::Dict)
append!(gfargs, geoms)
append!(gplt.guides, guides)
# # add scales
# addGadflyScales(gplt, d)
# add a regression line?
if d[:reg]
push!(gfargs, Gadfly.Geom.smooth(method=:lm))
@@ -177,8 +293,14 @@ function addGadflySeries!(gplt, d::Dict, initargs::Dict)
# add to the legend
if length(gplt.guides) > 0 && isa(gplt.guides[1], Gadfly.Guide.ManualColorKey)
# TODO: there's a BUG in gadfly if you pass in the same color more than once,
# since gadfly will call unique(colors), but doesn't also merge the rows that match
# Should ensure from this side that colors which are the same are merged together
push!(gplt.guides[1].labels, d[:label])
push!(gplt.guides[1].colors, d[:marker] == :none ? d[:color] : d[:markercolor])
push!(gplt.guides[1].colors, d[:marker] == :none ? first(d[:color]) : d[:markercolor])
# println("updated legend: ", gplt.guides)
end
# for histograms, set x=y
@@ -191,36 +313,89 @@ function addGadflySeries!(gplt, d::Dict, initargs::Dict)
# add the layer to the Gadfly.Plot
# prepend!(gplt.layers, Gadfly.layer(unique(gfargs)..., d[:args]...; x = x, y = d[:y], d[:kwargs]...))
prepend!(gplt.layers, Gadfly.layer(unique(gfargs)...; x = x, y = d[:y], yminmax...))
prepend!(gplt.layers, Gadfly.layer(unique(gfargs)...; x = x, y = d[:y], colorgroup..., yminmax...))
nothing
end
function replaceType(vec, val)
filter!(x -> !isa(x, typeof(val)), vec)
push!(vec, val)
end
function addTicksGuide(gplt, ticks, isx::Bool)
function addGadflyTicksGuide(gplt, ticks, isx::Bool)
ticks == :auto && return
ttype = ticksType(ticks)
if ttype == :ticks
gtype = isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks
filter!(x -> !isa(x, gtype), gplt.guides)
push!(gplt.guides, gtype(ticks = sort(collect(ticks))))
replaceType(gplt.guides, gtype(ticks = collect(ticks)))
elseif ttype == :ticks_and_labels
gtype = isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks
replaceType(gplt.guides, gtype(ticks = collect(ticks[1])))
# TODO add xtick_label function (given tick, return label??)
# Scale.x_discrete(; labels=nothing, levels=nothing, order=nothing)
filterGadflyScale(gplt, isx)
gfunc = isx ? Gadfly.Scale.x_discrete : Gadfly.Scale.y_discrete
labelmap = Dict(zip(ticks...))
labelfunc = val -> labelmap[val]
push!(gplt.scales, gfunc(levels = ticks[1], labels = labelfunc))
else
error("Invalid input for $(isx ? "xticks" : "yticks"): ", ticks)
end
end
isContinuousScale(scale, isx::Bool) = isa(scale, Gadfly.Scale.ContinuousScale) && scale.vars[1] == (isx ? :x : :y)
# isContinuousScale(scale, isx::Bool) = isa(scale, Gadfly.Scale.ContinuousScale) && scale.vars[1] == (isx ? :x : :y)
filterGadflyScale(gplt, isx::Bool) = filter!(scale -> scale.vars[1] != (isx ? :x : :y), gplt.scales)
function addLimitsScale(gplt, lims, isx::Bool)
lims == :auto && return
ltype = limsType(lims)
if ltype == :limits
# remove any existing scales, then add a new one
gfunc = isx ? Gadfly.Scale.x_continuous : Gadfly.Scale.y_continuous
filter!(scale -> !isContinuousScale(scale,isx), gplt.scales)
push!(gplt.scales, gfunc(minvalue = min(lims...), maxvalue = max(lims...)))
else
error("Invalid input for $(isx ? "xlims" : "ylims"): ", lims)
function getGadflyScaleFunction(d::Dict, isx::Bool)
scalekey = isx ? :xscale : :yscale
hasScaleKey = haskey(d, scalekey)
if hasScaleKey
scale = d[scalekey]
scale == :log && return isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log, hasScaleKey
scale == :log2 && return isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log2, hasScaleKey
scale == :log10 && return isx ? Gadfly.Scale.x_log2 : Gadfly.Scale.y_log10, hasScaleKey
scale == :asinh && return isx ? Gadfly.Scale.x_asinh : Gadfly.Scale.y_asinh, hasScaleKey
scale == :sqrt && return isx ? Gadfly.Scale.x_sqrt : Gadfly.Scale.y_sqrt, hasScaleKey
end
isx ? Gadfly.Scale.x_continuous : Gadfly.Scale.y_continuous, hasScaleKey
end
function addGadflyLimitsScale(gplt, d::Dict, isx::Bool)
# get the correct scale function
gfunc, hasScaleKey = getGadflyScaleFunction(d, isx)
# @show d gfunc hasScaleKey
# do we want to add min/max limits for the axis?
limsym = isx ? :xlims : :ylims
limargs = []
if haskey(d, limsym)
lims = d[limsym]
lims == :auto && return
if limsType(lims) == :limits
# remove any existing scales, then add a new one
# filterGadflyScale(gplt, isx)
# gfunc = isx ? Gadfly.Scale.x_continuous : Gadfly.Scale.y_continuous
# filter!(scale -> !isContinuousScale(scale,isx), gplt.scales)
# push!(gplt.scales, gfunc(minvalue = min(lims...), maxvalue = max(lims...)))
push!(limargs, (:minvalue, min(lims...)))
push!(limargs, (:maxvalue, max(lims...)))
else
error("Invalid input for $(isx ? "xlims" : "ylims"): ", lims)
end
end
# @show limargs
# replace any current scales with this one
if hasScaleKey || !isempty(limargs)
filterGadflyScale(gplt, isx)
push!(gplt.scales, gfunc(; limargs...))
end
# @show gplt.scales
return
end
@@ -256,10 +431,11 @@ function updateGadflyGuides(gplt, d::Dict)
haskey(d, :title) && findGuideAndSet(gplt, Gadfly.Guide.title, d[:title])
haskey(d, :xlabel) && findGuideAndSet(gplt, Gadfly.Guide.xlabel, d[:xlabel])
haskey(d, :ylabel) && findGuideAndSet(gplt, Gadfly.Guide.ylabel, d[:ylabel])
haskey(d, :xlims) && addLimitsScale(gplt, d[:xlims], true)
haskey(d, :ylims) && addLimitsScale(gplt, d[:ylims], false)
haskey(d, :xticks) && addTicksGuide(gplt, d[:xticks], true)
haskey(d, :yticks) && addTicksGuide(gplt, d[:yticks], false)
addGadflyLimitsScale(gplt, d, true)
addGadflyLimitsScale(gplt, d, false)
haskey(d, :xticks) && addGadflyTicksGuide(gplt, d[:xticks], true)
haskey(d, :yticks) && addGadflyTicksGuide(gplt, d[:yticks], false)
end
function updatePlotItems(plt::Plot{GadflyPackage}, d::Dict)
@@ -269,6 +445,22 @@ end
# ----------------------------------------------------------------
function createGadflyAnnotationObject(x, y, val::AbstractString)
Gadfly.Guide.annotation(Compose.compose(
Compose.context(),
Compose.text(x, y, val)
))
end
function addAnnotations{X,Y,V}(plt::Plot{GadflyPackage}, anns::AVec{Tuple{X,Y,V}})
for ann in anns
push!(plt.o.guides, createGadflyAnnotationObject(ann...))
end
end
# ----------------------------------------------------------------
# create the underlying object (each backend will do this differently)
function buildSubplotObject!(subplt::Subplot{GadflyPackage})
subplt.o = nothing
@@ -285,7 +477,7 @@ function buildGadflySubplotContext(subplt::Subplot)
i = 0
rows = []
for rowcnt in subplt.layout.rowcounts
push!(rows, Gadfly.hstack([getGadflyContext(plt.plotter, plt) for plt in subplt.plts[(1:rowcnt) + i]]...))
push!(rows, Gadfly.hstack([getGadflyContext(plt.backend, plt) for plt in subplt.plts[(1:rowcnt) + i]]...))
i += rowcnt
end
Gadfly.vstack(rows...)
@@ -296,7 +488,7 @@ function setGadflyDisplaySize(w,h)
end
function Base.writemime(io::IO, ::MIME"image/png", plt::Plot{GadflyPackage})
gplt = getGadflyContext(plt.plotter, plt)
gplt = getGadflyContext(plt.backend, plt)
setGadflyDisplaySize(plt.initargs[:size]...)
Gadfly.draw(Gadfly.PNG(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt)
end
@@ -310,7 +502,7 @@ end
function Base.writemime(io::IO, ::MIME"image/png", plt::Subplot{GadflyPackage})
gplt = getGadflyContext(plt.plotter, plt)
gplt = getGadflyContext(plt.backend, plt)
setGadflyDisplaySize(plt.initargs[1][:size]...)
Gadfly.draw(Gadfly.PNG(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt)
end
+13 -8
View File
@@ -54,7 +54,7 @@ function createGadflyAnnotation(d::Dict)
shape = Gadfly.circle(xs,ys,[sz])
end
Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), shape, Gadfly.fill(d[:markercolor]), Gadfly.stroke(nothing)))
Gadfly.Guide.annotation(Gadfly.compose(Gadfly.context(), shape, Gadfly.fill(d[:markercolor]), Gadfly.stroke(colorant"white")))
end
@@ -165,19 +165,24 @@ function star1(xs::AbstractArray, ys::AbstractArray, rs::AbstractArray, scalar =
polys = Vector{Vector{Tuple{Compose.Measure, Compose.Measure}}}(n)
# some magic scalars
sx = 0.7
sy1, sy2 = 1.2, 0.4
sx1, sx2, sx3 = 0.7, 0.4, 0.2
sy1, sy2, sy3 = 1.2, 0.45, 0.1
for i in 1:n
x = Compose.x_measure(xs[mod1(i, length(xs))])
y = Compose.y_measure(ys[mod1(i, length(ys))])
r = rs[mod1(i, length(rs))]
polys[i] = Tuple{Compose.Measure, Compose.Measure}[
(x-sx*r, y+r), # BL
(x, y-sy1*r), # T
(x+sx*r, y+r), # BR
(x-r, y-sy2*r), # L
(x+r, y-sy2*r) # R
(x-sx1*r, y+ r), # BL
(x, y+sy2*r),
(x+sx1*r, y+ r), # BR
(x+sx2*r, y+sy3*r),
(x+ r, y-sy2*r), # R
(x+sx3*r, y-sy2*r),
(x, y-sy1*r), # T
(x-sx3*r, y-sy2*r),
(x- r, y-sy2*r), # L
(x-sx2*r, y+sy3*r)
]
end
+31 -4
View File
@@ -3,8 +3,8 @@
immutable ImmersePackage <: PlottingPackage end
export immerse!
immerse!() = plotter!(:immerse)
export immerse
immerse() = backend(:immerse)
supportedArgs(::ImmersePackage) = supportedArgs(GadflyPackage())
@@ -12,6 +12,7 @@ supportedAxes(::ImmersePackage) = supportedAxes(GadflyPackage())
supportedTypes(::ImmersePackage) = supportedTypes(GadflyPackage())
supportedStyles(::ImmersePackage) = supportedStyles(GadflyPackage())
supportedMarkers(::ImmersePackage) = supportedMarkers(GadflyPackage())
supportedScales(::ImmersePackage) = supportedScales(GadflyPackage())
function createImmerseFigure(d::Dict)
@@ -49,6 +50,32 @@ function updatePlotItems(plt::Plot{ImmersePackage}, d::Dict)
end
# ----------------------------------------------------------------
function addAnnotations{X,Y,V}(plt::Plot{ImmersePackage}, anns::AVec{Tuple{X,Y,V}})
for ann in anns
push!(plt.o[2].guides, createGadflyAnnotationObject(ann...))
end
end
# ----------------------------------------------------------------
# accessors for x/y data
function Base.getindex(plt::Plot{ImmersePackage}, i::Int)
data = plt.o[2].layers[end-i+1].mapping
data[:x], data[:y]
end
function Base.setindex!(plt::Plot{ImmersePackage}, xy::Tuple, i::Integer)
data = plt.o[2].layers[end-i+1].mapping
data[:x], data[:y] = xy
plt
end
# ----------------------------------------------------------------
@@ -102,7 +129,7 @@ getGadflyContext(::ImmersePackage, plt::Plot) = plt.o[2]
getGadflyContext(::ImmersePackage, subplt::Subplot) = buildGadflySubplotContext(subplt)
function Base.writemime(io::IO, ::MIME"image/png", plt::Plot{ImmersePackage})
gplt = getGadflyContext(plt.plotter, plt)
gplt = getGadflyContext(plt.backend, plt)
setGadflyDisplaySize(plt.initargs[:size]...)
Gadfly.draw(Gadfly.PNG(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt)
end
@@ -122,7 +149,7 @@ end
function Base.writemime(io::IO, ::MIME"image/png", plt::Subplot{ImmersePackage})
gplt = getGadflyContext(plt.plotter, plt)
gplt = getGadflyContext(plt.backend, plt)
setGadflyDisplaySize(plt.initargs[1][:size]...)
Gadfly.draw(Gadfly.PNG(io, Compose.default_graphic_width, Compose.default_graphic_height), gplt)
end
+131 -31
View File
@@ -3,16 +3,60 @@
immutable PyPlotPackage <: PlottingPackage end
export pyplot!
pyplot!() = plotter!(:pyplot)
export pyplot
pyplot() = backend(:pyplot)
# -------------------------------
supportedArgs(::PyPlotPackage) = setdiff(_allArgs, [:reg, :heatmap_c, :fillto, :pos, :xlims, :ylims, :xticks, :yticks])
# supportedArgs(::PyPlotPackage) = setdiff(_allArgs, [:reg, :heatmap_c, :fillto, :pos, :xlims, :ylims, :xticks, :yticks])
supportedArgs(::PyPlotPackage) = [
:annotation,
# :args,
:axis,
:background_color,
:color,
# :fillto,
:foreground_color,
:group,
# :heatmap_c,
# :kwargs,
:label,
:layout,
:legend,
:linestyle,
:linetype,
:marker,
:markercolor,
:markersize,
:n,
:nbins,
:nc,
:nr,
# :pos,
# :reg,
# :ribbon,
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
:yrightlabel,
:yticks,
:xscale,
:yscale,
]
supportedAxes(::PyPlotPackage) = _allAxes
supportedTypes(::PyPlotPackage) = [:none, :line, :path, :step, :stepinverted, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar]
supportedTypes(::PyPlotPackage) = [:none, :line, :path, :step, :stepinverted, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline]
supportedStyles(::PyPlotPackage) = [:auto, :solid, :dash, :dot, :dashdot]
supportedMarkers(::PyPlotPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :hexagon]
supportedScales(::PyPlotPackage) = [:identity, :log, :log2, :log10]
subplotSupported(::PyPlotPackage) = false
# convert colorant to 4-tuple RGBA
@@ -149,17 +193,29 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
# PyPlot.figure(num) # makes this current
# makePyPlotCurrent(plt)
if !(d[:linetype] in supportedTypes(pkg))
error("linetype $(d[:linetype]) is unsupported in PyPlot. Choose from: $(supportedTypes(pkg))")
lt = d[:linetype]
if !(lt in supportedTypes(pkg))
error("linetype $(lt) is unsupported in PyPlot. Choose from: $(supportedTypes(pkg))")
end
if d[:linetype] == :sticks
if lt == :sticks
d,_ = sticksHack(;d...)
elseif d[:linetype] == :scatter
elseif lt == :scatter
d[:linetype] = :none
if d[:marker] == :none
d[:marker] = :ellipse
end
elseif lt in (:hline,:vline)
linewidth = d[:width]
linecolor = getPyPlotColor(d[:color])
linestyle = getPyPlotLineStyle(lt, d[:linestyle])
for yi in d[:y]
func = (lt == :hline ? PyPlot.axhline : PyPlot.axvline)
func(yi, linewidth=d[:width], color=linecolor, linestyle=linestyle)
end
end
lt = d[:linetype]
@@ -225,32 +281,79 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
end
function updatePlotItems(plt::Plot{PyPlotPackage}, d::Dict)
# makePyPlotCurrent(plt)
haskey(d, :title) && PyPlot.title(d[:title])
haskey(d, :xlabel) && PyPlot.xlabel(d[:xlabel])
if haskey(d, :ylabel)
ax = getLeftAxis(plt.o[1])
ax[:set_ylabel](d[:ylabel])
end
if haskey(d, :yrightlabel)
ax = getRightAxis(plt.o[1])
ax[:set_ylabel](d[:yrightlabel])
# -----------------------------------------------------------------
function addPyPlotLims(lims, isx::Bool)
lims == :auto && return
ltype = limsType(lims)
if ltype == :limits
(isx ? PyPlot.xlim : PyPlot.ylim)(lims...)
else
error("Invalid input for $(isx ? "xlims" : "ylims"): ", lims)
end
end
function addPyPlotTicks(ticks, isx::Bool)
ticks == :auto && return
ttype = ticksType(ticks)
if ttype == :ticks
(isx ? PyPlot.xticks : PyPlot.yticks)(ticks)
elseif ttype == :ticks_and_labels
(isx ? PyPlot.xticks : PyPlot.yticks)(ticks...)
else
error("Invalid input for $(isx ? "xticks" : "yticks"): ", ticks)
end
end
function updatePlotItems(plt::Plot{PyPlotPackage}, d::Dict)
fig = plt.o[1]
# -------------------------------
# title and axis labels
haskey(d, :title) && PyPlot.title(d[:title])
haskey(d, :xlabel) && PyPlot.xlabel(d[:xlabel])
if haskey(d, :ylabel)
ax = getLeftAxis(fig)
ax[:set_ylabel](d[:ylabel])
end
if haskey(d, :yrightlabel)
ax = getRightAxis(fig)
ax[:set_ylabel](d[:yrightlabel])
end
# function savepng(::PyPlotPackage, plt::PlottingObject, fn::AbstractString, args...)
# fig, num = plt.o
# addPyPlotLegend(plt)
# f = open(fn, "w")
# writemime(f, "image/png", fig)
# close(f)
# end
# limits and ticks
haskey(d, :xlims) && addPyPlotLims(d[:xlims], true)
haskey(d, :ylims) && addPyPlotLims(d[:ylims], false)
haskey(d, :xticks) && addPyPlotTicks(d[:xticks], true)
haskey(d, :yticks) && addPyPlotTicks(d[:yticks], false)
# scales
ax = getLeftAxis(fig)
haskey(d, :xscale) && applyPyPlotScale(ax, d[:xscale], true)
haskey(d, :yscale) && applyPyPlotScale(ax, d[:yscale], false)
end
function applyPyPlotScale(ax, scaleType::Symbol, isx::Bool)
func = ax[isx ? :set_xscale : :set_yscale]
scaleType == :identity && return func("linear")
scaleType == :log && return func("log", basex = e, basey = e)
scaleType == :log2 && return func("log", basex = 2, basey = 2)
scaleType == :log10 && return func("log", basex = 10, basey = 10)
warn("Unhandled scaleType: ", scaleType)
end
# -----------------------------------------------------------------
function createPyPlotAnnotationObject(plt::Plot{PyPlotPackage}, x, y, val::AbstractString)
ax = getLeftAxis(plt.o[1])
ax[:annotate](val, xy = (x,y))
end
function addAnnotations{X,Y,V}(plt::Plot{PyPlotPackage}, anns::AVec{Tuple{X,Y,V}})
for ann in anns
createPyPlotAnnotationObject(plt, ann...)
end
end
# -----------------------------------------------------------------
@@ -264,7 +367,7 @@ end
function addPyPlotLegend(plt::Plot)
if plt.initargs[:legend]
# gotta do this to ensure both axes are included
args = filter(x -> !(x[:linetype] in (:hist,:hexbin,:heatmap)), plt.seriesargs)
args = filter(x -> !(x[:linetype] in (:hist,:hexbin,:heatmap,:hline,:vline)), plt.seriesargs)
if length(args) > 0
PyPlot.legend([d[:serieshandle] for d in args], [d[:label] for d in args], loc="best")
end
@@ -274,7 +377,6 @@ end
function Base.writemime(io::IO, m::MIME"image/png", plt::PlottingObject{PyPlotPackage})
fig, num = plt.o
# makePyPlotCurrent(plt)
addPyPlotLegend(plt)
ax = fig.o[:axes][1]
updateAxisColors(ax, getPyPlotColor(plt.initargs[:foreground_color]))
@@ -284,8 +386,6 @@ end
function Base.display(::PlotsDisplay, plt::Plot{PyPlotPackage})
fig, num = plt.o
# PyPlot.figure(num) # makes this current
# makePyPlotCurrent(plt)
addPyPlotLegend(plt)
ax = fig.o[:axes][1]
updateAxisColors(ax, getPyPlotColor(plt.initargs[:foreground_color]))
+159 -9
View File
@@ -3,12 +3,56 @@
immutable QwtPackage <: PlottingPackage end
export qwt!
qwt!() = plotter!(:qwt)
export qwt
qwt() = backend(:qwt)
supportedArgs(::QwtPackage) = setdiff(_allArgs, [:xlims, :ylims, :xticks, :yticks])
supportedTypes(::QwtPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar]
# supportedArgs(::QwtPackage) = setdiff(_allArgs, [:xlims, :ylims, :xticks, :yticks])
supportedArgs(::QwtPackage) = [
:annotation,
# :args,
:axis,
:background_color,
:color,
:fillto,
:foreground_color,
:group,
:heatmap_c,
# :kwargs,
:label,
:layout,
:legend,
:linestyle,
:linetype,
:marker,
:markercolor,
:markersize,
:n,
:nbins,
:nc,
:nr,
:pos,
:reg,
# :ribbon,
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
:yrightlabel,
:yticks,
:xscale,
:yscale,
]
supportedTypes(::QwtPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline]
supportedMarkers(::QwtPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1, :star2, :hexagon]
supportedScales(::QwtPackage) = [:identity, :log10]
# -------------------------------
@@ -26,16 +70,27 @@ function replaceLinetypeAlias(d)
end
end
function adjustQwtKeywords(iscreating::Bool; kw...)
function adjustQwtKeywords(plt::Plot{QwtPackage}, iscreating::Bool; kw...)
d = Dict(kw)
if d[:linetype] == :scatter
lt = d[:linetype]
if lt == :scatter
d[:linetype] = :none
if d[:marker] == :none
d[:marker] = :ellipse
end
elseif !iscreating && d[:linetype] == :bar
elseif lt in (:hline, :vline)
addLineMarker(plt, d)
d[:linetype] = :none
d[:marker] = :ellipse
d[:markersize] = 1
if lt == :vline
d[:x], d[:y] = d[:y], d[:x]
end
elseif !iscreating && lt == :bar
d = barHack(; kw...)
elseif !iscreating && d[:linetype] == :hist
elseif !iscreating && lt == :hist
d = barHack(; histogramHack(; kw...)...)
end
@@ -51,18 +106,113 @@ function plot(pkg::QwtPackage; kw...)
end
function plot!(::QwtPackage, plt::Plot; kw...)
d = adjustQwtKeywords(false; kw...)
d = adjustQwtKeywords(plt, false; kw...)
Qwt.oplot(plt.o; d...)
push!(plt.seriesargs, d)
plt
end
# ----------------------------------------------------------------
function updateLimsAndTicks(plt::Plot{QwtPackage}, d::Dict, isx::Bool)
lims = get(d, isx ? :xlims : :ylims, nothing)
ticks = get(d, isx ? :xticks : :yticks, nothing)
w = plt.o.widget
axisid = Qwt.QWT.QwtPlot[isx ? :xBottom : :yLeft]
if typeof(lims) <: Tuple
if isx
plt.o.autoscale_x = false
else
plt.o.autoscale_y = false
end
w[:setAxisScale](axisid, lims...)
end
if typeof(ticks) <: Range
if isx
plt.o.autoscale_x = false
else
plt.o.autoscale_y = false
end
w[:setAxisScale](axisid, float(minimum(ticks)), float(maximum(ticks)), float(step(ticks)))
elseif ticks != nothing
warn("Only Range types are supported for Qwt xticks/yticks. typeof(ticks)=$(typeof(ticks))")
end
# change the scale
scalesym = isx ? :xscale : :yscale
if haskey(d, scalesym)
scaletype = d[scalesym]
scaletype == :identity && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLinearScaleEngine())
# scaletype == :log && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(e))
# scaletype == :log2 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLogScaleEngine(2))
scaletype == :log10 && w[:setAxisScaleEngine](axisid, Qwt.QWT.QwtLog10ScaleEngine())
scaletype in supportedScales() || warn("Unsupported scale type: ", scaletype)
end
end
function updatePlotItems(plt::Plot{QwtPackage}, d::Dict)
haskey(d, :title) && Qwt.title(plt.o, d[:title])
haskey(d, :xlabel) && Qwt.xlabel(plt.o, d[:xlabel])
haskey(d, :ylabel) && Qwt.ylabel(plt.o, d[:ylabel])
updateLimsAndTicks(plt, d, true)
updateLimsAndTicks(plt, d, false)
end
# ----------------------------------------------------------------
# curve.setPen(Qt.QPen(Qt.QColor(color), width, self.getLineStyle(linestyle)))
function addLineMarker(plt::Plot{QwtPackage}, d::Dict)
for yi in d[:y]
marker = Qwt.QWT.QwtPlotMarker()
ishorizontal = (d[:linetype] == :hline)
marker[:setLineStyle](ishorizontal ? 1 : 2)
marker[ishorizontal ? :setYValue : :setXValue](yi)
qcolor = Qwt.convertRGBToQColor(d[:color])
linestyle = plt.o.widget[:getLineStyle](string(d[:linestyle]))
marker[:setLinePen](Qwt.QT.QPen(qcolor, d[:width], linestyle))
marker[:attach](plt.o.widget)
end
# marker[:setValue](x, y)
# marker[:setLabel](Qwt.QWT.QwtText(val))
# marker[:attach](plt.o.widget)
end
function createQwtAnnotation(plt::Plot, x, y, val::AbstractString)
marker = Qwt.QWT.QwtPlotMarker()
marker[:setValue](x, y)
marker[:setLabel](Qwt.QWT.QwtText(val))
marker[:attach](plt.o.widget)
end
function addAnnotations{X,Y,V}(plt::Plot{QwtPackage}, anns::AVec{Tuple{X,Y,V}})
for ann in anns
createQwtAnnotation(plt, ann...)
end
end
# ----------------------------------------------------------------
# accessors for x/y data
function Base.getindex(plt::Plot{QwtPackage}, i::Int)
series = plt.o.lines[i]
series.x, series.y
end
function Base.setindex!(plt::Plot{QwtPackage}, xy::Tuple, i::Integer)
series = plt.o.lines[i]
series.x, series.y = xy
plt
end
# -------------------------------
# savepng(::QwtPackage, plt::PlottingObject, fn::AbstractString, args...) = Qwt.savepng(plt.o, fn)
+47 -3
View File
@@ -5,16 +5,60 @@
immutable [PkgName]Package <: PlottingPackage end
export [pkgname]!
[pkgname]!() = plotter!(:[pkgname])
export [pkgname]
[pkgname]() = backend(:[pkgname])
# ---------------------------------------------------------------------------
supportedArgs(::[PkgName]Package) = _allArgs
# supportedArgs(::[PkgName]Package) = _allArgs
supportedArgs(::[PkgName]Package) = [
:annotation,
# :args,
:axis,
:background_color,
:color,
:fillto,
:foreground_color,
:group,
# :heatmap_c,
# :kwargs,
:label,
:layout,
:legend,
:linestyle,
:linetype,
:marker,
:markercolor,
:markersize,
:n,
:nbins,
:nc,
:nr,
# :pos,
:reg,
# :ribbon,
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
:yticks,
# :xscale,
# :yscale,
]
supportedAxes(::[PkgName]Package) = _allAxes
supportedTypes(::[PkgName]Package) = _allTypes
supportedStyles(::[PkgName]Package) = _allStyles
supportedMarkers(::[PkgName]Package) = _allMarkers
supportedScales(::[PkgName]Package) = _allScales
subplotSupported(::[PkgName]Package) = false
# ---------------------------------------------------------------------------
+88 -13
View File
@@ -3,16 +3,60 @@
immutable UnicodePlotsPackage <: PlottingPackage end
export unicodeplots!
unicodeplots!() = plotter!(:unicodeplots)
export unicodeplots
unicodeplots() = backend(:unicodeplots)
# -------------------------------
supportedArgs(::UnicodePlotsPackage) = setdiff(_allArgs, [:reg, :heatmap_c, :fillto, :pos, :xlims, :ylims, :xticks, :yticks])
# supportedArgs(::UnicodePlotsPackage) = setdiff(_allArgs, [:reg, :heatmap_c, :fillto, :pos, :xlims, :ylims, :xticks, :yticks])
supportedArgs(::UnicodePlotsPackage) = [
# :annotation,
# :args,
# :axis,
# :background_color,
# :color,
# :fillto,
# :foreground_color,
:group,
# :heatmap_c,
# :kwargs,
:label,
# :layout,
:legend,
:linestyle,
:linetype,
:marker,
# :markercolor,
# :markersize,
# :n,
:nbins,
# :nc,
# :nr,
# :pos,
# :reg,
# :ribbon,
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,
:xlims,
# :xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
# :yticks,
# :xscale,
# :yscale,
]
supportedAxes(::UnicodePlotsPackage) = [:auto, :left]
supportedTypes(::UnicodePlotsPackage) = [:none, :line, :path, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar]
supportedTypes(::UnicodePlotsPackage) = [:none, :line, :path, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline]
supportedStyles(::UnicodePlotsPackage) = [:auto, :solid]
supportedMarkers(::UnicodePlotsPackage) = [:none, :auto, :ellipse]
supportedScales(::UnicodePlotsPackage) = [:identity]
function expandLimits!(lims, x)
@@ -28,17 +72,35 @@ 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])
iargs = plt.initargs
# get the x/y limits
if get(iargs, :xlims, :auto) == :auto
xlim = [Inf, -Inf]
for d in sargs
expandLimits!(xlim, d[:x])
end
else
xmin, xmax = iargs[:xlims]
xlim = [xmin, xmax]
end
if get(iargs, :ylims, :auto) == :auto
ylim = [Inf, -Inf]
for d in sargs
expandLimits!(ylim, d[:y])
end
else
ymin, ymax = iargs[:ylims]
ylim = [ymin, ymax]
end
# we set x/y to have a single point, since we need to create the plot with some data.
# since this point is at the bottom left corner of the plot, it shouldn't actually be shown
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,
@@ -53,7 +115,7 @@ function rebuildUnicodePlot!(plt::Plot)
# now use the ! functions to add to the plot
for d in sargs
addUnicodeSeries!(o, d, iargs[:legend])
addUnicodeSeries!(o, d, iargs[:legend], xlim, ylim)
end
# save the object
@@ -62,10 +124,23 @@ end
# add a single series
function addUnicodeSeries!(o, d::Dict, addlegend::Bool)
function addUnicodeSeries!(o, d::Dict, addlegend::Bool, xlim, ylim)
# get the function, or special handling for step/bar/hist
lt = d[:linetype]
# handle hline/vline separately
if lt in (:hline,:vline)
for yi in d[:y]
if lt == :hline
UnicodePlots.lineplot!(o, xlim, [yi,yi])
else
UnicodePlots.lineplot!(o, [yi,yi], ylim)
end
end
return
end
stepstyle = :post
if lt == :path
func = UnicodePlots.lineplot!
@@ -124,7 +199,7 @@ end
function updatePlotItems(plt::Plot{UnicodePlotsPackage}, d::Dict)
for k in (:title, :xlabel, :ylabel)
for k in (:title, :xlabel, :ylabel, :xlims, :ylims)
if haskey(d, k)
plt.initargs[k] = d[k]
end
+90 -17
View File
@@ -5,8 +5,8 @@
immutable WinstonPackage <: PlottingPackage end
export winston!
winston!() = plotter!(:winston)
export winston
winston() = backend(:winston)
# ---------------------------------------------------------------------------
@@ -30,13 +30,62 @@ const winston_marker = Dict(:none=>".",
)
supportedArgs(::WinstonPackage) = setdiff(_allArgs, [:heatmap_c, :fillto, :pos, :markercolor, :background_color, :xlims, :ylims, :xticks, :yticks])
# supportedArgs(::WinstonPackage) = setdiff(_allArgs, [:heatmap_c, :fillto, :pos, :markercolor, :background_color, :xlims, :ylims, :xticks, :yticks])
supportedArgs(::WinstonPackage) = [
:annotation,
# :args,
# :axis,
# :background_color,
:color,
:fillto,
# :foreground_color,
:group,
# :heatmap_c,
# :kwargs,
:label,
# :layout,
:legend,
:linestyle,
:linetype,
:marker,
:markercolor,
:markersize,
# :n,
:nbins,
# :nc,
# :nr,
# :pos,
:reg,
# :ribbon,
:show,
:size,
:title,
:width,
:windowtitle,
:x,
:xlabel,
:xlims,
# :xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
# :yticks,
:xscale,
:yscale,
]
supportedAxes(::WinstonPackage) = [:auto, :left]
supportedTypes(::WinstonPackage) = [:none, :line, :path, :sticks, :scatter, :hist, :bar]
supportedStyles(::WinstonPackage) = intersect(_allStyles, collect(keys(winston_linestyle)))
supportedMarkers(::WinstonPackage) = intersect(_allMarkers, collect(keys(winston_marker)))
supportedStyles(::WinstonPackage) = [:auto, :solid, :dash, :dot, :dashdot]
supportedMarkers(::WinstonPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star1]
supportedScales(::WinstonPackage) = [:identity, :log10]
subplotSupported(::WinstonPackage) = false
function preparePlotUpdate(plt::Plot{WinstonPackage})
Winston.ghf(plt.o)
end
# ---------------------------------------------------------------------------
@@ -170,29 +219,48 @@ function plot!(::WinstonPackage, plt::Plot; kw...)
end
# ----------------------------------------------------------------
const _winstonNames = Dict(
:xlims => :xrange,
:ylims => :yrange,
:xscale => :xlog,
:yscale => :ylog,
)
function updatePlotItems(plt::Plot{WinstonPackage}, d::Dict)
window, canvas, wplt = getWinstonItems(plt)
for k in (:xlabel, :ylabel, :title)
for k in (:xlabel, :ylabel, :title, :xlims, :ylims)
if haskey(d, k)
Winston.setattr(wplt, string(k), d[k])
Winston.setattr(wplt, string(get(_winstonNames, k, k)), d[k])
end
end
for k in (:xscale, :yscale)
if haskey(d, k)
islogscale = d[k] == :log10
Winston.setattr(wplt, (k == :xscale ? :xlog : :ylog), islogscale)
end
end
end
# -------------------------------
# ----------------------------------------------------------------
# function savepng(::WinstonPackage, plt::PlottingObject, fn::AbstractString; kw...)
# f = open(fn, "w")
# window, canvas, wplt = getWinstonItems(plt)
# addWinstonLegend(plt, wplt)
# writemime(f, "image/png", wplt)
# close(f)
# end
function createWinstonAnnotationObject(plt::Plot{WinstonPackage}, x, y, val::AbstractString)
Winston.text(x, y, val)
end
function addAnnotations{X,Y,V}(plt::Plot{WinstonPackage}, anns::AVec{Tuple{X,Y,V}})
for ann in anns
createWinstonAnnotationObject(plt, ann...)
end
end
# -------------------------------
# ----------------------------------------------------------------
function buildSubplotObject!(subplt::Subplot{WinstonPackage})
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
@@ -201,7 +269,9 @@ end
# ----------------------------------------------------------------
function addWinstonLegend(plt::Plot, wplt)
Winston.legend(wplt, [sd[:label] for sd in plt.seriesargs])
if plt.initargs[:legend]
Winston.legend(wplt, [sd[:label] for sd in plt.seriesargs])
end
end
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{WinstonPackage})
@@ -216,6 +286,9 @@ function Base.display(::PlotsDisplay, plt::Plot{WinstonPackage})
window, canvas, wplt = getWinstonItems(plt)
if window == nothing
if Winston.output_surface != :gtk
error("Gtk is the only supported display for Winston in Plots. Set `output_surface = gtk` in src/Winston.ini")
end
# initialize window
w,h = plt.initargs[:size]
canvas = Gtk.GtkCanvasLeaf()
+1 -1
View File
@@ -143,7 +143,7 @@ function handlePlotColors(::PlottingPackage, d::Dict)
else
bgcolor = _plotDefaults[:background_color]
if d[:background_color] != _plotDefaults[:background_color]
warn("Cannot set background_color with backend $(plotter())")
warn("Cannot set background_color with backend $(backend())")
end
end
d[:background_color] = bgcolor
+171 -43
View File
@@ -6,18 +6,18 @@ const CURRENT_PLOT = CurrentPlot(Nullable{PlottingObject}())
isplotnull() = isnull(CURRENT_PLOT.nullableplot)
function currentPlot()
function current()
if isplotnull()
error("No current plot/subplot")
end
get(CURRENT_PLOT.nullableplot)
end
currentPlot!(plot::PlottingObject) = (CURRENT_PLOT.nullableplot = Nullable(plot))
current(plot::PlottingObject) = (CURRENT_PLOT.nullableplot = Nullable(plot))
# ---------------------------------------------------------
Base.string(plt::Plot) = "Plot{$(plt.plotter) n=$(plt.n)}"
Base.string(plt::Plot) = "Plot{$(plt.backend) n=$(plt.n)}"
Base.print(io::IO, plt::Plot) = print(io, string(plt))
Base.show(io::IO, plt::Plot) = print(io, string(plt))
@@ -32,8 +32,8 @@ doc"""
The main plot command. 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(args...; kw...) # creates a new plot window, and sets it to be the current
plot!(args...; kw...) # adds to the `current`
plot!(plotobj, args...; kw...) # adds to the plot `plotobj`
```
@@ -43,7 +43,7 @@ When you pass in matrices, it splits by columns. See the documentation for more
# this creates a new plot with args/kw and sets it to be the current plot
function plot(args...; kw...)
pkg = plotter()
pkg = backend()
d = Dict(kw)
replaceAliases!(d, _keyAliases)
@@ -59,15 +59,16 @@ function plot(args...; kw...)
end
function plot_display(args...; kw...)
plt = plot(args...; kw...)
display(plt)
plt
end
# this adds to the current plot
# this adds to the current plot, or creates a new plot if none are current
function plot!(args...; kw...)
plot!(currentPlot(), args...; kw...)
local plt
try
plt = current()
catch
return plot(args...; kw...)
end
plot!(current(), args...; kw...)
end
# not allowed:
@@ -81,41 +82,116 @@ function plot!(plt::Plot, args...; kw...)
d = Dict(kw)
replaceAliases!(d, _keyAliases)
warnOnUnsupportedArgs(plt.plotter, d)
warnOnUnsupportedArgs(plt.backend, d)
# TODO: handle a "group by" mechanism.
# will probably want to check for the :group kw param, and split into
# index partitions/filters to be passed through to the next step.
# Ideally we don't change the insides ot createKWargsList too much to
# save from code repetition. We could consider adding a throw
groupargs = get(d, :group, nothing) == nothing ? [] : [extractGroupArgs(d[:group], args...)]
# @show groupargs
# just in case the backend needs to set up the plot (make it current or something)
preparePlotUpdate(plt)
kwList = createKWargsList(plt, args...; d...)
for (i,d) in enumerate(kwList)
# get the list of dictionaries, one per series
kwList, xmeta, ymeta = createKWargsList(plt, groupargs..., args...; d...)
# @show xmeta ymeta typeof(xmeta) typeof(ymeta)
# if we were able to extract guide information from the series inputs, then update the plot
updateDictWithMeta(d, plt.initargs, xmeta, true)
updateDictWithMeta(d, plt.initargs, ymeta, false)
# now we can plot the series
for (i,di) in enumerate(kwList)
plt.n += 1
plot!(plt.plotter, plt; d...)
setTicksFromStringVector(d, di, :x, :xticks)
setTicksFromStringVector(d, di, :y, :yticks)
# @show di[:x] di[:y]
# println("Plotting: ", di)
plot!(plt.backend, plt; di...)
end
addAnnotations(plt, d)
# @show d[:xticks] d[:yticks]
# add title, axis labels, ticks, etc
updatePlotItems(plt, d)
currentPlot!(plt)
current(plt)
# NOTE: lets ignore the show param and effectively use the semicolon at the end of the REPL statement
# # do we want to show it?
# if haskey(d, :show) && d[:show]
# display(plt)
# end
if haskey(d, :show) && d[:show]
gui()
end
plt
end
# --------------------------------------------------------------------
# if x or y are a vector of strings, we should create a list of unique strings,
# and map x/y to be the index of the string... then set the x/y tick labels
function setTicksFromStringVector(d::Dict, di::Dict, sym::Symbol, ticksym::Symbol)
# if the x or y values are strings, set ticks to the unique values, and x/y to the indices of the ticks
# @show sym di
v = di[sym]
# @show v
isa(v, AbstractArray) || return
T = eltype(v)
# @show T
if T <: AbstractString || (!isempty(T.types) && all(x -> x <: AbstractString, T.types))
# @show sym ticksym di[sym]
ticks = unique(di[sym])
# @show ticks
di[sym] = Int[findnext(ticks, v, 1) for v in di[sym]]
if !haskey(d, ticksym) || d[ticksym] == :auto
d[ticksym] = (collect(1:length(ticks)), UTF8String[t for t in ticks])
end
end
# @show sym ticksym di[sym] d[ticksym]
end
# --------------------------------------------------------------------
preparePlotUpdate(plt::Plot) = nothing
# # show/update the plot
# function Base.display(plt::PlottingObject)
# display(plt.plotter, plt)
# end
# --------------------------------------------------------------------
# should we update the x/y label given the meta info during input slicing?
function updateDictWithMeta(d::Dict, initargs::Dict, meta::Symbol, isx::Bool)
lsym = isx ? :xlabel : :ylabel
if initargs[lsym] == default(lsym)
d[lsym] = string(meta)
end
end
updateDictWithMeta(d::Dict, initargs::Dict, meta, isx::Bool) = nothing
# --------------------------------------------------------------------
annotations(::Void) = []
annotations{X<:Real, Y<:Real, V}(v::AVec{Tuple{X,Y,V}}) = v
annotations{X<:Real, Y<:Real, V}(t::Tuple{X,Y,V}) = [t]
annotations(anns) = error("Expecting a tuple (or vector of tuples) for annotations: ",
"(x, y, annotation)\n got: $(typeof(anns))")
function addAnnotations(plt::Plot, d::Dict)
anns = annotations(get(d, :annotation, nothing))
if !isempty(anns)
addAnnotations(plt, anns)
end
end
# --------------------------------------------------------------------
@@ -124,29 +200,33 @@ preparePlotUpdate(plt::Plot) = nothing
# Special handling for: no args, xmin/xmax, parametric, dataframes
# Then once inputs have been converted, build the series args, map functions, etc.
# This should cut down on boilerplate code and allow more focused dispatch on type
# note: returns meta information... mainly for use with automatic labeling from DataFrames for now
typealias FuncOrFuncs Union{Function, AVec{Function}}
# missing
convertToAnyVector(v::Void; kw...) = Any[nothing]
convertToAnyVector(v::Void; kw...) = Any[nothing], nothing
# fixed number of blank series
convertToAnyVector(n::Integer; kw...) = Any[zero(0) for i in 1:n]
convertToAnyVector(n::Integer; kw...) = Any[zero(0) for i in 1:n], nothing
# numeric vector
convertToAnyVector{T<:Real}(v::AVec{T}; kw...) = Any[v]
convertToAnyVector{T<:Real}(v::AVec{T}; kw...) = Any[v], nothing
# string vector
convertToAnyVector{T<:AbstractString}(v::AVec{T}; kw...) = Any[v], nothing
# numeric matrix
convertToAnyVector{T<:Real}(v::AMat{T}; kw...) = Any[v[:,i] for i in 1:size(v,2)]
convertToAnyVector{T<:Real}(v::AMat{T}; kw...) = Any[v[:,i] for i in 1:size(v,2)], nothing
# function
convertToAnyVector(f::Function; kw...) = Any[f]
convertToAnyVector(f::Function; kw...) = Any[f], nothing
# vector of OHLC
convertToAnyVector(v::AVec{OHLC}; kw...) = Any[v]
convertToAnyVector(v::AVec{OHLC}; kw...) = Any[v], nothing
# list of things (maybe other vectors, functions, or something else)
convertToAnyVector(v::AVec; kw...) = Any[vi for vi in v]
convertToAnyVector(v::AVec; kw...) = Any[vi for vi in v], nothing
# --------------------------------------------------------------------
@@ -154,10 +234,13 @@ convertToAnyVector(v::AVec; kw...) = Any[vi for vi in v]
# in computeXandY, we take in any of the possible items, convert into proper x/y vectors, then return.
# this is also where all the "set x to 1:length(y)" happens, and also where we assert on lengths.
computeX(x::Void, y) = 1:length(y)
computeX(x, y) = x
computeX(x, y) = copy(x)
computeY(x, y::Function) = map(y, x)
computeY(x, y) = y
computeY(x, y) = copy(y)
function computeXandY(x, y)
if x == nothing && isa(y, Function)
error("If you want to plot the function `$y`, you need to define the x values somehow!")
end
x, y = computeX(x,y), computeY(x,y)
@assert length(x) == length(y)
x, y
@@ -169,16 +252,36 @@ end
# create n=max(mx,my) series arguments. the shorter list is cycled through
# note: everything should flow through this
function createKWargsList(plt::PlottingObject, x, y; kw...)
xs = convertToAnyVector(x; kw...)
ys = convertToAnyVector(y; kw...)
xs, xmeta = convertToAnyVector(x; kw...)
ys, ymeta = convertToAnyVector(y; kw...)
mx = length(xs)
my = length(ys)
ret = []
for i in 1:max(mx, my)
n = plt.n + i
d = getSeriesArgs(plt.plotter, getinitargs(plt, n), kw, i, convertSeriesIndex(plt, n), n)
# try to set labels using ymeta
d = Dict(kw)
if !haskey(d, :label) && ymeta != nothing
if isa(ymeta, Symbol)
d[:label] = string(ymeta)
elseif isa(ymeta, AVec{Symbol})
d[:label] = string(ymeta[mod1(i,length(ymeta))])
end
end
# build the series arg dict
numUncounted = get(d, :numUncounted, 0)
n = plt.n + i + numUncounted
d = getSeriesArgs(plt.backend, getinitargs(plt, n), d, i + numUncounted, convertSeriesIndex(plt, n), n)
d[:x], d[:y] = computeXandY(xs[mod1(i,mx)], ys[mod1(i,my)])
if haskey(d, :idxfilter)
# @show d[:idxfilter] d[:x] d[:y]
d[:x] = d[:x][d[:idxfilter]]
d[:y] = d[:y][d[:idxfilter]]
end
# for linetype `line`, need to sort by x values
if d[:linetype] == :line
# order by x
indices = sortperm(d[:x])
@@ -187,9 +290,25 @@ function createKWargsList(plt::PlottingObject, x, y; kw...)
d[:linetype] = :path
end
# add it to our series list
push!(ret, d)
end
ret
ret, xmeta, ymeta
end
# handle grouping
function createKWargsList(plt::PlottingObject, groupby::GroupBy, args...; kw...)
ret = []
for (i,glab) in enumerate(groupby.groupLabels)
# TODO: don't automatically overwrite labels
kwlist, xmeta, ymeta = createKWargsList(plt, args...; kw...,
idxfilter = groupby.groupIds[i],
label = string(glab),
numUncounted = length(ret)) # we count the idx from plt.n + numUncounted + i
append!(ret, kwlist)
end
ret, nothing, nothing # TODO: handle passing meta through
end
# pass it off to the x/y version
@@ -228,7 +347,7 @@ function createKWargsList(plt::PlottingObject; kw...)
d = Dict(kw)
if !haskey(d, :y)
# assume we just want to create an empty plot object which can be added to later
return []
return [], nothing, nothing
# error("Called plot/subplot without args... must set y in the keyword args. Example: plot(; y=rand(10))")
end
@@ -242,13 +361,22 @@ end
# --------------------------------------------------------------------
"For DataFrame support. Imports DataFrames and defines the necessary methods which support them."
function dataframes!()
function dataframes()
@eval import DataFrames
@eval function createKWargsList(plt::PlottingObject, df::DataFrames.DataFrame, args...; kw...)
createKWargsList(plt, args...; kw..., dataframe = df)
end
# expecting the column name of a dataframe that was passed in... anything else should error
@eval function extractGroupArgs(s::Symbol, df::DataFrames.DataFrame, args...)
if haskey(df, s)
return extractGroupArgs(df[s])
else
error("Got a symbol, and expected that to be a key in d[:dataframe]. s=$s d=$d")
end
end
@eval function getDataFrameFromKW(; kw...)
for (k,v) in kw
if k == :dataframe
@@ -259,8 +387,8 @@ function dataframes!()
end
# the conversion functions for when we pass symbols or vectors of symbols to reference dataframes
@eval convertToAnyVector(s::Symbol; kw...) = Any[getDataFrameFromKW(;kw...)[s]]
@eval convertToAnyVector(v::AVec{Symbol}; kw...) = (df = getDataFrameFromKW(;kw...); Any[df[s] for s in v])
@eval convertToAnyVector(s::Symbol; kw...) = Any[getDataFrameFromKW(;kw...)[s]], s
@eval convertToAnyVector(v::AVec{Symbol}; kw...) = (df = getDataFrameFromKW(;kw...); Any[df[s] for s in v]), v
end
+9 -6
View File
@@ -28,7 +28,7 @@ const INITIALIZED_BACKENDS = Set{Symbol}()
backends() = BACKENDS
function backend(sym::Symbol)
function backendInstance(sym::Symbol)
sym == :qwt && return QwtPackage()
sym == :gadfly && return GadflyPackage()
sym == :unicodeplots && return UnicodePlotsPackage()
@@ -43,7 +43,7 @@ type CurrentBackend
sym::Symbol
pkg::PlottingPackage
end
CurrentBackend(sym::Symbol) = CurrentBackend(sym, backend(sym))
CurrentBackend(sym::Symbol) = CurrentBackend(sym, backendInstance(sym))
# ---------------------------------------------------------
@@ -90,7 +90,7 @@ end
doc"""
Returns the current plotting package name. Initializes package on first call.
"""
function plotter()
function backend()
currentBackendSymbol = CURRENT_BACKEND.sym
if !(currentBackendSymbol in INITIALIZED_BACKENDS)
@@ -125,6 +125,9 @@ function plotter()
try
@eval import PyPlot
@eval export PyPlot
if !isa(Base.Multimedia.displays[end], Base.REPL.REPLDisplay)
PyPlot.ioff()
end
catch
error("Couldn't import PyPlot. Install it with: Pkg.add(\"PyPlot\")")
end
@@ -146,7 +149,7 @@ function plotter()
end
else
error("Unknown plotter $currentBackendSymbol. Choose from: $BACKENDS")
error("Unknown backend $currentBackendSymbol. Choose from: $BACKENDS")
end
push!(INITIALIZED_BACKENDS, currentBackendSymbol)
# println("[Plots.jl] done.")
@@ -158,7 +161,7 @@ end
doc"""
Set the plot backend. Choose from: :qwt, :gadfly, :unicodeplots
"""
function plotter!(modname)
function backend(modname)
# set the PlottingPackage
if modname == :qwt
@@ -174,7 +177,7 @@ function plotter!(modname)
elseif modname == :winston
CURRENT_BACKEND.pkg = WinstonPackage()
else
error("Unknown plotter $modname. Choose from: $BACKENDS")
error("Unknown backend $modname. Choose from: $BACKENDS")
end
# update the symbol
+21 -20
View File
@@ -37,7 +37,7 @@ Base.length(layout::SubplotLayout) = layout.numplts
# ------------------------------------------------------------
Base.string(subplt::Subplot) = "Subplot{$(subplt.plotter) p=$(subplt.p) n=$(subplt.n)}"
Base.string(subplt::Subplot) = "Subplot{$(subplt.backend) p=$(subplt.p) n=$(subplt.n)}"
Base.print(io::IO, subplt::Subplot) = print(io, string(subplt))
Base.show(io::IO, subplt::Subplot) = print(io, string(subplt))
@@ -63,17 +63,19 @@ function subplot(args...; kw...)
replaceAliases!(d, _keyAliases)
# figure out the layout
if haskey(d, :layout)
layout = SubplotLayout(d[:layout])
layoutarg = get(d, :layout, nothing)
# if haskey(d, :layout)
if layoutarg != nothing
layout = SubplotLayout(layoutarg)
else
if !haskey(d, :n)
if !haskey(d, :n) || d[:n] < 0
error("You must specify either layout or n when creating a subplot: ", d)
end
layout = SubplotLayout(d[:n], get(d, :nr, -1), get(d, :nc, -1))
end
# initialize the individual plots
pkg = plotter()
pkg = backend()
plts = Plot[]
ds = Dict[]
for i in 1:length(layout)
@@ -100,7 +102,7 @@ Adds to a subplot.
# current subplot
function subplot!(args...; kw...)
subplot!(currentPlot(), args...; kw...)
subplot!(current(), args...; kw...)
end
@@ -113,7 +115,7 @@ end
# # this adds to a specific subplot... most plot commands will flow through here
function subplot!(subplt::Subplot, args...; kw...)
if !subplotSupported()
error(CURRENT_BACKEND.sym, " does not support the subplot/subplot! commands at this time. Try one of: ", join(filter(pkg->subplotSupported(backend(pkg)), backends()),", "))
error(CURRENT_BACKEND.sym, " does not support the subplot/subplot! commands at this time. Try one of: ", join(filter(pkg->subplotSupported(backendInstance(pkg)), backends()),", "))
end
d = Dict(kw)
@@ -122,12 +124,15 @@ function subplot!(subplt::Subplot, args...; kw...)
delete!(d, k)
end
kwList = createKWargsList(subplt, args...; d...)
for (i,d) in enumerate(kwList)
kwList, xmeta, ymeta = createKWargsList(subplt, args...; d...)
# TODO: something useful with meta info?
for (i,di) in enumerate(kwList)
subplt.n += 1
plt = getplot(subplt) # get the Plot object where this series will be drawn
d[:show] = false
plot!(plt; d...)
di[:show] = false
plot!(plt; di...)
end
# create the underlying object (each backend will do this differently)
@@ -137,16 +142,12 @@ function subplot!(subplt::Subplot, args...; kw...)
end
# set this to be current
currentPlot!(subplt)
current(subplt)
# NOTE: lets ignore the show param and effectively use the semicolon at the end of the REPL statement
# # do we want to show it?
# d = Dict(kw)
# @show d
# if haskey(d, :show) && d[:show]
# println("here...why?")
# display(subplt)
# end
# show it automatically?
if haskey(d, :show) && d[:show]
gui()
end
subplt
end
+2 -2
View File
@@ -9,7 +9,7 @@ abstract PlottingObject{T<:PlottingPackage}
type Plot{T<:PlottingPackage} <: PlottingObject{T}
o # the underlying object
plotter::T
backend::T
n::Int # number of series
# store these just in case
@@ -27,7 +27,7 @@ end
type Subplot{T<:PlottingPackage} <: PlottingObject{T}
o # the underlying object
plts::Vector{Plot} # the individual plots
plotter::T
backend::T
p::Int # number of plots
n::Int # number of series
layout::SubplotLayout
+115
View File
@@ -133,11 +133,126 @@ end
# ticksType{T<:Real,S<:Real}(ticks::Tuple{T,S}) = :limits
ticksType{T<:Real}(ticks::AVec{T}) = :ticks
ticksType{T<:AVec,S<:AVec}(ticks::Tuple{T,S}) = :ticks_and_labels
ticksType(ticks) = :invalid
limsType{T<:Real,S<:Real}(lims::Tuple{T,S}) = :limits
limsType(lims) = :invalid
# ---------------------------------------------------------------
# push/append/clear/set the underlying plot data
# NOTE: backends should implement the getindex and setindex! methods to get/set the x/y data objects
# index versions
function Base.push!(plt::Plot, i::Integer, x::Real, y::Real)
xdata, ydata = plt[i]
plt[i] = (extendSeriesData(xdata, x), extendSeriesData(ydata, y))
plt
end
function Base.push!(plt::Plot, i::Integer, y::Real)
xdata, ydata = plt[i]
if !isa(xdata, UnitRange)
error("Expected x is a UnitRange since you're trying to push a y value only")
end
plt[i] = (extendUnitRange(xdata), extendSeriesData(ydata, y))
plt
end
# update all at once
function Base.push!(plt::Plot, x::AVec, y::AVec)
nx = length(x)
ny = length(y)
for i in 1:plt.n
push!(plt, i, x[mod1(i,nx)], y[mod1(i,ny)])
end
plt
end
function Base.push!(plt::Plot, x::Real, y::AVec)
push!(plt, [x], y)
end
function Base.push!(plt::Plot, y::AVec)
ny = length(y)
for i in 1:plt.n
push!(plt, i, y[mod1(i,ny)])
end
plt
end
# append to index
function Base.append!(plt::Plot, i::Integer, x::AVec, y::AVec)
@assert length(x) == length(y)
xdata, ydata = plt[i]
plt[i] = (extendSeriesData(xdata, x), extendSeriesData(ydata, y))
plt
end
function Base.append!(plt::Plot, i::Integer, y::AVec)
xdata, ydata = plt[i]
if !isa(xdata, UnitRange{Int})
error("Expected x is a UnitRange since you're trying to push a y value only")
end
plt[i] = (extendUnitRange(xdata, length(y)), extendSeriesData(ydata, y))
plt
end
# used in updating an existing series
extendUnitRange(v::UnitRange{Int}, n::Int = 1) = minimum(v):maximum(v)+n
extendSeriesData(v::AVec, z) = (push!(v, z); v)
extendSeriesData(v::AVec, z::AVec) = (append!(v, z); v)
# ---------------------------------------------------------------
function supportGraph(allvals, func)
vals = reverse(sort(allvals))
bs = sort(backends())
x = ASCIIString[]
y = ASCIIString[]
for val in vals
for b in bs
supported = func(Plots.backendInstance(b))
if val in supported
push!(x, string(b))
push!(y, string(val))
end
end
end
n = length(vals)
scatter(x,y,
m=:rect,
ms=10,
size=(300,100+18*n),
# xticks=(collect(1:length(bs)), bs),
leg=false
)
end
supportGraphArgs() = supportGraph(_allArgs, supportedArgs)
supportGraphTypes() = supportGraph(_allTypes, supportedTypes)
supportGraphStyles() = supportGraph(_allStyles, supportedStyles)
supportGraphMarkers() = supportGraph(_allMarkers, supportedMarkers)
supportGraphScales() = supportGraph(_allScales, supportedScales)
supportGraphAxes() = supportGraph(_allAxes, supportedAxes)
function dumpSupportGraphs()
for func in (supportGraphArgs, supportGraphTypes, supportGraphStyles,
supportGraphMarkers, supportGraphScales, supportGraphAxes)
plt = func()
png(IMG_DIR * "/supported/$(string(func))")
end
end
# ---------------------------------------------------------------
# Some conversion functions
# note: I borrowed these conversion constants from Compose.jl's Measure
+13 -13
View File
@@ -4,15 +4,15 @@ using Plots
using FactCheck
# don't actually show the plots
plotDefault!(:show, false)
default(show=false)
srand(1234)
# note: we wrap in a try block so that the tests only run if we have the backend installed
try
Pkg.installed("Gadfly")
facts("Gadfly") do
@fact plotter!(:gadfly) --> Plots.GadflyPackage()
@fact plotter() --> Plots.GadflyPackage()
@fact backend(:gadfly) --> Plots.GadflyPackage()
@fact backend() --> Plots.GadflyPackage()
@fact typeof(plot(1:10)) --> Plots.Plot{Plots.GadflyPackage}
@@ -41,35 +41,35 @@ end
try
Pkg.installed("Qwt")
facts("Qwt") do
@fact plotter!(:qwt) --> Plots.QwtPackage()
@fact plotter() --> Plots.QwtPackage()
@fact backend(:qwt) --> Plots.QwtPackage()
@fact backend() --> Plots.QwtPackage()
@fact typeof(plot(1:10)) --> Plots.Plot{Plots.QwtPackage}
# plot(y::AVec; kw...) # one line... x = 1:length(y)
@fact plot(1:10) --> not(nothing)
@fact length(currentPlot().o.lines) --> 1
@fact length(current().o.lines) --> 1
# plot(x::AVec, f::Function; kw...) # one line, y = f(x)
@fact plot(1:10, sin) --> not(nothing)
@fact currentPlot().o.lines[1].y --> sin(collect(1:10))
@fact current().o.lines[1].y --> sin(collect(1:10))
# plot(x::AMat, f::Function; kw...) # multiple lines, yᵢⱼ = f(xᵢⱼ)
@fact plot(rand(10,2), sin) --> not(nothing)
@fact length(currentPlot().o.lines) --> 2
@fact length(current().o.lines) --> 2
# plot(y::AMat; kw...) # multiple lines (one per column of x), all sharing x = 1:size(y,1)
@fact plot!(rand(10,2)) --> not(nothing)
@fact length(currentPlot().o.lines) --> 4
@fact length(current().o.lines) --> 4
# plot(x::AVec, fs::AVec{Function}; kw...) # multiple lines, yᵢⱼ = fⱼ(xᵢ)
@fact plot(1:10, Function[sin,cos]) --> not(nothing)
@fact currentPlot().o.lines[1].y --> sin(collect(1:10))
@fact currentPlot().o.lines[2].y --> cos(collect(1:10))
@fact current().o.lines[1].y --> sin(collect(1:10))
@fact current().o.lines[2].y --> cos(collect(1:10))
# plot(y::AVec{AVec}; kw...) # multiple lines, each with x = 1:length(y[i])
@fact plot([11:20 ; rand(10)]) --> not(nothing)
@fact currentPlot().o.lines[1].x[4] --> 4
@fact currentPlot().o.lines[1].y[4] --> 14
@fact current().o.lines[1].x[4] --> 4
@fact current().o.lines[1].y[4] --> 14
end
end