Skip to content

math domain error using symlog norm #7595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ngoldbaum opened this issue Dec 9, 2016 · 4 comments
Closed

math domain error using symlog norm #7595

ngoldbaum opened this issue Dec 9, 2016 · 4 comments
Assignees
Milestone

Comments

@ngoldbaum
Copy link
Contributor

ngoldbaum commented Dec 9, 2016

I stumbled across this regression trying to use the matplotlib 2.0 release candidate with yt.

In yt we have a plotting class called SlicePlot that will switch to a symlog colorbar if a user tries to plot a field that we want to be log-scaled because it has a lot of dynamic range but that also has negative values. A very simple yt script (that works fine under matplotlib 1.5.3 but dies with a traceback under 2.0.0rc1) that triggers this looks like:

import yt
ds = yt.load('IsolatedGalaxy/galaxy0030/galaxy0030')
p = yt.SlicePlot(ds, 2, 'x-velocity')
p.save()

To make this easier for people who aren't familiar with yt internals to digest, I've come up with the following test script that only uses matplotlib but triggers what I think is the same error:

import matplotlib
import numpy as np

from matplotlib import pyplot as plt

image = np.array(
    [[-1, -1, -1],
     [0, 0, 0],
     [1, 1, 1]]
)

fig, ax = plt.subplots()

cax = fig.add_axes([0.85, 0.1, 0.1, 0.8])

norm = matplotlib.colors.SymLogNorm(0.1, vmin=-1, vmax=1)

image = ax.imshow(image, norm=norm, vmin=-1, vmax=1)

fig.colorbar(image, cax, format=matplotlib.ticker.LogFormatterMathtext())

plt.savefig('img.png')

It produces the following traceback:

Traceback (most recent call last):
  File "test2.py", line 20, in <module>
    fig.colorbar(image, cax, format=matplotlib.ticker.LogFormatterMathtext())
  File "/usr/local/lib/python3.5/site-packages/matplotlib/figure.py", line 1601, in colorbar
    cb = cbar.colorbar_factory(cax, mappable, **kw)
  File "/usr/local/lib/python3.5/site-packages/matplotlib/colorbar.py", line 1347, in colorbar_factory
    cb = Colorbar(cax, mappable, **kwargs)
  File "/usr/local/lib/python3.5/site-packages/matplotlib/colorbar.py", line 926, in __init__
    ColorbarBase.__init__(self, ax, **kw)
  File "/usr/local/lib/python3.5/site-packages/matplotlib/colorbar.py", line 326, in __init__
    self.draw_all()
  File "/usr/local/lib/python3.5/site-packages/matplotlib/colorbar.py", line 351, in draw_all
    self._config_axes(X, Y)
  File "/usr/local/lib/python3.5/site-packages/matplotlib/colorbar.py", line 447, in _config_axes
    self.update_ticks()
  File "/usr/local/lib/python3.5/site-packages/matplotlib/colorbar.py", line 376, in update_ticks
    ticks, ticklabels, offset_string = self._ticker()
  File "/usr/local/lib/python3.5/site-packages/matplotlib/colorbar.py", line 615, in _ticker
    formatter.set_locs(b)
  File "/usr/local/lib/python3.5/site-packages/matplotlib/ticker.py", line 920, in set_locs
    vmin = math.log(vmin) / math.log(b)
ValueError: math domain error

Under matplotlib 1.5.3 the same script produces the following image:

img

@dopplershift dopplershift added this to the 2.0 (style change major release) milestone Dec 9, 2016
@efiring efiring self-assigned this Dec 9, 2016
@efiring
Copy link
Member

efiring commented Dec 9, 2016

Thanks for the clear example. It looks like this is part of what I am trying to sort our right now, so this additional case is very helpful.

@efiring
Copy link
Member

efiring commented Dec 9, 2016

If you omit the 'format' kwarg, the colorbar tick formatting works as expected.

@ngoldbaum
Copy link
Contributor Author

Hmm, I don't actually know why that was ever necessary. Looks like it was added to yt in 2014 when we added support for symlog scaling:

https://bitbucket.org/yt_analysis/yt/commits/06c5cb9b11174a8d24c6e9f30181c0f03a0da3d9

I think the ticks are still correct under both 1.5.3 and 2.0.0rc1 when I remove the formatter kwarg, would your suggestion just be to remove it?

@efiring
Copy link
Member

efiring commented Dec 9, 2016

I added explicit SymlogNorm support, causing use of the LogFormatterSciNotation, in 2.0. In 1.5.3 it doesn't treat the SymlogNorm specially, so the labels are formatted as ordinary scalars and the ticks are linearly placed. So the format kwarg as you have it helps with 1.5.3. The problem is that with changes in 2.0, the formatter needs an additional kwarg, 'linthresh' (which did not exist in 1.5.3). I think I see how to make it work without that kwarg in a case like this, but without the improvements you get with 2.0 when you don't use the kwarg.

efiring added a commit to efiring/matplotlib that referenced this issue Dec 9, 2016
Closes matplotlib#7595, matplotlib#7493, matplotlib#7587.
Bbox._minpos is now initialized to [np.inf, np.inf] instead of
[1e-7, 1e-7].
Old code with a colorbar in which the formatter is set to
a LogFormatter and a SymlogNorm is used now works again (although
the results are better in 2.0 if the colorbar is left to handle
the formatter automatically).
LogLocator now has its own nonsingular() method which provides
a reasonable starting point for a log axis when no data have
been plotted.
efiring added a commit to efiring/matplotlib that referenced this issue Dec 10, 2016
Closes matplotlib#7595, matplotlib#7493, matplotlib#7587.
Bbox._minpos is now initialized to [np.inf, np.inf] instead of
[1e-7, 1e-7].
Old code with a colorbar in which the formatter is set to
a LogFormatter and a SymlogNorm is used now works again (although
the results are better in 2.0 if the colorbar is left to handle
the formatter automatically).
LogLocator now has its own nonsingular() method which provides
a reasonable starting point for a log axis when no data have
been plotted.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants