This change alone gives me more than a 2x speedup. So with
> GTKAgg + a custom normalizer (in this case a do nothing
> normalizer) you'll be running 4-5 times faster than you were
> before, me thinks.
Of the remaining time, about half of it, on my system, is spent in the
colormapping. Almost all of this is in
LinearSegmentedColormap.__call__, and is split between these numerix
methods
0.12s zeros : create the RGBA colormapped output array
0.23s where : make sure the data are in the [0,1] interval
0.49s take + makeMappingArray - actually doing the mapping
You may not want or need some of the overhead and extra checking that
matplotlib does in the colormapping. Do you want colormapping at all
by the way?
If not, you can special case colormapping by simply converting to RGB
in the 0-255 interval. Note, as I said it is a bit inelegant that
everything has to go through RGB even if you don't need it. I have
some ideas here, but that will have to wait a bit.
from pylab import *
def mynorm(X):
return X
class mycmap:
name = "my gray"
def __call__(self, X, alpha=None):
# what is the fastest way to make an MxNx3 array simply
# duplicating MxN on the last dimension?
m,n = X.shape
Z = zeros((m,n,3), typecode=X.typecode())
Z[...,0] = X
Z[...,1] = X
Z[...,2] = X
return Z
#norm = None # default
norm = mynorm
#cmap = None # default
cmap = mycmap()
ion()
rc('figure', figsize=(13,12))
X = rand(1600,1600)
figimage(X, cmap=cmap, norm=norm)
With the following numbers
# default cmap
peds-pc311:~/python/projects/matplotlib> time python ~/test.py --numarray -dGTKAgg
1.630u 0.430s 0:02.12 97.1% 0+0k 0+0io 4746pf+0w
# custom cmap
peds-pc311:~/python/projects/matplotlib> time python ~/test.py --numarray -dGTKAgg
1.080u 0.290s 0:01.42 96.4% 0+0k 0+0io 4745pf+0w
Of this 1.42 seconds, the big chunks are
0.660 The time it takes to do from pylab import *; half of this is
initializing the colormaps and dicts in cm. We should do some
work to get this number down. But it is a fixed cost that
doesn't scale with array size
0.320 RandomArray2.py:97(random) # creating the dummy data. We can
ignore this
0.540 backend_gtkagg.py:33(draw) # this creates the entire figure,
of this, 0.420s is in the function FigureImage.make_image,
most of which is in the extension code _image.fromarray
So ignoring for now the fixed cost of loading modules and creating
your arrays (Eg by running in pylab using the "run" function you only
pay the module loading costs once), the next place where a big win is
going to come from is in optimizing fromarray.
Note, the matplotlib figure canvas is a drawable widget. If you want
bare metal speed and don't want any of the features matplotlib offers
(interpolation, normalization, colormapping, etc), you can always dump
your image directly to the gtk canvas, especially if you compile gtk
with image support. This may be useful enough for us to consider a
backend figimage pipeline which would bypass a number of extra
copies. Currently we have for gtkagg
numarray -> agg image buffer -> figure canvas agg buffer -> gtk canvas
With some care, we might be able to simplify this, ideally doing for
the canvas
numarray -> gtk canvas # for screen
numarray -> agg buffer # for dumping to PNG
There are some subtleties to think through as to how this would work.
It would probably need to be a canvas method and not a renderer
method, for one thing, which would take a bit of redesign.
And then Midas would have to watch its back!
JDH