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

Segmentation Fault on adding BBoxImage to matshow #2963

Closed
JasperVanDenBosch opened this issue Apr 9, 2014 · 13 comments
Closed

Segmentation Fault on adding BBoxImage to matshow #2963

JasperVanDenBosch opened this issue Apr 9, 2014 · 13 comments

Comments

@JasperVanDenBosch
Copy link

I am trying to add an image to axes with matshow() but getting Segmentation fault (core dumped) (no stacktrace). When replacing the matshow with a simple e.g. plot(range(10)), it works as expected.

from matplotlib.image import BboxImage,imread
from matplotlib.transforms import Bbox
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111)
#ax.plot(range(10))                           # this works
ax.matshow(np.array([[1,2],[3,4]]))    #this doesn't
lowerCorner = ax.transData.transform((.8,-.8))
upperCorner = ax.transData.transform((1.2,-.4))
bbox_image = BboxImage(Bbox([lowerCorner[0],
                             lowerCorner[1],
                             upperCorner[0],
                             upperCorner[1],
                             ]),
                       norm = None, origin=None, clip_on=False)
path = '/usr/share/pixmaps/firefox.png' # example image available on ubuntu
image = imread(path)
bbox_image.set_data(image)
ax.add_artist(bbox_image)
plt.show()

Thanks for matplotlib!
Jasper

@tacaswell
Copy link
Member

what version of mpl are you using and how did you install it?

@JasperVanDenBosch
Copy link
Author

I'm using the one in the ubuntu repositories, 1.1.1rc

@tacaswell
Copy link
Member

I can not reproduce this with a current version of mpl.

Does imshow fair any better?

@JasperVanDenBosch
Copy link
Author

No, imshow causes the same error.

Upgrading to matplotlib==1.3.1 didn't help either for me.

@tacaswell
Copy link
Member

What backend are you using? plt.get_backend()

Is there anything peculiar about your system? Any non-standard libraries installed?

What version of numpy? iirc there was a persistent issue related to eye and multiarray or something like that a while ago that I don't think we ever got resolved.

maybe related : #2346 and #2354 (long shot)

@JasperVanDenBosch
Copy link
Author

>>> plt.get_backend()
'GTK3Agg'

numpy==1.8.1

It's a pretty fresh install of Ubuntu 12.04, fast workstation (12 cores, 128GB RAM). Can't think of any unusual libraries.

Here is a full pip freeze: https://gist.github.com/ilogue/10301235

@tacaswell
Copy link
Member

never mind, I can reproduce this. I miss understood the OP

@tacaswell tacaswell added this to the v1.4.0 milestone Apr 9, 2014
@JasperVanDenBosch
Copy link
Author

And here is a full python -v: https://gist.github.com/ilogue/10302181

Seems the last thing it does is call Cairo.

If I repeat the last statement:

>>> import gi._gi_cairo
__main__:1: Warning: g_ptr_array_add: assertion `array' failed

But the debug output for working version, with plot() ends with the same statement

@tacaswell
Copy link
Member

It happens with Qt4Agg as well which does not touch cairo so I suspect that is a false lead. @mdboom Can you take a look at this one? This is coming out of Agg someplace as I can get the segfault using the agg bare backend. It also seems to fail for the vector backends, but iirc they end up calling agg to deal with images.

@solvents
Copy link
Contributor

Well, the actual segfault comes from tkinter... they might be interested in this as well.
Edit: not related to tkinter

As far as I can tell, the critical difference between using matshow and plot here is that the y limit for ax is inverted after using matshow with autoscaling enabled.

That makes sense (to me at least), as well as the resulting transform of the corners having inverted y values. One fix to the example given, suggesting BboxImage doesn't handle inverted Bboxes in this case:

lowerCorner = ax.transData.transform((.8,-.8))
upperCorner = ax.transData.transform((1.2,-.4))
upperCorner = [upperCorner[1], upperCorner[0]]
bbox_image = BboxImage(Bbox([lowerCorner[0],

Note: the firefox image shows up somewhere else (the values of lowerCorner, upperCorner were, before this change, [402.4, 501.6] and [412.8, 489.6]).

It may just require a simple fix somewhere in BboxImage, but I didn't investigate any further. I did try changing this code (in BboxImage's constructor)

self.bbox = bbox

to

pts = bbox.get_points()
xs, ys = pts[0], pts[1]
self.bbox = Bbox([[xs.min(), xs.max()], [ys.min(), ys.max()]])

and it seemed to work (all tests passed). This is just speculation but there may be a C loop underneath tkinter of the form

for (i = ymin; i < ymax; i++)
    ...
    px[width*i + x] = ...

which uses the bbox returned from BboxImage.get_window_extent()

As for an actual fix, you'd need to test for isinstance(bbox, BboxBase) and decide whether changing the Bbox used to create an ImageBbox is supposed to have side effects on the ImageBbox or not.

@tacaswell
Copy link
Member

I am suspicious that it is rooted in tinker because I see it in Qt4, which should not be touching tk.

@JasperVanDenBosch
Copy link
Author

Thanks @solvents, that works for me. I didn't think of the inverted axis.

solvents added a commit to solvents/matplotlib that referenced this issue Apr 26, 2014
Image::resize will now raise a runtime error if the user passes in an invalid width or height.
BboxImage.make_image will now ensure that the width and height it passes to Image::resize are positive or zero.
BboxImage.draw will now calculate the bottom left corner of its Bbox, rather than using the "first" corner of its Bbox.
solvents added a commit to solvents/matplotlib that referenced this issue Apr 26, 2014
Image::resize will now raise a runtime error if the user passes in an invalid width or height.
BboxImage.make_image will now ensure that the width and height it passes to Image::resize are positive or zero.
BboxImage.draw now calculates the bottom left corner of its Bbox, rather than using the "first" corner of its Bbox.
@tacaswell
Copy link
Member

Closing as #3009 has been merged.

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

3 participants