Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3fc5f87388 | |||
| 623ca1effc | |||
| da05e7fe5e | |||
| f3734d4c64 | |||
| 9ab458e109 | |||
| d4c72e6f78 | |||
| 1f58ef5140 | |||
| 69d574c587 | |||
| a027fdded7 | |||
| 443df0501d | |||
| d68fe5f80d | |||
| ebf868bae3 | |||
| 8a9b3286e9 | |||
| a0455561b6 | |||
| 518ccf5a74 | |||
| 54f09c58cb | |||
| 029ad1045a | |||
| 2f55fb4d84 | |||
| add724eee9 | |||
| 07324ae892 | |||
| ffc05e971f | |||
| 30f42fd1d4 | |||
| f284857438 | |||
| 06ab514472 | |||
| 85b65acbe0 | |||
| 4d1d9de22f | |||
| a68ec9b191 | |||
| e386636d66 | |||
| cc3311b8eb | |||
| d3d1181769 | |||
| 001abf684c | |||
| 92a65296b5 | |||
| 3a7887d003 | |||
| 3334c4a87a | |||
| 228ce768e0 | |||
| eafc1a784c | |||
| fd3a4d0a0e | |||
| 77d679b63b | |||
| 730d764c6e | |||
| 6f1ef82e89 | |||
| d4da910f19 | |||
| a0a0773bd2 | |||
| 9ce8d138d5 | |||
| 0041b034e0 | |||
| d781c437de | |||
| 2fe21b8547 | |||
| dbc90c9417 | |||
| 431d60a58a | |||
| fcfcc9a94a | |||
| 870fb4e2df | |||
| e3612b973f | |||
| 75f4ca928f |
@@ -1,4 +1,5 @@
|
||||
*.jl.cov
|
||||
*.jl.*.cov
|
||||
*.jl.mem
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
examples/.ipynb_checkpoints/*
|
||||
@@ -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:
|
||||
|
||||

|
||||
|
||||
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
|
||||
|
||||
@@ -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!
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 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])
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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))
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -169,7 +169,7 @@ bar(randn(1000))
|
||||
|
||||
|
||||
```julia
|
||||
histogram(randn(1000); nbins=50)
|
||||
histogram(randn(1000),nbins=50)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
|
||||

|
||||
|
||||
### 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")])
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 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])
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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))
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -169,7 +169,7 @@ bar(randn(1000))
|
||||
|
||||
|
||||
```julia
|
||||
histogram(randn(1000); nbins=50)
|
||||
histogram(randn(1000),nbins=50)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
|
||||

|
||||
|
||||
### 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")])
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 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])
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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))
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -169,8 +169,20 @@ bar(randn(1000))
|
||||
|
||||
|
||||
```julia
|
||||
histogram(randn(1000); nbins=50)
|
||||
histogram(randn(1000),nbins=50)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 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")])
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 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])
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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))
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -169,7 +169,7 @@ bar(randn(1000))
|
||||
|
||||
|
||||
```julia
|
||||
histogram(randn(1000); nbins=50)
|
||||
histogram(randn(1000),nbins=50)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -209,3 +207,15 @@ subplot!(randn(100,3))
|
||||
|
||||

|
||||
|
||||
### 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")])
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||

|
||||
|
||||
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
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
```julia
|
||||
using Plots
|
||||
unicodeplots!()
|
||||
unicodeplots()
|
||||
```
|
||||
|
||||
### Lines
|
||||
|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 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])
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -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))
|
||||
```
|
||||
|
||||

|
||||
@@ -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)
|
||||
```
|
||||
|
||||

|
||||
@@ -159,8 +159,20 @@ bar(randn(1000))
|
||||
|
||||
|
||||
```julia
|
||||
histogram(randn(1000); nbins=50)
|
||||
histogram(randn(1000),nbins=50)
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 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")])
|
||||
```
|
||||
|
||||

|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 77 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,23 @@
|
||||
## Supported keyword arguments
|
||||
|
||||

|
||||
|
||||
## Supported plot types
|
||||
|
||||

|
||||
|
||||
## Supported markers
|
||||
|
||||

|
||||
|
||||
## Supported line styles
|
||||
|
||||

|
||||
|
||||
## Supported scales
|
||||
|
||||

|
||||
|
||||
## Supported axes
|
||||
|
||||

|
||||
|
After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -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
|
||||
|
||||
# ---------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||