Compare commits

..

84 Commits

Author SHA1 Message Date
Tom Breloff dd7b09552a Merge pull request #101 from tbreloff/dev
merging dev into master
2015-12-30 12:58:01 -05:00
Thomas Breloff 0b23aa9e7e relax tests 2015-12-30 12:36:18 -05:00
Thomas Breloff 0caa31bd6b fixes 2015-12-30 12:02:43 -05:00
Thomas Breloff cafac135a0 PyPlot fixes; test fixes 2015-12-30 11:24:44 -05:00
Thomas Breloff 6ac312bd49 removed nlevels keyword, now an alias to levels; cleanup 2015-12-30 10:13:53 -05:00
Tom Breloff 489877d6bf Merge pull request #99 from dlfivefifty/pull-request/c09545de
Add support for levels keyword in PyPlot
2015-12-30 09:38:27 -05:00
Sheehan Olver c09545de64 Add support for levels keyword in PyPlot 2015-12-29 15:32:49 +11:00
Thomas Breloff ed7cc9b89e pyplot surface/wireframe fix for matrix x/y; fix in with, when backend unset 2015-12-23 22:15:13 -05:00
Thomas Breloff 55501e68fb added tex output; fixes for surface inputs; commented out plotly_blink 2015-12-23 13:03:25 -05:00
Thomas Breloff eabe670ae8 working on plotlyjs integration 2015-12-18 17:33:57 -05:00
Thomas Breloff 9fffef6f53 cleanup 2015-12-18 13:19:22 -05:00
Thomas Breloff 368429b757 working on glvisualize 2015-12-18 10:14:15 -05:00
Tom Breloff 49f774eb0d Merge pull request #92 from dlfivefifty/dev
Add initial support for GLVisualize
2015-12-18 09:29:58 -05:00
Sheehan Olver 0487d7a058 merge glvisualize 2015-12-18 15:32:35 +11:00
Sheehan Olver 5943e77563 Fix backend_name 2015-12-18 15:30:07 +11:00
Sheehan Olver b10f0fb945 Started supporting GLVisualize 2015-12-18 15:30:07 +11:00
Sheehan Olver c299891fb0 Merge pull request #1 from tbreloff/dev
Dev
2015-12-18 15:27:35 +11:00
Thomas Breloff fe0f22dfc0 changed :log to map to :log10, switched :log to :ln; better support for plotly axis attributes, ticks, scale, etc; fix plotly bg/fg colors 2015-12-17 14:59:50 -05:00
Thomas Breloff 002603c388 added wireframe linetype; support for surface and wireframe in pyplot 2015-12-17 11:55:26 -05:00
Thomas Breloff 30ef8456c3 added xlims/ylims support in plotly 2015-12-17 00:14:38 -05:00
Thomas Breloff bee1ce401a moved annotation arg from series to plot; added annotation support for plotly 2015-12-16 23:22:46 -05:00
Thomas Breloff e18c4a370a added vline/hline marker shapes; plotly set/get, ticks 2015-12-16 11:14:06 -05:00
Thomas Breloff 2a60a929f1 recipe fix; plotly fixes 2015-12-15 22:53:57 -05:00
Thomas Breloff 939295ab04 _apply_recipe fix 2015-12-15 17:31:11 -05:00
Tom Breloff f6a0ef6a61 Merge pull request #90 from pkofod/patch-1
Added :line as to supportedTypes
2015-12-15 09:28:45 -05:00
Patrick Kofod Mogensen b3bce314e9 Added :line as to supportedTypes 2015-12-15 14:26:17 +01:00
Thomas Breloff e28b85d8b6 plotly support for ijulia and subplots 2015-12-08 12:01:26 -05:00
Thomas Breloff a0af2fc997 fix. closes #84 2015-12-07 23:14:10 -05:00
Tom Breloff 7f7f5c6f12 Merge pull request #85 from stevengj/patch-1
don't test for 0.4-
2015-11-28 20:13:06 -05:00
Steven G. Johnson d21fbfc9be don't test for 0.4-
Testing version > 0.4- is wrong because it incorrectly implies that all pre-releases of 0.4 work.  Either test for the specific 0.4 build you need, or test for `VERSION > v"0.4"` (i.e., the release version).

However, since you REQUIRE julia 0.4 anyway, you can omit this test entirely.
2015-11-25 17:00:57 -05:00
Thomas Breloff 366dc1cca9 travis 2015-11-24 17:43:18 -05:00
Thomas Breloff e9e3913bb7 switch tests to use ExamplePlots and VisualRegressionTests 2015-11-24 17:08:15 -05:00
Thomas Breloff 5491f6eff7 issubplot in _apply_recipe 2015-11-24 13:56:20 -05:00
Thomas Breloff 32e36ba324 added 3d example 2015-11-24 13:05:07 -05:00
Thomas Breloff 9d4c456461 plotly 3d path/scatter, surface 2015-11-24 12:39:54 -05:00
Thomas Breloff cdc7920dff added _apply_recipe 2015-11-24 10:45:49 -05:00
Thomas Breloff cdb4901d91 plotly fill, nbins, density; ref img 2015-11-23 23:05:24 -05:00
Thomas Breloff c7f3520ea8 plotly linestyle/markershape and others 2015-11-23 22:20:04 -05:00
Thomas Breloff f0e728c316 working on plotly; added contour and pie examples 2015-11-23 17:46:30 -05:00
Thomas Breloff 4b1f127eaf surface arg is now z; added orientation arg; working on plotly 2015-11-22 22:34:30 -05:00
Thomas Breloff 1db2d8d8d8 removed tests 2015-11-22 21:13:33 -05:00
Thomas Breloff 87bb45d01b added Surface, removed x/y length assert; added Surface createKWargsList; closes #82 2015-11-22 11:21:07 -05:00
Thomas Breloff 6beadcece8 fixes for contours in pyplot and gadfly 2015-11-21 13:59:26 -05:00
Thomas Breloff fc6f0f3a86 fixes in supported 2015-11-21 10:10:09 -05:00
Thomas Breloff ef7370f56d added density type 2015-11-21 09:26:35 -05:00
Thomas Breloff 52ba7cdbff working on plotly 2015-11-20 23:53:19 -05:00
Thomas Breloff b0c9dd44e9 working on plotly 2015-11-20 23:24:38 -05:00
Thomas Breloff 92ec093ed9 working on plotly 2015-11-20 18:36:50 -05:00
Thomas Breloff 6d2a1aafd2 working on plotly/web 2015-11-20 16:25:50 -05:00
Thomas Breloff f3a7734584 ref imgs 2015-11-20 14:28:26 -05:00
Thomas Breloff 9cf92f37f5 preparing for MLPlots; removed corrplot 2015-11-20 14:05:06 -05:00
Thomas Breloff 34831d42a4 subplot palette fix, added copy methods for Plot and Subplot 2015-11-20 12:55:45 -05:00
Thomas Breloff 607d5d7841 fixed empty plot() in gadfly backend 2015-11-20 10:17:31 -05:00
Thomas Breloff 75adfd2e9d new init logic; fix pyplot subplot bug 2015-11-20 09:26:43 -05:00
Thomas Breloff e92b5b2d35 fixed gadfly scales bug and new ref img; closes #74 2015-11-20 08:58:45 -05:00
Thomas Breloff a8c40a5493 started work on plotly 2015-11-18 21:26:16 -05:00
Thomas Breloff be5c3fb55c img_eps 2015-11-17 16:20:24 -05:00
Thomas Breloff e6e4a63022 added QuartzImageIO to test REQUIRE 2015-11-17 16:19:05 -05:00
Thomas Breloff 1cdc8928ba various fixes for pyplot and gadfly; new ref imgs 2015-11-17 15:59:45 -05:00
Thomas Breloff ad111a0163 added mpl version log 2015-11-17 11:48:10 -05:00
Thomas Breloff 7091a4899c imgcomp cleanup; pyplot dpi fix; new ref imgs 2015-11-17 11:19:12 -05:00
Thomas Breloff 3bd9e70fa9 moved PyPlot to first priority 2015-11-16 16:06:48 -05:00
Thomas Breloff 54bd2c620e gadfly ref imgs 2015-11-16 15:50:02 -05:00
Thomas Breloff 121640b1b3 fixed gadfly hline/vline constructors 2015-11-16 15:37:55 -05:00
Thomas Breloff 55e388513c fixes for gadfly and unicodeplots 2015-11-12 17:30:55 -05:00
Thomas Breloff b153dcbd63 reference images; gadfly markersize fix 2015-11-11 21:47:53 -05:00
Thomas Breloff 242cbe5ecb z/zcolor 2015-11-11 17:46:44 -05:00
Thomas Breloff f1cca13796 fix pyplot alpha and added stroke support 2015-11-11 16:27:21 -05:00
Thomas Breloff 918ba72107 readme 2015-11-10 16:41:26 -05:00
Thomas Breloff e596f27666 fixed numeric array without numeric type; updated readme; closes #64 2015-11-10 16:38:47 -05:00
Thomas Breloff a40d0000c5 fixed pyplot 2015-11-09 09:19:00 -05:00
Thomas Breloff fb82da74a1 gadfly layer order; fixes #63 2015-11-07 21:58:04 -05:00
Thomas Breloff b0991a0624 working on args 2015-11-06 15:58:15 -05:00
Thomas Breloff 6236acea02 working on markerstroke, name changes, and arg improvements 2015-11-06 15:49:27 -05:00
Thomas Breloff 391c7e8570 name changes; require to 0.4 2015-11-06 11:46:24 -05:00
Thomas Breloff 58041cc64e working on big renaming 2015-11-05 16:39:04 -05:00
Thomas Breloff 8c7d3a6e92 working on stroke/fill 2015-11-05 11:52:22 -05:00
Thomas Breloff ae1982369c working on bokeh 2015-11-03 15:48:04 -05:00
Thomas Breloff 5f85ac01f7 working on bokeh backend 2015-11-03 13:45:23 -05:00
Thomas Breloff cca263fb2b with method fix 2015-10-30 12:47:48 -04:00
Thomas Breloff 809ed02b85 gadfly/immerse downgrade fix 2015-10-30 10:03:10 -04:00
Thomas Breloff 9eab1083ab working on with 2015-10-29 17:18:14 -04:00
Thomas Breloff 60523bef80 working on 3d plotting 2015-10-29 15:44:07 -04:00
Thomas Breloff 46b959ff3c color reorg 2015-10-29 14:31:36 -04:00
72 changed files with 2809 additions and 1202 deletions
+5 -2
View File
@@ -11,10 +11,13 @@ notifications:
# uncomment the following lines to override the default test script
script:
- if [[ -a .git/shallow ]]; then git fetch --unshallow; fi
- julia -e 'Pkg.clone("https://github.com/tbreloff/Images.jl.git"); Pkg.checkout("Images","tom_imgcompare");'
- julia -e 'Pkg.clone(pwd()); Pkg.build("Plots")'
# - julia -e 'Pkg.clone("https://github.com/tbreloff/Images.jl.git"); Pkg.checkout("Images","tom_imgcompare");'
- julia -e 'Pkg.clone("Images"); Pkg.build("Images")'
- julia -e 'Pkg.clone("ImageMagick"); Pkg.build("ImageMagick")'
- julia -e 'Pkg.clone("https://github.com/tbreloff/VisualRegressionTests.jl.git");'
- julia -e 'Pkg.clone("https://github.com/tbreloff/ExamplePlots.jl.git");'
- julia -e 'Pkg.clone("Cairo"); Pkg.build("Cairo")'
- julia -e 'ENV["PYTHON"] = ""; Pkg.clone("PyPlot"); Pkg.build("PyPlot")'
- julia -e 'Pkg.clone(pwd()); Pkg.build("Plots")'
- julia -e 'Pkg.test("Plots"; coverage=false)'
# - julia -e 'cd(Pkg.dir("Plots")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder()); Codecov.submit(process_folder())'
+21 -11
View File
@@ -18,7 +18,7 @@ Plots is a plotting API and toolset. My goals with the package are:
Use the preprocessing pipeline in Plots to fully describe your visualization before it calls the backend code. This maintains modularity and allows for efficient separation of front end code, algorithms, and backend graphics. New graphical backends can be added with minimal effort.
Check out the [summary graphs](https://github.com/tbreloff/ExamplePlots.jl/tree/master/img/supported/supported.md) for the features that each backend supports.
Check out the [summary graphs](img/supported/supported.md) for the features that each backend supports.
Please add wishlist items, bugs, or any other comments/questions to the issues list.
@@ -52,7 +52,8 @@ Pkg.add("Gadfly")
Pkg.add("Immerse")
Pkg.add("PyPlot")
Pkg.add("UnicodePlots")
Pkg.clone("https://github.com/tbreloff/Qwt.jl.git")
Pkg.add("Qwt")
Pkg.add("Bokeh")
```
## Use
@@ -206,14 +207,13 @@ Keyword | Default | Type | Aliases
---- | ---- | ---- | ----
`:annotation` | `nothing` | Series | `:ann`, `:annotate`, `:annotations`, `:anns`
`:axis` | `left` | Series | `:axiss`
`:background_color` | `RGB{U8}(1.0,1.0,1.0)` | Plot | `:background`, `:bg`, `:bg_color`, `:bgcolor`
`:color` | `auto` | Series | `:c`, `:colors`
`:background_color` | `RGB{U8}(1.0,1.0,1.0)` | Plot | `:background`, `:background_colour`, `:bg`, `:bg_color`, `:bgcolor`
`:color_palette` | `auto` | Plot | `:palette`
`:fill` | `nothing` | Series | `:area`, `:f`
`:fillcolor` | `match` | Series | `:fc`, `:fcolor`, `:fillcolors`
`:fillopacity` | `nothing` | Series | `:fillopacitys`, `:fo`
`:fillalpha` | `nothing` | Series | `:fa`, `:fillalphas`, `:fillopacity`
`:fillcolor` | `match` | Series | `:fc`, `:fcolor`, `:fillcolors`, `:fillcolour`
`:fillrange` | `nothing` | Series | `:fillranges`, `:fillrng`
`:foreground_color` | `auto` | Plot | `:fg`, `:fg_color`, `:fgcolor`, `:foreground`
`:foreground_color` | `auto` | Plot | `:fg`, `:fg_color`, `:fgcolor`, `:foreground`, `:foreground_colour`
`:grid` | `true` | Plot |
`:group` | `nothing` | Series | `:g`, `:groups`
`:guidefont` | `Plots.Font("Helvetica",11,:hcenter,:vcenter,0.0,RGB{U8}(0.0,0.0,0.0))` | Plot |
@@ -222,7 +222,8 @@ Keyword | Default | Type | Aliases
`:legend` | `true` | Plot | `:leg`
`:legendfont` | `Plots.Font("Helvetica",8,:hcenter,:vcenter,0.0,RGB{U8}(0.0,0.0,0.0))` | Plot |
`:line` | `nothing` | Series | `:l`
`:lineopacity` | `nothing` | Series | `:lineopacitys`, `:lo`
`:linealpha` | `nothing` | Series | `:la`, `:linealphas`, `:lineopacity`
`:linecolor` | `auto` | Series | `:c`, `:color`, `:colour`, `:linecolors`
`:linestyle` | `solid` | Series | `:linestyles`, `:ls`, `:s`, `:style`
`:linetype` | `path` | Series | `:linetypes`, `:lt`, `:t`, `:type`
`:linewidth` | `1` | Series | `:linewidths`, `:lw`, `:w`, `:width`
@@ -231,18 +232,24 @@ Keyword | Default | Type | Aliases
`:linkx` | `false` | Plot | `:xlink`
`:linky` | `false` | Plot | `:ylink`
`:marker` | `nothing` | Series | `:m`, `:mark`
`:markercolor` | `match` | Series | `:markercolors`, `:mc`, `:mcolor`
`:markeropacity` | `nothing` | Series | `:alpha`, `:markeropacitys`, `:mo`, `:opacity`
`:markeralpha` | `nothing` | Series | `:alpha`, `:ma`, `:markeralphas`, `:markeropacity`, `:opacity`
`:markercolor` | `match` | Series | `:markercolors`, `:markercolour`, `:mc`, `:mcolor`
`:markershape` | `none` | Series | `:markershapes`, `:shape`
`:markersize` | `6` | Series | `:markersizes`, `:ms`, `:msize`
`:markerstrokealpha` | `nothing` | Series | `:markerstrokealphas`
`:markerstrokecolor` | `match` | Series | `:markerstrokecolors`
`:markerstrokestyle` | `solid` | Series | `:markerstrokestyles`
`:markerstrokewidth` | `1` | Series | `:markerstrokewidths`
`:n` | `-1` | Plot |
`:nbins` | `100` | Series | `:nb`, `:nbin`, `:nbinss`
`:nbins` | `30` | Series | `:nb`, `:nbin`, `:nbinss`
`:nc` | `-1` | Plot |
`:nlevels` | `15` | Series | `:nlevelss`
`:nr` | `-1` | Plot |
`:pos` | `(0,0)` | Plot |
`:show` | `false` | Plot | `:display`, `:gui`
`:size` | `(500,300)` | Plot | `:windowsize`, `:wsize`
`:smooth` | `false` | Series | `:reg`, `:regression`, `:smooths`
`:surface` | `nothing` | Series | `:surfaces`
`:tickfont` | `Plots.Font("Helvetica",8,:hcenter,:vcenter,0.0,RGB{U8}(0.0,0.0,0.0))` | Plot |
`:title` | `` | Plot |
`:windowtitle` | `Plots.jl` | Plot | `:wtitle`
@@ -280,6 +287,9 @@ Type | Desc | Aliases
`:hline` | Horizontal line (doesn't use x) |
`:vline` | Vertical line (doesn't use x) |
`:ohlc` | Open/High/Low/Close chart (expects y is AbstractVector{Plots.OHLC}) |
`:contour` | Contour lines (uses z) |
`:path3d` | 3D path (uses z) | `:line3d`
`:scatter3d` | 3D scatter plot (uses z) |
### Line styles:
+1 -1
View File
@@ -1,4 +1,4 @@
julia 0.3
julia 0.4
Colors
Reexport
Vendored Executable
+41
View File
File diff suppressed because one or more lines are too long
+58 -22
View File
@@ -31,7 +31,7 @@ const examples = PlotExample[
[
:(p = plot([sin,cos], zeros(0), leg=false)),
:(anim = Animation()),
:(for x in linspace(0, 10π, 200)
:(for x in linspace(0, 10π, 100)
push!(p, x, Float64[sin(x), cos(x)])
frame(anim)
end)
@@ -46,24 +46,28 @@ const examples = PlotExample[
[
:(y = rand(100)),
:(plot(0:10:100,rand(11,4),lab="lines",w=3, palette=:grays, fill=(0.5,:auto))),
:(scatter!(y, z=abs(y-.5), m=(10,:heat), lab="grad"))
:(scatter!(y, zcolor=abs(y-.5), m=(:heat,0.8,stroke(1,:green)), ms=10*abs(y-0.5)+4, lab="grad"))
]),
PlotExample("Global",
"Change the guides/background/limits/ticks. Convenience args `xaxis` and `yaxis` allow you to pass a tuple or value which will be mapped to the relevant args automatically. The `xaxis` below will be replaced with `xlabel` and `xlims` args automatically during the preprocessing step. You can also use shorthand functions: `title!`, `xaxis!`, `yaxis!`, `xlabel!`, `ylabel!`, `xlims!`, `ylims!`, `xticks!`, `yticks!`",
[
:(plot(rand(20,3), xaxis=("XLABEL",(-5,30),0:2:20,:flip), background_color = RGB(0.2,0.2,0.2), leg=false)),
:(y = rand(20,3)),
:(plot(y, xaxis=("XLABEL",(-5,30),0:2:20,:flip), background_color = RGB(0.2,0.2,0.2), leg=false)),
:(hline!(mean(y,1)+rand(1,3), line=(4,:dash,0.6,[:lightgreen :green :darkgreen]))),
:(vline!([5,10])),
:(title!("TITLE")),
:(yaxis!("YLABEL", :log10))
]),
PlotExample("Two-axis",
"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"))
:(plot(Vector[randn(100), randn(100)*100], axis = [:l :r], ylabel="LEFT", yrightlabel="RIGHT", xlabel="X", title="TITLE"))
]),
PlotExample("Arguments",
"Plot multiple series with different numbers of points. Mix arguments that apply to all series (marker/markersize) with arguments unique to each series (colors). Special arguments `line`, `marker`, and `fill` will automatically figure out what arguments to set (for example, we are setting the `linestyle`, `linewidth`, and `color` arguments with `line`.) Note that we pass a matrix of colors, and this applies the colors to each series.",
[
:(plot(Vector[rand(10), rand(20)], marker=(:ellipse,8), line=(:dot,3,[:black :orange])))
:(ys = Vector[rand(10), rand(20)]),
:(plot(ys, line=(:dot,4,[:black :orange]), marker=([:hex :d],12,0.8,stroke(3,:gray))))
]),
PlotExample("Build plot in pieces",
"Start with a base plot...",
@@ -78,7 +82,7 @@ const examples = PlotExample[
PlotExample("Heatmaps",
"",
[
:(heatmap(randn(10000),randn(10000), nbins=100))
:(heatmap(randn(10000),randn(10000), nbins=20))
]),
PlotExample("Line types",
"",
@@ -112,7 +116,7 @@ const examples = PlotExample[
PlotExample("Histogram",
"",
[
:(histogram(randn(1000), nbins=50))
:(histogram(randn(1000), nbins=20))
]),
PlotExample("Subplots",
"""
@@ -163,8 +167,37 @@ const examples = PlotExample[
m=(Shape(verts),30,RGBA(0,0,0,0.2)),
bg=:pink, fg=:darkblue,
xlim = (0,1), ylim=(0,1), leg=false))
]),
PlotExample("Contours",
"",
[
:(x = 1:0.3:20),
:(y = x),
:(f(x,y) = sin(x)+cos(y)),
:(contour(x, y, f, fill=true))
]),
PlotExample("Pie",
"",
[
:(x = ["Nerds", "Hackers", "Scientists"]),
:(y = [0.4, 0.35, 0.25]),
:(pie(x, y, title="The Julia Community", l=0.5))
]),
PlotExample("3D",
"",
[
:(n = 100),
:(ts = linspace(0,8π,n)),
:(x = ts .* map(cos,ts)),
:(y = 0.1ts .* map(sin,ts)),
:(z = 1:n),
:(plot(x, y, z, zcolor=reverse(z), m=(10,0.8,:blues,stroke(0)), leg=false, w=5)),
:(plot!(zeros(n),zeros(n),1:n, w=10))
])
]
@@ -301,20 +334,23 @@ end
@compat const _ltdesc = Dict(
:none => "No line",
:line => "Lines with sorted x-axis",
:path => "Lines",
:steppre => "Step plot (vertical then horizontal)",
:steppost => "Step plot (horizontal then vertical)",
:sticks => "Vertical lines",
:scatter => "Points, no lines",
:heatmap => "Colored regions by density",
:hexbin => "Similar to heatmap",
:hist => "Histogram (doesn't use x)",
:bar => "Bar plot (centered on x values)",
:hline => "Horizontal line (doesn't use x)",
:vline => "Vertical line (doesn't use x)",
:ohlc => "Open/High/Low/Close chart (expects y is AbstractVector{Plots.OHLC})",
:none => "No line",
:line => "Lines with sorted x-axis",
:path => "Lines",
:steppre => "Step plot (vertical then horizontal)",
:steppost => "Step plot (horizontal then vertical)",
:sticks => "Vertical lines",
:scatter => "Points, no lines",
:heatmap => "Colored regions by density",
:hexbin => "Similar to heatmap",
:hist => "Histogram (doesn't use x)",
:bar => "Bar plot (centered on x values)",
:hline => "Horizontal line (doesn't use x)",
:vline => "Vertical line (doesn't use x)",
:ohlc => "Open/High/Low/Close chart (expects y is AbstractVector{Plots.OHLC})",
:contour => "Contour lines (uses z)",
:path3d => "3D path (uses z)",
:scatter3d => "3D scatter plot (uses z)",
)
function buildReadme()
+3 -2
View File
@@ -18,7 +18,7 @@ Plots is a plotting API and toolset. My goals with the package are:
Use the preprocessing pipeline in Plots to fully describe your visualization before it calls the backend code. This maintains modularity and allows for efficient separation of front end code, algorithms, and backend graphics. New graphical backends can be added with minimal effort.
Check out the [summary graphs](https://github.com/tbreloff/ExamplePlots.jl/tree/master/img/supported/supported.md) for the features that each backend supports.
Check out the [summary graphs](img/supported/supported.md) for the features that each backend supports.
Please add wishlist items, bugs, or any other comments/questions to the issues list.
@@ -52,7 +52,8 @@ Pkg.add("Gadfly")
Pkg.add("Immerse")
Pkg.add("PyPlot")
Pkg.add("UnicodePlots")
Pkg.clone("https://github.com/tbreloff/Qwt.jl.git")
Pkg.add("Qwt")
Pkg.add("Bokeh")
```
## Use
Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 28 KiB

+65 -19
View File
@@ -1,7 +1,5 @@
if VERSION >= v"0.4-"
__precompile__()
end
__precompile__()
module Plots
@@ -10,6 +8,14 @@ using Reexport
@reexport using Colors
export
Plot,
Subplot,
SubplotLayout,
GridLayout,
FlexLayout,
AVec,
AMat,
plot,
plot!,
# plot_display,
@@ -19,6 +25,7 @@ export
current,
default,
with,
scatter,
scatter!,
@@ -26,8 +33,12 @@ export
bar!,
histogram,
histogram!,
density,
density!,
heatmap,
heatmap!,
hexbin,
hexbin!,
sticks,
sticks!,
hline,
@@ -36,6 +47,18 @@ export
vline!,
ohlc,
ohlc!,
pie,
pie!,
contour,
contour!,
surface,
surface!,
wireframe,
wireframe!,
path3d,
path3d!,
scatter3d,
scatter3d!,
title!,
xlabel!,
@@ -62,6 +85,9 @@ export
Shape,
text,
font,
stroke,
brush,
Surface,
OHLC,
colorscheme,
@@ -89,8 +115,8 @@ export
# recipes
PlotRecipe,
EllipseRecipe,
spy,
# EllipseRecipe,
# spy,
corrplot
# ---------------------------------------------------------
@@ -104,6 +130,7 @@ const IMG_DIR = Pkg.dir("Plots") * "/img/"
include("types.jl")
include("utils.jl")
include("colors.jl")
include("components.jl")
include("plotter.jl")
include("args.jl")
include("plot.jl")
@@ -121,8 +148,12 @@ bar(args...; kw...) = plot(args...; kw..., linetype = :bar)
bar!(args...; kw...) = plot!(args...; kw..., linetype = :bar)
histogram(args...; kw...) = plot(args...; kw..., linetype = :hist)
histogram!(args...; kw...) = plot!(args...; kw..., linetype = :hist)
density(args...; kw...) = plot(args...; kw..., linetype = :density)
density!(args...; kw...) = plot!(args...; kw..., linetype = :density)
heatmap(args...; kw...) = plot(args...; kw..., linetype = :heatmap)
heatmap!(args...; kw...) = plot!(args...; kw..., linetype = :heatmap)
hexbin(args...; kw...) = plot(args...; kw..., linetype = :hexbin)
hexbin!(args...; kw...) = plot!(args...; kw..., linetype = :hexbin)
sticks(args...; kw...) = plot(args...; kw..., linetype = :sticks, marker = :ellipse)
sticks!(args...; kw...) = plot!(args...; kw..., linetype = :sticks, marker = :ellipse)
hline(args...; kw...) = plot(args...; kw..., linetype = :hline)
@@ -131,6 +162,18 @@ vline(args...; kw...) = plot(args...; kw..., linetype = :vline)
vline!(args...; kw...) = plot!(args...; kw..., linetype = :vline)
ohlc(args...; kw...) = plot(args...; kw..., linetype = :ohlc)
ohlc!(args...; kw...) = plot!(args...; kw..., linetype = :ohlc)
pie(args...; kw...) = plot(args...; kw..., linetype = :pie)
pie!(args...; kw...) = plot!(args...; kw..., linetype = :pie)
contour(args...; kw...) = plot(args...; kw..., linetype = :contour)
contour!(args...; kw...) = plot!(args...; kw..., linetype = :contour)
surface(args...; kw...) = plot(args...; kw..., linetype = :surface)
surface!(args...; kw...) = plot!(args...; kw..., linetype = :surface)
wireframe(args...; kw...) = plot(args...; kw..., linetype = :wireframe)
wireframe!(args...; kw...) = plot!(args...; kw..., linetype = :wireframe)
path3d(args...; kw...) = plot(args...; kw..., linetype = :path3d)
path3d!(args...; kw...) = plot!(args...; kw..., linetype = :path3d)
scatter3d(args...; kw...) = plot(args...; kw..., linetype = :scatter3d)
scatter3d!(args...; kw...) = plot!(args...; kw..., linetype = :scatter3d)
title!(s::@compat(AbstractString); kw...) = plot!(; title = s, kw...)
@@ -178,10 +221,10 @@ yaxis!(plt::Plot, args...; kw...) = plot!(pl
# ---------------------------------------------------------
try
import DataFrames
dataframes()
end
# try
# import DataFrames
# dataframes()
# end
# const CURRENT_BACKEND = pickDefaultBackend()
@@ -194,18 +237,21 @@ end
# end
# end
const CURRENT_BACKEND = CurrentBackend(:none)
function __init__()
global const CURRENT_BACKEND = pickDefaultBackend()
# global CURRENT_BACKEND
# println("[Plots.jl] Default backend: ", CURRENT_BACKEND.sym)
# function __init__()
# # global const CURRENT_BACKEND = pickDefaultBackend()
# # global const CURRENT_BACKEND = CurrentBackend(:none)
# # auto init dataframes if the import statement doesn't error out
# try
# @eval import DataFrames
# dataframes()
# end
end
# # global CURRENT_BACKEND
# # 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
# ---------------------------------------------------------
+210 -154
View File
@@ -2,13 +2,17 @@
const _allAxes = [:auto, :left, :right]
@compat const _axesAliases = Dict(
:a => :auto,
:l => :left,
:a => :auto,
:l => :left,
:r => :right
)
const _allTypes = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
:heatmap, :hexbin, :hist, :bar, :hline, :vline, :ohlc, :contour]
const _3dTypes = [:path3d, :scatter3d, :surface, :wireframe]
const _allTypes = vcat([
:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
:heatmap, :hexbin, :hist, :density, :bar, :hline, :vline, :ohlc,
:contour, :pie
], _3dTypes)
@compat const _typeAliases = Dict(
:n => :none,
:no => :none,
@@ -26,9 +30,18 @@ const _allTypes = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
:stems => :sticks,
:dots => :scatter,
:histogram => :hist,
:contours => :contours,
:pdf => :density,
:contours => :contour,
:line3d => :path3d,
:surf => :surface,
:wire => :wireframe,
)
ishistlike(lt::Symbol) = lt in (:hist, :density)
islinelike(lt::Symbol) = lt in (:line, :path, :steppre, :steppost)
isheatmaplike(lt::Symbol) = lt in (:heatmap, :hexbin)
const _allStyles = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
@compat const _styleAliases = Dict(
:a => :auto,
@@ -78,61 +91,56 @@ const _allMarkers = vcat(:none, :auto, sort(collect(keys(_shapes))))
:hep => :heptagon,
:o => :octagon,
:oct => :octagon,
:spike => :vline,
)
const _allScales = [:identity, :log, :log2, :log10, :asinh, :sqrt]
const _allScales = [:identity, :ln, :log2, :log10, :asinh, :sqrt]
@compat const _scaleAliases = Dict(
:none => :identity,
:ln => :log,
:log => :log10,
)
supportedAxes(::PlottingPackage) = _allAxes
supportedTypes(::PlottingPackage) = _allTypes
supportedStyles(::PlottingPackage) = _allStyles
supportedMarkers(::PlottingPackage) = _allMarkers
supportedScales(::PlottingPackage) = _allScales
subplotSupported(::PlottingPackage) = true
supportedAxes() = supportedAxes(backend())
supportedTypes() = supportedTypes(backend())
supportedStyles() = supportedStyles(backend())
supportedMarkers() = supportedMarkers(backend())
supportedScales() = supportedScales(backend())
subplotSupported() = subplotSupported(backend())
# -----------------------------------------------------------------------------
const _seriesDefaults = Dict{Symbol, Any}()
# series-specific
_seriesDefaults[:axis] = :left
_seriesDefaults[:color] = :auto
_seriesDefaults[:label] = "AUTO"
_seriesDefaults[:linetype] = :path
_seriesDefaults[:linestyle] = :solid
_seriesDefaults[:linewidth] = 1
_seriesDefaults[:lineopacity] = nothing
_seriesDefaults[:markershape] = :none
_seriesDefaults[:markercolor] = :match
_seriesDefaults[:markeropacity] = nothing
_seriesDefaults[:markersize] = 6
_seriesDefaults[:fillrange] = nothing # ribbons, areas, etc
_seriesDefaults[:fillcolor] = :match
_seriesDefaults[:fillopacity] = nothing
# _seriesDefaults[:ribbon] = nothing
# _seriesDefaults[:ribboncolor] = :match
_seriesDefaults[:nbins] = 30 # number of bins for heatmaps and hists
# _seriesDefaults[:heatmap_c] = (0.15, 0.5) # TODO: this should be replaced with a ColorGradient
# _seriesDefaults[:fill] = nothing # fills in the area
_seriesDefaults[:smooth] = false # regression line?
_seriesDefaults[:group] = nothing # groupby vector
_seriesDefaults[:annotation] = nothing # annotation tuple(s)... (x,y,annotation)
_seriesDefaults[:z] = nothing # depth for contour, color scale, etc
# _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[:surface] = nothing
_seriesDefaults[:nlevels] = 15
_seriesDefaults[:axis] = :left
_seriesDefaults[:label] = "AUTO"
_seriesDefaults[:linetype] = :path
_seriesDefaults[:linestyle] = :solid
_seriesDefaults[:linewidth] = 1
_seriesDefaults[:linecolor] = :auto
_seriesDefaults[:linealpha] = nothing
# _seriesDefaults[:linestroke] = Stroke(1, :auto, nothing, :solid) # linewidth, linecolor, linealpha, linestyle
# _seriesDefaults[:fillbrush] = Brush(nothing, :match, nothing) # fillrange, fillcolor, fillalpha
_seriesDefaults[:fillrange] = nothing # ribbons, areas, etc
_seriesDefaults[:fillcolor] = :match
_seriesDefaults[:fillalpha] = nothing
_seriesDefaults[:markershape] = :none
# _seriesDefaults[:markerstroke] = Stroke(1, :match_foreground, nothing, :solid)
# _seriesDefaults[:markerbrush] = Brush(6, :match, nothing)
_seriesDefaults[:markercolor] = :match
_seriesDefaults[:markeralpha] = nothing
_seriesDefaults[:markersize] = 6
_seriesDefaults[:markerstrokestyle] = :solid
_seriesDefaults[:markerstrokewidth] = 1
_seriesDefaults[:markerstrokecolor] = :match
_seriesDefaults[:markerstrokealpha] = nothing
# _seriesDefaults[:ribbon] = nothing
# _seriesDefaults[:ribboncolor] = :match
_seriesDefaults[:nbins] = 30 # number of bins for heatmaps and hists
_seriesDefaults[:smooth] = false # regression line?
_seriesDefaults[:group] = nothing # groupby vector
# _seriesDefaults[:annotation] = nothing # annotation tuple(s)... (x,y,annotation)
_seriesDefaults[:x] = nothing
_seriesDefaults[:y] = nothing
_seriesDefaults[:z] = nothing # depth for contour, surface, etc
_seriesDefaults[:zcolor] = nothing # value for color scale
# _seriesDefaults[:surface] = nothing
# _seriesDefaults[:nlevels] = 15
_seriesDefaults[:levels] = 15
_seriesDefaults[:orientation] = :vertical
const _plotDefaults = Dict{Symbol, Any}()
@@ -170,6 +178,7 @@ _plotDefaults[:tickfont] = font(8)
_plotDefaults[:guidefont] = font(11)
_plotDefaults[:legendfont] = font(8)
_plotDefaults[:grid] = true
_plotDefaults[:annotation] = nothing # annotation tuple(s)... (x,y,annotation)
@@ -180,12 +189,6 @@ supportedArgs(::PlottingPackage) = _allArgs
supportedArgs() = supportedArgs(backend())
@compat const _argNotes = Dict(
:color => "Series color. To have different marker and/or fill colors, optionally set the markercolor and fillcolor args.",
:z => "Determines the depth. For color gradients, we expect 0 ≤ z ≤ 1.",
# :heatmap_c => "For Qwt heatmaps only... will be deprecated eventually.",
)
# -----------------------------------------------------------------------------
@@ -215,79 +218,91 @@ end
# Alternate args
@compat const _keyAliases = Dict(
:c => :color,
:lab => :label,
:l => :line,
:w => :linewidth,
:width => :linewidth,
:lw => :linewidth,
:lo => :lineopacity,
:type => :linetype,
:lt => :linetype,
:t => :linetype,
:style => :linestyle,
:s => :linestyle,
:ls => :linestyle,
:m => :marker,
:mark => :marker,
:shape => :markershape,
:mc => :markercolor,
:mcolor => :markercolor,
:ms => :markersize,
:msize => :markersize,
:mo => :markeropacity,
:opacity => :markeropacity,
:alpha => :markeropacity,
:f => :fill,
:area => :fill,
:fillrng => :fillrange,
:fc => :fillcolor,
:fcolor => :fillcolor,
:fo => :fillopacity,
:g => :group,
:nb => :nbins,
:nbin => :nbins,
:rib => :ribbon,
:ann => :annotation,
:anns => :annotation,
:annotate => :annotation,
:annotations => :annotation,
:xlab => :xlabel,
:ylab => :ylabel,
:yrlab => :yrightlabel,
:ylabr => :yrightlabel,
:y2lab => :yrightlabel,
:ylab2 => :yrightlabel,
:ylabelright => :yrightlabel,
:ylabel2 => :yrightlabel,
:y2label => :yrightlabel,
:leg => :legend,
:bg => :background_color,
:bgcolor => :background_color,
:bg_color => :background_color,
:background => :background_color,
:fg => :foreground_color,
:fgcolor => :foreground_color,
:fg_color => :foreground_color,
:foreground => :foreground_color,
:regression => :smooth,
:reg => :smooth,
:xlim => :xlims,
:xlimit => :xlims,
:xlimits => :xlims,
:ylim => :ylims,
:ylimit => :ylims,
:ylimits => :ylims,
:xtick => :xticks,
:ytick => :yticks,
:windowsize => :size,
:wsize => :size,
:wtitle => :windowtitle,
:gui => :show,
:display => :show,
:palette => :color_palette,
:xlink => :linkx,
:ylink => :linky,
:c => :linecolor,
:color => :linecolor,
:colour => :linecolor,
:lab => :label,
:l => :line,
:w => :linewidth,
:width => :linewidth,
:lw => :linewidth,
:la => :linealpha,
:lineopacity => :linealpha,
:type => :linetype,
:lt => :linetype,
:t => :linetype,
:style => :linestyle,
:s => :linestyle,
:ls => :linestyle,
:m => :marker,
:mark => :marker,
:shape => :markershape,
:mc => :markercolor,
:mcolor => :markercolor,
:markercolour => :markercolor,
:ms => :markersize,
:msize => :markersize,
:ma => :markeralpha,
:alpha => :markeralpha,
:opacity => :markeralpha,
:markeropacity => :markeralpha,
:f => :fill,
:area => :fill,
:fillrng => :fillrange,
:fc => :fillcolor,
:fcolor => :fillcolor,
:fillcolour => :fillcolor,
:fa => :fillalpha,
:fillopacity => :fillalpha,
:g => :group,
:nb => :nbins,
:nbin => :nbins,
:rib => :ribbon,
:ann => :annotation,
:anns => :annotation,
:annotate => :annotation,
:annotations => :annotation,
:xlab => :xlabel,
:ylab => :ylabel,
:yrlab => :yrightlabel,
:ylabr => :yrightlabel,
:y2lab => :yrightlabel,
:ylab2 => :yrightlabel,
:ylabelright => :yrightlabel,
:ylabel2 => :yrightlabel,
:y2label => :yrightlabel,
:leg => :legend,
:bg => :background_color,
:bgcolor => :background_color,
:bg_color => :background_color,
:background => :background_color,
:background_colour => :background_color,
:fg => :foreground_color,
:fgcolor => :foreground_color,
:fg_color => :foreground_color,
:foreground => :foreground_color,
:foreground_colour => :foreground_color,
:regression => :smooth,
:reg => :smooth,
:nlevels => :levels,
:nlev => :levels,
:levs => :levels,
:xlim => :xlims,
:xlimit => :xlims,
:xlimits => :xlims,
:ylim => :ylims,
:ylimit => :ylims,
:ylimits => :ylims,
:xtick => :xticks,
:ytick => :yticks,
:windowsize => :size,
:wsize => :size,
:wtitle => :windowtitle,
:gui => :show,
:display => :show,
:palette => :color_palette,
:xlink => :linkx,
:ylink => :linky,
)
# add all pluralized forms to the _keyAliases dict
@@ -396,21 +411,32 @@ function processLineArg(d::Dict, arg)
# linetype
if trueOrAllTrue(a -> get(_typeAliases, a, a) in _allTypes, arg)
d[:linetype] = arg
# linestyle
elseif trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg)
d[:linestyle] = arg
elseif typeof(arg) <: Stroke
arg.width == nothing || (d[:linewidth] = arg.width)
arg.color == nothing || (d[:linecolor] = arg.color == :auto ? :auto : colorscheme(arg.color))
arg.alpha == nothing || (d[:linealpha] = arg.alpha)
arg.style == nothing || (d[:linestyle] = arg.style)
elseif typeof(arg) <: Brush
arg.size == nothing || (d[:fillrange] = arg.size)
arg.color == nothing || (d[:fillcolor] = arg.color == :auto ? :auto : colorscheme(arg.color))
arg.alpha == nothing || (d[:fillalpha] = arg.alpha)
# linealpha
elseif trueOrAllTrue(a -> typeof(a) <: Real && a > 0 && a < 1, arg)
d[:linealpha] = arg
# linewidth
elseif trueOrAllTrue(a -> typeof(a) <: Integer, arg)
elseif trueOrAllTrue(a -> typeof(a) <: Real, arg)
d[:linewidth] = arg
# lineopacity
elseif trueOrAllTrue(a -> typeof(a) <: Real && a >= 0 && a <= 1, arg)
d[:lineopacity] = arg
# color
elseif !handleColors!(d, arg, :color)
elseif !handleColors!(d, arg, :linecolor)
warn("Skipped line arg $arg.")
end
@@ -425,24 +451,45 @@ function processMarkerArg(d::Dict, arg)
elseif trueOrAllTrue(a -> isa(a, Shape), arg)
d[:markershape] = arg
# markersize
elseif trueOrAllTrue(a -> typeof(a) <: Integer, arg)
d[:markersize] = arg
# stroke style
elseif trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg)
d[:markerstrokestyle] = arg
# lineopacity
elseif trueOrAllTrue(a -> typeof(a) <: Real && a >= 0 && a <= 1, arg)
d[:markeropacity] = arg
elseif typeof(arg) <: Stroke
arg.width == nothing || (d[:markerstrokewidth] = arg.width)
arg.color == nothing || (d[:markerstrokecolor] = arg.color == :auto ? :auto : colorscheme(arg.color))
arg.alpha == nothing || (d[:markerstrokealpha] = arg.alpha)
arg.style == nothing || (d[:markerstrokestyle] = arg.style)
elseif typeof(arg) <: Brush
arg.size == nothing || (d[:markersize] = arg.size)
arg.color == nothing || (d[:markercolor] = arg.color == :auto ? :auto : colorscheme(arg.color))
arg.alpha == nothing || (d[:markeralpha] = arg.alpha)
# linealpha
elseif trueOrAllTrue(a -> typeof(a) <: Real && a > 0 && a < 1, arg)
d[:markeralpha] = arg
# markersize
elseif trueOrAllTrue(a -> typeof(a) <: Real, arg)
d[:markersize] = arg
# markercolor
elseif !handleColors!(d, arg, :markercolor)
warn("Skipped marker arg $arg.")
end
end
function processFillArg(d::Dict, arg)
if !handleColors!(d, arg, :fillcolor)
if typeof(arg) <: Brush
arg.size == nothing || (d[:fillrange] = arg.size)
arg.color == nothing || (d[:fillcolor] = arg.color == :auto ? :auto : colorscheme(arg.color))
arg.alpha == nothing || (d[:fillalpha] = arg.alpha)
elseif !handleColors!(d, arg, :fillcolor)
d[:fillrange] = arg
end
end
@@ -450,7 +497,7 @@ end
"Handle all preprocessing of args... break out colors/sizes/etc and replace aliases."
function preprocessArgs!(d::Dict)
replaceAliases!(d, _keyAliases)
# handle axis args
for axisletter in ("x", "y")
asym = symbol(axisletter * "axis")
@@ -483,6 +530,8 @@ function preprocessArgs!(d::Dict)
end
delete!(d, :fill)
# convert into strokes and brushes
# handle subplot links
if haskey(d, :link)
l = d[:link]
@@ -545,7 +594,7 @@ end
function warnOnUnsupported(pkg::PlottingPackage, d::Dict)
(d[:axis] in supportedAxes(pkg)
(d[:axis] in supportedAxes(pkg)
|| warn("axis $(d[:axis]) is unsupported with $pkg. Choose from: $(supportedAxes(pkg))"))
(d[:linetype] == :none
|| d[:linetype] in supportedTypes(pkg)
@@ -623,7 +672,7 @@ end
# build the argument dictionary for a series
function getSeriesArgs(pkg::PlottingPackage, initargs::Dict, kw, commandIndex::Int, plotIndex::Int, globalIndex::Int) # TODO, pass in initargs, not plt
function getSeriesArgs(pkg::PlottingPackage, plotargs::Dict, kw, commandIndex::Int, plotIndex::Int, globalIndex::Int) # TODO, pass in plotargs, not plt
kwdict = Dict(kw)
d = Dict()
@@ -638,7 +687,7 @@ function getSeriesArgs(pkg::PlottingPackage, initargs::Dict, kw, commandIndex::I
d[k] = kwdict[k]
end
end
if haskey(_typeAliases, d[:linetype])
d[:linetype] = _typeAliases[d[:linetype]]
end
@@ -648,17 +697,24 @@ function getSeriesArgs(pkg::PlottingPackage, initargs::Dict, kw, commandIndex::I
aliasesAndAutopick(d, :markershape, _markerAliases, supportedMarkers(pkg), plotIndex)
# update color
d[:color] = getSeriesRGBColor(d[:color], initargs, plotIndex)
d[:linecolor] = getSeriesRGBColor(d[:linecolor], plotargs, plotIndex)
# update markercolor
mc = d[:markercolor]
mc = (mc == :match ? d[:color] : getSeriesRGBColor(mc, initargs, plotIndex))
d[:markercolor] = mc
c = d[:markercolor]
c = (c == :match ? d[:linecolor] : getSeriesRGBColor(c, plotargs, plotIndex))
d[:markercolor] = c
# update markerstrokecolor
c = d[:markerstrokecolor]
c = (c == :match ? plotargs[:foreground_color] : getSeriesRGBColor(c, plotargs, plotIndex))
d[:markerstrokecolor] = c
# update fillcolor
mc = d[:fillcolor]
mc = (mc == :match ? d[:color] : getSeriesRGBColor(mc, initargs, plotIndex))
d[:fillcolor] = mc
c = d[:fillcolor]
c = (c == :match ? d[:linecolor] : getSeriesRGBColor(c, plotargs, plotIndex))
d[:fillcolor] = c
# TODO: rebuild
# set label
label = d[:label]
+167
View File
@@ -0,0 +1,167 @@
# https://github.com/bokeh/Bokeh.jl
# make255(x) = round(Int, 255 * x)
# function bokehcolor(c::Colorant)
# @sprintf("rgba(%d, %d, %d, %1.3f)", [make255(f(c)) for f in [red,green,blue]]..., alpha(c))
# end
# bokehcolor(cs::ColorScheme) = bokehcolor(getColor(cs))
const _glyphtypes = Dict(
:ellipse => :Circle,
:rect => :Square,
:diamond => :Diamond,
:utriangle => :Triangle,
:dtriangle => :InvertedTriangle,
# :pentagon =>
# :hexagon =>
# :heptagon =>
# :octagon =>
:cross => :Cross,
:xcross => :X,
:star5 => :Asterisk,
)
function bokeh_glyph_type(d::Dict)
lt = d[:linetype]
mt = d[:markershape]
if lt == :scatter && mt == :none
mt = :ellipse
end
# if we have a marker, use that
if lt == :scatter || mt != :none
return _glyphtypes[mt]
end
# otherwise return a line
return :Line
end
function get_stroke_vector(linestyle::Symbol)
dash = 12
dot = 3
gap = 2
linestyle == :solid && return Int[]
linestyle == :dash && return Int[dash, gap]
linestyle == :dot && return Int[dot, gap]
linestyle == :dashdot && return Int[dash, gap, dot, gap]
linestyle == :dashdotdot && return Int[dash, gap, dot, gap, dot, gap]
error("unsupported linestyle: ", linestyle)
end
# ---------------------------------------------------------------------------
function _create_plot(pkg::BokehPackage; kw...)
d = Dict(kw)
# dumpdict(d, "plot", true)
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc
datacolumns = Bokeh.BokehDataSet[]
tools = Bokeh.tools()
filename = tempname() * ".html"
title = d[:title]
w, h = d[:size]
xaxis_type = d[:xscale] == :log10 ? :log : :auto
yaxis_type = d[:yscale] == :log10 ? :log : :auto
# legend = d[:legend] ? xxxx : nothing
legend = nothing
extra_args = Dict() # TODO: we'll put extra settings (xlim, etc) here
bplt = Bokeh.Plot(datacolumns, tools, filename, title, w, h, xaxis_type, yaxis_type, legend) #, extra_args)
Plot(bplt, pkg, 0, d, Dict[])
end
function _add_series(::BokehPackage, plt::Plot; kw...)
d = Dict(kw)
# dumpdict(d, "plot!", true)
bdata = Dict{Symbol, Vector}(:x => collect(d[:x]), :y => collect(d[:y]))
glyph = Bokeh.Bokehjs.Glyph(
glyphtype = bokeh_glyph_type(d),
linecolor = webcolor(d[:linecolor]), # shape's stroke or line color
linewidth = d[:linewidth], # shape's stroke width or line width
fillcolor = webcolor(d[:markercolor]),
size = ceil(Int, d[:markersize] * 2.5), # magic number 2.5 to keep in same scale as other backends
dash = get_stroke_vector(d[:linestyle])
)
legend = nothing # TODO
push!(plt.o.datacolumns, Bokeh.BokehDataSet(bdata, glyph, legend))
push!(plt.seriesargs, d)
plt
end
# ----------------------------------------------------------------
# TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot(plt::Plot{BokehPackage}, d::Dict)
end
function _update_plot_pos_size(plt::PlottingObject{BokehPackage}, d::Dict)
end
# ----------------------------------------------------------------
# accessors for x/y data
function Base.getindex(plt::Plot{BokehPackage}, i::Int)
series = plt.o.datacolumns[i].data
series[:x], series[:y]
end
function Base.setindex!(plt::Plot{BokehPackage}, xy::Tuple, i::Integer)
series = plt.o.datacolumns[i].data
series[:x], series[:y] = xy
plt
end
# ----------------------------------------------------------------
function _add_annotations{X,Y,V}(plt::Plot{BokehPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
# TODO: add the annotation to the plot
end
end
# ----------------------------------------------------------------
function _create_subplot(subplt::Subplot{BokehPackage}, isbefore::Bool)
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
end
function _expand_limits(lims, plt::Plot{BokehPackage}, isx::Bool)
# TODO: call expand limits for each plot data
end
function _remove_axis(plt::Plot{BokehPackage}, isx::Bool)
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
end
# ----------------------------------------------------------------
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{BokehPackage})
# TODO: write a png to io
warn("mime png not implemented")
end
function Base.display(::PlotsDisplay, plt::Plot{BokehPackage})
Bokeh.showplot(plt.o)
end
function Base.display(::PlotsDisplay, plt::Subplot{BokehPackage})
# TODO: display/show the subplot
end
+163 -80
View File
@@ -3,12 +3,16 @@
# ---------------------------------------------------------------------------
# immutable MissingVec <: AbstractVector{Float64} end
# Base.size(v::MissingVec) = (1,)
# Base.getindex(v::MissingVec, i::Integer) = 0.0
function createGadflyPlotObject(d::Dict)
gplt = Gadfly.Plot()
gplt.mapping = Dict()
gplt.data_source = DataFrames.DataFrame()
gplt.layers = gplt.layers[1:0]
gplt.data_source = Gadfly.DataFrames.DataFrame()
# gplt.layers = gplt.layers[1:0]
gplt.layers = [Gadfly.layer(Gadfly.Geom.point(tag=:remove), x=zeros(1), y=zeros(1));] # x=MissingVec(), y=MissingVec());]
gplt.guides = Gadfly.GuideElement[Gadfly.Guide.xlabel(d[:xlabel]),
Gadfly.Guide.ylabel(d[:ylabel]),
Gadfly.Guide.title(d[:title])]
@@ -36,42 +40,61 @@ function getLineGeom(d::Dict)
elseif lt == :steppre
Gadfly.Geom.step(direction = :vh)
elseif lt == :hline
Gadfly.Geom.hline(color = getColor(d[:color]), size = d[:linewidth] * Gadfly.px)
Gadfly.Geom.hline
elseif lt == :vline
Gadfly.Geom.vline(color = getColor(d[:color]), size = d[:linewidth] * Gadfly.px)
Gadfly.Geom.vline
elseif lt == :contour
Gadfly.Geom.contour(levels = d[:nlevels])
Gadfly.Geom.contour(levels = d[:levels])
else
nothing
end
end
function get_extra_theme_args(d::Dict, k::Symbol)
# gracefully handles old Gadfly versions
extra_theme_args = Dict()
try
extra_theme_args[:line_style] = Gadfly.get_stroke_vector(d[k])
catch err
if string(err) == "UndefVarError(:get_stroke_vector)"
Base.warn_once("Gadfly.get_stroke_vector failed... do you have an old version of Gadfly?")
else
rethrow()
end
end
extra_theme_args
end
function getGadflyLineTheme(d::Dict)
lc = getColor(d[:color])
α = d[:lineopacity]
if α != nothing
lc = RGBA(lc, α)
end
lc = convertColor(getColor(d[:linecolor]), d[:linealpha])
# lc = getColor(d[:linecolor])
# α = d[:linealpha]
# if α != nothing
# lc = RGBA(lc, α)
# end
fc = convertColor(getColor(d[:fillcolor]), d[:fillalpha])
# fc = getColor(d[:fillcolor])
# α = d[:fillalpha]
# if α != nothing
# fc = RGBA(fc, α)
# end
fc = getColor(d[:fillcolor])
α = d[:fillopacity]
if α != nothing
fc = RGBA(fc, α)
end
Gadfly.Theme(;
default_color = lc,
line_width = (d[:linetype] == :sticks ? 1 : d[:linewidth]) * Gadfly.px,
line_style = Gadfly.get_stroke_vector(d[:linestyle]),
# line_style = Gadfly.get_stroke_vector(d[:linestyle]),
lowlight_color = x->RGB(fc), # fill/ribbon
lowlight_opacity = alpha(fc), # fill/ribbon
bar_highlight = RGB(lc), # bars
get_extra_theme_args(d, :linestyle)...
)
end
# add a line as a new layer
function addGadflyLine!(plt::Plot, d::Dict, geoms...)
function addGadflyLine!(plt::Plot, numlayers::Int, d::Dict, geoms...)
gplt = getGadflyContext(plt)
gfargs = vcat(geoms...,
getGadflyLineTheme(d))
@@ -87,23 +110,50 @@ function addGadflyLine!(plt::Plot, d::Dict, geoms...)
push!(gfargs, Gadfly.Geom.ribbon)
end
# h/vlines
if lt == :hline
kwargs[:yintercept] = d[:y]
elseif lt == :vline
kwargs[:xintercept] = d[:y]
elseif lt == :sticks
w = 0.01 * mean(diff(d[:x]))
kwargs[:xmin] = d[:x] - w
kwargs[:xmax] = d[:x] + w
elseif lt == :contour
d[:y] = reverse(d[:y])
kwargs[:z] = d[:surface]
if lt in (:hline, :vline)
kwargs[lt == :hline ? :yintercept : :xintercept] = d[:y]
else
if lt == :sticks
w = 0.01 * mean(diff(d[:x]))
kwargs[:xmin] = d[:x] - w
kwargs[:xmax] = d[:x] + w
elseif lt == :contour
# d[:y] = reverse(d[:y])
kwargs[:z] = d[:z].surf
addGadflyContColorScale(plt, d[:linecolor])
end
kwargs[:x] = d[lt == :hist ? :y : :x]
kwargs[:y] = d[:y]
end
# # h/vlines
# if lt == :hline
# kwargs[:yintercept] = d[:y]
# elseif lt == :vline
# kwargs[:xintercept] = d[:y]
# elseif lt == :sticks
# w = 0.01 * mean(diff(d[:x]))
# kwargs[:xmin] = d[:x] - w
# kwargs[:xmax] = d[:x] + w
# elseif lt == :contour
# d[:y] = reverse(d[:y])
# kwargs[:z] = d[:surface]
# end
# if lt == :hist
# kwargs[:x] = kwargs[:y] = d[:y]
# elseif lt != :hline && lt != :vline
# kwargs[:x] = d[:x]
# kwargs[:y] = d[:y]
# end
# add the layer
x = d[d[:linetype] == :hist ? :y : :x]
Gadfly.layer(gfargs...; x = x, y = d[:y], kwargs...)
# # add the layer
# x = d[d[:linetype] == :hist ? :y : :x]
# Gadfly.layer(gfargs...; x = x, y = d[:y], order=numlayers, kwargs...)
Gadfly.layer(gfargs...; order=numlayers, kwargs...)
end
@@ -116,39 +166,56 @@ function getMarkerGeom(d::Dict)
end
function getGadflyMarkerTheme(d::Dict, initargs::Dict)
function getGadflyMarkerTheme(d::Dict, plotargs::Dict)
c = getColor(d[:markercolor])
α = d[:markeropacity]
α = d[:markeralpha]
if α != nothing
c = RGBA(RGB(c), α)
end
fg = getColor(initargs[:foreground_color])
Gadfly.Theme(
ms = d[:markersize]
ms = if typeof(ms) <: AVec
warn("Gadfly doesn't support variable marker sizes... using the average: $(mean(ms))")
mean(ms) * Gadfly.px
else
ms * Gadfly.px
end
# fg = getColor(plotargs[:foreground_color])
Gadfly.Theme(;
default_color = c,
default_point_size = d[:markersize] * Gadfly.px,
discrete_highlight_color = c -> RGB(fg),
highlight_width = d[:linewidth] * Gadfly.px,
default_point_size = ms,
discrete_highlight_color = c -> RGB(getColor(d[:markerstrokecolor])),
highlight_width = d[:markerstrokewidth] * Gadfly.px,
# get_extra_theme_args(d, :markerstrokestyle)...
)
end
function addGadflyMarker!(plt::Plot, d::Dict, initargs::Dict, geoms...)
function addGadflyContColorScale(plt::Plot{GadflyPackage}, c)
if !isa(c, ColorGradient)
c = colorscheme(:bluesreds)
end
push!(getGadflyContext(plt).scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(c, p))))
end
function addGadflyMarker!(plt::Plot, numlayers::Int, d::Dict, plotargs::Dict, geoms...)
gfargs = vcat(geoms...,
getGadflyMarkerTheme(d, initargs),
getGadflyMarkerTheme(d, plotargs),
getMarkerGeom(d))
kwargs = Dict()
# handle continuous color scales for the markers
z = d[:z]
if z != nothing && typeof(z) <: AVec
kwargs[:color] = z
if !isa(d[:markercolor], ColorGradient)
d[:markercolor] = colorscheme(:bluesreds)
end
push!(getGadflyContext(plt).scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(d[:markercolor], p))))
zcolor = d[:zcolor]
if zcolor != nothing && typeof(zcolor) <: AVec
kwargs[:color] = zcolor
addGadflyContColorScale(plt, d[:markercolor])
# if !isa(d[:markercolor], ColorGradient)
# d[:markercolor] = colorscheme(:bluesreds)
# end
# push!(getGadflyContext(plt).scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(d[:markercolor], p))))
end
Gadfly.layer(gfargs...; x = d[:x], y = d[:y], kwargs...)
Gadfly.layer(gfargs...; x = d[:x], y = d[:y], order=numlayers, kwargs...)
end
@@ -157,7 +224,7 @@ end
function addToGadflyLegend(plt::Plot, d::Dict)
# add the legend?
if plt.initargs[:legend]
if plt.plotargs[:legend]
gplt = getGadflyContext(plt)
# add the legend if needed
@@ -172,7 +239,7 @@ function addToGadflyLegend(plt::Plot, d::Dict)
# 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
c = getColor(d[d[:markershape] == :none ? :color : :markercolor])
c = getColor(d[d[:markershape] == :none ? :linecolor : :markercolor])
foundit = false
# extend the label if we found this color
@@ -202,6 +269,7 @@ getGadflySmoothing(smooth::Real) = [Gadfly.Geom.smooth(method=:loess, smoothing=
function addGadflySeries!(plt::Plot, d::Dict)
layers = Gadfly.Layer[]
gplt = getGadflyContext(plt)
# add a regression line?
# TODO: make more flexible
@@ -210,7 +278,7 @@ function addGadflySeries!(plt::Plot, d::Dict)
# lines
geom = getLineGeom(d)
if geom != nothing
prepend!(layers, addGadflyLine!(plt, d, geom, smooth...))
prepend!(layers, addGadflyLine!(plt, length(gplt.layers), d, geom, smooth...))
# don't add a regression for markers too
smooth = Any[]
@@ -220,20 +288,22 @@ function addGadflySeries!(plt::Plot, d::Dict)
lt = d[:linetype]
if lt == :ohlc
error("Haven't re-implemented after refactoring")
elseif lt in (:heatmap, :hexbin) && (isa(d[:linecolor], ColorGradient) || isa(d[:linecolor], ColorFunction))
push!(gplt.scales, Gadfly.Scale.ContinuousColorScale(p -> RGB(getColorZ(d[:linecolor], p))))
elseif lt == :scatter && d[:markershape] == :none
d[:markershape] = :ellipse
end
# markers
if d[:markershape] != :none
prepend!(layers, addGadflyMarker!(plt, d, plt.initargs, smooth...))
prepend!(layers, addGadflyMarker!(plt, length(gplt.layers), d, plt.plotargs, smooth...))
end
lt in (:hist, :heatmap, :hexbin, :contour) || addToGadflyLegend(plt, d)
# now save the layers that apply to this series
d[:gadflylayers] = layers
prepend!(getGadflyContext(plt).layers, layers)
prepend!(gplt.layers, layers)
end
@@ -245,7 +315,7 @@ end
# z = d[:z]
# # handle line segments of different colors
# cscheme = d[:color]
# cscheme = d[:linecolor]
# if isa(cscheme, ColorVector)
# # create a color scale, and set the color group to the index of the color
# push!(gplt.scales, Gadfly.Scale.color_discrete_manual(cscheme.v...))
@@ -257,7 +327,7 @@ end
# 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)]
# colorgroup = [(:linecolor, cs), (:group, grp)]
# ---------------------------------------------------------------------------
@@ -305,7 +375,7 @@ function getGadflyScaleFunction(d::Dict, isx::Bool)
hasScaleKey = haskey(d, scalekey)
if hasScaleKey
scale = d[scalekey]
scale == :log && return isx ? Gadfly.Scale.x_log : Gadfly.Scale.y_log, hasScaleKey
scale == :ln && 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_log10 : Gadfly.Scale.y_log10, hasScaleKey
scale == :asinh && return isx ? Gadfly.Scale.x_asinh : Gadfly.Scale.y_asinh, hasScaleKey
@@ -323,14 +393,19 @@ function addGadflyLimitsScale(gplt, d::Dict, isx::Bool)
# do we want to add min/max limits for the axis?
limsym = isx ? :xlims : :ylims
limargs = Any[]
lims = get(d, limsym, :auto)
lims == :auto && return
if limsType(lims) == :limits
push!(limargs, (:minvalue, min(lims...)))
push!(limargs, (:maxvalue, max(lims...)))
# map :auto to nothing, otherwise add to limargs
lims = get(d, limsym, :auto)
# lims == :auto && return
if lims == :auto
lims = nothing
else
error("Invalid input for $(isx ? "xlims" : "ylims"): ", lims)
if limsType(lims) == :limits
push!(limargs, (:minvalue, min(lims...)))
push!(limargs, (:maxvalue, max(lims...)))
else
error("Invalid input for $(isx ? "xlims" : "ylims"): ", lims)
end
end
# replace any current scales with this one
@@ -385,13 +460,13 @@ function updateGadflyGuides(plt::Plot, d::Dict)
ticks = get(d, :xticks, :auto)
if ticks == :none
handleLinkInner(plt, true)
_remove_axis(plt, true)
else
addGadflyTicksGuide(gplt, ticks, true)
end
ticks = get(d, :yticks, :auto)
if ticks == :none
handleLinkInner(plt, false)
_remove_axis(plt, false)
else
addGadflyTicksGuide(gplt, ticks, false)
end
@@ -403,9 +478,9 @@ end
function updateGadflyPlotTheme(plt::Plot, d::Dict)
kwargs = Dict()
# # get the full initargs, overriding any new settings
# # get the full plotargs, overriding any new settings
# # TODO: should this be part of the main `plot` command in plot.jl???
# d = merge!(plt.initargs, d)
# d = merge!(plt.plotargs, d)
# hide the legend?
if !get(d, :legend, true)
@@ -463,7 +538,7 @@ function createGadflyAnnotationObject(x, y, txt::PlotText)
))
end
function addAnnotations{X,Y,V}(plt::Plot{GadflyPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
function _add_annotations{X,Y,V}(plt::Plot{GadflyPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
push!(plt.o.guides, createGadflyAnnotationObject(ann...))
end
@@ -473,7 +548,7 @@ end
# ---------------------------------------------------------------------------
# create a blank Gadfly.Plot object
function plot(pkg::GadflyPackage; kw...)
function _create_plot(pkg::GadflyPackage; kw...)
d = Dict(kw)
gplt = createGadflyPlotObject(d)
Plot(gplt, pkg, 0, d, Dict[])
@@ -481,7 +556,14 @@ end
# plot one data series
function plot!(::GadflyPackage, plt::Plot; kw...)
function _add_series(::GadflyPackage, plt::Plot; kw...)
# first clear out the temporary layer
gplt = getGadflyContext(plt)
if gplt.layers[1].geom.tag == :remove
gplt.layers = gplt.layers[2:end]
end
d = Dict(kw)
addGadflySeries!(plt, d)
push!(plt.seriesargs, d)
@@ -490,7 +572,7 @@ end
function updatePlotItems(plt::Plot{GadflyPackage}, d::Dict)
function _update_plot(plt::Plot{GadflyPackage}, d::Dict)
updateGadflyGuides(plt, d)
updateGadflyPlotTheme(plt, d)
end
@@ -522,22 +604,22 @@ end
# create the underlying object (each backend will do this differently)
function buildSubplotObject!(subplt::Subplot{GadflyPackage}, isbefore::Bool)
function _create_subplot(subplt::Subplot{GadflyPackage}, isbefore::Bool)
isbefore && return false # wait until after plotting to create the subplots
subplt.o = nothing
true
end
function handleLinkInner(plt::Plot{GadflyPackage}, isx::Bool)
function _remove_axis(plt::Plot{GadflyPackage}, isx::Bool)
gplt = getGadflyContext(plt)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xlabel : Gadfly.Guide.ylabel, "")
end
function expandLimits!(lims, plt::Plot{GadflyPackage}, isx::Bool)
function _expand_limits(lims, plt::Plot{GadflyPackage}, isx::Bool)
for l in getGadflyContext(plt).layers
expandLimits!(lims, l.mapping[isx ? :x : :y])
_expand_limits(lims, l.mapping[isx ? :x : :y])
end
end
@@ -569,8 +651,8 @@ function buildGadflySubplotContext(subplt::Subplot)
end
setGadflyDisplaySize(w,h) = Compose.set_default_graphic_size(w * Compose.px, h * Compose.px)
setGadflyDisplaySize(plt::Plot) = setGadflyDisplaySize(plt.initargs[:size]...)
setGadflyDisplaySize(subplt::Subplot) = setGadflyDisplaySize(getinitargs(subplt, 1)[:size]...)
setGadflyDisplaySize(plt::Plot) = setGadflyDisplaySize(plt.plotargs[:size]...)
setGadflyDisplaySize(subplt::Subplot) = setGadflyDisplaySize(getplotargs(subplt, 1)[:size]...)
# -------------------------------------------------------------------------
@@ -585,9 +667,10 @@ getGadflyWriteFunc(::MIME"image/svg+xml") = Gadfly.SVG
# getGadflyWriteFunc(::MIME"text/html") = Gadfly.SVGJS
getGadflyWriteFunc(::MIME"application/pdf") = Gadfly.PDF
getGadflyWriteFunc(::MIME"application/postscript") = Gadfly.PS
getGadflyWriteFunc(::MIME"application/x-tex") = Gadfly.PGF
getGadflyWriteFunc(m::MIME) = error("Unsupported in Gadfly/Immerse: ", m)
for mime in (MIME"image/png", MIME"image/svg+xml", MIME"application/pdf", MIME"application/postscript")
for mime in (MIME"image/png", MIME"image/svg+xml", MIME"application/pdf", MIME"application/postscript", MIME"application/x-tex")
@eval function Base.writemime{P<:GadflyOrImmerse}(io::IO, ::$mime, plt::PlottingObject{P})
func = getGadflyWriteFunc($mime())
dowritemime(io, func, plt)
@@ -597,14 +680,14 @@ end
function Base.display(::PlotsDisplay, plt::Plot{GadflyPackage})
setGadflyDisplaySize(plt.initargs[:size]...)
setGadflyDisplaySize(plt.plotargs[:size]...)
display(plt.o)
end
function Base.display(::PlotsDisplay, subplt::Subplot{GadflyPackage})
setGadflyDisplaySize(getinitargs(subplt,1)[:size]...)
setGadflyDisplaySize(getplotargs(subplt,1)[:size]...)
ctx = buildGadflySubplotContext(subplt)
+105
View File
@@ -0,0 +1,105 @@
# [WEBSITE]
# ---------------------------------------------------------------------------
immutable GLScreenWrapper
window
render
end
function _create_plot(pkg::GLVisualizePackage; kw...)
d = Dict(kw)
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc
# TODO: this should be moved to the display method?
w,r=GLVisualize.glscreen()
@async r()
o = GLScreenWrapper(w,r)
Plot(o, pkg, 0, d, Dict[])
end
function _add_series(::GLVisualizePackage, plt::Plot; kw...)
d = Dict(kw)
# TODO: add one series to the underlying package
push!(plt.seriesargs, d)
# TODO: this should be moved to the display method?
x, y, z = map(Float32, d[:x]), map(Float32, d[:y]), map(Float32, d[:z].surf)
viz = GLVisualize.visualize(x*ones(y)', ones(x)*y', z, :surface)
GLVisualize.view(viz)
plt
end
function _add_annotations{X,Y,V}(plt::Plot{GLVisualizePackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
# TODO: add the annotation to the plot
end
end
# ----------------------------------------------------------------
function _before_update_plot(plt::Plot{GLVisualizePackage})
end
# TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot(plt::Plot{GLVisualizePackage}, d::Dict)
end
function _update_plot_pos_size(plt::PlottingObject{GLVisualizePackage}, d::Dict)
end
# ----------------------------------------------------------------
# accessors for x/y data
function Base.getindex(plt::Plot{GLVisualizePackage}, i::Int)
# TODO:
# series = plt.o.lines[i]
# series.x, series.y
nothing, nothing
end
function Base.setindex!(plt::Plot{GLVisualizePackage}, xy::Tuple, i::Integer)
# TODO:
# series = plt.o.lines[i]
# series.x, series.y = xy
plt
end
# ----------------------------------------------------------------
function _create_subplot(subplt::Subplot{GLVisualizePackage})
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
end
function _expand_limits(lims, plt::Plot{GLVisualizePackage}, isx::Bool)
# TODO: call expand limits for each plot data
end
function _remove_axis(plt::Plot{GLVisualizePackage}, isx::Bool)
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
end
# ----------------------------------------------------------------
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{GLVisualizePackage})
# TODO: write a png to io
end
function Base.display(::PlotsDisplay, plt::Plot{GLVisualizePackage})
# TODO: display/show the plot
# NOTE: I think maybe this should be empty? We can start with the assumption that creating
# and adding to a plot will automatically open a window and draw to it, then the display
# wouldn't actually need to do anything
end
function Base.display(::PlotsDisplay, plt::Subplot{GLVisualizePackage})
# TODO: display/show the subplot
end
+12 -23
View File
@@ -1,19 +1,6 @@
# https://github.com/JuliaGraphics/Immerse.jl
# immutable ImmersePackage <: PlottingPackage end
# export immerse
# immerse() = backend(:immerse)
# supportedArgs(::ImmersePackage) = supportedArgs(GadflyPackage())
# supportedAxes(::ImmersePackage) = supportedAxes(GadflyPackage())
# supportedTypes(::ImmersePackage) = supportedTypes(GadflyPackage())
# supportedStyles(::ImmersePackage) = supportedStyles(GadflyPackage())
# supportedMarkers(::ImmersePackage) = supportedMarkers(GadflyPackage())
# supportedScales(::ImmersePackage) = supportedScales(GadflyPackage())
function createImmerseFigure(d::Dict)
w,h = d[:size]
@@ -21,9 +8,11 @@ function createImmerseFigure(d::Dict)
Immerse.Figure(figidx)
end
# ----------------------------------------------------------------
# create a blank Gadfly.Plot object
function plot(pkg::ImmersePackage; kw...)
function _create_plot(pkg::ImmersePackage; kw...)
d = Dict(kw)
# create the underlying Gadfly.Plot object
@@ -35,7 +24,7 @@ end
# plot one data series
function plot!(::ImmersePackage, plt::Plot; kw...)
function _add_series(::ImmersePackage, plt::Plot; kw...)
d = Dict(kw)
addGadflySeries!(plt, d)
push!(plt.seriesargs, d)
@@ -43,7 +32,7 @@ function plot!(::ImmersePackage, plt::Plot; kw...)
end
function updatePlotItems(plt::Plot{ImmersePackage}, d::Dict)
function _update_plot(plt::Plot{ImmersePackage}, d::Dict)
updateGadflyGuides(plt, d)
updateGadflyPlotTheme(plt, d)
end
@@ -52,7 +41,7 @@ end
# ----------------------------------------------------------------
function addAnnotations{X,Y,V}(plt::Plot{ImmersePackage}, anns::AVec{@compat(Tuple{X,Y,V})})
function _add_annotations{X,Y,V}(plt::Plot{ImmersePackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
push!(getGadflyContext(plt).guides, createGadflyAnnotationObject(ann...))
end
@@ -78,14 +67,14 @@ end
# ----------------------------------------------------------------
function buildSubplotObject!(subplt::Subplot{ImmersePackage}, isbefore::Bool)
function _create_subplot(subplt::Subplot{ImmersePackage}, isbefore::Bool)
return false
# isbefore && return false
end
function showSubplotObject(subplt::Subplot{ImmersePackage})
# create the Gtk window with vertical box vsep
d = getinitargs(subplt,1)
d = getplotargs(subplt,1)
w,h = d[:size]
vsep = Gtk.GtkBoxLeaf(:v)
win = Gtk.GtkWindowLeaf(vsep, d[:windowtitle], w, h)
@@ -125,15 +114,15 @@ function showSubplotObject(subplt::Subplot{ImmersePackage})
end
function handleLinkInner(plt::Plot{ImmersePackage}, isx::Bool)
function _remove_axis(plt::Plot{ImmersePackage}, isx::Bool)
gplt = getGadflyContext(plt)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xticks : Gadfly.Guide.yticks; label=false)
addOrReplace(gplt.guides, isx ? Gadfly.Guide.xlabel : Gadfly.Guide.ylabel, "")
end
function expandLimits!(lims, plt::Plot{ImmersePackage}, isx::Bool)
function _expand_limits(lims, plt::Plot{ImmersePackage}, isx::Bool)
for l in getGadflyContext(plt).layers
expandLimits!(lims, l.mapping[isx ? :x : :y])
_expand_limits(lims, l.mapping[isx ? :x : :y])
end
end
@@ -148,7 +137,7 @@ function Base.display(::PlotsDisplay, plt::Plot{ImmersePackage})
fig, gplt = plt.o
if fig == nothing
fig = createImmerseFigure(plt.initargs)
fig = createImmerseFigure(plt.plotargs)
Gtk.on_signal_destroy((x...) -> (Immerse.dropfig(Immerse._display, fig.figno); plt.o = (nothing,gplt)), fig.canvas)
plt.o = (fig, gplt)
end
+447
View File
@@ -0,0 +1,447 @@
# https://plot.ly/javascript/getting-started
# ---------------------------------------------------------------------------
function _create_plot(pkg::PlotlyPackage; kw...)
d = Dict(kw)
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc
Plot(nothing, pkg, 0, d, Dict[])
end
function _add_series(::PlotlyPackage, plt::Plot; kw...)
d = Dict(kw)
# TODO: add one series to the underlying package
push!(plt.seriesargs, d)
plt
end
function _add_annotations{X,Y,V}(plt::Plot{PlotlyPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
# set or add to the annotation_list
if haskey(plt.plotargs, :annotation_list)
append!(plt.plotargs[:annotation_list], anns)
else
plt.plotargs[:annotation_list] = anns
end
end
# ----------------------------------------------------------------
function _before_update_plot(plt::Plot{PlotlyPackage})
end
# TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot(plt::Plot{PlotlyPackage}, d::Dict)
end
function _update_plot_pos_size(plt::PlottingObject{PlotlyPackage}, d::Dict)
end
# ----------------------------------------------------------------
# accessors for x/y data
function Base.getindex(plt::Plot{PlotlyPackage}, i::Int)
d = plt.seriesargs[i]
d[:x], d[:y]
end
function Base.setindex!(plt::Plot{PlotlyPackage}, xy::Tuple, i::Integer)
d = plt.seriesargs[i]
d[:x], d[:y] = xy
plt
end
# ----------------------------------------------------------------
function _create_subplot(subplt::Subplot{PlotlyPackage}, isbefore::Bool)
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
true
end
function _expand_limits(lims, plt::Plot{PlotlyPackage}, isx::Bool)
# TODO: call expand limits for each plot data
end
function _remove_axis(plt::Plot{PlotlyPackage}, isx::Bool)
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
end
# ----------------------------------------------------------------
# TODO:
# _plotDefaults[:yrightlabel] = ""
# _plotDefaults[:xlims] = :auto
# _plotDefaults[:ylims] = :auto
# _plotDefaults[:xticks] = :auto
# _plotDefaults[:yticks] = :auto
# _plotDefaults[:xscale] = :identity
# _plotDefaults[:yscale] = :identity
# _plotDefaults[:xflip] = false
# _plotDefaults[:yflip] = false
function plotlyfont(font::Font, color = font.color)
Dict(
:family => font.family,
:size => round(Int, font.pointsize*1.4),
:color => webcolor(color),
)
end
function get_annotation_dict(x, y, val::Union{AbstractString,Symbol})
Dict(
:text => val,
:xref => "x",
:x => x,
:yref => "y",
:y => y,
:showarrow => false,
)
end
function get_annotation_dict(x, y, ptxt::PlotText)
merge(get_annotation_dict(x, y, ptxt.str), Dict(
:font => plotlyfont(ptxt.font),
:xanchor => ptxt.font.halign == :hcenter ? :center : ptxt.font.halign,
:yanchor => ptxt.font.valign == :vcenter ? :middle : ptxt.font.valign,
:rotation => ptxt.font.rotation,
))
end
function plotlyscale(scale::Symbol)
if scale == :log10
"log"
else
"-"
end
end
use_axis_field(ticks) = !(ticks in (nothing, :none))
tickssym(isx::Bool) = symbol((isx ? "x" : "y") * "ticks")
limssym(isx::Bool) = symbol((isx ? "x" : "y") * "lims")
flipsym(isx::Bool) = symbol((isx ? "x" : "y") * "flip")
scalesym(isx::Bool) = symbol((isx ? "x" : "y") * "scale")
labelsym(isx::Bool) = symbol((isx ? "x" : "y") * "label")
function plotlyaxis(d::Dict, isx::Bool)
ax = Dict(
:title => d[labelsym(isx)],
:showgrid => d[:grid],
:zeroline => false,
)
fgcolor = webcolor(d[:foreground_color])
tsym = tickssym(isx)
if use_axis_field(d[tsym])
ax[:titlefont] = plotlyfont(d[:guidefont], fgcolor)
ax[:type] = plotlyscale(d[scalesym(isx)])
ax[:tickfont] = plotlyfont(d[:tickfont], fgcolor)
ax[:tickcolor] = fgcolor
ax[:linecolor] = fgcolor
# xlims
lims = d[limssym(isx)]
if lims != :auto && limsType(lims) == :limits
ax[:range] = lims
end
# xflip
if d[flipsym(isx)]
ax[:autorange] = "reversed"
end
# xticks
ticks = d[tsym]
if ticks != :auto
ttype = ticksType(ticks)
if ttype == :ticks
ax[:tickmode] = "array"
ax[:tickvals] = ticks
elseif ttype == :ticks_and_labels
ax[:tickmode] = "array"
ax[:tickvals], ax[:ticktext] = ticks
end
end
ax
else
ax[:showticklabels] = false
ax[:showgrid] = false
end
ax
end
# function get_plot_json(plt::Plot{PlotlyPackage})
# d = plt.plotargs
function plotly_layout(d::Dict)
d_out = Dict()
bgcolor = webcolor(d[:background_color])
fgcolor = webcolor(d[:foreground_color])
# set the fields for the plot
d_out[:title] = d[:title]
d_out[:titlefont] = plotlyfont(d[:guidefont], fgcolor)
d_out[:margin] = Dict(:l=>35, :b=>30, :r=>8, :t=>20)
d_out[:plot_bgcolor] = bgcolor
d_out[:paper_bgcolor] = bgcolor
# TODO: x/y axis tick values/labels
d_out[:xaxis] = plotlyaxis(d, true)
d_out[:yaxis] = plotlyaxis(d, false)
# legend
d_out[:showlegend] = d[:legend]
if d[:legend]
d_out[:legend] = Dict(
:bgcolor => bgcolor,
:bordercolor => fgcolor,
:font => plotlyfont(d[:legendfont]),
)
end
# annotations
anns = get(d, :annotation_list, [])
if !isempty(anns)
d_out[:annotations] = [get_annotation_dict(ann...) for ann in anns]
end
d_out
end
function get_plot_json(plt::Plot{PlotlyPackage})
JSON.json(plotly_layout(plt.plotargs))
end
function plotly_colorscale(grad::ColorGradient)
[[grad.values[i], webcolor(grad.colors[i])] for i in 1:length(grad.colors)]
end
plotly_colorscale(c) = plotly_colorscale(ColorGradient(:bluesreds))
const _plotly_markers = Dict(
:rect => "square",
:xcross => "x",
:utriangle => "triangle-up",
:dtriangle => "triangle-down",
:star5 => "star-triangle-up",
:vline => "line-ns",
:hline => "line-ew",
)
# get a dictionary representing the series params (d is the Plots-dict, d_out is the Plotly-dict)
function plotly_series(d::Dict; plot_index = nothing)
d_out = Dict()
x, y = collect(d[:x]), collect(d[:y])
d_out[:name] = d[:label]
lt = d[:linetype]
isscatter = lt in (:scatter, :scatter3d)
hasmarker = isscatter || d[:markershape] != :none
hasline = !isscatter
# set the "type"
if lt in (:line, :path, :scatter, :steppre, :steppost)
d_out[:type] = "scatter"
d_out[:mode] = if hasmarker
hasline ? "lines+markers" : "markers"
else
hasline ? "lines" : "none"
end
if d[:fillrange] == true || d[:fillrange] == 0
d_out[:fill] = "tozeroy"
d_out[:fillcolor] = webcolor(d[:fillcolor], d[:fillalpha])
elseif !(d[:fillrange] in (false, nothing))
warn("fillrange ignored... plotly only supports filling to zero. fillrange: $(d[:fillrange])")
end
d_out[:x], d_out[:y] = x, y
elseif lt == :bar
d_out[:type] = "bar"
d_out[:x], d_out[:y] = x, y
elseif lt == :heatmap
d_out[:type] = "histogram2d"
d_out[:x], d_out[:y] = x, y
if isa(d[:nbins], Tuple)
xbins, ybins = d[:nbins]
else
xbins = ybins = d[:nbins]
end
d_out[:nbinsx] = xbins
d_out[:nbinsy] = ybins
elseif lt in (:hist, :density)
d_out[:type] = "histogram"
isvert = d[:orientation] in (:vertical, :v, :vert)
d_out[isvert ? :x : :y] = y
d_out[isvert ? :nbinsx : :nbinsy] = d[:nbins]
if lt == :density
d_out[:histnorm] = "probability density"
end
elseif lt in (:contour, :surface, :wireframe)
d_out[:type] = lt == :wireframe ? :surface : string(lt)
d_out[:x], d_out[:y] = x, y
d_out[:z] = d[:z].surf
# d_out[:showscale] = d[:legend]
if lt == :contour
d_out[:ncontours] = d[:levels]
d_out[:contours] = Dict(:coloring => d[:fillrange] != nothing ? "fill" : "lines")
end
d_out[:colorscale] = plotly_colorscale(d[lt == :contour ? :linecolor : :fillcolor])
elseif lt == :pie
d_out[:type] = "pie"
d_out[:labels] = x
d_out[:values] = y
d_out[:hoverinfo] = "label+percent+name"
elseif lt in (:path3d, :scatter3d)
d_out[:type] = "scatter3d"
d_out[:mode] = if hasmarker
hasline ? "lines+markers" : "markers"
else
hasline ? "lines" : "none"
end
d_out[:x], d_out[:y] = x, y
d_out[:z] = collect(d[:z])
else
warn("Plotly: linetype $lt isn't supported.")
return Dict()
end
# add "marker"
if hasmarker
d_out[:marker] = Dict(
:symbol => get(_plotly_markers, d[:markershape], string(d[:markershape])),
:opacity => d[:markeralpha],
:size => 2 * d[:markersize],
:color => webcolor(d[:markercolor], d[:markeralpha]),
:line => Dict(
:color => webcolor(d[:markerstrokecolor], d[:markerstrokealpha]),
:width => d[:markerstrokewidth],
),
)
if d[:zcolor] != nothing
d_out[:marker][:color] = d[:zcolor]
d_out[:marker][:colorscale] = plotly_colorscale(d[:markercolor])
end
end
# add "line"
if hasline
d_out[:line] = Dict(
:color => webcolor(d[:linecolor], d[:linealpha]),
:width => d[:linewidth],
:shape => if lt == :steppre
"vh"
elseif lt == :steppost
"hv"
else
"linear"
end,
:dash => string(d[:linestyle]),
# :dash => "solid",
)
end
# # for subplots, we need to add the xaxis/yaxis fields
# if plot_index != nothing
# d_out[:xaxis] = "x$(plot_index)"
# d_out[:yaxis] = "y$(plot_index)"
# end
d_out
end
# get a list of dictionaries, each representing the series params
function get_series_json(plt::Plot{PlotlyPackage})
JSON.json(map(plotly_series, plt.seriesargs))
end
function get_series_json(subplt::Subplot{PlotlyPackage})
ds = Dict[]
for (i,plt) in enumerate(subplt.plts)
for d in plt.seriesargs
push!(ds, plotly_series(d, plot_index = i))
end
end
JSON.json(ds)
end
# ----------------------------------------------------------------
function html_head(plt::PlottingObject{PlotlyPackage})
"<script src=\"$(Pkg.dir("Plots","deps","plotly-latest.min.js"))\"></script>"
end
function html_body(plt::Plot{PlotlyPackage}, style = nothing)
if style == nothing
w, h = plt.plotargs[:size]
style = "width:$(w)px;height:$(h)px;"
end
uuid = Base.Random.uuid4()
"""
<div id=\"$(uuid)\" style=\"$(style)\"></div>
<script>
PLOT = document.getElementById('$(uuid)');
Plotly.plot(PLOT, $(get_series_json(plt)), $(get_plot_json(plt)));
</script>
"""
end
function html_body(subplt::Subplot{PlotlyPackage})
w, h = subplt.plts[1].plotargs[:size]
html = ["<div style=\"width:$(w)px;height:$(h)px;\">"]
nr = nrows(subplt.layout)
ph = h / nr
for r in 1:nr
push!(html, "<div style=\"clear:both;\">")
nc = ncols(subplt.layout, r)
pw = w / nc
for c in 1:nc
plt = subplt[r,c]
push!(html, html_body(plt, "float:left; width:$(pw)px; height:$(ph)px;"))
end
push!(html, "</div>")
end
push!(html, "</div>")
join(html)
end
# ----------------------------------------------------------------
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{PlotlyPackage})
isijulia() && return
# TODO: write a png to io
println("todo: png")
end
function Base.writemime(io::IO, ::MIME"text/html", plt::PlottingObject{PlotlyPackage})
write(io, html_head(plt) * html_body(plt))
end
function Base.display(::PlotsDisplay, plt::PlottingObject{PlotlyPackage})
standalone_html_window(plt)
end
# function Base.display(::PlotsDisplay, plt::Subplot{PlotlyPackage})
# # TODO: display/show the subplot
# end
+48
View File
@@ -0,0 +1,48 @@
# override some methods to use Plotlyjs/Blink
import Plotlyjs
function _create_plot(pkg::PlotlyPackage; kw...)
d = Dict(kw)
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc
o = Plotlyjs.Plot()
Plot(o, pkg, 0, d, Dict[])
end
function _add_series(::PlotlyPackage, plt::Plot; kw...)
d = Dict(kw)
# add to the data array
pdict = plotly_series(d)
gt = Plotlyjs.GenericTrace(pdict[:type], pdict)
push!(plt.o.data, gt)
if !isnull(plt.o.window)
Plotlyjs.addtraces!(plt.o, gt)
end
push!(plt.seriesargs, d)
plt
end
# TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot(plt::Plot{PlotlyPackage}, d::Dict)
pdict = plotly_layout(d)
plt.o.layout = Plotlyjs.Layout(pdict)
if !isnull(plt.o.window)
Plotlyjs.relayout!(plt.o, pdict...)
end
end
function Base.display(::PlotsDisplay, plt::Plot{PlotlyPackage})
dump(plt.o)
show(plt.o)
end
function Base.display(::PlotsDisplay, plt::Subplot{PlotlyPackage})
error()
end
+193 -106
View File
@@ -75,46 +75,73 @@ function getPyPlotStepStyle(linetype::Symbol)
end
immutable PyPlotFigWrapper
fig
end
# immutable PyPlotFigWrapper
# fig
# kwargs # for add_subplot
# end
immutable PyPlotAxisWrapper
type PyPlotAxisWrapper
ax
rightax
fig
kwargs # for add_subplot
end
getfig(wrap::@compat(Union{PyPlotAxisWrapper,PyPlotFigWrapper})) = wrap.fig
# getfig(wrap::@compat(Union{PyPlotAxisWrapper,PyPlotFigWrapper})) = wrap.fig
getfig(wrap::PyPlotAxisWrapper) = wrap.fig
# get a reference to the correct axis
function getLeftAxis(wrap::PyPlotFigWrapper)
axes = wrap.fig.o[:axes]
if isempty(axes)
return wrap.fig.o[:add_subplot](111)
function getLeftAxis(wrap::PyPlotAxisWrapper)
if wrap.ax == nothing
axes = wrap.fig.o[:axes]
if isempty(axes)
return wrap.fig.o[:add_subplot](111; wrap.kwargs...)
end
axes[1]
else
wrap.ax
end
axes[1]
end
getLeftAxis(wrap::PyPlotAxisWrapper) = wrap.ax
# getLeftAxis(wrap::PyPlotAxisWrapper) = wrap.ax
# getRightAxis(x) = getLeftAxis(x)[:twinx]()
function getRightAxis(wrap::PyPlotAxisWrapper)
if wrap.rightax == nothing
wrap.rightax = getLeftAxis(wrap)[:twinx]()
end
wrap.rightax
end
getLeftAxis(plt::Plot{PyPlotPackage}) = getLeftAxis(plt.o)
getRightAxis(x) = getLeftAxis(x)[:twinx]()
getRightAxis(plt::Plot{PyPlotPackage}) = getRightAxis(plt.o)
getAxis(plt::Plot{PyPlotPackage}, axis::Symbol) = (axis == :right ? getRightAxis : getLeftAxis)(plt)
# left axis is PyPlot.<func>, right axis is "f.axes[0].twinx().<func>"
function getPyPlotFunction(plt::Plot, axis::Symbol, linetype::Symbol)
# # need to access mplot3d functions differently
# if linetype == :surface
# return mplot3d.pymember("Axes3D")[:plot_surface]
# end
# in the 2-axis case we need to get: <rightaxis>[:<func>]
ax = getAxis(plt, axis)
ax[:set_ylabel](plt.initargs[:yrightlabel])
# ax[:set_ylabel](plt.plotargs[:yrightlabel])
fmap = @compat Dict(
:hist => :hist,
:sticks => :bar,
:bar => :bar,
:heatmap => :hexbin,
:hexbin => :hexbin,
:scatter => :scatter,
:contour => :contour,
:hist => :hist,
:density => :hist,
:sticks => :bar,
:bar => :bar,
:heatmap => :hexbin,
:hexbin => :hexbin,
:scatter => :scatter,
:contour => :contour,
:scatter3d => :scatter,
:surface => :plot_surface,
:wireframe => :plot_wireframe,
# :surface => pycolors.pymember("LinearSegmentedColormap")[:from_list]
)
return ax[get(fmap, linetype, :plot)]
end
@@ -138,7 +165,7 @@ function handleSmooth(plt::Plot{PyPlotPackage}, ax, d::Dict, smooth::Bool)
xs, ys = regressionXY(d[:x], d[:y])
ax[:plot](xs, ys,
# linestyle = getPyPlotLineStyle(:path, :dashdot),
color = getPyPlotColor(d[:color]),
color = getPyPlotColor(d[:linecolor]),
linewidth = 2
)
end
@@ -146,15 +173,15 @@ end
handleSmooth(plt::Plot{PyPlotPackage}, ax, d::Dict, smooth::Real) = handleSmooth(plt, ax, d, true)
nop() = nothing
makePyPlotCurrent(wrap::PyPlotFigWrapper) = PyPlot.figure(wrap.fig.o[:number])
makePyPlotCurrent(wrap::PyPlotAxisWrapper) = nothing #PyPlot.sca(wrap.ax.o)
makePyPlotCurrent(plt::Plot{PyPlotPackage}) = makePyPlotCurrent(plt.o)
# makePyPlotCurrent(wrap::PyPlotFigWrapper) = PyPlot.figure(wrap.fig.o[:number])
# makePyPlotCurrent(wrap::PyPlotAxisWrapper) = nothing #PyPlot.sca(wrap.ax.o)
makePyPlotCurrent(wrap::PyPlotAxisWrapper) = wrap.ax == nothing ? PyPlot.figure(wrap.fig.o[:number]) : nothing
makePyPlotCurrent(plt::Plot{PyPlotPackage}) = plt.o == nothing ? nothing : makePyPlotCurrent(plt.o)
function preparePlotUpdate(plt::Plot{PyPlotPackage})
function _before_add_series(plt::Plot{PyPlotPackage})
makePyPlotCurrent(plt)
end
@@ -169,7 +196,7 @@ end
# screen # Integer, move enclosing window to this screen number (for multiscreen desktops)
# show # true or false, show the plot (in case you don't want the window to pop up right away)
function plot(pkg::PyPlotPackage; kw...)
function _create_plot(pkg::PyPlotPackage; kw...)
# create the figure
d = Dict(kw)
@@ -179,7 +206,11 @@ function plot(pkg::PyPlotPackage; kw...)
else
w,h = map(px2inch, d[:size])
bgcolor = getPyPlotColor(d[:background_color])
wrap = PyPlotFigWrapper(PyPlot.figure(; figsize = (w,h), facecolor = bgcolor, dpi = 96))
wrap = PyPlotAxisWrapper(nothing, nothing, PyPlot.figure(; figsize = (w,h), facecolor = bgcolor, dpi = DPI, tight_layout = true), [])
if haskey(d, :linetype) && first(d[:linetype]) in _3dTypes # && isa(plt.o, PyPlotFigWrapper)
push!(wrap.kwargs, (:projection, "3d"))
end
end
plt = Plot(wrap, pkg, 0, d, Dict[])
@@ -187,22 +218,26 @@ function plot(pkg::PyPlotPackage; kw...)
end
function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
function _add_series(pkg::PyPlotPackage, plt::Plot; kw...)
d = Dict(kw)
ax = getAxis(plt, d[:axis])
lt = d[:linetype]
if lt in _3dTypes && isempty(plt.o.kwargs)
push!(plt.o.kwargs, (:projection, "3d"))
end
ax = getAxis(plt, d[:axis])
if !(lt in supportedTypes(pkg))
error("linetype $(lt) is unsupported in PyPlot. Choose from: $(supportedTypes(pkg))")
end
color = getPyPlotColor(d[:color], d[:lineopacity])
color = getPyPlotColor(d[:linecolor], d[:linealpha])
if lt == :sticks
d,_ = sticksHack(;d...)
elseif lt == :scatter
elseif lt in (:scatter, :scatter3d)
if d[:markershape] == :none
d[:markershape] = :ellipse
end
@@ -212,82 +247,127 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
linecolor = color
linestyle = getPyPlotLineStyle(lt, d[:linestyle])
for yi in d[:y]
func = ax[lt == :hline ? :axhline : axvline]
func = ax[lt == :hline ? :axhline : :axvline]
func(yi, linewidth=d[:linewidth], color=linecolor, linestyle=linestyle)
end
end
lt = d[:linetype]
# lt = d[:linetype]
extra_kwargs = Dict()
plotfunc = getPyPlotFunction(plt, d[:axis], lt)
# we have different args depending on plot type
if lt in (:hist, :sticks, :bar)
if lt in (:hist, :density, :sticks, :bar)
# NOTE: this is unsupported because it does the wrong thing... it shifts the whole axis
# extra_kwargs[:bottom] = d[:fill]
if lt == :hist
if ishistlike(lt)
extra_kwargs[:bins] = d[:nbins]
extra_kwargs[:normed] = lt == :density
else
extra_kwargs[:linewidth] = (lt == :sticks ? 0.1 : 0.9)
end
elseif lt in (:heatmap, :hexbin)
extra_kwargs[:gridsize] = d[:nbins]
extra_kwargs[:cmap] = getPyPlotColorMap(d[:color])
extra_kwargs[:cmap] = getPyPlotColorMap(d[:linecolor])
elseif lt == :contour
extra_kwargs[:cmap] = getPyPlotColorMap(d[:color])
extra_kwargs[:cmap] = getPyPlotColorMap(d[:linecolor])
extra_kwargs[:linewidths] = d[:linewidth]
extra_kwargs[:linestyles] = getPyPlotLineStyle(lt, d[:linestyle])
# TODO: will need to call contourf to fill in the contours
elseif lt in (:surface, :wireframe)
if lt == :surface
extra_kwargs[:cmap] = getPyPlotColorMap(d[:fillcolor], d[:fillalpha])
end
extra_kwargs[:rstride] = 1
extra_kwargs[:cstride] = 1
extra_kwargs[:linewidth] = d[:linewidth]
extra_kwargs[:edgecolor] = getPyPlotColor(d[:linecolor], d[:linealpha])
else
extra_kwargs[:linestyle] = getPyPlotLineStyle(lt, d[:linestyle])
extra_kwargs[:marker] = getPyPlotMarker(d[:markershape])
if lt == :scatter
extra_kwargs[:s] = d[:markersize]^2
if lt in (:scatter, :scatter3d)
extra_kwargs[:s] = d[:markersize].^2
c = d[:markercolor]
if isa(c, ColorGradient) && d[:z] != nothing
extra_kwargs[:c] = convert(Vector{Float64}, d[:z])
extra_kwargs[:cmap] = getPyPlotColorMap(c, d[:markeropacity])
if isa(c, ColorGradient) && d[:zcolor] != nothing
extra_kwargs[:c] = convert(Vector{Float64}, d[:zcolor])
extra_kwargs[:cmap] = getPyPlotColorMap(c, d[:markeralpha])
else
extra_kwargs[:c] = getPyPlotColor(c, d[:markeropacity])
extra_kwargs[:c] = getPyPlotColor(c, d[:markeralpha])
end
if d[:markeralpha] != nothing
extra_kwargs[:alpha] = d[:markeralpha]
end
extra_kwargs[:edgecolors] = getPyPlotColor(d[:markerstrokecolor], d[:markerstrokealpha])
extra_kwargs[:linewidths] = d[:markerstrokewidth]
else
extra_kwargs[:markersize] = d[:markersize]
extra_kwargs[:markerfacecolor] = getPyPlotColor(d[:markercolor], d[:markeropacity])
extra_kwargs[:markeredgecolor] = getPyPlotColor(plt.initargs[:foreground_color])
extra_kwargs[:markeredgewidth] = d[:linewidth]
extra_kwargs[:markerfacecolor] = getPyPlotColor(d[:markercolor], d[:markeralpha])
extra_kwargs[:markeredgecolor] = getPyPlotColor(d[:markerstrokecolor], d[:markerstrokealpha])
extra_kwargs[:markeredgewidth] = d[:markerstrokewidth]
extra_kwargs[:drawstyle] = getPyPlotStepStyle(lt)
end
end
# if d[:markeralpha] != nothing
# extra_kwargs[:alpha] = d[:markeralpha]
# elseif d[:linealpha] != nothing
# extra_kwargs[:alpha] = d[:linealpha]
# end
# set these for all types
if lt != :contour
extra_kwargs[:color] = color
extra_kwargs[:linewidth] = d[:linewidth]
if !(lt in (:contour,:surface,:wireframe))
if !(lt in (:scatter, :scatter3d))
extra_kwargs[:color] = color
extra_kwargs[:linewidth] = d[:linewidth]
end
extra_kwargs[:label] = d[:label]
extra_kwargs[:zorder] = plt.n
end
# do the plot
d[:serieshandle] = if lt == :hist
d[:serieshandle] = if ishistlike(lt)
plotfunc(d[:y]; extra_kwargs...)[1]
elseif lt == :contour
# NOTE: x/y are backwards in pyplot, so we switch the x and y args (also y is reversed),
# and take the transpose of the surface matrix
x, y = d[:y], d[:x]
surf = d[:surface]'
handle = plotfunc(x, y, surf, d[:nlevels]; extra_kwargs...)
x, y = d[:x], d[:y]
surf = d[:z].surf'
levels = d[:levels]
if isscalar(levels)
extra_args = (levels)
elseif isvector(levels)
extra_args = ()
extra_kwargs[:levels] = levels
else
error("Only numbers and vectors are supported with levels keyword")
end
handle = plotfunc(x, y, surf, extra_args...; extra_kwargs...)
if d[:fillrange] != nothing
handle = ax[:contourf](x, y, surf, d[:nlevels]; cmap = getPyPlotColorMap(d[:fillcolor], d[:fillopacity]))
extra_kwargs[:cmap] = getPyPlotColorMap(d[:fillcolor], d[:fillalpha])
delete!(extra_kwargs, :linewidths)
handle = ax[:contourf](x, y, surf, extra_args...; extra_kwargs...)
end
handle
elseif lt in (:surface,:wireframe)
x, y, z = d[:x], d[:y], Array(d[:z])
if !ismatrix(x) || !ismatrix(y)
x = repmat(x', length(y), 1)
y = repmat(y, 1, length(d[:x]))
z = z'
end
plotfunc(x, y, z; extra_kwargs...)
elseif lt in _3dTypes
plotfunc(d[:x], d[:y], d[:z]; extra_kwargs...)
elseif lt in (:scatter, :heatmap, :hexbin)
plotfunc(d[:x], d[:y]; extra_kwargs...)
else
@@ -297,20 +377,22 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
handleSmooth(plt, ax, d, d[:smooth])
# add the colorbar legend
if plt.initargs[:legend] && haskey(extra_kwargs, :cmap)
if plt.plotargs[:legend] && haskey(extra_kwargs, :cmap)
PyPlot.colorbar(d[:serieshandle])
end
# @show extra_kwargs
# this sets the bg color inside the grid
ax[:set_axis_bgcolor](getPyPlotColor(plt.initargs[:background_color]))
ax[:set_axis_bgcolor](getPyPlotColor(plt.plotargs[:background_color]))
fillrange = d[:fillrange]
if fillrange != nothing && lt != :contour
fillcolor = getPyPlotColor(d[:fillcolor], d[:fillopacity])
fillcolor = getPyPlotColor(d[:fillcolor], d[:fillalpha])
if typeof(fillrange) <: @compat(Union{Real, AVec})
ax[:fill_between](d[:x], fillrange, d[:y], facecolor = fillcolor)
ax[:fill_between](d[:x], fillrange, d[:y], facecolor = fillcolor, zorder = plt.n)
else
ax[:fill_between](d[:x], fillrange..., facecolor = fillcolor)
ax[:fill_between](d[:x], fillrange..., facecolor = fillcolor, zorder = plt.n)
end
end
@@ -334,29 +416,30 @@ function Base.getindex(plt::Plot{PyPlotPackage}, i::Integer)
# mapping[:x], mapping[:y]
end
function Base.setindex!(plt::Plot{PyPlotPackage}, xy::Tuple, i::Integer)
function Base.setindex!{X,Y}(plt::Plot{PyPlotPackage}, xy::Tuple{X,Y}, i::Integer)
series = plt.seriesargs[i][:serieshandle]
x, y = xy
try
series[:set_data](xy...)
series[:set_data](x, y)
catch
series[:set_offsets](hcat(xy...))
series[:set_offsets](hcat(x, y))
end
ax = series[:axes]
if plt.initargs[:xlims] == :auto
if plt.plotargs[:xlims] == :auto
xmin, xmax = ax[:get_xlim]()
ax[:set_xlim](min(xmin, minimum(xy[1])), max(xmax, maximum(xy[1])))
ax[:set_xlim](min(xmin, minimum(x)), max(xmax, maximum(x)))
end
if plt.initargs[:ylims] == :auto
if plt.plotargs[:ylims] == :auto
ymin, ymax = ax[:get_ylim]()
ax[:set_ylim](min(ymin, minimum(xy[2])), max(ymax, maximum(xy[2])))
ax[:set_ylim](min(ymin, minimum(y)), max(ymax, maximum(y)))
end
# getLeftAxis(plt)[:relim]()
# getRightAxis(plt)[:relim]()
# for mapping in getGadflyMappings(plt, i)
# mapping[:x], mapping[:y] = xy
# end
plt
end
function Base.setindex!{X,Y,Z}(plt::Plot{PyPlotPackage}, xyz::Tuple{X,Y,Z}, i::Integer)
warn("setindex not implemented for xyz")
plt
end
@@ -390,7 +473,7 @@ end
usingRightAxis(plt::Plot{PyPlotPackage}) = any(args -> args[:axis] in (:right,:auto), plt.seriesargs)
function updatePlotItems(plt::Plot{PyPlotPackage}, d::Dict)
function _update_plot(plt::Plot{PyPlotPackage}, d::Dict)
figorax = plt.o
ax = getLeftAxis(figorax)
# PyPlot.sca(ax)
@@ -403,7 +486,7 @@ function updatePlotItems(plt::Plot{PyPlotPackage}, d::Dict)
ax[:set_ylabel](d[:ylabel])
end
if usingRightAxis(plt) && get(d, :yrightlabel, "") != ""
rightax = getRightAxis(figorax)
rightax = getRightAxis(figorax)
rightax[:set_ylabel](d[:yrightlabel])
end
@@ -432,22 +515,22 @@ function updatePlotItems(plt::Plot{PyPlotPackage}, d::Dict)
# font sizes
for ax in axes
# haskey(d, :yrightlabel) || continue
# guides
sz = get(d, :guidefont, plt.initargs[:guidefont]).pointsize
sz = get(d, :guidefont, plt.plotargs[:guidefont]).pointsize
ax[:title][:set_fontsize](sz)
ax[:xaxis][:label][:set_fontsize](sz)
ax[:yaxis][:label][:set_fontsize](sz)
# ticks
sz = get(d, :tickfont, plt.initargs[:tickfont]).pointsize
sz = get(d, :tickfont, plt.plotargs[:tickfont]).pointsize
for sym in (:get_xticklabels, :get_yticklabels)
for lab in ax[sym]()
lab[:set_fontsize](sz)
end
end
# grid
if get(d, :grid, false)
ax[:xaxis][:grid](true)
@@ -461,7 +544,7 @@ 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 == :ln && 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)
@@ -488,7 +571,7 @@ function createPyPlotAnnotationObject(plt::Plot{PyPlotPackage}, x, y, val::PlotT
)
end
function addAnnotations{X,Y,V}(plt::Plot{PyPlotPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
function _add_annotations{X,Y,V}(plt::Plot{PyPlotPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
createPyPlotAnnotationObject(plt, ann...)
end
@@ -497,12 +580,12 @@ end
# -----------------------------------------------------------------
# NOTE: pyplot needs to build before
function buildSubplotObject!(subplt::Subplot{PyPlotPackage}, isbefore::Bool)
function _create_subplot(subplt::Subplot{PyPlotPackage}, isbefore::Bool)
l = subplt.layout
w,h = map(px2inch, getinitargs(subplt,1)[:size])
bgcolor = getPyPlotColor(getinitargs(subplt,1)[:background_color])
fig = PyPlot.figure(; figsize = (w,h), facecolor = bgcolor, dpi = 96)
w,h = map(px2inch, getplotargs(subplt,1)[:size])
bgcolor = getPyPlotColor(getplotargs(subplt,1)[:background_color])
fig = PyPlot.figure(; figsize = (w,h), facecolor = bgcolor, dpi = DPI, tight_layout = true)
nr = nrows(l)
for (i,(r,c)) in enumerate(l)
@@ -512,10 +595,11 @@ function buildSubplotObject!(subplt::Subplot{PyPlotPackage}, isbefore::Bool)
fakeidx = (r-1) * nc + c
ax = fig[:add_subplot](nr, nc, fakeidx)
subplt.plts[i].o = PyPlotAxisWrapper(ax, fig)
subplt.plts[i].o = PyPlotAxisWrapper(ax, nothing, fig, [])
end
subplt.o = PyPlotFigWrapper(fig)
# subplt.o = PyPlotFigWrapper(fig, [])
subplt.o = PyPlotAxisWrapper(nothing, nothing, fig, [])
true
end
@@ -528,26 +612,26 @@ function subplot(plts::AVec{Plot{PyPlotPackage}}, layout::SubplotLayout, d::Dict
n = sum([plt.n for plt in plts])
pkg = PyPlotPackage()
newplts = Plot{PyPlotPackage}[plot(pkg; subplot=true, plt.initargs...) for plt in plts]
newplts = Plot{PyPlotPackage}[_create_plot(pkg; subplot=true, plt.plotargs...) for plt in plts]
subplt = Subplot(nothing, newplts, PyPlotPackage(), p, n, layout, d, true, false, false, (r,c) -> (nothing,nothing))
preprocessSubplot(subplt, d)
buildSubplotObject!(subplt, true)
_preprocess_subplot(subplt, d)
_create_subplot(subplt, true)
for (i,plt) in enumerate(plts)
for seriesargs in plt.seriesargs
_plot_from_subplot!(newplts[i]; seriesargs...)
_add_series_subplot(newplts[i]; seriesargs...)
end
end
postprocessSubplot(subplt, d)
_postprocess_subplot(subplt, d)
subplt
end
function handleLinkInner(plt::Plot{PyPlotPackage}, isx::Bool)
function _remove_axis(plt::Plot{PyPlotPackage}, isx::Bool)
if isx
plot!(plt, xticks=zeros(0), xlabel="")
else
@@ -555,25 +639,26 @@ function handleLinkInner(plt::Plot{PyPlotPackage}, isx::Bool)
end
end
function expandLimits!(lims, plt::Plot{PyPlotPackage}, isx::Bool)
function _expand_limits(lims, plt::Plot{PyPlotPackage}, isx::Bool)
pltlims = plt.o.ax[isx ? :get_xbound : :get_ybound]()
expandLimits!(lims, pltlims)
_expand_limits(lims, pltlims)
end
# -----------------------------------------------------------------
# function addPyPlotLegend(plt::Plot)
function addPyPlotLegend(plt::Plot, ax)
if plt.initargs[:legend]
if plt.plotargs[:legend]
# gotta do this to ensure both axes are included
args = filter(x -> !(x[:linetype] in (:hist,:hexbin,:heatmap,:hline,:vline,:contour)), plt.seriesargs)
args = filter(x -> !(x[:linetype] in (:hist,:density,:hexbin,:heatmap,:hline,:vline,:contour, :surface, :wireframe, :path3d, :scatter3d)), plt.seriesargs)
if length(args) > 0
ax[:legend]([d[:serieshandle] for d in args],
leg = ax[:legend]([d[:serieshandle] for d in args],
[d[:label] for d in args],
loc="best",
fontsize = plt.initargs[:legendfont].pointsize
fontsize = plt.plotargs[:legendfont].pointsize
# framealpha = 0.6
)
leg[:set_zorder](1000)
end
end
end
@@ -581,7 +666,7 @@ end
function finalizePlot(plt::Plot{PyPlotPackage})
ax = getLeftAxis(plt)
addPyPlotLegend(plt, ax)
updateAxisColors(ax, getPyPlotColor(plt.initargs[:foreground_color]))
updateAxisColors(ax, getPyPlotColor(plt.plotargs[:foreground_color]))
PyPlot.draw()
end
@@ -590,8 +675,9 @@ function finalizePlot(subplt::Subplot{PyPlotPackage})
for (i,plt) in enumerate(subplt.plts)
ax = getLeftAxis(plt)
addPyPlotLegend(plt, ax)
updateAxisColors(ax, getPyPlotColor(plt.initargs[:foreground_color]))
updateAxisColors(ax, getPyPlotColor(plt.plotargs[:foreground_color]))
end
# fig[:tight_layout]()
PyPlot.draw()
end
@@ -658,10 +744,11 @@ for (mime, fmt) in _pyplot_mimeformats
fig = getfig(plt.o)
fig.o["canvas"][:print_figure](io,
format=$fmt,
bbox_inches="tight",
# bbox_inches = "tight",
# figsize = map(px2inch, plt.plotargs[:size]),
facecolor = fig.o["get_facecolor"](),
edgecolor = "none"
# edgecolor = fig.o["get_edgecolor"]()
edgecolor = "none",
dpi = DPI
)
end
end
+11 -19
View File
@@ -70,7 +70,7 @@ function adjustQwtKeywords(plt::Plot{QwtPackage}, iscreating::Bool; kw...)
d
end
function plot(pkg::QwtPackage; kw...)
function _create_plot(pkg::QwtPackage; kw...)
d = Dict(kw)
fixcolors(d)
dumpdict(d,"\n\n!!! plot")
@@ -79,7 +79,7 @@ function plot(pkg::QwtPackage; kw...)
plt
end
function plot!(::QwtPackage, plt::Plot; kw...)
function _add_series(::QwtPackage, plt::Plot; kw...)
d = adjustQwtKeywords(plt, false; kw...)
fixcolors(d)
dumpdict(d,"\n\n!!! plot!")
@@ -131,7 +131,7 @@ function updateLimsAndTicks(plt::Plot{QwtPackage}, d::Dict, isx::Bool)
end
function updatePlotItems(plt::Plot{QwtPackage}, d::Dict)
function _update_plot(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])
@@ -139,7 +139,7 @@ function updatePlotItems(plt::Plot{QwtPackage}, d::Dict)
updateLimsAndTicks(plt, d, false)
end
function updatePositionAndSize(plt::PlottingObject{QwtPackage}, d::Dict)
function _update_plot_pos_size(plt::PlottingObject{QwtPackage}, d::Dict)
haskey(d, :size) && Qwt.resizewidget(plt.o, d[:size]...)
haskey(d, :pos) && Qwt.movewidget(plt.o, d[:pos]...)
end
@@ -154,7 +154,7 @@ function addLineMarker(plt::Plot{QwtPackage}, d::Dict)
ishorizontal = (d[:linetype] == :hline)
marker[:setLineStyle](ishorizontal ? 1 : 2)
marker[ishorizontal ? :setYValue : :setXValue](yi)
qcolor = Qwt.convertRGBToQColor(getColor(d[:color]))
qcolor = Qwt.convertRGBToQColor(getColor(d[:linecolor]))
linestyle = plt.o.widget[:getLineStyle](string(d[:linestyle]))
marker[:setLinePen](Qwt.QT.QPen(qcolor, d[:linewidth], linestyle))
marker[:attach](plt.o.widget)
@@ -182,7 +182,7 @@ function createQwtAnnotation(plt::Plot, x, y, val::@compat(AbstractString))
marker[:attach](plt.o.widget)
end
function addAnnotations{X,Y,V}(plt::Plot{QwtPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
function _add_annotations{X,Y,V}(plt::Plot{QwtPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
createQwtAnnotation(plt, ann...)
end
@@ -211,7 +211,7 @@ end
# -------------------------------
# create the underlying object (each backend will do this differently)
function buildSubplotObject!(subplt::Subplot{QwtPackage}, isbefore::Bool)
function _create_subplot(subplt::Subplot{QwtPackage}, isbefore::Bool)
isbefore && return false
i = 0
rows = Any[]
@@ -228,23 +228,19 @@ function buildSubplotObject!(subplt::Subplot{QwtPackage}, isbefore::Bool)
# i += rowcnt
# end
subplt.o = Qwt.vsplitter(rows...)
# Qwt.resizewidget(subplt.o, getinitargs(subplt,1)[:size]...)
# Qwt.resizewidget(subplt.o, getplotargs(subplt,1)[:size]...)
# Qwt.moveToLastScreen(subplt.o) # hack so it goes to my center monitor... sorry
true
end
function handleLinkInner(plt::Plot{QwtPackage}, isx::Bool)
warn("handleLinkInner isn't implemented for qwt")
end
function expandLimits!(lims, plt::Plot{QwtPackage}, isx::Bool)
function _expand_limits(lims, plt::Plot{QwtPackage}, isx::Bool)
for series in plt.o.lines
expandLimits!(lims, isx ? series.x : series.y)
_expand_limits(lims, isx ? series.x : series.y)
end
end
function handleLinkInner(plt::Plot{QwtPackage}, isx::Bool)
function _remove_axis(plt::Plot{QwtPackage}, isx::Bool)
end
@@ -274,10 +270,6 @@ function Base.display(::PlotsDisplay, subplt::Subplot{QwtPackage})
for plt in subplt.plts
Qwt.refresh(plt.o)
end
# iargs = getinitargs(subplt,1)
# # iargs = subplt.initargs
# Qwt.resizewidget(subplt.o, iargs[:size]...)
# Qwt.movewidget(subplt.o, iargs[:pos]...)
Qwt.showwidget(subplt.o)
end
+266 -20
View File
@@ -1,13 +1,33 @@
supportedAxes(::PlottingPackage) = [:left]
supportedTypes(::PlottingPackage) = []
supportedStyles(::PlottingPackage) = [:solid]
supportedMarkers(::PlottingPackage) = [:none]
supportedScales(::PlottingPackage) = [:identity]
subplotSupported(::PlottingPackage) = false
stringsSupported(::PlottingPackage) = false
supportedAxes() = supportedAxes(backend())
supportedTypes() = supportedTypes(backend())
supportedStyles() = supportedStyles(backend())
supportedMarkers() = supportedMarkers(backend())
supportedScales() = supportedScales(backend())
subplotSupported() = subplotSupported(backend())
stringsSupported() = stringsSupported(backend())
# --------------------------------------------------------------------------------------
supportedArgs(::GadflyPackage) = [
:annotation,
# :axis,
:background_color,
:color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
:fillopacity,
:fillalpha,
:foreground_color,
:group,
:label,
@@ -16,11 +36,14 @@ supportedArgs(::GadflyPackage) = [
:linestyle,
:linetype,
:linewidth,
:lineopacity,
:linealpha,
:markershape,
:markercolor,
:markersize,
:markeropacity,
:markeralpha,
:markerstrokewidth,
:markerstrokecolor,
# :markerstrokestyle,
:n,
:nbins,
:nc,
@@ -45,18 +68,22 @@ supportedArgs(::GadflyPackage) = [
:xflip,
:yflip,
:z,
:zcolor,
:tickfont,
:guidefont,
:legendfont,
:grid,
:surface,
:nlevels,
# :surface,
:levels,
]
supportedAxes(::GadflyPackage) = [:auto, :left]
supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour]
supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppre, :steppost, :sticks,
:scatter, :heatmap, :hexbin, :hist, :bar,
:hline, :vline, :contour]
supportedStyles(::GadflyPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::GadflyPackage) = vcat(_allMarkers, Shape)
supportedScales(::GadflyPackage) = [:identity, :log, :log2, :log10, :asinh, :sqrt]
supportedScales(::GadflyPackage) = [:identity, :ln, :log2, :log10, :asinh, :sqrt]
subplotSupported(::GadflyPackage) = true
# --------------------------------------------------------------------------------------
@@ -68,6 +95,7 @@ supportedTypes(::ImmersePackage) = supportedTypes(GadflyPackage())
supportedStyles(::ImmersePackage) = supportedStyles(GadflyPackage())
supportedMarkers(::ImmersePackage) = supportedMarkers(GadflyPackage())
supportedScales(::ImmersePackage) = supportedScales(GadflyPackage())
subplotSupported(::ImmersePackage) = true
# --------------------------------------------------------------------------------------
@@ -77,7 +105,7 @@ supportedArgs(::PyPlotPackage) = [
:annotation,
:axis,
:background_color,
:color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
@@ -92,6 +120,9 @@ supportedArgs(::PyPlotPackage) = [
:markershape,
:markercolor,
:markersize,
:markerstrokewidth,
:markerstrokecolor,
# :markerstrokestyle,
:n,
:nbins,
:nc,
@@ -117,22 +148,25 @@ supportedArgs(::PyPlotPackage) = [
:xflip,
:yflip,
:z,
:zcolor, # only supported for scatter/scatter3d
:tickfont,
:guidefont,
:legendfont,
:grid,
:surface,
:nlevels,
:fillopacity,
:lineopacity,
:markeropacity,
# :surface,
:levels,
:fillalpha,
:linealpha,
:markeralpha,
]
supportedAxes(::PyPlotPackage) = _allAxes
supportedTypes(::PyPlotPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour]
supportedTypes(::PyPlotPackage) = [:none, :line, :path, :steppre, :steppost, #:sticks,
:scatter, :heatmap, :hexbin, :hist, :density, :bar,
:hline, :vline, :contour, :path3d, :scatter3d, :surface, :wireframe]
supportedStyles(::PyPlotPackage) = [:auto, :solid, :dash, :dot, :dashdot]
# supportedMarkers(::PyPlotPackage) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :hexagon]
supportedMarkers(::PyPlotPackage) = vcat(_allMarkers, Shape)
supportedScales(::PyPlotPackage) = [:identity, :log, :log2, :log10]
supportedScales(::PyPlotPackage) = [:identity, :ln, :log2, :log10]
subplotSupported(::PyPlotPackage) = true
@@ -145,7 +179,7 @@ supportedArgs(::QwtPackage) = [
# :args,
:axis,
:background_color,
:color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
@@ -162,6 +196,9 @@ supportedArgs(::QwtPackage) = [
:markershape,
:markercolor,
:markersize,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
:n,
:nbins,
:nc,
@@ -191,6 +228,7 @@ supportedArgs(::QwtPackage) = [
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, :star5, :star8, :hexagon]
supportedScales(::QwtPackage) = [:identity, :log10]
subplotSupported(::QwtPackage) = true
# --------------------------------------------------------------------------------------
@@ -201,7 +239,7 @@ supportedArgs(::UnicodePlotsPackage) = [
# :args,
# :axis,
# :background_color,
# :color,
# :linecolor,
# :fill,
# :foreground_color,
:group,
@@ -216,6 +254,9 @@ supportedArgs(::UnicodePlotsPackage) = [
:markershape,
# :markercolor,
# :markersize,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
:nbins,
# :nc,
@@ -247,6 +288,7 @@ supportedTypes(::UnicodePlotsPackage) = [:none, :line, :path, :steppost, :sticks
supportedStyles(::UnicodePlotsPackage) = [:auto, :solid]
supportedMarkers(::UnicodePlotsPackage) = [:none, :auto, :ellipse]
supportedScales(::UnicodePlotsPackage) = [:identity]
subplotSupported(::UnicodePlotsPackage) = true
@@ -259,7 +301,7 @@ supportedArgs(::WinstonPackage) = [
# :args,
# :axis,
# :background_color,
:color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
@@ -276,6 +318,9 @@ supportedArgs(::WinstonPackage) = [
:markershape,
:markercolor,
:markersize,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
:nbins,
# :nc,
@@ -310,4 +355,205 @@ supportedScales(::WinstonPackage) = [:identity, :log10]
subplotSupported(::WinstonPackage) = false
# --------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------
supportedArgs(::BokehPackage) = [
# :annotation,
# :axis,
# :background_color,
:linecolor,
# :color_palette,
# :fillrange,
# :fillcolor,
# :fillalpha,
# :foreground_color,
:group,
# :label,
# :layout,
# :legend,
:linestyle,
:linetype,
:linewidth,
# :linealpha,
:markershape,
:markercolor,
:markersize,
# :markeralpha,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
# :nbins,
# :nc,
# :nr,
# :pos,
# :smooth,
# :show,
:size,
:title,
# :windowtitle,
:x,
# :xlabel,
# :xlims,
# :xticks,
:y,
# :ylabel,
# :ylims,
# :yrightlabel,
# :yticks,
# :xscale,
# :yscale,
# :xflip,
# :yflip,
# :z,
# :tickfont,
# :guidefont,
# :legendfont,
# :grid,
# :surface,
# :levels,
]
supportedAxes(::BokehPackage) = [:auto, :left]
supportedTypes(::BokehPackage) = [:none, :path, :scatter] #,:steppre, :steppost, :sticks, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour]
supportedStyles(::BokehPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::BokehPackage) = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5] #vcat(_allMarkers, Shape)
supportedScales(::BokehPackage) = [:identity, :ln] #, :ln, :log2, :log10, :asinh, :sqrt]
subplotSupported(::BokehPackage) = false
# --------------------------------------------------------------------------------------
supportedArgs(::PlotlyPackage) = [
:annotation,
# :axis,
:background_color,
:color_palette,
:fillrange,
:fillcolor,
:fillalpha,
:foreground_color,
:group,
:label,
:layout,
:legend,
:linecolor,
:linestyle,
:linetype,
:linewidth,
:linealpha,
:markershape,
:markercolor,
:markersize,
:markeralpha,
:markerstrokewidth,
:markerstrokecolor,
:markerstrokestyle,
:n,
:nbins,
:nc,
:nr,
# :pos,
# :smooth,
:show,
:size,
:title,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
:yticks,
:xscale,
:yscale,
:xflip,
:yflip,
:z,
:zcolor,
:tickfont,
:guidefont,
:legendfont,
:grid,
:levels,
]
supportedAxes(::PlotlyPackage) = [:auto, :left]
supportedTypes(::PlotlyPackage) = [:none, :line, :path, :scatter, :steppre, :steppost,
:heatmap, :hist, :density, :bar, :contour, :surface, :path3d, :scatter3d,
:pie] #,, :sticks, :hexbin, :hline, :vline]
supportedStyles(::PlotlyPackage) = [:auto, :solid, :dash, :dot, :dashdot]
supportedMarkers(::PlotlyPackage) = [:none, :auto, :ellipse, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross,
:pentagon, :hexagon, :octagon, :vline, :hline] #vcat(_allMarkers, Shape)
supportedScales(::PlotlyPackage) = [:identity, :log10] #, :ln, :log2, :log10, :asinh, :sqrt]
subplotSupported(::PlotlyPackage) = true
stringsSupported(::PlotlyPackage) = true
# --------------------------------------------------------------------------------------
supportedArgs(::GLVisualizePackage) = [
# :annotation,
# :axis,
# :background_color,
# :color_palette,
# :fillrange,
# :fillcolor,
# :fillalpha,
# :foreground_color,
# :group,
# :label,
# :layout,
# :legend,
# :linecolor,
# :linestyle,
# :linetype,
# :linewidth,
# :linealpha,
# :markershape,
# :markercolor,
# :markersize,
# :markeralpha,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
# :nbins,
# :nc,
# :nr,
# :pos,
# :smooth,
# :show,
# :size,
# :title,
# :windowtitle,
# :x,
# :xlabel,
# :xlims,
# :xticks,
# :y,
# :ylabel,
# :ylims,
# :yrightlabel,
# :yticks,
# :xscale,
# :yscale,
# :xflip,
# :yflip,
# :z,
# :tickfont,
# :guidefont,
# :legendfont,
# :grid,
# :surface
# :levels,
]
supportedAxes(::GLVisualizePackage) = [:auto, :left]
supportedTypes(::GLVisualizePackage) = [:contour] #, :path, :scatter ,:steppre, :steppost, :sticks, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour]
supportedStyles(::GLVisualizePackage) = [:auto, :solid] #, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::GLVisualizePackage) = [:none, :auto, :ellipse] #, :rect, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5] #vcat(_allMarkers, Shape)
supportedScales(::GLVisualizePackage) = [:identity] #, :log, :log2, :log10, :asinh, :sqrt]
subplotSupported(::GLVisualizePackage) = false
+43 -65
View File
@@ -5,90 +5,68 @@
# ---------------------------------------------------------------------------
# supportedArgs(::[PkgName]Package) = _allArgs
supportedArgs(::[PkgName]Package) = [
:annotation,
# :args,
:axis,
:background_color,
:color,
:fillrange,
:fillcolor,
:foreground_color,
:group,
# :heatmap_c,
# :kwargs,
:label,
:layout,
:legend,
:linestyle,
:linetype,
:linewidth,
:markershape,
:markercolor,
:markersize,
:n,
:nbins,
:nc,
:nr,
# :pos,
:smooth,
# :ribbon,
:show,
:size,
:title,
:windowtitle,
:x,
:xlabel,
:xlims,
:xticks,
:y,
:ylabel,
:ylims,
# :yrightlabel,
:yticks,
# :xscale,
# :yscale,
# :xflip,
# :yflip,
# :z,
]
supportedAxes(::[PkgName]Package) = _allAxes
supportedTypes(::[PkgName]Package) = _allTypes
supportedStyles(::[PkgName]Package) = _allStyles
supportedMarkers(::[PkgName]Package) = _allMarkers
supportedScales(::[PkgName]Package) = _allScales
subplotSupported(::[PkgName]Package) = false
# ---------------------------------------------------------------------------
function plot(pkg::[PkgName]Package; kw...)
function _create_plot(pkg::[PkgName]Package; kw...)
d = Dict(kw)
# TODO: create the window/canvas/context that is the plot within the backend (call it `o`)
# TODO: initialize the plot... title, xlabel, bgcolor, etc
Plot(o, pkg, 0, d, Dict[])
Plot(nothing, pkg, 0, d, Dict[])
end
function plot!(::[PkgName]Package, plt::Plot; kw...)
function _add_series(::[PkgName]Package, plt::Plot; kw...)
d = Dict(kw)
# TODO: add one series to the underlying package
push!(plt.seriesargs, d)
plt
end
# ----------------------------------------------------------------
# TODO: override this to update plot items (title, xlabel, etc) after creation
function updatePlotItems(plt::Plot{[PkgName]Package}, d::Dict)
function _add_annotations{X,Y,V}(plt::Plot{[PkgName]Package}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
# TODO: add the annotation to the plot
end
end
# ----------------------------------------------------------------
function buildSubplotObject!(subplt::Subplot{[PkgName]Package})
function _before_update_plot(plt::Plot{[PkgName]Package})
end
# TODO: override this to update plot items (title, xlabel, etc) after creation
function _update_plot(plt::Plot{[PkgName]Package}, d::Dict)
end
function _update_plot_pos_size(plt::PlottingObject{[PkgName]Package}, d::Dict)
end
# ----------------------------------------------------------------
# accessors for x/y data
function Base.getindex(plt::Plot{[PkgName]Package}, i::Int)
series = plt.o.lines[i]
series.x, series.y
end
function Base.setindex!(plt::Plot{[PkgName]Package}, xy::Tuple, i::Integer)
series = plt.o.lines[i]
series.x, series.y = xy
plt
end
# ----------------------------------------------------------------
function _create_subplot(subplt::Subplot{[PkgName]Package}, isbefore::Bool)
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
end
function _expand_limits(lims, plt::Plot{[PkgName]Package}, isx::Bool)
# TODO: call expand limits for each plot data
end
function _remove_axis(plt::Plot{[PkgName]Package}, isx::Bool)
# TODO: if plot is inner subplot, might need to remove ticks or axis labels
end
# ----------------------------------------------------------------
function Base.writemime(io::IO, ::MIME"image/png", plt::PlottingObject{[PkgName]Package})
+12 -12
View File
@@ -9,13 +9,13 @@ function rebuildUnicodePlot!(plt::Plot)
# figure out the plotting area xlim = [xmin, xmax] and ylim = [ymin, ymax]
sargs = plt.seriesargs
iargs = plt.initargs
iargs = plt.plotargs
# get the x/y limits
if get(iargs, :xlims, :auto) == :auto
xlim = [Inf, -Inf]
for d in sargs
expandLimits!(xlim, d[:x])
_expand_limits(xlim, d[:x])
end
else
xmin, xmax = iargs[:xlims]
@@ -25,7 +25,7 @@ function rebuildUnicodePlot!(plt::Plot)
if get(iargs, :ylims, :auto) == :auto
ylim = [Inf, -Inf]
for d in sargs
expandLimits!(ylim, d[:y])
_expand_limits(ylim, d[:y])
end
else
ymin, ymax = iargs[:ylims]
@@ -39,7 +39,7 @@ function rebuildUnicodePlot!(plt::Plot)
# create a plot window with xlim/ylim set, but the X/Y vectors are outside the bounds
width, height = iargs[:size]
o = UnicodePlots.createPlotWindow(x, y; width = width,
o = UnicodePlots.Plot(x, y; width = width,
height = height,
title = iargs[:title],
# labels = iargs[:legend],
@@ -97,7 +97,7 @@ function addUnicodeSeries!(o, d::Dict, addlegend::Bool, xlim, ylim)
label = addlegend ? d[:label] : ""
# if we happen to pass in allowed color symbols, great... otherwise let UnicodePlots decide
color = d[:color] in UnicodePlots.autoColors ? d[:color] : :auto
color = d[:linecolor] in UnicodePlots.autoColors ? d[:linecolor] : :auto
# add the series
func(o, x, y; color = color, name = label, style = stepstyle)
@@ -112,18 +112,18 @@ end
# -------------------------------
function plot(pkg::UnicodePlotsPackage; kw...)
function _create_plot(pkg::UnicodePlotsPackage; kw...)
plt = Plot(nothing, pkg, 0, Dict(kw), Dict[])
# do we want to give a new default size?
if !haskey(plt.initargs, :size) || plt.initargs[:size] == _plotDefaults[:size]
plt.initargs[:size] = (60,20)
if !haskey(plt.plotargs, :size) || plt.plotargs[:size] == _plotDefaults[:size]
plt.plotargs[:size] = (60,20)
end
plt
end
function plot!(::UnicodePlotsPackage, plt::Plot; kw...)
function _add_series(::UnicodePlotsPackage, plt::Plot; kw...)
d = Dict(kw)
if d[:linetype] in (:sticks, :bar)
d = barHack(; d...)
@@ -135,10 +135,10 @@ function plot!(::UnicodePlotsPackage, plt::Plot; kw...)
end
function updatePlotItems(plt::Plot{UnicodePlotsPackage}, d::Dict)
function _update_plot(plt::Plot{UnicodePlotsPackage}, d::Dict)
for k in (:title, :xlabel, :ylabel, :xlims, :ylims)
if haskey(d, k)
plt.initargs[k] = d[k]
plt.plotargs[k] = d[k]
end
end
end
@@ -175,7 +175,7 @@ end
# we don't do very much for subplots... just stack them vertically
function buildSubplotObject!(subplt::Subplot{UnicodePlotsPackage}, isbefore::Bool)
function _create_subplot(subplt::Subplot{UnicodePlotsPackage}, isbefore::Bool)
isbefore && return false
true
end
+38
View File
@@ -0,0 +1,38 @@
# NOTE: backend should implement `html_body` and `html_head`
# CREDIT: parts of this implementation were inspired by @joshday's PlotlyLocal.jl
function standalone_html(plt::PlottingObject; title::AbstractString = get(plt.plotargs, :window_title, "Plots.jl"))
"""
<!DOCTYPE html>
<html>
<head>
<title>$title</title>
$(html_head(plt))
</head>
<body>
$(html_body(plt))
</body>
</html>
"""
end
function open_browser_window(filename::AbstractString)
@osx_only return run(`open $(filename)`)
@linux_only return run(`xdg-open $(filename)`)
@windows_only return run(`$(ENV["COMSPEC"]) /c start $(filename)`)
warn("Unknown OS... cannot open browser window.")
end
function standalone_html_window(plt::PlottingObject; kw...)
html = standalone_html(plt; kw...)
# println(html)
filename = string(tempname(), ".html")
output = open(filename, "w")
write(output, html)
close(output)
open_browser_window(filename)
end
+10 -10
View File
@@ -25,14 +25,14 @@
:star5 => "asterisk"
)
function preparePlotUpdate(plt::Plot{WinstonPackage})
function _before_add_series(plt::Plot{WinstonPackage})
Winston.ghf(plt.o)
end
# ---------------------------------------------------------------------------
function plot(pkg::WinstonPackage; kw...)
function _create_plot(pkg::WinstonPackage; kw...)
d = Dict(kw)
wplt = Winston.FramedPlot(title = d[:title], xlabel = d[:xlabel], ylabel = d[:ylabel])
@@ -56,7 +56,7 @@ function getWinstonItems(plt::Plot)
window, canvas, wplt
end
function plot!(::WinstonPackage, plt::Plot; kw...)
function _add_series(::WinstonPackage, plt::Plot; kw...)
d = Dict(kw)
window, canvas, wplt = getWinstonItems(plt)
@@ -68,7 +68,7 @@ function plot!(::WinstonPackage, plt::Plot; kw...)
e = Dict()
e[:color] = getColor(d[:color])
e[:color] = getColor(d[:linecolor])
e[:linewidth] = d[:linewidth]
e[:kind] = winston_linestyle[d[:linestyle]]
e[:symbolkind] = winston_marker[d[:markershape]]
@@ -157,7 +157,7 @@ end
:yscale => :ylog,
)
function updatePlotItems(plt::Plot{WinstonPackage}, d::Dict)
function _update_plot(plt::Plot{WinstonPackage}, d::Dict)
window, canvas, wplt = getWinstonItems(plt)
for k in (:xlabel, :ylabel, :title, :xlims, :ylims)
if haskey(d, k)
@@ -182,7 +182,7 @@ function createWinstonAnnotationObject(plt::Plot{WinstonPackage}, x, y, val::@co
Winston.text(x, y, val)
end
function addAnnotations{X,Y,V}(plt::Plot{WinstonPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
function _add_annotations{X,Y,V}(plt::Plot{WinstonPackage}, anns::AVec{@compat(Tuple{X,Y,V})})
for ann in anns
createWinstonAnnotationObject(plt, ann...)
end
@@ -191,14 +191,14 @@ end
# ----------------------------------------------------------------
function buildSubplotObject!(subplt::Subplot{WinstonPackage}, isbefore::Bool)
function _create_subplot(subplt::Subplot{WinstonPackage}, isbefore::Bool)
# TODO: build the underlying Subplot object. this is where you might layout the panes within a GUI window, for example
end
# ----------------------------------------------------------------
function addWinstonLegend(plt::Plot, wplt)
if plt.initargs[:legend]
if plt.plotargs[:legend]
Winston.legend(wplt, [sd[:label] for sd in plt.seriesargs])
end
end
@@ -219,9 +219,9 @@ function Base.display(::PlotsDisplay, plt::Plot{WinstonPackage})
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]
w,h = plt.plotargs[:size]
canvas = Gtk.GtkCanvasLeaf()
window = Gtk.GtkWindowLeaf(canvas, plt.initargs[:windowtitle], w, h)
window = Gtk.GtkWindowLeaf(canvas, plt.plotargs[:windowtitle], w, h)
plt.o = (window, canvas, wplt)
end
+44 -87
View File
@@ -1,88 +1,4 @@
# note: I found this list of hex values in a comment by Tatarize here: http://stackoverflow.com/a/12224359
const _masterColorList = [
0xFFFFFF,
0x000000,
0x0000FF,
0x00FF00,
0xFF0000,
0x01FFFE,
0xFFA6FE,
0xFFDB66,
0x006401,
0x010067,
0x95003A,
0x007DB5,
0xFF00F6,
0xFFEEE8,
0x774D00,
0x90FB92,
0x0076FF,
0xD5FF00,
0xFF937E,
0x6A826C,
0xFF029D,
0xFE8900,
0x7A4782,
0x7E2DD2,
0x85A900,
0xFF0056,
0xA42400,
0x00AE7E,
0x683D3B,
0xBDC6FF,
0x263400,
0xBDD393,
0x00B917,
0x9E008E,
0x001544,
0xC28C9F,
0xFF74A3,
0x01D0FF,
0x004754,
0xE56FFE,
0x788231,
0x0E4CA1,
0x91D0CB,
0xBE9970,
0x968AE8,
0xBB8800,
0x43002C,
0xDEFF74,
0x00FFC6,
0xFFE502,
0x620E00,
0x008F9C,
0x98FF52,
0x7544B1,
0xB500FF,
0x00FF78,
0xFF6E41,
0x005F39,
0x6B6882,
0x5FAD4E,
0xA75740,
0xA5FFD2,
0xFFB167,
0x009BFF,
0xE85EBE,
]
function darken(c, v=0.1)
rgba = convert(RGBA, c)
r = max(0, min(rgba.r - v, 1))
g = max(0, min(rgba.g - v, 1))
b = max(0, min(rgba.b - v, 1))
RGBA(r,g,b,rgba.alpha)
end
function lighten(c, v=0.3)
darken(c, -v)
end
# --------------------------------------------------------------
abstract ColorScheme
getColor(scheme::ColorScheme) = getColor(scheme, 1)
@@ -119,6 +35,19 @@ getColor(c) = convertColor(c)
# --------------------------------------------------------------
function darken(c, v=0.1)
rgba = convert(RGBA, c)
r = max(0, min(rgba.r - v, 1))
g = max(0, min(rgba.g - v, 1))
b = max(0, min(rgba.b - v, 1))
RGBA(r,g,b,rgba.alpha)
end
function lighten(c, v=0.3)
darken(c, -v)
end
# --------------------------------------------------------------
const _rainbowColors = [colorant"blue", colorant"purple", colorant"green", colorant"orange", colorant"red"]
const _testColors = [colorant"darkblue", colorant"blueviolet", colorant"darkcyan",colorant"green",
darken(colorant"yellow",0.3), colorant"orange", darken(colorant"red",0.2)]
@@ -286,6 +215,16 @@ function convertHexToRGB(h::Unsigned)
RGB([(x & mask) / 0xFF for x in (h >> 16, h >> 8, h)]...)
end
# note: I found this list of hex values in a comment by Tatarize here: http://stackoverflow.com/a/12224359
const _masterColorList = [
0xFFFFFF, 0x000000, 0x0000FF, 0x00FF00, 0xFF0000, 0x01FFFE, 0xFFA6FE, 0xFFDB66, 0x006401, 0x010067,
0x95003A, 0x007DB5, 0xFF00F6, 0xFFEEE8, 0x774D00, 0x90FB92, 0x0076FF, 0xD5FF00, 0xFF937E, 0x6A826C,
0xFF029D, 0xFE8900, 0x7A4782, 0x7E2DD2, 0x85A900, 0xFF0056, 0xA42400, 0x00AE7E, 0x683D3B, 0xBDC6FF,
0x263400, 0xBDD393, 0x00B917, 0x9E008E, 0x001544, 0xC28C9F, 0xFF74A3, 0x01D0FF, 0x004754, 0xE56FFE,
0x788231, 0x0E4CA1, 0x91D0CB, 0xBE9970, 0x968AE8, 0xBB8800, 0x43002C, 0xDEFF74, 0x00FFC6, 0xFFE502,
0x620E00, 0x008F9C, 0x98FF52, 0x7544B1, 0xB500FF, 0x00FF78, 0xFF6E41, 0x005F39, 0x6B6882, 0x5FAD4E,
0xA75740, 0xA5FFD2, 0xFFB167, 0x009BFF, 0xE85EBE
]
const _allColors = map(convertHexToRGB, _masterColorList)
const _darkColors = filter(isdark, _allColors)
const _lightColors = filter(islight, _allColors)
@@ -347,6 +286,10 @@ function get_color_palette(palette, bgcolor::@compat(Union{Colorant,ColorWrapper
RGBA[getColorZ(grad, z) for z in zrng]
end
function get_color_palette(palette::Vector{RGBA}, bgcolor::@compat(Union{Colorant,ColorWrapper}), numcolors::Integer)
palette
end
# ----------------------------------------------------------------------------------
@@ -382,7 +325,21 @@ end
# ----------------------------------------------------------------------------------
# TODO: try to use the algorithms from https://github.com/timothyrenner/ColorBrewer.jl
make255(x) = round(Int, 255 * x)
function webcolor(c::Color)
@sprintf("rgb(%d, %d, %d)", [make255(f(c)) for f in [red,green,blue]]...)
end
function webcolor(c::TransparentColor)
@sprintf("rgba(%d, %d, %d, %1.3f)", [make255(f(c)) for f in [red,green,blue]]..., alpha(c))
end
webcolor(cs::ColorScheme) = webcolor(getColor(cs))
webcolor(c) = webcolor(convertColor(c))
webcolor(c, α) = webcolor(convertColor(getColor(c), α))
# ----------------------------------------------------------------------------------
# TODO: allow the setting of the algorithm, either by passing a symbol (:colordiff, :fixed, etc) or a function?
# function getBackgroundRGBColor(c, d::Dict)
@@ -415,10 +372,10 @@ function handlePlotColors(::PlottingPackage, d::Dict)
end
# converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically
function getSeriesRGBColor(c, initargs::Dict, n::Int)
function getSeriesRGBColor(c, plotargs::Dict, n::Int)
if c == :auto
c = autopick(initargs[:color_palette], n)
c = autopick(plotargs[:color_palette], n)
end
# c should now be a subtype of ColorScheme
+243
View File
@@ -0,0 +1,243 @@
immutable Shape
vertices::AVec
end
"get an array of tuples of points on a circle with radius `r`"
function partialcircle(start_θ, end_θ, n = 20, r=1)
@compat(Tuple{Float64,Float64})[(r*cos(u),r*sin(u)) for u in linspace(start_θ, end_θ, n)]
end
"interleave 2 vectors into each other (like a zipper's teeth)"
function weave(x,y; ordering = Vector[x,y])
ret = eltype(x)[]
done = false
while !done
for o in ordering
try
push!(ret, shift!(o))
end
# try
# push!(ret, shift!(y))
# end
end
done = isempty(x) && isempty(y)
end
ret
end
"create a star by weaving together points from an outer and inner circle. `n` is the number of arms"
function makestar(n; offset = -0.5, radius = 1.0)
z1 = offset * π
z2 = z1 + π / (n)
outercircle = partialcircle(z1, z1 + 2π, n+1, radius)
innercircle = partialcircle(z2, z2 + 2π, n+1, 0.4radius)
Shape(weave(outercircle, innercircle)[1:end-2])
end
"create a shape by picking points around the unit circle. `n` is the number of point/sides, `offset` is the starting angle"
function makeshape(n; offset = -0.5, radius = 1.0)
z = offset * π
Shape(partialcircle(z, z + 2π, n+1, radius)[1:end-1])
end
function makecross(; offset = -0.5, radius = 1.0)
z2 = offset * π
z1 = z2 - π/8
outercircle = partialcircle(z1, z1 + 2π, 9, radius)
innercircle = partialcircle(z2, z2 + 2π, 5, 0.5radius)
Shape(weave(outercircle, innercircle,
ordering=Vector[outercircle,innercircle,outercircle])[1:end-2])
end
const _shapes = @compat Dict(
:ellipse => makeshape(20),
:rect => makeshape(4, offset=-0.25),
:diamond => makeshape(4),
:utriangle => makeshape(3),
:dtriangle => makeshape(3, offset=0.5),
:pentagon => makeshape(5),
:hexagon => makeshape(6),
:heptagon => makeshape(7),
:octagon => makeshape(8),
:cross => makecross(offset=-0.25),
:xcross => makecross(),
:vline => Shape([(0,1),(0,-1)]),
:hline => Shape([(1,0),(-1,0)]),
)
for n in [4,5,6,7,8]
_shapes[symbol("star$n")] = makestar(n)
end
# -----------------------------------------------------------------------
immutable Font
family::AbstractString
pointsize::Int
halign::Symbol
valign::Symbol
rotation::Float64
color::Colorant
end
"Create a Font from a list of unordered features"
function font(args...)
# defaults
family = "Helvetica"
pointsize = 14
halign = :hcenter
valign = :vcenter
rotation = 0.0
color = colorant"black"
for arg in args
T = typeof(arg)
if arg == :center
halign = :hcenter
valign = :vcenter
elseif arg in (:hcenter, :left, :right)
halign = arg
elseif arg in (:vcenter, :top, :bottom)
valign = arg
elseif T <: Colorant
color = arg
elseif T <: @compat Union{Symbol,AbstractString}
try
color = parse(Colorant, string(arg))
catch
family = string(arg)
end
elseif typeof(arg) <: Integer
pointsize = arg
elseif typeof(arg) <: Real
rotation = convert(Float64, arg)
else
warn("Unused font arg: $arg ($(typeof(arg)))")
end
end
Font(family, pointsize, halign, valign, rotation, color)
end
"Wrap a string with font info"
immutable PlotText
str::@compat(AbstractString)
font::Font
end
function text(str, args...)
PlotText(string(str), font(args...))
end
# -----------------------------------------------------------------------
immutable Stroke
width
color
alpha
style
end
function stroke(args...; alpha = nothing)
# defaults
# width = 1
# color = colorant"black"
# style = :solid
width = nothing
color = nothing
style = nothing
for arg in args
T = typeof(arg)
if arg in _allStyles
style = arg
elseif T <: Colorant
color = arg
elseif T <: @compat Union{Symbol,AbstractString}
try
color = parse(Colorant, string(arg))
end
elseif typeof(arg) <: Real
width = arg
else
warn("Unused stroke arg: $arg ($(typeof(arg)))")
end
end
Stroke(width, color, alpha, style)
end
immutable Brush
size # fillrange, markersize, or any other sizey attribute
color
alpha
end
function brush(args...; alpha = nothing)
# defaults
# sz = 1
# color = colorant"black"
size = nothing
color = nothing
for arg in args
T = typeof(arg)
if T <: Colorant
color = arg
elseif T <: @compat Union{Symbol,AbstractString}
try
color = parse(Colorant, string(arg))
end
elseif typeof(arg) <: Real
size = arg
else
warn("Unused brush arg: $arg ($(typeof(arg)))")
end
end
Brush(size, color, alpha)
end
# -----------------------------------------------------------------------
"type which represents z-values for colors and sizes (and anything else that might come up)"
immutable ZValues
values::Vector{Float64}
zrange::Tuple{Float64,Float64}
end
function zvalues{T<:Real}(values::AVec{T}, zrange::Tuple{T,T} = (minimum(values), maximum(values)))
ZValues(collect(float(values)), map(Float64, zrange))
end
# -----------------------------------------------------------------------
"represents a contour or surface mesh"
immutable Surface{M<:AMat}
# x::AVec
# y::AVec
surf::M
end
Surface(f::Function, x, y) = Surface(Float64[f(xi,yi) for xi in x, yi in y])
Base.Array(surf::Surface) = surf.surf
# -----------------------------------------------------------------------
type OHLC{T<:Real}
open::T
high::T
low::T
close::T
end
+10
View File
@@ -37,6 +37,15 @@ end
ps(fn::@compat(AbstractString)) = ps(current(), fn)
function tex(plt::PlottingObject, fn::@compat(AbstractString))
fn = addExtension(fn, "tex")
io = open(fn, "w")
writemime(io, MIME("application/x-tex"), plt)
close(io)
end
tex(fn::@compat(AbstractString)) = tex(current(), fn)
# ----------------------------------------------------------------
@@ -45,6 +54,7 @@ ps(fn::@compat(AbstractString)) = ps(current(), fn)
"svg" => svg,
"pdf" => pdf,
"ps" => ps,
"tex" => tex,
)
function getExtension(fn::@compat(AbstractString))
+96 -36
View File
@@ -22,7 +22,7 @@ Base.print(io::IO, plt::Plot) = print(io, string(plt))
Base.show(io::IO, plt::Plot) = print(io, string(plt))
getplot(plt::Plot) = plt
getinitargs(plt::Plot, idx::Int = 1) = plt.initargs
getplotargs(plt::Plot, idx::Int = 1) = plt.plotargs
convertSeriesIndex(plt::Plot, n::Int) = n
# ---------------------------------------------------------
@@ -48,9 +48,9 @@ function plot(args...; kw...)
preprocessArgs!(d)
dumpdict(d, "After plot preprocessing")
plotargs = getPlotArgs(pkg, d, 1)
plotargs = merge(d, getPlotArgs(pkg, d, 1))
dumpdict(plotargs, "Plot args")
plt = plot(pkg; plotargs...) # create a new, blank plot
plt = _create_plot(pkg; plotargs...) # create a new, blank plot
delete!(d, :background_color)
plot!(plt, args...; d...) # add to it
@@ -79,6 +79,9 @@ function plot!(plt::Plot, args...; kw...)
d = Dict(kw)
preprocessArgs!(d)
# for plotting recipes, swap out the args and update the parameter dictionary
args = _apply_recipe(d, args...; kw...)
dumpdict(d, "After plot! preprocessing")
warnOnUnsupportedArgs(plt.backend, d)
@@ -87,22 +90,24 @@ function plot!(plt::Plot, args...; kw...)
groupargs = get(d, :group, nothing) == nothing ? [] : [extractGroupArgs(d[:group], args...)]
# just in case the backend needs to set up the plot (make it current or something)
preparePlotUpdate(plt)
_before_add_series(plt)
# get the list of dictionaries, one per series
kwList, xmeta, ymeta = createKWargsList(plt, groupargs..., args...; d...)
seriesArgList, xmeta, ymeta = createKWargsList(plt, groupargs..., args...; d...)
# if we were able to extract guide information from the series inputs, then update the plot
# @show xmeta, ymeta
updateDictWithMeta(d, plt.initargs, xmeta, true)
updateDictWithMeta(d, plt.initargs, ymeta, false)
updateDictWithMeta(d, plt.plotargs, xmeta, true)
updateDictWithMeta(d, plt.plotargs, ymeta, false)
# now we can plot the series
for (i,di) in enumerate(kwList)
for (i,di) in enumerate(seriesArgList)
plt.n += 1
setTicksFromStringVector(d, di, :x, :xticks)
setTicksFromStringVector(d, di, :y, :yticks)
if !stringsSupported()
setTicksFromStringVector(d, di, :x, :xticks)
setTicksFromStringVector(d, di, :y, :yticks)
end
# remove plot args
for k in keys(_plotDefaults)
@@ -111,22 +116,22 @@ function plot!(plt::Plot, args...; kw...)
dumpdict(di, "Series $i")
plot!(plt.backend, plt; di...)
_add_series(plt.backend, plt; di...)
end
addAnnotations(plt, d)
_add_annotations(plt, d)
warnOnUnsupportedScales(plt.backend, d)
# add title, axis labels, ticks, etc
if !haskey(d, :subplot)
merge!(plt.initargs, d)
dumpdict(plt.initargs, "Updating plot items")
updatePlotItems(plt, plt.initargs)
merge!(plt.plotargs, d)
dumpdict(plt.plotargs, "Updating plot items")
_update_plot(plt, plt.plotargs)
end
updatePositionAndSize(plt, d)
_update_plot_pos_size(plt, d)
current(plt)
@@ -163,18 +168,18 @@ end
# --------------------------------------------------------------------
preparePlotUpdate(plt::Plot) = nothing
_before_add_series(plt::Plot) = nothing
# --------------------------------------------------------------------
# should we update the x/y label given the meta info during input slicing?
function updateDictWithMeta(d::Dict, initargs::Dict, meta::Symbol, isx::Bool)
function updateDictWithMeta(d::Dict, plotargs::Dict, meta::Symbol, isx::Bool)
lsym = isx ? :xlabel : :ylabel
if initargs[lsym] == default(lsym)
if plotargs[lsym] == default(lsym)
d[lsym] = string(meta)
end
end
updateDictWithMeta(d::Dict, initargs::Dict, meta, isx::Bool) = nothing
updateDictWithMeta(d::Dict, plotargs::Dict, meta, isx::Bool) = nothing
# --------------------------------------------------------------------
@@ -184,16 +189,27 @@ annotations{X,Y,V}(t::@compat(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)
function _add_annotations(plt::Plot, d::Dict)
anns = annotations(get(d, :annotation, nothing))
if !isempty(anns)
addAnnotations(plt, anns)
_add_annotations(plt, anns)
end
end
# --------------------------------------------------------------------
function Base.copy(plt::Plot)
backend(plt.backend)
plt2 = plot(; plt.plotargs...)
for sargs in plt.seriesargs
sargs = filter((k,v) -> haskey(_seriesDefaults,k), sargs)
plot!(plt2; sargs...)
end
plt2
end
# --------------------------------------------------------------------
# create a new "createKWargsList" which converts all inputs into xs = Any[xitems], ys = Any[yitems].
# Special handling for: no args, xmin/xmax, parametric, dataframes
@@ -221,11 +237,25 @@ convertToAnyVector{T<:Real}(v::AMat{T}; kw...) = Any[v[:,i] for i in 1:size(v,2)
# function
convertToAnyVector(f::Function; kw...) = Any[f], nothing
# surface
convertToAnyVector(s::Surface; kw...) = Any[s], nothing
# vector of OHLC
convertToAnyVector(v::AVec{OHLC}; kw...) = Any[v], nothing
# dates
convertToAnyVector{D<:Union{Date,DateTime}}(dts::AVec{D}; kw...) = Any[dts], nothing
# list of things (maybe other vectors, functions, or something else)
convertToAnyVector(v::AVec; kw...) = Any[vi for vi in v], nothing
function convertToAnyVector(v::AVec; kw...)
if all(x -> typeof(x) <: Real, v)
# all real numbers wrap the whole vector as one item
Any[convert(Vector{Float64}, v)], nothing
else
# something else... treat each element as an item
Any[vi for vi in v], nothing
end
end
# --------------------------------------------------------------------
@@ -241,7 +271,7 @@ function computeXandY(x, y)
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)
# @assert length(x) == length(y)
x, y
end
@@ -254,8 +284,6 @@ function createKWargsList(plt::PlottingObject, x, y; kw...)
xs, xmeta = convertToAnyVector(x; kw...)
ys, ymeta = convertToAnyVector(y; kw...)
# _debugMode.on && dumpcallstack()
mx = length(xs)
my = length(ys)
ret = Any[]
@@ -275,7 +303,7 @@ function createKWargsList(plt::PlottingObject, x, y; kw...)
numUncounted = get(d, :numUncounted, 0)
n = plt.n + i + numUncounted
dumpdict(d, "before getSeriesArgs")
d = getSeriesArgs(plt.backend, getinitargs(plt, n), d, i + numUncounted, convertSeriesIndex(plt, n), n)
d = getSeriesArgs(plt.backend, getplotargs(plt, n), d, i + numUncounted, convertSeriesIndex(plt, n), n)
dumpdict(d, "after getSeriesArgs")
d[:x], d[:y] = computeXandY(xs[mod1(i,mx)], ys[mod1(i,my)])
@@ -324,9 +352,13 @@ function createKWargsList(plt::PlottingObject, y; kw...)
createKWargsList(plt, nothing, y; kw...)
end
# contours or surfaces... irregular data
# 3d line or scatter
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, zvec::AVec; kw...)
error("TODO: contours or surfaces... irregular data")
d = Dict(kw)
if !(get(d, :linetype, :none) in _3dTypes)
d[:linetype] = :path3d
end
createKWargsList(plt, x, y; z=zvec, d...)
end
# contours or surfaces... function grid
@@ -346,9 +378,38 @@ function createKWargsList{T<:Real}(plt::PlottingObject, x::AVec, y::AVec, zmat::
@assert x == sort(x)
@assert y == sort(y)
@assert size(zmat) == (length(x), length(y))
surf = Array(Any,1,1)
surf[1,1] = convert(Matrix{Float64}, zmat)
createKWargsList(plt, x, y; kw..., surface = surf, linetype = :contour)
# surf = Surface(convert(Matrix{Float64}, zmat))
# surf = Array(Any,1,1)
# surf[1,1] = convert(Matrix{Float64}, zmat)
d = Dict(kw)
d[:z] = Surface(convert(Matrix{Float64}, zmat))
if !(get(d, :linetype, :none) in (:contour, :surface, :wireframe))
d[:linetype] = :contour
end
createKWargsList(plt, x, y; d...) #, z = surf)
end
# contours or surfaces... general x, y grid
function createKWargsList{T<:Real}(plt::PlottingObject, x::AMat{T}, y::AMat{T}, zmat::AMat{T}; kw...)
@assert size(zmat) == size(x) == size(y)
surf = Surface(convert(Matrix{Float64}, zmat))
# surf = Array(Any,1,1)
# surf[1,1] = convert(Matrix{Float64}, zmat)
d = Dict(kw)
d[:z] = Surface(convert(Matrix{Float64}, zmat))
if !(get(d, :linetype, :none) in (:contour, :surface, :wireframe))
d[:linetype] = :contour
end
createKWargsList(plt, Any[x], Any[y]; d...) #kw..., z = surf, linetype = :contour)
end
function createKWargsList(plt::PlottingObject, surf::Surface; kw...)
createKWargsList(plt, 1:size(surf.surf,1), 1:size(surf.surf,2), convert(Matrix{Float64}, surf.surf); kw...)
end
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, surf::Surface; kw...)
createKWargsList(plt, x, y, convert(Matrix{Float64}, surf.surf); kw...)
end
function createKWargsList(plt::PlottingObject, f::FuncOrFuncs; kw...)
@@ -363,7 +424,7 @@ end
# special handling... xmin/xmax with function(s)
function createKWargsList(plt::PlottingObject, f::FuncOrFuncs, xmin::Real, xmax::Real; kw...)
width = plt.initargs[:size][1]
width = get(plt.plotargs, :size, (100,))[1]
x = collect(linspace(xmin, xmax, width)) # we don't need more than the width
createKWargsList(plt, x, f; kw...)
end
@@ -386,7 +447,7 @@ function createKWargsList(plt::PlottingObject; kw...)
return [], nothing, nothing
# error("Called plot/subplot without args... must set y in the keyword args. Example: plot(; y=rand(10))")
end
if haskey(d, :x)
return createKWargsList(plt, d[:x], d[:y]; kw...)
else
@@ -429,4 +490,3 @@ end
# --------------------------------------------------------------------
+117 -54
View File
@@ -1,11 +1,15 @@
immutable GadflyPackage <: PlottingPackage end
immutable ImmersePackage <: PlottingPackage end
immutable PyPlotPackage <: PlottingPackage end
immutable QwtPackage <: PlottingPackage end
immutable GadflyPackage <: PlottingPackage end
immutable ImmersePackage <: PlottingPackage end
immutable PyPlotPackage <: PlottingPackage end
immutable QwtPackage <: PlottingPackage end
immutable UnicodePlotsPackage <: PlottingPackage end
immutable WinstonPackage <: PlottingPackage end
immutable WinstonPackage <: PlottingPackage end
immutable BokehPackage <: PlottingPackage end
immutable PlotlyPackage <: PlottingPackage end
immutable GLVisualizePackage <: PlottingPackage end
immutable NoPackage <: PlottingPackage end
typealias GadflyOrImmerse @compat(Union{GadflyPackage, ImmersePackage})
@@ -14,21 +18,31 @@ export
immerse,
pyplot,
qwt,
unicodeplots
unicodeplots,
bokeh,
plotly,
glvisualize
# winston
gadfly() = backend(:gadfly)
immerse() = backend(:immerse)
pyplot() = backend(:pyplot)
qwt() = backend(:qwt)
unicodeplots() = backend(:unicodeplots)
# winston() = backend(:winston)
gadfly() = backend(:gadfly)
immerse() = backend(:immerse)
pyplot() = backend(:pyplot)
qwt() = backend(:qwt)
unicodeplots() = backend(:unicodeplots)
bokeh() = backend(:bokeh)
plotly() = backend(:plotly)
glvisualize() = backend(:glvisualize)
# winston() = backend(:winston)
backend_name(::GadflyPackage) = :gadfly
backend_name(::ImmersePackage) = :immerse
backend_name(::PyPlotPackage) = :pyplot
backend_name(::UnicodePlotsPackage) = :unicodeplots
backend_name(::QwtPackage) = :qwt
backend_name(::BokehPackage) = :bokeh
backend_name(::PlotlyPackage) = :plotly
backend_name(::GLVisualizePackage) = :glvisualize
backend_name(::NoPackage) = :none
include("backends/supported.jl")
@@ -39,16 +53,22 @@ include("backends/pyplot.jl")
include("backends/immerse.jl")
include("backends/winston.jl")
include("backends/web.jl")
include("backends/bokeh.jl")
include("backends/plotly.jl")
include("backends/glvisualize.jl")
# ---------------------------------------------------------
plot(pkg::PlottingPackage; kw...) = error("plot($pkg; kw...) is not implemented")
plot!(pkg::PlottingPackage, plt::Plot; kw...) = error("plot!($pkg, plt; kw...) is not implemented")
updatePlotItems(pkg::PlottingPackage, plt::Plot, d::Dict) = error("updatePlotItems($pkg, plt, d) is not implemented")
_update_plot(pkg::PlottingPackage, plt::Plot, d::Dict) = error("_update_plot($pkg, plt, d) is not implemented")
# Base.display(pkg::PlottingPackage, plt::Plot) = error("display($pkg, plt) is not implemented")
updatePositionAndSize{P<:PlottingPackage}(plt::PlottingObject{P}, d::Dict) = nothing #error("updatePositionAndSize(plt,d) is not implemented for $P")
_update_plot_pos_size{P<:PlottingPackage}(plt::PlottingObject{P}, d::Dict) = nothing #error("_update_plot_pos_size(plt,d) is not implemented for $P")
subplot(pkg::PlottingPackage; kw...) = error("subplot($pkg; kw...) is not implemented")
subplot!(pkg::PlottingPackage, subplt::Subplot; kw...) = error("subplot!($pkg, subplt; kw...) is not implemented")
@@ -57,7 +77,7 @@ subplot!(pkg::PlottingPackage, subplt::Subplot; kw...) = error("subplot!($pkg, s
# ---------------------------------------------------------
const BACKENDS = [:qwt, :gadfly, :unicodeplots, :pyplot, :immerse]
const BACKENDS = [:qwt, :gadfly, :unicodeplots, :pyplot, :immerse, :bokeh, :plotly]
const INITIALIZED_BACKENDS = Set{Symbol}()
backends() = BACKENDS
@@ -69,8 +89,12 @@ function backendInstance(sym::Symbol)
sym == :pyplot && return PyPlotPackage()
sym == :immerse && return ImmersePackage()
sym == :winston && return WinstonPackage()
sym == :bokeh && return BokehPackage()
sym == :plotly && return PlotlyPackage()
sym == :glvisualize && return GLVisualizePackage()
sym == :none && return NoPackage()
error("Unsupported backend $sym")
end
end
type CurrentBackend
@@ -82,41 +106,13 @@ CurrentBackend(sym::Symbol) = CurrentBackend(sym, backendInstance(sym))
# ---------------------------------------------------------
function pickDefaultBackend()
try
if Pkg.installed("Immerse") != nothing
return CurrentBackend(:immerse)
for pkgstr in ("PyPlot", "Immerse", "Qwt", "Gadfly", "UnicodePlots", "Bokeh", "GLVisualize")
if Pkg.installed(pkgstr) != nothing
return backend(symbol(lowercase(pkgstr)))
end
end
try
if Pkg.installed("Qwt") != nothing
return CurrentBackend(:qwt)
end
end
try
if Pkg.installed("PyPlot") != nothing
return CurrentBackend(:pyplot)
end
end
try
if Pkg.installed("Gadfly") != nothing
return CurrentBackend(:gadfly)
end
end
try
if Pkg.installed("UnicodePlots") != nothing
return CurrentBackend(:unicodeplots)
end
end
try
if Pkg.installed("Winston") != nothing
return CurrentBackend(:winston)
end
end
warn("You don't have any of the supported backends installed! Chose from ", backends())
return CurrentBackend(:gadfly)
backend(:plotly)
end
# const CURRENT_BACKEND = pickDefaultBackend()
# println("[Plots.jl] Default backend: ", CURRENT_BACKEND.sym)
# ---------------------------------------------------------
@@ -125,7 +121,11 @@ end
Returns the current plotting package name. Initializes package on first call.
"""
function backend()
# error()
global CURRENT_BACKEND
if CURRENT_BACKEND.sym == :none
pickDefaultBackend()
end
currentBackendSymbol = CURRENT_BACKEND.sym
if !(currentBackendSymbol in INITIALIZED_BACKENDS)
@@ -143,8 +143,8 @@ function backend()
elseif currentBackendSymbol == :gadfly
try
@eval import Gadfly, Compose, DataFrames
@eval export Gadfly, Compose, DataFrames
@eval import Gadfly, Compose
@eval export Gadfly, Compose
@eval include(joinpath(Pkg.dir("Plots"), "src", "backends", "gadfly_shapes.jl"))
catch err
warn("Couldn't import Gadfly. Install it with: Pkg.add(\"Gadfly\").")
@@ -166,10 +166,11 @@ function backend()
@eval export PyPlot
@eval const pycolors = PyPlot.pywrap(PyPlot.pyimport("matplotlib.colors"))
@eval const pypath = PyPlot.pywrap(PyPlot.pyimport("matplotlib.path"))
@eval const mplot3d = PyPlot.pywrap(PyPlot.pyimport("mpl_toolkits.mplot3d"))
# @eval const pycolorbar = PyPlot.pywrap(PyPlot.pyimport("matplotlib.colorbar"))
if !isa(Base.Multimedia.displays[end], Base.REPL.REPLDisplay)
PyPlot.ioff() # stops wierd behavior of displaying incomplete graphs in IJulia
# # TODO: how the hell can I use PyQt4??
# "pyqt4"=>:qt_pyqt4
# PyPlot.backend[1] = "pyqt4"
@@ -198,6 +199,63 @@ function backend()
rethrow(err)
end
elseif currentBackendSymbol == :bokeh
try
@eval import Bokeh
@eval export Bokeh
catch err
warn("Couldn't import Bokeh. Install it with: Pkg.add(\"Bokeh\").")
rethrow(err)
end
elseif currentBackendSymbol == :plotly
try
@eval begin
import JSON
JSON._print(io::IO, state::JSON.State, dt::Union{Date,DateTime}) = print(io, '"', dt, '"')
############################
# borrowed from https://github.com/spencerlyon2/Plotlyjs.jl/blob/master/src/display.jl
_js_path = joinpath(Pkg.dir("Plots"), "deps", "plotly-latest.min.js")
# if we're in IJulia call setupnotebook to load js and css
if isijulia()
# the first script is some hack I needed to do in order for the notebook
# to not complain about Plotly being undefined
display("text/html", """
<script type="text/javascript">
require=requirejs=define=undefined;
</script>
<script type="text/javascript">
$(open(readall, _js_path, "r"))
</script>
""")
# display("text/html", "<p>Plotly javascript loaded.</p>")
end
# end borrowing (thanks :)
###########################
# try
# include(joinpath(Pkg.dir("Plots"), "src", "backends", "plotly_blink.jl"))
# catch err
# warn("Error including Plotlyjs: $err\n Note: Will fall back to built-in display.")
# end
end
catch err
warn("Couldn't setup Plotly")
rethrow(err)
end
elseif currentBackendSymbol == :glvisualize
try
@eval import GLVisualize
@eval export GLVisualize
catch err
warn("Couldn't setup GLVisualize")
rethrow(err)
end
elseif currentBackendSymbol == :winston
warn("Winston support is deprecated and broken. Try another backend: $BACKENDS")
try
@@ -222,13 +280,12 @@ end
Set the plot backend. Choose from: :qwt, :gadfly, :unicodeplots, :immerse, :pyplot
"""
function backend(pkg::PlottingPackage)
CURRENT_BACKEND.sym = backend_name(pkg)
CURRENT_BACKEND.pkg = pkg
end
function backend(modname)
# set the PlottingPackage
if modname == :qwt
CURRENT_BACKEND.pkg = QwtPackage()
@@ -242,6 +299,12 @@ function backend(modname)
CURRENT_BACKEND.pkg = ImmersePackage()
elseif modname == :winston
CURRENT_BACKEND.pkg = WinstonPackage()
elseif modname == :bokeh
CURRENT_BACKEND.pkg = BokehPackage()
elseif modname == :plotly
CURRENT_BACKEND.pkg = PlotlyPackage()
elseif modname == :glvisualize
CURRENT_BACKEND.pkg = GLVisualizePackage()
else
error("Unknown backend $modname. Choose from: $BACKENDS")
end
+104 -91
View File
@@ -14,102 +14,115 @@ plot(recipe::PlotRecipe, args...; kw...) = plot(getRecipeXY(recipe)..., args...;
plot!(recipe::PlotRecipe, args...; kw...) = plot!(getRecipeXY(recipe)..., args...; getRecipeArgs(recipe)..., kw...)
plot!(plt::Plot, recipe::PlotRecipe, args...; kw...) = plot!(getRecipeXY(recipe)..., args...; getRecipeArgs(recipe)..., kw...)
num_series(x::AMat) = size(x,2)
num_series(x) = 1
# -------------------------------------------------
_apply_recipe(d::Dict; kw...) = ()
function rotate(x::Real, y::Real, θ::Real; center = (0,0))
cx = x - center[1]
cy = y - center[2]
xrot = cx * cos(θ) - cy * sin(θ)
yrot = cy * cos(θ) + cx * sin(θ)
xrot + center[1], yrot + center[2]
end
# -------------------------------------------------
type EllipseRecipe <: PlotRecipe
w::Float64
h::Float64
x::Float64
y::Float64
θ::Float64
end
EllipseRecipe(w,h,x,y) = EllipseRecipe(w,h,x,y,0)
# return x,y coords of a rotated ellipse, centered at the origin
function rotatedEllipse(w, h, x, y, θ, rotθ)
# # coord before rotation
xpre = w * cos(θ)
ypre = h * sin(θ)
# rotate and translate
r = rotate(xpre, ypre, rotθ)
x + r[1], y + r[2]
end
function getRecipeXY(ep::EllipseRecipe)
x, y = unzip([rotatedEllipse(ep.w, ep.h, ep.x, ep.y, u, ep.θ) for u in linspace(0,2π,100)])
top = rotate(0, ep.h, ep.θ)
right = rotate(ep.w, 0, ep.θ)
linex = Float64[top[1], 0, right[1]] + ep.x
liney = Float64[top[2], 0, right[2]] + ep.y
Any[x, linex], Any[y, liney]
end
function getRecipeArgs(ep::EllipseRecipe)
[(:line, (3, [:dot :solid], [:red :blue], :path))]
end
# -------------------------------------------------
"Correlation scatter matrix"
function corrplot{T<:Real,S<:Real}(mat::AMat{T}, corrmat::AMat{S} = cor(mat);
colors = :redsblues,
labels = nothing, kw...)
m = size(mat,2)
centers = Float64[mean(extrema(mat[:,i])) for i in 1:m]
# might be a mistake?
@assert m <= 20
@assert size(corrmat) == (m,m)
# create a subplot grid, and a gradient from -1 to 1
p = subplot(rand(0,m^2); n=m^2, leg=false, grid=false, kw...)
cgrad = ColorGradient(colors, [-1,1])
# make all the plots
for i in 1:m
for j in 1:m
idx = p.layout[i,j]
plt = p.plts[idx]
if i==j
# histogram on diagonal
histogram!(plt, mat[:,i], c=:black)
i > 1 && plot!(plt, yticks = :none)
elseif i < j
# annotate correlation value in upper triangle
mi, mj = centers[i], centers[j]
plot!(plt, [mj], [mi],
ann = (mj, mi, text(@sprintf("Corr:\n%0.3f", corrmat[i,j]), 15)),
yticks=:none)
else
# scatter plots in lower triangle; color determined by correlation
c = RGBA(RGB(getColorZ(cgrad, corrmat[i,j])), 0.3)
scatter!(plt, mat[:,j], mat[:,i], w=0, ms=3, c=c, smooth=true)
end
if labels != nothing && length(labels) >= m
i == m && xlabel!(plt, string(labels[j]))
j == 1 && ylabel!(plt, string(labels[i]))
end
# if it's not a recipe, just do nothing and return the args
function _apply_recipe(d::Dict, args...; issubplot=false, kw...)
if issubplot && !haskey(d, :n) && !haskey(d, :layout)
# put in a sensible default
d[:n] = maximum(map(num_series, args))
end
end
# link the axes
subplot!(p, link = (r,c) -> (true, r!=c))
args
end
# # -------------------------------------------------
# function rotate(x::Real, y::Real, θ::Real; center = (0,0))
# cx = x - center[1]
# cy = y - center[2]
# xrot = cx * cos(θ) - cy * sin(θ)
# yrot = cy * cos(θ) + cx * sin(θ)
# xrot + center[1], yrot + center[2]
# end
# # -------------------------------------------------
# type EllipseRecipe <: PlotRecipe
# w::Float64
# h::Float64
# x::Float64
# y::Float64
# θ::Float64
# end
# EllipseRecipe(w,h,x,y) = EllipseRecipe(w,h,x,y,0)
# # return x,y coords of a rotated ellipse, centered at the origin
# function rotatedEllipse(w, h, x, y, θ, rotθ)
# # # coord before rotation
# xpre = w * cos(θ)
# ypre = h * sin(θ)
# # rotate and translate
# r = rotate(xpre, ypre, rotθ)
# x + r[1], y + r[2]
# end
# function getRecipeXY(ep::EllipseRecipe)
# x, y = unzip([rotatedEllipse(ep.w, ep.h, ep.x, ep.y, u, ep.θ) for u in linspace(0,2π,100)])
# top = rotate(0, ep.h, ep.θ)
# right = rotate(ep.w, 0, ep.θ)
# linex = Float64[top[1], 0, right[1]] + ep.x
# liney = Float64[top[2], 0, right[2]] + ep.y
# Any[x, linex], Any[y, liney]
# end
# function getRecipeArgs(ep::EllipseRecipe)
# [(:line, (3, [:dot :solid], [:red :blue], :path))]
# end
# # -------------------------------------------------
# "Correlation scatter matrix"
# function corrplot{T<:Real,S<:Real}(mat::AMat{T}, corrmat::AMat{S} = cor(mat);
# colors = :redsblues,
# labels = nothing, kw...)
# m = size(mat,2)
# centers = Float64[mean(extrema(mat[:,i])) for i in 1:m]
# # might be a mistake?
# @assert m <= 20
# @assert size(corrmat) == (m,m)
# # create a subplot grid, and a gradient from -1 to 1
# p = subplot(rand(0,m^2); n=m^2, leg=false, grid=false, kw...)
# cgrad = ColorGradient(colors, [-1,1])
# # make all the plots
# for i in 1:m
# for j in 1:m
# idx = p.layout[i,j]
# plt = p.plts[idx]
# if i==j
# # histogram on diagonal
# histogram!(plt, mat[:,i], c=:black)
# i > 1 && plot!(plt, yticks = :none)
# elseif i < j
# # annotate correlation value in upper triangle
# mi, mj = centers[i], centers[j]
# plot!(plt, [mj], [mi],
# ann = (mj, mi, text(@sprintf("Corr:\n%0.3f", corrmat[i,j]), 15)),
# yticks=:none)
# else
# # scatter plots in lower triangle; color determined by correlation
# c = RGBA(RGB(getColorZ(cgrad, corrmat[i,j])), 0.3)
# scatter!(plt, mat[:,j], mat[:,i], w=0, ms=3, c=c, smooth=true)
# end
# if labels != nothing && length(labels) >= m
# i == m && xlabel!(plt, string(labels[j]))
# j == 1 && ylabel!(plt, string(labels[i]))
# end
# end
# end
# # link the axes
# subplot!(p, link = (r,c) -> (true, r!=c))
# end
"Sparsity plot... heatmap of non-zero values of a matrix"
function spy{T<:Real}(y::AMat{T}; kw...)
+47 -85
View File
@@ -81,8 +81,8 @@ Base.getindex(layout::GridLayout, r::Int, c::Int) = (r-1) * layout.nc + c
Base.getindex(subplt::Subplot, args...) = subplt.plts[subplt.layout[args...]]
# handle "linking" the subplot axes together
# each backend should implement the handleLinkInner and expandLimits! methods
function linkAxis(subplt::Subplot, isx::Bool)
# each backend should implement the _remove_axis and _expand_limits methods
function link_axis(subplt::Subplot, isx::Bool)
# collect the list of plots and the expanded limits for those plots that should be linked on this axis
includedPlots = Any[]
@@ -104,7 +104,7 @@ function linkAxis(subplt::Subplot, isx::Bool)
isinner = (isx && r < nrows(subplt.layout)) || (!isx && !firstone)
push!(includedPlots, (plt, isinner, k))
expandLimits!(lims[k], plt, isx)
_expand_limits(lims[k], plt, isx)
end
end
@@ -112,7 +112,7 @@ function linkAxis(subplt::Subplot, isx::Bool)
# do the axis adjustments
for (plt, isinner, k) in includedPlots
if isinner
handleLinkInner(plt, isx)
_remove_axis(plt, isx)
end
(isx ? xlims! : ylims!)(plt, lims[k]...)
end
@@ -128,7 +128,7 @@ Base.print(io::IO, subplt::Subplot) = print(io, string(subplt))
Base.show(io::IO, subplt::Subplot) = print(io, string(subplt))
getplot(subplt::Subplot, idx::Int = subplt.n) = subplt.plts[mod1(idx, subplt.p)]
getinitargs(subplt::Subplot, idx::Int) = getplot(subplt, idx).initargs
getplotargs(subplt::Subplot, idx::Int) = getplot(subplt, idx).plotargs
convertSeriesIndex(subplt::Subplot, n::Int) = ceil(Int, n / subplt.p)
# ------------------------------------------------------------
@@ -156,6 +156,9 @@ function subplot(args...; kw...)
d = Dict(kw)
preprocessArgs!(d)
# for plotting recipes, swap out the args and update the parameter dictionary
args = _apply_recipe(d, args...; kw..., issubplot=true)
# figure out the layout
layoutarg = get(d, :layout, nothing)
if layoutarg != nothing
@@ -175,12 +178,12 @@ function subplot(args...; kw...)
di = getPlotArgs(pkg, d, i)
di[:subplot] = true
dumpdict(di, "Plot args (subplot $i)")
push!(plts, plot(pkg; di...))
push!(plts, _create_plot(pkg; di...))
end
# create the object and do the plotting
subplt = Subplot(nothing, plts, pkg, length(layout), 0, layout, d, false, false, false, (r,c) -> (nothing,nothing))
subplot!(subplt, args...; kw...)
subplot!(subplt, args...; d...)
subplt
end
@@ -209,29 +212,8 @@ function subplot{P<:PlottingPackage}(plts::AVec{Plot{P}}, layout::SubplotLayout,
n = sum([plt.n for plt in plts])
subplt = Subplot(nothing, collect(plts), P(), p, n, layout, Dict(), false, false, false, (r,c) -> (nothing,nothing))
# preprocessArgs!(d)
# #
# for (i,plt) in enumerate(plts)
# di = copy(plt.initargs)
# for ck in (:background_color, :foreground_color, :color_palette)
# # if we have a value to override, do it
# if haskey(d, ck)
# di[ck] = get_mod(d[ck], i)
# end
# # build a new dict from the initargs of the plots
# iargs = Dict()
# for k in keys(_plotDefaults)
# iargs[k] = Any[plt.initargs[k] for plt in plts]'
# end
# merge!(iargs, d)
preprocessSubplot(subplt, d)
postprocessSubplot(subplt, d)
_preprocess_subplot(subplt, d)
_postprocess_subplot(subplt, d)
subplt
end
@@ -241,26 +223,28 @@ end
# ------------------------------------------------------------------------------------------------
function preprocessSubplot(subplt::Subplot, d::Dict)
function _preprocess_subplot(subplt::Subplot, d::Dict, args = ())
validateSubplotSupported()
preprocessArgs!(d)
# for plotting recipes, swap out the args and update the parameter dictionary
args = _apply_recipe(d, args...; d..., issubplot=true)
dumpdict(d, "After subplot! preprocessing")
# get the full initargs, overriding any new settings
# TODO: subplt.initargs should probably be merged sooner and actually used
# get the full plotargs, overriding any new settings
# TODO: subplt.plotargs should probably be merged sooner and actually used
# for color selection, etc. (i.e. if we overwrite the subplot palettes to [:heat :rainbow])
# then we need to overwrite plt[1].initargs[:color_palette] to :heat before it's actually used
# then we need to overwrite plt[1].plotargs[:color_palette] to :heat before it's actually used
# for color selection!
# first merge the new args into the subplot's initargs. then process the plot args and merge
# those into the plot's initargs. (example... `palette = [:blues :reds]` goes into subplt.initargs,
# then the ColorGradient for :blues/:reds is merged into plot 1/2 initargs, which is then used for color selection)
# first merge the new args into the subplot's plotargs. then process the plot args and merge
# those into the plot's plotargs. (example... `palette = [:blues :reds]` goes into subplt.plotargs,
# then the ColorGradient for :blues/:reds is merged into plot 1/2 plotargs, which is then used for color selection)
for i in 1:length(subplt.layout)
# di = getPlotArgs(backend(), subplt.initargs, i)
# merge!(subplt.plts[i].initargs, di)
subplt.plts[i].initargs = getPlotArgs(backend(), merge(subplt.plts[i].initargs, d), i)
subplt.plts[i].plotargs = getPlotArgs(backend(), merge(subplt.plts[i].plotargs, d), i)
end
merge!(subplt.initargs, d)
merge!(subplt.plotargs, d)
# process links. TODO: extract to separate function
for s in (:linkx, :linky, :linkfunc)
@@ -269,43 +253,28 @@ function preprocessSubplot(subplt::Subplot, d::Dict)
delete!(d, s)
end
end
args
end
function postprocessSubplot(subplt::Subplot, d::Dict)
function _postprocess_subplot(subplt::Subplot, d::Dict)
# init (after plot creation)
if !subplt.initialized
subplt.initialized = buildSubplotObject!(subplt, false)
subplt.initialized = _create_subplot(subplt, false)
end
# add title, axis labels, ticks, etc
for (i,plt) in enumerate(subplt.plts)
# # # get the full initargs, overriding any new settings
# # di = copy(merge(plt.initargs, d))
# di = copy(d)
# for (k,v) in di
# if typeof(v) <: AVec
# di[k] = v[mod1(i, length(v))]
# elseif typeof(v) <: AMat
# m = size(v,2)
# di[k] = (size(v,1) == 1 ? v[1, mod1(i, m)] : v[:, mod1(i, m)])
# end
# end
# di = merge!(plt.initargs, di)
di = plt.initargs
di = plt.plotargs
dumpdict(di, "Updating sp $i")
updatePlotItems(plt, di)
_update_plot(plt, di)
end
updatePositionAndSize(subplt, d)
_update_plot_pos_size(subplt, d)
# handle links
subplt.linkx && linkAxis(subplt, true)
subplt.linky && linkAxis(subplt, false)
subplt.linkx && link_axis(subplt, true)
subplt.linky && link_axis(subplt, false)
# set this to be current
current(subplt)
@@ -335,14 +304,14 @@ function subplot!(subplt::Subplot, args...; kw...)
# validateSubplotSupported()
d = Dict(kw)
preprocessSubplot(subplt, d)
args = _preprocess_subplot(subplt, d, args)
# create the underlying object (each backend will do this differently)
# note: we call it once before doing the individual plots, and once after
# this is because some backends need to set up the subplots and then plot,
# and others need to do it the other way around
if !subplt.initialized
subplt.initialized = buildSubplotObject!(subplt, true)
subplt.initialized = _create_subplot(subplt, true)
end
# handle grouping
@@ -365,17 +334,6 @@ function subplot!(subplt::Subplot, args...; kw...)
plt = getplot(subplt)
plt.n += 1
# # update the plot's initargs for things such as palettes, etc
# for (k,v) in subplt.initargs
# haskey(_plotDefaults, k) || continue
# if typeof(v) <: AVec
# plt.initargs[k] = v[mod1(i, length(v))]
# elseif typeof(v) <: AMat
# m = size(v,2)
# plt.initargs[k] = (size(v,1) == 1 ? v[1, mod1(i, m)] : v[:, mod1(i, m)])
# end
# end
# cleanup the dictionary that we pass into the plot! command
di[:show] = false
di[:subplot] = true
@@ -384,12 +342,12 @@ function subplot!(subplt::Subplot, args...; kw...)
delete!(di, k)
end
dumpdict(di, "subplot! kwList $i")
dumpdict(plt.initargs, "plt.initargs before plotting")
dumpdict(plt.plotargs, "plt.plotargs before plotting")
_plot_from_subplot!(plt; di...)
_add_series_subplot(plt; di...)
end
postprocessSubplot(subplt, d)
_postprocess_subplot(subplt, d)
# show it automatically?
if haskey(d, :show) && d[:show]
@@ -401,18 +359,22 @@ end
function _plot_from_subplot!(plt::Plot, args...; kw...)
function _add_series_subplot(plt::Plot, args...; kw...)
d = Dict(kw)
setTicksFromStringVector(d, d, :x, :xticks)
setTicksFromStringVector(d, d, :y, :yticks)
# dumpdict(d, "Plot from subplot")
plot!(plt.backend, plt; d...)
_add_series(plt.backend, plt; d...)
addAnnotations(plt, d)
_add_annotations(plt, d)
warnOnUnsupportedScales(plt.backend, d)
end
# --------------------------------------------------------------------
function Base.copy(subplt::Subplot)
subplot(subplt.plts, subplt.layout, subplt.plotargs)
end
+3 -148
View File
@@ -13,7 +13,7 @@ type Plot{T<:PlottingPackage} <: PlottingObject{T}
n::Int # number of series
# store these just in case
initargs::Dict
plotargs::Dict
seriesargs::Vector{Dict} # args for each series
end
@@ -38,8 +38,8 @@ type Subplot{T<:PlottingPackage, L<:SubplotLayout} <: PlottingObject{T}
p::Int # number of plots
n::Int # number of series
layout::L
# initargs::Vector{Dict}
initargs::Dict
# plotargs::Vector{Dict}
plotargs::Dict
initialized::Bool
linkx::Bool
linky::Bool
@@ -47,148 +47,3 @@ type Subplot{T<:PlottingPackage, L<:SubplotLayout} <: PlottingObject{T}
end
# -----------------------------------------------------------------------
immutable Shape
vertices::AVec
end
"get an array of tuples of points on a circle with radius `r`"
function partialcircle(start_θ, end_θ, n = 20, r=1)
@compat(Tuple{Float64,Float64})[(r*cos(u),r*sin(u)) for u in linspace(start_θ, end_θ, n)]
end
"interleave 2 vectors into each other (like a zipper's teeth)"
function weave(x,y; ordering = Vector[x,y])
ret = eltype(x)[]
done = false
while !done
for o in ordering
try
push!(ret, shift!(o))
end
# try
# push!(ret, shift!(y))
# end
end
done = isempty(x) && isempty(y)
end
ret
end
"create a star by weaving together points from an outer and inner circle. `n` is the number of arms"
function makestar(n; offset = -0.5, radius = 1.0)
z1 = offset * π
z2 = z1 + π / (n)
outercircle = partialcircle(z1, z1 + 2π, n+1, radius)
innercircle = partialcircle(z2, z2 + 2π, n+1, 0.4radius)
Shape(weave(outercircle, innercircle)[1:end-2])
end
"create a shape by picking points around the unit circle. `n` is the number of point/sides, `offset` is the starting angle"
function makeshape(n; offset = -0.5, radius = 1.0)
z = offset * π
Shape(partialcircle(z, z + 2π, n+1, radius)[1:end-1])
end
function makecross(; offset = -0.5, radius = 1.0)
z2 = offset * π
z1 = z2 - π/8
outercircle = partialcircle(z1, z1 + 2π, 9, radius)
innercircle = partialcircle(z2, z2 + 2π, 5, 0.5radius)
Shape(weave(outercircle, innercircle,
ordering=Vector[outercircle,innercircle,outercircle])[1:end-2])
end
const _shapes = @compat Dict(
:ellipse => makeshape(20),
:rect => makeshape(4, offset=-0.25),
:diamond => makeshape(4),
:utriangle => makeshape(3),
:dtriangle => makeshape(3, offset=0.5),
:pentagon => makeshape(5),
:hexagon => makeshape(6),
:heptagon => makeshape(7),
:octagon => makeshape(8),
:cross => makecross(offset=-0.25),
:xcross => makecross(),
)
for n in [4,5,6,7,8]
_shapes[symbol("star$n")] = makestar(n)
end
# -----------------------------------------------------------------------
immutable Font
family::AbstractString
pointsize::Int
halign::Symbol
valign::Symbol
rotation::Float64
color::Colorant
end
"Create a Font from a list of unordered features"
function font(args...)
# defaults
family = "Helvetica"
pointsize = 14
halign = :hcenter
valign = :vcenter
rotation = 0.0
color = colorant"black"
for arg in args
T = typeof(arg)
if arg == :center
halign = :hcenter
valign = :vcenter
elseif arg in (:hcenter, :left, :right)
halign = arg
elseif arg in (:vcenter, :top, :bottom)
valign = arg
elseif T <: Colorant
color = arg
elseif T <: @compat Union{Symbol,AbstractString}
try
color = parse(Colorant, string(arg))
catch
family = string(arg)
end
elseif typeof(arg) <: Integer
pointsize = arg
elseif typeof(arg) <: Real
rotation = convert(Float64, arg)
else
warn("Unused font arg: $arg ($(typeof(arg)))")
end
end
Font(family, pointsize, halign, valign, rotation, color)
end
"Wrap a string with font info"
immutable PlotText
str::@compat(AbstractString)
font::Font
end
function text(str, args...)
PlotText(string(str), font(args...))
end
# -----------------------------------------------------------------------
type OHLC{T<:Real}
open::T
high::T
low::T
close::T
end
+113 -12
View File
@@ -116,6 +116,9 @@ end
# ------------------------------------------------------------------------------------
nop() = nothing
get_mod(v::AVec, idx::Int) = v[mod1(idx, length(v))]
get_mod(v::AMat, idx::Int) = size(v,1) == 1 ? v[1, mod1(idx, size(v,2))] : v[:, mod1(idx, size(v,2))]
get_mod(v, idx::Int) = v
@@ -131,7 +134,7 @@ maketuple{T,S}(x::@compat(Tuple{T,S})) = x
unzip{T,S}(v::AVec{@compat(Tuple{T,S})}) = [vi[1] for vi in v], [vi[2] for vi in v]
# given 2-element lims and a vector of data x, widen lims to account for the extrema of x
function expandLimits!(lims, x)
function _expand_limits(lims, x)
try
e1, e2 = extrema(x)
lims[1] = min(lims[1], e1)
@@ -162,7 +165,6 @@ end
function replaceAliases!(d::Dict, aliases::Dict)
ks = collect(keys(d))
# for (k,v) in d
for k in ks
if haskey(aliases, k)
d[aliases[k]] = d[k]
@@ -172,7 +174,9 @@ function replaceAliases!(d::Dict, aliases::Dict)
end
createSegments(z) = collect(repmat(z',2,1))[2:end]
Base.first(c::Colorant) = c
Base.first(x::Symbol) = x
sortedkeys(d::Dict) = sort(collect(keys(d)))
@@ -186,6 +190,18 @@ function fakedata(sz...)
y
end
isijulia() = isdefined(Main, :IJulia) && Main.IJulia.inited
istuple(::Tuple) = true
istuple(::Any) = false
isvector(::AVec) = true
isvector(::Any) = false
ismatrix(::AMat) = true
ismatrix(::Any) = false
isscalar(::Real) = true
isscalar(::Any) = false
# ticksType{T<:Real,S<:Real}(ticks::@compat(Tuple{T,S})) = :limits
@@ -198,6 +214,89 @@ limsType(lims::Symbol) = lims == :auto ? :auto : :invalid
limsType(lims) = :invalid
Base.convert{T<:Real}(::Type{Vector{T}}, rng::Range{T}) = T[x for x in rng]
Base.convert{T<:Real,S<:Real}(::Type{Vector{T}}, rng::Range{S}) = T[x for x in rng]
# ---------------------------------------------------------------
"""
Allows temporary setting of backend and defaults for Plots. Settings apply only for the `do` block. Example:
```
with(:gadfly, size=(400,400), type=:hist) do
plot(rand(10))
plot(rand(10))
end
```
"""
function with(f::Function, args...; kw...)
# dict to store old and new keyword args for anything that changes
newdefs = Dict(kw)
olddefs = Dict()
for k in keys(newdefs)
olddefs[k] = default(k)
end
# save the backend
if CURRENT_BACKEND.sym == :none
pickDefaultBackend()
end
oldbackend = CURRENT_BACKEND.sym
for arg in args
# change backend?
if arg in backends()
backend(arg)
end
# # TODO: generalize this strategy to allow args as much as possible
# # as in: with(:gadfly, :scatter, :legend, :grid) do; ...; end
# # TODO: can we generalize this enough to also do something similar in the plot commands??
# k = :linetype
# if arg in _allTypes
# olddefs[k] = default(k)
# newdefs[k] = arg
# elseif haskey(_typeAliases, arg)
# olddefs[k] = default(k)
# newdefs[k] = _typeAliases[arg]
# end
k = :legend
if arg in (k, :leg)
olddefs[k] = default(k)
newdefs[k] = true
end
k = :grid
if arg == k
olddefs[k] = default(k)
newdefs[k] = true
end
end
# display(olddefs)
# display(newdefs)
# now set all those defaults
default(; newdefs...)
# call the function
ret = f()
# put the defaults back
default(; olddefs...)
# revert the backend
if CURRENT_BACKEND.sym != oldbackend
backend(oldbackend)
end
# return the result of the function
ret
end
# ---------------------------------------------------------------
@@ -213,8 +312,8 @@ end
debugshow(x) = show(x)
debugshow(x::AbstractArray) = print(summary(x))
function dumpdict(d::Dict, prefix = "")
_debugMode.on || return
function dumpdict(d::Dict, prefix = "", alwaysshow = false)
_debugMode.on || alwaysshow || return
println()
if prefix != ""
println(prefix, ":")
@@ -354,12 +453,14 @@ end
# Some conversion functions
# note: I borrowed these conversion constants from Compose.jl's Measure
const INCH_SCALAR = 25.4
const PX_SCALAR = 1 / 3.78
inch2px(inches::Real) = float(inches * INCH_SCALAR / PX_SCALAR)
px2inch(px::Real) = float(px * PX_SCALAR / INCH_SCALAR)
inch2mm(inches::Real) = float(inches * INCH_SCALAR)
mm2inch(mm::Real) = float(mm / INCH_SCALAR)
px2mm(px::Real) = float(px * PX_SCALAR)
mm2px(mm::Real) = float(px / PX_SCALAR)
const PX_PER_INCH = 100
const DPI = PX_PER_INCH
const MM_PER_INCH = 25.4
const MM_PER_PX = MM_PER_INCH / PX_PER_INCH
inch2px(inches::Real) = float(inches * PX_PER_INCH)
px2inch(px::Real) = float(px / PX_PER_INCH)
inch2mm(inches::Real) = float(inches * MM_PER_INCH)
mm2inch(mm::Real) = float(mm / MM_PER_INCH)
px2mm(px::Real) = float(px * MM_PER_PX)
mm2px(mm::Real) = float(px / MM_PER_PX)
+2 -1
View File
@@ -1,4 +1,4 @@
julia 0.3
julia 0.4
Colors
Reexport
@@ -7,3 +7,4 @@ Gadfly
Images
ImageMagick
PyPlot
@osx QuartzImageIO
+88 -115
View File
@@ -1,35 +1,27 @@
# include this first to help with crashing??
try
@eval using Gtk
end
# # include this first to help with crashing??
# try
# @eval using Gtk
# catch err
# warn("Gtk not loaded. err: $err")
# end
using VisualRegressionTests
using ExamplePlots
# don't let pyplot use a gui... it'll crash
# note: Agg will set gui -> :none in PyPlot
ENV["MPLBACKEND"] = "Agg"
try
@eval import PyPlot
info("Matplotlib version: $(PyPlot.matplotlib[:__version__])")
end
# macro test_approx_eq_sigma_eps(A, B, sigma, eps)
# include("../docs/example_generation.jl")
include("../docs/example_generation.jl")
# # make and display one plot
# function test_examples(pkg::Symbol, idx::Int; debug = true)
# Plots._debugMode.on = debug
# println("Testing plot: $pkg:$idx:$(examples[idx].header)")
# backend(pkg)
# backend()
# map(eval, examples[idx].exprs)
# plt = current()
# gui(plt)
# plt
# end
using Plots, FactCheck
import Images, ImageMagick
# import Images, ImageMagick
# if !isdefined(ImageMagick, :init_deps)
# function ImageMagick.init_deps()
@@ -37,99 +29,75 @@ import Images, ImageMagick
# end
# end
function makeImageWidget(fn)
img = Gtk.GtkImageLeaf(fn)
vbox = Gtk.GtkBoxLeaf(:v)
push!(vbox, Gtk.GtkLabelLeaf(fn))
push!(vbox, img)
show(img)
vbox
end
# function makeImageWidget(fn)
# img = Gtk.GtkImageLeaf(fn)
# vbox = Gtk.GtkBoxLeaf(:v)
# push!(vbox, Gtk.GtkLabelLeaf(fn))
# push!(vbox, img)
# show(img)
# vbox
# end
function replaceReferenceImage(tmpfn, reffn)
cmd = `cp $tmpfn $reffn`
run(cmd)
info("Replaced reference image with: $cmd")
end
# function replaceReferenceImage(tmpfn, reffn)
# cmd = `cp $tmpfn $reffn`
# run(cmd)
# info("Replaced reference image with: $cmd")
# end
"Show a Gtk popup with both images and a confirmation whether we should replace the new image with the old one"
function compareToReferenceImage(tmpfn, reffn)
@eval import Gtk
# "Show a Gtk popup with both images and a confirmation whether we should replace the new image with the old one"
# function compareToReferenceImage(tmpfn, reffn)
# add the images
imgbox = Gtk.GtkBoxLeaf(:h)
push!(imgbox, makeImageWidget(tmpfn))
push!(imgbox, makeImageWidget(reffn))
# # add the images
# imgbox = Gtk.GtkBoxLeaf(:h)
# push!(imgbox, makeImageWidget(tmpfn))
# push!(imgbox, makeImageWidget(reffn))
# add the buttons
# doNothingButton = Gtk.GtkButtonLeaf("Skip")
# replaceReferenceButton = Gtk.GtkButtonLeaf("Replace reference image")
# btnbox = Gtk.GtkButtonBoxLeaf(:h)
# push!(btnbox, doNothingButton)
# push!(btnbox, replaceReferenceButton)
# win = Gtk.GtkWindowLeaf("Should we make this the new reference image?")
# push!(win, Gtk.GtkFrameLeaf(imgbox))
# # create the window
# box = Gtk.GtkBoxLeaf(:v)
# push!(box, imgbox)
# push!(box, btnbox)
win = Gtk.GtkWindowLeaf("Should we make this the new reference image?")
push!(win, Gtk.GtkFrameLeaf(imgbox))
# showall(win)
showall(win)
# # now ask the question
# if Gtk.ask_dialog("Should we make this the new reference image?", "No", "Yes")
# replaceReferenceImage(tmpfn, reffn)
# end
# now ask the question
if Gtk.ask_dialog("Should we make this the new reference image?", "No", "Yes")
replaceReferenceImage(tmpfn, reffn)
end
destroy(win)
# # we'll wait on this condition
# c = Condition()
# Gtk.on_signal_destroy((x...) -> notify(c), win)
# Gtk.signal_connect(replaceReferenceButton, "clicked") do widget
# replaceReferenceImage(tmpfn, reffn)
# notify(c)
# end
# Gtk.signal_connect(doNothingButton, "clicked") do widget
# notify(c)
# end
# # wait until a button is clicked, then close the window
# Gtk.showall(win)
# wait(c)
# Gtk.destroy(win)
end
# destroy(win)
# end
# TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that
# is referenced in a button press callback (the button clicked callback will call notify() on that condition)
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, sigma = [1,1], eps = 1e-2)
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)
# first
Plots._debugMode.on = debug
info("Testing plot: $pkg:$idx:$(PlotExamples.examples[idx].header)")
example = ExamplePlots._examples[idx]
info("Testing plot: $pkg:$idx:$(example.header)")
backend(pkg)
backend()
# ensure consistent results
srand(1234)
# test function
func = (fn, idx) -> begin
map(eval, example.exprs)
png(fn)
end
# run the example
map(eval, PlotExamples.examples[idx].exprs)
# map(eval, PlotExamples._examples[idx].exprs)
# save the png
tmpfn = tempname() * ".png"
png(tmpfn)
# # save the png
# tmpfn = tempname() * ".png"
# png(tmpfn)
# load the saved png
tmpimg = Images.load(tmpfn)
# # load the saved png
# tmpimg = Images.load(tmpfn)
# reference image location
# refdir = joinpath(Pkg.dir("Plots"), "test", "refimg", "v$(VERSION.major).$(VERSION.minor)", string(pkg))
# reference image directory setup
refdir = joinpath(Pkg.dir("Plots"), "test", "refimg", string(pkg))
try
run(`mkdir -p $refdir`)
@@ -138,45 +106,50 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, sigma = [1
end
reffn = joinpath(refdir, "ref$idx.png")
try
# the test
vtest = VisualTest(func, reffn, idx)
test_images(vtest, popup=popup, sigma=sigma, eps=eps)
# info("Comparing $tmpfn to reference $reffn")
# try
# # info("Comparing $tmpfn to reference $reffn")
# load the reference image
refimg = Images.load(reffn)
# # load the reference image
# refimg = Images.load(reffn)
# run the comparison test... a difference will throw an error
# NOTE: sigma is a 2-length vector with x/y values for the number of pixels
# to blur together when comparing images
diffpct = Images.test_approx_eq_sigma_eps(tmpimg, refimg, sigma, eps)
# # run the comparison test... a difference will throw an error
# # NOTE: sigma is a 2-length vector with x/y values for the number of pixels
# # to blur together when comparing images
# diffpct = Images.test_approx_eq_sigma_eps(tmpimg, refimg, sigma, eps)
# we passed!
info("Reference image $reffn matches. Difference: $diffpct")
return true
# # we passed!
# info("Reference image $reffn matches. Difference: $diffpct")
# return true
catch err
warn("Image did not match reference image $reffn. err: $err")
showerror(Base.STDERR, err)
# catch err
# warn("Image did not match reference image $reffn. err: $err")
# # showerror(Base.STDERR, err)
if isinteractive()
# if isinteractive()
# if we're in interactive mode, open a popup and give us a chance to examine the images
warn("Should we make this the new reference image?")
compareToReferenceImage(tmpfn, reffn)
return
# # if we're in interactive mode, open a popup and give us a chance to examine the images
# warn("Should we make this the new reference image?")
# compareToReferenceImage(tmpfn, reffn)
# # println("exited")
# return
else
# else
# if we rejected the image, or if we're in automated tests, throw the error
rethrow(err)
end
# # if we rejected the image, or if we're in automated tests, throw the error
# rethrow(err)
# end
end
# end
end
function image_comparison_tests(pkg::Symbol; skip = [], debug = false, sigma = [1,1], eps = 1e-2)
for i in 1:length(PlotExamples.examples)
function image_comparison_facts(pkg::Symbol; skip = [], debug = false, sigma = [1,1], eps = 1e-2)
for i in 1:length(ExamplePlots._examples)
i in skip && continue
@fact image_comparison_tests(pkg, i, debug=debug, sigma=sigma, eps=eps) --> true
@fact image_comparison_tests(pkg, i, debug=debug, sigma=sigma, eps=eps) |> success --> true
end
end
Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 114 KiB

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 31 KiB

+23 -27
View File
@@ -1,23 +1,23 @@
module PlotsTests
# don't let pyplot use a gui... it'll crash
# note: Agg will set gui -> :none in PyPlot
ENV["MPLBACKEND"] = "Agg"
try
@eval import PyPlot
catch err
warn("Couldn't import PyPlot: $err")
end
# # don't let pyplot use a gui... it'll crash
# # note: Agg will set gui -> :none in PyPlot
# ENV["MPLBACKEND"] = "Agg"
# try
# @eval import PyPlot
# catch err
# warn("Couldn't import PyPlot: $err")
# end
using Plots
using FactCheck
# using Plots
# using FactCheck
# note: wrap first include in a try block because of the ImageMagick init_deps bug
try
include("imgcomp.jl")
end
# # note: wrap first include in a try block because of the ImageMagick init_deps bug
# try
# include("imgcomp.jl")
# end
include("imgcomp.jl")
# don't actually show the plots
@@ -30,7 +30,7 @@ default(show=false)
# gadfly()
# backend()
img_eps = 1e-2
img_eps = 5e-2
facts("Gadfly") do
@fact gadfly() --> Plots.GadflyPackage()
@@ -40,27 +40,23 @@ facts("Gadfly") do
# plot(x::AVec, y::AVec; kw...) # one line (will assert length(x) == length(y))
@fact plot(Int[1,2,3], rand(3)) --> not(nothing)
@fact_throws plot(1:5, 1:4)
# @fact_throws plot(1:5, 1:4)
# plot(x::AVec, y::AMat; kw...) # multiple lines (one per column of x), all sharing x (will assert length(x) == size(y,1))
@fact plot(sort(rand(10)), rand(Int, 10, 3)) --> not(nothing)
@fact_throws(plot!(rand(10), rand(9,2)))
# @fact_throws(plot!(rand(10), rand(9,2)))
# plot(x::AMat, y::AMat; kw...) # multiple lines (one per column of x/y... will assert size(x) == size(y))
@fact plot!(rand(10,3), rand(10,3)) --> not(nothing)
if VERSION >= v"0.4-"
image_comparison_tests(:gadfly, skip=[4,19], eps=img_eps)
end
image_comparison_facts(:gadfly, skip=[4,6,19,23,24], eps=img_eps)
end
if VERSION >= v"0.4-"
facts("PyPlot") do
@fact pyplot() --> Plots.PyPlotPackage()
@fact backend() --> Plots.PyPlotPackage()
image_comparison_tests(:pyplot, skip=[19,21], eps=img_eps)
end
facts("PyPlot") do
@fact pyplot() --> Plots.PyPlotPackage()
@fact backend() --> Plots.PyPlotPackage()
image_comparison_facts(:pyplot, skip=[10,19,21,23], eps=img_eps)
end
@@ -117,7 +113,7 @@ end
# @fact backend() --> Plots.PyPlotPackage()
# @fact typeof(plot(1:10)) --> Plots.Plot{Plots.PyPlotPackage}
# # image_comparison_tests(:pyplot, skip=[19])
# # image_comparison_facts(:pyplot, skip=[19])
# end
# catch err
# warn("Skipped PyPlot due to: ", string(err))