I am creating a figure with 6 filled contour plots and a color bar (so, 7 axes total). The function creating the figure loops over a list of variable pairs and arranges the axes in 3x2 pattern with colorbar at the bottom, with a call to figure.colorbar at the end taking the last contourf call's output as leading input.
The problem - all out-of-range colors appear to be colored in as the "adjacent" color in the colorbar, except for the very last contourf plot, which seems to work as expected. But, commenting out the line that creates the colorbar results in the last plot also being broken (no "extended" colors).
All of the calls to contourf (inside of the loop) look like this; the levels and corresponding colors are fixed
plot = axes.contourf(aggregates_xs, aggregates_ys, aggregates_zs, color_levels, colors = color_values, extend = 'both'
plot.cmap.set_over('red')
plot.cmap.set_under('blue')
matplotlib version 3.0.2 (same behavior in 2.0.2, but I didn't guess to try removing the colorbar before updating)
Right, here is a minimal working example that replicates the logic of what I'm doing and produces the apparent bug:
import matplotlib.pylab as plt
#Create synthetic data
axis_values = [x for x in range(1,20)]
height_values = [[x*y for x in axis_values] for y in axis_values]
#See minimal and maximal height values
print(min([min(x) for x in height_values])) #1
print(max([max(x) for x in height_values])) #361
#Color levels and values
color_levels = [5, 10, 50, 100, 300]
color_values = ['#cecece', '#a5a5a5', '#868686', '#656565', '#3b3b3b']
#Create figure
current_figure = plt.figure(figsize = (5.0, 3.0))
axes_1 = current_figure.add_axes([0.0, 0.0, 0.5, 0.5])
axes_2 = current_figure.add_axes([0.5, 0.0, 0.5, 0.5])
plot_1 = axes_1.contourf(axis_values, axis_values, height_values, color_levels, colors = color_values, extend = 'both')
plot_1.cmap.set_over('red')
plot_1.cmap.set_under('blue')
plot_2 = axes_2.contourf(axis_values, axis_values, height_values, color_levels, colors = color_values, extend = 'both')
plot_2.cmap.set_over('red')
plot_2.cmap.set_under('blue')
#Add colorbar
caxes = current_figure.add_axes()
current_figure.colorbar(plot_2, cax = caxes, orientation = 'horizontal')
plt.show(current_figure)
You can easily check that switching to plot_1 results in out of range values on the first set of axes being properly colored in red/blue. Commenting out the colorbar lines removes red/blue colors from both sets of axes.
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
Activity
timhoffm commented on Dec 22, 2018
Can you please post a full minimal example, including code and the resulting figure?
alexlimonov commented on Dec 22, 2018
Right, here is a minimal working example that replicates the logic of what I'm doing and produces the apparent bug:
import matplotlib.pylab as plt #Create synthetic data axis_values = [x for x in range(1,20)] height_values = [[x*y for x in axis_values] for y in axis_values] #See minimal and maximal height values print(min([min(x) for x in height_values])) #1 print(max([max(x) for x in height_values])) #361 #Color levels and values color_levels = [5, 10, 50, 100, 300] color_values = ['#cecece', '#a5a5a5', '#868686', '#656565', '#3b3b3b'] #Create figure current_figure = plt.figure(figsize = (5.0, 3.0)) axes_1 = current_figure.add_axes([0.0, 0.0, 0.5, 0.5]) axes_2 = current_figure.add_axes([0.5, 0.0, 0.5, 0.5]) plot_1 = axes_1.contourf(axis_values, axis_values, height_values, color_levels, colors = color_values, extend = 'both') plot_1.cmap.set_over('red') plot_1.cmap.set_under('blue') plot_2 = axes_2.contourf(axis_values, axis_values, height_values, color_levels, colors = color_values, extend = 'both') plot_2.cmap.set_over('red') plot_2.cmap.set_under('blue') #Add colorbar caxes = current_figure.add_axes() current_figure.colorbar(plot_2, cax = caxes, orientation = 'horizontal') plt.show(current_figure)You can easily check that switching to plot_1 results in out of range values on the first set of axes being properly colored in red/blue. Commenting out the colorbar lines removes red/blue colors from both sets of axes.
alexlimonov commented on Dec 22, 2018
There is, however, an ugly workaround - adding a phantom colorbar for each set of axes, by inserting the following line,
current_figure.colorbar(plot_1, cax = caxes, orientation = 'horizontal', fraction = 0.0, shrink = 0.0, pad = 0.0, ticks = [])
timhoffm commented on Dec 25, 2018
Reason / Solution
The QuadContourSets do not get notified that the colormap is modified when you do:
plot_1.cmap.set_over('red') plot_1.cmap.set_under('blue')Therefore, please add plot_1.changed() after modifying the colormap. (Same with plot_2).
The partial update happens because you add a colorbar to plot_2. This calls plot_2.changed() internally.
github-actions commented on May 25, 2023
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
rcomer commented on Jun 3, 2023
I think this was addressed by the documentation update at #13047.