[SciPy-user] Alternative to NumTut's view() function?
Fernando Perez
fperez at pizero.colorado.edu
Fri Feb 14 21:32:59 EST 2003
On Thu, 13 Feb 2003, David Ascher wrote:
> >Any suggestions?
> >
> >
> It's working ok for me on win2k. I'll try tomorrow on rh8 at work.
>
> In the meantime, try forcing _inidle to be true before view() is
> defined. See if that behavior works better for you.
Well, that does help quite a bit. However, the keyboard response is still a
bit sluggish, which I honestly can't stand. I type reasonably fast and I
can't stand a delay in typing at a console (it is however far better than
before, and perhaps quite usable for most).
However, I've modified view.py and now have a reasonably functional version.
I'm attaching it to this message for the benefit of others, since it seems
that this problem is reasonably common. I also modified view() to accept a
single scaling factor besides the tuple of (scalex,scaley). This allows
zooming in both directions with a single number, a common operation.
Thanks a lot for all the suggestions, I did look at the tutorial and various
other options. I did go ahead, against my better judgement, and installed
wxpython. I say this because in the past, getting wxpython to work has been a
frustrating experience every single time.
No change :) I tried reproducing the instructions from teh tutorial mentioned
in another reply, and I got only a dead window labelled 'Figure 0'. The
window showed no contents and none of its control widgets worked (including
'close'). I could only kill it by exiting the python shell. Here's my text
output:
[libfmwt]> python
Python 2.2.1 (#1, Aug 30 2002, 12:15:30)
[GCC 3.2 20020822 (Red Hat Linux Rawhide 3.2-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import gui_thread
>>> from scipy import plt
>>> from scipy import *
>>> img = plt.lena()
>>> plt.image(img)
<type 'array'> ['__copy__', '__deepcopy__', 'astype', 'byteswapped', 'copy',
'iscontiguous', 'itemsize', 'resize', 'savespace', 'spacesaver', 'tolist',
'toscalar', 'tostring', 'typecode']
<C wxFrame instance at _86445e0_wxFrame_p>
>>>
Note that after the gui_thread statement, I did NOT see <wxPython imported>
printed as the tutorial says should occur.
This was done with a cvs copy of scipy from today which passed all tests with
scipy.test(level=10), on a RedHat 8.0 machine.
I'm sure that eventually it will be very nice to use all the nice
scipy-provided plotting functionality. But until that day arrives, the
simple-minded view.py I attach here may be of use to some.
Thanks again to all those who replied in various forms (in case I don't reply
to you directly, I did read all the responses).
Best regards,
Fernando.
-------------- next part --------------
"""
Displaying image files in a separate thread on Tk+thread, w/ xv in
forked & execv'ed processes otherwise.
view(array): will spawn a displaying program for arrays which are
either NxM or NxMx3. does the 'min/max' and conversion
to char.
array2ppm(array): given an NxM or NxMx3 array, returns a ppm string
which is a valid thing to put in a PPM file. (or
PGM file if NxM file).
TODO:
- automatic scaling for small images
- accept rank-1 arrays
NOTE: This is a modified version which removes all threading and PIL
support. It should work on any system with Tkinter alone.
"""
DEFAULT_HEIGHT = 255
MINSIZE = 150
import os
import Tkinter
from Numeric import *
import tempfile, time
def save_ppm(ppm, fname=None):
if fname == None:
fname = tempfile.mktemp('.ppm')
f = open(fname, 'wb')
f.write(ppm)
f.close()
return fname
def array2ppm(image):
# scaling
if len(image.shape) == 2:
# B&W:
image = transpose(image)
return "P5\n#PPM version of array\n%d %d\n255\n%s" % \
(image.shape[1], image.shape[0], ravel(image).tostring())
else:
# color
image = transpose(image, (1, 0, 2))
return "P6\n%d %d\n255\n%s" % \
(image.shape[1], image.shape[0], ravel(image).tostring())
def preprocess(image, (scalex,scaley)):
assert len(image.shape) in (1, 2) or \
len(image.shape) == 3 and image.shape[2] == 3, \
"image not correct format"
themin = float(minimum.reduce(ravel(image)))
themax = float(maximum.reduce(ravel(image)))
if len(image.shape) == 1:
len_x = image.shape[0]
ys = ((image - themin)/(themax-themin)*(DEFAULT_HEIGHT-1)).astype('b')
image = (zeros((DEFAULT_HEIGHT, len_x))+255).astype('b')
for x in range(len_x):
image[DEFAULT_HEIGHT-1-ys[x],len_x-x-1] = 0
image = transpose(image)
elif image.typecode() != 'b':
image = (image - themin) / (themax-themin) * 255
image = image.astype('b')
len_x, len_y = image.shape[:2]
if scalex is None:
if len_x < MINSIZE:
scalex = int(float(MINSIZE) / len_x) + 1
else:
scalex = 1
if scaley is None:
if len_y < MINSIZE:
scaley = int(float(MINSIZE) / len_y) + 1
else:
scaley = 1
return image, (scalex, scaley)
class PPMImage(Tkinter.Label):
def __init__(self, master, ppm, (scalex, scaley)):
self.image = Tkinter.PhotoImage(file=save_ppm(ppm))
w, h = self.image.width(), self.image.height()
self.image = self.image.zoom(scalex, scaley)
self.image.configure(width=w*scalex, height=h*scaley)
Tkinter.Label.__init__(self, master, image=self.image,
bg="black", bd=0)
self.pack()
# Start the Tk process from which all subsequent windows will be opened.
def tk_root():
if Tkinter._default_root is None:
root = Tkinter.Tk()
Tkinter._default_root.withdraw()
else:
root = Tkinter._default_root
return root
_root = tk_root()
def view(image, scale=None):
"""Display an image, optionally rescaling it.
scale can be either an integer or a tuple of 2 integers (for separate x/y
rescaling. """
if scale is None:
scale=(None,None)
else:
try:
len(scale)
except TypeError:
scale = (scale,scale)
image, scales = preprocess(image, scale)
tl = Tkinter.Toplevel()
u = PPMImage(tl, array2ppm(image), scales)
u.pack(fill='both', expand=1)
u.tkraise()
More information about the SciPy-User
mailing list