|
From: Patrick K. <pa...@ke...> - 2002-12-04 05:06:13
|
As you probably know, if you just close a Vpython display which was started
from a program running under Pythonwin, it causes Pythonwin to die, even
after the program terminates.
So I had to "invent" a method of gracefully terminating a Vpython program.
Not too difficult I know, but having done so, I thought I might as well
share it. So here is a function (a histogram plotter), with this capability.
#!/usr/bin/python
#
# Histo - plot a histogram of stacked cylinders using Vpython
#
# Author Patrick Keogh
#
from visual import *
def histo(stacked, data):
""" The second parameter which is passed is assumed to be a sequence,
which has:
- The first element is a sequence of category labels
- The second element is a sequence of data series labels.
- The third element is a sequence of sequences of the data values
"""
#
# This try/except figures out if there is already a scene. If not, it
creates it.
#
try:
type(scene)
except:
scene = display()
scene.show()
max_entries = len(data[0])
col = (color.red,color.blue,color.green,color.yellow)
data_array = []
for i in data[2]:
max_entries = max((max_entries, len(i)))
arrow(axis=(max_entries+1,0,0), shaftwidth=0.1, fixedwidth=1)
max_height = 0.0
for i in range(max_entries):
data_array.append([])
for j in range(len(data[2])):
data_array[i].append(data[2][j][i])
max_height=max((max_height,sum(data_array[i])))
arrow(axis=(0,10,0), shaftwidth=0.1, fixedwidth=1)
for j in range(len(data_array[0])):
label(pos=(-5,j*2,j*2),text=data[1][j],color=col[j],opacity=0,box=0,border=0
)
for i in range(len(data_array)):
base = 0
for j in range(len(data_array[i])):
cyl_height = data_array[i][j]*10.0/max_height
if stacked:
pos = (i+1,base,0)
base = base + cyl_height
else:
pos = (i+1,0,j*2)
axis = (0,cyl_height,0)
c = cylinder(pos=pos,axis=axis,radius=0.3,color=col[j])
c.label = "(" + data[0][i] + "," + repr(data_array[i][j]) + ")"
scene.center = (len(data_array)/2,5,0)
again = 1
prev = None
#
# Apart from the standard zoom and rotate capabilities, we will add
#
# Left click = Set a new center
# Ctrl-C = Exit
# Move over a bar = Display the (x,y) label for the histogram bar
# Note the "hack" of inserting the label as an attribute of the
cylinder
#
while again:
while scene.mouse.events:
if scene.mouse.clicked:
scene.center = scene.mouse.getclick().pos
if scene.kb.keys:
if scene.kb.getkey() == 'ctrl+c':
again = 0
if scene.mouse.pick <> None:
if prev <> scene.mouse.pick:
try:
l.visible = 0
except:
pass
prev = scene.mouse.pick
if prev.__class__ == cylinder:
l = label(pos=scene.mouse.pos, text=prev.label, box=0)
#
# If a control-c was entered, then the while loop exits, and we close down
the display and exit
#
scene.hide()
del(scene)
|