Created
December 10, 2011 00:11
-
-
Save astrofrog/1453933 to your computer and use it in GitHub Desktop.
Asynchronous Plotting in Matplotlib: rather than call savefig directly, add plots to an asynchronous queue to avoid holding up the main program. Makes use of multiple processes to speed up the writing out. Suggestions welcome!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import time | |
| import multiprocessing as mp | |
| import numpy as np | |
| import matplotlib | |
| matplotlib.use('Agg') | |
| import matplotlib.pyplot as plt | |
| class AsyncPlotter(): | |
| def __init__(self, processes=mp.cpu_count()): | |
| self.manager = mp.Manager() | |
| self.nc = self.manager.Value('i', 0) | |
| self.pids = [] | |
| self.processes = processes | |
| def async_plotter(self, nc, fig, filename, processes): | |
| while nc.value >= processes: | |
| time.sleep(0.1) | |
| nc.value += 1 | |
| print "Plotting " + filename | |
| fig.savefig(filename) | |
| plt.close(fig) | |
| nc.value -= 1 | |
| def save(self, fig, filename): | |
| p = mp.Process(target=self.async_plotter, | |
| args=(self.nc, fig, filename, self.processes)) | |
| p.start() | |
| self.pids.append(p) | |
| def join(self): | |
| for p in self.pids: | |
| p.join() | |
| # Create instance of Asynchronous plotter | |
| a = AsyncPlotter() | |
| for i in range(10): | |
| print 'Preparing %04i.png' % i | |
| # Generate random points | |
| x = np.random.random(10000) | |
| y = np.random.random(10000) | |
| # Generate figure | |
| fig = plt.figure() | |
| ax = fig.add_subplot(1, 1, 1) | |
| ax.set_xscale('log') | |
| ax.set_yscale('log') | |
| ax.scatter(x, y) | |
| # Add figure to queue | |
| a.save(fig, '%04i.png' % i) | |
| # Wait for all plots to finish | |
| a.join() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
when I run this, I get the following
RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase. This probably means that you are not using fork to start your child processes and you have forgotten to use the proper idiom in the main module: if __name__ == '__main__': freeze_support() ... The "freeze_support()" line can be omitted if the program is not going to be frozen to produce an executable.I was able to resolve this by changing the default start method to
forkmp.set_start_method("fork")Note that this might be due to my python version: Running 3.7