-#! /usr/bin/env python
+#!/usr/bin/env python
"""Generate an image from ASCII data.
z[x1,y1]
z[x2,y1]
...
- z[nN,y1]
+ z[xN,y1]
z[x1,y2]
...
z[xN,y2]
where `x` increases from `x1` to `xN` and `y` increases from `y1`
through `yN`.
-For usage info, run::
+You can use the `--xyz` option to read an alternative data format,
+which is::
+
+ x1 y1 z[x1,y1]
+ x2 y2 z[x1,y1]
+ ...
+
+If you use this method, the ordering of lines in the data file is
+irrelevant, and `Nx` and `Ny` are extracted from the data file itself.
+However, you still need to use a rectangular grid (i.e. for every
+`xi`, you need to have entries for every `yi`).
+
+For usage info, run::
./plot_image.py --help
import optparse
import sys
+import matplotlib
+import matplotlib.image
import numpy
# Depending on your Matplotlib configuration, you may need to adjust
# your backend. Do this before importing pylab or matplotlib.backends.
-#import matplotlib
#matplotlib.use('Agg') # select backend that doesn't require X Windows
#matplotlib.use('GTKAgg') # select backend that supports pylab.show()
_DOC = __doc__
-def read_data(stream, nx, ny):
+def read_data_1d(stream, nx, ny):
"""Read in data, one entry per line.
>>> from StringIO import StringIO
- >>> s = StringIO('\\n'.join([str(x) for x in range(10)])+'\\n')
- >>> X,Y,Z = read_data(s, 5, 2)
+ >>> s = StringIO('\\n'.join(map(str, range(10)))+'\\n')
+ >>> X,Y,Z = read_data_1d(s, 5, 2)
>>> X
array([[0, 1, 2, 3, 4, 5],
[0, 1, 2, 3, 4, 5],
Z = Z.reshape([x-1 for x in X.shape])
return (X,Y,Z)
+def read_data_3d(stream):
+ """Read in data, one `(x, y, z)` tuple per line.
+
+ >>> from StringIO import StringIO
+ >>> lines = []
+ >>> for x in range(5):
+ ... for y in range(2):
+ ... lines.append('\t'.join(map(str, [x, y, x+y*5])))
+ >>> s = StringIO('\\n'.join(lines)+'\\n')
+ >>> X,Y,Z = read_data_3d(s)
+ >>> X
+ array([[ 0., 1., 2., 3., 4., 5.],
+ [ 0., 1., 2., 3., 4., 5.],
+ [ 0., 1., 2., 3., 4., 5.]])
+ >>> Y
+ array([[ 0., 0., 0., 0., 0., 0.],
+ [ 1., 1., 1., 1., 1., 1.],
+ [ 2., 2., 2., 2., 2., 2.]])
+ >>> Z
+ array([[ 0., 1., 2., 3., 4.],
+ [ 5., 6., 7., 8., 9.]])
+ """
+ XYZ = numpy.loadtxt(stream)
+ assert len(XYZ.shape) == 2 and XYZ.shape[1] == 3, XYZ.shape
+ Xs = numpy.array(sorted(set(XYZ[:,0])))
+ Ys = numpy.array(sorted(set(XYZ[:,1])))
+ Z = numpy.ndarray((len(Ys), len(Xs)), dtype=float)
+ xyz = {} # dict of z values keyed by (x,y) tuples
+ for i in range(XYZ.shape[0]):
+ xyz[(XYZ[i,0], XYZ[i,1])] = XYZ[i,2]
+ for i,x in enumerate(Xs):
+ for j,y in enumerate(Ys):
+ Z[j,i] = xyz[x,y]
+ # add dummy row/column for pcolor
+ dx = Xs[-1] - Xs[-2]
+ dy = Ys[-1] - Ys[-2]
+ Xs = numpy.append(Xs, Xs[-1] + dx)
+ Ys = numpy.append(Ys, Ys[-1] + dy)
+ X,Y = pylab.meshgrid(Xs, Ys)
+ return (X,Y,Z)
-def plot(X, Y, Z, full=False, title=None, contours=None, cmap=None):
+def plot(X, Y, Z, full=False, title=None, contours=None, interpolation=None,
+ cmap=None):
"""Plot Z over the mesh X, Y.
>>> X, Y = pylab.meshgrid(range(6), range(2))
fig = pylab.figure()
if full:
- axes = pylab.axes([0, 0, 1, 1])
+ axes = fig.add_axes([0, 0, 1, 1])
else:
- axes = pylab.axes()
+ axes = fig.add_subplot(1, 1, 1)
if title:
axes.set_title(title)
axes.set_axis_off()
if contours:
cset = axes.contour(X[:-1,:-1], Y[:-1,:-1], Z, contours, cmap=cmap)
# [:-1,:-1] to strip dummy last row & column from X&Y.
- pylab.clabel(cset, inline=1, fmt='%1.1f', fontsize=10)
+ axes.clabel(cset, inline=1, fmt='%1.1f', fontsize=10)
else:
# pcolor() is much slower than imshow.
#plot = axes.pcolor(X, Y, Z, cmap=cmap, edgecolors='none')
#axes.autoscale_view(tight=True)
- plot = axes.imshow(Z, aspect='auto', interpolation='bilinear',
+ plot = axes.imshow(Z, aspect='auto', interpolation=interpolation,
origin='lower', cmap=cmap,
extent=(X_min, X_max, Y_min, Y_max))
if not full:
return fig
+def get_possible_interpolations():
+ try: # Matplotlib v1.0.1
+ return sorted(matplotlib.image.AxesImage._interpd.keys())
+ except AttributeError:
+ try: # Matplotlib v0.91.2
+ return sorted(matplotlib.image.AxesImage(None)._interpd.keys())
+ except AttributeError:
+ # give up ;)
+ pass
+ return ['nearest']
+
def test():
import doctest
results = doctest.testmod()
Title: Some like it hot
Image size: 5 2
False color
- Data range: 0.0 9.0
+ X range: 0 4 (6 steps)
+ Y range: 0 1 (3 steps)
+ Z range: 0.0 9.0
>>> img = o.read()
>>> img.startswith('\\x89PNG')
True
'displaying it immediately'))
p.add_option('-s', '--size', dest='size', default='%d,%d' % (16, 16),
help='Data size (columns,rows; default: %default)')
+ p.add_option('-3', '--xyz', dest='xyz', default=False, action='store_true',
+ help=('If set, read (x,y,z) tuples from the input data rather'
+ 'then reading `z` and calculating `x` and `y` from '
+ '`--size`.'))
p.add_option('-c', '--contours', dest='contours', type='int',
help=('Number of contour lines (if not set, draw false color '
'instead of contour lines; default: %default)'))
help='Title (%default)')
p.add_option('--test', dest='test', action='store_true',
help='Run internal tests and exit.')
+ interpolations = get_possible_interpolations()
+ p.add_option('--interpolation', dest='interpolation', default='nearest',
+ help=('Interpolation scheme (for false color images) from %s '
+ '(%%default)') % ', '.join(interpolations))
maps=[m for m in pylab.cm.datad if not m.endswith("_r")]
maps.sort()
p.add_option('-m', '--color-map', dest='cmap', default='jet',
print 'Plot_image'
print 'Title: ', options.title
- print 'Image size: ', nx, ny
+ if not options.xyz:
+ print 'Image size: ', nx, ny
if options.contours:
print '# countour lines: ', options.contours
else:
else:
fin = sys.stdin
- X,Y,Z = read_data(fin, nx, ny)
+ if options.xyz:
+ X,Y,Z = read_data_3d(fin)
+ else:
+ X,Y,Z = read_data_1d(fin, nx, ny)
if options.input:
fin.close()
Z_min = numpy.min(Z.flat)
Z_max = numpy.max(Z.flat)
- print 'Data range: ', Z_min, Z_max
+ print 'X range: {} {} ({} steps)'.format(
+ X[0,0], X[0,-2], X.shape[1])
+ print 'Y range: {} {} ({} steps)'.format(
+ Y[0,0], Y[-2,0], Y.shape[0])
+ print 'Z range: ', Z_min, Z_max
fig = plot(X, Y, Z, full=options.full, title=options.title,
- contours=options.contours, cmap=cmap)
+ contours=options.contours, interpolation=options.interpolation,
+ cmap=cmap)
if options.output:
fig.savefig(options.output)
else:
- pylab.ion()
pylab.show()