Merge pull request #1420 from daschw/contour-fix

Contour improvements
This commit is contained in:
Daniel Schwabeneder 2018-03-01 19:59:09 +01:00 committed by GitHub
commit c4bac660cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 8 deletions

View File

@ -43,6 +43,7 @@ const _arg_desc = KW(
:normalize => "Bool or Symbol. Histogram normalization mode. Possible values are: false/:none (no normalization, default), true/:pdf (normalize to a discrete Probability Density Function, where the total area of the bins is 1), :probability (bin heights sum to 1) and :density (the area of each bin, rather than the height, is equal to the counts - useful for uneven bin sizes).",
:weights => "AbstractVector. Used in histogram types for weighted counts.",
:contours => "Bool. Add contours to the side-grids of 3D plots? Used in surface/wireframe.",
:contour_labels => "Bool. Show labels at the contour lines?",
:match_dimensions => "Bool. For heatmap types... should the first dimension of a matrix (rows) correspond to the first dimension of the plot (x-axis)? The default is false, which matches the behavior of Matplotlib, Plotly, and others. Note: when passing a function for z, the function should still map `(x,y) -> z`.",
:subplot => "Integer (subplot index) or Subplot object. The subplot that this series belongs to.",
:series_annotations => "AbstractVector of String or PlotText. These are annotations which are mapped to data points/positions.",

View File

@ -272,6 +272,7 @@ const _series_defaults = KW(
:normalize => false, # do we want a normalized histogram?
:weights => nothing, # optional weights for histograms (1D and 2D)
:contours => false, # add contours to 3d surface and wireframe plots
:contour_labels => false,
:match_dimensions => false, # do rows match x (true) or y (false) for heatmap/image/spy? see issue 196
# this ONLY effects whether or not the z-matrix is transposed for a heatmap display!
:subplot => :auto, # which subplot(s) does this series belong to?
@ -574,6 +575,7 @@ add_aliases(:gridstyle, :grid_style, :gridlinestyle, :grid_linestyle, :grid_ls,
add_aliases(:framestyle, :frame_style, :frame, :axesstyle, :axes_style, :boxstyle, :box_style, :box, :borderstyle, :border_style, :border)
add_aliases(:tick_direction, :tickdirection, :tick_dir, :tickdir, :tick_orientation, :tickorientation, :tick_or, :tickor)
add_aliases(:camera, :cam, :viewangle, :view_angle)
add_aliases(:contour_labels, :contourlabels, :clabels, :clabs)
# add all pluralized forms to the _keyAliases dict
for arg in keys(_series_defaults)

View File

@ -45,6 +45,7 @@ const _gr_attr = merge_with_base_supported([
:framestyle,
:tick_direction,
:camera,
:contour_labels,
])
const _gr_seriestype = [
:path, :scatter,
@ -1055,24 +1056,28 @@ function gr_display(sp::Subplot{GRBackend}, w, h, viewport_canvas)
elseif st == :contour
zmin, zmax = clims
GR.setspace(zmin, zmax, 0, 90)
if typeof(series[:levels]) <: Array
if typeof(series[:levels]) <: AbstractArray
h = series[:levels]
else
h = linspace(zmin, zmax, series[:levels])
h = series[:levels] > 1 ? linspace(zmin, zmax, series[:levels]) : [(zmin + zmax) / 2]
end
if series[:fillrange] != nothing
GR.surface(x, y, z, GR.OPTION_CELL_ARRAY)
else
GR.setlinetype(gr_linetype[series[:linestyle]])
GR.setlinewidth(max(0, series[:linewidth] / (sum(gr_plot_size) * 0.001)))
GR.contour(x, y, h, z, 1000)
if plot_color(series[:linecolor]) == [plot_color(:black)]
GR.contour(x, y, h, z, 0 + (series[:contour_labels] == true ? 1 : 0))
else
GR.contour(x, y, h, z, 1000 + (series[:contour_labels] == true ? 1 : 0))
end
end
# create the colorbar of contour levels
if cmap
gr_set_line(1, :solid, yaxis[:foreground_color_axis])
gr_set_viewport_cmap(sp)
l = round.(Int32, 1000 + (h - ignorenan_minimum(h)) / (ignorenan_maximum(h) - ignorenan_minimum(h)) * 255)
l = (length(h) > 1) ? round.(Int32, 1000 + (h - ignorenan_minimum(h)) / (ignorenan_maximum(h) - ignorenan_minimum(h)) * 255) : Int32[1000, 1255]
GR.setwindow(xmin, xmax, zmin, zmax)
GR.cellarray(xmin, xmax, zmax, zmin, 1, length(l), l)
ztick = 0.5 * GR.tick(zmin, zmax)

View File

@ -45,6 +45,7 @@ const _plotly_attr = merge_with_base_supported([
:framestyle,
:tick_direction,
:camera,
:contour_labels,
])
const _plotly_seriestype = [
@ -432,6 +433,14 @@ 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=α), α)
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], α))]]
else
vals = linspace(0.0, 1.0, length(c))
return [[vals[i], rgba_string(plot_color(c[i], α))] for i in eachindex(c)]
end
end
# plotly_colorscale(c, alpha = nothing) = plotly_colorscale(cgrad(), alpha)
@ -557,7 +566,7 @@ function plotly_series(plt::Plot, series::Series)
d_out[:x], d_out[:y], d_out[:z] = x, y, z
# d_out[:showscale] = series[:colorbar] != :none
d_out[:ncontours] = series[:levels]
d_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines")
d_out[:contours] = KW(:coloring => series[:fillrange] != nothing ? "fill" : "lines", :showlabels => series[:contour_labels] == true)
d_out[:colorscale] = plotly_colorscale(series[:linecolor], series[:linealpha])
d_out[:showscale] = hascolorbar(sp)

View File

@ -42,6 +42,7 @@ const _pyplot_attr = merge_with_base_supported([
:framestyle,
:tick_direction,
:camera,
:contour_labels,
])
const _pyplot_seriestype = [
:path, :steppre, :steppost, :shape,
@ -645,15 +646,23 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
extrakw[:extend3d] = true
end
if typeof(series[:linecolor]) <: AbstractArray
extrakw[:colors] = py_color.(series[:linecolor])
else
extrakw[:cmap] = py_linecolormap(series)
end
# contour lines
handle = ax[:contour](x, y, z, levelargs...;
label = series[:label],
zorder = series[:series_plotindex],
linewidths = py_dpi_scale(plt, series[:linewidth]),
linestyles = py_linestyle(st, series[:linestyle]),
cmap = py_linecolormap(series),
extrakw...
)
if series[:contour_labels] == true
PyPlot.clabel(handle, handle[:levels])
end
push!(handles, handle)
# contour fills
@ -661,7 +670,6 @@ function py_add_series(plt::Plot{PyPlotBackend}, series::Series)
handle = ax[:contourf](x, y, z, levelargs...;
label = series[:label],
zorder = series[:series_plotindex] + 0.5,
cmap = py_fillcolormap(series),
extrakw...
)
push!(handles, handle)

View File

@ -575,7 +575,10 @@ _update_clims(zmin, zmax, emin, emax) = min(zmin, emin), max(zmax, emax)
function hascolorbar(series::Series)
st = series[:seriestype]
hascbar = st in (:heatmap, :contour)
hascbar = st == :heatmap
if st == :contour
hascbar = (isscalar(series[:levels]) ? (series[:levels] > 1) : (length(series[:levels]) > 1)) && (length(unique(Array(series[:z]))) > 1)
end
if series[:marker_z] != nothing || series[:line_z] != nothing || series[:fill_z] != nothing
hascbar = true
end