Skip to content

Instantly share code, notes, and snippets.

@btel
Last active October 25, 2018 20:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save btel/a6b97e50e0f26a1a5eaa to your computer and use it in GitHub Desktop.
Save btel/a6b97e50e0f26a1a5eaa to your computer and use it in GitHub Desktop.
Thined version of matplotlib Axes for better performance
When improving the performance of plotting high-dimensional data using
faceted scatter plots, I noticed that much of time was spent on the axis
creation (even 50%!).
On my machine creating 20x20 array of subplots without actually plotting
anything takes about 11 seconds (for comparison plotting 5000 points on
all of them takes only 0.6s!):
import matplotlib
matplotlib.interactive(True)
import matplotlib.pyplot as plt
fig, axes = plt.subplots(20,20)
plt.show()
Profiling shows that 50% of computation time is spent on axis/ticks
creation [1], which I have to remove anyways. Is there any easy way of
creating thinned axes without ticks and spines?
So far I solved the problem by subclassing Axes class (see this gist
[2]) and removing all spines and ticks. Running the above example gives
a 10x boost in performance (from 11s to 0.9s).
import thin_axes
fig, axes = plt.subplots(20,20, subplot_kw=dict(projection='thin'))
plt.show()
Profiling results show more uniform distribution of computing time
across functions (most time is spent on creating and applying transforms
[3]).
#!/usr/bin/env python
#coding=utf-8
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import thin_axes
import time
import numpy as np
import platform
print " ".join(platform.uname())
def plot(axes):
for a in axes.flatten():
x, y = np.random.randn(2, 5000)
a.plot(x, y, '.')
start_time = time.time()
fig, axes = plt.subplots(20,20)
plt.savefig('test.png')
print "Standard axes {} s".format(time.time() - start_time)
plt.close()
start_time = time.time()
fig, axes = plt.subplots(20,20, subplot_kw=dict(projection='thin'))
plt.savefig('test.png')
print "Thin axes {} s".format(time.time() - start_time)
plt.close()
start_time = time.time()
fig, axes = plt.subplots(20,20)
plt.savefig('test.png')
print "Standard axes with plotting {} s".format(time.time() - start_time)
plt.close()
start_time = time.time()
fig, axes = plt.subplots(20,20, subplot_kw=dict(projection='thin'))
plot(axes)
plt.savefig('test.png')
print "Thin axes with plotting {} s".format(time.time() - start_time)
plt.close()
Darwin Bartoszs-MacBook-Pro.local 13.1.0 Darwin Kernel Version 13.1.0: Wed Apr 2 23:52:02 PDT 2014; root:xnu-2422.92.1~2/RELEASE_X86_64 x86_64 i386
Standard axes 46.3883450031 s
Thin axes 2.5897591114 s
Standard axes with plotting 51.6446781158 s
Thin axes with plotting 7.36941695213 s
from matplotlib.axes import Axes
from matplotlib.ticker import NullLocator
from matplotlib.projections import register_projection
import matplotlib.axis as maxis
class NoTicksXAxis(maxis.XAxis):
def reset_ticks(self):
self._lastNumMajorTicks = 1
self._lastNumMinorTicks = 1
def set_clip_path(self, clippath, transform=None):
pass
class NoTicksYAxis(maxis.YAxis):
def reset_ticks(self):
self._lastNumMajorTicks = 1
self._lastNumMinorTicks = 1
def set_clip_path(self, clippath, transform=None):
pass
class ThinAxes(Axes):
"""Thin axes without spines and ticks to accelerate axes creation"""
name = 'thin'
def _init_axis(self):
self.xaxis = NoTicksXAxis(self)
self.yaxis = NoTicksYAxis(self)
def cla(self):
"""
Override to set up some reasonable defaults.
"""
Axes.cla(self)
self.xaxis.set_minor_locator(NullLocator())
self.yaxis.set_minor_locator(NullLocator())
self.xaxis.set_major_locator(NullLocator())
self.yaxis.set_major_locator(NullLocator())
def _gen_axes_spines(self):
return {}
# Now register the projection with matplotlib so the user can select
# it.
register_projection(ThinAxes)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment