From dd02a69e8f0b08ace5d94fff0d6ac6bd833538bf Mon Sep 17 00:00:00 2001 From: yharel Date: Thu, 28 Mar 2019 02:21:25 +0200 Subject: [PATCH 1/4] Consistent interpretation of contour levels across PyPlot,GR,Plotly[JS] backends. GR: fixed colorbar rendering/alignment for contour[f]. Merged colorbar for mutiple series. :colorbar_entry property to include series in colorbar. --- src/args.jl | 1 + src/backends.jl | 7 +-- src/backends/gr.jl | 130 +++++++++++++++++++++++++++++++---------- src/backends/plotly.jl | 8 +-- src/utils.jl | 22 ++++--- 5 files changed, 123 insertions(+), 45 deletions(-) diff --git a/src/args.jl b/src/args.jl index a5f043b4..c869bc5c 100644 --- a/src/args.jl +++ b/src/args.jl @@ -232,6 +232,7 @@ const _bar_width = 0.8 const _series_defaults = KW( :label => "AUTO", + :colorbar_entry => true, :seriescolor => :auto, :seriesalpha => nothing, :seriestype => :path, diff --git a/src/backends.jl b/src/backends.jl index 8f24be72..8cb4c0ce 100644 --- a/src/backends.jl +++ b/src/backends.jl @@ -332,7 +332,7 @@ const _gr_attr = merge_with_base_supported([ :guidefontfamily, :guidefontsize, :guidefonthalign, :guidefontvalign, :guidefontrotation, :guidefontcolor, :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :legendtitle, :colorbar, :colorbar_title, + :legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry, :fill_z, :line_z, :marker_z, :levels, :ribbon, :quiver, :orientation, @@ -386,7 +386,7 @@ const _plotly_attr = merge_with_base_supported([ :guide, :lims, :ticks, :scale, :flip, :rotation, :tickfont, :guidefont, :legendfont, :grid, :gridalpha, :gridlinewidth, - :legend, :colorbar, :colorbar_title, + :legend, :colorbar, :colorbar_title, :colorbar_entry, :marker_z, :fill_z, :line_z, :levels, :ribbon, :quiver, :orientation, @@ -511,7 +511,7 @@ const _pyplot_attr = merge_with_base_supported([ :tickfontfamily, :tickfontsize, :tickfontcolor, :guidefontfamily, :guidefontsize, :guidefontcolor, :grid, :gridalpha, :gridstyle, :gridlinewidth, - :legend, :legendtitle, :colorbar, + :legend, :legendtitle, :colorbar, :colorbar_title, :colorbar_entry, :marker_z, :line_z, :fill_z, :levels, :ribbon, :quiver, :arrow, @@ -524,7 +524,6 @@ const _pyplot_attr = merge_with_base_supported([ :clims, :inset_subplots, :dpi, - :colorbar_title, :stride, :framestyle, :tick_direction, diff --git a/src/backends/gr.jl b/src/backends/gr.jl index e844c881..3831ffda 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -415,24 +415,92 @@ function gr_set_viewport_polar() r end +mutable struct GRColorbar + heatmapseries::Union{Series,Nothing} + fillseries::Union{Series,Nothing} + linesseries::Union{Series,Nothing} + GRColorbar() = new(nothing,nothing,nothing) +end + +function gr_update_colorbar!(cbar::GRColorbar, series::Series) + if iscontour(series) + if isfilledcontour(series) + cbar.fillseries = series + else + cbar.linesseries = series + end + elseif series[:seriestype] == :heatmap + cbar.heatmapseries = series + end +end + +function gr_contour_levels(series::Series, clims) + levels = contour_levels(series, clims) + if isfilledcontour(series) + # GR implicitly uses the maximal z value as the highest level + if levels[end] < clims[2] + @warn("GR: highest contour level less than maximal z value is not supported.") + end + levels = levels[1:end-1] + end + levels +end + +function gr_colorbar_colors(series::Series, clims) + if iscontour(series) + levels = gr_contour_levels(series, clims) + if isfilledcontour(series) + # GR.contourf uses a color range according to supplied levels + zrange = ignorenan_extrema(levels) + else + # GR.contour uses a color range according to data range + zrange = clims + end + colors = 1000 .+ 255 .* (levels .- zrange[1]) ./ (zrange[2] - zrange[1]) + else + colors = 1000:1255 + end + round.(Int,colors) +end + # add the colorbar -function gr_colorbar(sp::Subplot, clims, levels) +function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) GR.savestate() xmin, xmax = gr_xy_axislims(sp)[1:2] zmin, zmax = clims[1:2] gr_set_viewport_cmap(sp) - l = if levels === nothing - (1000:1255)' - elseif length(levels) > 1 - min_level, max_level = ignorenan_minimum(levels), ignorenan_maximum(levels) - round.(Int32, 1000 .+ (levels .- min_level) ./ (max_level - min_level) .* 255) - else - Int32[1000, 1255] - end GR.setscale(0) GR.setwindow(xmin, xmax, zmin, zmax) - GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l) + if (hm = cbar.heatmapseries) !== nothing + gr_set_gradient!(hm) + # TODO should use z limits of the specific series + GR.cellarray(xmin, xmax, zmax, zmin, 1, 256, 1000:1255) + end + + if (series = cbar.fillseries) !== nothing + gr_set_gradient!(cbar.fillseries) + GR.setfillintstyle(GR.INTSTYLE_SOLID) + levels = contour_levels(series, clims) + colors = gr_colorbar_colors(series, clims) + for (from, to, color) in zip(levels[1:end-1], levels[2:end], colors) + GR.setfillcolorind(color) + GR.fillrect( xmin, xmax, from, to ) + end + end + + if (series = cbar.linesseries) !== nothing + gr_set_gradient!(series) + gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) + levels = contour_levels(series, clims) + colors = gr_colorbar_colors(series, clims) + for (line, color) in zip(levels, colors) + GR.setlinecolorind(color) + GR.polyline([xmin,xmax], [line,line] ) + end + end + ztick = 0.5 * GR.tick(zmin, zmax) + gr_set_line(1, :solid, plot_color(:black)) GR.axes(0, ztick, xmax, zmin, 0, 1, 0.005) gr_set_font(guidefont(sp[:yaxis])) @@ -489,6 +557,21 @@ function gr_set_gradient(c) grad end +function gr_set_gradient!(series::Series) + st = series[:seriestype] + if st in (:surface, :heatmap) || isfilledcontour(series) + gr_set_gradient(series[:fillcolor]) + elseif st in (:contour, :wireframe) + gr_set_gradient(series[:linecolor]) + elseif series[:marker_z] != nothing + series[:markercolor] = gr_set_gradient(series[:markercolor]) + elseif series[:line_z] != nothing + series[:linecolor] = gr_set_gradient(series[:linecolor]) + elseif series[:fill_z] != nothing + series[:fillcolor] = gr_set_gradient(series[:fillcolor]) + end +end + # this is our new display func... set up the viewport_canvas, compute bounding boxes, and display each subplot function gr_display(plt::Plot, fmt="") GR.clearws() @@ -671,7 +754,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) outside_ticks = false # calculate the colorbar limits once for a subplot clims = get_clims(sp) - clevels = nothing + cbar = GRColorbar() draw_axes = sp[:framestyle] != :none # axes_2d = true @@ -695,8 +778,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) data_lims = gr_xy_axislims(sp) end - # color levels overwritten by the last relevant series - hascolorbar(series) && (clevels = colorbar_levels(series, clims)) + hascolorbar(series) && gr_update_colorbar!(cbar,series) end # set our plot area view @@ -963,24 +1045,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) for (idx, series) in enumerate(series_list(sp)) st = series[:seriestype] - - # update the current stored gradient - if st in (:surface, :heatmap) || - (st == :contour && series[:fillrange] !== nothing) - gr_set_gradient(series[:fillcolor]) #, series[:fillalpha]) - elseif st in (:contour, :wireframe) - gr_set_gradient(series[:linecolor]) - elseif series[:marker_z] != nothing - series[:markercolor] = gr_set_gradient(series[:markercolor]) - elseif series[:line_z] != nothing - series[:linecolor] = gr_set_gradient(series[:linecolor]) - elseif series[:fill_z] != nothing - series[:fillcolor] = gr_set_gradient(series[:fillcolor]) - end + + # update the current stored gradient and the series + gr_set_gradient!(series) GR.savestate() - # update the bounding window if ispolar(sp) gr_set_viewport_polar() @@ -1046,12 +1116,12 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) elseif st == :contour GR.setspace(clims[1], clims[2], 0, 90) - h = colorbar_levels(series, clims) GR.setlinetype(gr_linetype[get_linestyle(series)]) GR.setlinewidth(max(0, get_linewidth(series) / (sum(gr_plot_size) * 0.001))) is_lc_black = let black=plot_color(:black) plot_color(series[:linecolor]) in (black,[black]) end + h = gr_contour_levels(series, clims) if series[:fillrange] != nothing if series[:fillcolor] != series[:linecolor] && !is_lc_black @warn("GR: filled contour only supported with black contour lines") @@ -1221,7 +1291,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) end # draw the colorbar - hascolorbar(sp) && gr_colorbar(sp, clims, clevels) + hascolorbar(sp) && gr_draw_colorbar(cbar, sp, clims) # add the legend if sp[:legend] != :none diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 8d7a0f12..3fd226de 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -506,13 +506,13 @@ function plotly_series(plt::Plot, series::Series) plotattributes_out[:showscale] = hascolorbar(sp) elseif st == :contour + filled = isfilledcontour(series) plotattributes_out[:type] = "contour" plotattributes_out[:x], plotattributes_out[:y], plotattributes_out[:z] = x, y, z - # plotattributes_out[:showscale] = series[:colorbar] != :none - plotattributes_out[:ncontours] = series[:levels] - plotattributes_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines", :showlabels => series[:contour_labels] == true) + plotattributes_out[:ncontours] = series[:levels] + 2 + plotattributes_out[:contours] = KW(:coloring => filled ? "fill" : "lines", :showlabels => series[:contour_labels] == true) plotattributes_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha]) - plotattributes_out[:showscale] = hascolorbar(sp) + plotattributes_out[:showscale] = hascolorbar(sp) && hascolorbar(series) elseif st in (:surface, :wireframe) plotattributes_out[:type] = "surface" diff --git a/src/utils.jl b/src/utils.jl index 687b0e49..472f67c4 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -582,6 +582,9 @@ end _update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax) function hascolorbar(series::Series) + if get(series, :colorbar_entry, true) == false + return false + end st = series[:seriestype] hascbar = st == :heatmap if st == :contour @@ -610,15 +613,20 @@ function hascolorbar(sp::Subplot) hascbar end -function colorbar_levels(series::Series, clims) - if series[:seriestype] == :contour +iscontour(series::Series) = series[:seriestype] == :contour +isfilledcontour(series::Series) = iscontour(series) && series[:fillrange] !== nothing + +function contour_levels(series::Series, clims) + if iscontour(series) zmin, zmax = clims levels = series[:levels] - levels isa AbstractArray ? - levels : - levels > 1 ? - range(zmin, stop=zmax, length=levels) : - [(zmin + zmax) / 2] + if levels isa Integer + levels = range(zmin, stop=zmax, length=levels+2) + if !isfilledcontour(series) + levels = levels[2:end-1] + end + end + levels else # including heatmap, surface nothing end From 78059bf825277171434146aa015ef86031f0de7b Mon Sep 17 00:00:00 2001 From: yharel Date: Thu, 28 Mar 2019 02:28:19 +0200 Subject: [PATCH 2/4] Support for non-gradient colors in surface-like plots (useful for contour) --- src/args.jl | 28 +++++++++++++++------------- src/backends/gr.jl | 2 +- src/backends/plotly.jl | 2 +- src/backends/pyplot.jl | 2 +- src/utils.jl | 3 +++ 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/args.jl b/src/args.jl index c869bc5c..f721e754 100644 --- a/src/args.jl +++ b/src/args.jl @@ -1510,19 +1510,19 @@ function has_black_border_for_default(st::Symbol) like_histogram(st) || st in (:hexbin, :bar, :shape) end - -# converts a symbol or string into a colorant (Colors.RGB), and assigns a color automatically -function getSeriesRGBColor(c, sp::Subplot, n::Int) +# converts a symbol or string into a Colorant or ColorGradient +# and assigns a color automatically +function get_series_color(c, sp::Subplot, n::Int, seriestype) if c == :auto - c = autopick(sp[:color_palette], n) + c = like_surface(seriestype) ? cgrad() : autopick(sp[:color_palette], n) elseif isa(c, Int) c = autopick(sp[:color_palette], c) end plot_color(c) end -function getSeriesRGBColor(c::AbstractArray, sp::Subplot, n::Int) - map(x->getSeriesRGBColor(x, sp, n), c) +function get_series_color(c::AbstractArray, sp::Subplot, n::Int, seriestype) + map(x->get_series_color(x, sp, n), c, seriestype) end function ensure_gradient!(plotattributes::KW, csym::Symbol, asym::Symbol) @@ -1567,21 +1567,23 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot) end # update series color - plotattributes[:seriescolor] = getSeriesRGBColor(plotattributes[:seriescolor], sp, plotIndex) + scolor = plotattributes[:seriescolor] + stype = plotattributes[:seriestype] + plotattributes[:seriescolor] = scolor = get_series_color(scolor, sp, plotIndex, stype) # update other colors for s in (:line, :marker, :fill) csym, asym = Symbol(s,:color), Symbol(s,:alpha) plotattributes[csym] = if plotattributes[csym] == :auto - plot_color(if has_black_border_for_default(plotattributes[:seriestype]) && s == :line + plot_color(if has_black_border_for_default(stype) && s == :line sp[:foreground_color_subplot] else - plotattributes[:seriescolor] + scolor end) elseif plotattributes[csym] == :match - plot_color(plotattributes[:seriescolor]) + plot_color(scolor) else - getSeriesRGBColor(plotattributes[csym], sp, plotIndex) + get_series_color(plotattributes[csym], sp, plotIndex, stype) end end @@ -1589,9 +1591,9 @@ function _update_series_attributes!(plotattributes::KW, plt::Plot, sp::Subplot) plotattributes[:markerstrokecolor] = if plotattributes[:markerstrokecolor] == :match plot_color(sp[:foreground_color_subplot]) elseif plotattributes[:markerstrokecolor] == :auto - getSeriesRGBColor(plotattributes[:markercolor], sp, plotIndex) + get_series_color(plotattributes[:markercolor], sp, plotIndex, stype) else - getSeriesRGBColor(plotattributes[:markerstrokecolor], sp, plotIndex) + get_series_color(plotattributes[:markerstrokecolor], sp, plotIndex, stype) end # if marker_z, fill_z or line_z are set, ensure we have a gradient diff --git a/src/backends/gr.jl b/src/backends/gr.jl index 3831ffda..b7111562 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -548,7 +548,7 @@ end const _gr_gradient_alpha = ones(256) function gr_set_gradient(c) - grad = c isa ColorGradient ? c : cgrad() + grad = _as_gradient(c) for (i,z) in enumerate(range(0, stop=1, length=256)) c = grad[z] GR.setcolorrep(999+i, red(c), green(c), blue(c)) diff --git a/src/backends/plotly.jl b/src/backends/plotly.jl index 3fd226de..dc06ed45 100644 --- a/src/backends/plotly.jl +++ b/src/backends/plotly.jl @@ -354,7 +354,7 @@ end function plotly_colorscale(grad::ColorGradient, α) [[grad.values[i], rgba_string(plot_color(grad.colors[i], α))] for i in 1:length(grad.colors)] end -plotly_colorscale(c, α) = plotly_colorscale(cgrad(alpha=α), α) +plotly_colorscale(c::Colorant,α) = plotly_colorscale(_as_gradient(c),α) function plotly_colorscale(c::AbstractVector{<:RGBA}, α) if length(c) == 1 return [[0.0, rgba_string(plot_color(c[1], α))], [1.0, rgba_string(plot_color(c[1], α))]] diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 1e3ca98d..8697c07f 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -73,7 +73,7 @@ function py_colormap(grad::ColorGradient) cm."set_bad"(color=(0,0,0,0.0), alpha=0.0) cm end -py_colormap(c) = py_colormap(cgrad()) +py_colormap(c::Colorant) = py_colormap(_as_gradient(c)) function py_shading(c, z) diff --git a/src/utils.jl b/src/utils.jl index 472f67c4..4b9c7ceb 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -273,6 +273,9 @@ _cycle(v, indices::AVec{Int}) = fill(v, length(indices)) _cycle(grad::ColorGradient, idx::Int) = _cycle(grad.colors, idx) _cycle(grad::ColorGradient, indices::AVec{Int}) = _cycle(grad.colors, indices) +_as_gradient(grad::ColorGradient) = grad +_as_gradient(c::Colorant) = ColorGradient([c,c]) + makevec(v::AVec) = v makevec(v::T) where {T} = T[v] From 8982a67902b61cd80320b80b3c3b3a5e4b7e9eb5 Mon Sep 17 00:00:00 2001 From: yharel Date: Fri, 29 Mar 2019 21:20:36 +0300 Subject: [PATCH 3/4] Fix colorbar for misc. series types with line_z,fill_z,marker_z. --- src/backends/gr.jl | 62 ++++++++++++++++++++++-------------------- src/utils.jl | 67 ++++++++++++++++++++-------------------------- 2 files changed, 62 insertions(+), 67 deletions(-) diff --git a/src/backends/gr.jl b/src/backends/gr.jl index b7111562..4cbee0d0 100644 --- a/src/backends/gr.jl +++ b/src/backends/gr.jl @@ -415,32 +415,30 @@ function gr_set_viewport_polar() r end -mutable struct GRColorbar - heatmapseries::Union{Series,Nothing} - fillseries::Union{Series,Nothing} - linesseries::Union{Series,Nothing} +struct GRColorbar + gradient::Ref{Union{Series,Nothing}} + fill::Ref{Union{Series,Nothing}} + lines::Ref{Union{Series,Nothing}} GRColorbar() = new(nothing,nothing,nothing) end function gr_update_colorbar!(cbar::GRColorbar, series::Series) - if iscontour(series) - if isfilledcontour(series) - cbar.fillseries = series - else - cbar.linesseries = series - end - elseif series[:seriestype] == :heatmap - cbar.heatmapseries = series + style = colorbar_style(series) + style === nothing && return + ref = style == cbar_gradient ? cbar.gradient : + style == cbar_fill ? cbar.fill : + style == cbar_lines ? cbar.lines : + error("Unknown colorbar style: $style.") + if ref[] !== nothing + @warn "Overwriting colorbar entry" end + ref[] = series end function gr_contour_levels(series::Series, clims) levels = contour_levels(series, clims) if isfilledcontour(series) # GR implicitly uses the maximal z value as the highest level - if levels[end] < clims[2] - @warn("GR: highest contour level less than maximal z value is not supported.") - end levels = levels[1:end-1] end levels @@ -471,16 +469,22 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) gr_set_viewport_cmap(sp) GR.setscale(0) GR.setwindow(xmin, xmax, zmin, zmax) - if (hm = cbar.heatmapseries) !== nothing - gr_set_gradient!(hm) - # TODO should use z limits of the specific series + if (series = cbar.gradient[]) !== nothing + gr_set_gradient(series) GR.cellarray(xmin, xmax, zmax, zmin, 1, 256, 1000:1255) end - if (series = cbar.fillseries) !== nothing - gr_set_gradient!(cbar.fillseries) + if (series = cbar.fill[]) !== nothing + gr_set_gradient(series) GR.setfillintstyle(GR.INTSTYLE_SOLID) levels = contour_levels(series, clims) + # GR implicitly uses the maximal z value as the highest level + if levels[end] < clims[2] + @warn("GR: highest contour level less than maximal z value is not supported.") + # replace levels, rather than assign to levels[end], to ensure type + # promotion in case levels is an integer array + levels = [levels[1:end-1]; clims[2]] + end colors = gr_colorbar_colors(series, clims) for (from, to, color) in zip(levels[1:end-1], levels[2:end], colors) GR.setfillcolorind(color) @@ -488,8 +492,8 @@ function gr_draw_colorbar(cbar::GRColorbar, sp::Subplot, clims) end end - if (series = cbar.linesseries) !== nothing - gr_set_gradient!(series) + if (series = cbar.lines[]) !== nothing + gr_set_gradient(series) gr_set_line(get_linewidth(series), get_linestyle(series), get_linecolor(series, clims)) levels = contour_levels(series, clims) colors = gr_colorbar_colors(series, clims) @@ -557,18 +561,18 @@ function gr_set_gradient(c) grad end -function gr_set_gradient!(series::Series) +function gr_set_gradient(series::Series) st = series[:seriestype] if st in (:surface, :heatmap) || isfilledcontour(series) gr_set_gradient(series[:fillcolor]) elseif st in (:contour, :wireframe) gr_set_gradient(series[:linecolor]) elseif series[:marker_z] != nothing - series[:markercolor] = gr_set_gradient(series[:markercolor]) + gr_set_gradient(series[:markercolor]) elseif series[:line_z] != nothing - series[:linecolor] = gr_set_gradient(series[:linecolor]) + gr_set_gradient(series[:linecolor]) elseif series[:fill_z] != nothing - series[:fillcolor] = gr_set_gradient(series[:fillcolor]) + gr_set_gradient(series[:fillcolor]) end end @@ -778,7 +782,7 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) data_lims = gr_xy_axislims(sp) end - hascolorbar(series) && gr_update_colorbar!(cbar,series) + gr_update_colorbar!(cbar,series) end # set our plot area view @@ -1046,8 +1050,8 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas) for (idx, series) in enumerate(series_list(sp)) st = series[:seriestype] - # update the current stored gradient and the series - gr_set_gradient!(series) + # update the current stored gradient + gr_set_gradient(series) GR.savestate() diff --git a/src/utils.jl b/src/utils.jl index 4b9c7ceb..bea33a07 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -584,55 +584,46 @@ end _update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax) -function hascolorbar(series::Series) - if get(series, :colorbar_entry, true) == false - return false +@enum ColorbarStyle cbar_gradient cbar_fill cbar_lines + +function colorbar_style(series::Series) + colorbar_entry = series[:colorbar_entry] + if !(colorbar_entry isa Bool) + @warn "Non-boolean colorbar_entry ignored." + colorbar_entry = true end - st = series[:seriestype] - hascbar = st == :heatmap - if st == :contour - hascbar = (isscalar(series[:levels]) ? (series[:levels] > 1) : (length(series[:levels]) > 1)) && (length(unique(Array(series[:z]))) > 1) + + if !colorbar_entry + nothing + elseif isfilledcontour(series) + cbar_fill + elseif iscontour(series) + cbar_lines + elseif series[:seriestype] ∈ (:heatmap,:surface) || + any(series[z] !== nothing for z ∈ [:marker_z,:line_z,:fill_z]) + cbar_gradient + else + nothing end - if series[:marker_z] != nothing || series[:line_z] != nothing || series[:fill_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 +hascolorbar(series::Series) = colorbar_style(series) !== nothing +hascolorbar(sp::Subplot) = sp[:colorbar] != :none && any(hascolorbar(s) for s in series_list(sp)) iscontour(series::Series) = series[:seriestype] == :contour isfilledcontour(series::Series) = iscontour(series) && series[:fillrange] !== nothing function contour_levels(series::Series, clims) - if iscontour(series) - zmin, zmax = clims - levels = series[:levels] - if levels isa Integer - levels = range(zmin, stop=zmax, length=levels+2) - if !isfilledcontour(series) - levels = levels[2:end-1] - end + iscontour(series) || error("Not a contour series") + zmin, zmax = clims + levels = series[:levels] + if levels isa Integer + levels = range(zmin, stop=zmax, length=levels+2) + if !isfilledcontour(series) + levels = levels[2:end-1] end - levels - else # including heatmap, surface - nothing end + levels end From 0075103ddfd83e26a0f4d08a3abf63fd90412029 Mon Sep 17 00:00:00 2001 From: yharel Date: Fri, 29 Mar 2019 22:01:28 +0300 Subject: [PATCH 4/4] Proportional colorbar spacing in pyplot --- src/backends/pyplot.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/backends/pyplot.jl b/src/backends/pyplot.jl index 8697c07f..d3e0e091 100644 --- a/src/backends/pyplot.jl +++ b/src/backends/pyplot.jl @@ -1013,6 +1013,7 @@ function _before_layout_calcs(plt::Plot{PyPlotBackend}) cmap."set_array"([]) handle = cmap end + kw[:spacing] = "proportional" # 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