I'm plotting a PGM image: Here's the data I'm using.
The problem is some of the shown pixels are wrong. For example:
Can anybody explain the discrepancies and how to fix them?
Here's my source:
from pylab import *
import numpy
LABELS = range(13)
NUM_MODES = len(LABELS)
def read_ascii_pgm(fname):
"""
Very fragile PGM reader. It's OK since this is only for reading files
output by my own app.
"""
lines = open(fname).read().strip().split('\n')
assert lines[0] == 'P2'
width, height = map(int, lines[1].split(' '))
assert lines[2] == '13'
pgm = numpy.zeros((height, width), dtype=numpy.uint8)
for i in range(height):
cols = lines[3+i].split(' ')
for j in range(width):
pgm[i,j] = int(cols[j])
return pgm
def main():
import sys
assert len(sys.argv) > 1
fname = sys.argv[1]
pgm = read_ascii_pgm(fname)
# EDIT: HACK!
pgm[0,0] = 12
cmap = cm.get_cmap('spectral', NUM_MODES)
imshow(pgm, cmap=cmap, interpolation='nearest')
edit = True
if edit:
cb = colorbar()
else:
ticks = [ (i*11./NUM_MODES + 6./NUM_MODES) for i in range(NUM_MODES) ]
cb = colorbar(ticks=ticks)
cb.ax.set_yticklabels(map(str, LABELS))
savefig('imshow.png')
if __name__ == '__main__':
main()
EDIT
I see what's happening here now. Basically, imshow
seems to be doing this:
[ min(image), max(image) ]
What I want it to do is:
I can verify this by forcing the dynamic range of the image to be 13 (see the line labelled HACK
). Is there a better way to do this?
Here's an updated image:
The solution is to set im.set_clim(vmin, vmax)
. Basically the values in the image were being translated to cover the entire color range. For example if 3
was the largest value in your data, it would be assigned the maximum color value.
Instead you need to tell it that max_nodes
is the highest value (13 in your case), even though it doesn't appear in the data, e.g. im.set_clim(0, 13)
.
I changed your code slightly to work with other data files with different values for num_modes
:
import numpy
from pylab import *
def read_ascii_pgm(fname):
lines = open(fname).read().strip().split('\n')
assert lines[0] == 'P2'
width, height = map(int, lines[1].split(' '))
num_modes = int(lines[2])
pgm = numpy.zeros((height, width), dtype=numpy.uint8)
for i in range(height):
cols = lines[3+i].split(' ')
for j in range(width):
pgm[i,j] = int(cols[j])
return pgm, num_modes + 1
if __name__ == '__main__':
import sys
assert len(sys.argv) > 1
fname = sys.argv[1]
pgm, num_modes = read_ascii_pgm(fname)
labels = range(num_modes)
cmap = cm.get_cmap('spectral', num_modes)
im = imshow(pgm, cmap=cmap, interpolation='nearest')
im.set_clim(0, num_modes)
ticks = [(i + 0.5) for i in range(num_modes)]
cb = colorbar(ticks=ticks)
cb.ax.set_yticklabels(map(str, labels))
savefig('imshow_new.png')
Some simpler test data to illustrate. Notice that the num_modes
value is 10, but no data point reaches that level. This shows how the values index into the colormap 1:1:
P2
5 3
10
0 1 0 2 0
3 0 2 0 1
0 1 0 2 0
Output:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With