Skip to content

Creating colorbar without artist fails with LogNorm #13967

Closed

Description

@dstansby

#13171 documented how to create a colobar that is not associated with an artist. This recipe fails when the colorbar norm is a LogNorm however:

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.colors as mcolor

fig, ax = plt.subplots()
sm = cm.ScalarMappable(norm=mcolor.LogNorm(), cmap='viridis')
fig.colorbar(sm)
plt.draw()

gives

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    fig.colorbar(sm)
  File "/Users/dstansby/github/matplotlib/lib/matplotlib/figure.py", line 2208, in colorbar
    cb = cbar.colorbar_factory(cax, mappable, **cb_kw)
  File "/Users/dstansby/github/matplotlib/lib/matplotlib/colorbar.py", line 1641, in colorbar_factory
    cb = Colorbar(cax, mappable, **kwargs)
  File "/Users/dstansby/github/matplotlib/lib/matplotlib/colorbar.py", line 1183, in __init__
    ColorbarBase.__init__(self, ax, **kw)
  File "/Users/dstansby/github/matplotlib/lib/matplotlib/colorbar.py", line 460, in __init__
    self.draw_all()
  File "/Users/dstansby/github/matplotlib/lib/matplotlib/colorbar.py", line 483, in draw_all
    self._process_values()
  File "/Users/dstansby/github/matplotlib/lib/matplotlib/colorbar.py", line 932, in _process_values
    b = self.norm.inverse(self._uniform_y(self.cmap.N + 1))
  File "/Users/dstansby/github/matplotlib/lib/matplotlib/colors.py", line 1085, in inverse
    return vmin * np.ma.power((vmax / vmin), val)
ZeroDivisionError: division by zero

Changing LogNorm to Normalize makes the example work fine again, as intended.

Activity

  1. anntzer commented on Apr 15, 2019

    @anntzer
    Contributor

    You need to pass in the norm bounds (LogNorm(vmin=..., vmax=...)), otherwise they default to 0..1 -> log(0) -> kaboom (note that unlike "standard" colorbars there's no data to autoscale the norm to).
    I don't think this is a bug, but this could be better documented, perhaps.

  2. dstansby commented on Apr 15, 2019

    @dstansby
    MemberAuthor

    Maybe it would be possible to default to say 0.1, 1 for LogNorm instead?

  3. anntzer commented on Apr 15, 2019

    @anntzer
    Contributor

    Probably rather 1..10 (10^(0..1)) but other than that, why not.

  4. anntzer commented on Apr 16, 2019

    @anntzer
    Contributor

    Ah, but the problem is not on LogNorm's side; it's colorbar() which tries to set the default values (in https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/colorbar.py#L923).
    I actually think it would be fair to say, if the norm is not normalized (so it's not associated to a real mappable with data), then we just throw here.
    Requesting the user to do ScalarMappable(Normalize(42, 123)) or ScalarMappable(LogNorm(1, 10)) instead of trying to guess what extents he wants seems fair...

  5. dstansby commented on May 6, 2019

    @dstansby
    MemberAuthor

    I think that's a fair expectation, closing since there is now a more sensible error message.

  6. added this to the v3.2.0 milestone on May 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions