diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index e2db4322..3bdb52a4 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -444,11 +444,16 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) xyargs = (st in _3dTypes ? (x,y,z) : (x,y)) # handle zcolor and get c/cmap - extrakw = KW() + needs_colorbar = hascolorbar(sp) + extrakw = if needs_colorbar + vmin, vmax = get_clims(sp) + KW(:vmin => vmin, :vmax => vmax) + else + KW() + end # holds references to any python object representing the matplotlib series handles = [] - needs_colorbar = false discrete_colorbar_values = nothing @@ -495,11 +500,7 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) :linewidth => py_dpi_scale(plt, series[:linewidth]), :linestyle => py_linestyle(st, series[:linestyle]) ) - clims = sp[:clims] - if is_2tuple(clims) - extrakw = KW() - isfinite(clims[1]) && (extrakw[:vmin] = clims[1]) - isfinite(clims[2]) && (extrakw[:vmax] = clims[2]) + if needs_colorbar kw[:norm] = pycolors["Normalize"](; extrakw...) end lz = collect(series[:line_z]) @@ -563,18 +564,11 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) if series[:markershape] != :none && st in (:path, :scatter, :path3d, :scatter3d, :steppre, :steppost, :bar) - extrakw = KW() if series[:marker_z] == nothing extrakw[:c] = py_color_fix(py_markercolor(series), x) else extrakw[:c] = convert(Vector{Float64}, series[:marker_z]) extrakw[:cmap] = py_markercolormap(series) - clims = sp[:clims] - if is_2tuple(clims) - isfinite(clims[1]) && (extrakw[:vmin] = clims[1]) - isfinite(clims[2]) && (extrakw[:vmax] = clims[2]) - end - needs_colorbar = true end xyargs = if st == :bar && !isvertical(series) (y, x) @@ -624,11 +618,6 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) end if st == :hexbin - clims = sp[:clims] - if is_2tuple(clims) - isfinite(clims[1]) && (extrakw[:vmin] = clims[1]) - isfinite(clims[2]) && (extrakw[:vmax] = clims[2]) - end handle = ax[:hexbin](x, y; label = series[:label], zorder = series[:series_plotindex], @@ -646,12 +635,6 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) z = transpose_z(series, z.surf) needs_colorbar = true - clims = sp[:clims] - if is_2tuple(clims) - isfinite(clims[1]) && (extrakw[:vmin] = clims[1]) - isfinite(clims[2]) && (extrakw[:vmax] = clims[2]) - end - if st == :contour3d extrakw[:extend3d] = true end @@ -688,11 +671,6 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) end z = transpose_z(series, z) if st == :surface - clims = sp[:clims] - if is_2tuple(clims) - isfinite(clims[1]) && (extrakw[:vmin] = clims[1]) - isfinite(clims[2]) && (extrakw[:vmax] = clims[2]) - end if series[:fill_z] != nothing # the surface colors are different than z-value extrakw[:facecolors] = py_shading(series[:fillcolor], transpose_z(series, series[:fill_z].surf)) @@ -727,10 +705,6 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) end end - # no colorbar if we are creating a surface LightSource - if haskey(extrakw, :facecolors) - needs_colorbar = false - end elseif typeof(z) <: AbstractVector # tri-surface plot (http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#tri-surface-plots) @@ -788,11 +762,6 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) discrete_colorbar_values = dvals end - clims = sp[:clims] - zmin, zmax = ignorenan_extrema(z) - extrakw[:vmin] = (is_2tuple(clims) && isfinite(clims[1])) ? clims[1] : zmin - extrakw[:vmax] = (is_2tuple(clims) && isfinite(clims[2])) ? clims[2] : zmax - handle = ax[:pcolormesh](x, y, py_mask_nans(z); label = series[:label], zorder = series[:series_plotindex], @@ -844,30 +813,6 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series) # # smoothing # handleSmooth(plt, ax, series, series[:smooth]) - # add the colorbar legend - if needs_colorbar && sp[:colorbar] != :none - # add keyword args for a discrete colorbar - handle = handles[end] - kw = KW() - if discrete_colorbar_values != nothing - locator, formatter = get_locator_and_formatter(discrete_colorbar_values) - # kw[:values] = 1:length(discrete_colorbar_values) - kw[:values] = sp[:zaxis][:continuous_values] - kw[:ticks] = locator - kw[:format] = formatter - kw[:boundaries] = vcat(0, kw[:values] + 0.5) - end - - # create and store the colorbar object (handle) and the axis that it is drawn on. - # note: the colorbar axis is positioned independently from the subplot axis - fig = plt.o - cbax = fig[:add_axes]([0.8,0.1,0.03,0.8], label = string(gensym())) - cb = fig[:colorbar](handle; cax = cbax, kw...) - cb[:set_label](sp[:colorbar_title]) - sp.attr[:cbar_handle] = cb - sp.attr[:cbar_ax] = cbax - end - # handle area filling fillrange = series[:fillrange] if fillrange != nothing && st != :contour @@ -1042,6 +987,32 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) # ax[:set_title](sp[:title], loc = loc) end + # add the colorbar legend + if hascolorbar(sp) + # add keyword args for a discrete colorbar + slist = series_list(sp) + colorbar_series = slist[findfirst(hascolorbar.(slist))] + handle = colorbar_series[:serieshandle][end] + kw = KW() + if !isempty(sp[:zaxis][:discrete_values]) && colorbar_series[:seriestype] == :heatmap + locator, formatter = get_locator_and_formatter(sp[:zaxis][:discrete_values]) + # kw[:values] = 1:length(sp[:zaxis][:discrete_values]) + kw[:values] = sp[:zaxis][:continuous_values] + kw[:ticks] = locator + kw[:format] = formatter + kw[:boundaries] = vcat(0, kw[:values] + 0.5) + end + + # create and store the colorbar object (handle) and the axis that it is drawn on. + # note: the colorbar axis is positioned independently from the subplot axis + fig = plt.o + cbax = fig[:add_axes]([0.8,0.1,0.03,0.8], label = string(gensym())) + cb = fig[:colorbar](handle; cax = cbax, kw...) + cb[:set_label](sp[:colorbar_title]) + sp.attr[:cbar_handle] = cb + sp.attr[:cbar_ax] = cbax + end + # framestyle if !ispolar(sp) && !is3d(sp) if sp[:framestyle] == :semi diff --git a/src/utils.jl b/src/utils.jl index 317c9da2..bc13d191 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -561,12 +561,25 @@ end _update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax) +function hascolorbar(series::Series) + st = series[:seriestype] + hascbar = st in (:heatmap, :contour) + if series[:marker_z] != nothing || series[:line_z] != nothing + hascbar = true + end + # no colorbar if we are creating a surface LightSource + if xor(st == :surface, series[:fill_z] != nothing) + hascbar = true + end + return hascbar +end + function hascolorbar(sp::Subplot) cbar = sp[:colorbar] hascbar = false if cbar != :none for series in series_list(sp) - if series[:seriestype] in (:heatmap, :contour, :surface) || series[:marker_z] != nothing || series[:line_z] != nothing + if hascolorbar(series) hascbar = true end end