Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 120f861a27 | |||
| 7e56d85b83 | |||
| 20af495581 | |||
| bf94c48225 | |||
| 27a68333b1 | |||
| 63f18dd26a | |||
| 4ea787743e | |||
| 3a4b881576 | |||
| f087594331 | |||
| 5491e40fd1 | |||
| 4b690ec9ad | |||
| 9fecb03b5f |
@@ -79,7 +79,7 @@
|
||||
|
||||
#### 0.7.0
|
||||
|
||||
- Check out [the summary](http://plots.readthedocs.io/en/latest/plots_v0.7/)
|
||||
- Check out [the summary](http://juliaplots.github.io/plots_v0.7/)
|
||||
- Revamped and simplified internals
|
||||
- [Recipes, recipes, recipes](https://github.com/JuliaPlots/RecipesBase.jl/issues/6)
|
||||
- [Layouts and Subplots](https://github.com/tbreloff/Plots.jl/issues/60)
|
||||
@@ -211,7 +211,7 @@
|
||||
- Integration with [PlotlyJS.jl](https://github.com/spencerlyon2/PlotlyJS.jl) for using Plotly inside a Blink window @spencerlyon2
|
||||
- The Plotly backend has been split into my built-in version (`plotly()`) and @spencerlyon2's backend (`plotlyjs()`)
|
||||
- Revamped backend setup code for easily adding new backends
|
||||
- New docs (WIP) at http://plots.readthedocs.org/
|
||||
- New docs (WIP) at http://juliaplots.github.io/
|
||||
- Overhaul to `:legend` keyword (see https://github.com/tbreloff/Plots.jl/issues/135)
|
||||
- New dependency on Requires, allows auto-loading of DataFrames support
|
||||
- Support for plotting lists of Tuples and FixedSizeArrays
|
||||
|
||||
@@ -12,22 +12,11 @@
|
||||
Plots is a plotting API and toolset. My goals with the package are:
|
||||
|
||||
- **Powerful**. Do more with less. Complex visualizations become easy.
|
||||
- **Intuitive**. Start generating plots without reading volumes of documentation. Commands should "just work".
|
||||
- **Intuitive**. Stop reading so much documentation. Commands should "just work".
|
||||
- **Concise**. Less code means fewer mistakes and more efficient development/analysis.
|
||||
- **Flexible**. Produce your favorite plots from your favorite package, but quicker and simpler.
|
||||
- **Consistent**. Don't commit to one graphics package. Use the same code and access the strengths of all [backends](http://plots.readthedocs.io/en/latest/backends/).
|
||||
- **Lightweight**. Very few dependencies, since backends are loaded and initialized dynamically.
|
||||
- **Consistent**. Don't commit to one graphics package, use the same code everywhere.
|
||||
- **Lightweight**. Very few dependencies.
|
||||
- **Smart**. Attempts to figure out what you **want** it to do... not just what you **tell** it.
|
||||
|
||||
Use the [preprocessing pipeline](http://plots.readthedocs.io/en/latest/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.
|
||||
|
||||
```julia
|
||||
using Plots
|
||||
@gif for i in linspace(0,2π,100)
|
||||
X = Y = linspace(-5,5,40)
|
||||
surface(X, Y, (x,y) -> sin(x+10sin(i))+cos(y))
|
||||
end
|
||||
```
|
||||
|
||||

|
||||
|
||||
View the [full documentation](http://plots.readthedocs.io).
|
||||
View the [full documentation](http://juliaplots.github.io).
|
||||
|
||||
@@ -175,6 +175,7 @@ end
|
||||
@shorthands vline
|
||||
@shorthands ohlc
|
||||
@shorthands contour
|
||||
@shorthands contourf
|
||||
@shorthands contour3d
|
||||
@shorthands surface
|
||||
@shorthands wireframe
|
||||
|
||||
@@ -63,6 +63,8 @@ const _arg_desc = KW(
|
||||
:html_output_format => "Symbol. When writing html output, what is the format? `:png` and `:svg` are currently supported.",
|
||||
:inset_subplots => "nothing or vector of 2-tuple (parent,bbox). optionally pass a vector of (parent,bbox) tuples which are the parent layout and the relative bounding box of inset subplots",
|
||||
:dpi => "Number. Dots Per Inch of output figures",
|
||||
:display_type => "Symbol (`:auto`, `:gui`, or `:inline`). When supported, `display` will either open a GUI window or plot inline.",
|
||||
:extra_kwargs => "KW (Dict{Symbol,Any}). Pass a map of extra keyword args which may be specific to a backend.",
|
||||
|
||||
# subplot args
|
||||
:title => "String. Subplot title.",
|
||||
|
||||
+7
-1
@@ -79,7 +79,7 @@ add_non_underscore_aliases!(_typeAliases)
|
||||
|
||||
like_histogram(seriestype::Symbol) = seriestype in (:histogram, :density)
|
||||
like_line(seriestype::Symbol) = seriestype in (:line, :path, :steppre, :steppost)
|
||||
like_surface(seriestype::Symbol) = seriestype in (:contour, :contour3d, :heatmap, :surface, :wireframe, :image)
|
||||
like_surface(seriestype::Symbol) = seriestype in (:contour, :contourf, :contour3d, :heatmap, :surface, :wireframe, :image)
|
||||
|
||||
is3d(seriestype::Symbol) = seriestype in _3dTypes
|
||||
is3d(series::Series) = is3d(series.d)
|
||||
@@ -217,6 +217,8 @@ const _plot_defaults = KW(
|
||||
:inset_subplots => nothing, # optionally pass a vector of (parent,bbox) tuples which are
|
||||
# the parent layout and the relative bounding box of inset subplots
|
||||
:dpi => DPI, # dots per inch for images, etc
|
||||
:display_type => :auto,
|
||||
:extra_kwargs => KW(),
|
||||
)
|
||||
|
||||
|
||||
@@ -928,6 +930,10 @@ function Base.getindex(axis::Axis, k::Symbol)
|
||||
end
|
||||
end
|
||||
|
||||
function Base.getindex(series::Series, k::Symbol)
|
||||
series.d[k]
|
||||
end
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
# update attr from an input dictionary
|
||||
|
||||
+6
-4
@@ -159,16 +159,18 @@ function expand_extrema!(sp::Subplot, d::KW)
|
||||
for letter in (:x, :y, :z)
|
||||
data = d[letter]
|
||||
axis = sp.attr[Symbol(letter, "axis")]
|
||||
if eltype(data) <: Number
|
||||
expand_extrema!(axis, data)
|
||||
elseif isa(data, Surface) && eltype(data.surf) <: Number
|
||||
if eltype(data) <: Number || (isa(data, Surface) && all(di -> isa(di, Number), data.surf))
|
||||
if !(eltype(data) <: Number)
|
||||
# huh... must have been a mis-typed surface? lets swap it out
|
||||
data = d[letter] = Surface(Matrix{Float64}(data.surf))
|
||||
end
|
||||
expand_extrema!(axis, data)
|
||||
elseif data != nothing
|
||||
# TODO: need more here... gotta track the discrete reference value
|
||||
# as well as any coord offset (think of boxplot shape coords... they all
|
||||
# correspond to the same x-value)
|
||||
# @show letter,eltype(data),typeof(data)
|
||||
d[letter], d[Symbol(letter,"_discrete_indices")] = discrete_value!(axis, data)
|
||||
expand_extrema!(axis, d[letter])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
+27
-8
@@ -157,6 +157,25 @@ function gr_polyline(x, y, func = GR.polyline)
|
||||
end
|
||||
end
|
||||
|
||||
function gr_inqtext(x, y, s)
|
||||
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
|
||||
GR.inqtextext(x, y, s[2:end-1])
|
||||
elseif search(s, '\\') != 0 || search(s, '_') != 0 || search(s, '^') != 0
|
||||
GR.inqtextext(x, y, s)
|
||||
else
|
||||
GR.inqtext(x, y, s)
|
||||
end
|
||||
end
|
||||
|
||||
function gr_text(x, y, s)
|
||||
if length(s) >= 2 && s[1] == '$' && s[end] == '$'
|
||||
GR.mathtex(x, y, s[2:end-1])
|
||||
elseif search(s, '\\') != 0 || search(s, '_') != 0 || search(s, '^') != 0
|
||||
GR.textext(x, y, s)
|
||||
else
|
||||
GR.text(x, y, s)
|
||||
end
|
||||
end
|
||||
|
||||
function gr_polaraxes(rmin, rmax)
|
||||
GR.savestate()
|
||||
@@ -569,14 +588,14 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
gr_set_font(sp[:titlefont])
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||
gr_set_textcolor(sp[:foreground_color_title])
|
||||
GR.text(gr_view_xcenter(), viewport_subplot[4], sp[:title])
|
||||
gr_text(gr_view_xcenter(), viewport_subplot[4], sp[:title])
|
||||
end
|
||||
|
||||
if xaxis[:guide] != ""
|
||||
gr_set_font(xaxis[:guidefont])
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_BOTTOM)
|
||||
gr_set_textcolor(xaxis[:foreground_color_guide])
|
||||
GR.text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide])
|
||||
gr_text(gr_view_xcenter(), viewport_subplot[3], xaxis[:guide])
|
||||
end
|
||||
|
||||
if yaxis[:guide] != ""
|
||||
@@ -584,7 +603,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
GR.settextalign(GR.TEXT_HALIGN_CENTER, GR.TEXT_VALIGN_TOP)
|
||||
GR.setcharup(-1, 0)
|
||||
gr_set_textcolor(yaxis[:foreground_color_guide])
|
||||
GR.text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide])
|
||||
gr_text(viewport_subplot[1], gr_view_ycenter(), yaxis[:guide])
|
||||
end
|
||||
GR.restorestate()
|
||||
|
||||
@@ -751,11 +770,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
if 90 <= alpha < 270
|
||||
x[3] = x[2] - 0.05
|
||||
GR.settextalign(GR.TEXT_HALIGN_RIGHT, GR.TEXT_VALIGN_HALF)
|
||||
GR.text(x[3] - 0.01, y[3], string(labels[i]))
|
||||
gr_text(x[3] - 0.01, y[3], string(labels[i]))
|
||||
else
|
||||
x[3] = x[2] + 0.05
|
||||
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF)
|
||||
GR.text(x[3] + 0.01, y[3], string(labels[i]))
|
||||
gr_text(x[3] + 0.01, y[3], string(labels[i]))
|
||||
end
|
||||
gr_polyline(x, y)
|
||||
a1 = a2
|
||||
@@ -809,7 +828,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
else
|
||||
lab = series.d[:label]
|
||||
end
|
||||
tbx, tby = GR.inqtext(0, 0, lab)
|
||||
tbx, tby = gr_inqtext(0, 0, lab)
|
||||
w = max(w, tbx[3] - tbx[1])
|
||||
end
|
||||
if w > 0
|
||||
@@ -865,7 +884,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
end
|
||||
GR.settextalign(GR.TEXT_HALIGN_LEFT, GR.TEXT_VALIGN_HALF)
|
||||
gr_set_textcolor(sp[:foreground_color_legend])
|
||||
GR.text(xpos, ypos, lab)
|
||||
gr_text(xpos, ypos, lab)
|
||||
ypos -= dy
|
||||
end
|
||||
end
|
||||
@@ -879,7 +898,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
|
||||
x, y, val = ann
|
||||
x, y = GR.wctondc(x, y)
|
||||
gr_set_font(val.font)
|
||||
GR.text(x, y, val.str)
|
||||
gr_text(x, y, val.str)
|
||||
end
|
||||
GR.restorestate()
|
||||
end
|
||||
|
||||
+17
-17
@@ -423,7 +423,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
if d[:line_z] == nothing
|
||||
handle = ax[:plot](xyargs...;
|
||||
label = d[:label],
|
||||
zorder = plt.n,
|
||||
zorder = d[:series_plotindex],
|
||||
color = py_linecolor(d),
|
||||
linewidth = py_dpi_scale(plt, d[:linewidth]),
|
||||
linestyle = py_linestyle(st, d[:linestyle]),
|
||||
@@ -504,7 +504,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
# end
|
||||
# handle = ax[isvertical(d) ? :bar : :barh](x, y;
|
||||
# label = d[:label],
|
||||
# zorder = plt.n,
|
||||
# zorder = d[:series_plotindex],
|
||||
# color = py_fillcolor(d),
|
||||
# edgecolor = py_linecolor(d),
|
||||
# linewidth = d[:linewidth],
|
||||
@@ -518,7 +518,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
# extrakw[isvertical(d) ? :width : :height] = 0.0
|
||||
# handle = ax[isvertical(d) ? :bar : :barh](x, y;
|
||||
# label = d[:label],
|
||||
# zorder = plt.n,
|
||||
# zorder = d[:series_plotindex],
|
||||
# color = py_linecolor(d),
|
||||
# edgecolor = py_linecolor(d),
|
||||
# linewidth = d[:linewidth],
|
||||
@@ -552,7 +552,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
handle = ax[:scatter](xyargs...;
|
||||
label = d[:label],
|
||||
zorder = plt.n + 0.5,
|
||||
zorder = d[:series_plotindex] + 0.5,
|
||||
marker = py_marker(d[:markershape]),
|
||||
s = py_dpi_scale(plt, d[:markersize] .^ 2),
|
||||
edgecolors = py_markerstrokecolor(d),
|
||||
@@ -565,7 +565,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
# if st == :histogram
|
||||
# handle = ax[:hist](y;
|
||||
# label = d[:label],
|
||||
# zorder = plt.n,
|
||||
# zorder = d[:series_plotindex],
|
||||
# color = py_fillcolor(d),
|
||||
# edgecolor = py_linecolor(d),
|
||||
# linewidth = d[:linewidth],
|
||||
@@ -594,7 +594,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
# end
|
||||
# handle = ax[:hist2d](x, y;
|
||||
# label = d[:label],
|
||||
# zorder = plt.n,
|
||||
# zorder = d[:series_plotindex],
|
||||
# bins = d[:bins],
|
||||
# normed = d[:normalize],
|
||||
# weights = d[:weights],
|
||||
@@ -619,7 +619,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
handle = ax[:hexbin](x, y;
|
||||
label = d[:label],
|
||||
zorder = plt.n,
|
||||
zorder = d[:series_plotindex],
|
||||
gridsize = d[:bins],
|
||||
linewidths = py_dpi_scale(plt, d[:linewidth]),
|
||||
edgecolors = py_linecolor(d),
|
||||
@@ -660,7 +660,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
# contour lines
|
||||
handle = ax[:contour](x, y, z, levelargs...;
|
||||
label = d[:label],
|
||||
zorder = plt.n,
|
||||
zorder = d[:series_plotindex],
|
||||
linewidths = py_dpi_scale(plt, d[:linewidth]),
|
||||
linestyles = py_linestyle(st, d[:linestyle]),
|
||||
cmap = py_linecolormap(d),
|
||||
@@ -672,7 +672,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
if d[:fillrange] != nothing
|
||||
handle = ax[:contourf](x, y, z, levelargs...;
|
||||
label = d[:label],
|
||||
zorder = plt.n + 0.5,
|
||||
zorder = d[:series_plotindex] + 0.5,
|
||||
cmap = py_fillcolormap(d),
|
||||
extrakw...
|
||||
)
|
||||
@@ -705,7 +705,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
handle = ax[st == :surface ? :plot_surface : :plot_wireframe](x, y, z;
|
||||
label = d[:label],
|
||||
zorder = plt.n,
|
||||
zorder = d[:series_plotindex],
|
||||
rstride = 1,
|
||||
cstride = 1,
|
||||
linewidth = py_dpi_scale(plt, d[:linewidth]),
|
||||
@@ -742,7 +742,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
handle = ax[:plot_trisurf](x, y, z;
|
||||
label = d[:label],
|
||||
zorder = plt.n,
|
||||
zorder = d[:series_plotindex],
|
||||
cmap = py_fillcolormap(d),
|
||||
linewidth = py_dpi_scale(plt, d[:linewidth]),
|
||||
edgecolor = py_linecolor(d),
|
||||
@@ -766,7 +766,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
z # hopefully it's in a data format that will "just work" with imshow
|
||||
end
|
||||
handle = ax[:imshow](z;
|
||||
zorder = plt.n,
|
||||
zorder = d[:series_plotindex],
|
||||
cmap = py_colormap([:black, :white]),
|
||||
vmin = 0.0,
|
||||
vmax = 1.0
|
||||
@@ -797,7 +797,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
|
||||
handle = ax[:pcolormesh](x, y, z;
|
||||
label = d[:label],
|
||||
zorder = plt.n,
|
||||
zorder = d[:series_plotindex],
|
||||
cmap = py_fillcolormap(d),
|
||||
edgecolors = (d[:linewidth] > 0 ? py_linecolor(d) : "face"),
|
||||
extrakw...
|
||||
@@ -820,7 +820,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
path = py_path(x, y)
|
||||
patches = pypatches.pymember("PathPatch")(path;
|
||||
label = d[:label],
|
||||
zorder = plt.n,
|
||||
zorder = d[:series_plotindex],
|
||||
edgecolor = py_linecolor(d),
|
||||
facecolor = py_fillcolor(d),
|
||||
linewidth = py_dpi_scale(plt, d[:linewidth]),
|
||||
@@ -887,7 +887,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
|
||||
end
|
||||
|
||||
handle = ax[f](args...;
|
||||
zorder = plt.n,
|
||||
zorder = d[:series_plotindex],
|
||||
facecolor = py_fillcolor(d),
|
||||
linewidths = 0
|
||||
)
|
||||
@@ -1278,12 +1278,12 @@ const _pyplot_mimeformats = Dict(
|
||||
for (mime, fmt) in _pyplot_mimeformats
|
||||
@eval function _writemime(io::IO, ::MIME{Symbol($mime)}, plt::Plot{PyPlotBackend})
|
||||
fig = plt.o
|
||||
fig.o["canvas"][:print_figure](
|
||||
fig.o[:canvas][:print_figure](
|
||||
io,
|
||||
format=$fmt,
|
||||
# bbox_inches = "tight",
|
||||
# figsize = map(px2inch, plt[:size]),
|
||||
facecolor = fig.o["get_facecolor"](),
|
||||
facecolor = fig.o[:get_facecolor](),
|
||||
edgecolor = "none",
|
||||
dpi = plt[:dpi]
|
||||
)
|
||||
|
||||
+2
-2
@@ -399,8 +399,8 @@ Base.Array(surf::Surface) = surf.surf
|
||||
for f in (:length, :size)
|
||||
@eval Base.$f(surf::Surface, args...) = $f(surf.surf, args...)
|
||||
end
|
||||
Base.copy(surf::Surface) = Surface(copy(surf.surf))
|
||||
Base.eltype(surf::Surface) = eltype(surf.surf)
|
||||
Base.copy(surf::Surface) = Surface{typeof(surf.surf)}(copy(surf.surf))
|
||||
Base.eltype{T}(surf::Surface{T}) = eltype(T)
|
||||
|
||||
function expand_extrema!(a::Axis, surf::Surface)
|
||||
ex = a[:extrema]
|
||||
|
||||
+10
-69
@@ -271,6 +271,7 @@ function _plot!(plt::Plot, d::KW, args...)
|
||||
else
|
||||
sts = get(d, :seriestype, :path)
|
||||
if typeof(sts) <: AbstractArray
|
||||
delete!(d, :seriestype)
|
||||
[begin
|
||||
dc = copy(d)
|
||||
dc[:seriestype] = sts[r,:]
|
||||
@@ -588,75 +589,15 @@ function prepared_object(plt::Plot)
|
||||
end
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
# plot to a Subplot
|
||||
|
||||
# function get_indices(orig, labels)
|
||||
# Int[findnext(labels, l, 1) for l in orig]
|
||||
# end
|
||||
|
||||
# # TODO: remove?? this is the old way of handling discrete data... should be
|
||||
# # replaced by the Axis type and logic
|
||||
# function setTicksFromStringVector(plt::Plot, d::KW, di::KW, letter)
|
||||
# sym = Symbol(letter)
|
||||
# ticksym = Symbol(letter * "ticks")
|
||||
# pargs = plt.attr
|
||||
# v = di[sym]
|
||||
#
|
||||
# # do we really want to do this?
|
||||
# typeof(v) <: AbstractArray || return
|
||||
# isempty(v) && return
|
||||
# trueOrAllTrue(_ -> typeof(_) <: AbstractString, v) || return
|
||||
#
|
||||
# # compute the ticks and labels
|
||||
# ticks, labels = if ticksType(pargs[ticksym]) == :ticks_and_labels
|
||||
# # extend the existing ticks and labels. only add to labels if they're new!
|
||||
# ticks, labels = pargs[ticksym]
|
||||
# newlabels = filter(_ -> !(_ in labels), unique(v))
|
||||
# newticks = if isempty(ticks)
|
||||
# collect(1:length(newlabels))
|
||||
# else
|
||||
# maximum(ticks) + collect(1:length(newlabels))
|
||||
# end
|
||||
# ticks = vcat(ticks, newticks)
|
||||
# labels = vcat(labels, newlabels)
|
||||
# ticks, labels
|
||||
# else
|
||||
# # create new ticks and labels
|
||||
# newlabels = unique(v)
|
||||
# collect(1:length(newlabels)), newlabels
|
||||
# end
|
||||
#
|
||||
# d[ticksym] = ticks, labels
|
||||
# plt.attr[ticksym] = ticks, labels
|
||||
#
|
||||
# # add an origsym field so that later on we can re-compute the x vector if ticks change
|
||||
# origsym = Symbol(letter * "orig")
|
||||
# di[origsym] = v
|
||||
# di[sym] = get_indices(v, labels)
|
||||
#
|
||||
# # loop through existing plt.seriesargs and adjust indices if there is an origsym key
|
||||
# for sargs in plt.seriesargs
|
||||
# if haskey(sargs, origsym)
|
||||
# # TODO: might need to call the setindex function instead to trigger a plot update for some backends??
|
||||
# sargs[sym] = get_indices(sargs[origsym], labels)
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
# function Base.copy(plt::Plot)
|
||||
# backend(plt.backend)
|
||||
# plt2 = plot(; plt.attr...)
|
||||
# for sargs in plt.seriesargs
|
||||
# sargs = filter((k,v) -> haskey(_series_defaults,k), sargs)
|
||||
# plot!(plt2; sargs...)
|
||||
# end
|
||||
# plt2
|
||||
# end
|
||||
function plot(sp::Subplot, args...; kw...)
|
||||
plt = sp.plt
|
||||
plot(plt, args...; kw..., subplot = findfirst(plt.subplots, sp))
|
||||
end
|
||||
function plot!(sp::Subplot, args...; kw...)
|
||||
plt = sp.plt
|
||||
plot!(plt, args...; kw..., subplot = findfirst(plt.subplots, sp))
|
||||
end
|
||||
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
+31
-50
@@ -98,14 +98,6 @@ end
|
||||
|
||||
# ----------------------------------------------------------------------------------
|
||||
|
||||
# abstract PlotRecipe
|
||||
|
||||
# getRecipeXY(recipe::PlotRecipe) = Float64[], Float64[]
|
||||
# getRecipeArgs(recipe::PlotRecipe) = ()
|
||||
|
||||
# plot(recipe::PlotRecipe, args...; kw...) = plot(getRecipeXY(recipe)..., args...; getRecipeArgs(recipe)..., kw...)
|
||||
# plot!(recipe::PlotRecipe, args...; kw...) = plot!(getRecipeXY(recipe)..., args...; getRecipeArgs(recipe)..., kw...)
|
||||
# plot!(plt::Plot, recipe::PlotRecipe, args...; kw...) = plot!(getRecipeXY(recipe)..., args...; getRecipeArgs(recipe)..., kw...)
|
||||
|
||||
num_series(x::AMat) = size(x,2)
|
||||
num_series(x) = 1
|
||||
@@ -113,63 +105,45 @@ num_series(x) = 1
|
||||
|
||||
RecipesBase.apply_recipe{T}(d::KW, ::Type{T}, plt::Plot) = throw(MethodError("Unmatched plot recipe: $T"))
|
||||
|
||||
# # if it's not a recipe, just do nothing and return the args
|
||||
# function RecipesBase.apply_recipe(d::KW, args...; issubplot=false)
|
||||
# if issubplot && !isempty(args) && !haskey(d, :n) && !haskey(d, :layout)
|
||||
# # put in a sensible default
|
||||
# d[:n] = maximum(map(num_series, args))
|
||||
# end
|
||||
# args
|
||||
# end
|
||||
|
||||
|
||||
if is_installed("DataFrames")
|
||||
@eval begin
|
||||
import DataFrames
|
||||
DFS = Union{Symbol, AbstractArray{Symbol}}
|
||||
|
||||
function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, dfs::DFS)
|
||||
if isa(dfs, Symbol)
|
||||
get!(d, Symbol(letter * "guide"), string(dfs))
|
||||
collect(df[dfs])
|
||||
else
|
||||
get!(d, :label, reshape(dfs, 1, length(dfs)))
|
||||
Any[collect(df[s]) for s in dfs]
|
||||
end
|
||||
# if it's one symbol, set the guide and return the column
|
||||
function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, sym::Symbol)
|
||||
get!(d, Symbol(letter * "guide"), string(sym))
|
||||
collect(df[sym])
|
||||
end
|
||||
|
||||
# if it's an array of symbols, set the labels and return a Vector{Any} of columns
|
||||
function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, syms::AbstractArray{Symbol})
|
||||
get!(d, :label, reshape(syms, 1, length(syms)))
|
||||
Any[collect(df[s]) for s in syms]
|
||||
end
|
||||
|
||||
# for anything else, no-op
|
||||
function handle_dfs(df::DataFrames.AbstractDataFrame, d::KW, letter, anything)
|
||||
anything
|
||||
end
|
||||
|
||||
# handle grouping by DataFrame column
|
||||
function extractGroupArgs(group::Symbol, df::DataFrames.AbstractDataFrame, args...)
|
||||
extractGroupArgs(collect(df[group]))
|
||||
end
|
||||
|
||||
|
||||
function handle_group(df::DataFrames.AbstractDataFrame, d::KW)
|
||||
if haskey(d, :group)
|
||||
g = d[:group]
|
||||
if isa(g, Symbol)
|
||||
d[:group] = collect(df[g])
|
||||
# if a DataFrame is the first arg, lets swap symbols out for columns
|
||||
@recipe function f(df::DataFrames.AbstractDataFrame, args...)
|
||||
# if any of these attributes are symbols, swap out for the df column
|
||||
for k in (:fillrange, :line_z, :marker_z, :markersize, :ribbon, :weights, :xerror, :yerror)
|
||||
if haskey(d, k) && isa(d[k], Symbol)
|
||||
d[k] = collect(df[d[k]])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@recipe function f(df::DataFrames.AbstractDataFrame, sy::DFS)
|
||||
handle_group(df, d)
|
||||
handle_dfs(df, d, "y", sy)
|
||||
end
|
||||
|
||||
@recipe function f(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS)
|
||||
handle_group(df, d)
|
||||
x = handle_dfs(df, d, "x", sx)
|
||||
y = handle_dfs(df, d, "y", sy)
|
||||
x, y
|
||||
end
|
||||
|
||||
@recipe function f(df::DataFrames.AbstractDataFrame, sx::DFS, sy::DFS, sz::DFS)
|
||||
handle_group(df, d)
|
||||
x = handle_dfs(df, d, "x", sx)
|
||||
y = handle_dfs(df, d, "y", sy)
|
||||
z = handle_dfs(df, d, "z", sz)
|
||||
x, y, z
|
||||
# return a list of new arguments
|
||||
tuple(Any[handle_dfs(df, d, (i==1 ? "x" : i==2 ? "y" : "z"), arg) for (i,arg) in enumerate(args)]...)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -747,7 +721,14 @@ end
|
||||
end
|
||||
@deps density path
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# contourf - filled contours
|
||||
|
||||
@recipe function f(::Type{Val{:contourf}}, x, y, z)
|
||||
fillrange := true
|
||||
seriestype := :contour
|
||||
()
|
||||
end
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Error Bars
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
|
||||
typealias FuncOrFuncs @compat(Union{Function, AVec{Function}})
|
||||
|
||||
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
|
||||
all3D(d::KW) = trueOrAllTrue(st -> st in (:contour, :contourf, :heatmap, :surface, :wireframe, :contour3d, :image), get(d, :seriestype, :none))
|
||||
|
||||
# missing
|
||||
convertToAnyVector(v::@compat(Void), d::KW) = Any[nothing], nothing
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ function should_add_to_legend(series::Series)
|
||||
series.d[:primary] && series.d[:label] != "" &&
|
||||
!(series.d[:seriestype] in (
|
||||
:hexbin,:histogram2d,:hline,:vline,
|
||||
:contour,:contour3d,:surface,:wireframe,
|
||||
:contour,:contourf,:contour3d,:surface,:wireframe,
|
||||
:heatmap, :pie, :image
|
||||
))
|
||||
end
|
||||
|
||||
+7
-6
@@ -83,12 +83,13 @@ function Plot()
|
||||
Subplot[], false)
|
||||
end
|
||||
|
||||
# TODO: make a decision... should plt[1] return the first subplot or the first series??
|
||||
# Base.getindex(plt::Plot, i::Integer) = plt.subplots[i]
|
||||
Base.getindex(plt::Plot, s::Symbol) = plt.spmap[s]
|
||||
Base.getindex(plt::Plot, r::Integer, c::Integer) = plt.layout[r,c]
|
||||
attr(plt::Plot, k::Symbol) = plt.attr[k]
|
||||
attr!(plt::Plot, v, k::Symbol) = (plt.attr[k] = v)
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
Base.getindex(plt::Plot, i::Integer) = plt.subplots[i]
|
||||
Base.getindex(plt::Plot, r::Integer, c::Integer) = plt.layout[r,c]
|
||||
# attr(plt::Plot, k::Symbol) = plt.attr[k]
|
||||
# attr!(plt::Plot, v, k::Symbol) = (plt.attr[k] = v)
|
||||
|
||||
Base.getindex(sp::Subplot, i::Integer) = series_list(sp)[i]
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
+1
-1
@@ -642,7 +642,7 @@ end
|
||||
# -------------------------------------------------------
|
||||
# indexing notation
|
||||
|
||||
Base.getindex(plt::Plot, i::Integer) = getxy(plt, i)
|
||||
# Base.getindex(plt::Plot, i::Integer) = getxy(plt, i)
|
||||
Base.setindex!{X,Y}(plt::Plot, xy::Tuple{X,Y}, i::Integer) = setxy!(plt, xy, i)
|
||||
Base.setindex!{X,Y,Z}(plt::Plot, xyz::Tuple{X,Y,Z}, i::Integer) = setxyz!(plt, xyz, i)
|
||||
|
||||
|
||||
+4
-3
@@ -22,7 +22,7 @@ default(size=(500,300))
|
||||
# TODO: use julia's Condition type and the wait() and notify() functions to initialize a Window, then wait() on a condition that
|
||||
# is referenced in a button press callback (the button clicked callback will call notify() on that condition)
|
||||
|
||||
const _current_plots_version = v"0.7.4"
|
||||
const _current_plots_version = v"0.7.5"
|
||||
|
||||
|
||||
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)
|
||||
@@ -41,9 +41,10 @@ function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = is
|
||||
fn = "ref$idx.png"
|
||||
|
||||
# firgure out version info
|
||||
G = glob(relpath(refdir) * "/*")
|
||||
G = glob(joinpath(relpath(refdir), "*"))
|
||||
# @show refdir fn G
|
||||
versions = map(fn -> VersionNumber(split(fn,"/")[end]), G)
|
||||
slash = (@windows ? "\\" : "/")
|
||||
versions = map(fn -> VersionNumber(split(fn, slash)[end]), G)
|
||||
versions = reverse(sort(versions))
|
||||
versions = filter(v -> v <= _current_plots_version, versions)
|
||||
# @show refdir fn versions
|
||||
|
||||
+2
-2
@@ -5,7 +5,7 @@ include("imgcomp.jl")
|
||||
# don't actually show the plots
|
||||
srand(1234)
|
||||
default(show=false, reuse=true)
|
||||
img_eps = 5e-2
|
||||
img_eps = isinteractive() ? 1e-2 : 10e-2
|
||||
|
||||
# facts("Gadfly") do
|
||||
# @fact gadfly() --> Plots.GadflyBackend()
|
||||
@@ -30,7 +30,7 @@ facts("GR") do
|
||||
@fact gr() --> Plots.GRBackend()
|
||||
@fact backend() --> Plots.GRBackend()
|
||||
|
||||
@linux_only image_comparison_facts(:gr, skip=[], eps=img_eps)
|
||||
@linux_only image_comparison_facts(:gr, skip=[30], eps=img_eps)
|
||||
end
|
||||
|
||||
facts("Plotly") do
|
||||
|
||||
Reference in New Issue
Block a user