Compare commits

...

23 Commits

Author SHA1 Message Date
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
46 changed files with 1256 additions and 795 deletions
+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
+27 -20
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,12 +46,15 @@ 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(3,:green)), ms=10*abs(y-0.5)+3, 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))
]),
@@ -63,7 +66,8 @@ const examples = PlotExample[
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",
"""
@@ -301,20 +305,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

+4
View File
@@ -19,6 +19,7 @@ export
current,
default,
with,
scatter,
scatter!,
@@ -62,6 +63,8 @@ export
Shape,
text,
font,
stroke,
brush,
OHLC,
colorscheme,
@@ -104,6 +107,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")
+182 -129
View File
@@ -7,8 +7,11 @@ const _allAxes = [:auto, :left, :right]
:r => :right
)
const _allTypes = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
:heatmap, :hexbin, :hist, :bar, :hline, :vline, :ohlc, :contour]
const _3dTypes = [:path3d, :scatter3d]
const _allTypes = vcat([
:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
:heatmap, :hexbin, :hist, :bar, :hline, :vline, :ohlc, :contour
], _3dTypes)
@compat const _typeAliases = Dict(
:n => :none,
:no => :none,
@@ -27,8 +30,10 @@ const _allTypes = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
:dots => :scatter,
:histogram => :hist,
:contours => :contours,
:line3d => :path3d,
)
const _allStyles = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
@compat const _styleAliases = Dict(
:a => :auto,
@@ -105,34 +110,38 @@ 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[:z] = nothing # depth for contour, surface, etc
_seriesDefaults[:zcolor] = nothing # value for color scale
_seriesDefaults[:surface] = nothing
_seriesDefaults[:nlevels] = 15
const _plotDefaults = Dict{Symbol, Any}()
@@ -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,88 @@ 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,
: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
@@ -401,16 +413,27 @@ function processLineArg(d::Dict, arg)
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
@@ -424,15 +447,30 @@ function processMarkerArg(d::Dict, arg)
d[:markershape] = arg
elseif trueOrAllTrue(a -> isa(a, Shape), arg)
d[:markershape] = arg
# stroke style
elseif trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg)
d[:markerstrokestyle] = 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) <: Integer, arg)
elseif trueOrAllTrue(a -> typeof(a) <: Real, arg)
d[:markersize] = arg
# lineopacity
elseif trueOrAllTrue(a -> typeof(a) <: Real && a >= 0 && a <= 1, arg)
d[:markeropacity] = arg
# markercolor
elseif !handleColors!(d, arg, :markercolor)
warn("Skipped marker arg $arg.")
@@ -442,7 +480,13 @@ 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
@@ -483,6 +527,8 @@ function preprocessArgs!(d::Dict)
end
delete!(d, :fill)
# convert into strokes and brushes
# handle subplot links
if haskey(d, :link)
l = d[:link]
@@ -623,7 +669,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()
@@ -648,17 +694,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] == :log ? :log : :auto
yaxis_type = d[:yscale] == :log ? :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 = bokehcolor(d[:linecolor]), # shape's stroke or line color
linewidth = d[:linewidth], # shape's stroke width or line width
fillcolor = bokehcolor(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
+121 -66
View File
@@ -7,7 +7,7 @@
function createGadflyPlotObject(d::Dict)
gplt = Gadfly.Plot()
gplt.mapping = Dict()
gplt.data_source = DataFrames.DataFrame()
gplt.data_source = Gadfly.DataFrames.DataFrame()
gplt.layers = gplt.layers[1:0]
gplt.guides = Gadfly.GuideElement[Gadfly.Guide.xlabel(d[:xlabel]),
Gadfly.Guide.ylabel(d[:ylabel]),
@@ -36,9 +36,9 @@ 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])
else
@@ -46,32 +46,51 @@ function getLineGeom(d::Dict)
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 +106,49 @@ 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[:surface]
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 +161,48 @@ 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 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
zcolor = d[:zcolor]
if zcolor != nothing && typeof(zcolor) <: AVec
kwargs[:color] = zcolor
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 +211,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 +226,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 +256,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 +265,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[]
@@ -226,14 +281,14 @@ function addGadflySeries!(plt::Plot, d::Dict)
# 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 +300,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 +312,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)]
# ---------------------------------------------------------------------------
@@ -385,13 +440,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 +458,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 +518,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 +528,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 +536,7 @@ end
# plot one data series
function plot!(::GadflyPackage, plt::Plot; kw...)
function _add_series(::GadflyPackage, plt::Plot; kw...)
d = Dict(kw)
addGadflySeries!(plt, d)
push!(plt.seriesargs, d)
@@ -490,7 +545,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 +577,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 +624,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]...)
# -------------------------------------------------------------------------
@@ -597,14 +652,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)
+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
+83 -61
View File
@@ -77,6 +77,7 @@ end
immutable PyPlotFigWrapper
fig
kwargs # for add_subplot
end
immutable PyPlotAxisWrapper
@@ -92,7 +93,7 @@ getfig(wrap::@compat(Union{PyPlotAxisWrapper,PyPlotFigWrapper})) = wrap.fig
function getLeftAxis(wrap::PyPlotFigWrapper)
axes = wrap.fig.o[:axes]
if isempty(axes)
return wrap.fig.o[:add_subplot](111)
return wrap.fig.o[:add_subplot](111; wrap.kwargs...)
end
axes[1]
end
@@ -106,15 +107,16 @@ function getPyPlotFunction(plt::Plot, axis::Symbol, linetype::Symbol)
# 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,
:sticks => :bar,
:bar => :bar,
:heatmap => :hexbin,
:hexbin => :hexbin,
:scatter => :scatter,
:contour => :contour,
:scatter3d => :scatter,
)
return ax[get(fmap, linetype, :plot)]
end
@@ -138,7 +140,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,7 +148,6 @@ 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])
@@ -154,7 +155,7 @@ makePyPlotCurrent(wrap::PyPlotAxisWrapper) = nothing #PyPlot.sca(wrap.ax.o)
makePyPlotCurrent(plt::Plot{PyPlotPackage}) = makePyPlotCurrent(plt.o)
function preparePlotUpdate(plt::Plot{PyPlotPackage})
function _before_add_series(plt::Plot{PyPlotPackage})
makePyPlotCurrent(plt)
end
@@ -169,7 +170,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 +180,7 @@ 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 = PyPlotFigWrapper(PyPlot.figure(; figsize = (w,h), facecolor = bgcolor, dpi = 96), [])
end
plt = Plot(wrap, pkg, 0, d, Dict[])
@@ -187,22 +188,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 && isa(plt.o, PyPlotFigWrapper)
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,7 +217,7 @@ 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
@@ -237,10 +242,10 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
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
@@ -250,29 +255,42 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
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])
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 (: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
@@ -285,9 +303,11 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
surf = d[:surface]'
handle = plotfunc(x, y, surf, d[:nlevels]; extra_kwargs...)
if d[:fillrange] != nothing
handle = ax[:contourf](x, y, surf, d[:nlevels]; cmap = getPyPlotColorMap(d[:fillcolor], d[:fillopacity]))
handle = ax[:contourf](x, y, surf, d[:nlevels]; cmap = getPyPlotColorMap(d[:fillcolor], d[:fillalpha]))
end
handle
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 +317,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
@@ -343,11 +365,11 @@ function Base.setindex!(plt::Plot{PyPlotPackage}, xy::Tuple, i::Integer)
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])))
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])))
end
@@ -390,7 +412,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)
@@ -435,13 +457,13 @@ function updatePlotItems(plt::Plot{PyPlotPackage}, d::Dict)
# 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)
@@ -488,7 +510,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,11 +519,11 @@ 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])
w,h = map(px2inch, getplotargs(subplt,1)[:size])
bgcolor = getPyPlotColor(getplotargs(subplt,1)[:background_color])
fig = PyPlot.figure(; figsize = (w,h), facecolor = bgcolor, dpi = 96)
nr = nrows(l)
@@ -515,7 +537,7 @@ function buildSubplotObject!(subplt::Subplot{PyPlotPackage}, isbefore::Bool)
subplt.plts[i].o = PyPlotAxisWrapper(ax, fig)
end
subplt.o = PyPlotFigWrapper(fig)
subplt.o = PyPlotFigWrapper(fig, [])
true
end
@@ -528,26 +550,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}[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,23 +577,23 @@ 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,:hexbin,:heatmap,:hline,:vline,:contour, :path3d, :scatter3d)), plt.seriesargs)
if length(args) > 0
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
)
end
@@ -581,7 +603,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,7 +612,7 @@ 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
PyPlot.draw()
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
+96 -13
View File
@@ -3,11 +3,11 @@ supportedArgs(::GadflyPackage) = [
:annotation,
# :axis,
:background_color,
:color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
:fillopacity,
:fillalpha,
:foreground_color,
:group,
:label,
@@ -16,11 +16,14 @@ supportedArgs(::GadflyPackage) = [
:linestyle,
:linetype,
:linewidth,
:lineopacity,
:linealpha,
:markershape,
:markercolor,
:markersize,
:markeropacity,
:markeralpha,
:markerstrokewidth,
:markerstrokecolor,
# :markerstrokestyle,
:n,
:nbins,
:nc,
@@ -45,6 +48,7 @@ supportedArgs(::GadflyPackage) = [
:xflip,
:yflip,
:z,
:zcolor,
:tickfont,
:guidefont,
:legendfont,
@@ -77,7 +81,7 @@ supportedArgs(::PyPlotPackage) = [
:annotation,
:axis,
:background_color,
:color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
@@ -92,6 +96,9 @@ supportedArgs(::PyPlotPackage) = [
:markershape,
:markercolor,
:markersize,
:markerstrokewidth,
:markerstrokecolor,
# :markerstrokestyle,
:n,
:nbins,
:nc,
@@ -117,18 +124,19 @@ supportedArgs(::PyPlotPackage) = [
:xflip,
:yflip,
:z,
:zcolor, # only supported for scatter/scatter3d
:tickfont,
:guidefont,
:legendfont,
:grid,
:surface,
:nlevels,
:fillopacity,
:lineopacity,
:markeropacity,
: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, :bar, :hline, :vline, :contour, :path3d, :scatter3d]
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)
@@ -145,7 +153,7 @@ supportedArgs(::QwtPackage) = [
# :args,
:axis,
:background_color,
:color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
@@ -162,6 +170,9 @@ supportedArgs(::QwtPackage) = [
:markershape,
:markercolor,
:markersize,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
:n,
:nbins,
:nc,
@@ -201,7 +212,7 @@ supportedArgs(::UnicodePlotsPackage) = [
# :args,
# :axis,
# :background_color,
# :color,
# :linecolor,
# :fill,
# :foreground_color,
:group,
@@ -216,6 +227,9 @@ supportedArgs(::UnicodePlotsPackage) = [
:markershape,
# :markercolor,
# :markersize,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
:nbins,
# :nc,
@@ -259,7 +273,7 @@ supportedArgs(::WinstonPackage) = [
# :args,
# :axis,
# :background_color,
:color,
:linecolor,
:color_palette,
:fillrange,
:fillcolor,
@@ -276,6 +290,9 @@ supportedArgs(::WinstonPackage) = [
:markershape,
:markercolor,
:markersize,
# :markerstrokewidth,
# :markerstrokecolor,
# :markerstrokestyle,
# :n,
:nbins,
# :nc,
@@ -310,4 +327,70 @@ 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,
# :nlevels,
]
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, :log] #, :log, :log2, :log10, :asinh, :sqrt]
+42 -64
View File
@@ -5,64 +5,7 @@
# ---------------------------------------------------------------------------
# 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
@@ -70,25 +13,60 @@ function plot(pkg::[PkgName]Package; kw...)
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})
# 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
+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
+25 -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)
@@ -382,7 +321,6 @@ end
# ----------------------------------------------------------------------------------
# TODO: try to use the algorithms from https://github.com/timothyrenner/ColorBrewer.jl
# 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 +353,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
+228
View File
@@ -0,0 +1,228 @@
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
# -----------------------------------------------------------------------
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
# -----------------------------------------------------------------------
type OHLC{T<:Real}
open::T
high::T
low::T
close::T
end
+30 -24
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
# ---------------------------------------------------------
@@ -50,7 +50,7 @@ function plot(args...; kw...)
plotargs = 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
@@ -87,18 +87,18 @@ 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)
@@ -111,22 +111,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 +163,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,10 +184,10 @@ 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
@@ -225,7 +225,15 @@ convertToAnyVector(f::Function; kw...) = Any[f], nothing
convertToAnyVector(v::AVec{OHLC}; kw...) = Any[v], nothing
# list of things (maybe other vectors, functions, or something else)
convertToAnyVector(v::AVec; kw...) = Any[vi for vi in v], 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
# --------------------------------------------------------------------
@@ -254,8 +262,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 +281,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)])
@@ -363,7 +369,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 = plt.plotargs[:size][1]
x = collect(linspace(xmin, xmax, width)) # we don't need more than the width
createKWargsList(plt, x, f; kw...)
end
+34 -14
View File
@@ -6,6 +6,7 @@ immutable PyPlotPackage <: PlottingPackage end
immutable QwtPackage <: PlottingPackage end
immutable UnicodePlotsPackage <: PlottingPackage end
immutable WinstonPackage <: PlottingPackage end
immutable BokehPackage <: PlottingPackage end
typealias GadflyOrImmerse @compat(Union{GadflyPackage, ImmersePackage})
@@ -14,7 +15,8 @@ export
immerse,
pyplot,
qwt,
unicodeplots
unicodeplots,
bokeh
# winston
gadfly() = backend(:gadfly)
@@ -22,6 +24,7 @@ immerse() = backend(:immerse)
pyplot() = backend(:pyplot)
qwt() = backend(:qwt)
unicodeplots() = backend(:unicodeplots)
bokeh() = backend(:bokeh)
# winston() = backend(:winston)
backend_name(::GadflyPackage) = :gadfly
@@ -29,6 +32,7 @@ backend_name(::ImmersePackage) = :immerse
backend_name(::PyPlotPackage) = :pyplot
backend_name(::UnicodePlotsPackage) = :unicodeplots
backend_name(::QwtPackage) = :qwt
backend_name(::BokehPackage) = :bokeh
include("backends/supported.jl")
@@ -38,6 +42,7 @@ include("backends/unicodeplots.jl")
include("backends/pyplot.jl")
include("backends/immerse.jl")
include("backends/winston.jl")
include("backends/bokeh.jl")
# ---------------------------------------------------------
@@ -45,10 +50,10 @@ include("backends/winston.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 +62,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]
const INITIALIZED_BACKENDS = Set{Symbol}()
backends() = BACKENDS
@@ -69,6 +74,7 @@ function backendInstance(sym::Symbol)
sym == :pyplot && return PyPlotPackage()
sym == :immerse && return ImmersePackage()
sym == :winston && return WinstonPackage()
sym == :bokeh && return BokehPackage()
error("Unsupported backend $sym")
end
@@ -82,6 +88,11 @@ CurrentBackend(sym::Symbol) = CurrentBackend(sym, backendInstance(sym))
# ---------------------------------------------------------
function pickDefaultBackend()
try
if Pkg.installed("PyPlot") != nothing
return CurrentBackend(:pyplot)
end
end
try
if Pkg.installed("Immerse") != nothing
return CurrentBackend(:immerse)
@@ -92,11 +103,6 @@ function pickDefaultBackend()
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)
@@ -107,6 +113,11 @@ function pickDefaultBackend()
return CurrentBackend(:unicodeplots)
end
end
try
if Pkg.installed("Bokeh") != nothing
return CurrentBackend(:bokeh)
end
end
try
if Pkg.installed("Winston") != nothing
return CurrentBackend(:winston)
@@ -115,8 +126,6 @@ function pickDefaultBackend()
warn("You don't have any of the supported backends installed! Chose from ", backends())
return CurrentBackend(:gadfly)
end
# const CURRENT_BACKEND = pickDefaultBackend()
# println("[Plots.jl] Default backend: ", CURRENT_BACKEND.sym)
# ---------------------------------------------------------
@@ -125,7 +134,6 @@ end
Returns the current plotting package name. Initializes package on first call.
"""
function backend()
# error()
currentBackendSymbol = CURRENT_BACKEND.sym
if !(currentBackendSymbol in INITIALIZED_BACKENDS)
@@ -143,8 +151,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,6 +174,7 @@ 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
@@ -198,6 +207,15 @@ 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 == :winston
warn("Winston support is deprecated and broken. Try another backend: $BACKENDS")
try
@@ -242,6 +260,8 @@ function backend(modname)
CURRENT_BACKEND.pkg = ImmersePackage()
elseif modname == :winston
CURRENT_BACKEND.pkg = WinstonPackage()
elseif modname == :bokeh
CURRENT_BACKEND.pkg = BokehPackage()
else
error("Unknown backend $modname. Choose from: $BACKENDS")
end
+32 -84
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)
# ------------------------------------------------------------
@@ -175,7 +175,7 @@ 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
@@ -209,29 +209,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 +220,24 @@ end
# ------------------------------------------------------------------------------------------------
function preprocessSubplot(subplt::Subplot, d::Dict)
function _preprocess_subplot(subplt::Subplot, d::Dict)
validateSubplotSupported()
preprocessArgs!(d)
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)
@@ -271,41 +248,24 @@ function preprocessSubplot(subplt::Subplot, d::Dict)
end
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 +295,14 @@ function subplot!(subplt::Subplot, args...; kw...)
# validateSubplotSupported()
d = Dict(kw)
preprocessSubplot(subplt, d)
_preprocess_subplot(subplt, d)
# 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 +325,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 +333,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,16 +350,15 @@ 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
+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
+86 -4
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]
@@ -198,6 +200,86 @@ 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
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 +295,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, ":")
+1 -1
View File
@@ -1,4 +1,4 @@
julia 0.3
julia 0.4
Colors
Reexport
+25 -2
View File
@@ -54,13 +54,21 @@ 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
# println("here000")
# @eval import Gtk
# Gtk.gtk_main()
# println("huh0")
# sleep(2)
# add the images
imgbox = Gtk.GtkBoxLeaf(:h)
# println("huh")
push!(imgbox, makeImageWidget(tmpfn))
# println("huh2")
push!(imgbox, makeImageWidget(reffn))
# println("here00")
# add the buttons
# doNothingButton = Gtk.GtkButtonLeaf("Skip")
# replaceReferenceButton = Gtk.GtkButtonLeaf("Replace reference image")
@@ -75,14 +83,28 @@ function compareToReferenceImage(tmpfn, reffn)
win = Gtk.GtkWindowLeaf("Should we make this the new reference image?")
push!(win, Gtk.GtkFrameLeaf(imgbox))
# println("here01")
# ################
# # TODO: remove this when it's fixed in Gtk... see http://stackoverflow.com/questions/33549485/julia-gtk-windows-do-not-display-outside-repl
# signal_connect(win, :destroy) do widget
# Gtk.gtk_quit()
# end
# ################
# println("here02")
showall(win)
# println("here1")
# now ask the question
if Gtk.ask_dialog("Should we make this the new reference image?", "No", "Yes")
replaceReferenceImage(tmpfn, reffn)
end
# println("here2")
destroy(win)
# println("here3")
# # we'll wait on this condition
# c = Condition()
@@ -156,13 +178,14 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, sigma = [1
catch err
warn("Image did not match reference image $reffn. err: $err")
showerror(Base.STDERR, err)
# showerror(Base.STDERR, err)
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)
println("exited")
return
else
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: 14 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 42 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: 201 KiB

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 37 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: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 31 KiB