diff --git a/src/args.jl b/src/args.jl index 8bb2d815..b543879d 100644 --- a/src/args.jl +++ b/src/args.jl @@ -40,8 +40,9 @@ const _allTypes = vcat([ :polygon => :shape, ) -ishistlike(lt::Symbol) = lt in (:hist, :density) -islinelike(lt::Symbol) = lt in (:line, :path, :steppre, :steppost) +like_histogram(linetype::Symbol) = linetype in (:hist, :density) +like_line(linetype::Symbol) = linetype in (:line, :path, :steppre, :steppost) +like_surface(linetype::Symbol) = linetype in (:contour, :heatmap, :surface, :wireframe) const _allStyles = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot] diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index aee0a3b8..6ec70367 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -347,7 +347,7 @@ function _add_series(pkg::PyPlotBackend, plt::Plot; kw...) # NOTE: this is unsupported because it does the wrong thing... it shifts the whole axis # extra_kwargs[:bottom] = d[:fill] - if ishistlike(lt) + if like_histogram(lt) extra_kwargs[:bins] = d[:nbins] extra_kwargs[:normed] = lt == :density else @@ -434,7 +434,7 @@ function _add_series(pkg::PyPlotBackend, plt::Plot; kw...) end # do the plot - d[:serieshandle] = if ishistlike(lt) + d[:serieshandle] = if like_histogram(lt) plotfunc(d[:y]; extra_kwargs...)[1] elseif lt == :contour diff --git a/src/components.jl b/src/components.jl index 3b413e2f..9a676336 100644 --- a/src/components.jl +++ b/src/components.jl @@ -6,6 +6,23 @@ end get_xs(shape::Shape) = Float64[v[1] for v in shape.vertices] get_ys(shape::Shape) = Float64[v[2] for v in shape.vertices] +function shape_coords(shape::Shape) + unzip(shape.vertices) +end + +function shape_coords(shapes::AVec{Shape}) + length(shapes) == 0 && return zeros(0), zeros(0) + xs = map(get_xs, shapes) + ys = map(get_ys, shapes) + x, y = unzip(shapes[1].vertices) + for shape in shapes[2:end] + tmpx, tmpy = unzip(shape.vertices) + x = vcat(x, NaN, tmpx) + y = vcat(y, NaN, tmpy) + end + x, y +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)] @@ -235,8 +252,10 @@ end # ----------------------------------------------------------------------- +abstract AbstractSurface + "represents a contour or surface mesh" -immutable Surface{M<:AMat} +immutable Surface{M<:AMat} <: AbstractSurface # x::AVec # y::AVec surf::M @@ -251,6 +270,12 @@ for f in (:length, :size) end Base.copy(surf::Surface) = Surface(copy(surf.surf)) + +"For the case of representing a surface as a function of x/y... can possibly avoid allocations." +immutable SurfaceFunction <: AbstractSurface + f::Function +end + # ----------------------------------------------------------------------- type OHLC{T<:Real} diff --git a/src/plot.jl b/src/plot.jl index daa991fb..215f3f35 100644 --- a/src/plot.jl +++ b/src/plot.jl @@ -88,7 +88,12 @@ function plot!(plt::Plot, args...; kw...) _before_add_series(plt) # get the list of dictionaries, one per series - seriesArgList, xmeta, ymeta = build_series_args(plt, groupargs..., args...; d...) + @show groupargs args + dumpdict(d, "before process_inputs") + process_inputs(plt, d, groupargs..., args...) + dumpdict(d, "after process_inputs") + seriesArgList, xmeta, ymeta = build_series_args(plt, d) + # seriesArgList, xmeta, ymeta = build_series_args(plt, groupargs..., args...; d...) # if we were able to extract guide information from the series inputs, then update the plot # @show xmeta, ymeta diff --git a/src/series_args.jl b/src/series_args.jl index 5e0e1bd3..50d8a964 100644 --- a/src/series_args.jl +++ b/src/series_args.jl @@ -77,8 +77,9 @@ compute_x(x::Void, y, z) = 1:size(y,1) compute_x(x::Function, y, z) = map(x, y) compute_x(x, y, z) = x +compute_y(x::Void, y::Function, z) = error() compute_y(x::Void, y::Void, z) = 1:size(z,2) -compute_y(x::Void, y, z) = 1:size(x,1) +# compute_y(x::Void, y, z) = 1:size(z,2) compute_y(x, y::Function, z) = map(y, x) compute_y(x, y, z) = y @@ -120,10 +121,14 @@ function build_series_args(plt::AbstractPlot, kw::KW) # build the series arg dict numUncounted = pop!(d, :numUncounted, 0) n = plt.n + i + numUncounted + dumpdict(d, "before getSeriesArgs") d = getSeriesArgs(plt.backend, getplotargs(plt, n), d, i + numUncounted, convertSeriesIndex(plt, n), n) dumpdict(d, "after getSeriesArgs") + + @show xs[mod1(i,mx)] ys[mod1(i,my)] zs[mod1(i,mz)] d[:x], d[:y], d[:z] = compute_xyz(xs[mod1(i,mx)], ys[mod1(i,my)], zs[mod1(i,mz)]) + @show d[:x] d[:y] d[:z] # # NOTE: this should be handled by the time it gets here # lt = d[:linetype] @@ -172,10 +177,21 @@ function build_series_args(plt::AbstractPlot, kw::KW) end +# -------------------------------------------------------------------- +# process_inputs +# -------------------------------------------------------------------- + +# These methods take a plot and the keyword arguments, and processes the input +# arguments (x/y/z, group, etc), populating the KW dict with appropriate values. + # -------------------------------------------------------------------- # 0 arguments # -------------------------------------------------------------------- +# don't do anything +function process_inputs(plt::AbstractPlot, d::KW) +end + # # TODO: all methods should probably do this... check for (and pop!) x/y/z values if they exist # # function build_series_args(plt::AbstractPlot, d::KW) @@ -205,118 +221,109 @@ end # -------------------------------------------------------------------- # no special handling... assume x and z are nothing -function build_series_args(plt::AbstractPlot, d::KW, y) - build_series_args(plt, d, nothing, y, nothing) +function process_inputs(plt::AbstractPlot, d::KW, y) + d[:y] = y end # matrix... is it z or y? -function build_series_args{T<:Number}(plt::AbstractPlot, d::KW, mat::AMat{T}) +function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, mat::AMat{T}) if all3D(d) n,m = size(mat) - build_series_args(plt, d, 1:n, 1:m, mat) + d[:x], d[:y], d[:z] = 1:n, 1:m, mat else - build_series_args(plt, d, nothing, mat, nothing) + d[:y] = mat end end + # plotting arbitrary shapes/polygons -function build_series_args(plt::AbstractPlot, d::KW, shape::Shape) - x, y = unzip(shape.vertices) - build_series_args(plt, d, x, y; linetype = :shape) +function process_inputs(plt::AbstractPlot, d::KW, shape::Shape) + d[:x], d[:y] = shape_coords(shape) + d[:linetype] = :shape end - -function shape_coords(shapes::AVec{Shape}) - xs = map(get_xs, shapes) - ys = map(get_ys, shapes) - x, y = unzip(shapes[1].vertices) - for shape in shapes[2:end] - tmpx, tmpy = unzip(shape.vertices) - x = vcat(x, NaN, tmpx) - y = vcat(y, NaN, tmpy) - end - x, y +function process_inputs(plt::AbstractPlot, d::KW, shapes::AVec{Shape}) + d[:x], d[:y] = shape_coords(shapes) + d[:linetype] = :shape end - -function build_series_args(plt::AbstractPlot, d::KW, shapes::AVec{Shape}) - x, y = shape_coords(shapes) - build_series_args(plt, d, x, y; linetype = :shape) -end -function build_series_args(plt::AbstractPlot, d::KW, shapes::AMat{Shape}) +function process_inputs(plt::AbstractPlot, d::KW, shapes::AMat{Shape}) x, y = [], [] for j in 1:size(shapes, 2) tmpx, tmpy = shape_coords(vec(shapes[:,j])) push!(x, tmpx) push!(y, tmpy) end - build_series_args(plt, d, x, y; linetype = :shape) + d[:x], d[:y] = x, y + d[:linetype] = :shape end -function build_series_args(plt::AbstractPlot, d::KW, f::FuncOrFuncs) - build_series_args(plt, d, f, xmin(plt), xmax(plt)) + +# function without range... use the current range of the x-axis +function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs) + process_inputs(plt, d, f, xmin(plt), xmax(plt)) end # -------------------------------------------------------------------- # 2 arguments # -------------------------------------------------------------------- -function build_series_args(plt::AbstractPlot, d::KW, x, y) - build_series_args(plt, d, x, y, nothing) +function process_inputs(plt::AbstractPlot, d::KW, x, y) + d[:x], d[:y] = x, y end -# list of functions -function build_series_args(plt::AbstractPlot, d::KW, f::FuncOrFuncs, x) +# if functions come first, just swap the order (not to be confused with parametric functions... +# as there would be more than one function passed in) +function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs, x) @assert !(typeof(x) <: FuncOrFuncs) # otherwise we'd hit infinite recursion here - build_series_args(plt, d, x, f) + process_inputs(plt, d, x, f) end # -------------------------------------------------------------------- # 3 arguments # -------------------------------------------------------------------- +# no special handling... just pass them through +function process_inputs(plt::AbstractPlot, d::KW, x, y, z) + d[:x], d[:y], d[:z] = x, y, z +end + # 3d line or scatter -function build_series_args(plt::AbstractPlot, d::KW, x::AVec, y::AVec, zvec::AVec) - d = KW(kw) +function process_inputs(plt::AbstractPlot, d::KW, x::AVec, y::AVec, zvec::AVec) + # default to path3d if we haven't set a 3d linetype if !(get(d, :linetype, :none) in _3dTypes) d[:linetype] = :path3d end - build_series_args(plt, d, x, y; z=zvec, d...) + d[:x], d[:y], d[:z] = x, y, z end -# contours or surfaces... function grid -function build_series_args(plt::AbstractPlot, d::KW, x::AVec, y::AVec, zf::Function) - # only allow sorted x/y for now - # TODO: auto sort x/y/z properly - @assert x == sort(x) - @assert y == sort(y) - surface = Float64[zf(xi, yi) for xi in x, yi in y] - build_series_args(plt, d, x, y, surface) # passes it to the zmat version +# surface-like... function +function process_inputs(plt::AbstractPlot, d::KW, x::AVec, y::AVec, zf::Function) + x, y = sort(x), sort(y) + d[:z] = Surface(zf, x, y) # TODO: replace with SurfaceFunction when supported + d[:x], d[:y] = x, y end -# contours or surfaces... matrix grid -function build_series_args{T<:Number}(plt::AbstractPlot, x::AVec, y::AVec, zmat::AMat{T}) - # only allow sorted x/y for now - # TODO: auto sort x/y/z properly - @assert x == sort(x) - @assert y == sort(y) +# surface-like... matrix grid +function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, x::AVec, y::AVec, zmat::AMat{T}) @assert size(zmat) == (length(x), length(y)) - d = KW(kw) - d[:z] = Surface(convert(Matrix{Float64}, zmat)) - if !(get(d, :linetype, :none) in (:contour, :heatmap, :surface, :wireframe)) + if !issorted(x) || !issorted(y) + x_idx = sortperm(x) + y_idx = sortperm(y) + x, y = x[x_idx], y[y_idx] + zmat = z[x_idx, y_idx] + end + d[:x], d[:y], d[:z] = x, y, Surface{Matrix{Float64}}(zmat) + if !like_surface(get(d, :linetype, :none)) d[:linetype] = :contour end - build_series_args(plt, d, x, y; d...) #, z = surf) end -# contours or surfaces... general x, y grid -function build_series_args{T<:Number}(plt::AbstractPlot, x::AMat{T}, y::AMat{T}, zmat::AMat{T}) +# surfaces-like... general x, y grid +function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, x::AMat{T}, y::AMat{T}, zmat::AMat{T}) @assert size(zmat) == size(x) == size(y) - surf = Surface(convert(Matrix{Float64}, zmat)) - d = KW(kw) - d[:z] = Surface(convert(Matrix{Float64}, zmat)) - if !(get(d, :linetype, :none) in (:contour, :heatmap, :surface, :wireframe)) + d[:x], d[:y], d[:z] = Any[x], Any[y], Surface{Matrix{Float64}}(zmat) + if !like_surface(get(d, :linetype, :none)) d[:linetype] = :contour end - build_series_args(plt, d, Any[x], Any[y]; d...) #kw..., z = surf, linetype = :contour) end @@ -325,57 +332,74 @@ end # -------------------------------------------------------------------- # special handling... xmin/xmax with function(s) -function build_series_args(plt::AbstractPlot, d::KW, f::FuncOrFuncs, xmin::Number, xmax::Number) +function process_inputs(plt::AbstractPlot, d::KW, f::FuncOrFuncs, xmin::Number, xmax::Number) width = get(plt.plotargs, :size, (100,))[1] - x = collect(linspace(xmin, xmax, width)) # we don't need more than the width - build_series_args(plt, d, x, f) + x = linspace(xmin, xmax, width) + process_inputs(plt, d, x, f) end - # special handling... xmin/xmax with parametric function(s) -build_series_args{T<:Number}(plt::AbstractPlot, fx::FuncOrFuncs, fy::FuncOrFuncs, u::AVec{T}) = build_series_args(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)) -build_series_args{T<:Number}(plt::AbstractPlot, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs) = build_series_args(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)) -build_series_args(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, umin::Number, umax::Number, numPoints::Int = 1000) = build_series_args(plt, d, fx, fy, linspace(umin, umax, numPoints)) +process_inputs{T<:Number}(plt::AbstractPlot, fx::FuncOrFuncs, fy::FuncOrFuncs, u::AVec{T}) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)) +process_inputs{T<:Number}(plt::AbstractPlot, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u)) +process_inputs(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, umin::Number, umax::Number, numPoints::Int = 1000) = process_inputs(plt, d, fx, fy, linspace(umin, umax, numPoints)) # special handling... 3D parametric function(s) -build_series_args{T<:Number}(plt::AbstractPlot, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, u::AVec{T}) = build_series_args(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u)) -build_series_args{T<:Number}(plt::AbstractPlot, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs) = build_series_args(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u)) -build_series_args(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, umin::Number, umax::Number, numPoints::Int = 1000) = build_series_args(plt, d, fx, fy, fz, linspace(umin, umax, numPoints)) +process_inputs{T<:Number}(plt::AbstractPlot, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, u::AVec{T}) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u)) +process_inputs{T<:Number}(plt::AbstractPlot, u::AVec{T}, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs) = process_inputs(plt, d, mapFuncOrFuncs(fx, u), mapFuncOrFuncs(fy, u), mapFuncOrFuncs(fz, u)) +process_inputs(plt::AbstractPlot, d::KW, fx::FuncOrFuncs, fy::FuncOrFuncs, fz::FuncOrFuncs, umin::Number, umax::Number, numPoints::Int = 1000) = process_inputs(plt, d, fx, fy, fz, linspace(umin, umax, numPoints)) # -------------------------------------------------------------------- # Lists of tuples and FixedSizeArrays # -------------------------------------------------------------------- +# if we get an unhandled tuple, just splat it in +function process_inputs(plt::AbstractPlot, d::KW, tup::Tuple) + process_inputs(plt, d, tup...) +end + # (x,y) tuples -function build_series_args{R1<:Number,R2<:Number}(plt::AbstractPlot, xy::AVec{Tuple{R1,R2}}) - build_series_args(plt, d, unzip(xy)...) +function process_inputs{R1<:Number,R2<:Number}(plt::AbstractPlot, d::KW, xy::AVec{Tuple{R1,R2}}) + process_inputs(plt, d, unzip(xy)...) end -function build_series_args{R1<:Number,R2<:Number}(plt::AbstractPlot, xy::Tuple{R1,R2}) - build_series_args(plt, d, [xy[1]], [xy[2]]) +function process_inputs{R1<:Number,R2<:Number}(plt::AbstractPlot, d::KW, xy::Tuple{R1,R2}) + process_inputs(plt, d, [xy[1]], [xy[2]]) end - -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 build_series_args{T<:Number}(plt::AbstractPlot, xy::AVec{FixedSizeArrays.Vec{2,T}}) - build_series_args(plt, d, unzip(xy)...) +# (x,y,z) tuples +function process_inputs{R1<:Number,R2<:Number,R3<:Number}(plt::AbstractPlot, d::KW, xyz::AVec{Tuple{R1,R2,R3}}) + process_inputs(plt, d, unzip(xyz)...) +end +function process_inputs{R1<:Number,R2<:Number,R3<:Number}(plt::AbstractPlot, d::KW, xyz::Tuple{R1,R2,R3}) + process_inputs(plt, d, [xyz[1]], [xyz[2]], [xyz[3]]) end -function build_series_args{T<:Number}(plt::AbstractPlot, xy::FixedSizeArrays.Vec{2,T}) - build_series_args(plt, d, [xy[1]], [xy[2]]) +# 2D FixedSizeArrays +function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xy::AVec{FixedSizeArrays.Vec{2,T}}) + process_inputs(plt, d, unzip(xy)...) +end +function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xy::FixedSizeArrays.Vec{2,T}) + process_inputs(plt, d, [xy[1]], [xy[2]]) +end + +# 3D FixedSizeArrays +function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xyz::AVec{FixedSizeArrays.Vec{3,T}}) + process_inputs(plt, d, unzip(xyz)...) +end +function process_inputs{T<:Number}(plt::AbstractPlot, d::KW, xyz::FixedSizeArrays.Vec{3,T}) + process_inputs(plt, d, [xyz[1]], [xyz[2]], [xyz[3]]) end # -------------------------------------------------------------------- # handle grouping # -------------------------------------------------------------------- -function build_series_args(plt::AbstractPlot, d::KW, groupby::GroupBy, args...) +function process_inputs(plt::AbstractPlot, d::KW, groupby::GroupBy, args...) ret = Any[] + error("unfinished after series reorg") for (i,glab) in enumerate(groupby.groupLabels) # TODO: don't automatically overwrite labels - kwlist, xmeta, ymeta = build_series_args(plt, d, args..., + kwlist, xmeta, ymeta = process_inputs(plt, d, args..., idxfilter = groupby.groupIds[i], label = string(glab), numUncounted = length(ret)) # we count the idx from plt.n + numUncounted + i @@ -391,8 +415,13 @@ end function setup_dataframes() @require DataFrames begin - function build_series_args(plt::AbstractPlot, d::KW, df::DataFrames.AbstractDataFrame, args...) - build_series_args(plt, d, args..., dataframe = df) + # function process_inputs(plt::AbstractPlot, d::KW, df::DataFrames.AbstractDataFrame, args...) + # process_inputs(plt, d, args..., dataframe = df) + # end + + function process_inputs(plt::AbstractPlot, d::KW, df::DataFrames.AbstractDataFrame, args...) + d[:dataframe] = df + process_inputs(plt, d, args...) end # expecting the column name of a dataframe that was passed in... anything else should error diff --git a/src/subplot.jl b/src/subplot.jl index bbe4e244..1ffa8a67 100644 --- a/src/subplot.jl +++ b/src/subplot.jl @@ -209,8 +209,9 @@ function subplot!(subplt::Subplot, args...; kw...) delete!(d, :group) end - - kwList, xmeta, ymeta = build_series_args(subplt, groupargs..., args...; d...) + process_inputs(subplt, d, groupargs..., args...) + kwList, xmeta, ymeta = build_series_args(subplt, d) + # kwList, xmeta, ymeta = build_series_args(subplt, groupargs..., args...; d...) # TODO: something useful with meta info? diff --git a/src/utils.jl b/src/utils.jl index b75f93cc..45ba9501 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -121,19 +121,24 @@ 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 +get_mod(v, idx::Int) = v makevec(v::AVec) = v makevec{T}(v::T) = T[v] "duplicate a single value, or pass the 2-tuple through" -maketuple(x::Real) = (x,x) +maketuple(x::Real) = (x,x) maketuple{T,S}(x::@compat(Tuple{T,S})) = x -mapFuncOrFuncs(f::Function, u::AVec) = map(f, u) +mapFuncOrFuncs(f::Function, u::AVec) = map(f, u) mapFuncOrFuncs(fs::AVec{Function}, u::AVec) = [map(f, u) for f in fs] -unzip{T,S}(v::AVec{@compat(Tuple{T,S})}) = [vi[1] for vi in v], [vi[2] for vi in v] +unzip{T,S}(xy::AVec{Tuple{T,S}}) = [x[1] for x in xy], [y[2] for y in xy] +unzip{T,S,R}(xyz::AVec{Tuple{T,S,R}}) = [x[1] for x in xyz], [y[2] for y in xyz], [z[3] for z in xyz] +unzip{T}(xy::AVec{FixedSizeArrays.Vec{2,T}}) = T[x[1] for x in xy], T[y[2] for y in xy] +unzip{T}(xy::FixedSizeArrays.Vec{2,T}) = T[xy[1]], T[xy[2]] +unzip{T}(xyz::AVec{FixedSizeArrays.Vec{3,T}}) = T[x[1] for x in xyz], T[y[2] for y in xyz], T[z[3] for z in xyz] +unzip{T}(xyz::FixedSizeArrays.Vec{3,T}) = T[xyz[1]], T[xyz[2]], T[xyz[3]] # given 2-element lims and a vector of data x, widen lims to account for the extrema of x function _expand_limits(lims, x) @@ -203,29 +208,29 @@ isijulia() = isdefined(Main, :IJulia) && Main.IJulia.inited isatom() = isdefined(Main, :Atom) && Atom.isconnected() istuple(::Tuple) = true -istuple(::Any) = false +istuple(::Any) = false isvector(::AVec) = true -isvector(::Any) = false +isvector(::Any) = false ismatrix(::AMat) = true -ismatrix(::Any) = false +ismatrix(::Any) = false isscalar(::Real) = true -isscalar(::Any) = false +isscalar(::Any) = false # ticksType{T<:Real,S<:Real}(ticks::@compat(Tuple{T,S})) = :limits -ticksType{T<:Real}(ticks::AVec{T}) = :ticks -ticksType{T<:AbstractString}(ticks::AVec{T}) = :labels -ticksType{T<:AVec,S<:AVec}(ticks::@compat(Tuple{T,S})) = :ticks_and_labels -ticksType(ticks) = :invalid +ticksType{T<:Real}(ticks::AVec{T}) = :ticks +ticksType{T<:AbstractString}(ticks::AVec{T}) = :labels +ticksType{T<:AVec,S<:AVec}(ticks::@compat(Tuple{T,S})) = :ticks_and_labels +ticksType(ticks) = :invalid -limsType{T<:Real,S<:Real}(lims::@compat(Tuple{T,S})) = :limits -limsType(lims::Symbol) = lims == :auto ? :auto : :invalid -limsType(lims) = :invalid +limsType{T<:Real,S<:Real}(lims::@compat(Tuple{T,S})) = :limits +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}(::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] Base.merge(a::AbstractVector, b::AbstractVector) = sort(unique(vcat(a,b))) @@ -238,14 +243,14 @@ wraptuple(x) = (x,) trueOrAllTrue(f::Function, x::AbstractArray) = all(f, x) trueOrAllTrue(f::Function, x) = f(x) -allLineTypes(arg) = trueOrAllTrue(a -> get(_typeAliases, a, a) in _allTypes, arg) -allStyles(arg) = trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg) -allShapes(arg) = trueOrAllTrue(a -> get(_markerAliases, a, a) in _allMarkers, arg) || - trueOrAllTrue(a -> isa(a, Shape), arg) -allAlphas(arg) = trueOrAllTrue(a -> (typeof(a) <: Real && a > 0 && a < 1) || - (typeof(a) <: AbstractFloat && (a == zero(typeof(a)) || a == one(typeof(a)))), arg) -allReals(arg) = trueOrAllTrue(a -> typeof(a) <: Real, arg) -allFunctions(arg) = trueOrAllTrue(a -> isa(a, Function), arg) +allLineTypes(arg) = trueOrAllTrue(a -> get(_typeAliases, a, a) in _allTypes, arg) +allStyles(arg) = trueOrAllTrue(a -> get(_styleAliases, a, a) in _allStyles, arg) +allShapes(arg) = trueOrAllTrue(a -> get(_markerAliases, a, a) in _allMarkers, arg) || + trueOrAllTrue(a -> isa(a, Shape), arg) +allAlphas(arg) = trueOrAllTrue(a -> (typeof(a) <: Real && a > 0 && a < 1) || + (typeof(a) <: AbstractFloat && (a == zero(typeof(a)) || a == one(typeof(a)))), arg) +allReals(arg) = trueOrAllTrue(a -> typeof(a) <: Real, arg) +allFunctions(arg) = trueOrAllTrue(a -> isa(a, Function), arg) # --------------------------------------------------------------- @@ -429,11 +434,11 @@ end # used in updating an existing series extendSeriesByOne(v::UnitRange{Int}, n::Int = 1) = isempty(v) ? (1:n) : (minimum(v):maximum(v)+n) -extendSeriesByOne(v::AVec, n::Integer = 1) = isempty(v) ? (1:n) : vcat(v, (1:n) + maximum(v)) -extendSeriesData{T}(v::Range{T}, z::Real) = extendSeriesData(float(collect(v)), z) -extendSeriesData{T}(v::Range{T}, z::AVec) = extendSeriesData(float(collect(v)), z) -extendSeriesData{T}(v::AVec{T}, z::Real) = (push!(v, convert(T, z)); v) -extendSeriesData{T}(v::AVec{T}, z::AVec) = (append!(v, convert(Vector{T}, z)); v) +extendSeriesByOne(v::AVec, n::Integer = 1) = isempty(v) ? (1:n) : vcat(v, (1:n) + maximum(v)) +extendSeriesData{T}(v::Range{T}, z::Real) = extendSeriesData(float(collect(v)), z) +extendSeriesData{T}(v::Range{T}, z::AVec) = extendSeriesData(float(collect(v)), z) +extendSeriesData{T}(v::AVec{T}, z::Real) = (push!(v, convert(T, z)); v) +extendSeriesData{T}(v::AVec{T}, z::AVec) = (append!(v, convert(Vector{T}, z)); v) # --------------------------------------------------------------- @@ -453,22 +458,15 @@ function supportGraph(allvals, func) end end n = length(vals) - - scatter(x,y, - m=:rect, - ms=10, - size=(300,100+18*n), - # xticks=(collect(1:length(bs)), bs), - leg=false - ) + scatter(x, y, m=:rect, ms=10, size=(300,100+18*n), leg=false) end -supportGraphArgs() = supportGraph(_allArgs, supportedArgs) -supportGraphTypes() = supportGraph(_allTypes, supportedTypes) -supportGraphStyles() = supportGraph(_allStyles, supportedStyles) +supportGraphArgs() = supportGraph(_allArgs, supportedArgs) +supportGraphTypes() = supportGraph(_allTypes, supportedTypes) +supportGraphStyles() = supportGraph(_allStyles, supportedStyles) supportGraphMarkers() = supportGraph(_allMarkers, supportedMarkers) -supportGraphScales() = supportGraph(_allScales, supportedScales) -supportGraphAxes() = supportGraph(_allAxes, supportedAxes) +supportGraphScales() = supportGraph(_allScales, supportedScales) +supportGraphAxes() = supportGraph(_allAxes, supportedAxes) function dumpSupportGraphs() for func in (supportGraphArgs, supportGraphTypes, supportGraphStyles, @@ -483,16 +481,18 @@ end # Some conversion functions # note: I borrowed these conversion constants from Compose.jl's Measure -const PX_PER_INCH = 100 -const DPI = PX_PER_INCH -const MM_PER_INCH = 25.4 -const MM_PER_PX = MM_PER_INCH / PX_PER_INCH -inch2px(inches::Real) = float(inches * PX_PER_INCH) -px2inch(px::Real) = float(px / PX_PER_INCH) -inch2mm(inches::Real) = float(inches * MM_PER_INCH) -mm2inch(mm::Real) = float(mm / MM_PER_INCH) -px2mm(px::Real) = float(px * MM_PER_PX) -mm2px(mm::Real) = float(px / MM_PER_PX) + +const PX_PER_INCH = 100 +const DPI = PX_PER_INCH +const MM_PER_INCH = 25.4 +const MM_PER_PX = MM_PER_INCH / PX_PER_INCH + +inch2px(inches::Real) = float(inches * PX_PER_INCH) +px2inch(px::Real) = float(px / PX_PER_INCH) +inch2mm(inches::Real) = float(inches * MM_PER_INCH) +mm2inch(mm::Real) = float(mm / MM_PER_INCH) +px2mm(px::Real) = float(px * MM_PER_PX) +mm2px(mm::Real) = float(px / MM_PER_PX) "Smallest x in plot"