-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Bug when saving to vector format (pdf, svg, eps) #2831
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
Comments
That is bad. This is maybe related to #2889 ? Can confirm this on master. If you set the dpi to 100 it more-or-less works correctly, you can see the corners of the red sequare outside of the edges of the annotation box, but it is in the right place. |
I've not seen the picture, but it is worth noting that the issue there was highlighted by a change which was applied after v1.3.1. Though it could be the same underlying bug, none-the-less. |
Interestingly, if you don't specify the correct DPI at savefig for PNG, the red box is also in the wrong place. Something is a little fishy there... |
@pelson The similarity is (I think) related to using |
Agreed. The issue can be seen with all backends with a simple modification to @wronk 's code:
The key is that the red box only appears after the figure has been re-drawn. The change in x/y limit is significant here. |
@pelson @efiring @mdboom I am going to punt this and the related issues to 1.5 (at least). My understanding of the problem here is that artists are being lined up in screen-space (through I will create an issue to add a note to |
@tacaswell - do you know if #3054 fixes this issue? |
I don't, but should probably check (I left this comment before I found that patch). |
This does seem like quite a fundamental problem; a full solution might require a dependency-tracking system. This reminds me of the lazy evaluation system (implemented via a C++ extension) that JDH originally used in mpl. Is it the case that get_window_extent can be used safely only inside a |
Using In the above case, And I agree with Eric that we need some sort of dependency-tracking. For the current example, here is a work-around. It defines a function that update the extent of def annoate_get_window_extent(renderer):
midBox3.update_positions(renderer)
Text.update_bbox_position_size(midBox3, renderer)
rr = midBox3.get_bbox_patch().get_window_extent(renderer)
return rr
gradient = BboxImage(annoate_get_window_extent,
data=np.zeros_like(np.atleast_2d(np.arange(256)/256.)))
ax.add_artist(gradient) Looking at the code above, I strongly feel that it should be simpler than this though. |
I re-milestoned this as 1.5.x as it seems that nothing in behaving incorrectly, just inconveniently. Tacking automatic tracking of changing on to the frame work sounds like it will be a good deal of work (if it is possible) and there is a work-around (which I agree works... @wronk Does the work-around work for you? |
That project is on the back burner for me at the moment, but I'll give it a On Sat, Jun 28, 2014 at 6:16 PM, Thomas A Caswell [email protected]
|
This is in response to issues raised in matplotlib#2831. Closes matplotlib#3055
This is in response to issues raised in matplotlib#2831. Closes matplotlib#3055
(Encountered this issue while generating a figure for my publication and signed up on github to tell you this) I tried this on Jupyter notebook and it generated wrong vector figure. When I copied the "same exact code" to IPython console, problem gone :) I don't know why. |
@sirenayka Can you be a bit more specific about what code you ran? I suspect the the effect was getting 'lucky' about what order things ran in. |
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help! |
This is a strange one. If I run it as-is, I see nothing in the PDF but the text. If I change the code to save the PNG first, then the PDF starts showing the image, but it disappears from the PNG. If I then change figure DPI to 72 (which matches PDF's internal DPI), then the image moves under the text. I guess this has to do with #2831 (comment) |
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help! |
I still see the same as reported by @QuLogic in that there is just the text, no box, in the PDF |
This "fixes" the problem ...: if saveFig:
...: pdfFile = PdfPages(save_fname + 'flowchart_PDF.pdf')
...: plt.savefig(BytesIO(), format='pdf', dpi=fig.dpi)
...: plt.savefig(pdfFile, format='pdf', dpi=fig.dpi)
...: pdfFile.close()
...: plt.savefig(save_fname + 'flowchart_PNG.png', dpi=fig.dpi)
...: plt.show() |
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help! |
Re-evaluating this, I think @leejjoon is completely correct. The source of the problem is that for zorder reasons we have to draw the background before the text, but the text does not know how big it is before has been drawn. Short of implementing a system to automatically detect when we need to render multiple times there are two fixes:
|
Does this work? I believe not reliably just with a If I do:
the |
Another approach would be to use a callable object that explicitly update the position of the text and the patch. This does not require rendering the figure twice def get_bbox(renderer):
midBox3.update_positions(renderer)
midBox3.update_bbox_position_size(renderer)
return midBox3.get_bbox_patch().get_window_extent(renderer)
arr = np.atleast_2d(np.arange(256)/256.)
bbox_image = BboxImage(get_bbox, data=arr)
ax.add_artist(bbox_image) Yet another option is to use patheffects. The example code below uses from matplotlib.patheffects import Normal
from mpl_visual_context.patheffects import FillImage
bbox_image = BboxImage(midBox4.get_bbox_patch().get_window_extent,
data=arr)
midBox3.get_bbox_patch().set_path_effects([FillImage(bbox_image, ax=ax),
Normal()]) |
My understanding is that in similar cases (passing @leejjoon's suggestion will work 100% with only one save, but requires the user to know which methods to call to update the correct state. |
There is a discrepancy between vector format (pdf, svg, eps) output and image output (png, jpg, etc) for the BboxImage object. I can't attach a pdf, but the this code creates and saves a pdf and png illustrating the BboxImage object translation. Just update the save folder path to run the code.
Thanks and let me know if I should include anything else.
(tacaswell edited for code markup)
The text was updated successfully, but these errors were encountered: