Skip to content

ColorbarBase fails to show if the first two values map to the same result #11923

Description

@ecerulm

Bug report

When ColorbarBase is used with a custom Normalizer, if the normalizer maps the first two elements of the input to the same output value then it will raise an ValueError: Both *x_transform* and *y_transform* must be 2D affine transforms

Code for reproduction

%matplotlib inline

import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np


plt.close('all')
fig,ax = plt.subplots(1,1)

class MyNorm(mpl.colors.Normalize):

    def __call__(self, value, clip=True):

        if clip is None:
            clip = self.clip

        result, is_scalar = self.process_value(value)

        fixed_result = np.linspace(0,1, len(result))
        fixed_result[1] = fixed_result[0]
        #fixed_result = np.interp(fixed_result, [0,0.0001, 1], [0,0, 1])
        result = np.ma.array(fixed_result)
        return result 
        
        
norm = MyNorm(vmax=12000, vmin=0, clip=False)
#norm = mpl.colors.Normalize(vmin=0, vmax=12000, clip=True)
cmap = plt.get_cmap('RdYlGn_r')  # From red to green
sm = mpl.cm.ScalarMappable(norm=norm, cmap=cmap)
cb1 = mpl.colorbar.ColorbarBase(ax, cmap=cmap, norm=norm, orientation='vertical',
                                ticks=[100, 1000, 10000])
plt.show()

Actual outcome

empty figure canvas

If using module://ipykernel.pylab.backend_inline then console show

# on  module://ipympl.backend_nbagg
C:\appl\Anaconda3\envs\fluidprediction27\lib\site-packages\matplotlib\colorbar.py:890: RuntimeWarning: invalid value encountered in true_divide
  z = np.take(y, i0) + (xn - np.take(b, i0)) * dy / db

# on module://ipykernel.pylab.backend_inline
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
C:\appl\Anaconda3\envs\fluidprediction27\lib\site-packages\IPython\core\formatters.pyc in __call__(self, obj)
    332                 pass
    333             else:
--> 334                 return printer(obj)
    335             # Finally look for special method names
    336             method = get_real_method(obj, self.print_method)

C:\appl\Anaconda3\envs\fluidprediction27\lib\site-packages\IPython\core\pylabtools.pyc in <lambda>(fig)
    245 
    246     if 'png' in formats:
--> 247         png_formatter.for_type(Figure, lambda fig: print_figure(fig, 'png', **kwargs))
    248     if 'retina' in formats or 'png2x' in formats:
    249         png_formatter.for_type(Figure, lambda fig: retina_figure(fig, **kwargs))

C:\appl\Anaconda3\envs\fluidprediction27\lib\site-packages\IPython\core\pylabtools.pyc in print_figure(fig, fmt, bbox_inches, **kwargs)
    129 
    130     bytes_io = BytesIO()
--> 131     fig.canvas.print_figure(bytes_io, **kw)
    132     data = bytes_io.getvalue()
    133     if fmt == 'svg':

C:\appl\Anaconda3\envs\fluidprediction27\lib\site-packages\matplotlib\backend_bases.pyc in print_figure(self, filename, dpi, facecolor, edgecolor, orientation, format, **kwargs)
   2220                 bbox_filtered = []
   2221                 for a in bbox_artists:
-> 2222                     bbox = a.get_window_extent(renderer)
   2223                     if a.get_clip_on():
   2224                         clip_box = a.get_clip_box()

C:\appl\Anaconda3\envs\fluidprediction27\lib\site-packages\matplotlib\patches.pyc in get_window_extent(self, renderer)
    569 
    570     def get_window_extent(self, renderer=None):
--> 571         return self.get_path().get_extents(self.get_transform())
    572 
    573 

C:\appl\Anaconda3\envs\fluidprediction27\lib\site-packages\matplotlib\path.pyc in get_extents(self, transform)
    531         path = self
    532         if transform is not None:
--> 533             transform = transform.frozen()
    534             if not transform.is_affine:
    535                 path = self.transformed(transform)

C:\appl\Anaconda3\envs\fluidprediction27\lib\site-packages\matplotlib\transforms.pyc in frozen(self)
   2240 
   2241     def frozen(self):
-> 2242         return blended_transform_factory(self._x.frozen(), self._y.frozen())
   2243     frozen.__doc__ = Transform.frozen.__doc__
   2244 

C:\appl\Anaconda3\envs\fluidprediction27\lib\site-packages\matplotlib\transforms.pyc in blended_transform_factory(x_transform, y_transform)
   2387     if (isinstance(x_transform, Affine2DBase)
   2388         and isinstance(y_transform, Affine2DBase)):
-> 2389         return BlendedAffine2D(x_transform, y_transform)
   2390     return BlendedGenericTransform(x_transform, y_transform)
   2391 

C:\appl\Anaconda3\envs\fluidprediction27\lib\site-packages\matplotlib\transforms.pyc in __init__(self, x_transform, y_transform, **kwargs)
   2328         is_correct = is_affine and is_separable
   2329         if not is_correct:
-> 2330             raise ValueError("Both *x_transform* and *y_transform* must be 2D "
   2331                              "affine transforms")
   2332 

ValueError: Both *x_transform* and *y_transform* must be 2D affine transforms


Expected outcome

A colorbar where the bottom two lines are the same color.

In the actual case where I encountered I have a custom normalizer in which I wanted to map certain ranges of values to a single color (instead of doing a regular gradient). It works fine unless the first two map to the same color. As an example if you replace fixed_result[1] = fixed_result[0] with fixed_result[2:200] = fixed_result[1] it works.

Matplotlib version

  • Operating system: Windows 7
  • Matplotlib version: 2.2.2
  • Matplotlib backend (print(matplotlib.get_backend())): module://ipympl.backend_nbagg and module://ipykernel.pylab.backend_inline
  • Python version: 2.7.15
  • Jupyter version (if applicable): 5.'5.0
  • Other libraries: module://ipympl.backend_nbagg

Installed via conda official

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions