Well even this late in my career I still aspire to be cool, so here it
is much as requested, a python routine to make the camera travel from
place to place in your molecule.
The arguments to the routine are :
FIRST: frame number for start of the sequence
NFRAMES : number of frames the sequence takes
SEL : a valid PyMol atom selection, encased in quotes, which defines
the view at the end of the sequence
ZFLAG : a flag to indicate whether the final view should be 'zoomed'
or not.
ZLEVEL : the degree of zoom  exactly the same as the 'buffer'
parameter in PyMol cmd.zoom
The routine generates view matrices that interpolate between the
current view and the view specified by the atom selection, updating the
view as it finishes so it can be applied iteratively to travel from
waypoint to waypoint.
I've also included a little routine which applies camera_travel
sequentially to each residue along a polypeptide chain  the movie is
quite large, and when running fast on a Mac G5 can make you a little
seasick, but it does illustrate the power of the routine. The major
technical problem comes from the need to interpolate general rotation
matrices, which is solved by using a quaternion representation. The
code for this is adapted from an article in a magazine called
GameDeveloper by Nick Bobick. I should add that I don't actually know
how to program in python and have no idea how its 'tuples' work, so
this is a very FORTRANlike routine  feel free to improve it.
# camera_travel  Laurence Pearl, November 2003
import cmd
import math
def camera_travel(first,nframes=30,sel='(all)',zflag=0,zlevel=2):
# first  start frame
# nframes  duration
# sel  atom selection that defines the orientation at the end of the
sequence
new_view = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
old_view = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
nxt = [1,2,0]
q = [0,0,0,1]
first=int(first)
nframes=int(nframes)
ff=float(1.0/nframes)
old_view = cmd.get_view(2)
# print "view : (%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f,
%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f,
%8.3f)" % (old_view)
# print "oldtran : %8.3f %8.3f %8.3f" % (old_view[12], old_view[13],
old_view[14])
# do orient operation on selection
cmd.orient(sel,0)
# if zoom to selection is required add this into view matrix
if zflag != 0:
cmd.zoom(sel,zlevel,0,1)
# get new view
new_view = cmd.get_view()
# capture new zoom/clip parameters
ozc1 = new_view[11]
ozc2 = new_view[15]
ozc3 = new_view[16]
# calculate shift in zoom/clip parameters
dzc1 = (ozc1  old_view[11]) * ff
dzc2 = (ozc2  old_view[15]) * ff
dzc3 = (ozc3  old_view[16]) * ff
ozc1 = old_view[11]
ozc2 = old_view[15]
ozc3 = old_view[16]
# capture new translation vector component
ox = new_view[12]
oy = new_view[13]
oz = new_view[14]
# calculate shift vector
dx = ox  old_view[12]
dy = oy  old_view[13]
dz = oz  old_view[14]
dx = dx*ff
dy = dy*ff
dz = dz*ff
ox = old_view[12]
oy = old_view[13]
oz = old_view[14]
# capture old rotation matrix component
# m[0][0] = v[0] m[0][1] = v[1] m[0][2] = v[2]
# m[1][0] = v[3] m[1][1] = v[4] m[1][2] = v[5]
# m[2][0] = v[6] m[2][1] = v[7] m[2][2] = v[8]
# convert to quaternion form
tr = old_view[0]+old_view[4]+old_view[8]
if tr > 0.0 :
s = math.sqrt(tr + 1.0)
qw1 = s / 2.0
s = 0.5 / s
qx1 = (old_view[5]  old_view[7]) * s
qy1 = (old_view[6]  old_view[2]) * s
qz1 = (old_view[1]  old_view[3]) * s
else :
i = 0
if (old_view[4] > old_view[0]):
i = 1
if (old_view[8] > old_view[i+3*i]):
i = 2
j = nxt[i]
k = nxt[j]
s = math.sqrt ((old_view[i+i*3]  (old_view[j+j*3] +
old_view[k+k*3])) + 1.0)
q[i] = s * 0.5
if (s != 0.0):
s = 0.5 / s
q[3] = (old_view[k+3*j]  old_view[j+3*k]) * s
q[j] = (old_view[j+3*i] + old_view[i+3*j]) * s
q[k] = (old_view[k+3*i] + old_view[i+3*k]) * s
qx1 = q[0]
qy1 = q[1]
qz1 = q[2]
qw1 = q[3]
# capture new rotation matrix component
# m[0][0] = v[0] m[0][1] = v[1] m[0][2] = v[2]
# m[1][0] = v[3] m[1][1] = v[4] m[1][2] = v[5]
# m[2][0] = v[6] m[2][1] = v[7] m[2][2] = v[8]
# convert to quaternion form
tr = new_view[0]+ new_view[4]+ new_view[8]
if tr > 0.0 :
s = math.sqrt(tr + 1.0)
qw2 = s / 2.0
s = 0.5 / s
qx2 = (new_view[5]  new_view[7]) * s
qy2 = (new_view[6]  new_view[2]) * s
qz2 = (new_view[1]  new_view[3]) * s
else :
i = 0
if (new_view[4] > new_view[0]):
i = 1
if (new_view[8] > new_view[i+3*i]):
i = 2
j = nxt[i]
k = nxt[j]
s = math.sqrt ((new_view[i+i*3]  (new_view[j+j*3] +
new_view[k+k*3])) + 1.0)
q[i] = s * 0.5
if (s != 0.0):
s = 0.5 / s
q[3] = (new_view[k+3*j]  new_view[j+3*k]) * s
q[j] = (new_view[j+3*i] + new_view[i+3*j]) * s
q[k] = (new_view[k+3*i] + new_view[i+3*k]) * s
qx2 = q[0]
qy2 = q[1]
qz2 = q[2]
qw2 = q[3]
# calc cosine
cosom = qx1 * qx2 + qy1 * qy2 + qz1 * qz2 + qw1 * qw2
# adjust signs
if (cosom < 0.0):
cosom = cosom
to0 = qx2
to1 = qy2
to2 = qz2
to3 = qw2
else:
to0 = qx2
to1 = qy2
to2 = qz2
to3 = qw2
# calc coefficients
omega = math.acos(cosom)
sinom = math.sin(omega)
# restore old view
cmd.set_view("%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f,
%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f" %
(old_view[0],old_view[1],old_view[2],old_view[3],old_view[4],old_view[5]
,old_view[6],old_view[7],old_view[8],old_view[9],old_view[10],old_view[1
1],old_view[12],old_view[13],old_view[14],old_view[15],old_view[16],old_
view[17]) )
# loop interpolating over nframes generating interpolated quaternion
a = 0
while a < (nframes+1) :
scale0 = math.sin((1.0  float(a*ff)) * omega) / sinom
scale1 = math.sin(float(a*ff) * omega) / sinom
rx = scale0 * qx1 + scale1 * to0;
ry = scale0 * qy1 + scale1 * to1;
rz = scale0 * qz1 + scale1 * to2;
rw = scale0 * qw1 + scale1 * to3;
# convert back to matrix
x2 = rx + rx
y2 = ry + ry
z2 = rz + rz
xx = rx * x2
xy = rx * y2
xz = rx * z2
yy = ry * y2
yz = ry * z2
zz = rz * z2
wx = rw * x2
wy = rw * y2
wz = rw * z2
nv0 = 1.0  (yy + zz)
nv3 = xy  wz
nv6 = xz + wy
nv1 = xy + wz
nv4 = 1.0  (xx + zz)
nv7 = yz  wx
nv2 = xz  wy
nv5 = yz + wx
nv8 = 1.0  (xx + yy)
# update translation vector
ox = ox + dx
oy = oy + dy
oz = oz + dz
# update zoom/clip parameters if required
if zflag != 0:
ozc1 = ozc1 + dzc1
ozc2 = ozc2 + dzc2
ozc3 = ozc3 + dzc3
cmd.mdo("%d" % (first),"set_view (%8.3f, %8.3f, %8.3f, %8.3f, %8.3f,
%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f,
%8.3f, %8.3f, %8.3f)" %
(nv0,nv1,nv2,nv3,nv4,nv5,nv6,nv7,nv8,old_view[9],old_view[10],ozc1,ox,oy
,oz,ozc2,ozc3,old_view[17]))
a = a + 1
first = first + 1
cmd.set_view("%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f,
%8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f, %8.3f" %
(nv0,nv1,nv2,nv3,nv4,nv5,nv6,nv7,nv8,old_view[9],old_view[10],ozc1,ox,oy
,oz,ozc2,ozc3,old_view[17]))
# SEQUENCE VISITOR
ires = 1
fr=1
res=" "
while ires < 215:
res = "resi %d" % (ires)
camera_travel(fr,9,res,1,2)
cmd.mdo("%d" % (fr+10),"show sticks,(resi %d and not n;c,n,o)" %
(ires))
fr = fr + 15
ires = ires + 1
On Thursday, November 13, 2003, at 09:24 PM, classen wrote:
> When making a movie It would be cool if you could set waypoints to
> create a
> sophisticated "tour"
> of your molecule.
>
> Each waypoint would be a different view of your molecule.
>
> Then you could specify the number of frames between any two waypoints
> (views). Each frame
> would be a specified amount of time and by changing the number of
> frames you
> would change the
> timing for that particular section of the movie.
>
> Press the play button and voila your tour begins.... zooming in,
> rotating,
> zooming back out, etc.
>
> Would this be difficult to implement?
>
> Regards,
> Scott Classen
>
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> Scott Classen, Ph.D.
> ACS Postdoctoral Fellow
> Department of Molecular & Cell Biology
> University of California, Berkeley
> 237 Hildebrand Hall #3206
> Berkeley, CA 947203206
> LAB 510.643.9491
> FAX 510.643.9290
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>
>
>
> 
> This SF.Net email sponsored by: ApacheCon 2003,
> 1619 November in Las Vegas. Learn firsthand the latest
> developments in Apache, PHP, Perl, XML, Java, MySQL,
> WebDAV, and more! http://www.apachecon.com/
> _______________________________________________
> PyMOLusers mailing list
> PyMOLusers@...
> https://lists.sourceforge.net/lists/listinfo/pymolusers
>


Laurence H. Pearl
Section of Structural Biology, Institute of Cancer Research
Chester Beatty Laboratories, 237 Fulham Road, London SW3 6JB, UK
Phone +44207970 6045 : Secretary +44207970 6046
FAX +44207970 6051 : EMail Laurence.Pearl@...


" Live Simply and do Serious Things .. "  Dorothy Crowfoot Hodgkin


