8000 Tutorial pyplot_scales.py crashes when used with plt.tight_layout() · Issue #6789 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Tutorial pyplot_scales.py crashes when used with plt.tight_layout() #6789

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
4 tasks done
afvincent opened this issue Jul 18, 2016 · 5 comments
Closed
4 tasks done

Tutorial pyplot_scales.py crashes when used with plt.tight_layout() #6789

afvincent opened this issue Jul 18, 2016 · 5 comments

Comments

@afvincent
Copy link
Contributor

Trying to replace plt.subplots_adjust with plt.tight_layout in the pyplot tutorial pyplot_scales.py (see #6779), seems to results in errors.

  • Matplotlib version, Python version and Platform (Windows, OSX, Linux ...):
  • Linux (at least Archlinux and CentOs 7)
  • Tested on mpl 1.5.1 from Anaconda and mpl 2.0.0b3.post1799+ga4fdd60 from github
  • MWE (kind of…):
    Based on pyplot_scales.py:
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('default')

# make up some data in the interval ]0, 1[
y = np.random.normal(loc=0.5, scale=0.4, size=1000)
y = y[(y > 0) & (y < 1)]
y.sort()
x = np.arange(len(y))

plt.figure(1)
plt.subplot(221)
plt.subplot(222)
plt.subplot(223)

# logit
plt.subplot(224)
plt.plot(x, y)
plt.yscale('logit')
#plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
#                    wspace=0.35)
plt.tight_layout()

plt.show()

When I run this example with plt.tight_layout instead of plt.subplots_adjust (or simply no subplot layout adjusting at all), I get these outputs (mpl 2.0.0b3.post1799+ga4fdd60):

  • with Qt4Agg backend
In [1]: run pyplot_scales_mwe.py  # that's the MWE posted above
/home/adrien/matplotlib/lib/matplotlib/transforms.py:380: RuntimeWarning: invalid value encountered in double_scalars
  return points[1, 0] - points[0, 0]
/home/adrien/matplotlib/lib/matplotlib/tight_layout.py:199: RuntimeWarning: invalid value encountered in double_scalars
  kwargs["wspace"] = hspace / h_axes
/home/adrien/matplotlib/lib/matplotlib/axis.py:1008: UserWarning: Unable to find pixel distance along axis for interval padding of ticks; assuming no interval padding needed.
  warnings.warn("Unable to find pixel distance along axis "
/home/adrien/matplotlib/lib/matplotlib/axis.py:1018: UserWarning: Unable to find pixel distance along axis for interval padding of ticks; assuming no interval padding needed.
  warnings.warn("Unable to find pixel distance along axis "

Traceback (most recent call last):
  File "/home/adrien/matplotlib/lib/matplotlib/backends/backend_qt5agg.py", line 182, in __draw_idle_agg
    FigureCanvasAgg.draw(self)
  File "/home/adrien/matplotlib/lib/matplotlib/backends/backend_agg.py", line 464, in draw
    self.figure.draw(self.renderer)
  File "/home/adrien/matplotlib/lib/matplotlib/artist.py", line 68, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/adrien/matplotlib/lib/matplotlib/figure.py", line 1262, in draw
    renderer, self, dsu, self.suppressComposite)
  File "/home/adrien/matplotlib/lib/matplotlib/image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/adrien/matplotlib/lib/matplotlib/artist.py", line 68, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/adrien/matplotlib/lib/matplotlib/axes/_base.py", line 2383, in draw
    mimage._draw_list_compositing_images(renderer, self, dsu)
  File "/home/adrien/matplotlib/lib/matplotlib/image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/adrien/matplotlib/lib/matplotlib/artist.py", line 68, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/adrien/matplotlib/lib/matplotlib/axis.py", line 1109, in draw
    ticks_to_draw = self._update_ticks(renderer)
  File "/home/adrien/matplotlib/lib/matplotlib/axis.py", line 942, in _update_ticks
    tick_tups = [t for t in self.iter_ticks()]
  File "/home/adrien/matplotlib/lib/matplotlib/axis.py", line 885, in iter_ticks
    majorLocs = self.major.locator()
  File "/home/adrien/matplotlib/lib/matplotlib/ticker.py", line 1721, in __call__
    return self.tick_values(vmin, vmax)
  File "/home/adrien/matplotlib/lib/matplotlib/ticker.py", line 1726, in tick_values
    locs = self._raw_ticks(vmin, vmax)
  File "/home/adrien/matplotlib/lib/matplotlib/ticker.py", line 1674, in _raw_ticks
    nbins = max(min(self.axis.get_tick_space(), 9),
  File "/home/adrien/matplotlib/lib/matplotlib/axis.py", line 2008, in get_tick_space
    return int(np.floor(length / size))
ValueError: cannot convert float NaN to integer

which results in
with_tight_layout
(NB: it's a screenshot because savefig complained about the “ValueError: cannot convert float NaN to integer” stuff)

  • with TkAgg backend
In [1]: run pyplot_scales_mwe.py  # that's again the MWE posted above
/home/adrien/matplotlib/lib/matplotlib/transforms.py:380: RuntimeWarning: invalid value encountered in double_scalars
  return points[1, 0] - points[0, 0]
/home/adrien/matplotlib/lib/matplotlib/tight_layout.py:199: RuntimeWarning: invalid value encountere
8000
d in double_scalars
  kwargs["wspace"] = hspace / h_axes
/home/adrien/matplotlib/lib/matplotlib/axis.py:1008: UserWarning: Unable to find pixel distance along axis for interval padding of ticks; assuming no interval padding needed.
  warnings.warn("Unable to find pixel distance along axis "
/home/adrien/matplotlib/lib/matplotlib/axis.py:1018: UserWarning: Unable to find pixel distance along axis for interval padding of ticks; assuming no interval padding needed.
  warnings.warn("Unable to find pixel distance along axis "

Exception in Tkinter callback
Traceback (most recent call last):
  File "/home/adrien/anaconda/envs/Python2.7_matplotlib-git/lib/python2.7/lib-tk/Tkinter.py", line 1536, in __call__
    return self.func(*args)
  File "/home/adrien/matplotlib/lib/matplotlib/backends/backend_tkagg.py", line 283, in resize
    self.show()
  File "/home/adrien/matplotlib/lib/matplotlib/backends/backend_tkagg.py", line 354, in draw
    FigureCanvasAgg.draw(self)
  File "/home/adrien/matplotlib/lib/matplotlib/backends/backend_agg.py", line 464, in draw
    self.figure.draw(self.renderer)
  File "/home/adrien/matplotlib/lib/matplotlib/artist.py", line 68, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/adrien/matplotlib/lib/matplotlib/figure.py", line 1262, in draw
    renderer, self, dsu, self.suppressComposite)
  File "/home/adrien/matplotlib/lib/matplotlib/image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/adrien/matplotlib/lib/matplotlib/artist.py", line 68, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/adrien/matplotlib/lib/matplotlib/axes/_base.py", line 2383, in draw
    mimage._draw_list_compositing_images(renderer, self, dsu)
  File "/home/adrien/matplotlib/lib/matplotlib/image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "/home/adrien/matplotlib/lib/matplotlib/artist.py", line 68, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "/home/adrien/matplotlib/lib/matplotlib/axis.py", line 1109, in draw
    ticks_to_draw = self._update_ticks(renderer)
  File "/home/adrien/matplotlib/lib/matplotlib/axis.py", line 942, in _update_ticks
    tick_tups = [t for t in self.iter_ticks()]
  File "/home/adrien/matplotlib/lib/matplotlib/axis.py", line 885, in iter_ticks
    majorLocs = self.major.locator()
  File "/home/adrien/matplotlib/lib/matplotlib/ticker.py", line 1721, in __call__
    return self.tick_values(vmin, vmax)
  File "/home/adrien/matplotlib/lib/matplotlib/ticker.py", line 1726, in tick_values
    locs = self._raw_ticks(vmin, vmax)
  File "/home/adrien/matplotlib/lib/matplotlib/ticker.py", line 1674, in _raw_ticks
    nbins = max(min(self.axis.get_tick_space(), 9),
  File "/home/adrien/matplotlib/lib/matplotlib/axis.py", line 2008, in get_tick_space
    return int(np.floor(length / size))
ValueError: cannot convert float NaN to integer

which produces an empty figure.

  • If this is an image generation bug attach a screenshot demonstrating the issue:
    See above.
  • If this is a regression (Used to work in an earlier version of Matplotlib), please
    note where it used to work:
    The behavior seems to be the same with mpl 1.5.1 and (at least) both TkAgg and Qt4Agg backends.
@tacaswell tacaswell added this to the 2.0.1 (next bug fix release) milestone Jul 22, 2016
@dstansby
Copy link
Member
dstansby commented Jan 19, 2017

Here's a more minimalist example that throws the same error as above:

import matplotlib.pyplot as plt

fig, axs = plt.subplots(2, 2)

axs[1, 1].set_yscale('logit')
plt.tight_layout()
plt.show()

@dstansby
Copy link
Member

Todo (see #7880):

  • Make tight_layout ignore artists at non-finite positions

@dstansby dstansby self-assigned this Feb 11, 2017
@janmedlock
Copy link

I've hit this bug, too. A slightly different minimal example, that doesn't depend on tight_layout:

import matplotlib.pyplot as plt

plt.plot([0.1, 0.9], [1, 2])
plt.xscale('logit')
plt.xlabel('x')
plt.show()

Rendering with QT5Agg causes a similar error as in the original report:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/matplotlib/backends/backend_qt5agg.py", g
    FigureCanvasAgg.draw(self)
  File "/usr/lib/python3/dist-packages/matplotlib/backends/backend_agg.py", linw
    self.figure.draw(self.renderer)
  File "/usr/lib/python3/dist-packages/matplotlib/artist.py", line 63, in draw_r
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/matplotlib/figure.py", line 1143, in draw
    renderer, self, dsu, self.suppressComposite)
  File "/usr/lib/python3/dist-packages/matplotlib/image.py", line 139, in _draws
    a.draw(renderer)
  File "/usr/lib/python3/dist-packages/matplotlib/artist.py", line 63, in draw_r
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/matplotlib/axes/_base.py", line 2409, inw
    mimage._draw_list_compositing_images(renderer, self, dsu)
  File "/usr/lib/python3/dist-packages/matplotlib/image.py", line 139, in _draws
    a.draw(renderer)
  File "/usr/lib/python3/dist-packages/matplotlib/artist.py", line 63, in draw_r
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/matplotlib/axis.py", line 1150, in draw
    self.label.draw(renderer)
  File "/usr/lib/python3/dist-packages/matplotlib/artist.py", line 63, in draw_r
    draw(artist, renderer, *args, **kwargs)
  File "/usr/lib/python3/dist-packages/matplotlib/text.py", line 762, in draw
    raise ValueError("posx and posy should be finite values")
ValueError: posx and posy should be finite values

I tried all the backends on my machine, with the same result (but perhaps slightly different error messages).

The script works fine if plt.xlabel() is removed, so I investigated the labeling code. Before rendering the label's position (using plt.gca().xaxis.get_label().get_position()) is (0.5, 0) and after rendering it is (0.5, -inf).

Setting the y position to -inf happens in matplotlib.axis.XAxis._update_label_position(), which gets called during rendering. Both before and after (partial?) rendering, plt.gca().spines['bottom'].get_path() is Path(array([[13., 0.], [13., 0.]]), None). But the transformed path,

spine = plt.gca().spines['bottom']
spinepath = spine.get_transform().transform_path(spine.get_path())

is Path(array([[7373.45454545, 52.8], [7373.45454545, 52.8]]), None) before and Path(array([[nan, nan], [nan, nan]]), None) after (partial?) rendering.

And I'm over my head at this point.

@janmedlock
Copy link

... and calling gca().spines['bottom']._adjust_location() ('bottom' for logit x scale, 'left' for logit y scale) before rendering prevents the error:

import matplotlib.pyplot as plt

plt.plot([0.1, 0.9], [1, 2])
plt.xscale('logit')
plt.xlabel('x')
gca().spines['bottom']._adjust_location()
plt.show()

It also works with dstansby's tight_layout example:

import matplotlib.pyplot as plt

fig, axs = plt.subplots(2, 2)

axs[1, 1].set_yscale('logit')
axs[1, 1].spines['left']._adjust_location()
plt.tight_layout()
plt.show()

@dstansby dstansby removed their assignment Apr 9, 2017
@QuLogic QuLogic modified the milestones: 2.0.1 (next bug fix release), 2.0.2 (next bug fix release) May 3, 2017
@tacaswell tacaswell modified the milestones: 2.1.1 (next bug fix release), 2.2 (next feature release) Oct 9, 2017
@dstansby
Copy link
Member

Seems to be fixed on master, feel free to re-open if it turns out to still be a problem.

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

Successfully merging a pull request may close this issue.

6 participants
0