line_z arg and pyplot implementation

This commit is contained in:
Thomas Breloff 2016-06-14 15:39:21 -04:00
parent a7493504ed
commit f64108523c
5 changed files with 54 additions and 23 deletions

View File

@ -27,7 +27,8 @@ const _arg_desc = KW(
:x => "Various. Input data. First Dimension",
:y => "Various. Input data. Second Dimension",
:z => "Various. Input data. Third Dimension. May be wrapped by a `Surface` for surface and heatmap types.",
:marker_z => "AbstractVector. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.",
:marker_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or nothing. z-values for each series data point, which correspond to the color to be used from a markercolor gradient.",
:line_z => "AbstractVector, Function `f(x,y,z) -> z_value`, or nothing. z-values for each series line segment, which correspond to the color to be used from a linecolor gradient. Note that for N points, only the first N-1 values are used (one per line-segment).",
:levels => "Integer, NTuple{2,Integer}. Number of levels (or x-levels/y-levels) for a contour type.",
:orientation => "Symbol. Horizontal or vertical orientation for bar types. Values `:h`, `:hor`, `:horizontal` correspond to horizontal (sideways, anchored to y-axis), and `:v`, `:vert`, and `:vertical` correspond to vertical (the default).",
:bar_position => "Symbol. Choose from `:overlay` (default), `:stack`. (warning: May not be implemented fully)",

View File

@ -163,6 +163,7 @@ const _series_defaults = KW(
:y => nothing,
:z => nothing, # depth for contour, surface, etc
:marker_z => nothing, # value for color scale
:line_z => nothing,
:levels => 15,
:orientation => :vertical,
:bar_position => :overlay, # for bar plots and histograms: could also be stack (stack up) or dodge (side by side)
@ -375,7 +376,8 @@ add_aliases(:linestyle, :style, :s, :ls)
add_aliases(:marker, :m, :mark)
add_aliases(:markershape, :shape)
add_aliases(:markersize, :ms, :msize)
add_aliases(:marker_z, :markerz, :zcolor)
add_aliases(:marker_z, :markerz, :zcolor, :mz)
add_aliases(:line_z, :linez, :zline, :lz)
add_aliases(:fill, :f, :area)
add_aliases(:fillrange, :fillrng, :frange, :fillto, :fill_between)
add_aliases(:group, :g, :grouping)

View File

@ -18,7 +18,9 @@ supported_args(::PyPlotBackend) = merge_with_base_supported([
:guide, :lims, :ticks, :scale, :flip, :rotation,
:tickfont, :guidefont, :legendfont,
:grid, :legend, :colorbar,
:marker_z, :levels,
:marker_z,
:line_z,
:levels,
:ribbon, :quiver, :arrow,
:orientation,
:overwrite_figure,
@ -61,6 +63,7 @@ function _initialize_backend(::PyPlotBackend)
const pycmap = PyPlot.pywrap(PyPlot.pyimport("matplotlib.cm"))
const pynp = PyPlot.pywrap(PyPlot.pyimport("numpy"))
const pytransforms = PyPlot.pywrap(PyPlot.pyimport("matplotlib.transforms"))
const pycollections = PyPlot.pywrap(PyPlot.pyimport("matplotlib.collections"))
end
# we don't want every command to update the figure
@ -406,17 +409,37 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
# line plot
if st in (:path, :path3d, :steppre, :steppost)
if d[:linewidth] > 0
handle = ax[:plot](xyargs...;
label = d[:label],
zorder = plt.n,
color = py_linecolor(d),
linewidth = d[:linewidth],
linestyle = py_linestyle(st, d[:linestyle]),
solid_capstyle = "round",
# dash_capstyle = "round",
drawstyle = py_stepstyle(st)
)[1]
push!(handles, handle)
if d[:line_z] == nothing
handle = ax[:plot](xyargs...;
label = d[:label],
zorder = plt.n,
color = py_linecolor(d),
linewidth = d[:linewidth],
linestyle = py_linestyle(st, d[:linestyle]),
solid_capstyle = "round",
drawstyle = py_stepstyle(st)
)[1]
push!(handles, handle)
else
# multicolored line segments
n = length(x) - 1
segments = Array(Any,n)
for i=1:n
segments[i] = [(cycle(x,i), cycle(y,i)), (cycle(x,i+1), cycle(y,i+1))]
end
lc = pycollections.LineCollection(segments;
label = d[:label],
zorder = plt.n,
cmap = py_linecolormap(d),
linewidth = d[:linewidth],
linestyle = py_linestyle(st, d[:linestyle])
)
lc[:set_array](d[:line_z])
handle = ax[:add_collection](lc)
push!(handles, handle)
needs_colorbar = true
end
a = d[:arrow]
if a != nothing && !is3d(st) # TODO: handle 3d later
@ -493,7 +516,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
extrakw[:c] = convert(Vector{Float64}, d[:marker_z])
extrakw[:cmap] = py_markercolormap(d)
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@ -542,7 +565,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
if st == :histogram2d
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@ -567,7 +590,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
if st == :hexbin
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@ -602,7 +625,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
needs_colorbar = true
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@ -648,7 +671,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
extrakw[:facecolors] = py_shading(d[:fillcolor], d[:marker_z], d[:fillalpha])
extrakw[:shade] = false
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@ -690,7 +713,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
elseif typeof(z) <: AbstractVector
# tri-surface plot (http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#tri-surface-plots)
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end
@ -744,7 +767,7 @@ function _series_added(plt::Plot{PyPlotBackend}, series::Series)
end
clims = sp[:clims]
if isa(clims, Tuple) && length(clims) == 2
if is_2tuple(clims)
isfinite(clims[1]) && (extrakw[:vmin] = clims[1])
isfinite(clims[2]) && (extrakw[:vmax] = clims[2])
end

View File

@ -272,7 +272,12 @@ function _plot!(plt::Plot, d::KW, args...)
# map marker_z if it's a Function
if isa(get(kw, :marker_z, nothing), Function)
# TODO: should this take y and/or z as arguments?
kw[:marker_z] = map(kw[:marker_z], kw[:x])
kw[:marker_z] = map(kw[:marker_z], kw[:x], kw[:y], kw[:z])
end
# map line_z if it's a Function
if isa(get(kw, :line_z, nothing), Function)
kw[:line_z] = map(kw[:line_z], kw[:x], kw[:y], kw[:z])
end
# convert a ribbon into a fillrange

View File

@ -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.1"
const _current_plots_version = v"0.7.2"
function image_comparison_tests(pkg::Symbol, idx::Int; debug = false, popup = isinteractive(), sigma = [1,1], eps = 1e-2)