diff --git a/REQUIRE b/REQUIRE index 04b7f31e..92655edd 100644 --- a/REQUIRE +++ b/REQUIRE @@ -3,3 +3,4 @@ julia 0.4 Colors Reexport Compat +Requires diff --git a/src/Plots.jl b/src/Plots.jl index 8fbb37f9..7f4f4501 100644 --- a/src/Plots.jl +++ b/src/Plots.jl @@ -6,6 +6,7 @@ module Plots using Compat using Reexport @reexport using Colors +using Requires export Plot, @@ -114,6 +115,7 @@ export Animation, frame, gif, + @animate, # recipes PlotRecipe, diff --git a/src/animation.jl b/src/animation.jl index 5122000f..02c5e746 100644 --- a/src/animation.jl +++ b/src/animation.jl @@ -51,3 +51,36 @@ end function Base.writemime(io::IO, ::MIME"text/html", agif::AnimatedGif) write(io, "\" />") end + + +# ----------------------------------------------- + +""" +Collect one frame per for-block iteration and return an `Animation` object. + +Example: + +``` + p = plot(1) + anim = @animate for x=0:0.1:5 + push!(p, 1, sin(x)) + end +``` +""" +macro animate(forloop::Expr) + if forloop.head != :for + error("@animate macro expects a for-block. got: $(forloop.head)") + end + + # add the call to frame to the end of each iteration + animsym = gensym("anim") + block = forloop.args[2] + push!(block.args, :(frame($animsym))) + + # full expression: + esc(quote + $animsym = Animation() # init animation object + $forloop # for loop, saving a frame after each iteration + $animsym # return the animation object + end) +end diff --git a/src/backends/gadfly.jl b/src/backends/gadfly.jl index 620d20b1..bf8ca178 100644 --- a/src/backends/gadfly.jl +++ b/src/backends/gadfly.jl @@ -234,7 +234,7 @@ end function addToGadflyLegend(plt::Plot, d::Dict) # add the legend? - if plt.plotargs[:legend] != :none + if plt.plotargs[:legend] != :none && d[:label] != "" gplt = getGadflyContext(plt) # add the legend if needed diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 200701e3..7fbc1fab 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -687,6 +687,7 @@ function addPyPlotLegend(plt::Plot, ax) if leg != :none # gotta do this to ensure both axes are included args = filter(x -> !(x[:linetype] in (:hist,:density,:hexbin,:heatmap,:hline,:vline,:contour, :surface, :wireframe, :path3d, :scatter3d)), plt.seriesargs) + args = filter(x -> x[:label] != "", args) if length(args) > 0 leg = ax[:legend]([d[:serieshandle] for d in args], [d[:label] for d in args], diff --git a/src/plot.jl b/src/plot.jl index 8a1d1433..e1a6e09a 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -437,6 +437,25 @@ createKWargsList{T<:Real}(plt::PlottingObject, fx::FuncOrFuncs, fy::FuncOrFuncs, createKWargsList{T<:Real}(plt::PlottingObject, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs; kw...) = createKWargsList(plt, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u); kw...) createKWargsList(plt::PlottingObject, fx::FuncOrFuncs, fy::FuncOrFuncs, umin::Real, umax::Real, numPoints::Int = 1000; kw...) = createKWargsList(plt, fx, fy, linspace(umin, umax, numPoints); kw...) +# (x,y) tuples +function createKWargsList{R1<:Real,R2<:Real}(plt::PlottingObject, xy::AVec{Tuple{R1,R2}}; kw...) + createKWargsList(plt, unzip(xy)...; kw...) +end +function createKWargsList{R1<:Real,R2<:Real}(plt::PlottingObject, xy::Tuple{R1,R2}; kw...) + createKWargsList(plt, [xy[1]], [xy[2]]; kw...) +end + +@require FixedSizeArrays begin + unzip{T}(x::AVec{FixedSizeArrays.Vec{2,T}}) = T[xi[1] for xi in x], T[xi[2] for xi in x] + unzip{T}(x::FixedSizeArrays.Vec{2,T}) = T[x[1]], T[x[2]] + + function createKWargsList{T<:Real}(plt::PlottingObject, xy::AVec{FixedSizeArrays.Vec{2,T}}; kw...) + createKWargsList(plt, unzip(xy)...; kw...) + end + function createKWargsList{T<:Real}(plt::PlottingObject, xy::FixedSizeArrays.Vec{2,T}; kw...) + createKWargsList(plt, [xy[1]], [xy[2]]; kw...) + end +end # special handling... no args... 1 series diff --git a/test/REQUIRE b/test/REQUIRE index 9ad44a64..17a29ad5 100644 --- a/test/REQUIRE +++ b/test/REQUIRE @@ -2,6 +2,7 @@ julia 0.4 Colors Reexport +Requires FactCheck Gadfly Images