Re: [PyMOL] you know what would be cool?
I'm still not sure about all this 'cool' stuff - Python looks to me like the illegitimate spawn of C and BASIC, but then I used to program in 6502 machine code so what do I know . Below is a variant of camera_travel (as Pythonised by Lieven Buts) which takes an explicit final view matrix as an argument rather than a PyMol selection as in the original version. This allows you to specify the exact view you want, rather than relying on the combination of PyMol 'orient' and 'zoom' command to generate it for you. This is particularly useful for defining a base view to which you can return. For those with tricky E-mail clients the routine is also attached as a text file. Cheers, Laurence def camera_view_travel(first,nframes=30,new_view=(\ 1.0,0.0,0.0,\ 0.0,1.0,0.0,\ 0.0,0.0,1.0,\ 0.0,0.0, -50.0,\ 0.0,0.0,0.0,\ 40.0, 100.0,0.0 )): """ Generate progressive view matrices to move the camera smoothly from the current view to a new view provided as an argument. first - start frame nframes - duration new_view - PyMol view matrix that defines the view at the end of the sequence """ try: first=int(first) except: print "camera_travel: first frame must be an integer" return -1 try: nframes=int(nframes) except: print "camera_travel: number of frames" ff=float(1.0/nframes) old_view = cmd.get_view(2) # print ( "view : (" + "%8.3f, "*17 + "%8.3f)" ) % (old_view) # print "oldtran : %8.3f %8.3f %8.3f" % (old_view[12], old_view[13], old_view[14]) # 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 and new rotation matrix components in quaternion form # 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] qx1,qy1,qz1,qw1 = quaternion(old_view) qx2,qy2,qz2,qw2 = quaternion(new_view) # calc cosine cosom = qx1 * qx2 + qy1 * qy2 + qz1 * qz2 + qw1 * qw2 limit = 0.001 if cosom>1.0+limit: raise ValueError,"Cosine of omega way out of range (positive)" elif cosom>1.0: print "Warning: cosom corrected from ",cosom,"to", cosom = 1.0 print cosom if cosom<-1.0-limit: raise ValueError,"Cosine of omega way out of range (negative)" elif cosom<-1.0: print "Warning: cosom corrected from ",cosom,"to", cosom = 1.0 print cosom # 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 = acos(cosom) sinom = sin(omega) if sinom==0.0: sinom=limit print "Warning: sinom corrected!" # restore old view cmd.set_view( ("%8.3f, " * 17 + "%8.3f") % tuple(old_view) ) # loop interpolating over nframes generating interpolated quaternion for a in range(nframes+1): scale0 = sin((1.0 - float(a*ff)) * omega) / sinom scale1 = 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
Re: [PyMOL] you know what would be cool?
On Monday 17 November 2003 14:06, Laurence Pearl wrote: > 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 FORTRAN-like routine - feel free to improve it. I have attached a "Pythonized" version of the code. It uses docstrings for the functions, try...except blocks to check some of the parameters, and things like ("%8.3f" * 17) to save some repetition of format specifiers. Python is cool! I have also changed the script to add two commands to PyMol using cmd.extend: "camtrav first,nframes,selection,zoom,buffer" and "seqfly object,firstres,lastres". Usage examples: #- load protein.pdb run camera_travel.py mset 1 x150 zoom all camtrav 1,100,(resi 50),1,4 mplay # This will zoom in from the complete molecule to residue 50. #- #- load protein.pdb run camera_travel.py mset 1 x150 seqfly protein,1,8 mplay # This will visit the sequence from residue 1 to 8 #- Finally, I ran into some trouble in a lysozyme structure (PDB 103L). At residue 139, cosom becomes slightly larger than 1 (1.0008 or so) and acos(cosom) fails. Also, omega and sinom become zero in this case, so the divisions by sinom fail. I added some checks to normalize this situation and stop the code from crashing, but we should look into what's causing this. -- Lieven Buts Department of Ultrastructure Vrije Universiteit Brussel# camera_travel - Laurence Pearl, November 2003 # Pythonized by Lieven Buts, November 2003 import cmd from math import sqrt,acos,sin def quaternion(view): """ Returns a quaternion representation of a view matrix. """ nxt = [1,2,0] q = [0.0,0.0,0.0,1.0] tr = view[0]+view[4]+view[8] if tr > 0.0 : s = sqrt(tr + 1.0) qw1 = s / 2.0 s = 0.5 / s return ( (view[5] - view[7]) * s, (view[6] - view[2]) * s, (view[1] - view[3]) * s, qw1 ) else : i = 0 if (view[4] > view[0]): i = 1 if (view[8] > view[i+3*i]): i = 2 j = nxt[i] k = nxt[j] s = sqrt ((view[i+i*3] - (view[j+j*3] + view[k+k*3])) + 1.0) q[i] = s * 0.5 if (s != 0.0): s = 0.5 / s q[3] = (view[k+3*j] - view[j+3*k]) * s q[j] = (view[j+3*i] + view[i+3*j]) * s q[k] = (view[k+3*i] + view[i+3*k]) * s return q def camera_travel(first,nframes=30,sel='(all)',zflag=0,zlevel=2): """ Generate progressive view matrices to move the camera smoothly from the current view to a view defined by a PyMol selection. first - start frame nframes - duration sel - atom selection that defines the orientation at the end of the sequence zflag - flag to indicate whether the final view should be 'zoomed' or not zlevel - buffer space for zooming final view (as in cmd.zoom) """ try: first=int(first) except: print "camera_travel: first frame must be an integer" return -1 try: nframes=int(nframes) except: print "camera_travel: number of frames" ff=float(1.0/nframes) old_view = cmd.get_view(2) # print ( "view : (" + "%8.3f, "*17 + "%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: 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 and new rotation matrix components in quaternion form # m[0][0] = v[0] m[0][1] = v[1] m[0][2] = v[2] # m[1][0] = v[3] m[1][1] =
Re: [PyMOL] you know what would be cool?
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 way-point to way-point. 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 sea-sick, 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 FORTRAN-like 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]
[PyMOL] you know what would be cool?
When making a movie It would be cool if you could set way-points to create a sophisticated "tour" of your molecule. Each way-point would be a different view of your molecule. Then you could specify the number of frames between any two way-points (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 94720-3206 LAB 510.643.9491 FAX 510.643.9290