-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Allow users to decide whether a vector graphics backend combines multiple images into a single image #4061
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
Conversation
Did the Travis CI build fail because I did not rebuild the documentation? If so, should I just execute |
No, definitely do not do that. The issues seems to be a large number of coding standards violations:
|
ax.set_xlim(0, 3) | ||
ax.imshow(Z, extent = [0, 1, 0, 1]) | ||
ax.imshow(Z[::-1], extent = [2, 3, 0, 1]) | ||
plt.rcParams['pdf.combine_images'] = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could save the plot to an io.BytesIO
buffer and then make sure there are more than one image command in the file. Then we've verified this actually works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. How do I incorporate checking for more than one image command into the testing architecture? As it is now, I just added the image_comparison
decorator to the test function. I don't see a similar decorator to check the contents of a text file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think @mdboom is suggesting to grab the byte stream from the savefig call and use the sting tools to search for image commands.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok. So I won't be searching a text file. Instead I will be searching through a very long string. After I have tested whether there are multiple image commands, then what do I do? The image_comparison
decorator did all the work for me. Do I just add a cleanup
decorator and do an assert
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think that would be enough.
Cool. 👍 to the idea. One issue for discussion: Does it make sense to have three different rcParams for this (one for each backend), or would one be enough? I usually wish we had fewer rcParams, and I don't see a good reason for turning this on individually. |
I don't see a reason to have one rcParam for each backend either. How about |
Since we already have an |
Definitely 👍 on using the |
I think it is important to chose a name that makes it easy to remember what the option does. So, I guess I still like Alternatively, I could go back to just having three different rcParams. One for each backend... |
The tests now use |
fig.savefig(ps, format="ps") | ||
ps.seek(0) | ||
buff = ps.read() | ||
assert buff.count(' colorimage') == 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The failure appears to be here, and similar locations below and in the svg test. I think ' colorimage'
needs to be bytes, not a string. I think you can wrap it with six.b()
.
OK. The tests now verify that there are two images in the vector graphics files, and the tests pass on Python 2.6, 2.7, 3.3, and 3.4. I also have fixed the PEP8 violations in the files I was working with, regardless of whether I created the violations or not. The only thing left to decide is what to call the rcParam option. As I said in my earlier comment, I am in favor of |
I think Other than that, this looks good, though unfortunately it needs a rebase. |
I compromised and called it |
My PR has gone stale for the second time now. If I rebase, will this be merged or does it need further review? |
This fell off my radar so I don't know the current state (and don't have time this second to look at it), but it needs to be rebased before it can be merged either way. |
@@ -1,3 +1,11 @@ | |||
2015-01-31 Added the rcParam 'vector_backends.combine_images' to permit users |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to update this with the new name
I really don't see the point in the API change. Sure, it is clearer, but that ship sailed awhile ago. It is a public method. If there are going to be API changes, they need to be noted, and compatibility needs to be provided. As for the name of the rcparam, I am fine with it. |
@@ -258,11 +258,11 @@ def test_image_composite_background(): | |||
ax.set_axis_bgcolor((1, 0, 0, 0.5)) | |||
ax.set_xlim([0, 12]) | |||
|
|||
@image_comparison(baseline_images=['image_composite_alpha'], remove_text=True) | |||
def test_image_composite_alpha(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why rename these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to make things consistent by using combine_images
everywhere instead of image_composite
.
Yes, I was trying to simply make things more clear. If you guys agree, then I will note the API change and add a depreciation notice to |
d3f416d
to
c254114
Compare
b357367
to
3a9a738
Compare
Rebased a third time. So, what's the verdict? Should I depreciate |
Let's stick with backwards compatibility. I can easily negate a boolean in Don't do what johnny-do-not-do does!
|
'ps.combine_images' to permit users to decide whether they want the vector graphics backend to combine all images within a set of axes into a single image. (If images do not get combined, users can open vector graphics files in Adobe Illustrator or Inkscape and edit each image individually.) Also changed 'renderer.option_nocomposite' to the clearer name 'renderer.option_combine_images'. Improved combine image tests to actually count the number of images in the vector graphics files. Also replaced the rcParams 'pdf.combine_images', 'svg.combine_images', and 'ps.combine_images' with 'vector_backends.combine_images' Corrected PEP8 coding standard violations Updated 'combine_images' tests for PS and SVG backends to hopefully make them Python 3 compatible. Fixed some PEP8 violations to leave the code cleaner than I found it. Fixed PEP8 violations introduced in my effort to fix PEP8 violations in my last commit. Changed the rcParam option name from 'vector_graphics.combine_images' to 'image.combine_images', and updated the matplotlibrc.template. Update the backend tests with the new rcParam name 'image.combine_images' Added the rcParams 'pdf.combine_images', 'svg.combine_images', and 'ps.combine_images' to permit users to decide whether they want the vector graphics backend to combine all images within a set of axes into a single image. (If images do not get combined, users can open vector graphics files in Adobe Illustrator or Inkscape and edit each image individually.) Also changed 'renderer.option_nocomposite' to the clearer name 'renderer.option_combine_images'. Improved combine image tests to actually count the number of images in the vector graphics files. Also replaced the rcParams 'pdf.combine_images', 'svg.combine_images', and 'ps.combine_images' with 'vector_backends.combine_images' Corrected PEP8 coding standard violations Updated 'combine_images' tests for PS and SVG backends to hopefully make them Python 3 compatible. Fixed some PEP8 violations to leave the code cleaner than I found it. Fixed PEP8 violations introduced in my effort to fix PEP8 violations in my last commit. Changed the rcParam option name from 'vector_graphics.combine_images' to 'image.combine_images', and updated the matplotlibrc.template. Update the backend tests with the new rcParam name 'image.combine_images'
Reverted from the 'combine_images' terminology back to the 'composite_image' terminology. With this terminology, we can keep the method name 'renderer.option_image_nocomposite()', and maintain backwards compatibility.
…a comment in 'test_image.test_image_composite_alpha()' to the 'composite_image' terminology.
@WeatherGod, thanks for the feedback. I have switched back to the |
Looks good to me. Just need a "whats_new" entry. One question... are changes going to be needed for the PGF backend? |
….composite_image']
… might use the 'image.composite_image' option.
… might use the 'image.composite_image' option.
I added a "whats_new" entry. I don't think the PGF backend needs any changes. As far as I can tell, PGF is not a vector graphics format, so the PGF backend just saves the entire figure as a rasterized image. There is no point to saving each image individually with that backend. @tacaswell, I think we are ready to merge this PR. |
@@ -249,7 +249,7 @@ class Figure(Artist): | |||
|
|||
*suppressComposite* | |||
For multiple figure images, the figure will make composite | |||
images depending on the renderer option_image_nocomposite | |||
images depending on the renderer option_combine_images |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change should be reverted (missed un-rename).
For future reference, see https://github.com/matplotlib/matplotlib/tree/master/doc/users/whats_new for adding whats_new entries. By splitting the up into individual files we will hopefully avoid the documentation related rebase-thrashing. |
…mposite'. Also moved the whats_new addition into a separate file.
Nice catch @tacaswell. The comment has been fixed. I also moved the whats_new entry over to the proper individual file. |
Ok, this looks good to me. Thank you for bearing with us through this. |
Allow users to decide whether a vector graphics backend combines multiple images into a single image
Thanks! Glad we got this sorted out and merged. |
Yay! Thank y'all for helping me learn the ropes. |
Currently, if multiple images are on a set of axes, matplotlib will combine them into a single image when the figure window is saved. This is fine when the figure is saved as a raster image, such as a PNG, but it may not be what the user wants when the figure is saved as a vector graphics file, such as a PDF.
Personally, I like to be able to open a PDF in Adobe Illustrator or Inkscape after I have saved the figure and move each image independently of the others. I frequently will save a sequence of, say 5, vertically stacked images, and then I will realize 3 months later that I want to horizontally stack them, stagger them, overlap them, or something else. Usually I am in a hurry to put together a presentation or a writeup for something. Rather than dig up the old code, and rewrite it to do staggered images, I would much rather just work in Adobe Illustrator to manipulate the images on the fly. I find the GUI is the way to go for quick, single time, operations. If find myself doing the same GUI operations over and over again, then I will go to the effort to code it up.
To accommodate this workflow, I propose to add the rcParams 'pdf.combine_images', 'svg.combine_images', and 'ps.combine_images' to permit users to decide whether they want the vector graphics backend to combine all images within a set of axes into a single image. I also propose to change 'renderer.option_nocomposite' to the clearer name 'renderer.option_combine_images'.
Note: As a side benefit, this PR will give users a viable workaround for issue 3918.