Skip to content
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

CGContextRef is NULL of tight_layout with MacOSX backend #2654

Closed
eteq opened this issue Dec 5, 2013 · 12 comments
Closed

CGContextRef is NULL of tight_layout with MacOSX backend #2654

eteq opened this issue Dec 5, 2013 · 12 comments

Comments

@eteq
Copy link

eteq commented Dec 5, 2013

This may be related to #166, but has a quite different immediate cause, so I'm reporting it separately. It might be that I should instead report this in ipython, so feel free to redirect me there, if that's more appropriate

If I do the following in ipython started with ipython -pylab=MacOSX :

def dp(x):
    plt.figure()
    plt.plot(x)
    plt.tight_layout()
dp(arange(10))

I get a CGContextRef is NULL exception (full traceback in the first comment). The plot still appears, but it does not have the tight-layout applied. If I change the function instead to:

def dp(x):
    plt.figure()
    plt.plot(x)
    plt.draw()
    plt.tight_layout()

it does work, with no exception.

Not that the same thing also happens if I use subplots instead of a single figure.

@eteq
Copy link
Author

eteq commented Dec 5, 2013

Traceback:

---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
<ipython-input-3-b0df2d66a819> in <module>()
----> 1 dp(randn(10))

<ipython-input-2-a2aa5ad11bf1> in dp(x)
      3     plot(x)
      4     #draw()
----> 5     tight_layout()
      6 

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/pyplot.pyc in tight_layout(pad, h_pad, w_pad, rect)
   1253 
   1254     fig = gcf()
-> 1255     fig.tight_layout(pad=pad, h_pad=h_pad, w_pad=w_pad, rect=rect)
   1256     draw_if_interactive()
   1257 

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/figure.pyc in tight_layout(self, renderer, pad, h_pad, w_pad, rect)
   1603                                          renderer,
   1604                                          pad=pad, h_pad=h_pad, w_pad=w_pad,
-> 1605                                          rect=rect)
   1606 
   1607         self.subplots_adjust(**kwargs)

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/tight_layout.pyc in get_tight_layout_figure(fig, axes_list, subplotspec_list, renderer, pad, h_pad, w_pad, rect)
    350                                      subplot_list=subplot_list,
    351                                      ax_bbox_list=ax_bbox_list,
--> 352                                      pad=pad, h_pad=h_pad, w_pad=w_pad)
    353 
    354     if rect is not None:

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/tight_layout.pyc in auto_adjust_subplotpars(fig, renderer, nrows_ncols, num1num2_list, subplot_list, ax_bbox_list, pad, h_pad, w_pad, rect)
    127         #ax_bbox = union([ax.get_position(original=True) for ax in subplots])
    128 
--> 129         tight_bbox_raw = union([ax.get_tightbbox(renderer) for ax in subplots])
    130         tight_bbox = TransformedBbox(tight_bbox_raw,
    131                                      fig.transFigure.inverted())

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axes.pyc in get_tightbbox(self, renderer, call_axes_locator)
   9155             bb.append(self._right_title.get_window_extent(renderer))
   9156 
-> 9157         bb_xaxis = self.xaxis.get_tightbbox(renderer)
   9158         if bb_xaxis:
   9159             bb.append(bb_xaxis)

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axis.pyc in get_tightbbox(self, renderer)
   1053         ticks_to_draw = self._update_ticks(renderer)
   1054         ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes(ticks_to_draw,
-> 1055                                                                 renderer)
   1056 
   1057         self._update_label_position(ticklabelBoxes, ticklabelBoxes2)

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/axis.pyc in _get_tick_bboxes(self, ticks, renderer)
   1036         for tick in ticks:
   1037             if tick.label1On and tick.label1.get_visible():
-> 1038                 extent = tick.label1.get_window_extent(renderer)
   1039                 ticklabelBoxes.append(extent)
   1040             if tick.label2On and tick.label2.get_visible():

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/text.pyc in get_window_extent(self, renderer, dpi)
    751             raise RuntimeError('Cannot get window extent w/o renderer')
    752 
--> 753         bbox, info, descent = self._get_layout(self._renderer)
    754         x, y = self.get_position()
    755         x, y = self.get_transform().transform_point((x, y))

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/text.pyc in _get_layout(self, renderer)
    318         tmp, lp_h, lp_bl = get_text_width_height_descent('lp',
    319                                                          self._fontproperties,
--> 320                                                          ismath=False)
    321         offsety = (lp_h - lp_bl) * self._linespacing
    322 

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/matplotlib/backends/backend_macosx.pyc in get_text_width_height_descent(self, s, prop, ismath)
    156         points = prop.get_size_in_points()
    157         size = self.points_to_pixels(points)
--> 158         width, height, descent = self.gc.get_text_width_height_descent(unicode(s), family, size, weight, style)
    159         return  width, height, 0.0*descent
    160 

RuntimeError: CGContextRef is NULL

@mdboom
Copy link
Member

mdboom commented Dec 5, 2013

Cc: @mdehoon

@mdehoon
Copy link
Contributor

mdehoon commented Dec 9, 2013

Currently, tight_layout makes the layout tight but does not maintain tightness. So if I call tight_layout but then add a label to an axis or resize the figure, the layout will not be tight anymore (it will be either too tight or not tight enough). Is this how it is supposed to function?

1 similar comment
@mdehoon
Copy link
Contributor

mdehoon commented Dec 9, 2013

Currently, tight_layout makes the layout tight but does not maintain tightness. So if I call tight_layout but then add a label to an axis or resize the figure, the layout will not be tight anymore (it will be either too tight or not tight enough). Is this how it is supposed to function?

@mdehoon
Copy link
Contributor

mdehoon commented Dec 9, 2013

Btw the comment above is relevant for this bug. Depending on how tight_layout is supposed to function, the offending code may need to move to figure.draw. If so, it would be called from inside the event loop, and this bug would go away.

@WeatherGod
Copy link
Member

My understanding has been that this is meant to be a one-shot function, to
be used prior to show() and/or savefig(). A couple years ago, I did put up
a PR for adding a tight_layout() button that could be used in interactive
mode, but it didn't gather enough interest at that time. Of course,
tight_layout() was much less mature at that time, so maybe it is time to
revisit that decision?

@mdehoon
Copy link
Contributor

mdehoon commented Dec 10, 2013

If tight_layout is redesigned, I'd be happy to help out in making sure that this bug doesn't reappear. This shouldn't be too hard: As long as the renderer is only used from inside the event loop callback (i.e., somewhere within the call to figure.draw), everything should be OK. The current tight_layout code on the other hand uses the renderer outside of figure.draw, which is causing this bug.

@amelio-vazquez-reina
Copy link

Having the same problem here myself. Does anyone have any recommendations for alternative backends in OSX? PyQT is giving me some speed problems with ipython (ipython -pylab=qt) with:

backend : QT4Agg
backend.qt4 : PySide

In case it matters, I am using conda.

Thanks,

Josh

@eteq
Copy link
Author

eteq commented Feb 12, 2014

@ribonoous - I've generally used Tk when having problems with the other backends - it seems to nearly always work at least ok.

Another option for the specific problem here is to do gcf().set_tight_layout(True) before plotting. For me that worked, even though the pylab.tight_layout call gave the error here.

@tacaswell tacaswell added the OSX label Feb 25, 2014
@tacaswell tacaswell added this to the v1.5.x milestone Feb 25, 2014
@tacaswell
Copy link
Member

Tagging this as 1.5.x as this seems to involve a major re-write. Please re-milestone if I am wrong.

@absimaHere
Copy link

a temporary solution
Do not include tight_layout in your script/code.
After plotting it, use tight_layout on terminal before/after showing it if you want. Then save it.

@huangshiyu13
Copy link

huangshiyu13 commented Mar 25, 2017

I just add plt.show() before tight_layout() as below. And it works for me.

import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt

sns.set(style="dark")
rs = np.random.RandomState(50)

# Set up the matplotlib figure
f, axes = plt.subplots(3, 3, figsize=(9, 9), sharex=True, sharey=True)

# Rotate the starting point around the cubehelix hue circle
for ax, s in zip(axes.flat, np.linspace(0, 3, 10)):

    # Create a cubehelix colormap to use with kdeplot
    cmap = sns.cubehelix_palette(start=s, light=1, as_cmap=True)

    # Generate and plot a random bivariate dataset
    x, y = rs.randn(2, 50)
    sns.kdeplot(x, y, cmap=cmap, shade=True, cut=5, ax=ax)
    ax.set(xlim=(-3, 3), ylim=(-3, 3))
plt.show()  # I just add this line, and it works
f.tight_layout()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants