support for contours in gadfly/immerse/pyplot

This commit is contained in:
Thomas Breloff 2015-10-26 18:07:22 -04:00
parent 614c5f694b
commit 9ea0585d71
8 changed files with 84 additions and 46 deletions

View File

@ -4,7 +4,6 @@ os:
- linux
- osx
julia:
- 0.3
- 0.4
#- nightly
notifications:
@ -17,5 +16,5 @@ script:
- julia -e 'Pkg.clone("Cairo"); Pkg.build("Cairo")'
- julia -e 'ENV["PYTHON"] = ""; Pkg.clone("PyPlot"); Pkg.build("PyPlot")'
- julia -e 'Pkg.clone(pwd()); Pkg.build("Plots")'
- julia -e 'Pkg.test("Plots"; coverage=true)'
- julia -e 'Pkg.test("Plots"; coverage=false)'
# - julia -e 'cd(Pkg.dir("Plots")); Pkg.add("Coverage"); using Coverage; Coveralls.submit(process_folder()); Codecov.submit(process_folder())'

View File

@ -1,4 +1,4 @@
julia 0.3
julia 0.4
Colors
Reexport

View File

@ -8,7 +8,7 @@ const _allAxes = [:auto, :left, :right]
)
const _allTypes = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
:heatmap, :hexbin, :hist, :bar, :hline, :vline, :ohlc]
:heatmap, :hexbin, :hist, :bar, :hline, :vline, :ohlc, :contour]
@compat const _typeAliases = Dict(
:n => :none,
:no => :none,
@ -26,6 +26,7 @@ const _allTypes = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
:stems => :sticks,
:dots => :scatter,
:histogram => :hist,
:contours => :contours,
)
const _allStyles = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
@ -130,6 +131,8 @@ _seriesDefaults[:z] = nothing # depth for contour, color sca
# _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
const _plotDefaults = Dict{Symbol, Any}()

View File

@ -39,6 +39,8 @@ function getLineGeom(d::Dict)
Gadfly.Geom.hline(color = getColor(d[:color]), size = d[:linewidth] * Gadfly.px)
elseif lt == :vline
Gadfly.Geom.vline(color = getColor(d[:color]), size = d[:linewidth] * Gadfly.px)
elseif lt == :contour
Gadfly.Geom.contour(levels = d[:nlevels])
else
nothing
end
@ -94,6 +96,8 @@ function addGadflyLine!(plt::Plot, d::Dict, geoms...)
w = 0.01 * mean(diff(d[:x]))
kwargs[:xmin] = d[:x] - w
kwargs[:xmax] = d[:x] + w
elseif lt == :contour
kwargs[:z] = d[:surface]
end
# add the layer
@ -224,7 +228,7 @@ function addGadflySeries!(plt::Plot, d::Dict)
prepend!(layers, addGadflyMarker!(plt, d, plt.initargs, smooth...))
end
lt in (:hist, :heatmap, :hexbin) || addToGadflyLegend(plt, d)
lt in (:hist, :heatmap, :hexbin, :contour) || addToGadflyLegend(plt, d)
# now save the layers that apply to this series
d[:gadflylayers] = layers

View File

@ -8,10 +8,10 @@ getPyPlotColor(c::Colorant) = map(f->float(f(c)), (red, green, blue, alpha))
getPyPlotColor(scheme::ColorScheme) = getPyPlotColor(getColor(scheme))
getPyPlotColor(c) = getPyPlotColor(convertColor(c))
# getPyPlotColorMap(c::ColorGradient) = PyPlot.matplotlib[:colors][:ListedColormap](map(getPyPlotColor, getColorVector(c)))
function getPyPlotColorMap(c::ColorGradient)
pycolors.pymember("LinearSegmentedColormap")[:from_list]("tmp", map(getPyPlotColor, getColorVector(c)))
end
getPyPlotColorMap(c) = getPyPlotColorMap(ColorGradient(:redsblues))
# get the style (solid, dashed, etc)
function getPyPlotLineStyle(linetype::Symbol, linestyle::Symbol)
@ -107,7 +107,8 @@ function getPyPlotFunction(plt::Plot, axis::Symbol, linetype::Symbol)
:bar => :bar,
:heatmap => :hexbin,
:hexbin => :hexbin,
:scatter => :scatter
:scatter => :scatter,
:contour => :contour,
)
return ax[get(fmap, linetype, :plot)]
end
@ -125,6 +126,7 @@ function updateAxisColors(ax, fgcolor)
ax[:title][:set_color](fgcolor)
end
nop() = nothing
@ -195,7 +197,7 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
end
lt = d[:linetype]
extraargs = Dict()
extra_kwargs = Dict()
plotfunc = getPyPlotFunction(plt, d[:axis], lt)
@ -203,63 +205,71 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
if lt in (:hist, :sticks, :bar)
# NOTE: this is unsupported because it does the wrong thing... it shifts the whole axis
# extraargs[:bottom] = d[:fill]
# extra_kwargs[:bottom] = d[:fill]
if lt == :hist
extraargs[:bins] = d[:nbins]
extra_kwargs[:bins] = d[:nbins]
else
extraargs[:linewidth] = (lt == :sticks ? 0.1 : 0.9)
extra_kwargs[:linewidth] = (lt == :sticks ? 0.1 : 0.9)
end
elseif lt in (:heatmap, :hexbin)
extra_kwargs[:gridsize] = d[:nbins]
extra_kwargs[:cmap] = getPyPlotColorMap(d[:color])
extraargs[:gridsize] = d[:nbins]
c = d[:color]
if !isa(c, ColorGradient)
c = ColorGradient(:redsblues)
end
# c = ColorGradient(d[:color])
extraargs[:cmap] = getPyPlotColorMap(c)
elseif lt == :contour
extra_kwargs[:cmap] = getPyPlotColorMap(d[:color])
extra_kwargs[:linewidths] = d[:linewidth]
extra_kwargs[:linestyles] = getPyPlotLineStyle(lt, d[:linestyle])
# TODO: will need to call contourf to fill in the contours
else
extraargs[:linestyle] = getPyPlotLineStyle(lt, d[:linestyle])
extraargs[:marker] = getPyPlotMarker(d[:markershape])
extra_kwargs[:linestyle] = getPyPlotLineStyle(lt, d[:linestyle])
extra_kwargs[:marker] = getPyPlotMarker(d[:markershape])
if lt == :scatter
extraargs[:s] = d[:markersize]^2
extra_kwargs[:s] = d[:markersize]^2
c = d[:markercolor]
if isa(c, ColorGradient) && d[:z] != nothing
extraargs[:c] = convert(Vector{Float64}, d[:z])
extraargs[:cmap] = getPyPlotColorMap(c)
extra_kwargs[:c] = convert(Vector{Float64}, d[:z])
extra_kwargs[:cmap] = getPyPlotColorMap(c)
else
extraargs[:c] = getPyPlotColor(c)
extra_kwargs[:c] = getPyPlotColor(c)
end
else
extraargs[:markersize] = d[:markersize]
extraargs[:markerfacecolor] = getPyPlotColor(d[:markercolor])
extraargs[:markeredgecolor] = getPyPlotColor(plt.initargs[:foreground_color])
extraargs[:markeredgewidth] = d[:linewidth]
extraargs[:drawstyle] = getPyPlotDrawStyle(lt)
extra_kwargs[:markersize] = d[:markersize]
extra_kwargs[:markerfacecolor] = getPyPlotColor(d[:markercolor])
extra_kwargs[:markeredgecolor] = getPyPlotColor(plt.initargs[:foreground_color])
extra_kwargs[:markeredgewidth] = d[:linewidth]
extra_kwargs[:drawstyle] = getPyPlotDrawStyle(lt)
end
end
# set these for all types
extraargs[:color] = getPyPlotColor(d[:color])
extraargs[:linewidth] = d[:linewidth]
extraargs[:label] = d[:label]
if lt != :contour
extra_kwargs[:color] = getPyPlotColor(d[:color])
extra_kwargs[:linewidth] = d[:linewidth]
extra_kwargs[:label] = d[:label]
end
# do the plot
d[:serieshandle] = if lt == :hist
plotfunc(d[:y]; extraargs...)[1]
plotfunc(d[:y]; extra_kwargs...)[1]
elseif lt == :contour
handle = plotfunc(d[:x], d[:y], d[:surface], d[:nlevels]; extra_kwargs...)
if d[:fillrange] != nothing
handle = ax[:contourf](d[:x], d[:y], d[:surface], d[:nlevels]; cmap = getPyPlotColorMap(d[:fillcolor]))
end
handle
elseif lt in (:scatter, :heatmap, :hexbin)
plotfunc(d[:x], d[:y]; extraargs...)
plotfunc(d[:x], d[:y]; extra_kwargs...)
else
plotfunc(d[:x], d[:y]; extraargs...)[1]
plotfunc(d[:x], d[:y]; extra_kwargs...)[1]
end
# add the colorbar legend
if plt.initargs[:legend] && haskey(extraargs, :cmap)
if plt.initargs[:legend] && haskey(extra_kwargs, :cmap)
PyPlot.colorbar(d[:serieshandle])
end
@ -267,7 +277,7 @@ function plot!(pkg::PyPlotPackage, plt::Plot; kw...)
ax[:set_axis_bgcolor](getPyPlotColor(plt.initargs[:background_color]))
fillrange = d[:fillrange]
if fillrange != nothing
if fillrange != nothing && lt != :contour
fillcolor = getPyPlotColor(d[:fillcolor])
if typeof(fillrange) <: @compat(Union{Real, AVec})
ax[:fill_between](d[:x], fillrange, d[:y], facecolor = fillcolor)
@ -494,7 +504,7 @@ end
function addPyPlotLegend(plt::Plot, ax)
if plt.initargs[:legend]
# gotta do this to ensure both axes are included
args = filter(x -> !(x[:linetype] in (:hist,:hexbin,:heatmap,:hline,:vline)), plt.seriesargs)
args = filter(x -> !(x[:linetype] in (:hist,:hexbin,:heatmap,:hline,:vline,:contour)), plt.seriesargs)
if length(args) > 0
ax[:legend]([d[:serieshandle] for d in args],
[d[:label] for d in args],

View File

@ -49,9 +49,11 @@ supportedArgs(::GadflyPackage) = [
:guidefont,
:legendfont,
:grid,
:surface,
:nlevels,
]
supportedAxes(::GadflyPackage) = [:auto, :left]
supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :ohlc]
supportedTypes(::GadflyPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour]
supportedStyles(::GadflyPackage) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
supportedMarkers(::GadflyPackage) = vcat(_allMarkers, Shape)
supportedScales(::GadflyPackage) = [:identity, :log, :log2, :log10, :asinh, :sqrt]
@ -122,9 +124,11 @@ supportedArgs(::PyPlotPackage) = [
:guidefont,
:legendfont,
# :grid,
:surface,
:nlevels,
]
supportedAxes(::PyPlotPackage) = _allAxes
supportedTypes(::PyPlotPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline]
supportedTypes(::PyPlotPackage) = [:none, :line, :path, :steppre, :steppost, :sticks, :scatter, :heatmap, :hexbin, :hist, :bar, :hline, :vline, :contour]
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)

View File

@ -321,20 +321,38 @@ function createKWargsList(plt::PlottingObject, y; kw...)
createKWargsList(plt, nothing, y; kw...)
end
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, z::AVec; kw...)
# contours or surfaces... irregular data
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, zvec::AVec; kw...)
error("TODO: contours or surfaces... irregular data")
end
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, z::Function; kw...)
error("TODO: contours or surfaces... function grid")
# contours or surfaces... function grid
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, zf::Function; kw...)
# 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]
createKWargsList(plt, x, y, surface; kw...) # passes it to the zmat version
end
function createKWargsList(plt::PlottingObject, x::AVec, y::AVec, z::AMat; kw...)
error("TODO: contours or surfaces... grid")
# contours or surfaces... matrix grid
function createKWargsList{T<:Real}(plt::PlottingObject, x::AVec, y::AVec, zmat::AMat{T}; kw...)
# only allow sorted x/y for now
# TODO: auto sort x/y/z properly
@assert x == sort(x)
@assert y == sort(y)
@assert size(zmat) == (length(x), length(y))
surf = Array(Any,1,1)
surf[1,1] = convert(Matrix{Float64}, zmat)
createKWargsList(plt, x, y; kw..., surface = surf, linetype = :contour)
end
function createKWargsList(plt::PlottingObject, f::FuncOrFuncs; kw...)
error("Can't pass a Function or Vector{Function} for y without also passing x")
end
# list of functions
function createKWargsList(plt::PlottingObject, f::FuncOrFuncs, x; kw...)
@assert !(typeof(x) <: FuncOrFuncs) # otherwise we'd hit infinite recursion here
createKWargsList(plt, x, f; kw...)

View File

@ -1,4 +1,4 @@
julia 0.3
julia 0.4
Colors
Reexport