diff --git a/src/backends/gr.jl b/src/backends/gr.jl index c58e4356..ebd35f20 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -341,7 +341,7 @@ function gr_draw_markers(series::Series, x, y, clims) mz = normalize_zvals(series[:marker_z], clims) GR.setfillintstyle(GR.INTSTYLE_SOLID) gr_draw_markers(series, x, y, series[:markersize], mz) - if mz != nothing + if hascolorbar(series[:subplot]) GR.setscale(0) gr_colorbar(series[:subplot], clims) end @@ -447,25 +447,21 @@ end # add the colorbar function gr_colorbar(sp::Subplot) - if sp[:colorbar] != :none - gr_set_viewport_cmap(sp) - GR.colorbar() - gr_set_viewport_plotarea() - end + gr_set_viewport_cmap(sp) + GR.colorbar() + gr_set_viewport_plotarea() end function gr_colorbar(sp::Subplot, clims) - if sp[:colorbar] != :none - xmin, xmax = gr_xy_axislims(sp)[1:2] - gr_set_viewport_cmap(sp) - l = zeros(Int32, 1, 256) - l[1,:] = Int[round(Int, _i) for _i in linspace(1000, 1255, 256)] - GR.setwindow(xmin, xmax, clims[1], clims[2]) - GR.cellarray(xmin, xmax, clims[2], clims[1], 1, length(l), l) - ztick = 0.5 * GR.tick(clims[1], clims[2]) - GR.axes(0, ztick, xmax, clims[1], 0, 1, 0.005) - gr_set_viewport_plotarea() - end + xmin, xmax = gr_xy_axislims(sp)[1:2] + gr_set_viewport_cmap(sp) + l = zeros(Int32, 1, 256) + l[1,:] = Int[round(Int, _i) for _i in linspace(1000, 1255, 256)] + GR.setwindow(xmin, xmax, clims[1], clims[2]) + GR.cellarray(xmin, xmax, clims[2], clims[1], 1, length(l), l) + ztick = 0.5 * GR.tick(clims[1], clims[2]) + GR.axes(0, ztick, xmax, clims[1], 0, 1, 0.005) + gr_set_viewport_plotarea() end gr_view_xcenter() = 0.5 * (viewport_plotarea[1] + viewport_plotarea[2]) @@ -677,14 +673,11 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) # reduced from before... set some flags based on the series in this subplot # TODO: can these be generic flags? outside_ticks = false - cmap = false + cmap = hascolorbar(sp) draw_axes = sp[:framestyle] != :none # axes_2d = true for series in series_list(sp) st = series[:seriestype] - if st in (:contour, :surface, :heatmap) || series[:marker_z] != nothing - cmap = true - end if st == :pie draw_axes = false end @@ -698,7 +691,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) end end - if cmap && sp[:colorbar] != :none + if cmap # note: add extra midpadding on the right for the colorbar viewport_plotarea[2] -= 0.1 end @@ -983,7 +976,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) end # create the colorbar of contour levels - if sp[:colorbar] != :none + if cmap gr_set_viewport_cmap(sp) l = round.(Int32, 1000 + (h - ignorenan_minimum(h)) / (ignorenan_maximum(h) - ignorenan_minimum(h)) * 255) GR.setwindow(xmin, xmax, zmin, zmax) 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 ba81dd30..bc13d191 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -561,6 +561,32 @@ 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 hascolorbar(series) + hascbar = true + end + end + end + hascbar +end + # --------------------------------------------------------------- makekw(; kw...) = KW(kw)