fmihpc/analysator

parula colormap mismatch

Closed this issue · 14 comments

Plotting with parula with Python 3.10 and matplotlib 3.5.1 on Windows 11 throws

Using matplotlib version 3.5.1
Traceback (most recent call last):
  File "script.py", line 9, in <module>
    pt.plot.plot_colormap3dslice(
  File "analysator-master/pyPlots\plot_colormap3dslice.py", line 1065, in plot_colormap3dslice
    norm = BoundaryNorm(levels, ncolors=cmapuse.N, clip=True)
  File "Python\Python310\lib\site-packages\matplotlib\colors.py", line 1781, in __init__  
    raise ValueError(f"There are {self._n_regions} color bins "
ValueError: There are 253 color bins including extensions, but ncolors = 64; ncolors must equal or exceed the number of bins   

(some paths shortened)
@alhom does not reproduce on his system, so it's unclear what the "actual" cause is.

Hmm, let's look at this again if someone is able to reproduce on a system we use more often.

I can reproduce on mahti.

Sorry.

Ok. Can you try replacing

cmaps[name] = ListedColormap(data, name=name)

cmaps[name] = ListedColormap(data, name=name)
with
cmaps[name] = matplotlib.colors.LinearSegmentedColormap.from_list(data, name=name)
and see if that helps?

I modified the import a few lines above but then it throws

Traceback (most recent call last):
  File "plot_evol_multiplane.py", line 1, in <module>
    import pytools as pt
  File "/users/kempf/analysator/pytools.py", line 107, in <module>
    import plot
  File "/users/kempf/analysator/pyPlots/plot.py", line 40, in <module>
    import colormaps as cmaps
  File "/users/kempf/analysator/pyPlots/colormaps.py", line 1119, in <module>
    cmaps[name] = LinearSegmentedColormap.from_list(data, name=name)
TypeError: from_list() got multiple values for argument 'name'

ah whoops. Try cmaps[name] = matplotlib.colors.LinearSegmentedColormap.from_list(name, data) instead?

Traceback (most recent call last):
  File "plot_evol_multiplane.py", line 1, in <module>
    import pytools as pt
  File "/users/kempf/analysator/pytools.py", line 107, in <module>
    import plot
  File "/users/kempf/analysator/pyPlots/plot.py", line 65, in <module>
    plt.register_cmap(name='parula_r', cmap=matplotlib.colors.ListedColormap(cmaps.parula.colors[::-1]))
AttributeError: 'LinearSegmentedColormap' object has no attribute 'colors'
alhom commented

So colors is a member of ListedColormap, not LinearSegmentedColormap (that has the more complex _segmentdata). LinearSegmentedColormap (and the base Colormap class!) has the method reversed that can be used instead to get the reversed cmap, so plt.register_cmap(name='parula_r', cmap=cmaps.parula.reversed)?

See #168.

@alhom this yields

Traceback (most recent call last):
  File "plot_evol_multiplane.py", line 210, in <module>
    plt.savefig(outputdir+outputfile, dpi=300, bbox_inches='tight', pad_inches=0.01)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/pyplot.py", line 859, in savefig
    res = fig.savefig(*args, **kwargs)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/figure.py", line 2311, in savefig
    self.canvas.print_figure(fname, **kwargs)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/backend_bases.py", line 2193, in print_figure
    self.figure.draw(renderer)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/figure.py", line 1863, in draw
    mimage._draw_list_compositing_images(
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/image.py", line 131, in _draw_list_compositing_images
    a.draw(renderer)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/cbook/deprecation.py", line 411, in wrapper
    return func(*inner_args, **inner_kwargs)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/axes/_base.py", line 2747, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/image.py", line 131, in _draw_list_compositing_images
    a.draw(renderer)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/artist.py", line 41, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/collections.py", line 2024, in draw
    self.update_scalarmappable()
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/collections.py", line 855, in update_scalarmappable
    self._facecolors = self.to_rgba(self._A, self._alpha)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/cm.py", line 333, in to_rgba
    rgba = self.cmap(x, alpha=alpha, bytes=bytes)
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/colors.py", line 568, in __call__
    self._init()
  File "/appl/opt/python/3.8.6-gnu930/lib/python3.8/site-packages/matplotlib-3.3.3-py3.8-linux-x86_64.egg/matplotlib/colors.py", line 760, in _init
    self.N, self._segmentdata['red'], self._gamma)
TypeError: 'NoneType' object is not subscriptable

parula_r can be constructed in colormaps.py the same way e.g. hot_desaturated_colormap_r is, and then registered in plot.py

So the reversed() works, but do you prefer the other way?

alhom commented

LinearSegmentedColormap.reversed() was added six years ago to Matplotlib. Is that good enough backwards compatibility? v.2.1.

Is this issue still an issue?