Saving multiple figs from loop to one pdf [duplicate] - python

I want to save 2 figures created at different parts of a script into a PDF using PdfPages, is it possible to append them to the pdf?
Example:
fig = plt.figure()
ax = fig_zoom.add_subplot(111)
ax.plot(range(10), range(10), 'b')
with PdfPages(pdffilepath) as pdf:
pdf.savefig(fig)
fig1 = plt.figure()
ax = fig_zoom.add_subplot(111)
ax.plot(range(10), range(2, 12), 'r')
with PdfPages(pdffilepath) as pdf:
pdf.savefig(fig1)

Sorry, that's a lame question. We just shouldn't use the with statement.
fig = plt.figure()
ax = fig_zoom.add_subplot(111)
ax.plot(range(10), range(10), 'b')
# create a PdfPages object
pdf = PdfPages(pdffilepath)
# save plot using savefig() method of pdf object
pdf.savefig(fig)
fig1 = plt.figure()
ax = fig_zoom.add_subplot(111)
ax.plot(range(10), range(2, 12), 'r')
pdf.savefig(fig1)
# remember to close the object to ensure writing multiple plots
pdf.close()

I think that Prashanth's answer can be generalized a bit better, for instance by incorporating it in a for loop, and avoiding the creation of multiple figures, which can generate memory leaks.
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
# create a PdfPages object
pdf = PdfPages('out.pdf')
# define here the dimension of your figure
fig = plt.figure()
for color in ['blue', 'red']:
plt.plot(range(10), range(10), color)
# save the current figure
pdf.savefig(fig)
# destroy the current figure
# saves memory as opposed to create a new figure
plt.clf()
# remember to close the object to ensure writing multiple plots
pdf.close()

None of these options append if the file is already closed (e.g. the file gets created in one execution of your program and you run the program again). In that use case, they all overwrite the file.
I think appending isn't currently supported. Looking at the code of backend_pdf.py, I see:
class PdfFile(object)
...
def __init__(self, filename):
...
fh = open(filename, 'wb')
Therefore, the function is always writing, never appending.

import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
# Use plt to draw whatever you want
pp = PdfPages('multipage.pdf')
plt.savefig(pp, format='pdf')
pp.savefig()
# Finally, after inserting all the pages, the multipage pdf object has to be closed.
pp.close()

You can directly do like this if your data is in data frame
#
with PdfPages(r"C:\Users\ddadi\Documents\multipage_pdf1.pdf","a") as pdf:
#insert first image
dataframe1.plot(kind='barh'); plt.axhline(0, color='k')
plt.title("first page")
pdf.savefig()
plt.close()
#insert second image
dataframe2.plot(kind='barh'); plt.axhline(0, color='k')
plt.title("second page")
pdf.savefig()
plt.close()

Related

How can I output function results to pdf in Jupyter Notebook

I am working in Jupyter Notebook and I have a function that generates multiple plots upon being called. I want to directly save all plots from this function call under one pdf. Is there ways to do that?
Any help will be much appreciated!
Alison
You can use PDFPages to save all of your plots into a pdf. You can try the following example and implement it similarly in your code:
You can create a plotGraph function:
def plotGraph(X,Y):
fig = plt.figure()
### Plotting code ###
return fig
Then use that to get your and place them in your pdf.
from matplotlib.backends.backend_pdf import PdfPages
plot1 = plotGraph(graph1, label1)
plot2 = plotGraph(graph2, label2)
plot3 = plotGraph(graph3, label3)
pp = PdfPages('foo.pdf')
pp.savefig(plot1)
pp.savefig(plot2)
pp.savefig(plot3)
pp.close()
If you are okay with saving it as a PNG file with all the plots you can try the following:
from matplotlib import pyplot as plt
fig = plt.figure()
axis1 = fig.add_subplot(211)
axis1.plot(range(10))
axis2 = fig.add_subplot(212)
axis2.plot(range(10,20))
fig.savefig('allplots.png')
This basically creates subplots and saves all your plots in 1 png file.

How to save matplotlib plot as a .png file

I have a piece of code that I have acquired from a collaborator in work. This piece of code produces a plot like the one seen below.
example image of a plot
It does this by referencing another function in another piece of code; which I do not want to alter in any way.
What I would like to do is to write a piece of code that saves this plot as a png file i.e. I am looking for a function that i can put the other function as a variable that would save it is as a png/ jpeg file.
Code:
Here is the code:
for file in files:
import matplotlib.pyplot as plt
connection = sqlite3.connect( file )
animalPool = AnimalPool( )
animalPool.loadAnimals( connection )
# show the mask of animals at frame 300
animalPool.showMask( 701 )
It is calling the following function:
def showMask(self, t ):
'''
show the mask of all animals in a figure
'''
fig, ax = plt.subplots()
ax.set_xlim(90, 420)
ax.set_ylim(-370, -40)
for animal in self.getAnimalList():
mask = animal.getBinaryDetectionMask( t )
mask.showMask( ax=ax )
plt.show()
I have already tried the matplotlib "savefig" function, but this just saves a blank image.
I am very new to coding, and am trying to learn on the fly, so if this question is not well worded or explained please let me know what is confusing, because I'm also learning how to ask questions about this kind of thing.
Functions that produce matplotlib plots should take a figure or axes as input and only optionally create those if needed. They should return the created objects for further use. Finally, they should not call plt.show(), or if they must, provide an opt-out option.
For example, for a single axes plotting function, it could look like
def plottingfunction(*arguments, ax=None, show=True):
if ax is None:
fig, ax = plt.subplots()
else:
fig = ax.figure
# do something with fig and ax here, e.g.
line, = ax.plot(*arguments)
if show:
plt.show()
return fig, ax, line
If you adhere to such structure, it's easy to do whatever you need to after calling the function
fig, _, _ = plottingfunction([1,2,3], [3,2,4], show=False)
fig.savefig("myplot.png")
plt.show()

Update subplots in Matplotlib figure that is already open

I have a matplotlib window with multiple subplots in it. I want to be able to dynamically update the contents of each subplot whenever a method is called. The simplified code looks like this:
import matplotlib.pyplot as plt
import numpy as np
fig = plt.figure(1)
fig, ax_list = plt.subplots(3, 2)
image1 = plt.imread("image1.jpg")
image2 = plt.imread("image2.jpg")
ax_list = ax_list.ravel()
ax_list[0].imshow(image1)
ax_list[1].imshow(image2)
plt.show()
def update_subplots():
# I want this method to change the contents of the subplots whenever it is called
pass
I've managed to figure out how to get this working- it's not very clean but it gets the job done.
We can set the figure to a global variable like so:
fig, ax_list = plt.subplots(4, 2)
We can then modify the contents of the subplots from any method like so:
def update_subplot(image):
global fig, ax_list
ax_list = ax_list.ravel()
# ax_list[0] refers to the first subplot
ax_list[0].imshow(image)
plt.draw()

how do I redraw an image using python's matplotlib?

What I am trying to do seems to be fairly straightforward, but I'm having a heck of a time trying to get it to work. I am simply trying to draw an image using imshow and then re-draw it periodically as new data arrives.
I've started out with this:
fig = figure()
ax = plt.axes(xlim=(0,200),ylim=(0,200))
myimg = ax.imshow(zeros((200,200),float))
Then I'm assuming I can call set_data like this to update the image:
myimg.set_data(newdata)
I've tried many other things, for example I've called ax.imshow(newdata) instead or I've tried using figure.show() after set_data().
You can simply call figure.canvas.draw() each time you append something new to the figure. This will refresh the plot.
from matplotlib import pyplot as plt
from builtins import input
fig = plt.figure()
ax = fig.gca()
fig.show()
block = False
for i in range(10):
ax.plot(i, i, 'ko')
fig.canvas.draw()
if block:
input('pause : press any key ...')
else:
plt.pause(0.1)
plt.close(fig)

Matplotlib crashes after saving many plots

I am plotting and saving thousands of files for later animation in a loop like so:
import matplotlib.pyplot as plt
for result in results:
plt.figure()
plt.plot(result) # this changes
plt.xlabel('xlabel') # this doesn't change
plt.ylabel('ylabel') # this doesn't change
plt.title('title') # this changes
plt.ylim([0,1]) # this doesn't change
plt.grid(True) # this doesn't change
plt.savefig(location, bbox_inches=0) # this changes
When I run this with a lot of results, it crashes after several thousand plots are saved. I think what I want to do is reuse my axes like in this answer: https://stackoverflow.com/a/11688881/354979 but I don't understand how. How can I optimize it?
I would create a single figure and clear the figure each time (use .clf).
import matplotlib.pyplot as plt
fig = plt.figure()
for result in results:
fig.clf() # Clears the current figure
...
You are running out of memory since each call to plt.figure creates a new figure object. Per #tcaswell's comment, I think this would be faster than .close. The differences are explained in:
When to use cla(), clf() or close() for clearing a plot in matplotlib?
Although this question is old, the answer would be:
import matplotlib.pyplot as plt
fig = plt.figure()
plot = plt.plot(results[0])
title = plt.title('title')
plt.xlabel('xlabel')
plt.ylabel('ylabel')
plt.ylim([0,1])
plt.grid(True)
for i in range(1,len(results)):
plot.set_data(results[i])
title.set_text('new title')
plt.savefig(location[i], bbox_inches=0)
plt.close('all')

Categories

Resources