https://pymolwiki.org/api.php?action=feedcontributions&user=Newacct&feedformat=atomPyMOLWiki - User contributions [en]2024-03-19T13:37:37ZUser contributionsMediaWiki 1.35.7https://pymolwiki.org/index.php?title=VisLoad&diff=9083VisLoad2011-05-19T08:18:30Z<p>Newacct: </p>
<hr />
<div>[[visLoad]] will load an object and show it in your desired representation. PyMOL by default loads things as lines (or spheres, a setting you may change), but not others.<br />
<br />
= Usage =<br />
* Save the code to "visLoad.py".<br />
* Run the code from PyMOL or put it in your .pymolrc<br />
* Use visLoad whenever you would use load<br />
* To change representations, update "cartoon" to something else, or add more intermediate commands.<br />
<br />
= The Code =<br />
<source lang="python"><br />
import os<br />
from os import path<br />
<br />
def visLoad(filename, object=None, *args, **kwargs):<br />
if object==None:<br />
object = os.path.basename(filename).split(".")[0]<br />
cmd.set("suspend_updates")<br />
try:<br />
cmd.load(filename, object, *args, **kwargs)<br />
cmd.show_as("cartoon", object)<br />
finally:<br />
cmd.set("suspend_updates", "off")<br />
<br />
cmd.extend("visLoad", visLoad)<br />
</source><br />
<br />
= See Also =<br />
[[Load]], [[Save]], [[Show_as]]<br />
<br />
[[Category:Script_Library]]<br />
[[Category:UI_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=BiologicalUnit&diff=9082BiologicalUnit2011-05-19T08:07:05Z<p>Newacct: </p>
<hr />
<div>This script can be used to re-create biological units for proteins. (This was created as a workaround of PyMOL's semi-functioning [[Symexp]] command.) It's also a fun script to play with for learning about symmetry.<br />
<br />
<gallery widths=250px heights=250px><br />
Image:before.png|single unit, before running this program<br />
Image:after.png|after the expansion of the 60 units<br />
Image:1rmv fiber.png|Example creating the biological unit for PDB 1RMV created from fiber diffraction.<br />
</gallery><br />
<br />
= Usage =<br />
<source lang="python"><br />
symMat = readSymmetry("/path/to/some/pdbFile.pdb","pdbFile")<br />
biologicalUnit("mates", "pdbFile", symMat)<br />
</source><br />
<br />
= The Code =<br />
<source lang="python"><br />
#<br />
# Jason Vertrees <Jason-dot-Vertrees-at-schrodinger_dot_com>, 2010.<br />
#<br />
import pymol<br />
from pymol import cmd<br />
<br />
def readSymmetry(inFile, verbose=None):<br />
"""<br />
This function will read "inFile" and glean the<br />
symmetry operations, if any, from it.<br />
<br />
PARAMS<br />
inFile<br />
(string) path to PDB file<br />
<br />
verbose<br />
(boolean) if verbose is not None, print more<br />
<br />
RETURNS<br />
matrix<br />
Array of lists. One 16-element list per symmetry operation. Feed this matrix<br />
into manualSymExp in order to make the other symmetry mates in the biological unit<br />
"""<br />
# a remark-350 lines has:<br />
# REMARK 350 BIOMTn TAGn X Y Z Tx<br />
REM, TAG, BIOMT, OPNO, X, Y, Z, TX = range(8)<br />
<br />
thePDB = open(inFile, 'rb').readlines()<br />
<br />
matrices = []<br />
curTrans = -1<br />
<br />
# The transformation is,<br />
# output = U*input + Tx<br />
<br />
for l in thePDB:<br />
tokens = l.split()<br />
if len(tokens)!=8:<br />
continue<br />
if tokens[REM]=="REMARK" and tokens[TAG]=="350" and tokens[BIOMT].startswith("BIOMT"):<br />
if tokens[OPNO]!=curTrans:<br />
# new transformation matrix<br />
matrices.append([])<br />
<br />
matrices[-1].append( map( lambda s: float(s), tokens[X:]))<br />
curTrans = tokens[OPNO]<br />
<br />
if verbose!=None:<br />
print "Found %s symmetry operators in %s." % (len(matrices), inFile)<br />
return matrices<br />
<br />
<br />
def biologicalUnit(prefix, objSel, matrices ):<br />
"""<br />
Manually expands the object in "objSel" by the symmetry operations provided in "matrices" and<br />
prefixes the new objects with "prefix".<br />
<br />
PARAMS<br />
prefix<br />
(string) prefix name for new objects<br />
<br />
objSel<br />
(string) name of object to expand<br />
<br />
matrices<br />
(list of 16-element lists) array of matrices from readSymmetry<br />
<br />
RETUNRS<br />
None<br />
<br />
SIDE EFFECTS<br />
Creates N new obects each rotated and translated according to the symmetry operators, where N<br />
equals len(matrices).<br />
"""<br />
for m in matrices:<br />
n = cmd.get_unused_name(prefix)<br />
cmd.create(n, objSel)<br />
s1 = "%s + (x*%s + y*%s + z*%s)" % (m[0][3], m[0][0], m[0][1], m[0][2])<br />
s2 = "%s + (x*%s + y*%s + z*%s)" % (m[1][3], m[1][0], m[1][1], m[1][2])<br />
s3 = "%s + (x*%s + y*%s + z*%s)" % (m[2][3], m[2][0], m[2][1], m[2][2])<br />
cmd.alter_state(1, n, "(x,y,z) = (%s, %s, %s)" % (s1, s2, s3) )<br />
</source><br />
<br />
= Notes =<br />
This is slow compared to [[Symexp]]; use the above for learning, playing and when [[Symexp]] doesn't work as advertised.<br />
<br />
= See Also =<br />
*[[BiologicalUnit/Quat]] (alternative implementation)<br />
*[[Symexp]]<br />
*[[SuperSym]]<br />
*[http://pdbbeta.rcsb.org/pdb/static.do?p=education_discussion/Looking-at-Structures/bioassembly_tutorial.html PDB Tutorial Biol. Units]<br />
*[http://en.wikipedia.org/wiki/Fiber_diffraction Wikipedia article]<br />
<br />
[[Category:Script_Library]]<br />
[[Category:Math_Scripts]]<br />
[[Category:Structural_Biology_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=8412Rotamer Toggle2010-08-17T08:04:30Z<p>Newacct: </p>
<hr />
<div>===DESCRIPTION===<br />
Backbone-Dependent Rotamer library (Dunbrack, Cohen ; see ref) is imported into pymol giving access to this information. There are a number of different ways to use the data, I've only implemented a few as well as added extra functions that seemed useful.<br />
*Rotamer Menu - an added menu into menu.py, which displays the most common rotamers for the given(clicked) residue; you can also set the residue any of the common rotamers as well<br />
*colorRotamers - color rotamers by closest matching rotamer angles from database; i.e. color by how common each rotamer of selection, blue - red (least to most common).<br />
*set_rotamer - routine called by above menu, but can be called manually to set a specific residues side-chain angles<br />
*set_phipsi - set all phi,psi angles of given selection to given angles (useful for creating secondary structures)<br />
*createRotamerPDBs - create pdb for each rotamer of given selection ; filter by rotamer-probability<br />
<br />
===IMAGES===<br />
<gallery><br />
Image:RotamerMenu.png|Rotamer Menu for a GLN residue<br />
Image:GLURotamerComparison5.png|Rotamer Comparison of crystal structure and most common for GLU; just as an example<br />
</gallery><br />
<br />
Print out while selecting most common rotamer from above-left image (GLN residue):<br />
Given GLN:40 PHI,PSI (-171.626373291,-96.0500335693) : bin (-170,-100)<br />
CHIs: [179.18069458007812, 72.539344787597656, -47.217315673828125]<br />
Setting Chi1 to -176.9<br />
Setting Chi2 to 177.4<br />
Setting Chi3 to 0.7<br />
<br />
===SETUP===<br />
run "rotamers.py" and use functions from commandline.<br />
<br />
or<br />
<br />
To setup a rotamer menu inside the residue menu (default windows pymol installation):<br />
*copy rotamers.py to C:/Program Files/DeLano Scientific/PyMol/modules/pymol/rotamers.py<br />
*copy mymenu.py to C:/Program Files/DeLano Scientific/PyMol/modules/pymol/menu.py (WARNING : overwrites default menu.py - use at your own risk)<br />
*copy bbdep02.May.sortlib to C:/Program Files/DeLano Scientific/PyMol/modules/pymol/bbdep02.May.sortlib (or newer version of sorted bbdep)<br />
This is only one possible way to do this, I am sure there are many others. I'm not going to post the bbdep, but there is a link in the References section to Dunbrack's download page (get the "sorted" lib)<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform, Red Hat Linux 9.0 and Fedora Core 4. Will test v0.98 and MacOSX later on.<br />
*The way it's setup now, when you import rotamers , it will automatically read-in the rotamer database; this may not be what you want.<br />
*Post problems in the discussion page, on 'my talk' page or just email me : dwkulp@mail.med.upenn.edu<br />
<br />
TASKS TODO:<br />
*Rotamer Movie, using mset, etc create movie to watch cycle through rotamers<br />
*Code could be organized a bit better; due to time constraints this is good for now..<br />
<br />
TASKS DONE:<br />
*Store crystal structure in rotamer menu, so you can go back to original orientation<br />
<br />
===USAGE===<br />
colorRotamers selection<br />
set_rotamer selection, chi1_angle [,chi2_angle] [,chi3_angle] [,chi4_angle]<br />
set_phipsi selection phi_angle, psi_angle<br />
createRotamerPBDs selection [,ncutoff] [,pcutoff] [,prefix]<br />
<br />
===EXAMPLES===<br />
colorRotamers chain A<br />
set_rotamer resi 40, -60,-40 (only set chi1,chi2 angles)<br />
set_phipsi resi 10-40, -60,-60 (create an alpha-helical-like section)<br />
createRotamerPDBs resi 10-12, ncutoff=3 (create 9 PDBs; each with one of the 3 most probable rotamers for resi 10,11,12)<br />
createRotamerPDBs resi 14, pcutoff=0.4 (create a pdb file for each rotamer of residue 14 with probablity > 0.4)<br />
<br />
===REFERENCES===<br />
Dunbrack and Cohen. Protein Science 1997<br />
<br />
[http://dunbrack.fccc.edu/bbdep/index.php Dunbrack Lab Page (Contains backbone-dependent library)]<br />
<br />
===SCRIPTS (Rotamers.py ; MyMenu.py)===<br />
Rotamers.py <br />
<source lang="python"><br />
##################################################################<br />
# File: Rotamers.py<br />
# Author: Dan Kulp<br />
# Creation Date: 6/8/05<br />
# Contact: dwkulp@mail.med.upenn.edu<br />
#<br />
# Notes:<br />
# Incorporation of Rotamer library<br />
# readRotLib() - fills rotdat; <br />
# indexed by "RES:PHI_BIN:PSI_BIN".<br />
#<br />
# Three main functions:<br />
# 1. colorRotamers - colors according<br />
# to rotamer probablitity<br />
# 2. getBins(sel)<br />
# phi,psi bin for rotamer<br />
# 3. set_rotamer - set a side-chain <br />
# to a specific rotamer<br />
#<br />
# To setup a rotamer menu in the <br />
# right click, under "Residue"<br />
# 1. cp mymenu.py modules/pymol/menu.py<br />
# 2. cp rotamers.py modules/pymol/rotamers.py (update ROTLIB)<br />
#<br />
# Requirements:<br />
# set ROTLIB to path for rotamer library<br />
# Reference: <br />
# Dunbrack and Cohen. Protein Science 1997<br />
####################################################################<br />
<br />
import colorsys,sys<br />
import editing<br />
import os<br />
import cmd<br />
import math<br />
<br />
# Path for library<br />
ROTLIB=os.environ['PYMOL_PATH']+"/modules/pymol/bbdep02.May.sortlib"<br />
<br />
# Place for library in memory..<br />
rotdat = {}<br />
<br />
def readRotLib():<br />
# Column indexes in rotamer library..<br />
RES = 0<br />
PHI = 1<br />
PSI = 2<br />
PROB = 8<br />
CHI1 = 9<br />
CHI2 = 10<br />
CHI3 = 11<br />
CHI4 = 12<br />
<br />
if os.path.exists(ROTLIB):<br />
print "File exists: "+ROTLIB<br />
input = open(ROTLIB, 'r')<br />
for line in input:<br />
<br />
# Parse by whitespace (I believe format is white space and not fixed-width columns)<br />
dat = line.split()<br />
<br />
# Add to rotamer library in memory : <br />
# key format RES:PHI_BIN:PSI_BIN<br />
# value format PROB, CHI1, CHI2, CHI3, CHI4<br />
key=dat[RES]+":"+dat[PHI]+":"+dat[PSI]<br />
if key in rotdat:<br />
rotdat[key].append([ dat[PROB], dat[CHI1], dat[CHI2], dat[CHI3], dat[CHI4] ])<br />
else:<br />
rotdat[key] = [ [ dat[PROB], dat[CHI1], dat[CHI2], dat[CHI3], dat[CHI4] ] ]<br />
<br />
<br />
else:<br />
print "Couldn't find Rotamer library"<br />
<br />
<br />
# Atoms for each side-chain angle for each residue<br />
CHIS = {}<br />
CHIS["ARG"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","NE" ],<br />
["CG","CD","NE","CZ" ]<br />
]<br />
<br />
CHIS["ASN"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","OD2" ]<br />
]<br />
<br />
CHIS["ASP"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","OD1" ]<br />
]<br />
CHIS["CYS"] = [ ["N","CA","CB","SG" ]<br />
]<br />
<br />
CHIS["GLN"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","OE1"]<br />
]<br />
<br />
CHIS["GLU"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","OE1"]<br />
]<br />
<br />
CHIS["HIS"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","ND1"]<br />
]<br />
<br />
CHIS["ILE"] = [ ["N","CA","CB","CG1" ],<br />
["CA","CB","CG1","CD1" ]<br />
]<br />
<br />
CHIS["LEU"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1" ]<br />
]<br />
<br />
CHIS["LYS"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","CE"],<br />
["CG","CD","CE","NZ"]<br />
]<br />
<br />
CHIS["MET"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","SD" ],<br />
["CB","CG","SD","CE"]<br />
]<br />
<br />
CHIS["PHE"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1" ]<br />
]<br />
<br />
CHIS["PRO"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ]<br />
]<br />
<br />
CHIS["SER"] = [ ["N","CA","CB","OG" ]<br />
]<br />
<br />
CHIS["THR"] = [ ["N","CA","CB","OG1" ]<br />
]<br />
<br />
CHIS["TRP"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1"]<br />
]<br />
<br />
CHIS["TYR"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1" ]<br />
]<br />
<br />
CHIS["VAL"] = [ ["N","CA","CB","CG1" ]<br />
]<br />
<br />
# Color Rotamer by side-chain angle position<br />
# 'bin' side-chain angles into closest<br />
def colorRotamers(sel):<br />
doRotamers(sel)<br />
<br />
# Utility function, to set phi,psi angles for a given selection<br />
# Note: Cartoon, Ribbon functionality will not display correctly after this<br />
def set_phipsi(sel, phi,psi):<br />
doRotamers(sel,angles=[phi,psi],type="set")<br />
<br />
# Set a rotamer, based on a selection, a restype and chi angles<br />
def set_rotamer(sel, chi1, chi2=0,chi3=0,chi4=0):<br />
at = cmd.get_model("byres ("+sel+")").atom[0]<br />
<br />
list = [chi1,chi2,chi3,chi4]<br />
for i in range(len(CHIS[at.resn])):<br />
print "Setting Chi"+str(i+1)+" to "+str(list[i])<br />
editing.set_dihedral(sel + ' and name '+CHIS[at.resn][i][0],<br />
sel + ' and name '+CHIS[at.resn][i][1],<br />
sel + ' and name '+CHIS[at.resn][i][2],<br />
sel + ' and name '+CHIS[at.resn][i][3], str(list[i]))<br />
<br />
# Remove some objects that got created<br />
cmd.delete("pk1")<br />
cmd.delete("pk2")<br />
cmd.delete("pkmol")<br />
<br />
# Get Phi,Psi bins for given selection<br />
# WARNING: assume selection is single residue (will only return first residue bins)<br />
def getBins(sel):<br />
return doRotamers(sel, type="bins")<br />
<br />
# Color Ramp...<br />
def rot_color(vals): <br />
nbins = 10<br />
vals.sort(key=lambda x:x[1])<br />
# print "End sort: "+str(len(vals))+" : "+str(nbins)<br />
<br />
<br />
# Coloring scheme...<br />
j = 0<br />
rgb = [0.0,0.0,0.0]<br />
sel_str = ""<br />
for i in range(len(vals)):<br />
if int(len(vals)/nbins) == 0 or i % int(len(vals)/nbins) == 0:<br />
hsv = (colorsys.TWO_THIRD - colorsys.TWO_THIRD * float(j) / (nbins-1), 1.0, 1.0)<br />
<br />
#convert to rgb and append to color list<br />
rgb = colorsys.hsv_to_rgb(hsv[0],hsv[1],hsv[2])<br />
if j < nbins-1:<br />
j += 1<br />
<br />
cmd.set_color("RotProbColor"+str(i), rgb)<br />
cmd.color("RotProbColor"+str(i), str(vals[i][0]))<br />
<br />
<br />
# Main function<br />
def doRotamers(sel,angles=[], type="color"):<br />
<br />
# Read in Rotamer library if not already done<br />
if len(rotdat) == 0:<br />
readRotLib()<br />
<br />
# Set up some variables..<br />
residues = ['dummy'] # Keep track of residues already done<br />
probs = [] # probability of each residue conformation<br />
phi = 0 # phi,psi angles of current residue<br />
psi = 0<br />
<br />
# Get atoms from selection<br />
atoms = cmd.get_model("byres ("+sel+")")<br />
<br />
# Loop through atoms in selection<br />
for at in atoms.atom:<br />
try:<br />
# Don't process Glycines or Alanines<br />
if not (at.resn == 'GLY' or at.resn == 'ALA'):<br />
if at.chain+":"+at.resn+":"+at.resi not in residues:<br />
residues.append(at.chain+":"+at.resn+":"+at.resi)<br />
<br />
# Check for a null chain id (some PDBs contain this) <br />
unit_select = ""<br />
if at.chain != "":<br />
unit_select = "chain "+str(at.chain)+" and "<br />
<br />
# Define selections for residue i-1, i and i+1<br />
residue_def = unit_select+'resi '+str(at.resi)<br />
residue_def_prev = unit_select+'resi '+str(int(at.resi)-1)<br />
residue_def_next = unit_select+'resi '+str(int(at.resi)+1)<br />
<br />
# Compute phi/psi angle<br />
<br />
phi = cmd.get_dihedral(residue_def_prev+' and name C',residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C',residue_def_next+' and name N')<br />
if type == "set":<br />
print "Changing "+at.resn+str(at.resi)+" from "+str(phi)+","+str(psi)+" to "+str(angles[0])+","+str(angles[1])<br />
cmd.set_dihedral(residue_def_prev+' and name C',residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C',residue_def_next+' and name N', angles[1])<br />
continue<br />
<br />
# Find correct 10x10 degree bin <br />
phi_digit = abs(int(phi)) - abs(int(phi/10)*10)<br />
psi_digit = abs(int(psi)) - abs(int(psi/10)*10)<br />
<br />
# Remember sign of phi,psi angles<br />
phi_sign = 1<br />
if phi < 0: phi_sign = -1<br />
<br />
psi_sign = 1<br />
if psi < 0: psi_sign = -1<br />
<br />
# Compute phi,psi bins<br />
phi_bin = int(math.floor(abs(phi/10))*10*phi_sign)<br />
if phi_digit >= 5: phi_bin = int(math.ceil(abs(phi/10))*10*phi_sign)<br />
<br />
psi_bin = int(math.floor(abs(psi/10))*10*psi_sign)<br />
if psi_digit >= 5: psi_bin = int(math.ceil(abs(psi/10))*10*psi_sign)<br />
<br />
print "Given "+at.resn+":"+at.resi+" PHI,PSI ("+str(phi)+","+str(psi)+") : bin ("+str(phi_bin)+","+str(psi_bin)+")"<br />
<br />
<br />
# Get current chi angle measurements<br />
chi = []<br />
for i in range(len(CHIS[at.resn])):<br />
chi.append(cmd.get_dihedral(residue_def + ' and name '+CHIS[at.resn][i][0],<br />
residue_def + ' and name '+CHIS[at.resn][i][1],<br />
residue_def + ' and name '+CHIS[at.resn][i][2],<br />
residue_def + ' and name '+CHIS[at.resn][i][3]))<br />
print "CHIs: "+str(chi)<br />
if type == 'bins':<br />
return [at.resn, phi_bin,psi_bin]<br />
<br />
# Compute probabilities for given chi angles<br />
prob = 0<br />
prob_box = 22 <br />
for item in range(len(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)])):<br />
print "Rotamer from db: "+str(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item])<br />
if chi[0]:<br />
if chi[0] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][1]) - (prob_box/2) and \<br />
chi[0] <= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][1]) + (prob_box/2):<br />
if len(chi) == 1:<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
if chi[1] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][2]) - (prob_box/2) and \<br />
float(chi[1] <= rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][2]) + (prob_box/2):<br />
if len(chi) == 2:<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
if chi[2] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][3]) - (prob_box/2) and \<br />
float(chi[2] <= rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][3]) + (prob_box/2):<br />
if len(chi) == 3:<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
if chi[3] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][4]) - (prob_box/2) and \<br />
float(chi[3] <= rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][4]) + (prob_box/2):<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
<br />
<br />
print "PROB OF ROTAMER: "+str(prob)<br />
print "---------------------------"<br />
probs.append([residue_def, prob])<br />
<br />
except:<br />
# probs.append([residue_def, -1])<br />
print "Exception found"<br />
continue<br />
<br />
# Color according to rotamer probability<br />
rot_color(probs)<br />
<br />
<br />
<br />
<br />
# Create PDB files containing most probable rotamers<br />
def createRotamerPDBs(sel,ncutoff=10,pcutoff=0,prefix="ROTAMER"):<br />
<br />
# Get atoms from selection<br />
atoms = cmd.get_model("byres ("+sel+")")<br />
<br />
# Set up some variables..<br />
residues = ['dummy'] # Keep track of residues already done<br />
<br />
# Loop through atoms in selection<br />
for at in atoms.atom:<br />
if at.resn in ('GLY','ALA') or "%s:%s:%s" % (at.chain,at.resn,at.resi) in residues:<br />
continue<br />
<br />
# Add to residue list (keep track of which ones we've done)<br />
residues.append("%s:%s:%s" % (at.chain,at.resn,at.resi))<br />
<br />
# Check for a null chain id (some PDBs contain this)<br />
unit_select = ""<br />
if not at.chain == "":<br />
unit_select = "chain "+str(at.chain)+" and "<br />
<br />
# Define selections for residue <br />
residue_def = unit_select+'resi '+str(at.resi)<br />
<br />
# Get bin (phi,psi) definitions for this residue<br />
bin = doRotamers(residue_def, type='bins')<br />
<br />
# Store crystal angle<br />
crystal_angles = [0.0,0.0,0.0,0.0]<br />
for angle in range(3):<br />
try:<br />
crystal_angles[angle] = bin[3][angle]<br />
except IndexError:<br />
break<br />
<br />
# Retreive list of rotamers for this phi,psi bin + residue type<br />
match_rotamers = rotdat["%s:%s:%s" % (bin[0],str(bin[1]),str(bin[2]))]<br />
<br />
count = 0<br />
for item in range(len(match_rotamers)):<br />
<br />
# Store probablity<br />
prob = match_rotamers[item][0]<br />
<br />
# Check cutoffs<br />
if float(prob) <= float(pcutoff):<br />
continue<br />
<br />
if float(count) >= float(ncutoff):<br />
break<br />
<br />
# Increment count<br />
count += 1<br />
<br />
# Output to screen ...<br />
print "Residue %s%s, rotamer %i, prob %s" % (str(at.resn),str(at.resi),int(item),str(prob))<br />
<br />
# Set to new rotamer<br />
set_rotamer(residue_def,match_rotamers[item][1],match_rotamers[item][2],match_rotamers[item][3],match_rotamers[item][4]) <br />
<br />
# Store in PDB file<br />
cmd.save("%s_%s%s_%i_%s.pdb" % (prefix,str(at.resn),str(at.resi),int(item),str(prob)))<br />
<br />
# Reset crystal angle<br />
set_rotamer(residue_def,crystal_angles[0],crystal_angles[1],crystal_angles[2],crystal_angles[3])<br />
<br />
# Uncommenting this is nice because it loads rotamer library upon startup<br />
# however, it slows the PyMOL loading process a lot<br />
# instead I've put this call into the menuing code..<br />
# readRotLib()<br />
<br />
cmd.extend('set_phipsi',set_phipsi)<br />
cmd.extend('set_rotamer',set_rotamer)<br />
cmd.extend('colorRotamers',colorRotamers)<br />
cmd.extend('createRotamerPDBs',createRotamerPDBs)<br />
</source><br />
<br />
MyMenu.py<br />
Since menu.py is copyrighted I can't post my edited version, but you can create it very simply by adding these two peices of code<br />
<br />
1. In the "pick_option(title,s,object=0)" function of menu.py add the following code after the first "result =" statement<br />
<source lang="python"><br />
# Edit dwkulp 6/11/05 , add a rotamer menu to residue menu<br />
if title == 'Residue':<br />
result.extend([[ 1, 'rotamers' , rotamer_menu(s)]])<br />
</source><br />
<br />
2. At the end of the file add this:<br />
<source lang="python"><br />
###############################################<br />
# Dan Kulp<br />
# Added Rotamer list to residue menu..<br />
# rotamer.py must be importable (I placed it in <br />
# the same directory as menu.py)<br />
###############################################<br />
<br />
import rotamers<br />
<br />
<br />
def rotamer_menu(s):<br />
# Check for rotamer library being loaded<br />
if not rotamers.rotdat:<br />
rotamers.readRotLib()<br />
# return [ [2, "Must run rotamers.py first",'']]<br />
<br />
# Check for valid rotamer residue..<br />
res = cmd.get_model("byres ("+s+")").atom[0].resn<br />
if not res in rotamers.CHIS.keys():<br />
return [ [2, "Residue: "+res+" not known sidechain or does not have rotamers", '']]<br />
<br />
# Get PHI,PSI bins for rotamer (also prints out current phi,psi, chi1,chi2,chi3,chi4)<br />
bins = rotamers.doRotamers(s,type='bins')<br />
<br />
# Add a title to the menu<br />
result = [ [2, bins[0]+' Rotamers in bin ('+str(bins[1])+','+str(bins[2])+')','' ], [1, ':::PROB,CHI1,CHI2,CHI3,CHI4:::','']]<br />
<br />
# Grab the entries for this residue and phi,psi bins<br />
match_rotamers = rotamers.rotdat[bins[0]+":"+str(bins[1])+":"+str(bins[2])]<br />
<br />
# Set max number of rotamers to display (probably should be somewhere 'higher up' in the code)<br />
max_rotamers = min(10, len(match_rotamers))<br />
<br />
# Create menu entry for each possible rotamer<br />
for item in range(max_rotamers):<br />
result.append( [ 1, str(match_rotamers[item]), 'rotamers.set_rotamer("'+s+'","'\<br />
+str(match_rotamers[item][1])+'","'\<br />
+str(match_rotamers[item][2])+'","'\<br />
+str(match_rotamers[item][3])+'","'\<br />
+str(match_rotamers[item][4])+'")'])<br />
return result<br />
<br />
<br />
</source><br />
<br />
<br />
[[Category:Script_Library|Rotamer Toggle]]<br />
<br />
[[Category:Structural_Biology_Scripts|Rotamer Toggle]]</div>Newaccthttps://pymolwiki.org/index.php?title=Wfmesh&diff=8095Wfmesh2010-03-11T20:36:14Z<p>Newacct: </p>
<hr />
<div>===DESCRIPTION===<br />
This script will create an object for any Wavefront(.OBJ) mesh file. This is a way to extend the number of objects you can use. Also, you have more control over the coloring, transformations, etc than the CGOs. Although there are a number of these obj files on the web, you can also easily created them with open source tools ([http://www.openfx.org OpenFX], [http://synapses.mcg.edu/tools/xroads/xroads.stm Crossroads3D]). It takes literally, 2 min to get an object created and then loaded into pymol. Simply open OpenFX Designer, click File->Insert->Model, then choose any of the models (or create your own of course!), then export it as .3ds file. Then open the .3ds file from Crossroads3D and export as Wavefront OBJ. <br />
<br />
*createWFMesh - create a mesh object from Wavefront (*.obj) formated file<br />
<br />
===IMAGES===<br />
[[Image:Starwars_pymol.png|thumb|left|Star Wars Anyone?]]<br />
[[Image:Torus_pymol.png|thumb|left|A Torus, as an example shape you could do. Notice polygon normals are being used...need smoothing!]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
[[Category:ThirdParty_Scripts]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
===SETUP===<br />
Simply "run WFMesh.py"<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform, should work on linux as well.<br />
*Coloring is fixed for grey and sections of mesh are stored, but not used.<br />
*Simple opengl calls; not optimized (display lists, etc) or anything.<br />
*Vertex Normal code is broken, so normals are per polygon right now.<br />
*Post problems in the discussion page, on 'my talk' page or just email me : dwkulp@mail.med.upenn.edu<br />
<br />
<br />
===USAGE===<br />
createWFObj file, name [,translate=[0,0,0]] [,flip=0]<br />
<br />
===EXAMPLES===<br />
createWFObj "ship.obj" "Ship"<br />
createWFObj "torus.obj" "Torus" flip=1 # Flip = 1, if OBJ created by openFX, crossroads3D combination<br />
createWFObj "torus.obj" "Torus" translate=[10,10,0] flip=1 <br />
<br />
===REFERENCES===<br />
[http://www.openfx.org OpenFX]<br />
[http://synapses.mcg.edu/tools/xroads/xroads.stm Crossroads3D]<br />
<br />
===SCRIPTS (WFMesh.py)===<br />
WFMesh.py<br />
<source lang="python"><br />
###############################################<br />
# File: WFObj.py<br />
# Author: Dan Kulp<br />
# Creation Date: 5/13/05<br />
#<br />
# Notes:<br />
# Create openGL objects from a wavefront (obj) file<br />
###############################################<br />
<br />
import os<br />
import re<br />
import math<br />
from pymol.opengl.gl import *<br />
from pymol.callback import Callback<br />
<br />
<br />
# Wrapper Function, to create a given WFObj with a specific name (flip = 1 if OpenFX + Crossroads used)<br />
def createWFObj(file, name,translate=[0,0,0],flip=0):<br />
obj = WFMesh(file,translate,flip)<br />
cmd.load_callback(obj,name)<br />
<br />
<br />
# Class for Wavefront Mesh<br />
class WFMesh(Callback):<br />
<br />
verts = [] # list of vertices<br />
polys = [] # list of poylgons<br />
pnorms = [] # list of polynomal normals<br />
vnorms = {} # dict. of vertex normals<br />
vavenorms = [] # list of vertex normals, redundant -- I'm far froma python pro.<br />
sections = {} # list of sections of mesh<br />
<br />
# Read mesh into memory<br />
def readOBJ(self,file):<br />
if os.path.exists(file):<br />
input = open(file,'r')<br />
for line in input:<br />
dat = re.split("\s+", line)<br />
<br />
# Find vertex line<br />
if line[0] == 'v' and line[1] != 't' and line[1] != 'n': self.verts.append([dat[1],dat[2],dat[3]])<br />
<br />
# Find polygon line<br />
if line[0] == 'f': self.polys.append([dat[1],dat[2],dat[3]])<br />
<br />
# Find section line<br />
if line[0] == 'g': self.sections[len(self.polys)] = dat[1] <br />
<br />
<br />
# Compute the normals for each polygon and each vertex <br />
def computeNorms(self):<br />
<br />
# Compute norms for each polygon<br />
for p in self.polys:<br />
v12 = [float(self.verts[int(p[1])-1][0]) - float(self.verts[int(p[0])-1][0]),\<br />
float(self.verts[int(p[1])-1][1]) - float(self.verts[int(p[0])-1][1]),\<br />
float(self.verts[int(p[1])-1][2]) - float(self.verts[int(p[0])-1][2]) \<br />
]<br />
<br />
v13 = [float(self.verts[int(p[2])-1][0]) - float(self.verts[int(p[0])-1][0]),\<br />
float(self.verts[int(p[2])-1][1]) - float(self.verts[int(p[0])-1][1]),\<br />
float(self.verts[int(p[2])-1][2]) - float(self.verts[int(p[0])-1][2]) \<br />
] <br />
<br />
# Compute poly normal<br />
polynorm = self.cross(v12,v13) <br />
norm = self.normalize(polynorm)<br />
<br />
<br />
# Files created by OpenFX, Crossroads combination need have their normals flipped <br />
if self.flip:<br />
norm[0] = -norm[0]<br />
norm[1] = -norm[1]<br />
norm[2] = -norm[2]<br />
<br />
# Append poly norm to polygonal norm array<br />
self.pnorms.append(norm)<br />
<br />
# Add norm to each vertexes norm..<br />
try:<br />
self.vnorms[int(p[0])-1] = [float(self.vnorms[int(p[0])-1][0]) + norm[0],<br />
float(self.vnorms[int(p[0])-1][1]) + norm[1],<br />
float(self.vnorms[int(p[0])-1][2]) + norm[2]<br />
]<br />
except:<br />
self.vnorms[int(p[0])-1] = [norm[0],norm[1],norm[2]]<br />
<br />
try: <br />
self.vnorms[int(p[1])-1] = [float(self.vnorms[int(p[1])-1][0]) + norm[0],<br />
float(self.vnorms[int(p[1])-1][1]) + norm[1],<br />
float(self.vnorms[int(p[1])-1][2]) + norm[2]<br />
]<br />
except:<br />
self.vnorms[int(p[1])-1] = [norm[0],norm[1],norm[2]]<br />
<br />
try:<br />
self.vnorms[int(p[2])-1] = [float(self.vnorms[int(p[1])-1][0]) + norm[0],<br />
float(self.vnorms[int(p[1])-1][1]) + norm[1],<br />
float(self.vnorms[int(p[1])-1][2]) + norm[2]<br />
]<br />
except:<br />
self.vnorms[int(p[2])-1] = [norm[0],norm[1],norm[2]]<br />
<br />
<br />
# Average out each vnorm..<br />
index = 0<br />
for v in self.vnorms.values():<br />
self.vavenorms.append([v[0]/4, v[1]/4, v[2]/4]) <br />
index += 1<br />
<br />
# Utility function to normalize a given vector<br />
def normalize(self,v):<br />
mag = v[0]*v[0]+v[1]*v[1]+v[2]*v[2]<br />
if mag <= 0:<br />
mag = 1<br />
else:<br />
mag = math.sqrt(mag)<br />
<br />
return [v[0]/mag, v[1]/mag,v[2]/mag]<br />
<br />
# Utility cross product function<br />
def cross(self,v1,v2):<br />
x = 0<br />
y = 1<br />
z = 2<br />
<br />
return [v1[y]*v2[z] - v1[z]*v2[y],\<br />
v1[z]*v2[x] - v1[x]*v2[z],\<br />
v1[x]*v2[y] - v1[y]*v2[x]<br />
]<br />
<br />
# Constructor<br />
def __init__(self, file,translate=[0,0,0],flip=0):<br />
self.verts = []<br />
self.polys = [] <br />
self.pnorms = []<br />
self.vnorms = {}<br />
self.vavenorms = []<br />
self.translate = translate<br />
self.flip = flip <br />
<br />
print "Read in file: "+str(file)<br />
self.readOBJ(file)<br />
print "Done reading in WFMesh, now compute norms"<br />
self.computeNorms()<br />
print "Done computing norms, now display WFMesh"<br />
<br />
# Draw Function<br />
def __call__(self):<br />
<br />
glColorMaterial(GL_FRONT, GL_DIFFUSE); <br />
glEnable(GL_COLOR_MATERIAL);<br />
glShadeModel(GL_SMOOTH);<br />
<br />
# Color Everything grey<br />
glColor3f(0.5,0.5,0.5);<br />
<br />
glPushMatrix()<br />
glTranslated(self.translate[0],self.translate[1],self.translate[2])<br />
for index, p in enumerate(self.polys):<br />
glBegin(GL_POLYGON)<br />
glNormal3f(float(self.pnorms[index][0]),float(self.pnorms[index][1]),float(self.pnorms[index][2]))<br />
<br />
for x in p:<br />
glVertex3f(float(self.verts[int(x)-1][0]),float(self.verts[int(x)-1][1]),float(self.verts[int(x)-1][2]))<br />
<br />
# Vertex Normals - not computed correctly, so commented out for now<br />
# norm = self.vnorms[int(x)-1]<br />
# glNormal3f(float(norm[0]),float(norm[1]),float(norm[2]))<br />
glEnd()<br />
glPopMatrix()<br />
<br />
<br />
<br />
<br />
<br />
cmd.extend("createWFObj", createWFObj)<br />
</source><br />
<br />
===ADDITIONAL RESOURCES===<br />
Torus.obj<br />
[http://pymolwiki.org/images/9/98/Torus.zip Torus.zip]<br />
<br />
<br />
[[Category:Script_Library|WFMesh]]</div>Newaccthttps://pymolwiki.org/index.php?title=Nmr_cnstr&diff=8092Nmr cnstr2010-03-10T09:44:43Z<p>Newacct: </p>
<hr />
<div>This script will display the NMR constrains used for a structure calculation atop a structure. Usage: Save this as "NMRcnstr.py" load your protein in PyMOL, and run the script. type upl('fname') or cns('fname') where fname is the filename with the NMR constrains you want to display. It is still a very preliminary version. <br />
<br />
[[Image:Cns.png]] [[Image:Upl.png]]<br />
<br />
<br />
<br />
<source lang="python"><br />
##############################################################################################################<br />
# Pymol Script: For visualizing the NMR constrains (DYANA & CNS format), on top of the calculated structure. #<br />
# Author: Evangelos Papadopoulos. #<br />
# current affiliation: Dept. of Biochemistry and Biophysics, #<br />
# Arrhenius Laboratories, #<br />
# Stockholm University #<br />
# SE-106 91 Stockholm, Sweden #<br />
# email:evangelos@dbb.su.se tel: +468164580 #<br />
# NOTES: This is a preliminary version. #<br />
# #<br />
# '''Reference:''' please if you find this script usefull add the following reference: #<br />
# NMR Solution Structure of the Peptide Fragment 1-30, Derived from Unprocessed Mouse Doppel #<br />
# Protein, in DHPC Micelles. Biochemistry. 2006 Jan 10;45(1):159-166. PMID: 16388591 #<br />
# #<br />
##############################################################################################################<br />
<br />
<br />
<br />
def upl(fname):<br />
<br />
f=open(fname,'r')<br />
i=1<br />
upl=f.readline()<br />
#<br />
while upl!='':<br />
<br />
print upl,i<br />
cns=string.split(upl)<br />
cmd.dist('upl'+str(i),'i. '+cns[0]+' & n. '+cns[2],'i. '+cns[3]+' & n. '+cns[5])<br />
upl=f.readline()<br />
i+=1<br />
#<br />
f.close()<br />
cmd.hide('labels')<br />
cmd.set ('dash_gap', 0.05)<br />
cmd.do ("orient")<br />
cmd.set ('movie_delay', 1500)<br />
<br />
def cns(fname):<br />
<br />
f=open(fname,'r')<br />
i=1<br />
upl=f.readline()<br />
print upl,i<br />
while upl!='':<br />
if upl=='\n': <br />
upl=f.readline()<br />
continue<br />
cns=string.split(upl)<br />
print cns,i<br />
if cns[0]=='assign' : <br />
print 'CNS'<br />
if cns[5]=='HB*': print 'CNS***'<br />
cmd.dist('upl'+str(i),'i. '+cns[2]+' & n. '+cns[5],'i. '+cns[7]+' & n. '+cns[10])<br />
i+=1<br />
upl=f.readline()<br />
print '*'+upl+'*',i<br />
<br />
f.close()<br />
cmd.set ('dash_gap', 0.05)<br />
cmd.hide('labels')<br />
cmd.do ("orient")<br />
cmd.set ('movie_delay', 1500)<br />
</source><br />
[[Category:Script_Library|Show NMR Constraints]]<br />
[[Category:Structural_Biology_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Pucker&diff=8091Pucker2010-03-10T08:57:56Z<p>Newacct: </p>
<hr />
<div>===DESCRIPTION=== <br />
'''pucker.py''' is a PyMol script that returns the sugar pucker information (phase, amplitude, pucker) for a given selection.<br />
<br />
This script uses its own dihedral calculation scheme rather than the get_dihedral command. Thus, it is lightning fast!<br />
<br />
If a selection does not contain any ribose sugars then an error message is returned. <br />
<br />
===USAGE===<br />
<br />
load the script using the [[run]] command<br />
<br />
<source lang="python"><br />
pucker selection<br />
#Calculates the sugar information for the given selection<br />
<br />
pucker selection, state=1<br />
#Calculates the sugar information for the given selection in state 1<br />
<br />
pucker selection, state=0 <br />
#Iterates over all states and calculates the sugar information for the given selection <br />
</source><br />
<br />
===EXAMPLES===<br />
<source lang="python"><br />
#fetch 1BNA.pdb<br />
fetch 1bna<br />
<br />
#Select DNA only<br />
#Otherwise, you will get an error for water not having sugars<br />
select DNA, not solvent<br />
<br />
#Execute pucker command<br />
pucker DNA<br />
<br />
#The output should look like this<br />
Phase Amp Pucker Residue<br />
161.22 55.32 C2'-endo A 1<br />
139.52 41.67 C1'-exo A 2<br />
92.82 38.31 O4'-endo A 3<br />
166.35 48.47 C2'-endo A 4<br />
128.57 46.30 C1'-exo A 5<br />
126.92 49.75 C1'-exo A 6<br />
101.30 47.32 O4'-endo A 7<br />
115.62 49.23 C1'-exo A 8<br />
140.44 46.37 C1'-exo A 9<br />
145.79 53.36 C2'-endo A 10<br />
147.47 47.04 C2'-endo A 11<br />
113.80 51.69 C1'-exo A 12<br />
<br />
Phase Amp Pucker Residue<br />
153.24 43.15 C2'-endo B 13<br />
128.49 45.01 C1'-exo B 14<br />
67.74 43.84 C4'-exo B 15<br />
149.33 41.01 C2'-endo B 16<br />
169.27 42.30 C2'-endo B 17<br />
147.03 42.30 C2'-endo B 18<br />
116.29 47.52 C1'-exo B 19<br />
129.62 49.92 C1'-exo B 20<br />
113.61 42.93 C1'-exo B 21<br />
156.34 50.98 C2'-endo B 22<br />
116.89 44.21 C1'-exo B 23<br />
34.70 45.55 C3'-endo B 24<br />
</source><br />
<br />
<br />
===PYMOL API===<br />
<br />
<source lang=python><br />
from pymol.cgo import * # get constants<br />
from math import *<br />
from pymol import cmd<br />
<br />
def pucker(selection,state=1):<br />
<br />
# Author: Sean Law<br />
# Institute: Michigan State University<br />
# E-mail: slaw@msu.edu<br />
<br />
#Comparison to output from 3DNA is identical<br />
#Note that the 3DNA output has the second chain<br />
#printed out in reverse order<br />
state=int(state)<br />
if state == 0:<br />
for state in range(1,cmd.count_states()+1):<br />
sel=cmd.get_model(selection,state)<br />
if state == 1:<br />
print " " #Blank line to separate chain output<br />
print "%5s %6s %6s %8s Residue" % ("State","Phase","Amp", "Pucker")<br />
get_pucker(sel,iterate=state)<br />
else:<br />
sel=cmd.get_model(selection,state)<br />
get_pucker(sel,iterate=0)<br />
return<br />
<br />
def get_pucker (sel,iterate=0):<br />
iterate=int(iterate)<br />
first=1<br />
old=" "<br />
oldchain=" "<br />
residue={}<br />
theta={}<br />
count=0<br />
for atom in sel.atom:<br />
new=atom.chain+" "+str(atom.resi)<br />
newchain=atom.chain+" "+atom.segi<br />
if oldchain != newchain and first:<br />
if iterate == 0:<br />
print " " #Blank line to separate chain output<br />
print "%6s %6s %8s Residue" % ("Phase", "Amp", "Pucker")<br />
if new != old and not first:<br />
#Check that all 5 atoms exist<br />
if len(residue) == 15:<br />
#Construct planes<br />
get_dihedrals(residue,theta)<br />
#Calculate pucker<br />
info = pseudo(residue,theta)<br />
print info+" "+old<br />
else:<br />
print "There is no sugar in this residue"<br />
if oldchain != newchain:<br />
print " " #Blank line to separate chain output<br />
print "%6s %6s %8s Residue" % ("Phase", "Amp", "Pucker")<br />
#Clear values<br />
residue={}<br />
dihedrals={}<br />
theta={}<br />
#Store new value<br />
store_atom(atom,residue)<br />
else:<br />
store_atom(atom,residue)<br />
first=0<br />
old=new<br />
oldchain=newchain<br />
#Final Residue<br />
#Calculate dihedrals for final residue<br />
if len(residue) == 15:<br />
#Construct planes<br />
get_dihedrals(residue,theta)<br />
#Calculate pucker for final residue<br />
info = pseudo(residue,theta)<br />
if iterate == 0:<br />
print info+" "+old<br />
else:<br />
print "%5d %s" % (iterate,info+" "+old)<br />
else:<br />
print "There is no sugar in this residue"<br />
return<br />
<br />
def sele_exists(sele):<br />
return sele in cmd.get_names("selections");<br />
<br />
def pseudo(residue,theta):<br />
other=2*(sin(math.radians(36.0))+sin(math.radians(72.0)))<br />
<br />
#phase=atan2((theta4+theta1)-(theta3+theta0),2*theta2*(sin(math.radians(36.0))+sin(math.radians(72.0))))<br />
phase=atan2((theta['4']+theta['1'])-(theta['3']+theta['0']),theta['2']*other)<br />
amplitude=theta['2']/cos(phase)<br />
phase=math.degrees(phase)<br />
if phase < 0:<br />
phase+=360 # 0 <= Phase < 360<br />
#Determine pucker<br />
if phase < 36:<br />
pucker = "C3'-endo"<br />
elif phase < 72:<br />
pucker = "C4'-exo"<br />
elif phase < 108:<br />
pucker = "O4'-endo"<br />
elif phase < 144:<br />
pucker = "C1'-exo"<br />
elif phase < 180:<br />
pucker = "C2'-endo"<br />
elif phase < 216:<br />
pucker = "C3'-exo"<br />
elif phase < 252:<br />
pucker = "C4'-endo"<br />
elif phase < 288:<br />
pucker = "O4'-exo"<br />
elif phase < 324:<br />
pucker = "C1'-endo"<br />
elif phase < 360:<br />
pucker = "C2'-exo"<br />
else:<br />
pucker = "Phase is out of range"<br />
info = "%6.2f %6.2f %8s" % (phase, amplitude, pucker)<br />
return info<br />
<br />
<br />
def store_atom(atom,residue):<br />
if atom.name == "O4'" or atom.name == "O4*":<br />
residue['O4*X'] = atom.coord[0]<br />
residue['O4*Y'] = atom.coord[1]<br />
residue['O4*Z'] = atom.coord[2]<br />
elif atom.name == "C1'" or atom.name == "C1*":<br />
residue['C1*X'] = atom.coord[0]<br />
residue['C1*Y'] = atom.coord[1]<br />
residue['C1*Z'] = atom.coord[2]<br />
elif atom.name == "C2'" or atom.name == "C2*":<br />
residue['C2*X'] = atom.coord[0]<br />
residue['C2*Y'] = atom.coord[1]<br />
residue['C2*Z'] = atom.coord[2]<br />
elif atom.name == "C3'" or atom.name == "C3*":<br />
residue['C3*X'] = atom.coord[0]<br />
residue['C3*Y'] = atom.coord[1]<br />
residue['C3*Z'] = atom.coord[2]<br />
elif atom.name == "C4'" or atom.name == "C4*":<br />
residue['C4*X'] = atom.coord[0]<br />
residue['C4*Y'] = atom.coord[1]<br />
residue['C4*Z'] = atom.coord[2]<br />
return<br />
<br />
def get_dihedrals(residue,theta):<br />
<br />
C = []<br />
ribose = residue.keys()<br />
ribose.sort()<br />
<br />
shift_up(ribose,6)<br />
for i in range (0,12):<br />
C.append(residue[ribose[i]])<br />
theta['0']=calcdihedral(C)<br />
<br />
C = []<br />
shift_down(ribose,3)<br />
for i in range (0,12):<br />
C.append(residue[ribose[i]])<br />
theta['1']=calcdihedral(C)<br />
<br />
<br />
C = []<br />
shift_down(ribose,3)<br />
for i in range (0,12):<br />
C.append(residue[ribose[i]])<br />
theta['2']=calcdihedral(C)<br />
<br />
<br />
C = []<br />
shift_down(ribose,3)<br />
for i in range (0,12):<br />
C.append(residue[ribose[i]])<br />
theta['3']=calcdihedral(C)<br />
<br />
C = []<br />
shift_down(ribose,3)<br />
for i in range (0,12):<br />
C.append(residue[ribose[i]])<br />
theta['4']=calcdihedral(C)<br />
<br />
return<br />
<br />
def shift_up(list,value):<br />
for i in range (0,value):<br />
list.insert(0,list.pop())<br />
return<br />
<br />
def shift_down(list,value):<br />
for i in range (0,value):<br />
list.append(list.pop(0))<br />
return<br />
<br />
def calcdihedral(C):<br />
<br />
DX12=C[0]-C[3]<br />
DY12=C[1]-C[4]<br />
DZ12=C[2]-C[5]<br />
<br />
DX23=C[3]-C[6]<br />
DY23=C[4]-C[7]<br />
DZ23=C[5]-C[8]<br />
<br />
DX43=C[9]-C[6];<br />
DY43=C[10]-C[7];<br />
DZ43=C[11]-C[8];<br />
<br />
#Cross product to get normal<br />
<br />
PX1=DY12*DZ23-DY23*DZ12;<br />
PY1=DZ12*DX23-DZ23*DX12;<br />
PZ1=DX12*DY23-DX23*DY12;<br />
<br />
NP1=sqrt(PX1*PX1+PY1*PY1+PZ1*PZ1);<br />
<br />
PX1=PX1/NP1<br />
PY1=PY1/NP1<br />
PZ1=PZ1/NP1<br />
<br />
PX2=DY43*DZ23-DY23*DZ43;<br />
PY2=DZ43*DX23-DZ23*DX43;<br />
PZ2=DX43*DY23-DX23*DY43;<br />
<br />
NP2=sqrt(PX2*PX2+PY2*PY2+PZ2*PZ2);<br />
<br />
PX2=PX2/NP2<br />
PY2=PY2/NP2<br />
PZ2=PZ2/NP2<br />
<br />
DP12=PX1*PX2+PY1*PY2+PZ1*PZ2<br />
<br />
TS=1.0-DP12*DP12<br />
<br />
if TS < 0:<br />
TS=0<br />
else:<br />
TS=sqrt(TS)<br />
<br />
ANGLE=math.pi/2.0-atan2(DP12,TS)<br />
<br />
PX3=PY1*PZ2-PY2*PZ1<br />
PY3=PZ1*PX2-PZ2*PX1<br />
PZ3=PX1*PY2-PX2*PY1<br />
<br />
DP233=PX3*DX23+PY3*DY23+PZ3*DZ23<br />
<br />
if DP233 > 0:<br />
ANGLE=-ANGLE<br />
<br />
ANGLE=math.degrees(ANGLE)<br />
<br />
if ANGLE > 180:<br />
ANGLE-=360<br />
if ANGLE < -180:<br />
ANGLE+=360<br />
<br />
return ANGLE<br />
<br />
cmd.extend("pucker",pucker)<br />
<br />
</source><br />
<br />
[[Category:Script_Library]]<br />
[[Category:Biochemical_Properties]]<br />
[[Category:Biochemical_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Colorama&diff=8089Colorama2010-03-03T10:35:29Z<p>Newacct: </p>
<hr />
<div>=COLORAMA=<br />
<br />
COLORAMA is a PyMOL plugin which allows to color objects using adjustable scale bars. <br />
<br />
==Program features==<br />
In RGB mode, each color R, G, B is represented by one scale bar which can be manually adjusted while the selected object is colored in real time. For convenience, it is as well possible to switch to the HSV color system.<br />
<br />
Additionally, a color gradient with user-defined start- and end-colors can be created for the selected molecule.<br />
<br />
==Screenshot==<br />
[[Image:COLORAMA-screenshot.jpg]]<br />
<br />
==Usage==<br />
<br />
Install the program by copying the code below into an empty text file (e.g. "colorama.py") located in the \Pymol\modules\pmg_tk\startup directory. After PyMOL has been started, the program can be launched from the PLUGINS menu. COLORAMA has not been tested with PyMOL versions older than 1.0.<br />
<br />
===Single color===<br />
<br />
#Type the name of a PyMOL object to be colored into the COLORAMA entry field.<br />
#Push the "Set" button.<br />
#The scales are adjusted to the current color which is additionally visualized in a field left to the scales.<br />
#If one of the scales is moved, the color of the selected object will change in real-time.<br />
#Pushing the RGB or HSV buttons on the left allows to switch between both color systems.<br />
<br />
===Color gradients===<br />
<br />
#After an object has been selected, push the "G" button (gradient).<br />
#Select the start color by pushing "C1" and adjusting it using the scales.<br />
#Select the end color "C2" in the same way.<br />
#To create the gradient, push "Set gradient".<br />
<br />
A new object will be created which is called "dummy-OLD_OBJECT". The B-factor column of this object is overwritten and now contains the number of each residue. The original object is left unchanged. The gradient mode can be left by pushing "M" (monochrome).<br />
This part of the program uses a modified version of the [http://pldserver1.biochem.queensu.ca/~rlc/work/pymol/ color_b script] by Robert L. Campbell & James Stroud.<br />
<br />
==Contact==<br />
Gregor Hagelueken,<br />
gh50@st-andrews.ac.uk<br />
<br />
==Code==<br />
<source lang="python"><br />
"""<br />
--- COLORAMA: Coloring Widget for PyMOL --- <br />
Author : Gregor Hagelueken<br />
Program : Color_select<br />
Date : Oct 2007<br />
Version : 0.1.1<br />
Mail : gha@helmholtz-hzi.de<br />
<br />
<br />
<br />
COLORAMA is a plugin for the PyMOL Molecular Graphics System. <br />
It allows to color molecules using RGB or HSV colors which can be manually adjusted. <br />
Alternatively, a user defined color gradient can be applied to the molecule.<br />
The program works properly with PyMOL versions >=1.0.<br />
<br />
<br />
The program uses a modified version of the color_b program by Robert L. Campbell & James Stroud<br />
for the gradient calculation and the RGBToHTMLColor function by Paul Winkler.<br />
<br />
Literature:<br />
DeLano, W.L. The PyMOL Molecular Graphics System (2002) DeLano Scientific, San Carlos, CA, USA. http://www.pymol.org<br />
<br />
----------------------------------------------------------------------<br />
----------------------------------------------------------------------<br />
<br />
"""<br />
<br />
import colorsys,sys<br />
from pymol import cmd,stored<br />
from Tkinter import *<br />
class Colorama:<br />
def __init__ (self,master):<br />
#create frames<br />
self.F1 = Frame(roota, padx=5, pady=5, bg='red')<br />
self.F2 = Frame(roota, padx=5, pady=5, bg='green')<br />
self.F3 = Frame(roota, padx=5, pady=5, bg='blue')<br />
self.F4 = Frame(self.F1, padx=5, pady=5, bg='yellow')<br />
self.F5 = Frame(self.F1, padx=5, pady=5, bg='white')<br />
self.F6 = Frame(self.F1, padx=5, pady=5, bg='pink')<br />
<br />
#color system radiobuttons<br />
self.Radiocolorsystem = IntVar()<br />
self.RGB = Radiobutton (self.F3, text='RGB', indicatoron=0, variable=self.Radiocolorsystem, value=1, command=self.Scalergb)<br />
self.HSV = Radiobutton (self.F3, text='HSV', indicatoron=0, variable=self.Radiocolorsystem, value=2, command=self.Scalehsv)<br />
<br />
#mono/gradient and Farbe1/Farbe2 radiobuttons<br />
self.RadioMonoGradient = IntVar()<br />
self.RadioFarbe12 = IntVar()<br />
self.Monobutton = Radiobutton (self.F3, text='M', indicatoron=0, variable=self.RadioMonoGradient, value=1, command=self.Mono)<br />
self.Gradbutton = Radiobutton (self.F3, text='G', indicatoron=0, variable=self.RadioMonoGradient, value=2, command=self.Grad)<br />
self.Farbe1button = Radiobutton (self.F3, text='C1', indicatoron=0, variable=self.RadioFarbe12, value=1, command=self.Farbe1) <br />
self.Farbe2button = Radiobutton (self.F3, text='C2', indicatoron=0, variable=self.RadioFarbe12, value=2, command=self.Farbe2) <br />
<br />
#preselect RGB and mono<br />
self.RGB.select()<br />
self.Monobutton.select()<br />
self.Farbe1button.select()<br />
self.monograd='mono'<br />
self.colorsystem='rgb'<br />
self.farbe12='farbe1'<br />
<br />
#initialize the scales<br />
self.Scales()<br />
<br />
#other GUI elements<br />
self.selectionentry = Entry(master=self.F5, font=('Arial', 10))<br />
self.selectionentry.insert(0,"")<br />
self.selectionbutton = Button(master=self.F5, text='Set', command=self.setselection)<br />
self.setgradientbutton = Button(master=self.F5, text='Set Gradient', command=self.setgradient)<br />
self.label = Label(master=self.F4, text="None", font=('Arial', 10))<br />
self.selectionlabel = Label(master=self.F4, text="Active:", font=('Arial', 10))<br />
self.inputlabel = Label (master=self.F5, text="Object:", font=('Arial', 10))<br />
self.colorfield1 = Label(master=self.F3,width=3, height=10)<br />
self.colorfield2 = Label(master=self.F3,width=3, height=10)<br />
<br />
self.selection=""<br />
self.setselection()<br />
<br />
#start layout procedure<br />
self.layout()<br />
<br />
def layout(self):<br />
self.F1.pack(side=TOP, anchor=NW)<br />
self.F4.pack(side=BOTTOM, fill=X, anchor=W)<br />
self.F5.pack(side=TOP)<br />
self.F2.pack(side=RIGHT, fill=Y)<br />
self.F3.pack(side=LEFT, fill=X)<br />
<br />
#entry and buttons<br />
self.setgradientbutton.pack(side=RIGHT,fill=X, anchor=NE)<br />
self.selectionbutton.pack(side=RIGHT, anchor=N)<br />
self.selectionentry.pack(side=RIGHT,fill=X, anchor=NE)<br />
<br />
#labels<br />
self.inputlabel.pack(side=TOP, anchor=NW)<br />
self.selectionlabel.pack(side=LEFT, anchor=W)<br />
self.label.pack(side=LEFT)<br />
<br />
#colorfields<br />
self.colorfield2.pack(side=RIGHT)<br />
self.colorfield1.pack(side=RIGHT)<br />
<br />
#scales<br />
self.ScaleRed.pack(side=RIGHT, fill=Y)<br />
self.ScaleGreen.pack(side=RIGHT, fill=Y)<br />
self.ScaleBlue.pack(side=RIGHT, fill=Y)<br />
<br />
#radiobuttons<br />
self.RGB.pack(side=TOP, fill=X)<br />
self.HSV.pack(side=TOP, fill=X)<br />
self.Monobutton.pack(side=TOP, fill=X)<br />
self.Gradbutton.pack(side=TOP, fill=X)<br />
self.Farbe1button.pack(side=TOP, fill=X)<br />
self.Farbe2button.pack(side=TOP, fill=X)<br />
<br />
def Scales(self):<br />
self.ScaleRed = Scale(master=self.F2, label='R', length='3c',<br />
from_=0, to=255,<br />
#set(startred),<br />
command=self.setzeFarbe)<br />
self.ScaleGreen = Scale(master=self.F2, label='G', length='3c',<br />
from_=0, to=255,<br />
#set(startgreen),<br />
command=self.setzeFarbe)<br />
self.ScaleBlue = Scale(master=self.F2, label='B', length='3c',<br />
from_=0, to=255,<br />
#set(startblue),<br />
command=self.setzeFarbe)<br />
<br />
def Scalergb(self):<br />
if self.colorsystem=='hsv':<br />
h=float(self.ScaleRed.get())<br />
s=float(self.ScaleGreen.get())<br />
v=float(self.ScaleBlue.get())<br />
rgbcolor = colorsys.hsv_to_rgb(h,s,v)<br />
r=255*rgbcolor[0]<br />
g=255*rgbcolor[1]<br />
b=255*rgbcolor[2]<br />
self.ScaleRed.config(label='R', from_=0, to=255, resolution=1)<br />
self.ScaleGreen.config(label='G', from_=0, to=255, resolution=1)<br />
self.ScaleBlue.config(label='B', from_=0, to=255, resolution=1)<br />
self.ScaleRed.set(r)<br />
self.ScaleGreen.set(g)<br />
self.ScaleBlue.set(b)<br />
self.colorsystem='rgb'<br />
<br />
def Scalehsv(self):<br />
if self.colorsystem=='rgb':<br />
r=float(self.ScaleRed.get())/255<br />
g=float(self.ScaleGreen.get())/255<br />
b=float(self.ScaleBlue.get())/255<br />
hsvcolor = colorsys.rgb_to_hsv(r,g,b)<br />
h=hsvcolor[0]<br />
s=hsvcolor[1]<br />
v=hsvcolor[2]<br />
self.ScaleRed.config(label='H', from_=0, to=1, resolution=0.01)<br />
self.ScaleGreen.config(label='S', from_=0, to=1, resolution=0.01)<br />
self.ScaleBlue.config(label='V', from_=0, to=1, resolution=0.01)<br />
self.ScaleRed.set(h)<br />
self.ScaleGreen.set(s)<br />
self.ScaleBlue.set(v)<br />
self.colorsystem='hsv'<br />
<br />
def Mono(self):<br />
self.monograd='mono'<br />
<br />
def Grad(self):<br />
self.monograd='grad'<br />
<br />
def Farbe1(self):<br />
#Let the scales know which color is to be changed<br />
self.farbe12='farbe1'<br />
#set scales to farbe1<br />
if self.monograd=='grad':<br />
if self.colorsystem=='rgb':<br />
startred=self.farbe1[0]<br />
startgreen=self.farbe1[1]<br />
startblue=self.farbe1[2] <br />
self.ScaleRed.set(startred)<br />
self.ScaleGreen.set(startgreen)<br />
self.ScaleBlue.set(startblue)<br />
elif self.colorsystem=='hsv':<br />
hsvcolor=colorsys.rgb_to_hsv(self.farbe1[0], self.farbe1[1], self.farbe1[2])<br />
h=hsvcolor[0]<br />
s=hsvcolor[1]<br />
v=hsvcolor[2]<br />
self.ScaleRed.set(h)<br />
self.ScaleGreen.set(s)<br />
self.ScaleBlue.set(v)<br />
<br />
def Farbe2(self):<br />
#Let the scales know which color is to be changed<br />
self.farbe12='farbe2'<br />
#set scales to farbe1<br />
if self.monograd=='grad':<br />
if self.colorsystem=='rgb':<br />
startred=self.farbe2[0]<br />
startgreen=self.farbe2[1]<br />
startblue=self.farbe2[2] <br />
self.ScaleRed.set(startred)<br />
self.ScaleGreen.set(startgreen)<br />
self.ScaleBlue.set(startblue)<br />
elif self.colorsystem=='hsv':<br />
hsvcolor=colorsys.rgb_to_hsv(self.farbe2[0], self.farbe2[1], self.farbe2[2])<br />
h=hsvcolor[0]<br />
s=hsvcolor[1]<br />
v=hsvcolor[2]<br />
self.ScaleRed.set(h)<br />
self.ScaleGreen.set(s)<br />
self.ScaleBlue.set(v)<br />
<br />
def setselection(self):<br />
if self.selectionentry.get() != "":<br />
self.selection=self.selectionentry.get()<br />
<br />
#Color of each residue is stored in stored.colorlist to check if the molecule has a colorgradient<br />
stored.colorlist = []<br />
cmd.iterate (self.selection+" & name CA", "stored.colorlist.append(int(color))")<br />
<br />
if len(stored.colorlist)==0:<br />
#for other objects (e.g. density...)<br />
stored.colorlist.append(cmd.get_object_color_index(self.selection))<br />
stored.colorlist.append(cmd.get_object_color_index(self.selection))<br />
<br />
<br />
initialcolornterm=cmd.get_color_tuple(stored.colorlist[0])<br />
initialcolorcterm=cmd.get_color_tuple(stored.colorlist[-1])<br />
self.farbe1=initialcolornterm[0]*255, initialcolornterm[1]*255, initialcolornterm[2]*255<br />
self.farbe2=initialcolorcterm[0]*255, initialcolorcterm[1]*255, initialcolorcterm[2]*255<br />
<br />
#Set active object to label<br />
self.label.config(text=self.selection)<br />
<br />
#check if there is a gradient and adjust Mono/Gradbutton<br />
if initialcolornterm==initialcolorcterm:<br />
self.Monobutton.select()<br />
self.Mono()<br />
<br />
elif initialcolornterm!=initialcolorcterm:<br />
self.Gradbutton.select()<br />
self.Grad()<br />
<br />
#adjust colorfields<br />
self.colorfield1.config(bg=self.RGBToHTMLColor(self.farbe1))<br />
self.colorfield2.config(bg=self.RGBToHTMLColor(self.farbe2))<br />
self.Farbe1button.select()<br />
self.Farbe1()<br />
<br />
#Set scales to initialcolor of the new object <br />
if self.colorsystem=='rgb':<br />
startred=255*initialcolornterm[0]<br />
startgreen=255*initialcolornterm[1]<br />
startblue=255*initialcolornterm[2] <br />
self.ScaleRed.set(startred)<br />
self.ScaleGreen.set(startgreen)<br />
self.ScaleBlue.set(startblue)<br />
elif self.colorsystem=='hsv':<br />
hsvcolor=colorsys.rgb_to_hsv(initialcolornterm[0], initialcolornterm[1], initialcolornterm[2])<br />
h=hsvcolor[0]<br />
s=hsvcolor[1]<br />
v=hsvcolor[2]<br />
self.ScaleRed.set(h)<br />
self.ScaleGreen.set(s)<br />
self.ScaleBlue.set(v)<br />
<br />
def setzeFarbe(self, event):<br />
if self.selection != "" && self.monograd == 'mono':<br />
if self.colorsystem=='rgb':<br />
col=[]<br />
#read RGB values from scales<br />
r=int(self.ScaleRed.get())<br />
g=int(self.ScaleGreen.get())<br />
b=int(self.ScaleBlue.get())<br />
rgbcolor=r,g,b<br />
#Prepare a rgb tupel<br />
col.append(rgbcolor)<br />
#hexcolor for colorfields<br />
hexcolor=self.RGBToHTMLColor(rgbcolor)<br />
self.colorfield1.config(bg=hexcolor)<br />
self.colorfield2.config(bg=hexcolor)<br />
cmd.delete(self.selection+"_color")<br />
cmd.set_color(self.selection+"_color", col[0])<br />
cmd.color(self.selection+"_color", self.selection)<br />
del col[0]<br />
elif self.colorsystem=='hsv':<br />
col=[]<br />
#read HSV values from scales<br />
h=float(self.ScaleRed.get())<br />
s=float(self.ScaleGreen.get())<br />
v=float(self.ScaleBlue.get())<br />
<br />
#HSV to RGB and change from 1.0, 1.0, 1.0 format to 255,255,255 format<br />
rgbcolor = colorsys.hsv_to_rgb(h,s,v)<br />
r = 255*rgbcolor[0]<br />
g = 255*rgbcolor[1]<br />
b = 255*rgbcolor[2]<br />
#as above<br />
rgbcolor = r,g,b<br />
col.append(rgbcolor)<br />
#hexcolor for colorfields<br />
hexcolor=self.RGBToHTMLColor(rgbcolor)<br />
self.colorfield1.config(bg=hexcolor)<br />
self.colorfield2.config(bg=hexcolor)<br />
cmd.delete(self.selection+"_color")<br />
cmd.set_color(self.selection+"_color", col[0])<br />
cmd.color(self.selection+"_color", self.selection)<br />
del col[0]<br />
elif self.selection !="" && self.monograd == 'grad':<br />
<br />
if self.colorsystem=='rgb':<br />
col=[]<br />
#read RGB values from scales<br />
r=int(self.ScaleRed.get())<br />
g=int(self.ScaleGreen.get())<br />
b=int(self.ScaleBlue.get())<br />
rgbcolor=r,g,b<br />
#Prepare a rgb tupel<br />
col.append(rgbcolor)<br />
#hexcolor for colorfields<br />
hexcolor=self.RGBToHTMLColor(rgbcolor)<br />
if self.farbe12=='farbe1':<br />
self.colorfield1.config(bg=hexcolor)<br />
self.farbe1=rgbcolor<br />
elif self.farbe12=='farbe2':<br />
self.colorfield2.config(bg=hexcolor)<br />
self.farbe2=rgbcolor<br />
<br />
elif self.colorsystem=='hsv':<br />
col=[]<br />
#read HSV values from scales<br />
h=float(self.ScaleRed.get())<br />
s=float(self.ScaleGreen.get())<br />
v=float(self.ScaleBlue.get())<br />
<br />
#HSV to RGB and change from 1.0, 1.0, 1.0 format to 255,255,255 format<br />
rgbcolor = colorsys.hsv_to_rgb(h,s,v)<br />
r = 255*rgbcolor[0]<br />
g = 255*rgbcolor[1]<br />
b = 255*rgbcolor[2]<br />
#as above<br />
rgbcolor = r,g,b<br />
col.append(rgbcolor)<br />
#hexcolor for colorfields<br />
hexcolor=self.RGBToHTMLColor(rgbcolor)<br />
<br />
if self.farbe12=='farbe1':<br />
self.colorfield1.config(bg=hexcolor)<br />
self.farbe1=rgbcolor<br />
elif self.farbe12=='farbe2':<br />
self.colorfield2.config(bg=hexcolor)<br />
self.farbe2=rgbcolor<br />
<br />
def setgradient(self):<br />
<br />
stored.residuelist = []<br />
cmd.iterate (self.selection, "stored.residuelist.append(int(resi))")<br />
firstresidue=min(stored.residuelist)<br />
lastresidue=max(stored.residuelist)<br />
rs=float(self.farbe1[0])/float(255)<br />
gs=float(self.farbe1[1])/float(255)<br />
bs=float(self.farbe1[2])/float(255)<br />
re=float(self.farbe2[0])/float(255)<br />
ge=float(self.farbe2[1])/float(255)<br />
be=float(self.farbe2[2])/float(255)<br />
hsvcolorstart = colorsys.rgb_to_hsv(rs, gs, bs)<br />
hs=hsvcolorstart[0]<br />
ss=hsvcolorstart[1]<br />
vs=hsvcolorstart[2]<br />
hsvcolorend = colorsys.rgb_to_hsv(re, ge, be)<br />
he=hsvcolorend[0]<br />
se=hsvcolorend[1]<br />
ve=hsvcolorend[2]<br />
color_grad(selection=self.selection, minimum=firstresidue, maximum=lastresidue, hs=hs, he=he,ss=ss,se=se,vs=vs,ve=ve)<br />
<br />
<br />
def RGBToHTMLColor(self, rgb_tuple):<br />
#by Paul Winkler<br />
""" convert an (R, G, B) tuple to #RRGGBB """<br />
hexcolor = '#%02x%02x%02x' % rgb_tuple<br />
# that's it! '%02x' means zero-padded, 2-digit hex values<br />
return hexcolor<br />
<br />
def __init__(self):<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Colorama',<br />
label = 'Colorama',<br />
command = lambda s=self : open_Colorama())<br />
<br />
def open_Colorama():<br />
#initialize window (roota)<br />
global roota<br />
roota = Tk()<br />
roota.title(' COLORAMA by gha')<br />
global colorama<br />
colorama = Colorama(roota)<br />
<br />
def color_grad(selection='',item='b',mode='hist',gradient='bgr',nbins=11,sat=1,value=1,minimum='1',maximum='1',dummy='dummy_all', hs=1, he=1, ss=1,se=1,vs=1,ve=1, colorname='init'):<br />
"""<br />
--- color_grad: color gradient tool for PyMOL --- <br />
Author : Gregor Hagelueken<br />
Program : Color_grad<br />
Date : Oct 2007<br />
Version : 0.1.0<br />
Mail : gha@helmholtz-hzi.de<br />
<br />
<br />
<br />
<br />
This is a modified version of the color_b program by Robert L. Campbell & James Stroud<br />
<br />
Literature:<br />
DeLano, W.L. The PyMOL Molecular Graphics System (2002) DeLano Scientific, San Carlos, CA, USA. http://www.pymol.org<br />
<br />
----------------------------------------------------------------------<br />
----------------------------------------------------------------------<br />
"""<br />
<br />
nbins=int(nbins)<br />
sat=float(sat)<br />
value=float(value)<br />
hs=float(hs)<br />
he=float(he)<br />
ss=float(ss)<br />
se=float(se)<br />
vs=float(vs)<br />
ve=float(ve)<br />
colorname='color_'+selection<br />
<br />
nbins=int(maximum)-int(minimum)+2<br />
dummy="dummy-"+selection<br />
colname="col"+selection<br />
<br />
<br />
# make sure sat and value are in the range 0-1.0<br />
sat = min(sat, 1.0)<br />
sat = max(sat, 0.0)<br />
value = min(value, 1.0)<br />
value = max(value, 0.0)<br />
<br />
# make sure lowercase<br />
gradient.lower()<br />
mode.lower()<br />
<br />
# Sanity checking<br />
if nbins == 1:<br />
print "\n WARNING: You specified nbins=1, which doesn't make sense...resetting nbins=11\n"<br />
nbins=11<br />
<br />
if mode not in ('hist','ramp'):<br />
print "\n WARNING: Unknown mode ",mode, " -----> Nothing done.\n"<br />
return<br />
if selection == '':<br />
print "\n USAGE: color_grad dimB, minimum=380, maximum=531, hs=0.3, he=0.25,ss=0.7,se=0.2,vs=1,ve=0.5\n"<br />
return<br />
elif gradient not in ('bgr','rgb','rainbow','reverserainbow','bwr','rwb',<br />
'bmr','rmb','rw','wr','gw','wg','bw','wb','gy','yg','gray','grey','reversegray','reversegrey'):<br />
print "\n WARNING: Unknown gradient: ",gradient, " -----> Nothing done.\n"<br />
return<br />
<br />
print "MODE, GRADIENT, NBINS:", mode,gradient, nbins<br />
<br />
# get list of B-factors from selection<br />
m = cmd.get_model(selection)<br />
sel = []<br />
b_list = []<br />
<br />
if len(m.atom) == 0:<br />
print "Sorry, no atoms selected"<br />
<br />
else:<br />
if item == 'b':<br />
for x in m.atom:<br />
x.b=x.resi<br />
b_list.append(x.b) <br />
<br />
elif item == 'q':<br />
for x in m.atom:<br />
b_list.append(x.q)<br />
<br />
else:<br />
print "Not configured to work on item %s" % item<br />
return<br />
<br />
cmd.load_model(m, dummy)<br />
<br />
print selection<br />
max_b = maximum<br />
min_b = minimum<br />
print "Minimum and Maximum B-values: ", min_b, max_b<br />
#nbins = (max_b - min_b)<br />
<br />
<br />
if mode == 'hist':<br />
<br />
# check if minimum or maximum was specified and use the entered values<br />
if minimum != '':<br />
min_b = int(minimum)-1<br />
if maximum != '':<br />
max_b = int(maximum)+1<br />
# histogram:<br />
# color in bins of equal B-value ranges<br />
# subtract 0.1 from the lowest B in order to ensure that the single<br />
# atom with the lowest B value doesn't get omitted<br />
bin_width = (max_b - min_b)/nbins<br />
sel.append(selection + " and (%s = %4.4g" % (item,min_b + bin_width) + ")")<br />
for j in range(1,nbins):<br />
#sel.append(selection + " and %s > %4.4g" % (item,min_b + j*bin_width))<br />
sel.append(dummy + " and %s = %4.4g" % (item,min_b + j*bin_width))<br />
<br />
<br />
# call the function to create the gradient which returns a list of colours<br />
colours = make_gradient(sel,gradient,nbins,sat,value,hs,he,ss,se,vs,ve,colorname)<br />
<br />
# do the colouring now<br />
for j in range(nbins):<br />
print "Color select: ",sel[j]<br />
cmd.color(colours[j],sel[j])<br />
sel = []<br />
colours = []<br />
# function for creating the gradient<br />
def make_gradient(sel,gradient,nbins,sat,value,hs,he,ss,se,vs,ve,colorname):<br />
if gradient == 'bgr' or gradient == 'rainbow':<br />
col=[]<br />
coldesc=[]<br />
for j in range(nbins):<br />
# must append the str(sel[j]) to the color name so that it is unique <br />
# for the selection<br />
coldesc.append(colorname + str(j))<br />
# coldesc.append('col' + str(sel[j]) + str(j))<br />
<br />
# create colors using hsv scale (fractional) starting at blue(.6666667) <br />
# through red(0.00000) in intervals of .6666667/(nbins -1) (the "nbins-1" <br />
# ensures that the last color is, in fact, red (0)<br />
# rewrote this to use the colorsys module to convert hsv to rgb<br />
hsv = (hs - (hs-he) * float(j) / (nbins-1), ss-(ss-se)*float(j)/(nbins-1), vs-(vs-ve)*float(j)/(nbins-1) )<br />
#convert to rgb and append to color list<br />
rgb = colorsys.hsv_to_rgb(hsv[0],hsv[1],hsv[2])<br />
<br />
col.append(rgb)<br />
# cmd.set_color("col" + str(sel[j]) + str(j),col[j])<br />
cmd.set_color(colorname + str(j),col[j])<br />
<br />
#cmd.color(,resi[j])<br />
<br />
# return the gradient as a list of colors named by their index (i.e. col0,col1,col2,col3,...)<br />
return coldesc<br />
</source><br />
<br />
==Download==<br />
[[Media:colorama-0.1.1.tar.bz2|colorama-0.1.1.tar.bz2]]<br />
<br />
[[Category:Plugins]]<br />
[[Category:Script_Library|Helicity Check]]<br />
[[Category:Coloring]]</div>Newaccthttps://pymolwiki.org/index.php?title=DynoPlot&diff=8088DynoPlot2010-03-03T10:30:28Z<p>Newacct: </p>
<hr />
<div>===DESCRIPTION===<br />
This script was setup to do generic plotting, that is given a set of data and axis labels it would create a plot. Initially, I had it setup to draw the plot directly in the PyMol window (allowing for both 2D and 3D style plots), but because I couldn't figure out how to billboard CGO objects (Warren told me at the time that it couldn't be done) I took a different approach. The plot now exists in it's own window and can only do 2D plots. It is however interactive. I only have here a Rama.(phi,psi) plot, but the code can be easily extended to other types of data. For instance, I had this working for an energy vs distance data that I had generated by another script.<br />
<br />
This script will create a Phi vs Psi(Ramachandran) plot of the selection given. The plot will display data points which can be dragged around Phi,Psi space with the corresponding residue's Phi,Psi angles changing in the structure (PyMol window).<br />
<br />
===IMAGES===<br />
<gallery><br />
Image:RamaPlotInitComposite.png|Initial Ramachandran plot of 1ENV<br />
Image:RamaPlotBentComposite.png|Modified pose and plot of 1ENV<br />
</gallery><br />
<br />
===SETUP===<br />
place the DynoPlot.py script into the appropriate startup directory then restart PyMol<br />
<br />
==== LINUX old-style installation ====<br />
<br />
$PYMOL_PATH/modules/pmg_tk/startup/<br />
<br />
==== LINUX distutils installation ====<br />
<br />
/usr/lib/pythonX.X/site-packages/pmg_tk/startup/<br />
<br />
==== Windows ====<br />
<br />
PYMOL_PATH/modules/pmg_tk/startup/ , where PYMOL_PATH on Windows is defaulted to C:/Program Files/DeLano Scientific/PyMol/start/<br />
<br />
===NOTES / STATUS===<br />
*Tested on Windows, PyMol version 0.97<br />
*This is an initial version, which needs some work. <br />
*Left, Right mouse buttons do different things; Right = identify data point, Left = drag data point around<br />
*Post comments/questions or send them to: dwkulp@mail.med.upenn.edu<br />
<br />
===USAGE===<br />
rama SELECTION<br />
<br />
===EXAMPLES=== <br />
*load pdb file 1ENV (download it or use the PDB loader plugin)<br />
*select resi 129-136<br />
*rama sel01<br />
*rock # the object needs to be moving in order for the angles to be updated.<br />
<br />
===REFERENCES===<br />
<br />
===SCRIPTS (DynoPlot.py)===<br />
DynoPlot.py<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
###############################################<br />
# File: DynoPlot.py<br />
# Author: Dan Kulp<br />
# Creation Date: 8/29/05<br />
#<br />
# Notes:<br />
# Draw plots that display interactive data.<br />
# Phi,Psi plot shown.<br />
###############################################<br />
<br />
<br />
from __future__ import division<br />
from __future__ import generators<br />
<br />
import os,math<br />
import Tkinter<br />
from Tkinter import *<br />
import Pmw<br />
import distutils.spawn # used for find_executable<br />
import random<br />
from pymol import cmd<br />
<br />
try:<br />
import pymol<br />
REAL_PYMOL = True<br />
except ImportError:<br />
print "Nope"<br />
<br />
canvas = None<br />
rootframe = None<br />
init = 0<br />
<br />
class SimplePlot(Tkinter.Canvas):<br />
<br />
# Class variables<br />
mark = 'Oval' # Only 'Oval' for now..<br />
mark_size = 5<br />
xlabels = [] # axis labels<br />
ylabels = []<br />
spacingx = 0 # spacing in x direction<br />
spacingy = 0<br />
xmin = 0 # min value from each axis<br />
ymin = 0<br />
lastx = 0 # previous x,y pos of mouse<br />
lasty = 0<br />
down = 0 # flag for mouse pressed<br />
item = (0,) # items array used for clickable events<br />
shapes = {} # store plot data, x,y etc..<br />
<br />
def axis(self,xmin=40,xmax=300,ymin=10,ymax=290,xint=290,yint=40,xlabels=[],ylabels=[]):<br />
<br />
# Store variables in self object<br />
self.xlabels = xlabels<br />
self.ylabels = ylabels<br />
self.spacingx = (xmax-xmin) / (len(xlabels) - 1)<br />
self.spacingy = (ymax-ymin) / (len(ylabels) - 1)<br />
self.xmin = xmin<br />
self.ymin = ymin<br />
<br />
# Create axis lines<br />
self.create_line((xmin,xint,xmax,xint),fill="black",width=3)<br />
self.create_line((yint,ymin,yint,ymax),fill="black",width=3)<br />
<br />
# Create tick marks and labels<br />
nextspot = xmin<br />
for label in xlabels:<br />
self.create_line((nextspot, xint+5,nextspot, xint-5),fill="black",width=2)<br />
self.create_text(nextspot, xint-15, text=label)<br />
if len(xlabels) == 1:<br />
nextspot = xmax<br />
else:<br />
nextspot += (xmax - xmin)/ (len(xlabels) - 1)<br />
<br />
<br />
nextspot = ymax<br />
for label in ylabels:<br />
self.create_line((yint+5,nextspot,yint-5,nextspot),fill="black",width=2)<br />
self.create_text(yint-20,nextspot,text=label)<br />
if len(ylabels) == 1:<br />
nextspot = ymin<br />
else:<br />
nextspot -= (ymax - ymin)/ (len(ylabels) - 1)<br />
<br />
<br />
# Plot a point<br />
def plot(self,xp,yp,meta):<br />
<br />
# Convert from 'label' space to 'pixel' space<br />
x = self.convertToPixel("X",xp)<br />
y = self.convertToPixel("Y",yp)<br />
<br />
if self.mark == "Oval":<br />
oval = self.create_oval(x-self.mark_size,y-self.mark_size,x+self.mark_size,y+self.mark_size,width=1,outline="black",fill="SkyBlue2")<br />
<br />
self.shapes[oval] = [x,y,0,xp,yp,meta]<br />
<br />
<br />
# Repaint all points<br />
def repaint(self):<br />
for value in self.shapes.values():<br />
x = value[0]<br />
y = value[1]<br />
self.create_oval(x-self.mark_size,y-self.mark_size,x+self.mark_size,y+self.mark_size,width=1,outline="black",fill="SkyBlue2")<br />
<br />
# Convert from pixel space to label space<br />
def convertToLabel(self,axis, value):<br />
<br />
# Defaultly use X-axis info<br />
label0 = self.xlabels[0]<br />
label1 = self.xlabels[1]<br />
spacing = self.spacingx<br />
min = self.xmin<br />
<br />
# Set info for Y-axis use<br />
if axis == "Y":<br />
label0 = self.ylabels[0]<br />
label1 = self.ylabels[1]<br />
spacing = self.spacingy<br />
min = self.ymin<br />
<br />
pixel = value - min<br />
label = pixel / spacing<br />
label = label0 + label * abs(label1 - label0)<br />
<br />
if axis == "Y":<br />
label = - label<br />
<br />
return label<br />
<br />
# Converts value from 'label' space to 'pixel' space<br />
def convertToPixel(self,axis, value):<br />
<br />
# Defaultly use X-axis info<br />
label0 = self.xlabels[0]<br />
label1 = self.xlabels[1]<br />
spacing = self.spacingx<br />
min = self.xmin<br />
<br />
# Set info for Y-axis use<br />
if axis == "Y":<br />
label0 = self.ylabels[0]<br />
label1 = self.ylabels[1]<br />
spacing = self.spacingy<br />
min = self.ymin <br />
<br />
<br />
# Get axis increment in 'label' space<br />
inc = abs(label1 - label0)<br />
<br />
# 'Label' difference from value and smallest label (label0)<br />
diff = float(value - label0)<br />
<br />
# Get whole number in 'label' space<br />
whole = int(diff / inc)<br />
<br />
# Get fraction number in 'label' space<br />
part = float(float(diff/inc) - whole)<br />
<br />
# Return 'pixel' position value<br />
pixel = whole * spacing + part * spacing<br />
<br />
# print "Pixel: %f * %f + %f * %f = %f" % (whole, spacing, part, spacing,pixel)<br />
<br />
# Reverse number by subtracting total number of pixels - value pixels<br />
if axis == "Y":<br />
tot_label_diff = float(self.ylabels[-1] - label0)<br />
tot_label_whole = int(tot_label_diff / inc)<br />
tot_label_part = float(float(tot_label_diff / inc) - tot_label_whole)<br />
tot_label_pix = tot_label_whole * spacing + tot_label_part *spacing<br />
<br />
pixel = tot_label_pix - pixel<br />
<br />
# Add min edge pixels<br />
pixel = pixel + min<br />
<br />
return pixel<br />
<br />
<br />
# Print out which data point you just clicked on..<br />
def pickWhich(self,event):<br />
<br />
# Find closest data point <br />
x = event.widget.canvasx(event.x)<br />
y = event.widget.canvasx(event.y)<br />
spot = event.widget.find_closest(x,y)<br />
<br />
# Print the shape's meta information corresponding with the shape that was picked<br />
if spot[0] in self.shapes:<br />
print "Residue(Ca): %s\n" % self.shapes[spot[0]][5][2]<br />
<br />
<br />
# Mouse Down Event<br />
def down(self,event):<br />
<br />
# Store x,y position<br />
self.lastx = event.x<br />
self.lasty = event.y<br />
<br />
# Find the currently selected item<br />
x = event.widget.canvasx(event.x)<br />
y = event.widget.canvasx(event.y)<br />
self.item = event.widget.find_closest(x,y)<br />
<br />
# Identify that the mouse is down<br />
self.down = 1<br />
<br />
# Mouse Up Event<br />
def up(self,event):<br />
<br />
# Get label space version of x,y<br />
labelx = self.convertToLabel("X",event.x)<br />
labely = self.convertToLabel("Y",event.y)<br />
<br />
# Convert new position into label space..<br />
if self.item[0] in self.shapes:<br />
self.shapes[self.item[0]][0] = event.x<br />
self.shapes[self.item[0]][1] = event.y<br />
self.shapes[self.item[0]][2] = 1<br />
self.shapes[self.item[0]][3] = labelx<br />
self.shapes[self.item[0]][4] = labely<br />
<br />
# Reset Flags<br />
self.item = (0,)<br />
self.down = 0<br />
<br />
<br />
# Mouse Drag(Move) Event<br />
def drag(self,event):<br />
<br />
# Check that mouse is down and item clicked is a valid data point<br />
if self.down and self.item[0] in self.shapes:<br />
<br />
self.move(self.item, event.x - self.lastx, event.y - self.lasty)<br />
<br />
self.lastx = event.x<br />
self.lasty = event.y<br />
<br />
<br />
def __init__(self):<br />
<br />
self.menuBar.addcascademenu('Plugin', 'PlotTools', 'Plot Tools',<br />
label='Plot Tools')<br />
self.menuBar.addmenuitem('PlotTools', 'command',<br />
'Launch Rama Plot',<br />
label='Rama Plot',<br />
command = lambda s=self: ramaplot())<br />
<br />
<br />
def ramaplot(x=0,y=0,meta=[],clear=0):<br />
global canvas<br />
global rootframe<br />
global init<br />
<br />
# If no window is open<br />
if init == 0:<br />
rootframe=Tk()<br />
rootframe.title(' Dynamic Angle Plotting ')<br />
rootframe.protocol("WM_DELETE_WINDOW", close_callback)<br />
<br />
canvas = SimplePlot(rootframe,width=320,height=320)<br />
canvas.bind("<Button-2>",canvas.pickWhich)<br />
canvas.bind("<Button-3>",canvas.pickWhich)<br />
canvas.bind("<ButtonPress-1>",canvas.down)<br />
canvas.bind("<ButtonRelease-1>",canvas.up)<br />
canvas.bind("<Motion>",canvas.drag)<br />
canvas.pack(side=Tkinter.LEFT,fill="both",expand=1)<br />
canvas.axis(xint=150,xlabels=[-180,-150,-120,-90,-60,-30,0,30,60,90,120,150,180],ylabels=[-180,-150,-120,-90,-60,-30,0,30,60,90,120,150,180])<br />
canvas.update()<br />
init = 1<br />
else:<br />
canvas.plot(int(x), int(y),meta)<br />
<br />
def close_callback():<br />
global init<br />
global rootframe<br />
init = 0<br />
rootframe.destroy()<br />
<br />
<br />
# New Callback object, so that we can update the structure when phi,psi points are moved.<br />
class DynoRamaObject:<br />
global canvas<br />
<br />
def start(self,sel):<br />
<br />
# Get selection model<br />
model = cmd.get_model(sel)<br />
residues = ['dummy']<br />
resnames = ['dummy']<br />
phi = []<br />
psi = []<br />
dummy = []<br />
i = 0<br />
<br />
# Loop through each atom<br />
for at in model.atom:<br />
<br />
# Only plot once per residue<br />
if at.chain+":"+at.resn+":"+at.resi not in residues:<br />
residues.append(at.chain+":"+at.resn+":"+at.resi)<br />
resnames.append(at.resn+at.resi)<br />
dummy.append(i)<br />
i += 1<br />
<br />
# Check for a null chain id (some PDBs contain this)<br />
unit_select = ""<br />
if at.chain != "":<br />
unit_select = "chain "+str(at.chain)+" and "<br />
<br />
# Define selections for residue i-1, i and i+1<br />
residue_def = unit_select+'resi '+str(at.resi)<br />
residue_def_prev = unit_select+'resi '+str(int(at.resi)-1)<br />
residue_def_next = unit_select+'resi '+str(int(at.resi)+1)<br />
<br />
try:<br />
# Store phi,psi residue definitions to pass on to plot routine<br />
phi_psi = [<br />
# Phi angles<br />
residue_def_prev+' and name C',<br />
residue_def+' and name N',<br />
residue_def+' and name CA',<br />
residue_def+' and name C',<br />
# Psi angles<br />
residue_def+' and name N',<br />
residue_def+' and name CA',<br />
residue_def+' and name C',<br />
residue_def_next+' and name N']<br />
<br />
# Compute phi/psi angle<br />
phi = cmd.get_dihedral(phi_psi[0],phi_psi[1],phi_psi[2],phi_psi[3])<br />
psi = cmd.get_dihedral(phi_psi[4],phi_psi[5],phi_psi[6],phi_psi[7])<br />
<br />
print "Plotting Phi,Psi: "+str(phi)+","+str(psi)<br />
ramaplot(phi,psi,meta=phi_psi)<br />
except:<br />
continue<br />
<br />
<br />
def __call__(self):<br />
<br />
# Loop through each item on plot to see if updated<br />
for key,value in canvas.shapes.items():<br />
dihedrals = value[5]<br />
<br />
# Look for update flag...<br />
if value[2]:<br />
<br />
# Set residue's phi,psi to new values<br />
print "Re-setting Phi,Psi: %s,%s" % (value[3],value[4])<br />
cmd.set_dihedral(dihedrals[0],dihedrals[1],dihedrals[2],dihedrals[3],value[3])<br />
cmd.set_dihedral(dihedrals[4],dihedrals[5],dihedrals[6],dihedrals[7],value[4])<br />
<br />
value[2] = 0<br />
<br />
<br />
<br />
# The wrapper function, used to create the Ploting window and the PyMol callback object <br />
def rama(sel):<br />
rama = DynoRamaObject()<br />
rama.start(sel)<br />
cmd.load_callback(rama, "DynoRamaObject")<br />
cmd.zoom("all")<br />
<br />
<br />
# Extend these commands<br />
cmd.extend('rama',rama)<br />
cmd.extend('ramaplot',ramaplot)<br />
</source><br />
<br />
===ADDITIONAL RESOURCES===<br />
<br />
<br />
<br />
[[Category:Script_Library|DynoPlot]]<br />
[[Category:Structural_Biology_Scripts|DynoPlot]]</div>Newaccthttps://pymolwiki.org/index.php?title=Slerpy&diff=8080Slerpy2010-03-01T08:01:34Z<p>Newacct: </p>
<hr />
<div>= Manual for Slerpy.py =<br />
<br />
An extension to pymol that creates a moderately easy to use environment for doing keyframe animation. <br />
<br />
<br />
==General Use==<br />
<br />
At the pymol command line type:<br />
<br />
import slerpy<br />
<br />
This will load the extended commands. All commands in slerpy begin with the letter s. Pymol's tab autocomplete feature will work on the additional commands.<br />
<br />
==Important concepts==<br />
<br />
The main function of slerpy is to record a series of pymol views. A movie can then be created by interpolating between these views. A pymol view consists mostly of the camera orientation (that is, the orientation of the viewers eye with respect to the molecule). It also includes information about the clipping planes.<br />
<br />
It is important to realize that most slerpy commands act on the "current" view. You can navigate among views by using the sn, sp, and sgo commands. If you've changed the view around with the mouse or you just want to know the number of the current view you can get back to the current view with the sc command.<br />
<br />
Pymol views do not contain information about how pymol objects and selections are displayed. If you just want to create a movie which moves around a single representation of a molecule then all you need to do is record the set of views that define the tour of the molecule.<br />
<br />
If, on the other hand, you want to change the representation or change which items are displayed you will need to add actions to some of your views. An action is any set of pymol commands. Actions can be associated with any view in the series recorded by slerpy. The ''sscene'' command inserts a new view and simultaneously creates a pymol scene and the action to display it. The scene will include all of the objects and representations visible at the time the command was issued.<br />
<br />
In order to control the rate of motion between the defined views in a slerpy movie, you can control the number of frames used in each interpolation. When a view is saved in slerpy it is associated by default with a transition of 50 frames to the next view. The number of frames in the transition can be altered with the ''ssetf'' command in slerpy.<br />
<br />
The views and actions stored by slerpy can (and should) be saved to a key file with the ''swrite'' command. They can then be retrieved with the sread command. Note that swrite saves the current pymol state in a .pse file but sread does not read in the .pse file. If you're starting a new pymol session to continue work on an existing movie you should load the pse file before doing an sread.<br />
<br />
==Quick Start Tutorial==<br />
<br />
If you haven't installed slerpy yet see [[#Installation|Installation]]<br />
<br />
;Step 1: You probably want to start off in a nice clean working directory that just has the coordinate files you want to work with.<br />
<br />
;Step 2: Read in your molecule(s) and create the various selections and representations that you want to include in the movie.<br />
<br />
;Step 3: At the pymol prompt, type:<br />
<br />
import slerpy<br />
<br />
;Step 4: Get your molecule in exactly the orientation and representation that you want to use for the beginning of your movie.<br />
<br />
;Step 5: Type:<br />
<br />
sinsert<br />
<br />
;Step 6: Using the mouse, move your molecule to the next orientation that you want to use. When you record the movie, the camera orientation will be interpolated between each consecutive pair of views. This can include changes in rotation, zooming, clipping etc.<br />
<br />
:Loop back to Step 5. Continue this until you've got all your orientations stored.<br />
<br />
:You can check how any set of transitions will look at any time by using the ''sshow'' command (see [[#Command Reference|Command Reference]] for details).<br />
<br />
:You can adjust the rate of any transition using the ''ssetf'' command<br />
<br />
;Step 7A: Add any actions to your views using the saction command. Any number of pymol commands can be strung together separated by semicolons. If, for example, you want to change your protein from a cartoon to a surface and add a ligand when you get to view 5 you would do the following (assuming you've defined the pymol selections prot and lig):<br />
<br />
sgo 5<br />
saction "hide cartoon, prot; show surface, prot; show sticks, lig"<br />
<br />
;Step 7B (Alternative using scenes):<br />
<br />
sgo 5<br />
<br />
:Now use the gui to create the representation you want and then:<br />
<br />
sscene<br />
<br />
;Step 8: Save everything. Save your slerpy views and actions as well as a pse file of your current pymol session:<br />
<br />
swrite mymovie<br />
<br />
This will create mymovie.key, which has all of the views, frame counts, actions etc. and mymovie.pse, the associated pymol session file.<br />
<br />
;Step 9: Record the movie! Type:<br />
<br />
srecord<br />
<br />
:You can then play the movie by typing the standard pymol command ''mplay'' or by clicking the play button in pymol.<br />
<br />
;Step 10: If you save the pymol session again, the pse file will contain the movie which can then be shown immediately after startup without running slerpy.py. Note that pymol will warn you when you load a pse file that contains a movie.<br />
<br />
;Step 11: If you want to, the movie can be exported using the mpng command (see the pymol [http://pymol.sourceforge.net/newman/ref/S1000comref.html#2_105 documentation]). Also, see the useful article [[Making_Movies|Making Movies]].<br />
<br />
==Tips and Tricks==<br />
<br />
===Converting scenes to movies===<br />
<br />
You can just step through the scenes and type sscene for each one. This will create a duplicate slerpy scene for each of the scenes you'd already saved but that's not such a disaster. Be sure to swrite when you're done.<br />
<br />
Note that there is some overhead associated with recalling scenes. To avoid pauses at view transitions, I prefer to actually issue the set of show and hide commands that will generate the scene rather than using the above method.<br />
<br />
===Starting off right===<br />
<br />
It's a bit of a pain, but I like to associate with the first frame of the movie an action list that hides everything and then turns on all the objects that I want to have visible at the beginning. This ensures that when your movie loops back to the beginning it will look the same as it did the first time through. For example:<br />
<br />
sgo 0<br />
saction "hide everything; show lines, prot; show surface, activesite; show sticks, ligand"<br />
<br />
Alternatively, start your slerpy work with an ''sscene''.<br />
<br />
===Live pymol presentations during a talk===<br />
Be sure to run your movie once it's been opened and before your presentation if you're presenting in pymol. This will ensure that any objects that don't appear until the middle of the movie are available in memory and won't need to be rebuilt while your audience waits.<br />
<br />
Of course showing your movie from within pymol allows you to show movies in stereo if you've got a presentation system that allows this. If you pass out stereo glasses first it's guaranteed that everyone will remember your talk...<br />
<br />
===Pausing on a view===<br />
<br />
Just sgo to the view you want to stay on for a while and do an sinsert. This will insert a new view with the same orientation etc as the one you were just on. You can adjust the length of the pause by changing the number of frames for the transistion between these two identical views using the ssetf command.<br />
<br />
===Morphing and multi-state models===<br />
<br />
Morphs and multi-conformation models are represented in pymol as single objects with multiple states. Cycling through the states as an animation is very straightforward in pymol. Slerpy allows you to include this animation over the states of an object as a transition between slerpy views within the context of larger movie. This is done using the ''smorph'' command (see [[#Command Reference|Command Reference]]). ''smorph'' allows you to specify the starting and ending pymol state numbers to use during the transition from the current to the next view. It will often be appropriate to have the movie continue after the morph using the final state of the morphing model, that is, the conformation to which you morphed. Since the default for a typical slerpy view is to show the first state of an object, you'll probably need to have available, in addition to your multi-state model, a single-state object containing the final conformation. You can then hide the multistate object and show the single-state final conformation as an action associated with the final view of your morphing sequence.<br />
<br />
To generate morphs you can use the [http://www.delanoscientific.com/rigimol.html rigimol] program provided by Warren as part of the incentive pymol package for subscribers or use [http://alpha2.bmc.uu.se/usf/mol_morph.html lsqman] from Gerard Kleywegt.<br />
<br />
==Command Reference==<br />
<br />
Note that it is essential to understand that slerpy uses the concept of a current or active view. This is the element in the list to which most commands are applied. It is not necessarily the view that is currently visible on the screen. It is advisable to use the sc command frequently to make sure you really know which view your command is being applied to.<br />
<br />
'''saction ''string'':''' Assoiciates the pymol commands in ''string'' with the current view. ''string'' must be enclosed in quotes and must contain only valid pymol commands separated by semicolons.<br />
<br />
'''sappend''': Add the currently displayed view at the end of the list of views in slerpy<br />
<br />
'''sappendaction ''string'':''' Adds the action(s) in ''string'' to the list of actions associated with the current view<br />
<br />
'''sc''': Go to the slerpy active view<br />
<br />
'''scrossfade ''startobject, endobject'':''' During the transition from the current view to the next view ''startobject'' will fade out and'' endobject'' will fade in. The two objects must be shown as sticks. They must be objects, not merely selections, as of pymol 0.99.<br />
<br />
'''sdelaction''': Deletes the action associated with the current view. Be sure you're sure which view you're on before you use this. This will also delete any actions etc. associated with the view so be careful.<br />
<br />
'''sdelete''': Remove the slerpy active view from the list of views to be interpolated.<br />
<br />
'''sdeletesetting: '''Remove the setting interpolation for the current view.<br />
<br />
'''sdumpactions: '''List all actions by frame.<br />
<br />
'''sgo ''n'':''' Change the slerpy active view to view ''n''.<br />
<br />
'''sinsert''': Add the currently displayed view after the slerpy active view.<br />
<br />
'''sinterpsetting ''setting, selection, startval, endval'' :''' The pymol setting ''setting'' will be interpolated linearly from ''startval'' to ''endval'' during the transition from the current view to the next view. You can only interpolate one setting per transition. This is the hard way to, for example, fade out an object:<br />
<br />
sinterpsetting stick_transparency, lig, 0.0, 1.0<br />
<br />
'''slist''': List all views stored for interpolation. Also lists the number of frames in each transition.<br />
<br />
'''smorph ''startmodel,endmodel'':''' The transition from the current frame to the next frame will consist of one frame per pymol state starting with state ''startmodel'' and ending with state ''endmodel''. Subsequent frames (i.e. from subsequent views) will revert to state 1. The state numbers apply to currently visible objects so you will most likely want to have an object with your starting conformation, an object with your multi-state morphing model, and an object with your final conformation. You would then sgo to the frame where you want the morph to start and add an action to hide the starting conformation object and show the multi-model morphing object, do an smorph 1,30 or whatever the number of states in your morph is, append another frame and give it an action where the multi-state model is hidden and the final conformation is shown.<br />
<br />
'''sn''': Go to the next view<br />
<br />
'''sp''': Go to the previous view.<br />
<br />
'''sread ''filename'':''' Restore all the information written with swrite. Does not read in the pse file (to avoid inadvertantly writing over some new selections, scenes or whatever).<br />
<br />
'''srecord''': Records the movie<br />
<br />
'''sreplace''': Replace the slerpy current view with the currently displayed view.<br />
<br />
'''sscene''': Add a the currently displayed view after the slerpy active view and create a scene to go with it. The current pymol state, including which objects are displayed and how they are shown will be captured.<br />
<br />
'''ssetf''': Set the number of frames to use in the transition from the slerpy active view to the next view<br />
<br />
'''ssetupview ''n'':''' This attempts to make sure that all objects are displayed (or not) as they would be when view ''n'' is arrived at in the movie. It goes through and executes all of the sactions from all preceeding views. For some reason this doesn't always work in complex cases.<br />
<br />
'''sshow ''n,m'':''' This command records and shows a segment of the movie showing the transitions starting with view n and ending with view m. If the arguments m and n are omitted the transition from the current view to the next view will be shown.<br />
<br />
'''swrite ''filename'':''' Writes all the information used by slerpy to a file ''filename''.key. It also writes a pymol session file ''filename''.pse containing all of your current objects, selections etc. The format of the .key file is supposed to be human readable and it can be convenient to edit this file rather than using saction over and over. After editing it by hand be sure to do an sread.<br />
<br />
==Why is it called slerpy?==<br />
<br />
slerp is an acronym of sorts for spherical linear interpolation. The transition between two views approximates spherical linear interpolation of the their camera positions using quaternions. See the Wikipedia [http://en.wikipedia.org/wiki/Slerp article] on slerps.<br />
<br />
=Script Files=<br />
<br />
==Installation==<br />
<br />
To install, copy (by pasting into a text editor) the following two python code segments to files named slerpy.py and movs.py, respectively. Place these files in the pymol/modules/pymol/ directory created by the pymol installation.<br />
<br />
If you don't have write priviledges in the pymol installation directories you can just copy these files to the working directory from which pymol will be run. <br />
<br />
==Code==<br />
<br />
===slerpy.py===<br />
<br />
:The command definitions for slerpy<br />
<br />
<source lang="python"><br />
################################################################################<br />
#slerpy.py - Command definition routines for slerpy<br />
#Copyright (C) 2006 Joel Bard<br />
#<br />
#This program is free software; you can redistribute it and/or<br />
#modify it under the terms of the GNU General Public License<br />
#as published by the Free Software Foundation; either version 2<br />
#of the License, or (at your option) any later version.<br />
#<br />
#This program is distributed in the hope that it will be useful,<br />
#but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br />
#GNU General Public License for more details.<br />
#<br />
#You should have received a copy of the GNU General Public License<br />
#along with this program; if not, write to the Free Software<br />
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br />
#################################################################################<br />
<br />
from pymol import cmd<br />
import movs<br />
<br />
def readViews( filename ):<br />
#obsolete<br />
vfile = open( filename, 'r')<br />
views = [] #a list of views each of which is a list of 18 numbers<br />
vstrings = vfile.readlines()<br />
for vstring in vstrings:<br />
vals = vstring.split()<br />
view = [float(v) for v in vals]<br />
views.append( view )<br />
vfile.close()<br />
return views<br />
<br />
def readFrames( filename ):<br />
#obsolete<br />
ffile = open( filename, 'r' )<br />
frames = []<br />
fstrings = ffile.readlines()<br />
for fstring in fstrings:<br />
frames.append( int(fstring) )<br />
ffile.close()<br />
return frames<br />
<br />
def readActions( filename ):<br />
#obsolete<br />
#actions are stored in file where<br />
#for each line, the first 4 chars are the view index<br />
#associated with the action and the rest of the<br />
#line is the pymol command to be executed<br />
#upon reading, a dictionary is returned<br />
#with view indices as keys and actions as values<br />
actions = {}<br />
try:<br />
afile = open( filename, 'r' )<br />
except:<br />
print "No actions for this project"<br />
return actions<br />
astrings = afile.readlines()<br />
for astring in astrings:<br />
try:<br />
aindex = int(astring[:4])<br />
action = astring[4:]<br />
actions[ aindex ] = action[:-1]<br />
except:<br />
print "empty line"<br />
afile.close()<br />
return actions<br />
<br />
def readModels( filename ):<br />
#obsolete<br />
models = {}<br />
try:<br />
mfile = open( filename, 'r' )<br />
except:<br />
print "No models for this project"<br />
return models<br />
mstrings = mfile.readlines()<br />
for mstring in mstrings:<br />
try:<br />
mindex = int(mstring[:4])<br />
model = mstring[4:]<br />
models[ mindex ] = model[:-1]<br />
except:<br />
print "empty line"<br />
mfile.close()<br />
return models<br />
<br />
def readSettings( filename ):<br />
#obsolete<br />
settings = {}<br />
try:<br />
sfile = open( filename, 'r' )<br />
except:<br />
print "No settings for this project"<br />
return settings<br />
sstrings = sfile.readlines()<br />
for sstring in sstrings:<br />
try:<br />
sindex = int(sstring[:4])<br />
scommas = sstring[4:]<br />
settingName,selection,startVal,endVal = scommas.split(',')<br />
setting = [settingName,selection,float(startVal),float(endVal)]<br />
settings[sindex] = setting<br />
except:<br />
print "unable to parse setting"<br />
sfile.close()<br />
return settings<br />
<br />
def readScenes( filename ):<br />
#obsolete<br />
global scene_counter<br />
<br />
scene_counter = 0<br />
scenes = {}<br />
try:<br />
sfile = open( filename, 'r' )<br />
except:<br />
print "No scenes file for this project"<br />
return scenes<br />
sstrings = sfile.readlines()<br />
for sstring in sstrings:<br />
try:<br />
sindex = int(sstring[:4])<br />
scene = sstring[4:]<br />
scenes[ sindex ] = scene[:-1]<br />
scene_counter += 1<br />
#print "reading scene", sstring, sindex, scene<br />
except:<br />
print "empty line"<br />
sfile.close()<br />
return scenes<br />
<br />
def read_all( fileroot ):<br />
#obsolete in favor of readKeyViewFile<br />
global views<br />
global frames<br />
global actions<br />
global cur_view<br />
global cur_index<br />
global scenes<br />
global models<br />
global settings<br />
<br />
views = readViews( fileroot+".txt" )<br />
frames = readFrames( fileroot+".frm")<br />
actions = readActions( fileroot+".act")<br />
scenes = readScenes( fileroot+".scn")<br />
models = readModels( fileroot+".mod")<br />
settings = readSettings( fileroot+".set")<br />
cur_view = views[0]<br />
cur_index = 0<br />
show_cur()<br />
<br />
def print_view( view ):<br />
for i in range(0,6):<br />
for j in range(0,3):<br />
print "%12.6f"% view[ 3*i+j ] ,<br />
print<br />
<br />
def show_next():<br />
global cur_index<br />
global cur_view<br />
global views<br />
if cur_index == len( views )-1:<br />
print "No more views."<br />
return<br />
cur_index += 1<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def show_prev():<br />
global cur_index<br />
global cur_view<br />
global views<br />
if cur_index == 0:<br />
print "No more views."<br />
return<br />
cur_index -= 1<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def show_cur():<br />
global cur_index<br />
global cur_view<br />
global views<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def go_to_view( arg=0 ):<br />
global cur_index<br />
global cur_view<br />
global views<br />
n = int( arg )<br />
if n < 0 or n >= len(views):<br />
print "Index out of range."<br />
return<br />
cur_index = n<br />
cur_view = views[n]<br />
cmd.set_view( cur_view )<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ", cur_index<br />
<br />
def insert_current():<br />
#insert the current view into the list after the view<br />
#in views[cur_index]<br />
#set frames to default<br />
global cur_index<br />
global cur_view<br />
global views<br />
global frames<br />
global actions<br />
global scenes<br />
global settings<br />
global models<br />
global fades<br />
<br />
cur_index += 1<br />
cur_view = cmd.get_view()<br />
views.insert( cur_index, [cv for cv in cur_view] )<br />
frames.insert( cur_index, 50 )<br />
<br />
#deal with actions dictionary<br />
actions = incKeyAbove( actions, cur_index )<br />
scenes = incKeyAbove( scenes, cur_index )<br />
settings = incKeyAbove( settings, cur_index )<br />
models = incKeyAbove( models, cur_index )<br />
fades = incKeyAbove( fades, cur_index )<br />
<br />
print "New view:"<br />
print_view( cur_view )<br />
print "Inserted view with index", cur_index, "and a 50 frame transition"<br />
<br />
def append_view():<br />
global views<br />
global frames<br />
global cur_index<br />
global cur_view<br />
<br />
cur_index = len(views)<br />
cur_view = cmd.get_view()<br />
views.append( [cv for cv in cur_view] )<br />
frames.append( 50 )<br />
<br />
print "New view: "<br />
print_view( cur_view )<br />
print "Appended view with index", cur_index, "and a 50 frame transition"<br />
print "The current view is", cur_index<br />
<br />
def incKeyAbove( dict, index ):<br />
tempDict = {}<br />
for key, val in dict.iteritems():<br />
if key >= index:<br />
newkey = key + 1<br />
tempDict[newkey] = val<br />
else:<br />
tempDict[key] = val<br />
return tempDict<br />
<br />
def decKeyAbove( dict, index ):<br />
tempDict = {}<br />
for key, val in dict.iteritems():<br />
if key > index:<br />
newkey = key - 1<br />
tempDict[newkey] = val<br />
else:<br />
tempDict[key] = val<br />
return tempDict<br />
<br />
def delete_current():<br />
#remove the current view from the list<br />
#show the previous view<br />
global cur_index<br />
global cur_view<br />
global views<br />
global actions<br />
global scenes<br />
global settings<br />
global models<br />
global frames<br />
global fades<br />
<br />
del views[cur_index]<br />
del frames[cur_index]<br />
if cur_index in actions:<br />
del actions[cur_index]<br />
if cur_index in scenes:<br />
del scenes[cur_index]<br />
if cur_index in settings:<br />
del settings[cur_index]<br />
<br />
#deal with dictionaries<br />
actions = decKeyAbove( actions, cur_index )<br />
scenes = decKeyAbove( scenes, cur_index )<br />
settings = decKeyAbove( settings, cur_index )<br />
models = decKeyAbove( models, cur_index ) <br />
fades = decKeyAbove( fades, cur_index )<br />
<br />
print "View number",cur_index,"deleted."<br />
if cur_index > 0:<br />
cur_index -= 1<br />
cur_view = views[cur_index]<br />
cmd.set_view( cur_view )<br />
print "Current view is number",cur_index<br />
<br />
def delete_settings():<br />
global settings<br />
global cur_index<br />
del settings[cur_index]<br />
<br />
def replace_current():<br />
global cur_index<br />
global cur_view<br />
global views<br />
cur_view = cmd.get_view()<br />
views[cur_index] = [cv for cv in cur_view]<br />
<br />
def insert_scene():<br />
global views<br />
global actions<br />
global settings<br />
global frames<br />
global cur_index<br />
global cur_view<br />
global scenes<br />
global scene_counter<br />
global models<br />
global fades<br />
<br />
cur_index += 1<br />
cur_view = cmd.get_view()<br />
views.insert( cur_index, [cv for cv in cur_view] )<br />
frames.insert( cur_index, 50 )<br />
<br />
#deal with dictionaries<br />
actions = incKeyAbove( actions, cur_index )<br />
scenes = incKeyAbove( scenes, cur_index )<br />
settings = incKeyAbove( settings, cur_index )<br />
models = incKeyAbove( models, cur_index )<br />
fades = incKeyAbove( fades, cur_index )<br />
<br />
#this stuff has to be done after the above<br />
#find a free scene name<br />
i = 1<br />
while True:<br />
for sname in scenes.values():<br />
print "|"+sname+"|"<br />
if sname == "slerpy_"+str(i):<br />
break<br />
else:<br />
break<br />
i += 1<br />
newname = "slerpy_"+str(i)<br />
<br />
scene_counter += 1<br />
cmd.scene( newname, "store" )<br />
scenes[ cur_index ] = newname<br />
actions[ cur_index ] = "scene "+newname<br />
<br />
print "New view:"<br />
print_view( cur_view )<br />
print "Inserted view with index", cur_index, "and a 50 frame transition"<br />
print "Added scene",newname<br />
<br />
def write_views( filename ):<br />
#deprecated in favor of key files<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
<br />
viewfile = open( filename+".txt", 'w')<br />
for view in views:<br />
for v in view:<br />
viewfile.write( str(v) + " " )<br />
viewfile.write('\n')<br />
viewfile.close()<br />
<br />
framefile = open( filename+".frm", 'w' )<br />
for frame in frames:<br />
framefile.write( str( frame )+'\n' )<br />
framefile.close()<br />
<br />
actionfile = open( filename+".act", 'w' )<br />
for key,action in actions.iteritems():<br />
keystring = str( key )<br />
actionfile.write( keystring.rjust(4)+action + '\n' )<br />
actionfile.close()<br />
<br />
scenefile = open( filename+".scn", 'w' )<br />
for key,scene in scenes.iteritems():<br />
keystring = str( key )<br />
scenefile.write( keystring.rjust(4)+scene + '\n' )<br />
scenefile.close()<br />
<br />
modelfile = open( filename+".mod", 'w' )<br />
for key,model in models.iteritems():<br />
keystring = str( key )<br />
modelfile.write( keystring.rjust(4)+model + '\n' )<br />
modelfile.close()<br />
<br />
settingsfile = open( filename+".set", 'w' )<br />
for key,setting in settings.iteritems():<br />
keystring = str( key )<br />
settingName, selection, startVal, endVal = setting<br />
settingsfile.write( "%s%s,%s,%f,%f\n" % (keystring.rjust(4), settingName, selection, startVal, endVal))<br />
settingsfile.close()<br />
cmd.save( filename+".pse" )<br />
<br />
print "Wrote files", filename+".txt,",filename+".frm,",filename+".pse, and",filename+".act"<br />
<br />
def writeKeyViewFile( filename ):<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
<br />
keyviewfile = open( filename + ".key", 'w' )<br />
for i,view in enumerate(views):<br />
keyviewfile.write( "VIEW: %4d " % i )<br />
for v in view:<br />
keyviewfile.write( str(v) + " " )<br />
keyviewfile.write('\n')<br />
keyviewfile.write( "FRAMES: %d\n" % frames[i] )<br />
if i in actions:<br />
keyviewfile.write( "ACTIONS: %s\n" % actions[i] )<br />
if i in scenes:<br />
keyviewfile.write( "SCENES: %s\n" % scenes[i] )<br />
if i in models:<br />
keyviewfile.write( "MODELS: %s\n" % models[i] )<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
keyviewfile.write( "SETTINGS: %s, %s, %f, %f\n" % (settingName, selection, startVal, endVal))<br />
if i in fades:<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
keyviewfile.write( "FADES: %s, %s, %d\n" % (startVisSelection, endVisSelection, sticksOnly)) <br />
keyviewfile.write("\n")<br />
keyviewfile.close()<br />
cmd.save( filename + ".pse" )<br />
print "Wrote files " , filename + ".key", filename + ".pse"<br />
<br />
def readKeyViewFile( filename ):<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
global scene_counter<br />
<br />
views = []<br />
frames = []<br />
actions = {}<br />
scenes = {}<br />
models = {}<br />
settings = {}<br />
fades = {}<br />
scene_counter = 0<br />
<br />
if filename.endswith(".key"): filename = filename[:-4]<br />
keyviewfile = open( filename + ".key", 'r' )<br />
viewstrings = keyviewfile.readlines()<br />
keyviewfile.close()<br />
viewindex = 0<br />
for line in viewstrings:<br />
if line.startswith("VIEW: "):<br />
viewindex = int( line[6:10] )<br />
vals = line[10:].split()<br />
view = [float(v) for v in vals]<br />
views.append( view )<br />
if line.startswith("FRAMES: "):<br />
frames.append( int( line[8:] ) )<br />
if line.startswith("ACTIONS: "):<br />
actions[ viewindex ] = line[9:-1]<br />
if line.startswith("SCENES: "):<br />
scenes[ viewindex ] = line[8:-1]<br />
scene_counter += 1<br />
if line.startswith("MODELS: "):<br />
models[ viewindex ] = line[8:-1]<br />
if line.startswith("SETTINGS: "):<br />
settingName,selection,startVal,endVal = line[10:-1].split(',')<br />
settings[ viewindex ] = [settingName,selection,float(startVal),float(endVal)]<br />
if line.startswith( "FADES: " ):<br />
startVisSelection, endVisSelection, sticksOnly = line[7:-1].split(',')<br />
fades[ viewindex ] = [startVisSelection, endVisSelection, int(sticksOnly) ]<br />
cur_view = views[0]<br />
cur_index = 0<br />
show_cur()<br />
<br />
def set_frames_current( arg=50 ):<br />
global frames<br />
global cur_index<br />
frames[cur_index] = int(arg)<br />
<br />
def list_frames():<br />
global frames<br />
global views<br />
global actions<br />
global models<br />
global settings<br />
<br />
f=0<br />
for i,view in enumerate(views[:-1]):<br />
if i in actions:<br />
a = actions[i]<br />
else:<br />
a = ""<br />
if i in models:<br />
m = "States: " + models[i]<br />
else:<br />
m = ""<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
s = "Settings: %s %s %f %f" % (settingName, selection, startVal, endVal)<br />
else:<br />
s = ""<br />
print "View",i,"to",i+1,"Frames ",f,"to",f+frames[i],a,m,s<br />
f += frames[i]<br />
<br />
def add_action_current( cmd ):<br />
global cur_index<br />
global actions<br />
actions[cur_index] = cmd[1:-1] #strip off quotes<br />
<br />
def append_action_current( cmd ):<br />
global cur_index<br />
global actions<br />
actions[cur_index] += ";" + cmd[1:-1]<br />
<br />
def clear_action_current():<br />
global actions<br />
global cur_index<br />
del actions[cur_index]<br />
<br />
def list_actions():<br />
global actions<br />
for i,a in actions.iteritems():<br />
print i,a<br />
<br />
def morph_models( start_model, end_model ):<br />
global cur_index<br />
global frames<br />
global models<br />
models[cur_index] = "%s -%s" % (start_model, end_model)<br />
frames[cur_index] = abs(int(end_model) - int(start_model)) + 1<br />
<br />
def interpolate_settings( setting, selection, startval, endval ):<br />
global cur_index<br />
global settings<br />
settingEntry = [setting, selection, float(startval), float(endval)]<br />
settings[cur_index] = settingEntry <br />
<br />
def crossfade( startVisSelection, endVisSelection, sticksOnly = 1 ):<br />
#cross fade the specified objects, vary stick transparency only if stickOnly=1<br />
global cur_index<br />
global fades<br />
fades[cur_index] = [startVisSelection, endVisSelection, int(sticksOnly) ]<br />
<br />
def setup_view( index ):<br />
for i in range( int(index)+1 ):<br />
if i in actions:<br />
print "Executing %s from actions %d" % (actions[i],i)<br />
cmd.do( actions[i] )<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
action = "set %s, %f, %s;" % (settingName, endVal, selection)<br />
print "Executing %s from settings %d" % (action,i)<br />
cmd.do( action )<br />
if i in fades:<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
action = "set stick_transparency, 0, %s; set stick_transparency, 1, %s;" % (endVisSelection, startVisSelection)<br />
print "Executing %s from fades %d" % (action, i)<br />
cmd.do( action )<br />
<br />
def show_transition(start_index=0, end_index=0):<br />
#show the transition from the current view to the next view<br />
global frames<br />
global views<br />
global cur_index<br />
global actions<br />
global models<br />
if start_index == 0 and end_index == 0:<br />
if cur_index >= len(views)-1:<br />
print "Current view is last in sequence."<br />
return<br />
start_index=cur_index<br />
end_index=cur_index+1<br />
else:<br />
start_index = int(start_index)<br />
end_index = int(end_index)<br />
ftot = 0<br />
setcommand = ""<br />
i = start_index<br />
for nframes in frames[start_index:end_index]:<br />
#ftot += nframes<br />
if i in models:<br />
setcommand += " " + models[i] + " "<br />
else:<br />
setcommand += " 1 x%i" % nframes<br />
i += 1<br />
<br />
# cmd.mset("1 x%i" % ftot)<br />
cmd.mset( setcommand )<br />
start_frame = 1<br />
#first do all actions that happen up to this point to make sure<br />
#things look the way they should<br />
first_action = ""<br />
for i in range( start_index ):<br />
if i in actions:<br />
first_action += actions[i] + ';'<br />
#print "Executing %s from actions %d" % (actions[i],i)<br />
#cmd.do( actions[i] )<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
action = "set %s, %f, %s;" % (settingName, endVal, selection)<br />
first_action += action<br />
#print "Executing %s from settings %d" % (action,i)<br />
#cmd.do( action )<br />
if i in fades:<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
action = "set stick_transparency, 0, %s; set stick_transparency, 1, %s;" % (endVisSelection, startVisSelection)<br />
first_action += action<br />
#print "Executing %s from fades %d" % (action, i)<br />
#cmd.do( action )<br />
for i in range( start_index, end_index ):<br />
if i in settings:<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame, settings[i] )<br />
elif i in fades:<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame, fades[i] )<br />
else:<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame )<br />
#add an action<br />
if start_frame == 1:<br />
mdo_cmd = first_action<br />
if i in actions:<br />
mdo_cmd += actions[i]+";"<br />
#mdo_cmd += "set_view("+str(views[i])+")"<br />
print mdo_cmd<br />
cmd.mdo(start_frame, mdo_cmd)<br />
elif i in actions:<br />
mdo_cmd = actions[i]+";set_view("+str(views[i])+")"<br />
cmd.mdo(start_frame, mdo_cmd)<br />
#print mdo_cmd<br />
start_frame += frames[i]<br />
cmd.frame(1)<br />
cmd.mplay()<br />
<br />
def make_all():<br />
#make the whole movie<br />
global views<br />
global frames<br />
global models<br />
<br />
#first get total number of frames<br />
ftot = 0<br />
setcommand = ""<br />
for i,nframes in enumerate(frames[:-1]):<br />
ftot += nframes<br />
if i in models:<br />
setcommand += " " + models[i] + " "<br />
else:<br />
setcommand += " 1 x%i" % nframes<br />
<br />
#initialize movie<br />
#cmd.mset("1 x%i" % ftot)<br />
#cmd.mset("1 x50 1 -30 30 x20")<br />
cmd.mset( setcommand )<br />
<br />
#loop through views<br />
start_view = views[0][:]<br />
first_frame = 1<br />
for i,view in enumerate(views[1:]):<br />
end_view = view[:]<br />
if i in settings:<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame, settings[i] )<br />
elif i in fades:<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame, fades[i] )<br />
else:<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame )<br />
#add an action<br />
if i in actions:<br />
mdo_cmd = actions[i]#+";set_view ("+str( views[i] )+")"<br />
print mdo_cmd<br />
cmd.mdo(first_frame, mdo_cmd)<br />
first_frame += frames[i]<br />
start_view = end_view[:]<br />
cmd.frame(1)<br />
<br />
## views = readViews( "viewfile.txt" )<br />
## frames = readFrames( "viewfile.frm" )<br />
## actions = readActions( "viewfile.act" )<br />
##print "Length ",len(views)<br />
#for v in views:<br />
# print v<br />
#cur_view = views[0]<br />
views = []<br />
frames = []<br />
models = {}<br />
actions = {}<br />
scenes = {}<br />
settings = {}<br />
fades = {}<br />
scene_counter = 0<br />
cur_index = -1<br />
cmd.set( "scene_animation_duration","0" )<br />
#cmd.set_view( cur_view )<br />
<br />
cmd.extend("sn", show_next )<br />
cmd.extend("sp", show_prev )<br />
cmd.extend("sc", show_cur )<br />
cmd.extend("sinsert", insert_current )<br />
cmd.extend("sdelete", delete_current )<br />
cmd.extend("sreplace", replace_current )<br />
cmd.extend("sappend", append_view )<br />
cmd.extend("sscene", insert_scene )<br />
cmd.extend("sgo", go_to_view )<br />
cmd.extend("sreadold", read_all )<br />
cmd.extend("swriteold", write_views )<br />
cmd.extend("slist", list_frames )<br />
cmd.extend("ssetf", set_frames_current )<br />
cmd.extend("sshow", show_transition )<br />
cmd.extend("srecord", make_all )<br />
cmd.extend("saction", add_action_current )<br />
cmd.extend("sdelaction", clear_action_current )<br />
cmd.extend("sdumpactions", list_actions )<br />
cmd.extend("sappendaction", append_action_current )<br />
cmd.extend("smorph", morph_models )<br />
cmd.extend("sinterpsetting", interpolate_settings )<br />
cmd.extend("sdeletesetting", delete_settings )<br />
cmd.extend("scrossfade", crossfade )<br />
cmd.extend("swrite", writeKeyViewFile )<br />
cmd.extend("sread", readKeyViewFile )<br />
cmd.extend("ssetupview", setup_view )<br />
</source><br />
<br />
===movs.py===<br />
<br />
:Math and animation routines for slerpy<br />
<br />
<source lang="python"><br />
##################################################################################<br />
#movs.py - Math and animation routines for slerpy<br />
#Copyright (C) 2006 Joel Bard<br />
#<br />
#This program is free software; you can redistribute it and/or<br />
#modify it under the terms of the GNU General Public License<br />
#as published by the Free Software Foundation; either version 2<br />
#of the License, or (at your option) any later version.<br />
#<br />
#This program is distributed in the hope that it will be useful,<br />
#but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br />
#GNU General Public License for more details.<br />
#<br />
#You should have received a copy of the GNU General Public License<br />
#along with this program; if not, write to the Free Software<br />
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br />
#################################################################################<br />
<br />
from pymol import cmd,stored<br />
from math import *<br />
<br />
def rmat2quat( M ):<br />
#M is a list of 9 values being the elements of the rotation matrix in row order<br />
T = M[0] + M[4] + M[8] + 1<br />
print "Trace ",T<br />
if T>0:<br />
S = 0.5 / sqrt(T)<br />
W = 0.25/S<br />
X = (M[7] - M[5])*S<br />
Y = (M[2] - M[6])*S<br />
Z = (M[3] - M[1])*S<br />
elif M[0] > M[4] and M[0] > M[8]:<br />
S = sqrt( 1.0 + M[0] - M[4] - M[8]) * 2<br />
X = 0.25 * S<br />
Y = (M[1] + M[3])/S<br />
Z = (M[2] + M[6])/S<br />
W = (M[5] - M[7])/S<br />
elif M[4] > M[8]:<br />
S = sqrt( 1.0 + M[4] - M[0] - M[8] ) * 2<br />
X = (M[1] + M[3])/S<br />
Y = 0.25 * S<br />
Z = (M[5] + M[7])/S<br />
W = (M[2] - M[6])/S<br />
else:<br />
S = sqrt( 1.0 + M[8] - M[0] - M[4]) * 2<br />
X = (M[2] + M[6])/S<br />
Y = (M[5] + M[7])/S<br />
Z = 0.25 * S<br />
W = (M[1] - M[3])/S<br />
return [X,Y,Z,W]<br />
<br />
def quat2rmat( Q ):<br />
#Q is a list of 4 values being the quaternion X Y Z W<br />
X=Q[0]<br />
Y=Q[1]<br />
Z=Q[2]<br />
W=Q[3]<br />
xx = X*X<br />
xy = X*Y<br />
xz = X*Z<br />
xw = X*W<br />
yy = Y*Y<br />
yz = Y*Z<br />
yw = Y*W<br />
zz = Z*Z<br />
zw = Z*W<br />
<br />
M= [1.0]*9<br />
M[0] = 1 - 2 * ( yy + zz )<br />
M[1] = 2 * ( xy - zw )<br />
M[2] = 2 * ( xz + yw )<br />
M[3] = 2 * ( xy + zw )<br />
M[4] = 1 - 2 * ( xx + zz )<br />
M[5] = 2 * ( yz - xw )<br />
M[6] = 2 * ( xz - yw )<br />
M[7] = 2 * ( yz + xw )<br />
M[8] = 1 - 2 * ( xx + yy )<br />
return M<br />
<br />
def quatconj( Q ):<br />
return [-Q[0],-Q[1],-Q[2],Q[3]]<br />
<br />
def quatmag( Q ):<br />
s = 0.0<br />
QC = quatconj(Q)<br />
for x in range(4):<br />
s += Q[x]*Q[x]<br />
print s<br />
return sqrt(s)<br />
<br />
def quatnorm( Q ):<br />
m = quatmag( Q )<br />
return [q/m for q in Q]<br />
<br />
def quatdotprod( q1, q2 ):<br />
dp = 0<br />
for i in range(4):<br />
dp += q1[i]*q2[i]<br />
return dp<br />
<br />
def vectnorm( V ):<br />
mag = 0.0<br />
for x in V:<br />
mag += x*x<br />
mag = sqrt(mag)<br />
return [x/mag for x in V]<br />
<br />
def quat2axisangle( Q ):<br />
#returns list where 0..2 are rot axis and 3 is angle<br />
qn = quatnorm( Q )<br />
cos_a = Q[3]<br />
angle = acos( cos_a ) * 2<br />
sin_a = sqrt( 1.0 - cos_a * cos_a )<br />
if fabs( sin_a ) < 0.000005:<br />
sin_a = 1<br />
ax_an = [ q/sin_a for q in Q[0:3] ]<br />
ax_an.append( angle )<br />
return ax_an<br />
<br />
def axisangle2quat( ax_an ):<br />
#ax_an is a list with axis coordinates followed by rotation angle<br />
axn = vectnorm( ax_an[:3] )<br />
angle = ax_an[3]<br />
sin_a = sin( angle / 2 )<br />
cos_a = cos( angle / 2 )<br />
Q = [ x * sin_a for x in axn ]<br />
Q.append( cos_a )<br />
return Q<br />
<br />
def rmat2axisangle( M ):<br />
q = rmat2quat( M )<br />
return quat2axisangle( q )<br />
<br />
def axisangle2rmat( a ):<br />
q = axisangle2quat( a )<br />
return quat2rmat( q )<br />
<br />
def animate_transition( start_view, end_view, nframes, first_frame, settings = [] ):<br />
#print "Views"<br />
#print start_view,'\n',end_view<br />
<br />
cview = start_view[:]<br />
cmd.set_view( start_view )<br />
<br />
#get initial and final quaternions for interpolation<br />
#print start_view[0:9]<br />
#get quaternions<br />
qstart = rmat2quat( start_view[0:9] )<br />
qend = rmat2quat( end_view[0:9] )<br />
<br />
#test for long way vs. short way<br />
if quatdotprod( qstart,qend ) < 0:<br />
qstart = [-q for q in qstart]<br />
<br />
axan_start = quat2axisangle( qstart )<br />
axan_end = quat2axisangle( qend )<br />
<br />
axan_cur = axan_start[:]<br />
frame_start = first_frame<br />
frame_end = frame_start + nframes<br />
doFade = 0<br />
doSetting = 0<br />
if len( settings ) == 4:<br />
settingName, selection, startVal, endVal = settings<br />
settingStep = (endVal-startVal)/float(nframes)<br />
print "Setting step ", settingStep<br />
doSetting = 1<br />
elif len( settings ) == 3:<br />
startVisSelection, endVisSelection, sticksOnly = settings<br />
settingStep = 1.0/float(nframes)<br />
doFade = 1<br />
for f in range( frame_start , frame_end):<br />
#get rotmat<br />
#using angle axis<br />
<br />
for i in range(4):<br />
axan_cur[i] = axan_cur[i] + (axan_end[i]-axan_start[i])/nframes<br />
newmat = axisangle2rmat( axan_cur )<br />
#print cview<br />
for i in range(9):<br />
cview[i] = newmat[i]<br />
<br />
mdo_cmd = "set_view (["<br />
for i in range(18):<br />
if i>8:<br />
cview[i] = cview[i]+(end_view[i]-start_view[i])/nframes<br />
mdo_cmd += "%12.7f,"% cview[i]<br />
mdo_cmd = mdo_cmd[:-1]+"])"<br />
if doSetting: <br />
val = float(f-frame_start)*settingStep + startVal <br />
print val;<br />
mdo_cmd += "; set %s, %f, %s" % (settingName, val, selection)<br />
print mdo_cmd;<br />
#print "mdo ", mdo_cmd<br />
if doFade:<br />
val = float(f-frame_start)*settingStep<br />
otherVal = 1.0 - val<br />
mdo_cmd += "; set stick_transparency, %f, %s; set stick_transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
if not sticksOnly:<br />
#comment out surface transparency interpolation due to problem with transparent sticks in front of <br />
#transparent surfaces (get black holes)<br />
# mdo_cmd += "; set transparency, %f, %s; set transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
mdo_cmd += "; set cartoon_transparency, %f, %s; set cartoon_transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
cmd.mdo(f,mdo_cmd)<br />
<br />
</source><br />
[[Category:Script_Library|Slerpy]]<br />
[[Category:Math_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Colorama&diff=8079Colorama2010-02-26T20:52:48Z<p>Newacct: </p>
<hr />
<div>=COLORAMA=<br />
<br />
COLORAMA is a PyMOL plugin which allows to color objects using adjustable scale bars. <br />
<br />
==Program features==<br />
In RGB mode, each color R, G, B is represented by one scale bar which can be manually adjusted while the selected object is colored in real time. For convenience, it is as well possible to switch to the HSV color system.<br />
<br />
Additionally, a color gradient with user-defined start- and end-colors can be created for the selected molecule.<br />
<br />
==Screenshot==<br />
[[Image:COLORAMA-screenshot.jpg]]<br />
<br />
==Usage==<br />
<br />
Install the program by copying the code below into an empty text file (e.g. "colorama.py") located in the \Pymol\modules\pmg_tk\startup directory. After PyMOL has been started, the program can be launched from the PLUGINS menu. COLORAMA has not been tested with PyMOL versions older than 1.0.<br />
<br />
===Single color===<br />
<br />
#Type the name of a PyMOL object to be colored into the COLORAMA entry field.<br />
#Push the "Set" button.<br />
#The scales are adjusted to the current color which is additionally visualized in a field left to the scales.<br />
#If one of the scales is moved, the color of the selected object will change in real-time.<br />
#Pushing the RGB or HSV buttons on the left allows to switch between both color systems.<br />
<br />
===Color gradients===<br />
<br />
#After an object has been selected, push the "G" button (gradient).<br />
#Select the start color by pushing "C1" and adjusting it using the scales.<br />
#Select the end color "C2" in the same way.<br />
#To create the gradient, push "Set gradient".<br />
<br />
A new object will be created which is called "dummy-OLD_OBJECT". The B-factor column of this object is overwritten and now contains the number of each residue. The original object is left unchanged. The gradient mode can be left by pushing "M" (monochrome).<br />
This part of the program uses a modified version of the [http://pldserver1.biochem.queensu.ca/~rlc/work/pymol/ color_b script] by Robert L. Campbell & James Stroud.<br />
<br />
==Contact==<br />
Gregor Hagelueken,<br />
gh50@st-andrews.ac.uk<br />
<br />
==Code==<br />
<source lang="python"><br />
"""<br />
--- COLORAMA: Coloring Widget for PyMOL --- <br />
Author : Gregor Hagelueken<br />
Program : Color_select<br />
Date : Oct 2007<br />
Version : 0.1.1<br />
Mail : gha@helmholtz-hzi.de<br />
<br />
<br />
<br />
COLORAMA is a plugin for the PyMOL Molecular Graphics System. <br />
It allows to color molecules using RGB or HSV colors which can be manually adjusted. <br />
Alternatively, a user defined color gradient can be applied to the molecule.<br />
The program works properly with PyMOL versions >=1.0.<br />
<br />
<br />
The program uses a modified version of the color_b program by Robert L. Campbell & James Stroud<br />
for the gradient calculation and the RGBToHTMLColor function by Paul Winkler.<br />
<br />
Literature:<br />
DeLano, W.L. The PyMOL Molecular Graphics System (2002) DeLano Scientific, San Carlos, CA, USA. http://www.pymol.org<br />
<br />
----------------------------------------------------------------------<br />
----------------------------------------------------------------------<br />
<br />
"""<br />
<br />
import colorsys,sys<br />
from pymol import cmd,stored<br />
from Tkinter import *<br />
class Colorama:<br />
def __init__ (self,master):<br />
#create frames<br />
self.F1 = Frame(roota, padx=5, pady=5, bg='red')<br />
self.F2 = Frame(roota, padx=5, pady=5, bg='green')<br />
self.F3 = Frame(roota, padx=5, pady=5, bg='blue')<br />
self.F4 = Frame(self.F1, padx=5, pady=5, bg='yellow')<br />
self.F5 = Frame(self.F1, padx=5, pady=5, bg='white')<br />
self.F6 = Frame(self.F1, padx=5, pady=5, bg='pink')<br />
<br />
#color system radiobuttons<br />
self.Radiocolorsystem = IntVar()<br />
self.RGB = Radiobutton (self.F3, text='RGB', indicatoron=0, variable=self.Radiocolorsystem, value=1, command=self.Scalergb)<br />
self.HSV = Radiobutton (self.F3, text='HSV', indicatoron=0, variable=self.Radiocolorsystem, value=2, command=self.Scalehsv)<br />
<br />
#mono/gradient and Farbe1/Farbe2 radiobuttons<br />
self.RadioMonoGradient = IntVar()<br />
self.RadioFarbe12 = IntVar()<br />
self.Monobutton = Radiobutton (self.F3, text='M', indicatoron=0, variable=self.RadioMonoGradient, value=1, command=self.Mono)<br />
self.Gradbutton = Radiobutton (self.F3, text='G', indicatoron=0, variable=self.RadioMonoGradient, value=2, command=self.Grad)<br />
self.Farbe1button = Radiobutton (self.F3, text='C1', indicatoron=0, variable=self.RadioFarbe12, value=1, command=self.Farbe1) <br />
self.Farbe2button = Radiobutton (self.F3, text='C2', indicatoron=0, variable=self.RadioFarbe12, value=2, command=self.Farbe2) <br />
<br />
#preselect RGB and mono<br />
self.RGB.select()<br />
self.Monobutton.select()<br />
self.Farbe1button.select()<br />
self.monograd='mono'<br />
self.colorsystem='rgb'<br />
self.farbe12='farbe1'<br />
<br />
#initialize the scales<br />
self.Scales()<br />
<br />
#other GUI elements<br />
self.selectionentry = Entry(master=self.F5, font=('Arial', 10))<br />
self.selectionentry.insert(0,"")<br />
self.selectionbutton = Button(master=self.F5, text='Set', command=self.setselection)<br />
self.setgradientbutton = Button(master=self.F5, text='Set Gradient', command=self.setgradient)<br />
self.label = Label(master=self.F4, text="None", font=('Arial', 10))<br />
self.selectionlabel = Label(master=self.F4, text="Active:", font=('Arial', 10))<br />
self.inputlabel = Label (master=self.F5, text="Object:", font=('Arial', 10))<br />
self.colorfield1 = Label(master=self.F3,width=3, height=10)<br />
self.colorfield2 = Label(master=self.F3,width=3, height=10)<br />
<br />
self.selection=""<br />
self.setselection()<br />
<br />
#start layout procedure<br />
self.layout()<br />
<br />
def layout(self):<br />
self.F1.pack(side=TOP, anchor=NW)<br />
self.F4.pack(side=BOTTOM, fill=X, anchor=W)<br />
self.F5.pack(side=TOP)<br />
self.F2.pack(side=RIGHT, fill=Y)<br />
self.F3.pack(side=LEFT, fill=X)<br />
<br />
#entry and buttons<br />
self.setgradientbutton.pack(side=RIGHT,fill=X, anchor=NE)<br />
self.selectionbutton.pack(side=RIGHT, anchor=N)<br />
self.selectionentry.pack(side=RIGHT,fill=X, anchor=NE)<br />
<br />
#labels<br />
self.inputlabel.pack(side=TOP, anchor=NW)<br />
self.selectionlabel.pack(side=LEFT, anchor=W)<br />
self.label.pack(side=LEFT)<br />
<br />
#colorfields<br />
self.colorfield2.pack(side=RIGHT)<br />
self.colorfield1.pack(side=RIGHT)<br />
<br />
#scales<br />
self.ScaleRed.pack(side=RIGHT, fill=Y)<br />
self.ScaleGreen.pack(side=RIGHT, fill=Y)<br />
self.ScaleBlue.pack(side=RIGHT, fill=Y)<br />
<br />
#radiobuttons<br />
self.RGB.pack(side=TOP, fill=X)<br />
self.HSV.pack(side=TOP, fill=X)<br />
self.Monobutton.pack(side=TOP, fill=X)<br />
self.Gradbutton.pack(side=TOP, fill=X)<br />
self.Farbe1button.pack(side=TOP, fill=X)<br />
self.Farbe2button.pack(side=TOP, fill=X)<br />
<br />
def Scales(self):<br />
self.ScaleRed = Scale(master=self.F2, label='R', length='3c',<br />
from_=0, to=255,<br />
#set(startred),<br />
command=self.setzeFarbe)<br />
self.ScaleGreen = Scale(master=self.F2, label='G', length='3c',<br />
from_=0, to=255,<br />
#set(startgreen),<br />
command=self.setzeFarbe)<br />
self.ScaleBlue = Scale(master=self.F2, label='B', length='3c',<br />
from_=0, to=255,<br />
#set(startblue),<br />
command=self.setzeFarbe)<br />
<br />
def Scalergb(self):<br />
if self.colorsystem=='hsv':<br />
h=float(self.ScaleRed.get())<br />
s=float(self.ScaleGreen.get())<br />
v=float(self.ScaleBlue.get())<br />
rgbcolor = colorsys.hsv_to_rgb(h,s,v)<br />
r=255*rgbcolor[0]<br />
g=255*rgbcolor[1]<br />
b=255*rgbcolor[2]<br />
self.ScaleRed.config(label='R', from_=0, to=255, resolution=1)<br />
self.ScaleGreen.config(label='G', from_=0, to=255, resolution=1)<br />
self.ScaleBlue.config(label='B', from_=0, to=255, resolution=1)<br />
self.ScaleRed.set(r)<br />
self.ScaleGreen.set(g)<br />
self.ScaleBlue.set(b)<br />
self.colorsystem='rgb'<br />
<br />
def Scalehsv(self):<br />
if self.colorsystem=='rgb':<br />
r=float(self.ScaleRed.get())/255<br />
g=float(self.ScaleGreen.get())/255<br />
b=float(self.ScaleBlue.get())/255<br />
hsvcolor = colorsys.rgb_to_hsv(r,g,b)<br />
h=hsvcolor[0]<br />
s=hsvcolor[1]<br />
v=hsvcolor[2]<br />
self.ScaleRed.config(label='H', from_=0, to=1, resolution=0.01)<br />
self.ScaleGreen.config(label='S', from_=0, to=1, resolution=0.01)<br />
self.ScaleBlue.config(label='V', from_=0, to=1, resolution=0.01)<br />
self.ScaleRed.set(h)<br />
self.ScaleGreen.set(s)<br />
self.ScaleBlue.set(v)<br />
self.colorsystem='hsv'<br />
<br />
def Mono(self):<br />
self.monograd='mono'<br />
<br />
def Grad(self):<br />
self.monograd='grad'<br />
<br />
def Farbe1(self):<br />
#Let the scales know which color is to be changed<br />
self.farbe12='farbe1'<br />
#set scales to farbe1<br />
if self.monograd=='grad':<br />
if self.colorsystem=='rgb':<br />
startred=self.farbe1[0]<br />
startgreen=self.farbe1[1]<br />
startblue=self.farbe1[2] <br />
self.ScaleRed.set(startred)<br />
self.ScaleGreen.set(startgreen)<br />
self.ScaleBlue.set(startblue)<br />
elif self.colorsystem=='hsv':<br />
hsvcolor=colorsys.rgb_to_hsv(self.farbe1[0], self.farbe1[1], self.farbe1[2])<br />
h=hsvcolor[0]<br />
s=hsvcolor[1]<br />
v=hsvcolor[2]<br />
self.ScaleRed.set(h)<br />
self.ScaleGreen.set(s)<br />
self.ScaleBlue.set(v)<br />
<br />
def Farbe2(self):<br />
#Let the scales know which color is to be changed<br />
self.farbe12='farbe2'<br />
#set scales to farbe1<br />
if self.monograd=='grad':<br />
if self.colorsystem=='rgb':<br />
startred=self.farbe2[0]<br />
startgreen=self.farbe2[1]<br />
startblue=self.farbe2[2] <br />
self.ScaleRed.set(startred)<br />
self.ScaleGreen.set(startgreen)<br />
self.ScaleBlue.set(startblue)<br />
elif self.colorsystem=='hsv':<br />
hsvcolor=colorsys.rgb_to_hsv(self.farbe2[0], self.farbe2[1], self.farbe2[2])<br />
h=hsvcolor[0]<br />
s=hsvcolor[1]<br />
v=hsvcolor[2]<br />
self.ScaleRed.set(h)<br />
self.ScaleGreen.set(s)<br />
self.ScaleBlue.set(v)<br />
<br />
def setselection(self):<br />
if self.selectionentry.get() != "":<br />
self.selection=self.selectionentry.get()<br />
<br />
#Color of each residue is stored in stored.colorlist to check if the molecule has a colorgradient<br />
stored.colorlist = []<br />
cmd.iterate (self.selection+" & name CA", "stored.colorlist.append(int(color))")<br />
<br />
if len(stored.colorlist)==0:<br />
#for other objects (e.g. density...)<br />
stored.colorlist.append(cmd.get_object_color_index(self.selection))<br />
stored.colorlist.append(cmd.get_object_color_index(self.selection))<br />
<br />
<br />
initialcolornterm=cmd.get_color_tuple(stored.colorlist[0])<br />
initialcolorcterm=cmd.get_color_tuple(stored.colorlist[len(stored.colorlist)-1])<br />
self.farbe1=initialcolornterm[0]*255, initialcolornterm[1]*255, initialcolornterm[2]*255<br />
self.farbe2=initialcolorcterm[0]*255, initialcolorcterm[1]*255, initialcolorcterm[2]*255<br />
<br />
#Set active object to label<br />
self.label.config(text=self.selection)<br />
<br />
#check if there is a gradient and adjust Mono/Gradbutton<br />
if initialcolornterm==initialcolorcterm:<br />
self.Monobutton.select()<br />
self.Mono()<br />
<br />
elif initialcolornterm!=initialcolorcterm:<br />
self.Gradbutton.select()<br />
self.Grad()<br />
<br />
#adjust colorfields<br />
self.colorfield1.config(bg=self.RGBToHTMLColor(self.farbe1))<br />
self.colorfield2.config(bg=self.RGBToHTMLColor(self.farbe2))<br />
self.Farbe1button.select()<br />
self.Farbe1()<br />
<br />
#Set scales to initialcolor of the new object <br />
if self.colorsystem=='rgb':<br />
startred=255*initialcolornterm[0]<br />
startgreen=255*initialcolornterm[1]<br />
startblue=255*initialcolornterm[2] <br />
self.ScaleRed.set(startred)<br />
self.ScaleGreen.set(startgreen)<br />
self.ScaleBlue.set(startblue)<br />
elif self.colorsystem=='hsv':<br />
hsvcolor=colorsys.rgb_to_hsv(initialcolornterm[0], initialcolornterm[1], initialcolornterm[2])<br />
h=hsvcolor[0]<br />
s=hsvcolor[1]<br />
v=hsvcolor[2]<br />
self.ScaleRed.set(h)<br />
self.ScaleGreen.set(s)<br />
self.ScaleBlue.set(v)<br />
<br />
def setzeFarbe(self, event):<br />
if self.selection != "" && self.monograd == 'mono':<br />
if self.colorsystem=='rgb':<br />
col=[]<br />
#read RGB values from scales<br />
r=int(self.ScaleRed.get())<br />
g=int(self.ScaleGreen.get())<br />
b=int(self.ScaleBlue.get())<br />
rgbcolor=r,g,b<br />
#Prepare a rgb tupel<br />
col.append(rgbcolor)<br />
#hexcolor for colorfields<br />
hexcolor=self.RGBToHTMLColor(rgbcolor)<br />
self.colorfield1.config(bg=hexcolor)<br />
self.colorfield2.config(bg=hexcolor)<br />
cmd.delete(self.selection+"_color")<br />
cmd.set_color(self.selection+"_color", col[0])<br />
cmd.color(self.selection+"_color", self.selection)<br />
del col[0]<br />
elif self.colorsystem=='hsv':<br />
col=[]<br />
#read HSV values from scales<br />
h=float(self.ScaleRed.get())<br />
s=float(self.ScaleGreen.get())<br />
v=float(self.ScaleBlue.get())<br />
<br />
#HSV to RGB and change from 1.0, 1.0, 1.0 format to 255,255,255 format<br />
rgbcolor = colorsys.hsv_to_rgb(h,s,v)<br />
r = 255*rgbcolor[0]<br />
g = 255*rgbcolor[1]<br />
b = 255*rgbcolor[2]<br />
#as above<br />
rgbcolor = r,g,b<br />
col.append(rgbcolor)<br />
#hexcolor for colorfields<br />
hexcolor=self.RGBToHTMLColor(rgbcolor)<br />
self.colorfield1.config(bg=hexcolor)<br />
self.colorfield2.config(bg=hexcolor)<br />
cmd.delete(self.selection+"_color")<br />
cmd.set_color(self.selection+"_color", col[0])<br />
cmd.color(self.selection+"_color", self.selection)<br />
del col[0]<br />
elif self.selection !="" && self.monograd == 'grad':<br />
<br />
if self.colorsystem=='rgb':<br />
col=[]<br />
#read RGB values from scales<br />
r=int(self.ScaleRed.get())<br />
g=int(self.ScaleGreen.get())<br />
b=int(self.ScaleBlue.get())<br />
rgbcolor=r,g,b<br />
#Prepare a rgb tupel<br />
col.append(rgbcolor)<br />
#hexcolor for colorfields<br />
hexcolor=self.RGBToHTMLColor(rgbcolor)<br />
if self.farbe12=='farbe1':<br />
self.colorfield1.config(bg=hexcolor)<br />
self.farbe1=rgbcolor<br />
elif self.farbe12=='farbe2':<br />
self.colorfield2.config(bg=hexcolor)<br />
self.farbe2=rgbcolor<br />
<br />
elif self.colorsystem=='hsv':<br />
col=[]<br />
#read HSV values from scales<br />
h=float(self.ScaleRed.get())<br />
s=float(self.ScaleGreen.get())<br />
v=float(self.ScaleBlue.get())<br />
<br />
#HSV to RGB and change from 1.0, 1.0, 1.0 format to 255,255,255 format<br />
rgbcolor = colorsys.hsv_to_rgb(h,s,v)<br />
r = 255*rgbcolor[0]<br />
g = 255*rgbcolor[1]<br />
b = 255*rgbcolor[2]<br />
#as above<br />
rgbcolor = r,g,b<br />
col.append(rgbcolor)<br />
#hexcolor for colorfields<br />
hexcolor=self.RGBToHTMLColor(rgbcolor)<br />
<br />
if self.farbe12=='farbe1':<br />
self.colorfield1.config(bg=hexcolor)<br />
self.farbe1=rgbcolor<br />
elif self.farbe12=='farbe2':<br />
self.colorfield2.config(bg=hexcolor)<br />
self.farbe2=rgbcolor<br />
<br />
def setgradient(self):<br />
<br />
stored.residuelist = []<br />
cmd.iterate (self.selection, "stored.residuelist.append(int(resi))")<br />
firstresidue=min(stored.residuelist)<br />
lastresidue=max(stored.residuelist)<br />
rs=float(self.farbe1[0])/float(255)<br />
gs=float(self.farbe1[1])/float(255)<br />
bs=float(self.farbe1[2])/float(255)<br />
re=float(self.farbe2[0])/float(255)<br />
ge=float(self.farbe2[1])/float(255)<br />
be=float(self.farbe2[2])/float(255)<br />
hsvcolorstart = colorsys.rgb_to_hsv(rs, gs, bs)<br />
hs=hsvcolorstart[0]<br />
ss=hsvcolorstart[1]<br />
vs=hsvcolorstart[2]<br />
hsvcolorend = colorsys.rgb_to_hsv(re, ge, be)<br />
he=hsvcolorend[0]<br />
se=hsvcolorend[1]<br />
ve=hsvcolorend[2]<br />
color_grad(selection=self.selection, minimum=firstresidue, maximum=lastresidue, hs=hs, he=he,ss=ss,se=se,vs=vs,ve=ve)<br />
<br />
<br />
def RGBToHTMLColor(self, rgb_tuple):<br />
#by Paul Winkler<br />
""" convert an (R, G, B) tuple to #RRGGBB """<br />
hexcolor = '#%02x%02x%02x' % rgb_tuple<br />
# that's it! '%02x' means zero-padded, 2-digit hex values<br />
return hexcolor<br />
<br />
def __init__(self):<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Colorama',<br />
label = 'Colorama',<br />
command = lambda s=self : open_Colorama())<br />
<br />
def open_Colorama():<br />
#initialize window (roota)<br />
global roota<br />
roota = Tk()<br />
roota.title(' COLORAMA by gha')<br />
global colorama<br />
colorama = Colorama(roota)<br />
<br />
def color_grad(selection='',item='b',mode='hist',gradient='bgr',nbins=11,sat=1,value=1,minimum='1',maximum='1',dummy='dummy_all', hs=1, he=1, ss=1,se=1,vs=1,ve=1, colorname='init'):<br />
"""<br />
--- color_grad: color gradient tool for PyMOL --- <br />
Author : Gregor Hagelueken<br />
Program : Color_grad<br />
Date : Oct 2007<br />
Version : 0.1.0<br />
Mail : gha@helmholtz-hzi.de<br />
<br />
<br />
<br />
<br />
This is a modified version of the color_b program by Robert L. Campbell & James Stroud<br />
<br />
Literature:<br />
DeLano, W.L. The PyMOL Molecular Graphics System (2002) DeLano Scientific, San Carlos, CA, USA. http://www.pymol.org<br />
<br />
----------------------------------------------------------------------<br />
----------------------------------------------------------------------<br />
"""<br />
<br />
nbins=int(nbins)<br />
sat=float(sat)<br />
value=float(value)<br />
hs=float(hs)<br />
he=float(he)<br />
ss=float(ss)<br />
se=float(se)<br />
vs=float(vs)<br />
ve=float(ve)<br />
colorname='color_'+selection<br />
<br />
nbins=int(maximum)-int(minimum)+2<br />
dummy="dummy-"+selection<br />
colname="col"+selection<br />
<br />
<br />
# make sure sat and value are in the range 0-1.0<br />
sat = min(sat, 1.0)<br />
sat = max(sat, 0.0)<br />
value = min(value, 1.0)<br />
value = max(value, 0.0)<br />
<br />
# make sure lowercase<br />
gradient.lower()<br />
mode.lower()<br />
<br />
# Sanity checking<br />
if nbins == 1:<br />
print "\n WARNING: You specified nbins=1, which doesn't make sense...resetting nbins=11\n"<br />
nbins=11<br />
<br />
if mode not in ('hist','ramp'):<br />
print "\n WARNING: Unknown mode ",mode, " -----> Nothing done.\n"<br />
return<br />
if selection == '':<br />
print "\n USAGE: color_grad dimB, minimum=380, maximum=531, hs=0.3, he=0.25,ss=0.7,se=0.2,vs=1,ve=0.5\n"<br />
return<br />
elif gradient not in ('bgr','rgb','rainbow','reverserainbow','bwr','rwb',<br />
'bmr','rmb','rw','wr','gw','wg','bw','wb','gy','yg','gray','grey','reversegray','reversegrey'):<br />
print "\n WARNING: Unknown gradient: ",gradient, " -----> Nothing done.\n"<br />
return<br />
<br />
print "MODE, GRADIENT, NBINS:", mode,gradient, nbins<br />
<br />
# get list of B-factors from selection<br />
m = cmd.get_model(selection)<br />
sel = []<br />
b_list = []<br />
<br />
if len(m.atom) == 0:<br />
print "Sorry, no atoms selected"<br />
<br />
else:<br />
if item == 'b':<br />
for i in range(len(m.atom)):<br />
m.atom[i].b=m.atom[i].resi<br />
b_list.append(m.atom[i].b) <br />
<br />
elif item == 'q':<br />
for i in range(len(m.atom)):<br />
b_list.append(m.atom[i].q)<br />
<br />
else:<br />
print "Not configured to work on item %s" % item<br />
return<br />
<br />
cmd.load_model(m, dummy)<br />
<br />
print selection<br />
max_b = maximum<br />
min_b = minimum<br />
print "Minimum and Maximum B-values: ", min_b, max_b<br />
#nbins = (max_b - min_b)<br />
<br />
<br />
if mode == 'hist':<br />
<br />
# check if minimum or maximum was specified and use the entered values<br />
if minimum != '':<br />
min_b = int(minimum)-1<br />
if maximum != '':<br />
max_b = int(maximum)+1<br />
# histogram:<br />
# color in bins of equal B-value ranges<br />
# subtract 0.1 from the lowest B in order to ensure that the single<br />
# atom with the lowest B value doesn't get omitted<br />
bin_width = (max_b - min_b)/nbins<br />
sel.append(selection + " and (%s = %4.4g" % (item,min_b + bin_width) + ")")<br />
for j in range(1,nbins):<br />
#sel.append(selection + " and %s > %4.4g" % (item,min_b + j*bin_width))<br />
sel.append(dummy + " and %s = %4.4g" % (item,min_b + j*bin_width))<br />
<br />
<br />
# call the function to create the gradient which returns a list of colours<br />
colours = make_gradient(sel,gradient,nbins,sat,value,hs,he,ss,se,vs,ve,colorname)<br />
<br />
# do the colouring now<br />
for j in range(nbins):<br />
print "Color select: ",sel[j]<br />
cmd.color(colours[j],sel[j])<br />
sel = []<br />
colours = []<br />
# function for creating the gradient<br />
def make_gradient(sel,gradient,nbins,sat,value,hs,he,ss,se,vs,ve,colorname):<br />
if gradient == 'bgr' or gradient == 'rainbow':<br />
col=[]<br />
coldesc=[]<br />
for j in range(nbins):<br />
# must append the str(sel[j]) to the color name so that it is unique <br />
# for the selection<br />
coldesc.append(colorname + str(j))<br />
# coldesc.append('col' + str(sel[j]) + str(j))<br />
<br />
# create colors using hsv scale (fractional) starting at blue(.6666667) <br />
# through red(0.00000) in intervals of .6666667/(nbins -1) (the "nbins-1" <br />
# ensures that the last color is, in fact, red (0)<br />
# rewrote this to use the colorsys module to convert hsv to rgb<br />
hsv = (hs - (hs-he) * float(j) / (nbins-1), ss-(ss-se)*float(j)/(nbins-1), vs-(vs-ve)*float(j)/(nbins-1) )<br />
#convert to rgb and append to color list<br />
rgb = colorsys.hsv_to_rgb(hsv[0],hsv[1],hsv[2])<br />
<br />
col.append(rgb)<br />
# cmd.set_color("col" + str(sel[j]) + str(j),col[j])<br />
cmd.set_color(colorname + str(j),col[j])<br />
<br />
#cmd.color(,resi[j])<br />
<br />
# return the gradient as a list of colors named by their index (i.e. col0,col1,col2,col3,...)<br />
return coldesc<br />
</source><br />
<br />
==Download==<br />
[[Media:colorama-0.1.1.tar.bz2|colorama-0.1.1.tar.bz2]]<br />
<br />
[[Category:Plugins]]<br />
[[Category:Script_Library|Helicity Check]]<br />
[[Category:Coloring]]</div>Newaccthttps://pymolwiki.org/index.php?title=Kabsch&diff=8078Kabsch2010-02-26T08:13:19Z<p>Newacct: </p>
<hr />
<div>==Intro==<br />
The Kabsch algorithm uses linear and vector algebra to find the optimal rotation and translation of two sets of points in N-dimensional space as to minimize the RMSD between them. The following program is a Python implementation of the Kabsch algorithm.<br />
<br />
This program when called will align the two selections, optimally, convert the proteins in the selection to ribbons and change the color of the selections to show the matched alignments.<br />
<br />
'''WHAT THIS DOESN'T DO''': This program does NOT provide a pairwise alignment of two structures from scratch. You have to tell it what the equivalent items are. See [[Cealign]].<br />
<br />
'''NOTE:''' This has '''NOT''' been tested on any other machine than mine, by me. It works on all PyMols 0.97 and newer (haven't tested earlier versions) and I use Python 2.3's Numeric Version 23.3.<br />
<br />
'''NOTE:''' I have added new Kabsch code. The new code uses SVD, and fixed an old bug. For ease of use, try the new code (requires numpy, though).<br />
<br />
==To use==<br />
<br />
# Save this script to Kabsch.py<br />
# Open PyMol<br />
# Load the alignment script: '''run Kabsch.py''' (The command '''optAlign''' is now defined in PyMol.)<br />
# Load your proteins<br />
# Align the proper segments (see below examples)<br />
<br />
To align two equivalent sets of residues do:<br />
<source lang="python"><br />
optAlign SEL1 and n. CA and i. a-b, SEL2 and n. CA and i. c-d<br />
</source><br />
where<br />
* '''SEL1''' is the first protein<br />
* '''a-b''' is the range of residues to align in the first protein<br />
* '''SEL2''' is the second protein<br />
* '''c-d''' is the range of residues to align in the second protein<br />
<br />
===Caveats===<br />
* Ensure that you're equivalencing '''N''' atoms to '''N''' atoms (run [[Count_Atoms]] over your two selections to ensure they are the same length).<br />
* Sometimes PyMol doesn't seem to superimpose them right the first time. Hit the up-arrow and rerun the program if this happens. It always superimposes the correctly the second time. I think it has something to do with the orientation. I'll fix this when I find the error.<br />
* The RMSD is only between the equivalent atoms. Use PyMol's [[Rms_Cur]] if you want a full RMSD.<br />
* Make sure your atom selections are numbered correctly. Many times PDB files start residue numbers at something other than 0 or 1. To ensure you're aligning the right things, do <source lang="python">set seq_view,1</source> to turn on the sequence viewer and double check your residue numbers. If a protein has residue one numbered as something other than one, say 2064, simply run <source lang="python">alter (SEL), resi=str(int(resi)-2064)</source> and then <source lang="python">sort</source> where '''SEL''' is the name of the protein and 2064 is the offset to adjust by. Your protein will now work as needed. See [[Alter]]. This capability is also provided in a script; See [[zero_residues]].<br><br />
<br />
== Notes ==<br />
<ol><li>Windows users are having problems running the script. Python tells them first off "TypeError: Can't convert rank-0 arrays to Python scalars." The fix to that breaks some code in Numeric -- which I don't maintain.</li><br><br />
<li>However, to make this work, you can change the code in <b>Numeric.py</b> supplied with Pymol, located in the folder "<Pymol Home>\modules\Numeric\" (for example: "C:\Program Files\DeLano Scientific\PyMOL\modules\Numeric").<br><br><br />
Essentially, you need to search for the line: <source lang="python"> if axis2 < 0: axis2 = axis1 + n # (should be around line 250) </source> and replace it with: <source lang="python">if axis2 < 0: axis2 = axis2 + n </source></li></ol><br />
<br />
===Examples===<br />
optAlign 1cll and n. CA and i. 4-20+30-60, 1ggz and n. CA and i. 4-20+30-60<br />
<br />
optAlign 1kao and n. CA and i. 20-50, 1ctq and n. CA and i. 20-50<br />
<br />
<gallery><br />
Image:OptAlign1.png|1cll and 1ggz loaded<br />
Image:OptAlign2.png|1cll and 1ggz aligned to residues 5-50+55-80 shown in red<br />
</gallery><br />
<br />
Kabsch can also align hetero-atoms:<br />
<source lang="python"><br />
load 1cll.pdb<br />
load 1ggz.pdb<br />
optAlign 1cll and e. CA, 1ggz and e. CA<br />
</source><br />
The above aligns the 4 Calciums in each structure.<br />
<br />
==The Code==<br />
<source lang="python"><br />
#!python<br />
<br />
##############################################################################<br />
#<br />
# @SUMMARY: -- QKabsch.py. A python implementation of the optimal superposition<br />
# of two sets of vectors as proposed by Kabsch 1976 & 1978.<br />
#<br />
# @AUTHOR: Jason Vertrees<br />
# @COPYRIGHT: Jason Vertrees (C), 2005-2007<br />
# @LICENSE: Released under GPL:<br />
# This program is free software; you can redistribute it and/or modify<br />
# it under the terms of the GNU General Public License as published by<br />
# the Free Software Foundation; either version 2 of the License, or<br />
# (at your option) any later version.<br />
# This program is distributed in the hope that it will be useful, but WITHOUT<br />
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS<br />
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.<br />
#<br />
# You should have received a copy of the GNU General Public License along with<br />
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin<br />
# Street, Fifth Floor, Boston, MA 02110-1301, USA <br />
#<br />
# DATE : 2007-01-01<br />
# REV : 2<br />
# REQUIREMENTS: numpy<br />
#<br />
#############################################################################<br />
from array import *<br />
<br />
# system stuff<br />
import os<br />
import copy<br />
<br />
# pretty printing<br />
import pprint<br />
<br />
# for importing as a plugin into PyMol<br />
from pymol import cmd<br />
from pymol import stored<br />
from pymol import selector<br />
<br />
# using numpy for linear algebra<br />
import numpy<br />
<br />
def optAlign( sel1, sel2 ):<br />
"""<br />
optAlign performs the Kabsch alignment algorithm upon the alpha-carbons of two selections.<br />
Example: optAlign MOL1 and i. 20-40, MOL2 and i. 102-122<br />
Example 2: optAlign 1GGZ and i. 4-146 and n. CA, 1CLL and i. 4-146 and n. CA<br />
<br />
Two RMSDs are returned. One comes from the Kabsch algorithm and the other from<br />
PyMol based upon your selections.<br />
<br />
By default, this program will optimally align the ALPHA CARBONS of the selections provided.<br />
To turn off this feature remove the lines between the commented "REMOVE ALPHA CARBONS" below.<br />
<br />
@param sel1: First PyMol selection with N-atoms<br />
@param sel2: Second PyMol selection with N-atoms<br />
"""<br />
cmd.reset()<br />
<br />
# make the lists for holding coordinates<br />
# partial lists<br />
stored.sel1 = []<br />
stored.sel2 = []<br />
# full lists<br />
stored.mol1 = []<br />
stored.mol2 = []<br />
<br />
# -- CUT HERE<br />
sel1 += " and N. CA"<br />
sel2 += " and N. CA"<br />
# -- CUT HERE<br />
<br />
# Get the selected coordinates. We<br />
# align these coords.<br />
cmd.iterate_state(1, selector.process(sel1), "stored.sel1.append([x,y,z])")<br />
cmd.iterate_state(1, selector.process(sel2), "stored.sel2.append([x,y,z])")<br />
<br />
# get molecule name<br />
mol1 = cmd.identify(sel1,1)[0][0]<br />
mol2 = cmd.identify(sel2,1)[0][0]<br />
<br />
# Get all molecule coords. We do this because<br />
# we have to rotate the whole molcule, not just<br />
# the aligned selection<br />
cmd.iterate_state(1, mol1, "stored.mol1.append([x,y,z])")<br />
cmd.iterate_state(1, mol2, "stored.mol2.append([x,y,z])")<br />
<br />
# check for consistency<br />
assert len(stored.sel1) == len(stored.sel2)<br />
L = len(stored.sel1)<br />
assert L > 0<br />
<br />
# must alway center the two proteins to avoid<br />
# affine transformations. Center the two proteins<br />
# to their selections.<br />
COM1 = numpy.sum(stored.sel1,axis=0) / float(L)<br />
COM2 = numpy.sum(stored.sel2,axis=0) / float(L)<br />
stored.sel1 -= COM1<br />
stored.sel2 -= COM2<br />
<br />
# Initial residual, see Kabsch.<br />
E0 = numpy.sum( numpy.sum(stored.sel1 * stored.sel1,axis=0),axis=0) + numpy.sum( numpy.sum(stored.sel2 * stored.sel2,axis=0),axis=0)<br />
<br />
#<br />
# This beautiful step provides the answer. V and Wt are the orthonormal<br />
# bases that when multiplied by each other give us the rotation matrix, U.<br />
# S, (Sigma, from SVD) provides us with the error! Isn't SVD great!<br />
V, S, Wt = numpy.linalg.svd( numpy.dot( numpy.transpose(stored.sel2), stored.sel1))<br />
<br />
# we already have our solution, in the results from SVD.<br />
# we just need to check for reflections and then produce<br />
# the rotation. V and Wt are orthonormal, so their det's<br />
# are +/-1.<br />
reflect = float(str(float(numpy.linalg.det(V) * numpy.linalg.det(Wt))))<br />
<br />
if reflect == -1.0:<br />
S[-1] = -S[-1]<br />
V[:,-1] = -V[:,-1]<br />
<br />
RMSD = E0 - (2.0 * sum(S))<br />
RMSD = numpy.sqrt(abs(RMSD / L))<br />
<br />
#U is simply V*Wt<br />
U = numpy.dot(V, Wt)<br />
<br />
# rotate and translate the molecule<br />
stored.sel2 = numpy.dot((stored.mol2 - COM2), U)<br />
stored.sel2 = stored.sel2.tolist()<br />
# center the molecule<br />
stored.sel1 = stored.mol1 - COM1<br />
stored.sel1 = stored.sel1.tolist()<br />
<br />
# let PyMol know about the changes to the coordinates<br />
cmd.alter_state(1,mol1,"(x,y,z)=stored.sel1.pop(0)")<br />
cmd.alter_state(1,mol2,"(x,y,z)=stored.sel2.pop(0)")<br />
<br />
print "RMSD=%f" % RMSD<br />
<br />
# make the alignment OBVIOUS<br />
cmd.hide('everything')<br />
cmd.show('ribbon', sel1 + ' or ' + sel2)<br />
cmd.color('gray70', mol1 )<br />
cmd.color('paleyellow', mol2 )<br />
cmd.color('red', 'visible')<br />
cmd.show('ribbon', 'not visible')<br />
cmd.center('visible')<br />
cmd.orient()<br />
cmd.zoom('visible')<br />
<br />
cmd.extend("optAlign", optAlign)<br />
</source><br />
<br />
=== The Old Code ===<br />
<br />
<source lang="python"><br />
#!python<br />
<br />
##############################################################################<br />
#<br />
# @SUMMARY: -- Kabsch.py. A python implementation of the optimal superposition<br />
# of two sets of vectors as proposed by Kabsch 1976 & 1978.<br />
#<br />
# @AUTHOR: Jason Vertrees<br />
# @COPYRIGHT: Jason Vertrees (C), 2005-2007<br />
# @LICENSE: Released under GPL:<br />
# This program is free software; you can redistribute it and/or modify<br />
# it under the terms of the GNU General Public License as published by<br />
# the Free Software Foundation; either version 2 of the License, or<br />
# (at your option) any later version.<br />
# This program is distributed in the hope that it will be useful, but WITHOUT<br />
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS<br />
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.<br />
#<br />
# You should have received a copy of the GNU General Public License along with<br />
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin<br />
# Street, Fifth Floor, Boston, MA 02110-1301, USA <br />
#<br />
# DATE : 2005-04-07<br />
# REV : 2<br />
# NOTES: Updated RMSD, notes, cleaned up the code a little.<br />
#<br />
#############################################################################<br />
# math imports<br />
import math<br />
import Numeric<br />
import LinearAlgebra<br />
import Matrix<br />
<br />
from array import *<br />
<br />
# system stuff<br />
import os<br />
import copy<br />
<br />
# pretty printing<br />
import pprint<br />
<br />
# for importing as a plugin into PyMol<br />
#import tkSimpleDialog<br />
#import tkMessageBox<br />
from pymol import cmd<br />
from pymol import stored<br />
from pymol import selector<br />
<br />
class kabsch:<br />
"""<br />
Kabsch alignment of two set of vectors to produce and optimal alignment.<br />
<br />
Steps<br />
===== <br />
1. Calculate the center of mass for each protein. Then, move the protein<br />
to its center of mass. We choose as a convention, to use the origin as <br />
the center of mass of the first set of coordinates. This will allow us to<br />
return one translation vector, instead of two.<br />
<br />
Update: Since any rotation around a point that's not the origin, is in fact<br />
an affine rotation. So, to beat that, we translate both to the center.<br />
<br />
NAME: superpose(c1, c2)<br />
POST: T is now defined.<br />
<br />
2. Calculate the matrix, R, by (eq7, 1976). r_{i,j} = sum_n w_n * y_{ni} * x_{nj},<br />
where y_{ni} is the ith component of the vector y_n.<br />
NAME: calcR<br />
POST: R is now defined<br />
<br />
3. Calculate RtR (R-transpose * R).<br />
NAME: calcRtR<br />
POST: RtR is now defined<br />
<br />
4. Calculate the corresponding eigenpairs for RtR, and sort them accordingly:<br />
m1 >= m2 >= m3; set v3 = v1 x v2 to ensure a RHS<br />
NAME: calcEigenPairs<br />
POST: The eigen pairs are calculated, sorted such that m1 >= m2 >= m3 and<br />
v3 = v1 x v2.<br />
<br />
5. Calculate R*v_k and normalize the first two vectors to obtain b_1, b_2 and set<br />
b_3 = b_1 x b_2. This also takes care of m1 > m2 = 0. <br />
NAME: calcBVectors<br />
POST: b-Vectors are defined and returned<br />
<br />
6. Calculate U=(u_{ij})=(sum n b_{ki} * a_{kj}) to obtain the best rotation. Set<br />
sigma_3 = -1 if b3(Ra3) < 0 else sigma_3 = +1.<br />
NAME: calcU<br />
POST: U is defined<br />
<br />
7. Calculate the RMSD. The residual error is then<br />
The E = E0 - sqrt(m1) - sqrt(m2) - sigma_3(sqrt(m3)).<br />
NAME: calcRMSD<br />
POST: RMSD is computed.<br />
<br />
@note: This should be a static method that takes three parameters<br />
<br />
1. The first protein's coordinates, f. This program will <br />
accept coordinates in the form an array of 3D vectors/lists<br />
<br />
2. The second protein's coordinates, g.<br />
<br />
3. The array of integer pairs representing the pairs to align.<br />
Coordinates should be formatted as as array of 2D vectors/lists.<br />
<br />
<br />
<br />
"""<br />
<br />
def __init__(self):<br />
"""<br />
Constructor. @see kabsch.align.<br />
<br />
"""<br />
<br />
#<br />
# Instance Variables: All three of these will be updated<br />
# every time the user calls ~.align. Just to warn ya'.<br />
# <br />
# U, the rotation matrix<br />
self.U = []<br />
# T, the translation vector<br />
self.T = []<br />
# R, the RMSD<br />
self.R = -1.0<br />
<br />
#self.menuBar.addmenuitem('Plugin', 'command', 'Kabsch Align', label = "Align Selections to Optial RMSD", command = lamda s=self: fetchPDBDialog(s))<br />
<br />
<br />
def align(self, c1, c2, pairs):<br />
"""<br />
Finds the best alignment of c1 and c2's pairs resulting in<br />
the smallest possible RMSD.<br />
<br />
<br />
@note:<br />
- All weights in this first version are set to 1. Kabsch allows,<br />
differential weighting. In the future, I may extend to this option,<br />
and then pairs may become 3D (r1, r2, weight) or I may add another<br />
parameter.<br />
<br />
- Helper functions will soon be provided such that the user may<br />
just use this package alone to compute the rotation.<br />
<br />
@param c1: coordinats of the first vectors, as an array of 3D vectors.<br />
@type c1: Python list<br />
<br />
@param c2: coordinates of the second set of vectors, as an array of 3D vectors.<br />
@type c2: Python list<br />
<br />
@param pairs: the list of pairs as an array of 2D pairs.<br />
@type pairs: Python list of 2D lists.<br />
<br />
@return: U, the rotation matrix that gives the optimal rotation between the two proteins.<br />
<br />
T, the translation vector given to align the two objects centers of mass.<br />
<br />
R, the RMSD of the final rotation.<br />
"""<br />
<br />
#<br />
# First we move the center of mass of one protein, to the<br />
# center of mass of the other. This removes any translation<br />
# between the two.<br />
#<br />
T1, T2, c1, c2 = self.superpose(c1, c2)<br />
# Calculate the initial RMSD<br />
E0 = self.calcE0(c1, c2)<br />
# Calculate R via eq. 7.<br />
R = self.calcR(c1, c2)<br />
# Calculate R(transpose)*R<br />
RtR = self.calcRtR(R)<br />
# Determined the eigenpairs for the matrix RtR.<br />
eValues, eVectors = self.calcEigenPairs(RtR)<br />
# Determine the bVectors as required<br />
bVectors = self.calcBVectors(R, eVectors)<br />
# Calculate the roation matrix<br />
U = self.calcU(eVectors, bVectors)<br />
# Calculate the final RMSD using U.<br />
RMSD = self.calcRMSD(E0, eValues, eVectors, bVectors, R, len(c1))<br />
<br />
return U, T1, T2, RMSD, c1, c2<br />
<br />
<br />
def superpose(self, c1, c2 ):<br />
"""<br />
Calculate the center of mass for each protein. Then, move the protein<br />
to its center of mass. We choose as a convention, to use the origin as <br />
the center of mass of the first set of coordinates. This will allow us to<br />
return one translation vector, instead of two.<br />
(CORRECT)<br />
<br />
@precondition: c1 and c2 are well defined lists of N-dimensional points with length > 0.<br />
@postcondition: T is now defined.<br />
<br />
@param c1: coordinats of the first vectors, as an array of 3D vectors.<br />
@type c1: Python list<br />
<br />
@param c2: coordinates of the second set of vectors, as an array of 3D vectors.<br />
@type c2: Python list<br />
<br />
@return: T the translation vector.<br />
<br />
c2 one list of coordinates that of c2 translated to the COM of c1.<br />
<br />
"""<br />
<br />
# make sure we don't get bad data<br />
if len(c1) != len(c2):<br />
print "Two different length selections, with lengths, %d and %d." % (len(c1), len(c2))<br />
print "This algorithm must be used with selections of the same length." <br />
print "In PyMol, type 'count_atoms sel1' where sel1 are your selections to find out their lengths."<br />
print "Example: optAlign MOL1 and i. 20-40, MOL2 and i. 102-122"<br />
print "Example 2: optAlign 1GGZ and i. 4-146 and n. CA, 1CLL and i. 4-146 and n. CA"<br />
<br />
<br />
assert len(c1) == len(c2) != 0<br />
<br />
L = len(c1)<br />
<br />
#<br />
# Centers of Mass<br />
#<br />
c1COM = Numeric.zeros((3,1), Numeric.Float64)<br />
c2COM = Numeric.zeros((3,1), Numeric.Float64)<br />
<br />
# calculate the CsOM <br />
for i in range(L):<br />
for j in range(3):<br />
c1COM[j] += c1[i][j]<br />
c2COM[j] += c2[i][j]<br />
<br />
T1 = - c1COM / L<br />
T2 = - c2COM / L<br />
<br />
# move everything back to the origin.<br />
for i in range(L):<br />
for j in range(3):<br />
c1[i][j] += T1[j]<br />
c2[i][j] += T2[j]<br />
<br />
return T1, T2, c1, c2<br />
<br />
<br />
def calcR( self, c1, c2 ):<br />
"""<br />
Calculate the matrix, R, by (eq7, 1976). M{r_{i,j} = sum_n w_n * y_{ni} * x_{nj}},<br />
where M{y_{ni}} is the ith component of the vector M{y_n}.<br />
(CORRECT)<br />
<br />
@param c1: coordinates of the first vectors, as an array of 3D vectors.<br />
@type c1: Python list<br />
<br />
@param c2: coordinates of the second set of vectors, as an array of 3D vectors.<br />
@type c2: Python list<br />
<br />
@postcondition: R is now defined.<br />
<br />
@return: R<br />
@rtype : 3x3 matrix<br />
<br />
"""<br />
<br />
# Create the 3x3 matrix<br />
R = Numeric.zeros((3,3), Numeric.Float64)<br />
L = len(c1)<br />
<br />
for k in range(L):<br />
for i in range(3):<br />
for j in range(3):<br />
R[i][j] += c2[k][i] * c1[k][j]<br />
<br />
# return R the 3x3 PSD Matrix.<br />
return R<br />
<br />
<br />
def calcRtR( self, R ):<br />
"""<br />
Calculate RtR (R-transpose * R).<br />
(CORRECT)<br />
<br />
@param R: Matrix<br />
@type R: 3x3 Matrix<br />
<br />
@precondition: R is a the well formed matrix as per Kabsch.<br />
@postcondition: RtR is now defined<br />
<br />
@return: M{R^tR}<br />
@rtype : 3x3 matrix<br />
<br />
"""<br />
<br />
RtR = Numeric.matrixmultiply(Numeric.transpose(R), R)<br />
<br />
return RtR<br />
<br />
<br />
def calcEigenPairs( self, RtR ):<br />
"""<br />
Calculate the corresponding eigenpairs for RtR, and sort them accordingly:<br />
M{m1 >= m2 >= m3}; set M{v3 = v1 x v2} to ensure a RHS<br />
(CORRECT)<br />
<br />
@postcondition: The eigen pairs are calculated, sorted such that M{m1 >= m2 >= m3} and<br />
M{v3 = v1 x v2}.<br />
<br />
@param RtR: 3x3 Matrix of M{R^t * R}.<br />
@type RtR: 3x3 Matrix<br />
@return : Eigenpairs for the RtR matrix.<br />
@rtype : List of stuff<br />
<br />
"""<br />
<br />
eVal, eVec = LinearAlgebra.eigenvectors(RtR)<br />
<br />
# This is cool. We sort it using Numeric.sort(eVal)<br />
# then we reverse it using nifty-crazy ass notation [::-1].<br />
eVal2 = Numeric.sort(eVal)[::-1]<br />
eVec2 = [[],[],[]] #Numeric.zeros((3,3), Numeric.Float64)<br />
<br />
# Map the vectors to their appropriate owners <br />
if eVal2[0] == eVal[0]:<br />
eVec2[0] = eVec[0]<br />
if eVal2[1] == eVal[1]:<br />
eVec2[1] = eVec[1]<br />
eVec2[2] = eVec[2]<br />
else:<br />
eVec2[1] = eVec[2]<br />
eVec2[2] = eVec[1]<br />
elif eVal2[0] == eVal[1]:<br />
eVec2[0] = eVec[1]<br />
if eVal2[1] == eVal[0]:<br />
eVec2[1] = eVec[0]<br />
eVec2[2] = eVec[2]<br />
else:<br />
eVec2[1] = eVec[2]<br />
eVec2[2] = eVec[0]<br />
elif eVal2[0] == eVal[2]:<br />
eVec2[0] = eVec[2]<br />
if eVal2[1] == eVal[1]:<br />
eVec2[1] = eVec[1]<br />
eVec2[2] = eVec[0]<br />
else:<br />
eVec2[1] = eVec[0]<br />
eVec2[2] = eVec[1]<br />
<br />
eVec2[2][0] = eVec2[0][1]*eVec2[1][2] - eVec2[0][2]*eVec2[1][1]<br />
eVec2[2][1] = eVec2[0][2]*eVec2[1][0] - eVec2[0][0]*eVec2[1][2]<br />
eVec2[2][2] = eVec2[0][0]*eVec2[1][1] - eVec2[0][1]*eVec2[1][0]<br />
<br />
return [eVal2, eVec2]<br />
<br />
<br />
def calcBVectors( self, R, eVectors ):<br />
"""<br />
Calculate M{R*a_k} and normalize the first two vectors to obtain M{b_1, b_2} and set<br />
M{b_3 = b_1 x b_2}. This also takes care of {m2 > m3 = 0}. <br />
(CORRECT)<br />
<br />
@postcondition: b-Vectors are defined and returned<br />
<br />
@return: The three B-vectors<br />
@rtype: List of 3D vectors (Python LOL).<br />
"""<br />
<br />
bVectors = Numeric.zeros((3,3), Numeric.Float64)<br />
<br />
for i in range(3):<br />
bVectors[i] = Numeric.matrixmultiply(R, eVectors[i])<br />
<br />
bVectors[0] = bVectors[0] / Numeric.sqrt(Numeric.add.reduce(bVectors[0]**2))<br />
bVectors[1] = bVectors[1] / Numeric.sqrt(Numeric.add.reduce(bVectors[1]**2))<br />
bVectors[2] = bVectors[2] / Numeric.sqrt(Numeric.add.reduce(bVectors[2]**2))<br />
<br />
bVectors[2][0] = bVectors[0][1]*bVectors[1][2] - bVectors[0][2]*bVectors[1][1]<br />
bVectors[2][1] = bVectors[0][2]*bVectors[1][0] - bVectors[0][0]*bVectors[1][2]<br />
bVectors[2][2] = bVectors[0][0]*bVectors[1][1] - bVectors[0][1]*bVectors[1][0]<br />
<br />
return bVectors<br />
<br />
<br />
<br />
def calcU( self, eVectors, bVectors ):<br />
"""<br />
Calculate M{U=(u_{ij})=(sum n b_{ki} * a_{kj})} to obtain the best rotation. Set<br />
M{sigma_3 = -1 if b3(Ra3) < 0 else sigma_3 = +1}.<br />
(CORRECT)<br />
<br />
@postcondition: U is defined<br />
<br />
@param eVectors: Eigenvectors for the system.<br />
@type eVectors: Eigenvectors<br />
<br />
@param bVectors: BVectors as described by Kabsch.<br />
@type bVectors: BVectors<br />
<br />
@return: U the rotation matrix.<br />
@rtype :3x3 matrix.<br />
<br />
"""<br />
<br />
U = Numeric.zeros((3,3), Numeric.Float64)<br />
<br />
for k in range(3):<br />
for i in range(3):<br />
for j in range(3):<br />
U[i][j] += Numeric.matrixmultiply(bVectors[k][i], eVectors[k][j])<br />
<br />
return U<br />
<br />
<br />
def calcE0( self, c1, c2 ):<br />
"""<br />
Calculates the initial RMSD, which Kacbsch called E0.<br />
(CORRECT)<br />
<br />
@param c1: coordinats of the first vectors, as an array of 3D vectors.<br />
@type c1: Python list<br />
<br />
@param c2: coordinates of the second set of vectors, as an array of 3D vectors.<br />
@type c2: Python list<br />
<br />
@return: E0 the initial RMSD.<br />
@rtype : float.<br />
<br />
"""<br />
<br />
E0 = 0.0<br />
<br />
L = len(c1)<br />
for i in range( L ):<br />
for j in range(3):<br />
E0 += 0.5*( c1[i][j]*c1[i][j]+c2[i][j]*c2[i][j])<br />
<br />
return E0<br />
<br />
def calcRMSD( self, E0, eValues, eVectors, bVectors, R, N):<br />
"""<br />
Calculate the RMSD. The residual error is then<br />
The M{E = E0 - sqrt(m1) - sqrt(m2) - sigma_3(sqrt(m3))}.<br />
<br />
@param E0: Initial RMSD as calculated in L{calcE0}.<br />
@type E0: float.<br />
<br />
@param eVectors: Eigenvectors as calculated from L{calcEigenPairs}<br />
@type eVectors: vectors, dammit!<br />
<br />
@param bVectors: B-vectors as calc. from L{calcBVectors}<br />
@type bVectors: More vectors.<br />
<br />
@param R: The matrix R, from L{calcR}.<br />
@type R: 3x3 matrix. <br />
<br />
@param N: Number of equivalenced points<br />
@type N: integer<br />
<br />
@postcondition: RMSD is computed.<br />
@return: The RMSD.<br />
<br />
"""<br />
sigma3 = 0<br />
if Numeric.matrixmultiply(bVectors[2], Numeric.matrixmultiply( R, eVectors[2])) < 0:<br />
sigma3 = -1<br />
else:<br />
sigma3 = 1<br />
<br />
E = math.sqrt( 2*(E0 - math.sqrt(eValues[0]) - math.sqrt(eValues[1]) - sigma3*(math.sqrt(eValues[2]))) / N)<br />
<br />
return E<br />
<br />
<br />
def calcSimpleRMSD( self, c1, c2 ):<br />
"""<br />
Calculates the usual concept of RMSD between two set of points. The CalcRMSD above<br />
sticks to Kabsch's alignment method protocol and calculates something much different.<br />
@see kabsch.calcRMSD<br />
<br />
@param c1: List of points #1<br />
@type c1: LOL<br />
<br />
@param c2: List of points #2<br />
@type c2: LOL<br />
<br />
@return: RMSD between the two<br />
<br />
"""<br />
<br />
RMSD = 0.0<br />
for i in range(len(c1)):<br />
for j in range(3):<br />
RMSD += (c2[i][j]-c1[i][j])**2<br />
<br />
RMSD = RMSD / len(c1)<br />
RMSD = Numeric.sqrt(RMSD)<br />
return RMSD<br />
<br />
<br />
#####################################################################<br />
#<br />
# UTIL Functions<br />
def rotatePoints(self, U, c2):<br />
"""<br />
Rotate all points in c2 based on the rotation matrix U.<br />
<br />
@param U: 3x3 Rotation matrix<br />
@type U: 3x3 matrix<br />
<br />
@param c2: List of points to rotate<br />
@type c2: List of 3D vectors<br />
<br />
@return: List of rotated points<br />
<br />
"""<br />
<br />
L = len(c2)<br />
<br />
for n in range(L):<br />
c2[n][0] = c2[n][0] * U[0][0] + c2[n][1] * U[1][0] + c2[n][2] * U[2][0]<br />
c2[n][1] = c2[n][0] * U[0][1] + c2[n][1] * U[1][1] + c2[n][2] * U[2][1]<br />
c2[n][2] = c2[n][0] * U[0][2] + c2[n][1] * U[1][2] + c2[n][2] * U[2][2]<br />
<br />
return c2<br />
<br />
def writeU( self, U, fileName ):<br />
"""<br />
Convenience function. Writes U to disk.<br />
<br />
"""<br />
<br />
if len(fileName) == 0:<br />
fileName = "./U"<br />
<br />
outFile = open( fileName, "wb")<br />
for i in range(3):<br />
for j in range(3):<br />
outFile.write( str(U[i][j]).ljust(20) )<br />
outFile.write("\n")<br />
outFile.close() <br />
<br />
<br />
<br />
def optAlign( sel1, sel2 ):<br />
"""<br />
optAlign performs the Kabsch alignment algorithm upon the alpha-carbons of two selections.<br />
Example: optAlign MOL1 and i. 20-40, MOL2 and i. 102-122<br />
Example 2: optAlign 1GGZ and i. 4-146 and n. CA, 1CLL and i. 4-146 and n. CA<br />
<br />
Two RMSDs are returned. One comes from the Kabsch algorithm and the other from<br />
PyMol based upon your selections.<br />
<br />
By default, this program will optimally align the ALPHA CARBONS of the selections provided.<br />
To turn off this feature remove the lines between the commented "REMOVE ALPHA CARBONS" below.<br />
<br />
@param sel1: First PyMol selection with N-atoms<br />
@param sel2: Second PyMol selection with N-atoms<br />
"""<br />
cmd.reset()<br />
<br />
# make the lists for holding coordinates<br />
# partial lists<br />
stored.sel1 = []<br />
stored.sel2 = []<br />
# full lists<br />
stored.mol1 = []<br />
stored.mol2 = []<br />
<br />
# now put the coordinates into a list<br />
# partials<br />
<br />
# -- REMOVE ALPHA CARBONS<br />
sel1 += " and N. CA"<br />
sel2 += " and N. CA"<br />
# -- REMOVE ALPHA CARBONS<br />
<br />
cmd.iterate_state(1, selector.process(sel1), "stored.sel1.append([x,y,z])")<br />
cmd.iterate_state(1, selector.process(sel2), "stored.sel2.append([x,y,z])")<br />
# full molecule<br />
mol1 = cmd.identify(sel1,1)[0][0]<br />
mol2 = cmd.identify(sel2,1)[0][0]<br />
cmd.iterate_state(1, mol1, "stored.mol1.append([x,y,z])")<br />
cmd.iterate_state(1, mol2, "stored.mol2.append([x,y,z])")<br />
<br />
K = kabsch()<br />
U, T1, T2, RMSD, c1, c2 = K.align(stored.sel1, stored.sel2, [])<br />
<br />
stored.mol2 = map(lambda v:[T2[0]+((v[0]*U[0][0])+(v[1]*U[1][0])+(v[2]*U[2][0])),T2[1]+((v[0]*U[0][1])+(v[1]*U[1][1])+(v[2]*U[2][1])),T2[2]+((v[0]*U[0][2])+(v[1]*U[1][2])+(v[2]*U[2][2]))],stored.mol2)<br />
#stored.mol1 = map(lambda v:[ v[0]+T1[0], v[1]+T1[1], v[2]+T1[2] ], stored.mol1)<br />
stored.mol1 = map(lambda v:[ v[0]+T1[0], v[1]+T1[1], v[2]+T1[2] ], stored.mol1)<br />
<br />
cmd.alter_state(1,mol1,"(x,y,z)=stored.mol1.pop(0)")<br />
cmd.alter_state(1,mol2,"(x,y,z)=stored.mol2.pop(0)")<br />
cmd.alter( 'all',"segi=''")<br />
cmd.alter('all', "chain=''")<br />
print "RMSD=%f" % cmd.rms_cur(sel1, sel2)<br />
print "MY RMSD=%f" % RMSD<br />
cmd.hide('everything')<br />
cmd.show('ribbon', sel1 + ' or ' + sel2)<br />
cmd.color('gray70', mol1 )<br />
cmd.color('paleyellow', mol2 )<br />
cmd.color('red', 'visible')<br />
cmd.show('ribbon', 'not visible')<br />
cmd.center('visible')<br />
cmd.orient()<br />
cmd.zoom('visible')<br />
<br />
cmd.extend("optAlign", optAlign) <br />
</source><br />
<br />
==References==<br />
'''[Kabsch, 1976]''' Kabsch, W. (1976).<br />
A solution for the best rotation to relate two sets of vectors.<br />
''Acta. Crystal'', 32A:922-923.<br />
<br />
'''[Kabsch, 1978]''' Kabsch, W. (1978).<br />
A discussion of the solution for the best rotation to related two sets of vectors.<br />
''Acta. Crystal'', 34A:827-828.<br />
<br />
<br />
[[Category:Script_Library|Kabsch Alignment]]<br />
[[Category:Structure_Alignment|Kabsch Alignment]]</div>Newaccthttps://pymolwiki.org/index.php?title=User:Philaltist&diff=8066User:Philaltist2010-02-23T07:24:00Z<p>Newacct: </p>
<hr />
<div>Hi everyone !<br />
<br />
I have created a script because I was tired of browsing the pdb for endless searches of structures relevant to my field. This scripts takes as input a text file in which you copied your favourite keywords, and the number of days you want to search back (by default, it will look at the structures added the last 50 days). It generates a report text file that contains the pdb id and name of the relevant structures that have been recently added. All you need to do is add 'run pdbsurvey.py' to your startup file, and create a text file called 'keywords.txt' with your keywords separated by an end-of-line character. Then you're ready to go. Just hit 'pdbsurvey' from within your PyMol instance, and the program returns the report file. The pdb ftp server is updated every tuesday.<br />
<br />
<source lang="python"><br />
from pymol import cmd<br />
<br />
def pdbsurvey(days=50):<br />
<br />
"""USAGE : pdbsurvey (<days>)<br />
Surveys the updates added to the PDB (ftp.rcsb.org) in the last<br />
50 days (or otherwise specified when calling this function) for<br />
entries that contain the words specified in the file<br />
keywords.txt.<br />
"""<br />
print days<br />
<br />
import ftplib<br />
import time<br />
import os<br />
<br />
<br />
<br />
def todaymerge():<br />
"""Puts today's date in a pdb format string.<br />
"""<br />
date=time.localtime()<br />
return "%d%02d%02d" % date[0:2]<br />
<br />
def file2list(filename):<br />
"""Low-level routine to brainlessly implement<br />
file.read().<br />
"""<br />
fq=open(filename,'rb')<br />
linesS=fq.read()<br />
fq.close()<br />
LIST=linesS.splitlines()<br />
return LIST<br />
<br />
def connect2pdb():<br />
"""Opens an anonymous socket to ftp://ftp.rcsb.org<br />
"""<br />
f=ftplib.FTP()<br />
f.connect ('ftp.rcsb.org')<br />
f.login ()<br />
print "Remote connection established","\n"<br />
return f<br />
<br />
def decrementdate(dateS):<br />
"""given a string date (pdb format yyyymmdd)<br />
this routine returns a string of the day before<br />
(sadly assuming that every month has 31 days, but<br />
no big deal here...).<br />
"""<br />
#decompose dateS into components<br />
yearS=dateS[0]+dateS[1]+dateS[2]+dateS[3]<br />
monthS=dateS[4]+dateS[5]<br />
dayS=dateS[6]+dateS[7]<br />
<br />
#convert each into integers<br />
yearI=int(yearS)<br />
monthI=int(monthS)<br />
dayI=int(dayS)<br />
<br />
#actual stuff<br />
dayI-=1<br />
if dayI==0:<br />
dayI=31<br />
monthI-=1<br />
if monthI==0:<br />
monthI=12<br />
yearI-=1<br />
#and finally...<br />
return "%d%02d%02d" % (yearI, monthI, dayI)<br />
<br />
def findlastdir(dateS,f,days):<br />
"""Puts the names of the "recent" directories in the<br />
list named "directoriesL".<br />
"""<br />
directoriesL=[]<br />
for p in range(days):<br />
dateS=decrementdate(dateS)<br />
attempt="/pub/pdb/data/status/"+dateS<br />
try :<br />
f.cwd(attempt)<br />
directoriesL.append(attempt)<br />
except :<br />
pass<br />
return directoriesL<br />
<br />
def compilinfile(directoriesL,f):<br />
"""lists all structures in the added.pdb files<br />
contained in the directories specified in directoriesL<br />
"""<br />
command="RETR added.pdb"<br />
handle=open("donotedit.dat","wrb")<br />
for k in directoriesL:<br />
f.cwd(k)<br />
print "Currently in directory ",f.pwd()<br />
f.retrbinary(command,handle.write)<br />
handle.close()<br />
return len(directoriesL)<br />
<br />
def listparser():<br />
"""Extracts the pdbids from donotedit.dat file,<br />
and stacks them into the list pdbidsL<br />
"""<br />
linesL=file2list("donotedit.dat")<br />
pdbidsL=[]<br />
for iter in linesL:<br />
pdbidsL.append(iter[57:61])<br />
for iter in pdbidsL:<br />
iter=iter.lower()<br />
pdbidsL.sort()<br />
return pdbidsL<br />
<br />
def currentrelease(f):<br />
"""Stores the content of cmpd_res.idx file<br />
This file contains the equivalencies pdbid<->title<br />
for all current entries of the PDB.<br />
"""<br />
command="RETR cmpd_res.idx"<br />
f.cwd("/pub/pdb/derived_data/index/")<br />
print "Currently in directory ",f.pwd()<br />
fq=open("dictionnary.dat",'wrb')<br />
f.retrbinary(command,fq.write)<br />
fq.close()<br />
dictL=file2list("dictionnary.dat")<br />
return dictL<br />
<br />
def extract(pdbidsL,dictL):<br />
"""Populates dictionnaryD with pdb entries found in the<br />
latest releases.<br />
"""<br />
dictionnaryD={}<br />
problemL=[]<br />
extractL=[dictionnaryD,problemL]<br />
for i in dictL:<br />
tempS=i[0:4].lower()<br />
for ii in pdbidsL:<br />
if ii == tempS:<br />
title=i[14:216]<br />
extractL[0][ii]=title<br />
if len(extractL[0]) != len(pdbidsL):<br />
print "Dimension mismatch, seeking troublemaker..."<br />
for i in pdbidsL:<br />
equiv=0<br />
for ii in extractL[0]:<br />
if i==ii:<br />
equiv+=1<br />
if equiv==0:<br />
extractL[1].append(i)<br />
return extractL<br />
<br />
def disconnectpdb(f):<br />
"""Diconnects the current ftp session<br />
"""<br />
f.quit()<br />
print "Remote connection terminated","\n"<br />
return f<br />
<br />
def releventries(dictionnaryD):<br />
"""Generates a cleaned dictionnary with only entries<br />
that have one or more keywords specified in the local<br />
user-defined keywords.txt file<br />
"""<br />
keywL=file2list("keywords.txt")<br />
relevdicD={}<br />
for i in keywL:<br />
for elem,temp in dictionnaryD.items():<br />
if i in temp:<br />
relevdicD[elem]=temp<br />
return relevdicD<br />
<br />
def diskcleanup(filelist=["donotedit.dat","dictionnary.dat"]):<br />
"""Lo-level disk cleanup to free up memory without the user<br />
"""<br />
for filename in filelist:<br />
command='DEL '+filename<br />
os.system(command)<br />
return "clean"<br />
<br />
<br />
<br />
<br />
print "Welcome in the auto-PDB updater !"<br />
<br />
print "Survey of updates made since",days,"days ago."<br />
<br />
print "Acquisition of local time..."<br />
dateS=todaymerge() #Initializes dateS<br />
print "today is ",dateS<br />
print "Connecting to remote ftp server..."<br />
f=connect2pdb() #Connect anonymously to ftp.rcsb.org<br />
<br />
print "Acquisition of latest added remote directories..."<br />
directoriesL=findlastdir(dateS,f,days) #Lists recent directories in directoriesL<br />
if len(directoriesL)==0:<br />
print "No updates have been found since",days,"ago. Starting over with 50 days ago."<br />
directoriesL=findlastdir(dateS,f,50)<br />
<br />
print "Acquisition of latest addedremote files..."<br />
updatesnumberI=compilinfile(directoriesL,f) #Concatenates the corresponding added.pdb into donotedit.dat<br />
<br />
print "Parsing of latest entries..."<br />
pdbidsL=listparser() #Recent names now present in the pdbidsL list (one name per element)<br />
<br />
print "Acquisition of the current pdb distribution..."<br />
dictL=currentrelease(f) #Populates dictL with the current entries of the PDB<br />
<br />
print "Parsing of the current pdb distribution into [code,title] tuples..."<br />
extractL=extract(pdbidsL,dictL) #generates the dictionnary of latest releases key:PDBid ; definition:pdbtitle<br />
<br />
print "Disconnection from the remote ftp server..."<br />
f=disconnectpdb(f) #Closes the ftp instance<br />
<br />
print "Extraction of the relevant entries..."<br />
relevdicD=releventries(extractL[0]) #Generates a subset of dictionnary D with criterion being "has keywords contained in keywords.txt in its title"<br />
<br />
print "Cleaning program-generated temporary files..."<br />
clean=diskcleanup() #Cleans the mess generated by the program<br />
<br />
reportL=[]<br />
reportL.append("\n")<br />
reportL.append("###############REPORT########################################\n")<br />
reportL.append("\n")<br />
lendictS="%i" %(len(dictL))<br />
chmilblik = 'The current pdb version (as of '+dateS+") has "+lendictS+" entries.\n"<br />
reportL.append(chmilblik)<br />
line="The most recent directory is : "+directoriesL[0]+".\n"<br />
reportL.append(line)<br />
updatesnumberS="%i" %(updatesnumberI)<br />
entriesnumber="%i" %(len(extractL[0].keys()))<br />
line="The "+updatesnumberS+" last updates ("+entriesnumber+" entries) have been examined.\n"<br />
reportL.append(line)<br />
diclengthS="%i" %(len(relevdicD.keys()))<br />
line=diclengthS+" are relevant to you :\n"<br />
reportL.append(line)<br />
for i,x in relevdicD.items():<br />
entry=i+" : "+x+"\n"<br />
reportL.append(entry)<br />
problemS=""<br />
for i in extractL[1]:<br />
problemS=i+";"+problemS<br />
problemS="["+problemS<br />
problemS=problemS.strip(";")<br />
problemS=problemS+"]"<br />
lineS="The entries "+problemS+" raised problems,"<br />
reportL.append(lineS)<br />
reportL.append("they should be examined manually.")<br />
reportL.append("\n")<br />
reportL.append("###############END OF REPORT#################################\n")<br />
report=open("report.aut","w")<br />
for elem in reportL:<br />
print elem<br />
elem+='\n'<br />
report.writelines(elem)<br />
report.close()<br />
command2='start keywords.txt'<br />
command3='start report.aut'<br />
os.system(command2)<br />
os.system(command3)<br />
<br />
cmd.extend("pdbsurvey",pdbsurvey)<br />
</source><br />
<br />
Thank you for any feedback, ways of improving it,...</div>Newaccthttps://pymolwiki.org/index.php?title=SuperSymSource&diff=8065SuperSymSource2010-02-23T07:16:37Z<p>Newacct: </p>
<hr />
<div>This page contains source files for the [[SuperSym]] plugin. For documentation and use instructions, see [[SuperSym]].<br />
<br />
==Source Code==<br />
<br />
File: SuperSymPlugin12.py<br />
<source lang="python"><br />
from Tkinter import *<br />
import tkSimpleDialog<br />
import tkMessageBox<br />
import tkColorChooser<br />
import tkFileDialog<br />
import sys<br />
import re<br />
from pymol import stored, cmd, selector<br />
import math<br />
from pymol.cgo import *<br />
from pymol.vfont import plain<br />
try:<br />
from cctbx import sgtbx, uctbx<br />
import numpy as N<br />
from numpy.linalg import *<br />
from cctbx import uctbx, sgtbx<br />
except:<br />
quit("Oops! SuperSym requires cctbx and numeric python to function. Please install these.")<br />
<br />
<br />
def __init__(self):<br />
#MAIN<br />
self.menuBar.addcascademenu('Plugin','SuperSym')<br />
#DEFAULT SET BUILD<br />
self.menuBar.addmenuitem('SuperSym', 'command', 'Default Symmetry Partner Set',<br />
label = 'Default Symmetry Partner Set', <br />
command = lambda s = self: symDialog(s, 0))<br />
#UNIT CELL BUILD<br />
self.menuBar.addmenuitem('SuperSym', 'command', 'Draw Unit Cell',<br />
label = 'Draw Unit Cell', <br />
command = lambda s = self: cellDialog(s))<br />
#SYM SUBMENU<br />
self.menuBar.addcascademenu('SuperSym', 'Build Symmetry Partners')<br />
<br />
self.menuBar.addmenuitem('Build Symmetry Partners', 'command', 'Cell [0,0,0] (default)', <br />
label = 'Cell [0,0,0] (default)', <br />
command = lambda s = self: symDialog(s, 0))<br />
<br />
self.menuBar.addmenuitem('Build Symmetry Partners', 'command', 'Cell [x,y,z] (custom)',<br />
label = 'Cell [x,y,z] (custom)', <br />
command = lambda s = self: symDialog(s, 1))<br />
<br />
self.menuBar.addmenuitem('Build Symmetry Partners', 'command', '2x2x2 Block',<br />
label = '2x2x2 Block', <br />
command = lambda s = self: symDialog(s, 2))<br />
<br />
self.menuBar.addmenuitem('Build Symmetry Partners', 'command', '3x3x3 Block',<br />
label = '3x3x3 Block', <br />
command = lambda s = self: symDialog(s, 3))<br />
<br />
self.menuBar.addmenuitem('Build Symmetry Partners', 'command', 'By Partner',<br />
label = 'By Partner', <br />
command = lambda s = self: symDialog(s, 4))<br />
#COLOR SUBMENU<br />
self.menuBar.addcascademenu('SuperSym', 'Coloring')<br />
<br />
self.menuBar.addmenuitem('Coloring', 'command', 'Default Rainbow',<br />
label = 'Default Rainbow', <br />
command = lambda s = self: colorDialog(s, 0))<br />
<br />
self.menuBar.addmenuitem('Coloring', 'command', 'Select color for each operation',<br />
label = 'Select color for each operation', <br />
command = lambda s = self: colorDialog(s, 1))<br />
<br />
self.menuBar.addmenuitem('Coloring', 'command', 'Select one color for custom set of operations',<br />
label = 'Select one color for custom set of operations', <br />
command = lambda s = self: colorDialog(s, 2))<br />
#GRAPHICS SUBMENU<br />
self.menuBar.addcascademenu('SuperSym', 'Graphics')<br />
<br />
self.menuBar.addmenuitem('Graphics', 'command', 'Lines',<br />
label = 'Lines', <br />
command = lambda s = self: graphicsDialog(s, 0))<br />
<br />
self.menuBar.addmenuitem('Graphics', 'command', 'Ribbon',<br />
label = 'Ribbon', <br />
command = lambda s = self: graphicsDialog(s, 1))<br />
self.menuBar.addmenuitem('Graphics', 'command', 'Cartoon',<br />
label = 'Cartoon',<br />
command = lambda s = self: graphicsDialog(s, 2))<br />
self.menuBar.addmenuitem('Graphics', 'command', 'Sphere Surface (best for printing)',<br />
label = 'Sphere Surface (best for printing)', <br />
command = lambda s = self: graphicsDialog(s, 3))<br />
<br />
self.menuBar.addmenuitem('Graphics', 'command', 'Surface (high load render)',<br />
label = 'Surface (high load render)', <br />
command = lambda s = self: graphicsDialog(s, 4))<br />
#SYM AXES SUBMENU<br />
self.menuBar.addcascademenu('SuperSym', 'Symmetry Axes')<br />
<br />
self.menuBar.addmenuitem('Symmetry Axes', 'command', 'Build Axes',<br />
label = 'Build Axes', <br />
command = lambda s = self: axesDialog(s))<br />
#ADD OTHER SYMMETRY AXES OPTION HERE<br />
self.menuBar.addmenuitem('SuperSym', 'command', 'Move symmetry partners',<br />
label = 'Move symmetry partners',<br />
command = lambda s = self: cellShiftInfo(s))<br />
self.menuBar.addmenuitem('SuperSym', 'command', 'About',<br />
label = 'About',<br />
command = lambda s = self: aboutInfo(s))<br />
self.menuBar.addmenuitem('SuperSym', 'command', 'Help',<br />
label = 'Help',<br />
command = lambda s = self: helpInfo(s))<br />
cmd.cell_shift = cell_shift<br />
cmd.get_operations = get_operations<br />
cmd.get_matrix = get_orthogonalization_matrix<br />
cmd.symset = symset<br />
cmd.cell_shift_helper = cell_shift_helper<br />
cmd.set_key("ALT-6", cell_shift_proxyX1)<br />
cmd.set_key("ALT-4", cell_shift_proxyX2) <br />
cmd.set_key("ALT-8", cell_shift_proxyY1) <br />
cmd.set_key("ALT-2", cell_shift_proxyY2) <br />
cmd.set_key("ALT-5", cell_shift_proxyZ1) <br />
cmd.set_key("ALT-1", cell_shift_proxyZ2)<br />
<br />
<br />
'''<br />
symDialog: Dialog generator and command issuer for generating symmetry partners<br />
<br />
This function is called by SuperSymMenu when any symmetry partner generating option is<br />
selected. It creates dialog windows and receives user input for symmetry generation parameters.<br />
<br />
@app -- identifies the GUI interface to build dialog boxes onto.<br />
@mode -- determines specific treatment of symmetry building command<br />
'''<br />
def symDialog(app, mode):<br />
prefix = tkSimpleDialog.askstring('Prefix',<br />
'Enter desired prefix for these partners:', parent=app.root)<br />
object = tkSimpleDialog.askstring('Object',<br />
'Enter object to generate partners from:', parent=app.root)<br />
if mode == 0: #make default symmetry set in cell [0,0,0]<br />
symset(prefix, object)<br />
if mode == 1: #make symmetry set in custom cell<br />
cell = tkSimpleDialog.askstring('Cell',<br />
'Enter lattice cell coordinates separated by commas (ex:x,y,z):', parent = app.root)<br />
x,y,z = cell.split(',')<br />
x,y,z = int(x),int(y),int(z)<br />
symset(prefix, object, x, y, z)<br />
if mode == 2: #make 2x2x2 block of symmetry sets<br />
for i in range(2):<br />
for j in range(2):<br />
for k in range(2):<br />
symset(prefix, object, i, j, k)<br />
if mode == 3: #make 3x3x3 block of symmetry sets<br />
for i in range(-1,2):<br />
for j in range(-1,2):<br />
for k in range(-1,2):<br />
symset(prefix, object, i, j, k)<br />
if mode == 4: #select individual partners by operation and cell<br />
ops = get_operations(object)<br />
opString = ""<br />
for i,x in enumerate(ops):<br />
opString += str(i) + " : " + x + "\n"<br />
opIndeces = tkSimpleDialog.askstring("Symmetry Operations", opString +<br />
"Enter numbers of desired operations separated by commas (ex:0,2,9)", parent = app.root) <br />
opListStrings = opIndeces.split(",")<br />
opList = []<br />
for op in opListStrings:<br />
opList.append(int(op))<br />
cell = tkSimpleDialog.askstring('Cell',<br />
'Enter lattice cell coordinates separated by commas (ex:x,y,z):', parent = app.root)<br />
x,y,z = cell.split(',')<br />
x,y,z = int(x),int(y),int(z)<br />
symset(prefix, object, x,y,z, opList)<br />
<br />
'''<br />
colorDialog: Dialog generator for coloring commands<br />
<br />
This function colors sets of symmetry partners defined by the user in the<br />
dialog which it generates.<br />
<br />
@app -- identifies root menu calling this function<br />
@mode -- determines coloring scheme to execute<br />
'''<br />
def colorDialog(app, mode):<br />
prefix = tkSimpleDialog.askstring('Prefix',<br />
'Enter the prefix of symmetry partners to color', parent = app.root)<br />
if mode == 0: #standard rainbow by symmetry operation<br />
colors = ["red", "orange", "yellow", "green", "blue", "purple",<br />
"salmon", "grey", "pink", "teal", "brown", "br0", "aquamarine", <br />
"deepolive", "dirtyviolet", "slate", "br4", "darksalmon", "br7",<br />
"chocolate", "firebrick", "brightorange"]<br />
for i in range(20):<br />
try: #required because PyMOL inappropriately throws an exception<br />
#when the cmd.color() function colors no objects<br />
cmd.color(colors[i], "%s%02d*" % (prefix, i))<br />
except:<br />
pass #allows us to move on to next symmetry operator<br />
if mode == 1: #specify for each symmetry operation<br />
cmd.iterate_state(1, prefix + "*", "stored.tmpObject = model")<br />
ops = get_operations(stored.tmpObject)<br />
opString = ""<br />
for i,x in enumerate(ops):<br />
opString += str(i) + " : " + x + "\n"<br />
opIndeces = tkSimpleDialog.askstring("Symmetry Operations", opString +<br />
"Enter numbers of desired operations separated by commas (ex:0,2,9) or all", parent = app.root) <br />
if opIndeces == "all":<br />
opList = []<br />
for i in range(len(ops)):<br />
opList.append(i)<br />
else:<br />
opList = opIndeces.split(",")<br />
opStringList = opString.split("\n")<br />
for i in opList:<br />
try:<br />
cmd.color("white", "%s%02d*" % (prefix, i))<br />
cmd.center("%s%02d*" % (prefix, i))<br />
<br />
except:<br />
pass<br />
tempColor = tkColorChooser.askcolor(title = "Color for " + opStringList[int(i)] + " (currently white)",<br />
parent = app.root)[0]<br />
rgb = []<br />
for value in tempColor:<br />
value = float(value)<br />
value = value/255<br />
rgb.append(value)<br />
cmd.set_color("tempColor", rgb)<br />
try:<br />
cmd.color("tempColor", "%s%02d*" % (prefix, i))<br />
except:<br />
pass<br />
if mode == 2: #monochrome for a set of operations<br />
cmd.iterate_state(1, prefix + "*", "stored.tmpObject = model")<br />
ops = get_operations(stored.tmpObject)<br />
opString = ""<br />
for i,x in enumerate(ops):<br />
opString += str(i) + " : " + x + "\n"<br />
opIndeces = tkSimpleDialog.askstring("Symmetry Operations", opString +<br />
"Enter numbers of desired operations separated by commas (ex:0,2,9) or all", parent = app.root) <br />
if opIndeces == 'all':<br />
opList = []<br />
for i in range(len(ops)):<br />
opList.append(i)<br />
else:<br />
opList = opIndeces.split(",")<br />
opStringList = opString.split("\n")<br />
tempColor = tkColorChooser.askcolor(parent = app.root)[0]<br />
rgb = []<br />
for value in tempColor:<br />
value = float(value)<br />
value = value/255<br />
rgb.append(value)<br />
cmd.set_color("tempColor", rgb)<br />
for i in opList:<br />
try:<br />
cmd.color("tempColor", "%s%02d*" % (prefix, i))<br />
except:<br />
pass<br />
'''<br />
graphicsDialog: Dialog generator for graphics commands<br />
<br />
This function sets visual representations for sets of symmetry partners.<br />
<br />
@app -- identifies root menu<br />
@mode -- determines type of representation to show<br />
'''<br />
def graphicsDialog(app, mode):<br />
prefix = tkSimpleDialog.askstring('Prefix',<br />
'Enter prefix of symmetry partners to display', parent = app.root)<br />
cmd.hide("everything", prefix + "*")<br />
if mode == 0: # show lines<br />
cmd.show("lines", prefix + "*")<br />
if mode == 1: # show ribbon<br />
cmd.show("ribbon", prefix + "*")<br />
if mode == 2: # show cartoon<br />
cmd.show("cartoon", prefix + "*")<br />
if mode == 3: # sphere surface<br />
objSel = prefix + "*"<br />
findSurfaceResidues(objSel, 3.5, "surface")<br />
cmd.set("sphere_scale", 1.8)<br />
cmd.show("spheres", "surface")<br />
if mode == 4: # regular surface<br />
cmd.show("surface", prefix + "*")<br />
<br />
'''<br />
cellDialog: dialog proxy for draw_cell<br />
<br />
This function generates a unit cell representation<br />
FUTURE IMPLEMENTATIONS: select which lattice coordinates to generate unit cell for<br />
<br />
@app -- identifies root menu<br />
'''<br />
def cellDialog(app):<br />
object = tkSimpleDialog.askstring('Object',<br />
'Enter object to generate cell for:', parent = app.root)<br />
if tkMessageBox.askyesno('3D Printing', 'Going to print this model?', parent = app.root):<br />
draw_cell(object, 3.0)<br />
else:<br />
draw_cell(object)<br />
<br />
'''<br />
axesDialog: dialog proxy for draw_symops_cctbx<br />
<br />
This function generates one set of symmetry axes for a given object<br />
FUTURE IMPLEMENTATIONS: select individual axes to generate, attach to model for 3D printing,<br />
generate axes for multiple unit cells<br />
<br />
@app -- identifies root menu<br />
'''<br />
def axesDialog(app):<br />
object = tkSimpleDialog.askstring('Object',<br />
'Enter object to generate symmetry axes for:', parent = app.root)<br />
if tkMessageBox.askyesno('3D Printing', 'Going to print this model?', parent = app.root):<br />
draw_symops(object, 2.0)<br />
else:<br />
draw_symops(object)<br />
<br />
'''<br />
cellShiftInfo: displays info for using cell_shift hotkeys<br />
<br />
@app -- identifies root menu<br />
'''<br />
def cellShiftInfo(app):<br />
tkMessageBox.showinfo('Cell Shifting',<br />
"To shift a symmetry partner, simply click to select any part of it (select only one partner at a time). \n\n" +<br />
"Next, hold ALT and press the numpad key corresponding to the axis direction you\'d like to move. \n\n" +<br />
"Key assignments:\n" +<br />
"A (x) axis: down--4, up--6 \n" +<br />
"B (y) axis: down--2, up--8 \n" +<br />
"C (z) axis: down--1, up--5", parent = app.root)<br />
tkMessageBox.showwarning('Caution', 'Only attempt to shift symmetry partners created by SuperSym.'+<br />
'Attempting to shift any other object will result in errors.')<br />
<br />
def aboutInfo(app):<br />
tkMessageBox.showinfo('About',<br />
'SuperSym \nDeveloped by Stuart Ballard (srballard@wisc.edu)\nDepartment of Biochemistry\n'+<br />
'University of Wisconsin-Madison', parent = app.root)<br />
def helpInfo(app):<br />
tkMessageBox.showinfo('Help',<br />
'For documentation see http://pymolwiki.org/index.php/SuperSym', parent = app.root)<br />
<br />
'''<br />
symset: generates up to one full set of symmetry partners for a given object in a given lattice position<br />
<br />
1. Obtain all essential symmetry information from CCTBX. This includes the space group, unit cell parameters,<br />
and fractional coordinates corresponding to symmetry operations.<br />
2. Generate transformation matrices to translate coordinates from orthogonal to fractional, and back.<br />
3. <br />
'''<br />
def symset(prefix = "sym", object = -1, x=0,y=0,z=0, opList = []):<br />
if object == -1:<br />
object = cmd.get_names()[0]<br />
cell = [float(x),float(y),float(z)]<br />
view = cmd.get_view()<br />
cmd.show("lines", object)<br />
sgInfo = cmd.get_symmetry(object)<br />
raw_ops = []<br />
for s in sgtbx.space_group_info(sgInfo[6]).group():<br />
raw_ops.append(str(s))<br />
if len(opList) == 0:<br />
for i in range(len(raw_ops)):<br />
opList.append(i)<br />
opMatrices = []<br />
vars = ["x","y","z"]<br />
#CREATE 4X4 MATRICES FOR SYMMETRY OPERATORS<br />
for i,raw_op in enumerate(raw_ops):<br />
ops = raw_op.split(",")<br />
matrix = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,1]]<br />
for j in range(len(ops)):<br />
for k in range(len(vars)):<br />
index = ops[j].find(vars[k])<br />
if index != -1:<br />
if index == 0:<br />
matrix[k][j] = 1<br />
elif ops[j][index - 1] == "-":<br />
matrix[k][j] = -1<br />
else:<br />
matrix[k][j] = 1<br />
index = ops[j].find("/")<br />
if index != -1:<br />
matrix[3][j] = float(ops[j][index - 1]) / float(ops[j][index + 1])<br />
opMatrices.append(matrix)<br />
a,b,c,alpha,beta,gamma = sgInfo[0:6]<br />
ca = math.cos(math.radians(alpha))<br />
cb = math.cos(math.radians(beta))<br />
cg = math.cos(math.radians(gamma))<br />
sb = math.sin(math.radians(beta))<br />
sg = math.sin(math.radians(gamma))<br />
fracToOrt = N.array([[a, b * cg, c * cb, 0.0], <br />
[0.0, b * sg, c * (ca - cb * cg) / sg, 0.0], <br />
[0.0, 0.0, c * sb * math.sqrt(1.0 - ((cb * cg - ca) / (sb * sg))**2), 0.0],<br />
[0.0,0.0,0.0,1.0]])<br />
fracToOrt = fracToOrt.transpose()<br />
ortToFrac = inv(fracToOrt)<br />
stored.atoms = []<br />
cmd.iterate_state(1,object,"stored.atoms.append([x,y,z,1])")<br />
stored.atoms = N.array(stored.atoms)<br />
fracCoords = N.dot(stored.atoms,ortToFrac)<br />
for i in opList:<br />
try:<br />
op = opMatrices[i]<br />
except:<br />
print "Bad symmetry partner numbers. Try again."<br />
quit()<br />
copy = "%s%02d_%d_%d_%d" % (prefix, i, x, y, z)<br />
cmd.copy(copy, object)<br />
newCoordsFrac = N.dot(fracCoords, op)<br />
stored.newCoords = N.dot(newCoordsFrac, fracToOrt)<br />
stored.j = 0<br />
cmd.alter_state(1,copy,"x,y,z = stored.newCoords[stored.j][0], stored.newCoords[stored.j][1], stored.newCoords[stored.j][2]; stored.j = stored.j + 1")<br />
xSum=ySum=zSum=0.0<br />
for a,b,c in newCoordsFrac:<br />
xSum += a<br />
ySum += b<br />
zSum += c<br />
center = N.array([xSum,ySum,zSum])<br />
center = center/len(stored.newCoords)<br />
shift = [cell[0]-math.floor(center[0]),<br />
cell[1]-math.floor(center[1]),<br />
cell[2]-math.floor(center[2])]<br />
cell_shift(copy,shift[0],shift[1],shift[2],0)<br />
'''<br />
#COPIES COORDINATES OF EACH ATOM TO CORRESPONDING ONE IN GIVEN SYMMETRY PARTNER<br />
#cmd.alter_state(1, copy, "x,y,z = cmd.sym_partner([x,y,z], stored.tmpOp)")<br />
#MOVES SYMMETRY PARTNER TO PROPER LATTICE COORDINATES AND CORRECTS FOR NATIVE LATTICE POSITION ERROR<br />
#stored.xSum,stored.ySum,stored.zSum = 0.0,0.0,0.0<br />
#atoms = cmd.count_atoms(copy)<br />
#cmd.iterate_state(1, copy, "stored.xSum = stored.xSum + x; stored.ySum = stored.ySum + y; stored.zSum = stored.zSum + z")<br />
#xMean = stored.xSum / atoms<br />
#yMean = stored.ySum / atoms<br />
#zMean = stored.zSum / atoms<br />
#xError, yError, zError = N.dot(N.array([xMean,yMean,zMean]), stored.ortToFrac)<br />
#dX,dY,dZ = cell[0]-math.floor(xError), cell[1]-math.floor(yError), cell[2]-math.floor(zError)<br />
#cell_shift(copy,dX,dY,dZ, 0)<br />
'''<br />
cmd.hide("everything", object)<br />
cmd.set_view(view)<br />
<br />
'''<br />
def sym_partner(coords, op):<br />
fracCoords = N.dot(N.array(coords), stored.ortToFrac)<br />
op = op.replace("x", "(" + str(fracCoords[0]) + ")")<br />
op = op.replace("y", "(" + str(fracCoords[1]) + ")")<br />
op = op.replace("z", "(" + str(fracCoords[2]) + ")")<br />
op = op.split(",")<br />
for i in range(3):<br />
index = op[i].find("/")<br />
if index != -1:<br />
if len(op[i]) == index + 2:<br />
op[i] = op[i][0:index - 1] + str(float(op[i][index - 1]) / float(op[i][index + 1]))<br />
else:<br />
op[i] = op[i][0:index - 1] + str(float(op[i][index - 1]) / float(op[i][index + 1])) + op[i][index + 2:]<br />
op[i] = eval(op[i])<br />
return N.dot(N.array(op), stored.fracToOrt)<br />
'''<br />
<br />
<br />
def cell_shift_proxyX1():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, 1,0,0)<br />
def cell_shift_proxyX2():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, -1,0,0)<br />
def cell_shift_proxyY1():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, 0,1,0)<br />
def cell_shift_proxyY2():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, 0,-1,0)<br />
def cell_shift_proxyZ1():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, 0,0,1)<br />
def cell_shift_proxyZ2():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, 0,0,-1)<br />
<br />
def cell_shift(object, dX, dY, dZ, rename = 1):<br />
if rename:<br />
oldName = object.split("_")<br />
oldPre = oldName[0]<br />
oldX = int(oldName[1])<br />
oldY = int(oldName[2])<br />
oldZ = int(oldName[3])<br />
newX = "_" + str(int(dX) + oldX)<br />
newY = "_" + str(int(dY) + oldY)<br />
newZ = "_" + str(int(dZ) + oldZ)<br />
newName = oldPre + newX + newY + newZ<br />
#if cmd.get_names().find(newName) != -1:<br />
# print "Symmetry partner already exists in destination position!"<br />
# quit()<br />
cmd.set_name(object, newName)<br />
object = newName<br />
stored.shift = [float(dX),float(dY),float(dZ)]<br />
stored.sgInfo = cmd.get_symmetry(object)<br />
a,b,c,alpha,beta,gamma = stored.sgInfo[0:6]<br />
ca = math.cos(math.radians(alpha))<br />
cb = math.cos(math.radians(beta))<br />
cg = math.cos(math.radians(gamma))<br />
sb = math.sin(math.radians(beta))<br />
sg = math.sin(math.radians(gamma))<br />
stored.fracToOrt = N.array([[a, b * cg, c * cb], <br />
[0.0, b * sg, c * (ca - cb * cg) / sg], <br />
[0.0, 0.0, c * sb * math.sqrt(1.0 - ((cb * cg - ca) / (sb * sg))**2)]])<br />
stored.fracToOrt = stored.fracToOrt.transpose()<br />
stored.ortToFrac = inv(stored.fracToOrt)<br />
cmd.cell_shift_helper = cell_shift_helper<br />
cmd.alter_state(1, object, "x,y,z = cmd.cell_shift_helper([x,y,z],stored.shift)")<br />
<br />
def cell_shift_helper(coords, shift):<br />
fracCoords = N.dot(N.array(coords), stored.ortToFrac)<br />
for i in range(3):<br />
fracCoords[i] += shift[i]<br />
coords = N.dot(N.array(fracCoords), stored.fracToOrt)<br />
return coords[0], coords[1], coords[2]<br />
<br />
def get_operations(object):<br />
raw_ops = []<br />
sgInfo = cmd.get_symmetry(object)<br />
for s in sgtbx.space_group_info(sgInfo[6]).group():<br />
raw_ops.append(str(s))<br />
return raw_ops <br />
<br />
def get_orthogonalization_matrix(object, quiet = 0):<br />
a,b,c,alpha,beta,gamma = cmd.get_symmetry(object)[0:6]<br />
ca = math.cos(math.radians(alpha))<br />
cb = math.cos(math.radians(beta))<br />
cg = math.cos(math.radians(gamma))<br />
sb = math.sin(math.radians(beta))<br />
sg = math.sin(math.radians(gamma))<br />
fracToOrt = N.array([[a, b * cg, c * cb], <br />
[0.0, b * sg, c * (ca - cb * cg) / sg], <br />
[0.0, 0.0, c * sb * math.sqrt(1.0 - ((cb * cg - ca) / (sb * sg))**2)]])<br />
if not quiet:<br />
print fracToOrt<br />
print inv(fracToOrt)<br />
return fracToOrt<br />
<br />
# -*- coding: utf-8 -*-<br />
def findSurfaceResidues(objSel="(all)", cutoff=2.5, selName = 0):<br />
"""<br />
findSurfaceResidues<br />
finds those residues on the surface of a protein<br />
that have at least 'cutoff' exposed A**2 surface area.<br />
<br />
PARAMS<br />
objSel (string)<br />
the object or selection in which to find<br />
exposed residues<br />
DEFAULT: (all)<br />
<br />
cutoff (float)<br />
your cutoff of what is exposed or not. <br />
DEFAULT: 2.5 Ang**2<br />
<br />
asSel (boolean)<br />
make a selection out of the residues found<br />
<br />
RETURNS<br />
(list: (chain, resv ) )<br />
A Python list of residue numbers corresponding<br />
to those residues w/more exposure than the cutoff.<br />
<br />
"""<br />
tmpObj="__tmp"<br />
cmd.create( tmpObj, objSel + " and polymer");<br />
cmd.set("dot_solvent");<br />
cmd.get_area(selection=tmpObj, load_b=1)<br />
<br />
# threshold on what one considers an "exposed" atom (in A**2):<br />
cmd.remove( tmpObj + " and b < " + str(cutoff) )<br />
<br />
stored.tmp_dict = {}<br />
cmd.iterate(tmpObj, "stored.tmp_dict[(chain,resv)]=1")<br />
exposed = stored.tmp_dict.keys()<br />
exposed.sort()<br />
<br />
cmd.select(selName, objSel + " in " + tmpObj )<br />
cmd.delete(tmpObj)<br />
<br />
return exposed<br />
<br />
#CELL DRAWING<br />
<br />
def set_to_zero(a):<br />
if abs(a) < 1e-10:<br />
a=0<br />
return a<br />
<br />
def draw_cell(obj,radius=1.0,mode=0):<br />
"""<br />
From pymol issue the "run draw_cell.py" command to load the script,<br />
then issue the "draw_cell(object,<optional radius>)" command <br />
to actually run it and create the cgo object showing the unit cell<br />
border for the space group specified by molecular object 'object'.<br />
<br />
e.g. load 1avv.pdb<br />
run draw_cell.py<br />
draw_cell 1avv 0.5 (or draw_cell('1avv',.5))<br />
<br />
see also help(draw_cell_param) to draw the cell border for <br />
user-defined cell dimensions (i.e. not loaded from a pdb file)<br />
<br />
See also "help(draw_cell_param) to draw the cell border by<br />
specifying the unit cell parameters directly (i.e. not loaded from<br />
a pdb file).<br />
"""<br />
radius=float(radius)<br />
cell_info=cmd.get_symmetry(obj)<br />
draw_cell_param(cell_info[0:6],radius,mode)<br />
<br />
def draw_cell_param(cell_param_list,radius=1.0,mode=0):<br />
"""<br />
If you wish to draw the unit cell border for any cell without the<br />
need to load a pdb file, then do this:<br />
<br />
e.g. run draw_cell.py<br />
draw_cell_param((45.2,45.2,70.8,90.,90.,120.),0.5)<br />
<br />
to generate the cell border for this trigonal space group "p 31 2 1"<br />
with a radius of 0.5A. Labels for the origin, and A, B and C axes<br />
will appear as well. The perimeter of the cell is colored with the<br />
RGB components corresponding to the A,B,C components.<br />
"""<br />
<br />
U=uctbx.unit_cell((cell_param_list))<br />
<br />
vert_000 = map(set_to_zero,U.orthogonalize((0.,0.,0)))<br />
vert_100 = map(set_to_zero,U.orthogonalize((1.,0.,0)))<br />
vert_010 = map(set_to_zero,U.orthogonalize((0.,1.,0)))<br />
vert_001 = map(set_to_zero,U.orthogonalize((0.,0.,1)))<br />
vert_110 = map(set_to_zero,U.orthogonalize((1.,1.,0)))<br />
vert_011 = map(set_to_zero,U.orthogonalize((0.,1.,1)))<br />
vert_101 = map(set_to_zero,U.orthogonalize((1.,0.,1)))<br />
vert_111 = map(set_to_zero,U.orthogonalize((1.,1.,1)))<br />
<br />
# vert_000 = map(None,U.orthogonalize((0.,0.,0)))<br />
# vert_100 = map(None,U.orthogonalize((1.,0.,0)))<br />
# vert_010 = map(None,U.orthogonalize((0.,1.,0)))<br />
# vert_001 = map(None,U.orthogonalize((0.,0.,1)))<br />
# vert_110 = map(None,U.orthogonalize((1.,1.,0)))<br />
# vert_011 = map(None,U.orthogonalize((0.,1.,1)))<br />
# vert_101 = map(None,U.orthogonalize((1.,0.,1)))<br />
# vert_111 = map(None,U.orthogonalize((1.,1.,1)))<br />
<br />
#print vert_000<br />
<br />
#CYLINDER = ['CYLINDER']<br />
#radius = [0.2]<br />
#print radius<br />
cell = [] <br />
cell.append(CYLINDER)<br />
cell.extend(vert_000 + vert_100 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_000 + vert_010 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_000 + vert_001 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_100 + vert_110 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_100 + vert_101 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_010 + vert_110 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_010 + vert_011 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_001 + vert_101 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_001 + vert_011 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_110 + vert_111 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_101 + vert_111 + [radius] + [1,1,1] + [1,1,1])<br />
cell.append(CYLINDER)<br />
cell.extend(vert_011 + vert_111 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(SPHERE)<br />
cell.extend(vert_000 + [radius])<br />
cell.append(SPHERE)<br />
cell.extend(vert_001 + [radius])<br />
cell.append(SPHERE)<br />
cell.extend(vert_010 + [radius])<br />
cell.append(SPHERE)<br />
cell.extend(vert_011 + [radius])<br />
cell.append(SPHERE)<br />
cell.extend(vert_100 + [radius])<br />
cell.append(SPHERE)<br />
cell.extend(vert_101 + [radius])<br />
cell.append(SPHERE)<br />
cell.extend(vert_110 + [radius])<br />
cell.append(SPHERE)<br />
cell.extend(vert_111 + [radius])<br />
<br />
cmd.load_cgo(cell,"cell")<br />
#return cell<br />
<br />
if mode == 1:<br />
text = [COLOR, 1.0, 0.0, 1.0,]<br />
<br />
#wire_text(text,plain,[-5.,-5.,-1],'Origin',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])<br />
#wire_text(text,plain,map(None,U.orthogonalize((1.05,0.0,0.0))),'A',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])<br />
#wire_text(text,plain,map(None,U.orthogonalize((0.0,1.05,0.0))),'B',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])<br />
#wire_text(text,plain,map(None,U.orthogonalize((0.0,0.0,1.05))),'C',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])<br />
<br />
cyl_text(text,plain,[-5.,-5.,-1],'Origin',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[1.0,0.0,1.0])<br />
cyl_text(text,plain,map(None,U.orthogonalize((1.05,0.0,0.0))),'A',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[1.0,0.0,0.0])<br />
cyl_text(text,plain,map(None,U.orthogonalize((0.0,1.05,0.0))),'B',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[0.0,1.0,0.0])<br />
cyl_text(text,plain,map(None,U.orthogonalize((0.0,0.0,1.05))),'C',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[0.0,0.0,1.0])<br />
<br />
cmd.load_cgo(text,'text')<br />
<br />
<br />
#AXES DRAWING<br />
#! /usr/bin/env python<br />
# Copyright (c) 2004 Robert L. Campbell<br />
<br />
#import math<br />
<br />
def set_to_zero(a):<br />
if abs(a) < 1e-10:<br />
a=0<br />
return a<br />
<br />
def draw_symbol(start,end,symb,color,radius=0.2):<br />
degtorad = N.pi/180.<br />
costhirty = N.cos(30.0*degtorad)<br />
sinthirty = N.sin(30.0*degtorad)<br />
symb_obj = []<br />
<br />
if symb in ('2', '2^1'):<br />
pass<br />
<br />
elif symb in ('3', '3^1', '3^2'):<br />
symb_obj = [ BEGIN, TRIANGLES, COLOR ] + color<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([start]) + N.array([radius, 0, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([start]) + N.array([-radius*sinthirty, radius*costhirty, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([start]) + N.array([-radius*sinthirty, -radius*costhirty, 0]))[0].tolist())<br />
<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([end]) + N.array([radius, 0, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([end]) + N.array([-radius*sinthirty, radius*costhirty, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([end]) + N.array([-radius*sinthirty, -radius*costhirty, 0]))[0].tolist())<br />
symb_obj.append(END)<br />
<br />
elif symb in ('4', '4^1', '4^2', '4^3'):<br />
symb_obj = [ BEGIN, TRIANGLES, COLOR ] + color<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([start]) + N.array([radius, radius, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([start]) + N.array([-radius, radius, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([start]) + N.array([-radius, -radius, 0]))[0].tolist())<br />
<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([start]) + N.array([radius, radius, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([start]) + N.array([radius, -radius, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([start]) + N.array([-radius, -radius, 0]))[0].tolist())<br />
<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([end]) + N.array([radius, radius, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([end]) + N.array([-radius, radius, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([end]) + N.array([-radius, -radius, 0]))[0].tolist())<br />
<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([end]) + N.array([radius, radius, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([end]) + N.array([radius, -radius, 0]))[0].tolist())<br />
symb_obj.append(VERTEX)<br />
symb_obj.extend((N.array([end]) + N.array([-radius, -radius, 0]))[0].tolist())<br />
symb_obj.append(END)<br />
<br />
elif symb in ('6', '6^1', '6^2', '6^3', '6^4', '6^5'):<br />
# hexagons still need to be created :)<br />
pass<br />
<br />
return symb_obj<br />
<br />
def draw_symops(obj,radius=0.2,extension=0):<br />
"""<br />
From pymol issue the "run draw_symops_cctbx.py" command to load the script,<br />
then issue the "draw_symops(object,<optional radius>,<optional extension>)" command <br />
to actually run it and create the cgo object.<br />
<br />
e.g. load 1avv.pdb<br />
run draw_symops_cctbx.py<br />
draw_symops 1avv, 0.5, .2 <br />
or draw_symops('1avv',.5,.2)<br />
or draw_symops 1avv, radius=.5, extension=.2<br />
<br />
The different axis types appear as different objects on the PyMOL menu so they can be turned<br />
on and off individually.<br />
<br />
See also help(draw_symops_param) to draw operators by specifying the space group <br />
and cell dimensions directly (i.e. not loaded from a pdb file)<br />
<br />
The 'extension' parameter is a fractional increase in the length of each symmetry<br />
operator axis drawn. i.e. a value of 0 is the default and a value of .2 increases<br />
the length by 20% at each end<br />
"""<br />
radius=float(radius)<br />
extension=float(extension)<br />
cell_info=cmd.get_symmetry(obj)<br />
draw_symops_param(cell_info[0:6],cell_info[6],radius,extension)<br />
<br />
def draw_symops_param(cell_param_list,sg,radius=0.2,extension=0):<br />
"""<br />
If you wish to draw the symmetry operators for any cell without the need to load a<br />
pdb file, then do this:<br />
<br />
e.g. run draw_symops_cctbx.py<br />
draw_symops_param((45.2,45.2,70.8,90.,90.,120.),'p3121',0.5,0.1)<br />
<br />
to generate the symmetry operators for this trigonal space group "p 31 2 1"<br />
of radius .5 with 10% added as an extension at each end.<br />
"""<br />
radius=float(radius)<br />
extension=float(extension)<br />
<br />
U=uctbx.unit_cell((cell_param_list))<br />
<br />
#rotation axes<br />
# "2" "yellow",<br />
# "3" "orange",<br />
# "4" "mauve",<br />
# "6" "purple",<br />
<br />
#screw axes (all sub_1 axes are green)<br />
# "21" "green",<br />
# "31" "green",<br />
# "32" "lime",<br />
# "41" "green",<br />
# "42" "cyan",<br />
# "43" "iceblue",<br />
# "61" "green",<br />
# "62" "silver",<br />
# "63" "cyan",<br />
# "64" "iceblue",<br />
# "65" "blue",<br />
<br />
color = {<br />
"2" : [1.0, 1.0, 0.0],<br />
"3" : [1.0, 0.5, 0.0],<br />
"4" : [1.0, 0.5, 1.0],<br />
"6" : [1.0, 0.0, 1.0],<br />
"2^1" : [0.0, 1.0, 0.0],<br />
"3^1" : [0.0, 1.0, 0.0],<br />
"3^2" : [0.5, 1.0, 0.5],<br />
"4^1" : [0.0, 1.0, 0.0],<br />
"4^2" : [0.0, 1.0, 1.0],<br />
"4^3" : [0.5, 0.5, 1.0],<br />
"6^1" : [0.0, 1.0, 0.0],<br />
"6^2" : [0.8, 0.8, 0.8],<br />
"6^3" : [0.0, 1.0, 1.0],<br />
"6^4" : [0.5, 0.5, 1.0],<br />
"6^5" : [0.0, 0.0, 1.0],<br />
}<br />
<br />
sg = sg.upper()<br />
symop_axes = get_all_axes(sg,extension=extension)<br />
<br />
#CYLINDER = 'CYLINDER'<br />
ax_obj = {}<br />
#vert_obj = []<br />
<br />
#debug_out = open('debug.log','w')<br />
<br />
if symop_axes:<br />
for ax in symop_axes:<br />
#print ax<br />
start = map(set_to_zero,U.orthogonalize(list(ax['start'])))<br />
end = map(set_to_zero,U.orthogonalize(list(ax['end'])))<br />
###############################################################################<br />
# Tried rounding off start and end values in order to understand why axes go <br />
# missing in the drawing, but seem to be present in the cgo. Doesn't help!<br />
# e.g. for space group 'p23' one of the 3-fold rotations is missing (0,0,0 -> x,-x,x)<br />
# changing one cell axis to something ever so slightly different recovers the axis<br />
# e.g. set cell to be (30.00001,30.,30.,90.,90.,90) and it works!<br />
# start = map(lambda x: round(x,3),U.orthogonalize(ax['start']))<br />
# end = map(lambda x: round(x,3),U.orthogonalize(ax['end']))<br />
###############################################################################<br />
symb_ax = ax['symb']<br />
color_ax = color[symb_ax]<br />
<br />
#print "axis: ",symb_ax, start, end<br />
if symb_ax in ax_obj:<br />
ax_obj[symb_ax].append(CYLINDER)<br />
else:<br />
ax_obj[symb_ax] = [CYLINDER]<br />
<br />
ax_obj[symb_ax].extend(start + end + [radius])<br />
ax_obj[symb_ax].extend(color[symb_ax] + color[symb_ax])<br />
ax_obj[symb_ax].extend(draw_symbol(start,end,symb_ax,color[symb_ax],radius*6.))<br />
<br />
# #######################################################################################<br />
# # Debugging output to try to understand why some axes go missing in the drawing.<br />
# # They don't appear to be missing from the cgo object, though!<br />
# for xxx in ax_obj[symb_ax]:<br />
# if xxx == 9.0:<br />
# #print "\n\n",xxx<br />
# xxx = "\n\n" + str(xxx) + " "<br />
# debug_out.write(xxx)<br />
# else:<br />
# #print xxx<br />
# #xxx = "\n" + str(xxx) + " "<br />
# xxx = str(xxx) + " "<br />
# debug_out.write(xxx)<br />
# #print ax_obj[symb_ax]<br />
# debug_out.write("\n\n")<br />
# big_string = str(ax_obj)<br />
# debug_out.write(big_string)<br />
# # End of debugging output<br />
# #######################################################################################<br />
<br />
else:<br />
print "\nNo symmetry axes found for this space group: %s\n" % sg<br />
<br />
for key,val in ax_obj.items():<br />
name=sg + "_" + key<br />
cmd.load_cgo(val,name)<br />
#debug_out.write("\n\n" + key + "\n" + str(val))<br />
#return ax_obj<br />
<br />
#cmd.extend("draw_symops_param",draw_symops_param)<br />
<br />
#! /usr/bin/env python<br />
# List all axes in the unit cell.<br />
<br />
# usage:<br />
# python all_axes.py - show axes for the 230 reference settings.<br />
# python all_axes.py P2 - show axes for (e.g.) space group P2<br />
<br />
# RWGK = Ralf W. Grosse-Kunstleve<br />
# RWGK Some further refinement is required:<br />
# RWGK - List only the axes of highest order (e.g. only 4, not 4 and 2).<br />
# RWGK - List only the axes with the smallest intrinsic component<br />
# RWGK (e.g. list only 3(1), not both 3(1) and 3(2)).<br />
# RWGK See also: comment regarding shift_range below.<br />
<br />
def list_plus(lhs, rhs):<br />
return [l + r for l, r in zip(lhs, rhs)]<br />
<br />
def list_minus(lhs, rhs):<br />
return [l - r for l, r in zip(lhs, rhs)]<br />
<br />
def list_multiplies(lhs, rhs):<br />
return [l * r for l, r in zip(lhs, rhs)]<br />
<br />
def list_divides(lhs, rhs):<br />
return [l / r for l, r in zip(lhs, rhs)]<br />
<br />
def list_modulus(lhs, rhs):<br />
return [l % r for l, r in zip(lhs, rhs)]<br />
<br />
def list_dot_product(lhs, rhs=0):<br />
if rhs == 0: rhs = lhs<br />
result = 0<br />
for l, r in zip(lhs, rhs): result += l * r<br />
return result<br />
<br />
def str_ev(EV):<br />
return "[%d,%d,%d]" % EV<br />
<br />
###def fract_2_dec(fraction):<br />
### list = fraction.split('/')<br />
### if len(list) == 2 and list[1] != 0:<br />
### decimal = float(list[0])/float(list[1])<br />
### else:<br />
### decimal = float(fraction)<br />
### return decimal<br />
<br />
def rlc_RTMxAnalysis(M):<br />
r_info = sgtbx.rot_mx_info(M.r())<br />
t_info = sgtbx.translation_part_info(M)<br />
t_intrinsic = t_info.intrinsic_part().mod_positive().as_double()<br />
t_shift = t_info.origin_shift().mod_positive().as_double()<br />
<br />
#End = list_plus(Start + map(None,r_info.ev()))<br />
####debug<br />
### trans = 0<br />
### length = 0<br />
####debug<br />
<br />
#if r_info.type() == 1:<br />
if r_info.type() < 2:<br />
#(rt, start, end) = ('1',(0,0,0),(0,0,0))<br />
return None<br />
#elif r_info.type() == -1:<br />
# (rt, start, end) = (str(r_info.type()),t_shift,())<br />
elif abs(r_info.type()) == 2:<br />
trans = sum(t_intrinsic)<br />
if trans == 0:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
(rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r)))<br />
#(rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r_info.ev())))<br />
else:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
(rt, start, end) = (str(r_info.type())+"^1",t_shift,tuple(list_plus(t_shift,r)))<br />
#(rt, start, end) = (str(r_info.type())+"^1",t_shift,tuple(list_plus(t_shift,r_info.ev())))<br />
elif r_info.type() == 3:<br />
if r_info.sense() >= 0 :<br />
# ignore opposite sense of rotation axes since they superimpose<br />
trans = N.sqrt(sum((map(lambda x,y:(y-x)*(y-x),(0,0,0),t_intrinsic))))<br />
# trans = N.sqrt(t_intrinsic[0]**2 + t_intrinsic[1]**2 + t_intrinsic[2]**2)<br />
if trans == 0:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
# fudge to make sure that PyMOL actually draws the axis (move it slightly off [1,-1,1]) !!!<br />
r[0] = r[0]*1.000001<br />
(rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r)))<br />
#(rt, start, end) = (str(r_info.type()),t_shift, tuple(list_plus(t_shift,r_info.ev())))<br />
else:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
#(rt, start, end) = (str(r_info.type())+ "^" + subscript ,t_shift,tuple(list_plus(t_shift,r)))<br />
(start, end) = (t_shift,tuple(list_plus(t_shift,r)))<br />
length = N.sqrt(sum((map(lambda x,y:(y-x)*(y-x),start, end))))<br />
<br />
# r_info.sense() for 3^1 and 3^2 seems always to be "1" ???<br />
# if r_info.sense() < 0:<br />
# subscript = str(1-r_info.sense())<br />
# else:<br />
# subscript = str(r_info.sense())<br />
<br />
# use ratio of trans to length to get the correct axis symbol:<br />
# fudged the value to get the right numbers. (using length/2., rather than length/3.)<br />
if trans < length*0.5 :<br />
subscript = '1'<br />
else:<br />
subscript = '2'<br />
<br />
rt = str(r_info.type())+ "^" + subscript <br />
#(rt, start, end) = (str(r_info.type()) + "^" + subscript,t_shift, tuple(list_plus(t_shift,r_info.ev())))<br />
### print "Type, sense, Start, End, length, trans", rt, r_info.sense(), start, end, length, trans<br />
# print "type: %s, sense: %s, trans: %s, length: %s," % (r_info.type(), r_info.sense(), trans, length)<br />
# print "(rt, start, end)", (rt,start,end)<br />
else:<br />
return None<br />
#return (r_info.type(),r_info.ev(), t_intrinsic, t_shift)<br />
elif r_info.sense() > 0:<br />
# ignore opposite sense of rotation axes since they superimpose<br />
trans = sum(t_intrinsic)<br />
if trans == 0:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
(rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r)))<br />
#(rt, start, end) = (str(r_info.type()),t_shift, tuple(list_plus(t_shift,r_info.ev())))<br />
else:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
subscript = str(int(trans*r_info.type()+.5)) # add 0.5 to fix rounding errors<br />
(rt, start, end) = (str(r_info.type())+ "^" + subscript ,t_shift,tuple(list_plus(t_shift,r)))<br />
#(rt, start, end) = (str(r_info.type()) + "^" + subscript,t_shift, tuple(list_plus(t_shift,r_info.ev())))<br />
#return (r_info.type(),r_info.ev(), t_intrinsic, t_shift)<br />
else:<br />
return None<br />
# print "type: %s, sense: %s, trans: %s, length: %s," % (r_info.type(), r_info.sense(), trans, length),<br />
# print "(rt, start, end)", (rt,start,end)<br />
return (rt, start, end)<br />
<br />
def get_all_axes(space_group_symbol=None, space_group_info=None, extension=0):<br />
assert space_group_symbol is None or space_group_info is None<br />
shift_range = 1 # RWGK Works for the 230 reference settings; it is not<br />
# RWGK clear to me (rwgk) what value is needed in general.<br />
if space_group_symbol is not None:<br />
space_group_info = sgtbx.space_group_info(symbol=space_group_symbol)<br />
#space_group_info.show_summary()<br />
<br />
axes_dict = {}<br />
for smx in space_group_info.group():<br />
r = smx.r()<br />
t = smx.t()<br />
shift = [0,0,0]<br />
for shift[0] in range(-shift_range,shift_range+1):<br />
for shift[1] in range(-shift_range,shift_range+1):<br />
for shift[2] in range(-shift_range,shift_range+1):<br />
ts = t.plus(sgtbx.tr_vec(shift, 1)).new_denominator(t.den())<br />
m = sgtbx.rt_mx(r, ts)<br />
#print m<br />
rtmxanal = rlc_RTMxAnalysis(m)<br />
#print r, t, shift, ts, m<br />
if rtmxanal:<br />
#print rtmxanal<br />
axes_dict[rtmxanal] = 0<br />
axes_list = axes_dict.keys()<br />
axes_list.sort()<br />
<br />
# reject nonenantiomorphic space groups<br />
if len(axes_list) > 0 and not re.compile("[A-z]").search(space_group_symbol[1:]):<br />
try:<br />
sgtbx.space_group_info(space_group_symbol).show_summary(), <br />
#print len(axes_list), space_group_symbol<br />
except:<br />
print space_group, space_group_symbol<br />
print<br />
sys.exit(1)<br />
axes = []<br />
for a in axes_list:<br />
if len(a) == 3 and len(a[1]) == 3 and len(a[2]) == 3:<br />
tmp_dict = {}<br />
print "%4s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f " % (a[0],a[1][0],a[1][1],a[1][2],a[2][0],a[2][1],a[2][2])<br />
tmp_dict['symb'] = a[0]<br />
start_array = N.asarray(a[1])<br />
end_array = N.asarray(a[2])<br />
start_vec = start_array - (end_array - start_array)*extension<br />
end_vec = end_array + (end_array - start_array)*extension<br />
tmp_dict['start'] = start_vec<br />
tmp_dict['end'] = end_vec<br />
#rlc# tmp_dict['start'] = a[1]<br />
#rlc# tmp_dict['end'] = a[2]<br />
axes.append(tmp_dict)<br />
else:<br />
print a<br />
else:<br />
return None<br />
<br />
return axes<br />
<br />
if __name__ == "__main__":<br />
import sys<br />
if len(sys.argv) == 1:<br />
for i in range(230):<br />
get_all_axes(i + 1)<br />
else:<br />
for symbol in sys.argv[1:]:<br />
get_all_axes(symbol)<br />
</source></div>Newaccthttps://pymolwiki.org/index.php?title=Findseq&diff=8064Findseq2010-02-23T06:49:48Z<p>Newacct: </p>
<hr />
<div>= Overview & Motivation =<br />
Anyone ever give you a protein and then say, find the sequence "FLVEW"? Well, this script will find any string or regular expression in a given object and return that selection for you. Here's an example,<br />
<source lang="python"><br />
# fetch two sugar-binding PDB<br />
fetch 1tvn<br />
# Now, find FATEW in 1tvn, similarly<br />
findSeq FATEW, 1tvn<br />
# lower-case works, too<br />
findSeq fatew, 1tvn<br />
# how about a regular expression?<br />
findSeq F.*W, 1tvn<br />
<br />
# Find the regular expression:<br />
# ..H[TA]LVWH<br />
# in the few proteins loaded.<br />
# I then showed them as sticks and colored them to highlight matched AAs<br />
for x in cmd.get_names(): seqFinder( "..H[TA]LVWH", x, "sele_"+x, firstOnly=1 )<br />
</source><br />
<br />
[[Image:SeqFinder.png|center|thumb|400px|Red residues were those matching the regular expression '..H[TA]LVWH'.]]<br />
<br />
= Usage =<br />
I built this to be rather flexible. You call it as:<br />
<source lang="python">findSeq needle, haystack[, selName[, het[, firstOnly ]]]</source> where the options are:<br />
:: '''needle''' the sequence of amino acids to find. Should be a string of one letter amino acid abbreviations. Can also be a string-style regular expression (eg. FW.*QQ).<br />
:: '''haystack''' the PyMOL object or selection in which to search<br />
:: '''selName''' the name of the returned selection. If you leave this blank, it'll be ''foundSeqXYZ'' where XYZ is some random integer (eg. foundSeq1435); if you supply ''sele'' then the usual PyMOL ''(sele)'' is used; and, finally, if it's anything else, then that will be used verbatim. Defaults to ''foundSeqXYZ'' so as not to overwrite any selections you might have in ''sele''.<br />
:: '''het''' 0/1 -- if 0 then heteroatoms are not considered; if 1 then they are; defaults to 0<br />
:: '''firstOnly''' 0/1 -- if 0 then all matches are selected and returned; if 1 then only the first is returned<br />
<br />
= The Code =<br />
<source lang="python"><br />
# -*- coding: utf-8 -*-<br />
#<br />
# -- seqFinder.py<br />
#<br />
# Finds given amino acids in a protein & returns the selection.<br />
#<br />
#<br />
import re<br />
import types<br />
import random<br />
<br />
import pymol<br />
from pymol import stored<br />
<br />
def checkParams(needle,haystack,selName,het,firstOnly):<br />
"""<br />
This is just a helper function for checking the user input<br />
"""<br />
# check Needle<br />
if len(needle)==0 or type(needle)!=types.StringType:<br />
print "Error: Please provide a string 'needle' to search for."<br />
print "Error: For help type 'help motifFinder'."<br />
return False<br />
<br />
# check Haystack<br />
if len(haystack)==0 or type(haystack)!=types.StringType:<br />
print "Error: Please provide valid PyMOL object or selection name"<br />
print "Error: in which to search."<br />
print "Error: For help type 'help motifFinder'."<br />
return False<br />
<br />
# check het<br />
try:<br />
het = bool(int(het))<br />
except ValueError:<br />
print "Error: The 'het' parameter was not 0 or 1."<br />
return False<br />
<br />
# check first Only<br />
try:<br />
firstOnly = bool(int(het))<br />
except ValueError:<br />
print "Error: The 'firstOnly' parameter was not 0 or 1."<br />
return False<br />
<br />
# check selName<br />
if type(selName)!=types.StringType:<br />
print "Error: selName was not a string."<br />
return False<br />
<br />
return True<br />
<br />
<br />
def seqFinder(needle, haystack, selName=None, het=0, firstOnly=0):<br />
"""<br />
DESCRIPTION:<br />
Given a sequence/regex to find, select those<br />
matching amino acids in the protein.<br />
<br />
USAGE:<br />
seqFinder needle, haystack[, selName[, het[, firstOnly]]]<br />
<br />
PARAMS:<br />
needle (string)<br />
the sequence of amino acids to match and select<br />
in the haystack. This can be a sequence of amino<br />
acids, or a string-style regular expression. See<br />
examples.<br />
<br />
hastack (string or PyMOL selection)<br />
name of the PyMOL object/selection in which <br />
to find the needle.<br />
<br />
selName (string; defaults to None)<br />
This is the name of the selection to return. If selName<br />
is left blank (None), then the selection name will be<br />
foundSeqXYZ where XYZ is some random number; if selName is<br />
"sele" the usual PyMOL "(sele)" will be used; and, lastly,<br />
if selName is anything else, that name will be used verbatim.<br />
<br />
het (0 or 1; defaults to 0)<br />
This boolean flag allows (1) or disallows (0) heteroatoms<br />
from being considered.<br />
<br />
firstOnly (0 or 1; defaults to 0)<br />
Subsequences or motifs might be repeated, this controls how we<br />
consider multiple matches. If firstOnly is False (0) then we return<br />
all found subsequences; if firstOnly is True (1), then we just return<br />
the first found sequence.<br />
<br />
RETURNS:<br />
a newly created selection with the atoms you sought. If there are<br />
more than two contiguous regions, then a newly created group is<br />
returned with each contiguous segment its own selection.<br />
<br />
EXAMPLE:<br />
# find SPVI in 1h12, foundSeqXYZ as return name<br />
seqFinder SPVI, 1h12<br />
<br />
# find FATEW and make it (sele).<br />
seqFinder FATEW, 1g01, sele<br />
<br />
# find the regular expression GMS.*QWY in 1a3h<br />
# and put the return value in (sele).<br />
fetch 1a3h<br />
# this ends up finding the sequence, GMSSHGLQWY<br />
seqFinder GMS.*QWY, 1a3h, sele<br />
<br />
NOTES:<br />
Assumes we're using the ONE LETTER amino acid abbreviations.<br />
<br />
AUTHOR:<br />
Jason Vertrees, 2009.<br />
<br />
"""<br />
# input checking<br />
if not checkParams(needle, haystack, selName, het, firstOnly):<br />
print "There was an error with a parameter. Please see"<br />
print "the above error message for how to fix it."<br />
return None<br />
<br />
one_letter ={'VAL':'V', 'ILE':'I', 'LEU':'L', 'GLU':'E', 'GLN':'Q', \<br />
'ASP':'D', 'ASN':'N', 'HIS':'H', 'TRP':'W', 'PHE':'F', 'TYR':'Y', \<br />
'ARG':'R', 'LYS':'K', 'SER':'S', 'THR':'T', 'MET':'M', 'ALA':'A', \<br />
'GLY':'G', 'PRO':'P', 'CYS':'C'}<br />
<br />
# remove hetero atoms (waters/ligands/etc) from consideration?<br />
if het:<br />
cmd.select( "__h", "br. " + haystack )<br />
else:<br />
cmd.select( "__h", "br. " + haystack + " and not het" )<br />
<br />
# get the AAs in the haystack<br />
aaDict = { 'aaList' : [] }<br />
cmd.iterate("(name ca) and __h","aaList.append((resi,resn))",space=aaDict)<br />
<br />
IDs = map( lambda x: int(x[0]), aaDict['aaList'] )<br />
AAs = ''.join(map( lambda x: one_letter[x[1]], aaDict['aaList'] ))<br />
<br />
reNeedle = re.compile( needle.upper() )<br />
it = reNeedle.finditer( AAs )<br />
<br />
# set the name of the selection to return.<br />
if selName == None:<br />
rSelName = "foundSeq" + str(random.randint(0,32000))<br />
elif selName == "sele":<br />
rSelName = "sele"<br />
else:<br />
rSelName = selName<br />
<br />
# make an empty selection to which we add residues<br />
cmd.select( rSelName, 'None')<br />
<br />
for i in it:<br />
(start,stop) = i.span()<br />
cmd.select( rSelName, rSelName + " __h and i. " + str(IDs[start]) + "-" + str(IDs[stop-1]))<br />
if int(firstOnly):<br />
break<br />
<br />
cmd.delete("__h")<br />
return rSelName<br />
<br />
cmd.extend("seqFinder", seqFinder )<br />
</source><br />
<br />
[[Category:Script_Library]]<br />
[[Category:ObjSel_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Slerpy&diff=8040Slerpy2010-02-07T00:58:52Z<p>Newacct: </p>
<hr />
<div>= Manual for Slerpy.py =<br />
<br />
An extension to pymol that creates a moderately easy to use environment for doing keyframe animation. <br />
<br />
<br />
==General Use==<br />
<br />
At the pymol command line type:<br />
<br />
import slerpy<br />
<br />
This will load the extended commands. All commands in slerpy begin with the letter s. Pymol's tab autocomplete feature will work on the additional commands.<br />
<br />
==Important concepts==<br />
<br />
The main function of slerpy is to record a series of pymol views. A movie can then be created by interpolating between these views. A pymol view consists mostly of the camera orientation (that is, the orientation of the viewers eye with respect to the molecule). It also includes information about the clipping planes.<br />
<br />
It is important to realize that most slerpy commands act on the "current" view. You can navigate among views by using the sn, sp, and sgo commands. If you've changed the view around with the mouse or you just want to know the number of the current view you can get back to the current view with the sc command.<br />
<br />
Pymol views do not contain information about how pymol objects and selections are displayed. If you just want to create a movie which moves around a single representation of a molecule then all you need to do is record the set of views that define the tour of the molecule.<br />
<br />
If, on the other hand, you want to change the representation or change which items are displayed you will need to add actions to some of your views. An action is any set of pymol commands. Actions can be associated with any view in the series recorded by slerpy. The ''sscene'' command inserts a new view and simultaneously creates a pymol scene and the action to display it. The scene will include all of the objects and representations visible at the time the command was issued.<br />
<br />
In order to control the rate of motion between the defined views in a slerpy movie, you can control the number of frames used in each interpolation. When a view is saved in slerpy it is associated by default with a transition of 50 frames to the next view. The number of frames in the transition can be altered with the ''ssetf'' command in slerpy.<br />
<br />
The views and actions stored by slerpy can (and should) be saved to a key file with the ''swrite'' command. They can then be retrieved with the sread command. Note that swrite saves the current pymol state in a .pse file but sread does not read in the .pse file. If you're starting a new pymol session to continue work on an existing movie you should load the pse file before doing an sread.<br />
<br />
==Quick Start Tutorial==<br />
<br />
If you haven't installed slerpy yet see [[#Installation|Installation]]<br />
<br />
;Step 1: You probably want to start off in a nice clean working directory that just has the coordinate files you want to work with.<br />
<br />
;Step 2: Read in your molecule(s) and create the various selections and representations that you want to include in the movie.<br />
<br />
;Step 3: At the pymol prompt, type:<br />
<br />
import slerpy<br />
<br />
;Step 4: Get your molecule in exactly the orientation and representation that you want to use for the beginning of your movie.<br />
<br />
;Step 5: Type:<br />
<br />
sinsert<br />
<br />
;Step 6: Using the mouse, move your molecule to the next orientation that you want to use. When you record the movie, the camera orientation will be interpolated between each consecutive pair of views. This can include changes in rotation, zooming, clipping etc.<br />
<br />
:Loop back to Step 5. Continue this until you've got all your orientations stored.<br />
<br />
:You can check how any set of transitions will look at any time by using the ''sshow'' command (see [[#Command Reference|Command Reference]] for details).<br />
<br />
:You can adjust the rate of any transition using the ''ssetf'' command<br />
<br />
;Step 7A: Add any actions to your views using the saction command. Any number of pymol commands can be strung together separated by semicolons. If, for example, you want to change your protein from a cartoon to a surface and add a ligand when you get to view 5 you would do the following (assuming you've defined the pymol selections prot and lig):<br />
<br />
sgo 5<br />
saction "hide cartoon, prot; show surface, prot; show sticks, lig"<br />
<br />
;Step 7B (Alternative using scenes):<br />
<br />
sgo 5<br />
<br />
:Now use the gui to create the representation you want and then:<br />
<br />
sscene<br />
<br />
;Step 8: Save everything. Save your slerpy views and actions as well as a pse file of your current pymol session:<br />
<br />
swrite mymovie<br />
<br />
This will create mymovie.key, which has all of the views, frame counts, actions etc. and mymovie.pse, the associated pymol session file.<br />
<br />
;Step 9: Record the movie! Type:<br />
<br />
srecord<br />
<br />
:You can then play the movie by typing the standard pymol command ''mplay'' or by clicking the play button in pymol.<br />
<br />
;Step 10: If you save the pymol session again, the pse file will contain the movie which can then be shown immediately after startup without running slerpy.py. Note that pymol will warn you when you load a pse file that contains a movie.<br />
<br />
;Step 11: If you want to, the movie can be exported using the mpng command (see the pymol [http://pymol.sourceforge.net/newman/ref/S1000comref.html#2_105 documentation]). Also, see the useful article [[Making_Movies|Making Movies]].<br />
<br />
==Tips and Tricks==<br />
<br />
===Converting scenes to movies===<br />
<br />
You can just step through the scenes and type sscene for each one. This will create a duplicate slerpy scene for each of the scenes you'd already saved but that's not such a disaster. Be sure to swrite when you're done.<br />
<br />
Note that there is some overhead associated with recalling scenes. To avoid pauses at view transitions, I prefer to actually issue the set of show and hide commands that will generate the scene rather than using the above method.<br />
<br />
===Starting off right===<br />
<br />
It's a bit of a pain, but I like to associate with the first frame of the movie an action list that hides everything and then turns on all the objects that I want to have visible at the beginning. This ensures that when your movie loops back to the beginning it will look the same as it did the first time through. For example:<br />
<br />
sgo 0<br />
saction "hide everything; show lines, prot; show surface, activesite; show sticks, ligand"<br />
<br />
Alternatively, start your slerpy work with an ''sscene''.<br />
<br />
===Live pymol presentations during a talk===<br />
Be sure to run your movie once it's been opened and before your presentation if you're presenting in pymol. This will ensure that any objects that don't appear until the middle of the movie are available in memory and won't need to be rebuilt while your audience waits.<br />
<br />
Of course showing your movie from within pymol allows you to show movies in stereo if you've got a presentation system that allows this. If you pass out stereo glasses first it's guaranteed that everyone will remember your talk...<br />
<br />
===Pausing on a view===<br />
<br />
Just sgo to the view you want to stay on for a while and do an sinsert. This will insert a new view with the same orientation etc as the one you were just on. You can adjust the length of the pause by changing the number of frames for the transistion between these two identical views using the ssetf command.<br />
<br />
===Morphing and multi-state models===<br />
<br />
Morphs and multi-conformation models are represented in pymol as single objects with multiple states. Cycling through the states as an animation is very straightforward in pymol. Slerpy allows you to include this animation over the states of an object as a transition between slerpy views within the context of larger movie. This is done using the ''smorph'' command (see [[#Command Reference|Command Reference]]). ''smorph'' allows you to specify the starting and ending pymol state numbers to use during the transition from the current to the next view. It will often be appropriate to have the movie continue after the morph using the final state of the morphing model, that is, the conformation to which you morphed. Since the default for a typical slerpy view is to show the first state of an object, you'll probably need to have available, in addition to your multi-state model, a single-state object containing the final conformation. You can then hide the multistate object and show the single-state final conformation as an action associated with the final view of your morphing sequence.<br />
<br />
To generate morphs you can use the [http://www.delanoscientific.com/rigimol.html rigimol] program provided by Warren as part of the incentive pymol package for subscribers or use [http://alpha2.bmc.uu.se/usf/mol_morph.html lsqman] from Gerard Kleywegt.<br />
<br />
==Command Reference==<br />
<br />
Note that it is essential to understand that slerpy uses the concept of a current or active view. This is the element in the list to which most commands are applied. It is not necessarily the view that is currently visible on the screen. It is advisable to use the sc command frequently to make sure you really know which view your command is being applied to.<br />
<br />
'''saction ''string'':''' Assoiciates the pymol commands in ''string'' with the current view. ''string'' must be enclosed in quotes and must contain only valid pymol commands separated by semicolons.<br />
<br />
'''sappend''': Add the currently displayed view at the end of the list of views in slerpy<br />
<br />
'''sappendaction ''string'':''' Adds the action(s) in ''string'' to the list of actions associated with the current view<br />
<br />
'''sc''': Go to the slerpy active view<br />
<br />
'''scrossfade ''startobject, endobject'':''' During the transition from the current view to the next view ''startobject'' will fade out and'' endobject'' will fade in. The two objects must be shown as sticks. They must be objects, not merely selections, as of pymol 0.99.<br />
<br />
'''sdelaction''': Deletes the action associated with the current view. Be sure you're sure which view you're on before you use this. This will also delete any actions etc. associated with the view so be careful.<br />
<br />
'''sdelete''': Remove the slerpy active view from the list of views to be interpolated.<br />
<br />
'''sdeletesetting: '''Remove the setting interpolation for the current view.<br />
<br />
'''sdumpactions: '''List all actions by frame.<br />
<br />
'''sgo ''n'':''' Change the slerpy active view to view ''n''.<br />
<br />
'''sinsert''': Add the currently displayed view after the slerpy active view.<br />
<br />
'''sinterpsetting ''setting, selection, startval, endval'' :''' The pymol setting ''setting'' will be interpolated linearly from ''startval'' to ''endval'' during the transition from the current view to the next view. You can only interpolate one setting per transition. This is the hard way to, for example, fade out an object:<br />
<br />
sinterpsetting stick_transparency, lig, 0.0, 1.0<br />
<br />
'''slist''': List all views stored for interpolation. Also lists the number of frames in each transition.<br />
<br />
'''smorph ''startmodel,endmodel'':''' The transition from the current frame to the next frame will consist of one frame per pymol state starting with state ''startmodel'' and ending with state ''endmodel''. Subsequent frames (i.e. from subsequent views) will revert to state 1. The state numbers apply to currently visible objects so you will most likely want to have an object with your starting conformation, an object with your multi-state morphing model, and an object with your final conformation. You would then sgo to the frame where you want the morph to start and add an action to hide the starting conformation object and show the multi-model morphing object, do an smorph 1,30 or whatever the number of states in your morph is, append another frame and give it an action where the multi-state model is hidden and the final conformation is shown.<br />
<br />
'''sn''': Go to the next view<br />
<br />
'''sp''': Go to the previous view.<br />
<br />
'''sread ''filename'':''' Restore all the information written with swrite. Does not read in the pse file (to avoid inadvertantly writing over some new selections, scenes or whatever).<br />
<br />
'''srecord''': Records the movie<br />
<br />
'''sreplace''': Replace the slerpy current view with the currently displayed view.<br />
<br />
'''sscene''': Add a the currently displayed view after the slerpy active view and create a scene to go with it. The current pymol state, including which objects are displayed and how they are shown will be captured.<br />
<br />
'''ssetf''': Set the number of frames to use in the transition from the slerpy active view to the next view<br />
<br />
'''ssetupview ''n'':''' This attempts to make sure that all objects are displayed (or not) as they would be when view ''n'' is arrived at in the movie. It goes through and executes all of the sactions from all preceeding views. For some reason this doesn't always work in complex cases.<br />
<br />
'''sshow ''n,m'':''' This command records and shows a segment of the movie showing the transitions starting with view n and ending with view m. If the arguments m and n are omitted the transition from the current view to the next view will be shown.<br />
<br />
'''swrite ''filename'':''' Writes all the information used by slerpy to a file ''filename''.key. It also writes a pymol session file ''filename''.pse containing all of your current objects, selections etc. The format of the .key file is supposed to be human readable and it can be convenient to edit this file rather than using saction over and over. After editing it by hand be sure to do an sread.<br />
<br />
==Why is it called slerpy?==<br />
<br />
slerp is an acronym of sorts for spherical linear interpolation. The transition between two views approximates spherical linear interpolation of the their camera positions using quaternions. See the Wikipedia [http://en.wikipedia.org/wiki/Slerp article] on slerps.<br />
<br />
=Script Files=<br />
<br />
==Installation==<br />
<br />
To install, copy (by pasting into a text editor) the following two python code segments to files named slerpy.py and movs.py, respectively. Place these files in the pymol/modules/pymol/ directory created by the pymol installation.<br />
<br />
If you don't have write priviledges in the pymol installation directories you can just copy these files to the working directory from which pymol will be run. <br />
<br />
==Code==<br />
<br />
===slerpy.py===<br />
<br />
:The command definitions for slerpy<br />
<br />
<source lang="python"><br />
################################################################################<br />
#slerpy.py - Command definition routines for slerpy<br />
#Copyright (C) 2006 Joel Bard<br />
#<br />
#This program is free software; you can redistribute it and/or<br />
#modify it under the terms of the GNU General Public License<br />
#as published by the Free Software Foundation; either version 2<br />
#of the License, or (at your option) any later version.<br />
#<br />
#This program is distributed in the hope that it will be useful,<br />
#but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br />
#GNU General Public License for more details.<br />
#<br />
#You should have received a copy of the GNU General Public License<br />
#along with this program; if not, write to the Free Software<br />
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br />
#################################################################################<br />
<br />
from pymol import cmd<br />
import movs<br />
<br />
def readViews( filename ):<br />
#obsolete<br />
vfile = open( filename, 'r')<br />
views = [] #a list of views each of which is a list of 18 numbers<br />
vstrings = vfile.readlines()<br />
for vstring in vstrings:<br />
vals = vstring.split()<br />
view = [float(v) for v in vals]<br />
views.append( view )<br />
vfile.close()<br />
return views<br />
<br />
def readFrames( filename ):<br />
#obsolete<br />
ffile = open( filename, 'r' )<br />
frames = []<br />
fstrings = ffile.readlines()<br />
for fstring in fstrings:<br />
frames.append( int(fstring) )<br />
ffile.close()<br />
return frames<br />
<br />
def readActions( filename ):<br />
#obsolete<br />
#actions are stored in file where<br />
#for each line, the first 4 chars are the view index<br />
#associated with the action and the rest of the<br />
#line is the pymol command to be executed<br />
#upon reading, a dictionary is returned<br />
#with view indices as keys and actions as values<br />
actions = {}<br />
try:<br />
afile = open( filename, 'r' )<br />
except:<br />
print "No actions for this project"<br />
return actions<br />
astrings = afile.readlines()<br />
for astring in astrings:<br />
try:<br />
aindex = int(astring[:4])<br />
action = astring[4:]<br />
actions[ aindex ] = action[:-1]<br />
except:<br />
print "empty line"<br />
afile.close()<br />
return actions<br />
<br />
def readModels( filename ):<br />
#obsolete<br />
models = {}<br />
try:<br />
mfile = open( filename, 'r' )<br />
except:<br />
print "No models for this project"<br />
return models<br />
mstrings = mfile.readlines()<br />
for mstring in mstrings:<br />
try:<br />
mindex = int(mstring[:4])<br />
model = mstring[4:]<br />
models[ mindex ] = model[:-1]<br />
except:<br />
print "empty line"<br />
mfile.close()<br />
return models<br />
<br />
def readSettings( filename ):<br />
#obsolete<br />
settings = {}<br />
try:<br />
sfile = open( filename, 'r' )<br />
except:<br />
print "No settings for this project"<br />
return settings<br />
sstrings = sfile.readlines()<br />
for sstring in sstrings:<br />
try:<br />
sindex = int(sstring[:4])<br />
scommas = sstring[4:]<br />
settingName,selection,startVal,endVal = scommas.split(',')<br />
setting = [settingName,selection,float(startVal),float(endVal)]<br />
settings[sindex] = setting<br />
except:<br />
print "unable to parse setting"<br />
sfile.close()<br />
return settings<br />
<br />
def readScenes( filename ):<br />
#obsolete<br />
global scene_counter<br />
<br />
scene_counter = 0<br />
scenes = {}<br />
try:<br />
sfile = open( filename, 'r' )<br />
except:<br />
print "No scenes file for this project"<br />
return scenes<br />
sstrings = sfile.readlines()<br />
for sstring in sstrings:<br />
try:<br />
sindex = int(sstring[:4])<br />
scene = sstring[4:]<br />
scenes[ sindex ] = scene[:-1]<br />
scene_counter += 1<br />
#print "reading scene", sstring, sindex, scene<br />
except:<br />
print "empty line"<br />
sfile.close()<br />
return scenes<br />
<br />
def read_all( fileroot ):<br />
#obsolete in favor of readKeyViewFile<br />
global views<br />
global frames<br />
global actions<br />
global cur_view<br />
global cur_index<br />
global scenes<br />
global models<br />
global settings<br />
<br />
views = readViews( fileroot+".txt" )<br />
frames = readFrames( fileroot+".frm")<br />
actions = readActions( fileroot+".act")<br />
scenes = readScenes( fileroot+".scn")<br />
models = readModels( fileroot+".mod")<br />
settings = readSettings( fileroot+".set")<br />
cur_view = views[0]<br />
cur_index = 0<br />
show_cur()<br />
<br />
def print_view( view ):<br />
for i in range(0,6):<br />
for j in range(0,3):<br />
print "%12.6f"% view[ 3*i+j ] ,<br />
print<br />
<br />
def show_next():<br />
global cur_index<br />
global cur_view<br />
global views<br />
if cur_index == len( views )-1:<br />
print "No more views."<br />
return<br />
cur_index += 1<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def show_prev():<br />
global cur_index<br />
global cur_view<br />
global views<br />
if cur_index == 0:<br />
print "No more views."<br />
return<br />
cur_index -= 1<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def show_cur():<br />
global cur_index<br />
global cur_view<br />
global views<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def go_to_view( arg=0 ):<br />
global cur_index<br />
global cur_view<br />
global views<br />
n = int( arg )<br />
if n < 0 or n >= len(views):<br />
print "Index out of range."<br />
return<br />
cur_index = n<br />
cur_view = views[n]<br />
cmd.set_view( cur_view )<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ", cur_index<br />
<br />
def insert_current():<br />
#insert the current view into the list after the view<br />
#in views[cur_index]<br />
#set frames to default<br />
global cur_index<br />
global cur_view<br />
global views<br />
global frames<br />
global actions<br />
global scenes<br />
global settings<br />
global models<br />
global fades<br />
<br />
cur_index += 1<br />
cur_view = cmd.get_view()<br />
views.insert( cur_index, [cv for cv in cur_view] )<br />
frames.insert( cur_index, 50 )<br />
<br />
#deal with actions dictionary<br />
actions = incKeyAbove( actions, cur_index )<br />
scenes = incKeyAbove( scenes, cur_index )<br />
settings = incKeyAbove( settings, cur_index )<br />
models = incKeyAbove( models, cur_index )<br />
fades = incKeyAbove( fades, cur_index )<br />
<br />
print "New view:"<br />
print_view( cur_view )<br />
print "Inserted view with index", cur_index, "and a 50 frame transition"<br />
<br />
def append_view():<br />
global views<br />
global frames<br />
global cur_index<br />
global cur_view<br />
<br />
cur_index = len(views)<br />
cur_view = cmd.get_view()<br />
views.append( [cv for cv in cur_view] )<br />
frames.append( 50 )<br />
<br />
print "New view: "<br />
print_view( cur_view )<br />
print "Appended view with index", cur_index, "and a 50 frame transition"<br />
print "The current view is", cur_index<br />
<br />
def incKeyAbove( dict, index ):<br />
tempDict = {}<br />
for key, val in dict.iteritems():<br />
if key >= index:<br />
newkey = key + 1<br />
tempDict[newkey] = val<br />
else:<br />
tempDict[key] = val<br />
return tempDict<br />
<br />
def decKeyAbove( dict, index ):<br />
tempDict = {}<br />
for key, val in dict.iteritems():<br />
if key > index:<br />
newkey = key - 1<br />
tempDict[newkey] = val<br />
else:<br />
tempDict[key] = val<br />
return tempDict<br />
<br />
def delete_current():<br />
#remove the current view from the list<br />
#show the previous view<br />
global cur_index<br />
global cur_view<br />
global views<br />
global actions<br />
global scenes<br />
global settings<br />
global models<br />
global frames<br />
global fades<br />
<br />
del views[cur_index]<br />
del frames[cur_index]<br />
if cur_index in actions:<br />
del actions[cur_index]<br />
if cur_index in scenes:<br />
del scenes[cur_index]<br />
if cur_index in settings:<br />
del settings[cur_index]<br />
<br />
#deal with dictionaries<br />
actions = decKeyAbove( actions, cur_index )<br />
scenes = decKeyAbove( scenes, cur_index )<br />
settings = decKeyAbove( settings, cur_index )<br />
models = decKeyAbove( models, cur_index ) <br />
fades = decKeyAbove( fades, cur_index )<br />
<br />
print "View number",cur_index,"deleted."<br />
if cur_index > 0:<br />
cur_index -= 1<br />
cur_view = views[cur_index]<br />
cmd.set_view( cur_view )<br />
print "Current view is number",cur_index<br />
<br />
def delete_settings():<br />
global settings<br />
global cur_index<br />
del settings[cur_index]<br />
<br />
def replace_current():<br />
global cur_index<br />
global cur_view<br />
global views<br />
cur_view = cmd.get_view()<br />
views[cur_index] = [cv for cv in cur_view]<br />
<br />
def insert_scene():<br />
global views<br />
global actions<br />
global settings<br />
global frames<br />
global cur_index<br />
global cur_view<br />
global scenes<br />
global scene_counter<br />
global models<br />
global fades<br />
<br />
cur_index += 1<br />
cur_view = cmd.get_view()<br />
views.insert( cur_index, [cv for cv in cur_view] )<br />
frames.insert( cur_index, 50 )<br />
<br />
#deal with dictionaries<br />
actions = incKeyAbove( actions, cur_index )<br />
scenes = incKeyAbove( scenes, cur_index )<br />
settings = incKeyAbove( settings, cur_index )<br />
models = incKeyAbove( models, cur_index )<br />
fades = incKeyAbove( fades, cur_index )<br />
<br />
#this stuff has to be done after the above<br />
#find a free scene name<br />
i = 1<br />
while True:<br />
for sname in scenes.values():<br />
print "|"+sname+"|"<br />
if sname == "slerpy_"+str(i):<br />
break<br />
else:<br />
break<br />
i += 1<br />
newname = "slerpy_"+str(i)<br />
<br />
scene_counter += 1<br />
cmd.scene( newname, "store" )<br />
scenes[ cur_index ] = newname<br />
actions[ cur_index ] = "scene "+newname<br />
<br />
print "New view:"<br />
print_view( cur_view )<br />
print "Inserted view with index", cur_index, "and a 50 frame transition"<br />
print "Added scene",newname<br />
<br />
def write_views( filename ):<br />
#deprecated in favor of key files<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
<br />
viewfile = open( filename+".txt", 'w')<br />
for view in views:<br />
for v in view:<br />
viewfile.write( str(v) + " " )<br />
viewfile.write('\n')<br />
viewfile.close()<br />
<br />
framefile = open( filename+".frm", 'w' )<br />
for frame in frames:<br />
framefile.write( str( frame )+'\n' )<br />
framefile.close()<br />
<br />
actionfile = open( filename+".act", 'w' )<br />
for key,action in actions.iteritems():<br />
keystring = str( key )<br />
actionfile.write( keystring.rjust(4)+action + '\n' )<br />
actionfile.close()<br />
<br />
scenefile = open( filename+".scn", 'w' )<br />
for key,scene in scenes.iteritems():<br />
keystring = str( key )<br />
scenefile.write( keystring.rjust(4)+scene + '\n' )<br />
scenefile.close()<br />
<br />
modelfile = open( filename+".mod", 'w' )<br />
for key,model in models.iteritems():<br />
keystring = str( key )<br />
modelfile.write( keystring.rjust(4)+model + '\n' )<br />
modelfile.close()<br />
<br />
settingsfile = open( filename+".set", 'w' )<br />
for key,setting in settings.iteritems():<br />
keystring = str( key )<br />
settingName, selection, startVal, endVal = setting<br />
settingsfile.write( "%s%s,%s,%f,%f\n" % (keystring.rjust(4), settingName, selection, startVal, endVal))<br />
settingsfile.close()<br />
cmd.save( filename+".pse" )<br />
<br />
print "Wrote files", filename+".txt,",filename+".frm,",filename+".pse, and",filename+".act"<br />
<br />
def writeKeyViewFile( filename ):<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
<br />
keyviewfile = open( filename + ".key", 'w' )<br />
for i,view in enumerate(views):<br />
keyviewfile.write( "VIEW: %4d " % i )<br />
for v in view:<br />
keyviewfile.write( str(v) + " " )<br />
keyviewfile.write('\n')<br />
keyviewfile.write( "FRAMES: %d\n" % frames[i] )<br />
if i in actions:<br />
keyviewfile.write( "ACTIONS: %s\n" % actions[i] )<br />
if i in scenes:<br />
keyviewfile.write( "SCENES: %s\n" % scenes[i] )<br />
if i in models:<br />
keyviewfile.write( "MODELS: %s\n" % models[i] )<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
keyviewfile.write( "SETTINGS: %s, %s, %f, %f\n" % (settingName, selection, startVal, endVal))<br />
if i in fades:<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
keyviewfile.write( "FADES: %s, %s, %d\n" % (startVisSelection, endVisSelection, sticksOnly)) <br />
keyviewfile.write("\n")<br />
keyviewfile.close()<br />
cmd.save( filename + ".pse" )<br />
print "Wrote files " , filename + ".key", filename + ".pse"<br />
<br />
def readKeyViewFile( filename ):<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
global scene_counter<br />
<br />
views = []<br />
frames = []<br />
actions = {}<br />
scenes = {}<br />
models = {}<br />
settings = {}<br />
fades = {}<br />
scene_counter = 0<br />
<br />
if filename.endswith(".key"): filename = filename[:-4]<br />
keyviewfile = open( filename + ".key", 'r' )<br />
viewstrings = keyviewfile.readlines()<br />
keyviewfile.close()<br />
viewindex = 0<br />
for line in viewstrings:<br />
if line.startswith("VIEW: "):<br />
viewindex = int( line[6:10] )<br />
vals = line[10:].split()<br />
view = [float(v) for v in vals]<br />
views.append( view )<br />
if line.startswith("FRAMES: "):<br />
frames.append( int( line[8:] ) )<br />
if line.startswith("ACTIONS: "):<br />
actions[ viewindex ] = line[9:-1]<br />
if line.startswith("SCENES: "):<br />
scenes[ viewindex ] = line[8:-1]<br />
scene_counter += 1<br />
if line.startswith("MODELS: "):<br />
models[ viewindex ] = line[8:-1]<br />
if line.startswith("SETTINGS: "):<br />
settingName,selection,startVal,endVal = line[10:-1].split(',')<br />
settings[ viewindex ] = [settingName,selection,float(startVal),float(endVal)]<br />
if line.startswith( "FADES: " ):<br />
startVisSelection, endVisSelection, sticksOnly = line[7:-1].split(',')<br />
fades[ viewindex ] = [startVisSelection, endVisSelection, int(sticksOnly) ]<br />
cur_view = views[0]<br />
cur_index = 0<br />
show_cur()<br />
<br />
def set_frames_current( arg=50 ):<br />
global frames<br />
global cur_index<br />
frames[cur_index] = int(arg)<br />
<br />
def list_frames():<br />
global frames<br />
global views<br />
global actions<br />
global models<br />
global settings<br />
<br />
f=0<br />
for i,view in enumerate(views[:-1]):<br />
if i in actions:<br />
a = actions[i]<br />
else:<br />
a = ""<br />
if i in models:<br />
m = "States: " + models[i]<br />
else:<br />
m = ""<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
s = "Settings: %s %s %f %f" % (settingName, selection, startVal, endVal)<br />
else:<br />
s = ""<br />
print "View",i,"to",i+1,"Frames ",f,"to",f+frames[i],a,m,s<br />
f += frames[i]<br />
<br />
def add_action_current( cmd ):<br />
global cur_index<br />
global actions<br />
actions[cur_index] = cmd[1:-1] #strip off quotes<br />
<br />
def append_action_current( cmd ):<br />
global cur_index<br />
global actions<br />
actions[cur_index] += ";" + cmd[1:-1]<br />
<br />
def clear_action_current():<br />
global actions<br />
global cur_index<br />
del actions[cur_index]<br />
<br />
def list_actions():<br />
global actions<br />
for i,a in actions.iteritems():<br />
print i,a<br />
<br />
def morph_models( start_model, end_model ):<br />
global cur_index<br />
global frames<br />
global models<br />
models[cur_index] = "%s -%s" % (start_model, end_model)<br />
frames[cur_index] = abs(int(end_model) - int(start_model)) + 1<br />
<br />
def interpolate_settings( setting, selection, startval, endval ):<br />
global cur_index<br />
global settings<br />
settingEntry = [setting, selection, float(startval), float(endval)]<br />
settings[cur_index] = settingEntry <br />
<br />
def crossfade( startVisSelection, endVisSelection, sticksOnly = 1 ):<br />
#cross fade the specified objects, vary stick transparency only if stickOnly=1<br />
global cur_index<br />
global fades<br />
fades[cur_index] = [startVisSelection, endVisSelection, int(sticksOnly) ]<br />
<br />
def setup_view( index ):<br />
for i in range( int(index)+1 ):<br />
if i in actions:<br />
print "Executing %s from actions %d" % (actions[i],i)<br />
cmd.do( actions[i] )<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
action = "set %s, %f, %s;" % (settingName, endVal, selection)<br />
print "Executing %s from settings %d" % (action,i)<br />
cmd.do( action )<br />
if i in fades:<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
action = "set stick_transparency, 0, %s; set stick_transparency, 1, %s;" % (endVisSelection, startVisSelection)<br />
print "Executing %s from fades %d" % (action, i)<br />
cmd.do( action )<br />
<br />
def show_transition(start_index=0, end_index=0):<br />
#show the transition from the current view to the next view<br />
global frames<br />
global views<br />
global cur_index<br />
global actions<br />
global models<br />
if start_index == 0 and end_index == 0:<br />
if cur_index >= len(views)-1:<br />
print "Current view is last in sequence."<br />
return<br />
start_index=cur_index<br />
end_index=cur_index+1<br />
else:<br />
start_index = int(start_index)<br />
end_index = int(end_index)<br />
ftot = 0<br />
setcommand = ""<br />
i = start_index<br />
for nframes in frames[start_index:end_index]:<br />
#ftot += nframes<br />
if i in models:<br />
setcommand += " " + models[i] + " "<br />
else:<br />
setcommand += " 1 x%i" % nframes<br />
i += 1<br />
<br />
# cmd.mset("1 x%i" % ftot)<br />
cmd.mset( setcommand )<br />
start_frame = 1<br />
#first do all actions that happen up to this point to make sure<br />
#things look the way they should<br />
first_action = ""<br />
for i in range( start_index ):<br />
if i in actions:<br />
first_action += actions[i] + ';'<br />
#print "Executing %s from actions %d" % (actions[i],i)<br />
#cmd.do( actions[i] )<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
action = "set %s, %f, %s;" % (settingName, endVal, selection)<br />
first_action += action<br />
#print "Executing %s from settings %d" % (action,i)<br />
#cmd.do( action )<br />
if i in fades:<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
action = "set stick_transparency, 0, %s; set stick_transparency, 1, %s;" % (endVisSelection, startVisSelection)<br />
first_action += action<br />
#print "Executing %s from fades %d" % (action, i)<br />
#cmd.do( action )<br />
for i in range( start_index, end_index ):<br />
if i in settings:<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame, settings[i] )<br />
elif i in fades:<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame, fades[i] )<br />
else:<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame )<br />
#add an action<br />
if start_frame == 1:<br />
mdo_cmd = first_action<br />
if i in actions:<br />
mdo_cmd += actions[i]+";"<br />
#mdo_cmd += "set_view("+str(views[i])+")"<br />
print mdo_cmd<br />
cmd.mdo(start_frame, mdo_cmd)<br />
elif i in actions:<br />
mdo_cmd = actions[i]+";set_view("+str(views[i])+")"<br />
cmd.mdo(start_frame, mdo_cmd)<br />
#print mdo_cmd<br />
start_frame += frames[i]<br />
cmd.frame(1)<br />
cmd.mplay()<br />
<br />
def make_all():<br />
#make the whole movie<br />
global views<br />
global frames<br />
global models<br />
<br />
#first get total number of frames<br />
ftot = 0<br />
setcommand = ""<br />
for i,nframes in enumerate(frames[:-1]):<br />
ftot += nframes<br />
if i in models:<br />
setcommand += " " + models[i] + " "<br />
else:<br />
setcommand += " 1 x%i" % nframes<br />
<br />
#initialize movie<br />
#cmd.mset("1 x%i" % ftot)<br />
#cmd.mset("1 x50 1 -30 30 x20")<br />
cmd.mset( setcommand )<br />
<br />
#loop through views<br />
start_view = views[0][:]<br />
first_frame = 1<br />
for i,view in enumerate(views[1:]):<br />
end_view = view[:]<br />
if i in settings:<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame, settings[i] )<br />
elif i in fades:<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame, fades[i] )<br />
else:<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame )<br />
#add an action<br />
if i in actions:<br />
mdo_cmd = actions[i]#+";set_view ("+str( views[i] )+")"<br />
print mdo_cmd<br />
cmd.mdo(first_frame, mdo_cmd)<br />
first_frame += frames[i]<br />
start_view = end_view[:]<br />
cmd.frame(1)<br />
<br />
## views = readViews( "viewfile.txt" )<br />
## frames = readFrames( "viewfile.frm" )<br />
## actions = readActions( "viewfile.act" )<br />
##print "Length ",len(views)<br />
#for v in views:<br />
# print v<br />
#cur_view = views[0]<br />
views = []<br />
frames = []<br />
models = {}<br />
actions = {}<br />
scenes = {}<br />
settings = {}<br />
fades = {}<br />
scene_counter = 0<br />
cur_index = -1<br />
cmd.set( "scene_animation_duration","0" )<br />
#cmd.set_view( cur_view )<br />
<br />
cmd.extend("sn", show_next )<br />
cmd.extend("sp", show_prev )<br />
cmd.extend("sc", show_cur )<br />
cmd.extend("sinsert", insert_current )<br />
cmd.extend("sdelete", delete_current )<br />
cmd.extend("sreplace", replace_current )<br />
cmd.extend("sappend", append_view )<br />
cmd.extend("sscene", insert_scene )<br />
cmd.extend("sgo", go_to_view )<br />
cmd.extend("sreadold", read_all )<br />
cmd.extend("swriteold", write_views )<br />
cmd.extend("slist", list_frames )<br />
cmd.extend("ssetf", set_frames_current )<br />
cmd.extend("sshow", show_transition )<br />
cmd.extend("srecord", make_all )<br />
cmd.extend("saction", add_action_current )<br />
cmd.extend("sdelaction", clear_action_current )<br />
cmd.extend("sdumpactions", list_actions )<br />
cmd.extend("sappendaction", append_action_current )<br />
cmd.extend("smorph", morph_models )<br />
cmd.extend("sinterpsetting", interpolate_settings )<br />
cmd.extend("sdeletesetting", delete_settings )<br />
cmd.extend("scrossfade", crossfade )<br />
cmd.extend("swrite", writeKeyViewFile )<br />
cmd.extend("sread", readKeyViewFile )<br />
cmd.extend("ssetupview", setup_view )<br />
</source><br />
<br />
===movs.py===<br />
<br />
:Math and animation routines for slerpy<br />
<br />
<source lang="python"><br />
##################################################################################<br />
#movs.py - Math and animation routines for slerpy<br />
#Copyright (C) 2006 Joel Bard<br />
#<br />
#This program is free software; you can redistribute it and/or<br />
#modify it under the terms of the GNU General Public License<br />
#as published by the Free Software Foundation; either version 2<br />
#of the License, or (at your option) any later version.<br />
#<br />
#This program is distributed in the hope that it will be useful,<br />
#but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br />
#GNU General Public License for more details.<br />
#<br />
#You should have received a copy of the GNU General Public License<br />
#along with this program; if not, write to the Free Software<br />
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br />
#################################################################################<br />
<br />
from pymol import cmd,stored<br />
from math import *<br />
<br />
def rmat2quat( M ):<br />
#M is a list of 9 values being the elements of the rotation matrix in row order<br />
T = M[0] + M[4] + M[8] + 1<br />
print "Trace ",T<br />
if T>0:<br />
S = 0.5 / sqrt(T)<br />
W = 0.25/S<br />
X = (M[7] - M[5])*S<br />
Y = (M[2] - M[6])*S<br />
Z = (M[3] - M[1])*S<br />
else:<br />
if M[0] > M[4] and M[0] > M[8]:<br />
S = sqrt( 1.0 + M[0] - M[4] - M[8]) * 2<br />
X = 0.25 * S<br />
Y = (M[1] + M[3])/S<br />
Z = (M[2] + M[6])/S<br />
W = (M[5] - M[7])/S<br />
elif M[4] > M[8]:<br />
S = sqrt( 1.0 + M[4] - M[0] - M[8] ) * 2<br />
X = (M[1] + M[3])/S<br />
Y = 0.25 * S<br />
Z = (M[5] + M[7])/S<br />
W = (M[2] - M[6])/S<br />
else:<br />
S = sqrt( 1.0 + M[8] - M[0] - M[4]) * 2<br />
X = (M[2] + M[6])/S<br />
Y = (M[5] + M[7])/S<br />
Z = 0.25 * S<br />
W = (M[1] - M[3])/S<br />
return [X,Y,Z,W]<br />
<br />
def quat2rmat( Q ):<br />
#Q is a list of 4 values being the quaternion X Y Z W<br />
X=Q[0]<br />
Y=Q[1]<br />
Z=Q[2]<br />
W=Q[3]<br />
xx = X*X<br />
xy = X*Y<br />
xz = X*Z<br />
xw = X*W<br />
yy = Y*Y<br />
yz = Y*Z<br />
yw = Y*W<br />
zz = Z*Z<br />
zw = Z*W<br />
<br />
M= [1.0]*9<br />
M[0] = 1 - 2 * ( yy + zz )<br />
M[1] = 2 * ( xy - zw )<br />
M[2] = 2 * ( xz + yw )<br />
M[3] = 2 * ( xy + zw )<br />
M[4] = 1 - 2 * ( xx + zz )<br />
M[5] = 2 * ( yz - xw )<br />
M[6] = 2 * ( xz - yw )<br />
M[7] = 2 * ( yz + xw )<br />
M[8] = 1 - 2 * ( xx + yy )<br />
return M<br />
<br />
def quatconj( Q ):<br />
return [-Q[0],-Q[1],-Q[2],Q[3]]<br />
<br />
def quatmag( Q ):<br />
s = 0.0<br />
QC = quatconj(Q)<br />
for x in range(4):<br />
s += Q[x]*Q[x]<br />
print s<br />
return sqrt(s)<br />
<br />
def quatnorm( Q ):<br />
m = quatmag( Q )<br />
return [q/m for q in Q]<br />
<br />
def quatdotprod( q1, q2 ):<br />
dp = 0<br />
for i in range(4):<br />
dp += q1[i]*q2[i]<br />
return dp<br />
<br />
def vectnorm( V ):<br />
mag = 0.0<br />
for x in V:<br />
mag += x*x<br />
mag = sqrt(mag)<br />
return [x/mag for x in V]<br />
<br />
def quat2axisangle( Q ):<br />
#returns list where 0..2 are rot axis and 3 is angle<br />
qn = quatnorm( Q )<br />
cos_a = Q[3]<br />
angle = acos( cos_a ) * 2<br />
sin_a = sqrt( 1.0 - cos_a * cos_a )<br />
if fabs( sin_a ) < 0.000005:<br />
sin_a = 1<br />
ax_an = [ q/sin_a for q in Q[0:3] ]<br />
ax_an.append( angle )<br />
return ax_an<br />
<br />
def axisangle2quat( ax_an ):<br />
#ax_an is a list with axis coordinates followed by rotation angle<br />
axn = vectnorm( ax_an[:3] )<br />
angle = ax_an[3]<br />
sin_a = sin( angle / 2 )<br />
cos_a = cos( angle / 2 )<br />
Q = [ x * sin_a for x in axn ]<br />
Q.append( cos_a )<br />
return Q<br />
<br />
def rmat2axisangle( M ):<br />
q = rmat2quat( M )<br />
return quat2axisangle( q )<br />
<br />
def axisangle2rmat( a ):<br />
q = axisangle2quat( a )<br />
return quat2rmat( q )<br />
<br />
def animate_transition( start_view, end_view, nframes, first_frame, settings = [] ):<br />
#print "Views"<br />
#print start_view,'\n',end_view<br />
<br />
cview = start_view[:]<br />
cmd.set_view( start_view )<br />
<br />
#get initial and final quaternions for interpolation<br />
#print start_view[0:9]<br />
#get quaternions<br />
qstart = rmat2quat( start_view[0:9] )<br />
qend = rmat2quat( end_view[0:9] )<br />
<br />
#test for long way vs. short way<br />
if quatdotprod( qstart,qend ) < 0:<br />
qstart = [-q for q in qstart]<br />
<br />
axan_start = quat2axisangle( qstart )<br />
axan_end = quat2axisangle( qend )<br />
<br />
axan_cur = axan_start[:]<br />
frame_start = first_frame<br />
frame_end = frame_start + nframes<br />
doFade = 0<br />
doSetting = 0<br />
if len( settings ) == 4:<br />
settingName, selection, startVal, endVal = settings<br />
settingStep = (endVal-startVal)/float(nframes)<br />
print "Setting step ", settingStep<br />
doSetting = 1<br />
elif len( settings ) == 3:<br />
startVisSelection, endVisSelection, sticksOnly = settings<br />
settingStep = 1.0/float(nframes)<br />
doFade = 1<br />
for f in range( frame_start , frame_end):<br />
#get rotmat<br />
#using angle axis<br />
<br />
for i in range(4):<br />
axan_cur[i] = axan_cur[i] + (axan_end[i]-axan_start[i])/nframes<br />
newmat = axisangle2rmat( axan_cur )<br />
#print cview<br />
for i in range(9):<br />
cview[i] = newmat[i]<br />
<br />
mdo_cmd = "set_view (["<br />
for i in range(18):<br />
if i>8:<br />
cview[i] = cview[i]+(end_view[i]-start_view[i])/nframes<br />
mdo_cmd += "%12.7f,"% cview[i]<br />
mdo_cmd = mdo_cmd[:-1]+"])"<br />
if doSetting: <br />
val = float(f-frame_start)*settingStep + startVal <br />
print val;<br />
mdo_cmd += "; set %s, %f, %s" % (settingName, val, selection)<br />
print mdo_cmd;<br />
#print "mdo ", mdo_cmd<br />
if doFade:<br />
val = float(f-frame_start)*settingStep<br />
otherVal = 1.0 - val<br />
mdo_cmd += "; set stick_transparency, %f, %s; set stick_transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
if not sticksOnly:<br />
#comment out surface transparency interpolation due to problem with transparent sticks in front of <br />
#transparent surfaces (get black holes)<br />
# mdo_cmd += "; set transparency, %f, %s; set transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
mdo_cmd += "; set cartoon_transparency, %f, %s; set cartoon_transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
cmd.mdo(f,mdo_cmd)<br />
<br />
</source><br />
[[Category:Script_Library|Slerpy]]<br />
[[Category:Math_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Pdbsurvey&diff=8010Pdbsurvey2010-01-29T05:33:33Z<p>Newacct: </p>
<hr />
<div>Hi everyone !<br />
<br />
I have created a script because I was tired of browsing the pdb for endless searches of structures relevant to my field. This scripts takes as input a text file in which you copied your favourite keywords, and the number of days you want to search back (by default, it will look at the structures added the last 50 days). It generates a report text file that contains the pdb id and name of the relevant structures that have been recently added. All you need to do is add 'run pdbsurvey.py' to your startup file, and create a text file called 'keywords.txt' with your keywords separated by an end-of-line character. Then you're ready to go. Just hit 'pdbsurvey' from within your PyMol instance, and the program returns the report file. The pdb ftp server is updated weekly.<br />
<br />
<source lang="python"><br />
from pymol import cmd<br />
<br />
def pdbsurvey(days=50):<br />
<br />
"""USAGE : pdbsurvey (<days>)<br />
Surveys the updates added to the PDB (ftp.rcsb.org) in the last<br />
50 days (or otherwise specified when calling this function) for<br />
entries that contain the words specified in the file<br />
keywords.txt.<br />
"""<br />
print days<br />
<br />
import ftplib<br />
import time<br />
import os<br />
<br />
<br />
<br />
def todaymerge():<br />
"""Puts today's date in a pdb format string.<br />
"""<br />
date=time.localtime()<br />
fyear="%i" %(date[0])<br />
fmonth="%i" %(date[1])<br />
if date[1]<10:<br />
fmonth="0"+"%i" %(date[1])<br />
fday="%i" %(date[2])<br />
if date[2]<10:<br />
fday="0"+"%i" %(date[2])<br />
dateS=fyear+fmonth+fday<br />
return dateS<br />
<br />
def file2list(filename):<br />
"""Low-level routine to brainlessly implement<br />
file.read().<br />
"""<br />
fq=open(filename,'rb')<br />
linesS=fq.read()<br />
fq.close()<br />
LIST=linesS.splitlines()<br />
return LIST<br />
<br />
def connect2pdb():<br />
"""Opens an anonymous socket to ftp://ftp.rcsb.org<br />
"""<br />
f=ftplib.FTP()<br />
f.connect ('ftp.rcsb.org')<br />
f.login ()<br />
print "Remote connection established","\n"<br />
return f<br />
<br />
def decrementdate(dateS):<br />
"""given a string date (pdb format yyyymmdd)<br />
this routine returns a string of the day before<br />
(sadly assuming that every month has 31 days, but<br />
no big deal here...).<br />
"""<br />
#decompose dateS into components<br />
yearS=dateS[0]+dateS[1]+dateS[2]+dateS[3]<br />
monthS=dateS[4]+dateS[5]<br />
dayS=dateS[6]+dateS[7]<br />
<br />
#convert each into integers<br />
yearI=int(yearS)<br />
monthI=int(monthS)<br />
dayI=int(dayS)<br />
<br />
#actual stuff<br />
dayI=dayI-1<br />
if dayI==0:<br />
dayI=31<br />
monthI-=1<br />
if monthI==0:<br />
monthI=12<br />
yearI-=1<br />
dayS="%i" %(dayI)<br />
monthS="%i" %(monthI)<br />
yearS="%i" %(yearI)<br />
if dayI<10:<br />
dayS="0"+dayS<br />
if monthI<10:<br />
monthS="0"+monthS<br />
#and finally...<br />
dateS=yearS+monthS+dayS<br />
return dateS<br />
<br />
def findlastdir(dateS,f,days):<br />
"""Puts the names of the "recent" directories in the<br />
list named "directoriesL".<br />
"""<br />
directoriesL=[]<br />
for p in range(days):<br />
dateS=decrementdate(dateS)<br />
attempt="/pub/pdb/data/status/"+dateS<br />
try:<br />
f.cwd(attempt)<br />
directoriesL.append(attempt)<br />
except:<br />
pass<br />
return directoriesL<br />
<br />
def compilinfile(directoriesL,f):<br />
"""lists all structures in the added.pdb files<br />
contained in the directories specified in directoriesL<br />
"""<br />
command="RETR added.pdb"<br />
handle=open("donotedit.dat","wrb")<br />
for k in directoriesL:<br />
f.cwd(k)<br />
print "Currently in directory ",f.pwd()<br />
f.retrbinary(command,handle.write)<br />
handle.close()<br />
return len(directoriesL)<br />
<br />
def listparser():<br />
"""Extracts the pdbids from donotedit.dat file,<br />
and stacks them into the list pdbidsL<br />
"""<br />
linesL=file2list("donotedit.dat")<br />
pdbidsL=[]<br />
for iter in linesL:<br />
pdbidsL.append(iter[57:61])<br />
pdbidsL.sort()<br />
return pdbidsL<br />
<br />
def currentrelease(f):<br />
"""Stores the content of cmpd_res.idx file<br />
This file contains the equivalencies pdbid<->title<br />
for all current entries of the PDB.<br />
"""<br />
command="RETR cmpd_res.idx"<br />
f.cwd("/pub/pdb/derived_data/index/")<br />
print "Currently in directory ",f.pwd()<br />
fq=open("dictionnary.dat",'wrb')<br />
f.retrbinary(command,fq.write)<br />
fq.close()<br />
dictL=file2list("dictionnary.dat")<br />
return dictL<br />
<br />
def extract(pdbidsL,dictL):<br />
"""Populates dictionnaryD with pdb entries found in the<br />
latest releases.<br />
"""<br />
dictionnaryD={}<br />
problemL=[]<br />
extractL=[dictionnaryD,problemL]<br />
for i in dictL:<br />
tempS=i[0:4].lower()<br />
for ii in pdbidsL:<br />
if ii == tempS:<br />
title=i[14:216]<br />
extractL[0][ii]=title<br />
if len(extractL[0]) != len(pdbidsL):<br />
print "Dimension mismatch, seeking troublemaker..."<br />
for i in pdbidsL:<br />
if not any(i == ii for ii in extractL[0]):<br />
extractL[1].append(i)<br />
return extractL<br />
<br />
def disconnectpdb(f):<br />
"""Diconnects the current ftp session<br />
"""<br />
f.quit()<br />
print "Remote connection terminated","\n"<br />
return f<br />
<br />
def releventries(dictionnaryD):<br />
"""Generates a cleaned dictionary with only entries<br />
that have one or more keywords specified in the local<br />
user-defined keywords.txt file<br />
"""<br />
keywL=file2list("keywords.txt")<br />
relevdicD={}<br />
for i in keywL:<br />
for elem,temp in dictionnaryD.items():<br />
if i in temp:<br />
relevdicD[elem]=temp<br />
return relevdicD<br />
<br />
def diskcleanup(filelist=["donotedit.dat","dictionnary.dat"]):<br />
"""Lo-level disk cleanup to free up memory without the user<br />
"""<br />
for filename in filelist:<br />
command='DEL '+filename<br />
os.system(command)<br />
return "clean"<br />
<br />
<br />
<br />
<br />
print "Welcome in the auto-PDB updater !"<br />
<br />
print "Survey of updates made since",days,"days ago."<br />
<br />
print "Acquisition of local time..."<br />
dateS=todaymerge() #Initializes dateS<br />
print "today is ",dateS<br />
print "Connecting to remote ftp server..."<br />
f=connect2pdb() #Connect anonymously to ftp.rcsb.org<br />
<br />
print "Acquisition of latest added remote directories..."<br />
directoriesL=findlastdir(dateS,f,days) #Lists recent directories in directoriesL<br />
if len(directoriesL)==0:<br />
print "No updates have been found since",days,"ago. Starting over with 50 days ago."<br />
directoriesL=findlastdir(dateS,f,50)<br />
<br />
print "Acquisition of latest addedremote files..."<br />
updatesnumberI=compilinfile(directoriesL,f) #Concatenates the corresponding added.pdb into donotedit.dat<br />
<br />
print "Parsing of latest entries..."<br />
pdbidsL=listparser() #Recent names now present in the pdbidsL list (one name per element)<br />
<br />
print "Acquisition of the current pdb distribution..."<br />
dictL=currentrelease(f) #Populates dictL with the current entries of the PDB<br />
<br />
print "Parsing of the current pdb distribution into [code,title] tuples..."<br />
extractL=extract(pdbidsL,dictL) #generates the dictionnary of latest releases key:PDBid ; definition:pdbtitle<br />
<br />
print "Disconnection from the remote ftp server..."<br />
f=disconnectpdb(f) #Closes the ftp instance<br />
<br />
print "Extraction of the relevant entries..."<br />
relevdicD=releventries(extractL[0]) #Generates a subset of dictionnary D with criterion being "has keywords contained in keywords.txt in its title"<br />
<br />
print "Cleaning program-generated temporary files..."<br />
clean=diskcleanup() #Cleans the mess generated by the program<br />
<br />
reportL=[]<br />
reportL.append("\n")<br />
reportL.append("###############REPORT########################################\n")<br />
reportL.append("\n")<br />
lendictS="%i" %(len(dictL))<br />
chmilblik = 'The current pdb version (as of '+dateS+") has "+lendictS+" entries.\n"<br />
reportL.append(chmilblik)<br />
line="The most recent directory is : "+directoriesL[0]+".\n"<br />
reportL.append(line)<br />
updatesnumberS="%i" %(updatesnumberI)<br />
entriesnumber="%i" %(len(extractL[0]))<br />
line="The "+updatesnumberS+" last updates ("+entriesnumber+" entries) have been examined.\n"<br />
reportL.append(line)<br />
diclengthS="%i" %(len(relevdicD))<br />
line=diclengthS+" are relevant to you :\n"<br />
reportL.append(line)<br />
for i,x in relevdicD.items():<br />
entry=i+" : "+x+"\n"<br />
reportL.append(entry)<br />
problemS=""<br />
for i in extractL[1]:<br />
problemS=i+";"+problemS<br />
problemS="["+problemS<br />
problemS=problemS.strip(";")<br />
problemS=problemS+"]"<br />
lineS="The entries "+problemS+" raised problems,"<br />
reportL.append(lineS)<br />
reportL.append("they should be examined manually.")<br />
reportL.append("\n")<br />
reportL.append("###############END OF REPORT#################################\n")<br />
report=open("report.aut","w")<br />
for elem in reportL:<br />
print elem<br />
report.writelines(elem+'\n')<br />
report.close()<br />
command2='start keywords.txt'<br />
command3='start report.aut'<br />
os.system(command2)<br />
os.system(command3)<br />
<br />
cmd.extend("pdbsurvey",pdbsurvey)<br />
</source><br />
<br />
Thank you for any feedback, ways of improving it,...<br />
<br />
[[Category:Script_Library]]<br />
[[Category:System_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=PDB_Web_Services_Script&diff=7993PDB Web Services Script2010-01-26T10:22:50Z<p>Newacct: /* The Code */</p>
<hr />
<div>== Overview ==<br />
A short snippet of code utilizing the new PDB Web Services.<br />
<br />
Notes:<br />
# See [http://www.rcsb.org/robohelp/webservices/summary.htm PDB Web Services]<br />
# You need [http://pywebsvcs.sourceforge.net/ SOAP for Python] installed<br />
# The sequence of a chain fetched from the PDB does not always equal the sequence of a chain fetched from the PDB Web Services. I believe the PDB Web Services has the complete biological chain, not just what's in the structure.<br />
# The offset is a hack; it uses a trick in PyMOL and may not be robust at all. Use at your own caution.<br />
<br />
== The Code ==<br />
<source lang="python"><br />
import pymol<br />
from pymol import stored, cmd<br />
import SOAPpy<br />
<br />
# define a mapping from three letters to one<br />
# Thanks to whomever posted this on the PyMOLWiki:<br />
# http://www.pymolwiki.org/index.php/Label<br />
one_letter ={'VAL':'V', 'ILE':'I', 'LEU':'L', 'GLU':'E', 'GLN':'Q', \<br />
'ASP':'D', 'ASN':'N', 'HIS':'H', 'TRP':'W', 'PHE':'F', 'TYR':'Y', \<br />
'ARG':'R', 'LYS':'K', 'SER':'S', 'THR':'T', 'MET':'M', 'ALA':'A', \<br />
'GLY':'G', 'PRO':'P', 'CYS':'C'}<br />
<br />
# fetch some molecule; yes, 1foo exists in the PDB<br />
cmd.fetch("1foo", async=0)<br />
# get the sequence from PyMOL<br />
stored.pyMOLSeq = []<br />
cmd.iterate( "1foo and c. A and n. CA" , "stored.pyMOLSeq.append( one_letter[resn] )" )<br />
<br />
# open up the PDB web services and make a connection<br />
stored.pyMOLSeq = ''.join( stored.pyMOLSeq )<br />
server = SOAPpy.SOAPProxy("http://www.pdb.org/pdb/services/pdbws")<br />
<br />
# fetch the secondary structure assignment from the PDB &<br />
# split it up into an array of characters<br />
stored.ss = list( server.getKabschSander("1foo", "A") )<br />
<br />
# get the sequence<br />
pdbSeq = server.getSequenceForStructureAndChain("1foo", "A")<br />
# danger: hackishly foolish, but worked for 1foo.<br />
offset = pdbSeq.find( stored.pyMOLSeq )<br />
<br />
# make the assignment in PyMOL<br />
cmd.alter( "1foo and c. A and n. CA and i. " + str(offset) + "-", "ss=stored.ss.pop(0)" )<br />
<br />
# show as cartoons<br />
cmd.as("cartoon")<br />
</source><br />
<br />
[[Category:Script_Library]]<br />
[[Category:UI_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=PDB_Web_Services_Script&diff=7992PDB Web Services Script2010-01-26T10:22:29Z<p>Newacct: </p>
<hr />
<div>== Overview ==<br />
A short snippet of code utilizing the new PDB Web Services.<br />
<br />
Notes:<br />
# See [http://www.rcsb.org/robohelp/webservices/summary.htm PDB Web Services]<br />
# You need [http://pywebsvcs.sourceforge.net/ SOAP for Python] installed<br />
# The sequence of a chain fetched from the PDB does not always equal the sequence of a chain fetched from the PDB Web Services. I believe the PDB Web Services has the complete biological chain, not just what's in the structure.<br />
# The offset is a hack; it uses a trick in PyMOL and may not be robust at all. Use at your own caution.<br />
<br />
== The Code ==<br />
<source lang="python"><br />
import pymol<br />
from pymol import stored, cmd<br />
import SOAPpy<br />
<br />
# define a mapping from three letters to one<br />
# Thanks to whomever posted this on the PyMOLWiki:<br />
# http://www.pymolwiki.org/index.php/Label<br />
one_letter ={'VAL':'V', 'ILE':'I', 'LEU':'L', 'GLU':'E', 'GLN':'Q', \<br />
'ASP':'D', 'ASN':'N', 'HIS':'H', 'TRP':'W', 'PHE':'F', 'TYR':'Y', \<br />
'ARG':'R', 'LYS':'K', 'SER':'S', 'THR':'T', 'MET':'M', 'ALA':'A', \<br />
'GLY':'G', 'PRO':'P', 'CYS':'C'}<br />
<br />
# fetch some molecule; yes, 1foo exists in the PDB<br />
cmd.fetch("1foo", async=0)<br />
# get the sequence from PyMOL<br />
stored.pyMOLSeq = []<br />
cmd.iterate( "1foo and c. A and n. CA" , "stored.pyMOLSeq.append( one_letter[resn] )" )<br />
<br />
# open up the PDB web services and make a connection<br />
stored.pyMOLSeq = ''.join( stored.pyMOLSeq )<br />
server = SOAPpy.SOAPProxy("http://www.pdb.org/pdb/services/pdbws")<br />
<br />
# fetch the secondary structure assignment from the PDB &<br />
# split it up into an array of characters<br />
stored.ss = [ x for x in server.getKabschSander("1foo", "A") ]<br />
<br />
# get the sequence<br />
pdbSeq = server.getSequenceForStructureAndChain("1foo", "A")<br />
# danger: hackishly foolish, but worked for 1foo.<br />
offset = pdbSeq.find( stored.pyMOLSeq )<br />
<br />
# make the assignment in PyMOL<br />
cmd.alter( "1foo and c. A and n. CA and i. " + str(offset) + "-", "ss=stored.ss.pop(0)" )<br />
<br />
# show as cartoons<br />
cmd.as("cartoon")<br />
</source><br />
<br />
[[Category:Script_Library]]<br />
[[Category:UI_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Modevectors&diff=7991Modevectors2010-01-26T10:14:29Z<p>Newacct: </p>
<hr />
<div>[[Image:Modevectors.png|right|thumb|250px|Example showing modevectors in action. (See Examples below).]]<br />
<br />
===DESCRIPTION=== <br />
'''modevectors.py''' is a PyMol script that was originally written to visualize results obtained from Normal Mode Analysis (NMA) by drawing arrows or vectors from a starting structure to a final structure. However, this script can be used to visualize the direction of motion between two specified states (e.g. targeted MD, comparing open and closed structures, etc). The strength of this script is that the arrows are highly customizable with numerous options to choose from (see script below). It is important to note that the two states MUST be identical except for the X, Y, and Z coordinates. That is, you cannot draw vectors between homologous structures. The default settings sets the background to white and displays the arrows along with the first object frame (in cartoon representation).<br />
<br />
<br />
Note: Ray tracing these CGO arrows appears to be a memory intensive process so please save a session before ray tracing and use "pymol -qc" where necessary. If anybody can come up with a method to improve this please e-mail me (see address in script).<br />
<br />
Update: A new way of drawing the arrows has been implemented for PyMOL v.1.1 and has been updated in this code (which automatically detects the version that you are using). The new method uses the built in cone primitive rather than concentric circles decreasing in size. Thus, the new method is much less memory intensive and is a significant improvement over the old method. Additionally, you may want to turn off [[ray shadow]] depending on the [[scene]] that you are viewing as shadows can be confusing to others when seen in publications.<br />
<br />
===USAGE===<br />
<br />
load the script using the [[run]] command<br />
<br />
<source lang="python"><br />
modevectors first_obj_frame, last_obj_frame [,outname=modevectors [,head=1.0 [,tail=0.3 \<br />
[,head_length=1.5 [,headrgb=(1.0,1.0,1.0) [,tailrgb=(1.0,1.0,1.0) [,cutoff=4.0 [,skip=0 \<br />
[,cut=0.5 [,atom=CA [,stat=show [,factor=1.0]]]]]]]]]]]<br />
</source><br />
<br />
Please see the script comments for further custom options. Once the script completes, it will generate a new object called "modevectors" (which can be changed through the options).<br />
<br />
<br />
===EXAMPLES===<br />
<source lang="python"><br />
modevectors 1E3M, 1W7A<br />
modevectors 1E3M, 1W7A, outname="arrows"<br />
modevectors 1E3M, 1W7A, atom="P"<br />
</source><br />
<br />
Copy/paste the following code to see an example of modevectors. This uses a multistate protein and the arrows are connected between the first and last states.<br />
<source lang="python"><br />
# load the code<br />
run modevectors.py<br />
# fetch the PDBs from pdb.org<br />
fetch 1c3y, finish=1, multiplex=0<br />
# separate the first and last states of the NMR ensemble to individual objects<br />
split_states 1c3y, 1, 1<br />
split_states 1c3y, 23, 23<br />
hide<br />
# run the modevectors code<br />
modevectors 1c3y_0001, 1c3y_0023<br />
# just setup a nice representation<br />
as cartoon, 1c3y_0001 or 1c3y_0023<br />
show cgo, modevectors<br />
color marine, 1c3y_0001<br />
color purpleblue, 1c3y_0023<br />
</source><br />
<br />
The following set of examples will illustrate the power of each optional argument. Each example should be compared to the default figure in the table below.<br />
<br />
{|<br />
|[[Image:mv_default.png|thumb|300px|left|Fig.1 - Default Settings]]<br />
||[[Image:mv_fig2.png|thumb|300px|left|Fig.2 - Arrow direction drawn from CA to CA]]<br />
||[[Image:mv_fig3.png|thumb|300px|left|Fig.3 - Arrow head radius]]<br />
|-<br />
|[[Image:mv_fig4.png|thumb|300px|left|Fig.4 - Arrow tail radius]]<br />
||[[Image:mv_fig5.png|thumb|300px|left|Fig.5 - Arrow head length]]<br />
||[[Image:mv_fig6.png|thumb|300px|left|Fig.6 - Arrow head RGB]]<br />
|-<br />
|[[Image:mv_fig7.png|thumb|300px|left|Fig.7 - Arrow tail RGB]]<br />
||[[Image:mv_fig8.png|thumb|300px|left|Fig.8 - Arrow length cutoff]]<br />
||[[Image:mv_fig9.png|thumb|300px|left|Fig.9 - Skip every other arrow]]<br />
|-<br />
|[[Image:mv_fig10.png|thumb|300px|left|Fig.10 - Subtract value from vector length]]<br />
||[[Image:mv_fig11.png|thumb|300px|left|Fig.11 - Draw arrows from CB atoms]]<br />
||[[Image:mv_fig12.png|thumb|300px|left|Fig.12 - Shorten by 50%]]<br />
|-<br />
|||[[Image:mv_fig13.png|thumb|300px|left|Fig.13 - Multiple options being used (see final example below)]]<br />
<br />
|}<br />
<br />
<source lang="python"><br />
fetch 1c3y<br />
split_states 1c3y, 1, 1<br />
split_states 1c3y, 23, 23<br />
hide<br />
<br />
#This is the default setting (Fig.1)<br />
modevectors 1c3y_0001, 1c3y_0023<br />
<br />
#This is shows that the direction of the arrows is drawn from the 1c3y_0001 towards 1c3y_0023 (Fig.2)<br />
show cartoon, 1c3y_0023<br />
color red, 1c3y_0023<br />
<br />
#This controls the base radius of the cone/arrow head in angstroms (Fig.3)<br />
modevectors 1c3y_0001, 1c3y_0023, head=2.5<br />
<br />
#This controls the radius of the cylinders/arrow tails in angstroms (Fig.4)<br />
modevectors 1c3y_0001, 1c3y_0023, tail=0.75<br />
<br />
#This controls the length of the cone/arrow head in angstroms (Fig.5)<br />
#Note that this option does NOT increase the vector length but simply changes the tail length<br />
modevectors 1c3y_0001, 1c3y_0023, head_length=3.0<br />
<br />
#This controls the colour of the cone/arrow head using RGB values (Fig.6)<br />
modevectors 1c3y_0001, 1c3y_0023, headrgb=(1.0,0.0,0.0)<br />
<br />
#This controls the colour of the cylinder/arrow tails using RGB values (Fig.7)<br />
modevectors 1c3y_0001, 1c3y_0023, tailrgb=(1.0,0.0,0.0)<br />
<br />
#This controls the which vectors to show based on a specific cutoff value in angstroms. Vector lengths that are less <br />
#than the cutoff value will not be displayed (Fig.8)<br />
modevectors 1c3y_0001, 1c3y_0023, cutoff=30.0<br />
<br />
#This controls how many vectors to skip (integer value) and is useful when there are too many vectors showing. <br />
#Skip=1 will show every other arrow (Fig.9)<br />
modevectors 1c3y_0001, 1c3y_0023, skip=1<br />
<br />
#This controls how much to cut from each vector (in angstroms). Note that arrows will point in the opposite directions <br />
#when too much is cutoff (resulting in a negative vector length) (Fig.10) and should be used with caution!<br />
modevectors 1c3y_0001, 1c3y_0023, cut=15.0<br />
<br />
#This controls which atom to draw a vector from (Fig.11). Note that this is case-sensitive and is really only useful <br />
#when atom=CA or when atom=P (for DNA backbones)<br />
modevectors 1c3y_0001, 1c3y_0023, atom=CB<br />
<br />
#This controls how much to multiple the length of each vector by (percentage increase/decrease) (Fig.12)<br />
#This example halves the length of each vector (50%)<br />
modevectors 1c3y_0001, 1c3y_0023, factor=0.5<br />
<br />
#This hides the statistics which count atoms skipped, atoms counted (number of arrows showing), and number of atoms <br />
#that did not meet the cutoff and are not shown<br />
modevectors 1c3y_0001, 1c3y_0023, stat=hide<br />
<br />
#Finally, this example shows multiple options being used (Fig.13)<br />
modevectors 1c3y_0001, 1c3y_0023, head=2.0, tail=1.0, head_length=2.0, headrgb=(1.0,0.0,0.0), tailrgb=(0.0,0.0,1.0),<br />
cutoff=0.0,skip=0,cut=0,atom=CA,factor=0.8<br />
<br />
</source><br />
<br />
===PYMOL API===<br />
<source lang=python><br />
from pymol.cgo import * # get constants<br />
from math import *<br />
from pymol import cmd<br />
<br />
def modevectors( first_obj_frame, last_obj_frame, outname="modevectors", head=1.0,tail=0.3, head_length=1.5, headrgb="1.0,1.0,1.0",tailrgb="1.0,1.0,1.0",cutoff=4.0,skip=0,cut=0.5,atom="CA",stat="show",factor=1.0):<br />
"""<br />
Authors Sean Law & Srinivasa<br />
Michigan State University<br />
slaw_(at)_msu_dot_edu<br />
<br />
Editor Sacha Yee<br />
<br />
USAGE<br />
<br />
While in PyMOL<br />
<br />
Parameter Preset Type Description<br />
first_obj_frame Undefined String Object name of the first structure. The mode vector will propagate from this structure. Defined by user.<br />
last_obj_frame Undefined String Object name of the last structure. The mode vector (arrow head) will end at this structure. Defined by user.<br />
outname modevectors String Name of object to store mode vectors in.<br />
head 1.0 Float Radius for the circular base of the arrow head (cone)<br />
tail 0.3 Float Radius for the cylinder of the arrow tail (cylinder)<br />
head_length 1.5 Float Length of the arrow head (from the base of the cone to the tip of cone)<br />
head_rgb 1.0,1.0,1.0 String RGB colour for the arrow head.<br />
tail_rgb 1.0,1.0,1.0 String RGB colour for the arrow tail.<br />
cutoff 4.0 Float Skips mode vectors that do not meet the cutoff distance (in Angstroms).<br />
skip 0 Integer Denotes how many atoms to skip. No arrows will be created for skipped atoms.<br />
cut 0.0 Float Truncates all arrow tail lengths (without disturbing the arrow head) (in Angstroms).<br />
atom CA String Designates the atom to derive mode vectors from.<br />
stat show String Keeps track and prints statistics (total modevectors, skipped, cutoff).<br />
factor 1.0 Float Multiplies each mode vector length by a specified factor.<br />
Values between 0 and 1 will decrease the relative mode vector length.<br />
Values greater than 1 will increase the relative mode vector length.<br />
<br />
"""<br />
<br />
framefirst=cmd.get_model(first_obj_frame)<br />
framelast=cmd.get_model(last_obj_frame)<br />
objectname=outname<br />
factor=float(factor)<br />
arrow_head_radius=float(head)<br />
arrow_tail_radius=float(tail)<br />
arrow_head_length=float(head_length)<br />
cutoff=float(cutoff)<br />
skip=int(skip)<br />
cut=float(cut)<br />
atomtype=atom.strip('"[]()')<br />
<br />
headrgb=headrgb.strip('" []()')<br />
tailrgb=tailrgb.strip('" []()')<br />
hr,hg,hb=map(float,headrgb.split(','))<br />
tr,tg,tb=map(float,tailrgb.split(','))<br />
<br />
version=cmd.get_version()<br />
arrow=[]<br />
arrowhead = []<br />
arrowtail = []<br />
x1 = []<br />
y1 = []<br />
z1 = []<br />
x2 = []<br />
y2 = []<br />
z2 = []<br />
exit_flag=False<br />
<br />
##############################################################<br />
# #<br />
# Define an object called "tail" and store the tail and a #<br />
# circular base of the triangle in this object. #<br />
# #<br />
##############################################################<br />
<br />
skipcount=0<br />
skipcounter=0<br />
keepcounter=0<br />
atom_lookup={}<br />
for atom in framefirst.atom:<br />
if atom.name == atomtype:<br />
if skipcount == skip:<br />
x1.append(atom.coord[0])<br />
y1.append(atom.coord[1])<br />
z1.append(atom.coord[2])<br />
<br />
##########################################<br />
# #<br />
# Set atom_lookup for a specific atom #<br />
# equal to ONE for the first input set. #<br />
# This dictionary will be used as a #<br />
# reference for the second set. #<br />
# #<br />
##########################################<br />
<br />
current_atom="CHAIN "+atom.chain+" RESID "\<br />
+atom.resi+" RESTYPE "\<br />
+atom.resn+\<br />
" ATMNUM "+str(atom.index)<br />
# print current_atom<br />
atom_lookup['current_atom']=1<br />
<br />
skipcount=0<br />
keepcounter+=1<br />
else:<br />
# print skipcount<br />
skipcount+=1<br />
skipcounter+=1<br />
<br />
skipcount=0<br />
for atom in framelast.atom:<br />
if atom.name == atomtype:<br />
if skipcount == skip:<br />
x2.append(atom.coord[0])<br />
y2.append(atom.coord[1])<br />
z2.append(atom.coord[2])<br />
<br />
#########################################<br />
# #<br />
# Get atom information from second set #<br />
# and compare with first set. All #<br />
# atoms from this second set MUST be #<br />
# found in the first set! Otherwise, #<br />
# the script will exit with an error #<br />
# since modevectors can only be created #<br />
# by calculating values from identical #<br />
# sources. #<br />
# #<br />
#########################################<br />
<br />
current_atom="CHAIN "+atom.chain+" RESID "\<br />
+atom.resi+" RESTYPE "\<br />
+atom.resn+\<br />
" ATMNUM "+str(atom.index)<br />
# print current_atom<br />
if 'current_atom' not in atom_lookup:<br />
print "\nError: "+current_atom+" from \""\<br />
+last_obj_frame+\<br />
" \"is not found in \""+first_obj_frame+"\"."<br />
print "\nPlease check your input and/or selections and try again."<br />
exit_flag=True<br />
break<br />
<br />
skipcount=0<br />
else:<br />
skipcount+=1<br />
<br />
if exit_flag:<br />
###########################################<br />
# #<br />
# Exit script because an atom cannot be #<br />
# found in both input files #<br />
# #<br />
###########################################<br />
return<br />
<br />
cutoff_counter=0 # Track number of atoms failing to meet the cutoff<br />
<br />
###################################################<br />
# #<br />
# Check that the two selections/PDB files contain #<br />
# the same number of atoms. #<br />
# #<br />
###################################################<br />
<br />
if len(x2) != len(x1):<br />
print "\nError: \""+first_obj_frame+\<br />
"\" and \""+last_obj_frame+\<br />
"\" contain different number of residue/atoms."<br />
print "\nPlease check your input and/or selections and try again."<br />
return<br />
else:<br />
#Continue with representing modevectors!<br />
#########################################<br />
# #<br />
# Delete old selection or object if it #<br />
# exists so that it can be overwritten #<br />
# #<br />
#########################################<br />
save_view=cmd.get_view(output=1,quiet=1)<br />
cmd.delete(name=outname)<br />
cmd.hide(representation="everything",selection=first_obj_frame)<br />
cmd.hide(representation="everything",selection=last_obj_frame)<br />
<br />
<br />
<br />
###################################################<br />
# #<br />
# Begin drawing arrow tails #<br />
# #<br />
###################################################<br />
<br />
arrowtail = []<br />
for mv in range(len(x1)):<br />
vectorx=x2[mv]-x1[mv]<br />
vectory=y2[mv]-y1[mv]<br />
vectorz=z2[mv]-z1[mv]<br />
length=sqrt(vectorx**2+vectory**2+vectorz**2)<br />
if length < cutoff:<br />
cutoff_counter+=1<br />
continue<br />
t=1.0-(cut/length)<br />
x2[mv]=x1[mv]+factor*t*vectorx<br />
y2[mv]=y1[mv]+factor*t*vectory<br />
z2[mv]=z1[mv]+factor*t*vectorz<br />
vectorx=x2[mv]-x1[mv]<br />
vectory=y2[mv]-y1[mv]<br />
vectorz=z2[mv]-z1[mv]<br />
length=sqrt(vectorx**2+vectory**2+vectorz**2)<br />
d=arrow_head_length # Distance from arrow tip to arrow base<br />
t=1.0-(d/length)<br />
tail = [<br />
# Tail of cylinder<br />
CYLINDER, x1[mv],y1[mv],z1[mv]\<br />
,x1[mv]+(t+0.01)*vectorx,y1[mv]+(t+0.01)*vectory,z1[mv]+(t+0.01)*vectorz\<br />
,arrow_tail_radius,tr,tg,tb,tr,tg,tb # Radius and RGB for each cylinder tail<br />
]<br />
arrow.extend(tail)<br />
<br />
x=x1[mv]+t*vectorx<br />
y=y1[mv]+t*vectory<br />
z=z1[mv]+t*vectorz<br />
dx=x2[mv]-x<br />
dy=y2[mv]-y<br />
dz=z2[mv]-z<br />
seg=d/100<br />
intfactor=int(factor)<br />
if version < 1.1: #Version >= 1.1 has cone primitive<br />
for i in range (100,0,-1): #i=100 is tip of cone<br />
print i<br />
t1=seg*i<br />
t2=seg*(i+1)<br />
radius=arrow_head_radius*(1.0-i/(100.0)) #Radius of each disc that forms cone<br />
head=[<br />
CYLINDER, x+t2*dx,y+t2*dy,z+t2*dz\<br />
,x+t1*dx,y+t1*dy,z+t1*dz\<br />
,radius,hr,hg,hb,hr,hg,hb # Radius and RGB for slice of arrow head<br />
]<br />
arrow.extend(head)<br />
else:<br />
head=[<br />
CONE, x, y ,z, x+d*dx, y+d*dy, z+d*dz, arrow_head_radius, 0.0, hr, hg, hb, hr, hg, hb, 1.0, 1.0 ]<br />
arrow.extend(head)<br />
<br />
##############################################################<br />
# #<br />
# Load the entire object into PyMOL #<br />
# #<br />
# Print statistics if requested by user #<br />
# #<br />
##############################################################<br />
<br />
if stat == "show":<br />
natoms=skipcounter+keepcounter<br />
print "\nTotal number of atoms = "+str(natoms)<br />
print "Atoms skipped = "+str(skipcounter)<br />
if keepcounter-cutoff_counter > 0:<br />
print "Atoms counted = "+str(keepcounter-cutoff_counter)+" (see PyMOL object \""+outname+"\")"<br />
else:<br />
print "Atoms counted = "+str(keepcounter-cutoff_counter)+" (Empty CGO object not loaded)" <br />
print "Atoms cutoff = "+str(cutoff_counter) #Note that cutoff occurs AFTER skipping!<br />
if keepcounter-cutoff_counter > 0:<br />
cmd.load_cgo(arrow,objectname) #Ray tracing an empty object will cause a segmentation fault. No arrows = Do not display in PyMOL!!!<br />
cmd.show(representation="cartoon",selection=first_obj_frame)<br />
cmd.cartoon("tube")<br />
cmd.show(representation="cartoon",selection=last_obj_frame)<br />
cmd.hide(representation="cartoon",selection=last_obj_frame)<br />
cmd.bg_color(color="white")<br />
cmd.set_view(save_view)<br />
return<br />
<br />
cmd.extend("modevectors",modevectors)<br />
</source><br />
[[Category:Script_Library]]<br />
[[Category:Math_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=7794Rotamer Toggle2009-12-28T02:19:32Z<p>Newacct: </p>
<hr />
<div>===DESCRIPTION===<br />
Backbone-Dependent Rotamer library (Dunbrack, Cohen ; see ref) is imported into pymol giving access to this information. There are a number of different ways to use the data, I've only implemented a few as well as added extra functions that seemed useful.<br />
*Rotamer Menu - an added menu into menu.py, which displays the most common rotamers for the given(clicked) residue; you can also set the residue any of the common rotamers as well<br />
*colorRotamers - color rotamers by closest matching rotamer angles from database; i.e. color by how common each rotamer of selection, blue - red (least to most common).<br />
*set_rotamer - routine called by above menu, but can be called manually to set a specific residues side-chain angles<br />
*set_phipsi - set all phi,psi angles of given selection to given angles (useful for creating secondary structures)<br />
*createRotamerPDBs - create pdb for each rotamer of given selection ; filter by rotamer-probability<br />
<br />
===IMAGES===<br />
<gallery><br />
Image:RotamerMenu.png|Rotamer Menu for a GLN residue<br />
Image:GLURotamerComparison5.png|Rotamer Comparison of crystal structure and most common for GLU; just as an example<br />
</gallery><br />
<br />
Print out while selecting most common rotamer from above-left image (GLN residue):<br />
Given GLN:40 PHI,PSI (-171.626373291,-96.0500335693) : bin (-170,-100)<br />
CHIs: [179.18069458007812, 72.539344787597656, -47.217315673828125]<br />
Setting Chi1 to -176.9<br />
Setting Chi2 to 177.4<br />
Setting Chi3 to 0.7<br />
<br />
===SETUP===<br />
run "rotamers.py" and use functions from commandline.<br />
<br />
or<br />
<br />
To setup a rotamer menu inside the residue menu (default windows pymol installation):<br />
*copy rotamers.py to C:/Program Files/DeLano Scientific/PyMol/modules/pymol/rotamers.py<br />
*copy mymenu.py to C:/Program Files/DeLano Scientific/PyMol/modules/pymol/menu.py (WARNING : overwrites default menu.py - use at your own risk)<br />
*copy bbdep02.May.sortlib to C:/Program Files/DeLano Scientific/PyMol/modules/pymol/bbdep02.May.sortlib (or newer version of sorted bbdep)<br />
This is only one possible way to do this, I am sure there are many others. I'm not going to post the bbdep, but there is a link in the References section to Dunbrack's download page (get the "sorted" lib)<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform, Red Hat Linux 9.0 and Fedora Core 4. Will test v0.98 and MacOSX later on.<br />
*The way it's setup now, when you import rotamers , it will automatically read-in the rotamer database; this may not be what you want.<br />
*Post problems in the discussion page, on 'my talk' page or just email me : dwkulp@mail.med.upenn.edu<br />
<br />
TASKS TODO:<br />
*Rotamer Movie, using mset, etc create movie to watch cycle through rotamers<br />
*Code could be organized a bit better; due to time constraints this is good for now..<br />
<br />
TASKS DONE:<br />
*Store crystal structure in rotamer menu, so you can go back to original orientation<br />
<br />
===USAGE===<br />
colorRotamers selection<br />
set_rotamer selection, chi1_angle [,chi2_angle] [,chi3_angle] [,chi4_angle]<br />
set_phipsi selection phi_angle, psi_angle<br />
createRotamerPBDs selection [,ncutoff] [,pcutoff] [,prefix]<br />
<br />
===EXAMPLES===<br />
colorRotamers chain A<br />
set_rotamer resi 40, -60,-40 (only set chi1,chi2 angles)<br />
set_phipsi resi 10-40, -60,-60 (create an alpha-helical-like section)<br />
createRotamerPDBs resi 10-12, ncutoff=3 (create 9 PDBs; each with one of the 3 most probable rotamers for resi 10,11,12)<br />
createRotamerPDBs resi 14, pcutoff=0.4 (create a pdb file for each rotamer of residue 14 with probablity > 0.4)<br />
<br />
===REFERENCES===<br />
Dunbrack and Cohen. Protein Science 1997<br />
<br />
[http://dunbrack.fccc.edu/bbdep/index.php Dunbrack Lab Page (Contains backbone-dependent library)]<br />
<br />
===SCRIPTS (Rotamers.py ; MyMenu.py)===<br />
Rotamers.py <br />
<source lang="python"><br />
##################################################################<br />
# File: Rotamers.py<br />
# Author: Dan Kulp<br />
# Creation Date: 6/8/05<br />
# Contact: dwkulp@mail.med.upenn.edu<br />
#<br />
# Notes:<br />
# Incorporation of Rotamer library<br />
# readRotLib() - fills rotdat; <br />
# indexed by "RES:PHI_BIN:PSI_BIN".<br />
#<br />
# Three main functions:<br />
# 1. colorRotamers - colors according<br />
# to rotamer probablitity<br />
# 2. getBins(sel)<br />
# phi,psi bin for rotamer<br />
# 3. set_rotamer - set a side-chain <br />
# to a specific rotamer <br />
#<br />
# To setup a rotamer menu in the <br />
# right click, under "Residue"<br />
# 1. cp mymenu.py modules/pymol/menu.py<br />
# 2. cp rotamers.py modules/pymol/rotamers.py (update ROTLIB)<br />
#<br />
# Requirements:<br />
# set ROTLIB to path for rotamer library<br />
# Reference: <br />
# Dunbrack and Cohen. Protein Science 1997<br />
####################################################################<br />
<br />
import colorsys,sys<br />
import re<br />
import editing<br />
import os<br />
import cmd<br />
import math<br />
<br />
# Path for library<br />
ROTLIB=os.environ['PYMOL_PATH']+"/modules/pymol/bbdep02.May.sortlib"<br />
<br />
# Place for library in memory..<br />
rotdat = {}<br />
<br />
def readRotLib(): <br />
# Column indexes in rotamer library..<br />
RES = 0<br />
PHI = 1<br />
PSI = 2<br />
PROB = 8<br />
CHI1 = 9<br />
CHI2 = 10<br />
CHI3 = 11<br />
CHI4 = 12<br />
<br />
if os.path.exists(ROTLIB):<br />
print "File exists: "+ROTLIB<br />
input = open(ROTLIB, 'r')<br />
for line in input:<br />
<br />
# Parse by whitespace (I believe format is white space and not fixed-width columns)<br />
dat = re.split("\s+",line)<br />
<br />
# Add to rotamer library in memory : <br />
# key format RES:PHI_BIN:PSI_BIN<br />
# value format PROB, CHI1, CHI2, CHI3, CHI4<br />
key = dat[RES]+":"+dat[PHI]+":"+dat[PSI]<br />
if key in rotdat:<br />
rotdat[key].append([ dat[PROB], dat[CHI1], dat[CHI2], dat[CHI3], dat[CHI4] ])<br />
else:<br />
rotdat[key] = [ [ dat[PROB], dat[CHI1], dat[CHI2], dat[CHI3], dat[CHI4] ] ]<br />
<br />
<br />
else:<br />
print "Couldn't find Rotamer library"<br />
<br />
<br />
# Atoms for each side-chain angle for each residue<br />
CHIS = {}<br />
CHIS["ARG"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","NE" ],<br />
["CG","CD","NE","CZ" ]<br />
]<br />
<br />
CHIS["ASN"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","OD2" ]<br />
]<br />
<br />
CHIS["ASP"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","OD1" ]<br />
]<br />
CHIS["CYS"] = [ ["N","CA","CB","SG" ]<br />
]<br />
CHIS["GLN"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","OE1"]<br />
]<br />
<br />
CHIS["GLU"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","OE1"]<br />
]<br />
<br />
CHIS["HIS"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","ND1"]<br />
]<br />
<br />
CHIS["ILE"] = [ ["N","CA","CB","CG1" ],<br />
["CA","CB","CG1","CD1" ]<br />
]<br />
<br />
CHIS["LEU"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1" ]<br />
]<br />
<br />
CHIS["LYS"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","CE"],<br />
["CG","CD","CE","NZ"]<br />
]<br />
<br />
CHIS["MET"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","SD" ],<br />
["CB","CG","SD","CE"]<br />
]<br />
<br />
CHIS["PHE"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1" ]<br />
]<br />
<br />
CHIS["PRO"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ]<br />
]<br />
<br />
CHIS["SER"] = [ ["N","CA","CB","OG" ]<br />
]<br />
<br />
CHIS["THR"] = [ ["N","CA","CB","OG1" ]<br />
]<br />
<br />
CHIS["TRP"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1"]<br />
]<br />
<br />
CHIS["TYR"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1" ]<br />
]<br />
<br />
CHIS["VAL"] = [ ["N","CA","CB","CG1" ]<br />
]<br />
<br />
# Color Rotamer by side-chain angle position<br />
# 'bin' side-chain angles into closest<br />
def colorRotamers(sel):<br />
doRotamers(sel)<br />
<br />
# Utility function, to set phi,psi angles for a given selection<br />
# Note: Cartoon, Ribbon functionality will not display correctly after this<br />
def set_phipsi(sel, phi,psi):<br />
doRotamers(sel,angles=[phi,psi],type="set")<br />
<br />
# Set a rotamer, based on a selection, a restype and chi angles<br />
def set_rotamer(sel, chi1, chi2=0,chi3=0,chi4=0):<br />
at = cmd.get_model("byres ("+sel+")").atom[0]<br />
<br />
list = [chi1,chi2,chi3,chi4]<br />
for i in range(len(CHIS[at.resn])):<br />
print "Setting Chi"+str(i+1)+" to "+str(list[i])<br />
editing.set_dihedral(sel + ' and name '+CHIS[at.resn][i][0], <br />
sel + ' and name '+CHIS[at.resn][i][1], <br />
sel + ' and name '+CHIS[at.resn][i][2], <br />
sel + ' and name '+CHIS[at.resn][i][3], str(list[i])) <br />
<br />
# Remove some objects that got created<br />
cmd.delete("pk1")<br />
cmd.delete("pk2")<br />
cmd.delete("pkmol")<br />
<br />
# Get Phi,Psi bins for given selection<br />
# WARNING: assume selection is single residue (will only return first residue bins)<br />
def getBins(sel):<br />
return doRotamers(sel, type="bins")<br />
<br />
# Color Ramp...<br />
def rot_color(vals): <br />
nbins = 10<br />
vals.sort(key=lambda x: x[1])<br />
# print "End sort: "+str(len(vals))+" : "+str(nbins)<br />
<br />
<br />
# Coloring scheme...<br />
j = 0<br />
rgb = [0.0,0.0,0.0]<br />
sel_str = ""<br />
for i in range(len(vals)):<br />
if int(len(vals)/nbins) == 0 or i % int(len(vals)/nbins) == 0:<br />
hsv = (colorsys.TWO_THIRD - colorsys.TWO_THIRD * float(j) / (nbins-1), 1.0, 1.0)<br />
<br />
#convert to rgb and append to color list<br />
rgb = colorsys.hsv_to_rgb(hsv[0],hsv[1],hsv[2])<br />
if j < nbins-1:<br />
j += 1 <br />
<br />
cmd.set_color("RotProbColor"+str(i), rgb)<br />
cmd.color("RotProbColor"+str(i), str(vals[i][0]))<br />
<br />
<br />
# Main function <br />
def doRotamers(sel,angles=[], type="color"): <br />
<br />
# Read in Rotamer library if not already done<br />
if len(rotdat) == 0:<br />
readRotLib()<br />
<br />
# Set up some variables..<br />
residues = ['dummy'] # Keep track of residues already done<br />
probs = [] # probability of each residue conformation<br />
phi = 0 # phi,psi angles of current residue<br />
psi = 0<br />
<br />
# Get atoms from selection<br />
atoms = cmd.get_model("byres ("+sel+")")<br />
<br />
# Loop through atoms in selection <br />
for at in atoms.atom:<br />
try:<br />
# Don't process Glycines or Alanines<br />
if not (at.resn == 'GLY' or at.resn == 'ALA'):<br />
if at.chain+":"+at.resn+":"+at.resi not in residues:<br />
residues.append(at.chain+":"+at.resn+":"+at.resi)<br />
<br />
# Check for a null chain id (some PDBs contain this) <br />
unit_select = ""<br />
if at.chain != "":<br />
unit_select = "chain "+str(at.chain)+" and "<br />
<br />
# Define selections for residue i-1, i and i+1 <br />
residue_def = unit_select+'resi '+str(at.resi)<br />
residue_def_prev = unit_select+'resi '+str(int(at.resi)-1)<br />
residue_def_next = unit_select+'resi '+str(int(at.resi)+1)<br />
<br />
# Compute phi/psi angle<br />
<br />
phi = cmd.get_dihedral(residue_def_prev+' and name C',residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C',residue_def_next+' and name N')<br />
if type == "set":<br />
print "Changing "+at.resn+str(at.resi)+" from "+str(phi)+","+str(psi)+" to "+str(angles[0])+","+str(angles[1])<br />
cmd.set_dihedral(residue_def_prev+' and name C',residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C',residue_def_next+' and name N', angles[1])<br />
continue<br />
<br />
# Find correct 10x10 degree bin <br />
phi_digit = abs(int(phi)) - abs(int(phi/10)*10)<br />
psi_digit = abs(int(psi)) - abs(int(psi/10)*10)<br />
<br />
# Remember sign of phi,psi angles<br />
phi_sign = 1<br />
if phi < 0: phi_sign = -1<br />
<br />
psi_sign = 1<br />
if psi < 0: psi_sign = -1<br />
<br />
# Compute phi,psi bins<br />
phi_bin = int(math.floor(abs(phi/10))*10*phi_sign)<br />
if phi_digit >= 5: phi_bin = int(math.ceil(abs(phi/10))*10*phi_sign)<br />
<br />
psi_bin = int(math.floor(abs(psi/10))*10*psi_sign)<br />
if psi_digit >= 5: psi_bin = int(math.ceil(abs(psi/10))*10*psi_sign)<br />
<br />
print "Given "+at.resn+":"+at.resi+" PHI,PSI ("+str(phi)+","+str(psi)+") : bin ("+str(phi_bin)+","+str(psi_bin)+")"<br />
<br />
<br />
# Get current chi angle measurements<br />
chi = []<br />
for i in range(len(CHIS[at.resn])):<br />
chi.append(cmd.get_dihedral(residue_def + ' and name '+CHIS[at.resn][i][0], <br />
residue_def + ' and name '+CHIS[at.resn][i][1], <br />
residue_def + ' and name '+CHIS[at.resn][i][2], <br />
residue_def + ' and name '+CHIS[at.resn][i][3])) <br />
print "CHIs: "+str(chi)<br />
if type == 'bins':<br />
return [at.resn, phi_bin,psi_bin]<br />
<br />
# Compute probabilities for given chi angles<br />
prob = 0<br />
prob_box = 22 <br />
for item in range(len(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)])):<br />
print "Rotamer from db: "+str(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item])<br />
if chi[0]:<br />
if chi[0] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][1]) - (prob_box/2) and \<br />
chi[0] <= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][1]) + (prob_box/2):<br />
if len(chi) == 1:<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
if chi[1] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][2]) - (prob_box/2) and \<br />
float(chi[1] <= rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][2]) + (prob_box/2):<br />
if len(chi) == 2:<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
if chi[2] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][3]) - (prob_box/2) and \<br />
float(chi[2] <= rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][3]) + (prob_box/2):<br />
if len(chi) == 3:<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
if chi[3] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][4]) - (prob_box/2) and \<br />
float(chi[3] <= rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][4]) + (prob_box/2):<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
<br />
<br />
print "PROB OF ROTAMER: "+str(prob)<br />
print "---------------------------"<br />
probs.append([residue_def, prob])<br />
<br />
except:<br />
# probs.append([residue_def, -1])<br />
print "Exception found"<br />
continue<br />
<br />
# Color according to rotamer probability<br />
rot_color(probs) <br />
<br />
<br />
<br />
<br />
# Create PDB files containing most probable rotamers<br />
def createRotamerPDBs(sel,ncutoff=10,pcutoff=0,prefix="ROTAMER"):<br />
<br />
# Get atoms from selection<br />
atoms = cmd.get_model("byres ("+sel+")")<br />
<br />
# Set up some variables..<br />
residues = ['dummy'] # Keep track of residues already done<br />
<br />
# Loop through atoms in selection <br />
for at in atoms.atom:<br />
if at.resn in ('GLY', 'ALA') or "%s:%s:%s" % (at.chain,at.resn,at.resi) in residues:<br />
continue<br />
<br />
# Add to residue list (keep track of which ones we've done)<br />
residues.append("%s:%s:%s" % (at.chain,at.resn,at.resi))<br />
<br />
# Check for a null chain id (some PDBs contain this) <br />
unit_select = ""<br />
if at.chain != "":<br />
unit_select = "chain "+str(at.chain)+" and "<br />
<br />
# Define selections for residue <br />
residue_def = unit_select+'resi '+str(at.resi)<br />
<br />
# Get bin (phi,psi) definitions for this residue<br />
bin = doRotamers(residue_def, type='bins')<br />
<br />
# Store crystal angle<br />
crystal_angles = [0.0,0.0,0.0,0.0]<br />
for angle in range(3):<br />
try:<br />
crystal_angles[angle] = bin[3][angle]<br />
except IndexError:<br />
break<br />
<br />
# Retreive list of rotamers for this phi,psi bin + residue type<br />
match_rotamers = rotdat["%s:%s:%s" % (bin[0],str(bin[1]),str(bin[2]))]<br />
<br />
count = 0<br />
for item in range(len(match_rotamers)):<br />
<br />
# Store probablity<br />
prob = match_rotamers[item][0]<br />
<br />
# Check cutoffs<br />
if float(prob) <= float(pcutoff):<br />
continue<br />
<br />
if float(count) >= float(ncutoff):<br />
break<br />
<br />
# Increment count<br />
count += 1<br />
<br />
# Output to screen ...<br />
print "Residue %s%s, rotamer %i, prob %s" % (at.resn,at.resi,item,prob)<br />
<br />
# Set to new rotamer<br />
set_rotamer(residue_def,match_rotamers[item][1],match_rotamers[item][2],match_rotamers[item][3],match_rotamers[item][4]) <br />
<br />
# Store in PDB file<br />
cmd.save("%s_%s%s_%i_%s.pdb" % (prefix,str(at.resn),str(at.resi),int(item),str(prob)))<br />
<br />
# Reset crystal angle<br />
set_rotamer(residue_def,crystal_angles[0],crystal_angles[1],crystal_angles[2],crystal_angles[3])<br />
<br />
# Uncommenting this is nice because it loads rotamer library upon startup<br />
# however, it slows the PyMOL loading process a lot<br />
# instead I've put this call into the menuing code..<br />
# readRotLib()<br />
<br />
cmd.extend('set_phipsi',set_phipsi)<br />
cmd.extend('set_rotamer',set_rotamer)<br />
cmd.extend('colorRotamers',colorRotamers)<br />
cmd.extend('createRotamerPDBs',createRotamerPDBs)<br />
<br />
</source><br />
<br />
MyMenu.py<br />
Since menu.py is copyrighted I can't post my edited version, but you can create it very simply by adding these two peices of code<br />
<br />
1. In the "pick_option(title,s,object=0)" function of menu.py add the following code after the first "result =" statement<br />
<source lang="python"><br />
# Edit dwkulp 6/11/05 , add a rotamer menu to residue menu<br />
if title == 'Residue':<br />
result.extend([[ 1, 'rotamers' , rotamer_menu(s)]])<br />
</source><br />
<br />
2. At the end of the file add this:<br />
<source lang="python"><br />
###############################################<br />
# Dan Kulp<br />
# Added Rotamer list to residue menu..<br />
# rotamer.py must be importable (I placed it in <br />
# the same directory as menu.py)<br />
###############################################<br />
<br />
import rotamers<br />
<br />
<br />
def rotamer_menu(s):<br />
# Check for rotamer library being loaded<br />
if not rotamers.rotdat:<br />
rotamers.readRotLib()<br />
# return [ [2, "Must run rotamers.py first",'']]<br />
<br />
# Check for valid rotamer residue..<br />
res = cmd.get_model("byres ("+s+")").atom[0].resn<br />
if not res in rotamers.CHIS.keys():<br />
return [ [2, "Residue: "+res+" not known sidechain or does not have rotamers", '']]<br />
<br />
# Get PHI,PSI bins for rotamer (also prints out current phi,psi, chi1,chi2,chi3,chi4)<br />
bins = rotamers.doRotamers(s,type='bins')<br />
<br />
# Add a title to the menu<br />
result = [ [2, bins[0]+' Rotamers in bin ('+str(bins[1])+','+str(bins[2])+')','' ], [1, ':::PROB,CHI1,CHI2,CHI3,CHI4:::','']]<br />
<br />
# Grab the entries for this residue and phi,psi bins<br />
match_rotamers = rotamers.rotdat[bins[0]+":"+str(bins[1])+":"+str(bins[2])]<br />
<br />
# Set max number of rotamers to display (probably should be somewhere 'higher up' in the code)<br />
max_rotamers = min(10, len(match_rotamers))<br />
<br />
# Create menu entry for each possible rotamer<br />
for item in range(max_rotamers):<br />
result.append( [ 1, str(match_rotamers[item]), 'rotamers.set_rotamer("'+s+'","'\<br />
+str(match_rotamers[item][1])+'","'\<br />
+str(match_rotamers[item][2])+'","'\<br />
+str(match_rotamers[item][3])+'","'\<br />
+str(match_rotamers[item][4])+'")'])<br />
return result<br />
<br />
<br />
</source><br />
<br />
<br />
[[Category:Script_Library|Rotamer Toggle]]<br />
<br />
[[Category:Structural_Biology_Scripts|Rotamer Toggle]]</div>Newaccthttps://pymolwiki.org/index.php?title=Apropos&diff=7793Apropos2009-12-23T06:59:13Z<p>Newacct: </p>
<hr />
<div>'''DESCRIPTION'''<br />
<br />
"apropos" searches through the documentation of all currently defined commands and lists those commands for which the keyword is either contained in the documentation or matches the command name itself.<br />
<br />
If an appropriate '''DESCRIPTION''' section is provided in the documentation of the command, the first 80 characters are listed as a summary.<br />
<br />
'''INSTALLATION'''<br />
<br />
1. copy the script bellow to a folder and name it ''apropos.py'' <br />
<br />
2. run it from within pymol with the '''run''' command:<br />
<source lang="python"><br />
run apropos.py<br />
</source><br />
<br />
3. see example bellow on how to use it<br />
<br />
'''USAGE'''<br />
<source lang="python"><br />
apropos [keyword or regexp]<br />
</source><br />
<br />
'''EXAMPLE'''<br />
<br />
''apropos fit''<br />
<pre><br />
###EXACT MATCH FOR: fit ==> try 'help fit' at the prompt.<br />
<br />
###The following commands are NOT documented.<br />
<br />
vdw_fit<br />
<br />
###The following commands are documented. 'help command' <br />
<br />
fit : "fit" superimposes the model in the first selection on to the model<br />
intra_fit : "intra_fit" fits all states of an object to an atom selection<br />
rms : "rms" computes a RMS fit between two atom selections, but does not<br />
pair_fit : "pair_fit" fits a set of atom pairs between two models. Each atom<br />
intra_rms_cur : "intra_rms_cur" calculates rms values for all states of an object<br />
commands : >>>>>>>> Ooopsie, no DESCRIPTION found for this command!!! <<<<<<<br />
zoom : "zoom" scales and translates the window and the origin to cover the<br />
intra_rms : "intra_rms" calculates rms fit values for all states of an object<br />
align : "align" performs a sequence alignment followed by a structural<br />
rms_cur : "rms_cur" computes the RMS difference between two atom<br />
fitting : "fitting" allows the superpositioning of object1 onto object2 using<br />
</pre><br />
<br />
'''SEE ALSO'''<br />
grepset(www.pymolwiki.org), Python re module<br />
<br />
'''apropos.py'''<br />
<source lang="python"><br />
#<br />
# apropos.py <br />
# Author: Ezequiel Panepucci<br />
# Date: 2006-07-20<br />
#<br />
from pymol import cmd<br />
import re<br />
<br />
def apropos(regexp=''):<br />
'''<br />
DESCRIPTION<br />
"apropos" searches through the documentation of all currently <br />
defined commands and lists those commands for which the keyword<br />
is either contained in the documentation or matches the command<br />
name itself.<br />
<br />
If an appropriate "DESCRIPTION" section is provided in the documentation<br />
of the command, the first 80 characters are listed as a summary.<br />
<br />
USAGE<br />
apropos [keyword or regexp]<br />
<br />
EXAMPLE<br />
apropos fit<br />
<br />
###EXACT MATCH FOR: fit ==> try 'help fit' at the prompt.<br />
<br />
###The following commands are NOT documented.<br />
<br />
vdw_fit<br />
<br />
###The following commands are documented. 'help command' <br />
<br />
fit : "fit" superimposes the model in the first selection on to the model<br />
intra_fit : "intra_fit" fits all states of an object to an atom selection<br />
rms : "rms" computes a RMS fit between two atom selections, but does not<br />
pair_fit : "pair_fit" fits a set of atom pairs between two models. Each atom<br />
intra_rms_cur : "intra_rms_cur" calculates rms values for all states of an object<br />
commands : >>>>>>>> Ooopsie, no DESCRIPTION found for this command!!! <<<<<<<br />
zoom : "zoom" scales and translates the window and the origin to cover the<br />
intra_rms : "intra_rms" calculates rms fit values for all states of an object<br />
align : "align" performs a sequence alignment followed by a structural<br />
rms_cur : "rms_cur" computes the RMS difference between two atom<br />
fitting : "fitting" allows the superpositioning of object1 onto object2 using<br />
<br />
SEE ALSO<br />
grepset(www.pymolwiki.org), Python re module<br />
'''<br />
cmd.set("text","1",quiet=1)<br />
<br />
count=0<br />
docre = re.compile(regexp, re.MULTILINE | re.IGNORECASE)<br />
cmdre = re.compile(regexp, re.IGNORECASE)<br />
<br />
matches_with_help = []<br />
matches_without_help = []<br />
<br />
maxcclen=0<br />
for cc in cmd.keyword:<br />
if cc == regexp:<br />
print '\n###EXACT MATCH FOR: %s ==> try \'help %s\' at the prompt.' % (cc,cc)<br />
<br />
doc = cmd.keyword[cc][0].__doc__<br />
<br />
if doc == None:<br />
if re.search(regexp, cc, re.IGNORECASE):<br />
count += 1<br />
matches_without_help.append(cc)<br />
continue<br />
<br />
if re.search(regexp, doc, re.MULTILINE | re.IGNORECASE):<br />
count += 1<br />
if len(cc) > maxcclen:<br />
maxcclen = len(cc)<br />
<br />
docmatches = re.match(r"""^\s+DESCRIPTION\s+(.{0,80})\S*""", doc, re.IGNORECASE)<br />
if docmatches == None:<br />
desc = '>>>>>>>> Ooopsie, no DESCRIPTION found for this command!!! <<<<<<'<br />
else:<br />
desc = docmatches.group(1)<br />
matches_with_help.append( (cc, desc ) )<br />
<br />
<br />
if len(matches_without_help) > 0:<br />
print '\n###The following commands are NOT documented.\n'<br />
for cc in matches_without_help:<br />
print '%*s' % (maxcclen, cc)<br />
<br />
if len(matches_with_help) > 0:<br />
print '\n###The following commands are documented. \'help command\' \n'<br />
for cc,desc in matches_with_help:<br />
print '%*s : %s' % (maxcclen, cc,desc)<br />
<br />
cmd.extend('apropos',apropos)<br />
<br />
</source><br />
<br />
''Author: Ezequiel (Zac) Panepucci''<br />
<br />
[[Category:Script_Library|Apropos]]<br />
[[Category:UI_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=DynoPlot&diff=7724DynoPlot2009-12-17T20:21:56Z<p>Newacct: </p>
<hr />
<div>===DESCRIPTION===<br />
This script was setup to do generic plotting, that is given a set of data and axis labels it would create a plot. Initially, I had it setup to draw the plot directly in the PyMol window (allowing for both 2D and 3D style plots), but because I couldn't figure out how to billboard CGO objects (Warren told me at the time that it couldn't be done) I took a different approach. The plot now exists in it's own window and can only do 2D plots. It is however interactive. I only have here a Rama.(phi,psi) plot, but the code can be easily extended to other types of data. For instance, I had this working for an energy vs distance data that I had generated by another script.<br />
<br />
This script will create a Phi vs Psi(Ramachandran) plot of the selection given. The plot will display data points which can be dragged around Phi,Psi space with the corresponding residue's Phi,Psi angles changing in the structure (PyMol window).<br />
<br />
===IMAGES===<br />
<gallery><br />
Image:RamaPlotInitComposite.png|Initial Ramachandran plot of 1ENV<br />
Image:RamaPlotBentComposite.png|Modified pose and plot of 1ENV<br />
</gallery><br />
<br />
===SETUP===<br />
place the DynoPlot.py script into the appropriate startup directory then restart PyMol<br />
<br />
==== LINUX old-style installation ====<br />
<br />
$PYMOL_PATH/modules/pmg_tk/startup/<br />
<br />
==== LINUX distutils installation ====<br />
<br />
/usr/lib/pythonX.X/site-packages/pmg_tk/startup/<br />
<br />
==== Windows ====<br />
<br />
PYMOL_PATH/modules/pmg_tk/startup/ , where PYMOL_PATH on Windows is defaulted to C:/Program Files/DeLano Scientific/PyMol/start/<br />
<br />
===NOTES / STATUS===<br />
*Tested on Windows, PyMol version 0.97<br />
*This is an initial version, which needs some work. <br />
*Left, Right mouse buttons do different things; Right = identify data point, Left = drag data point around<br />
*Post comments/questions or send them to: dwkulp@mail.med.upenn.edu<br />
<br />
===USAGE===<br />
rama SELECTION<br />
<br />
===EXAMPLES=== <br />
*load pdb file 1ENV (download it or use the PDB loader plugin)<br />
*select resi 129-136<br />
*rama sel01<br />
*rock # the object needs to be moving in order for the angles to be updated.<br />
<br />
===REFERENCES===<br />
<br />
===SCRIPTS (DynoPlot.py)===<br />
DynoPlot.py<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
###############################################<br />
# File: DynoPlot.py<br />
# Author: Dan Kulp<br />
# Creation Date: 8/29/05<br />
#<br />
# Notes:<br />
# Draw plots that display interactive data. <br />
# Phi,Psi plot shown.<br />
###############################################<br />
<br />
<br />
from __future__ import division<br />
from __future__ import generators<br />
<br />
import os,math<br />
import Tkinter<br />
from Tkinter import *<br />
import Pmw<br />
import distutils.spawn # used for find_executable<br />
import random<br />
from pymol import cmd<br />
<br />
try:<br />
import pymol<br />
REAL_PYMOL = True<br />
except ImportError:<br />
print "Nope"<br />
<br />
canvas = None<br />
init = 0<br />
<br />
class SimplePlot(Tkinter.Canvas):<br />
<br />
# Class variables<br />
mark = 'Oval' # Only 'Oval' for now..<br />
mark_size = 5<br />
xlabels = [] # axis labels<br />
ylabels = []<br />
spacingx = 0 # spacing in x direction<br />
spacingy = 0 <br />
xmin = 0 # min value from each axis<br />
ymin = 0<br />
lastx = 0 # previous x,y pos of mouse <br />
lasty = 0<br />
down = 0 # flag for mouse pressed<br />
item = (0,) # items array used for clickable events<br />
shapes = {} # store plot data, x,y etc..<br />
<br />
def axis(self,xmin=40,xmax=300,ymin=10,ymax=290,xint=290,yint=40,xlabels=[],ylabels=[]):<br />
<br />
# Store variables in self object<br />
self.xlabels = xlabels<br />
self.ylabels = ylabels<br />
self.spacingx = (xmax-xmin) / (len(xlabels) - 1)<br />
self.spacingy = (ymax-ymin) / (len(ylabels) - 1)<br />
self.xmin = xmin<br />
self.ymin = ymin<br />
<br />
# Create axis lines<br />
self.create_line((xmin,xint,xmax,xint),fill="black",width=3)<br />
self.create_line((yint,ymin,yint,ymax),fill="black",width=3)<br />
<br />
# Create tick marks and labels<br />
nextspot = xmin<br />
for label in xlabels:<br />
self.create_line((nextspot, xint+5,nextspot, xint-5),fill="black",width=2)<br />
self.create_text(nextspot, xint-15, text=label)<br />
if len(xlabels) == 1:<br />
nextspot = xmax<br />
else:<br />
nextspot += (xmax - xmin)/ (len(xlabels) - 1)<br />
<br />
<br />
nextspot = ymax<br />
for label in ylabels:<br />
self.create_line((yint+5,nextspot,yint-5,nextspot),fill="black",width=2)<br />
self.create_text(yint-20,nextspot,text=label)<br />
if len(ylabels) == 1:<br />
nextspot = ymin<br />
else:<br />
nextspot -= (ymax - ymin)/ (len(ylabels) - 1)<br />
<br />
<br />
# Plot a point<br />
def plot(self,xp,yp,meta):<br />
<br />
# Convert from 'label' space to 'pixel' space<br />
x = self.convertToPixel("X",xp)<br />
y = self.convertToPixel("Y",yp)<br />
<br />
if self.mark == "Oval":<br />
oval = self.create_oval(x-self.mark_size,y-self.mark_size,x+self.mark_size,y+self.mark_size,width=1,outline="black",fill="SkyBlue2")<br />
<br />
self.shapes[oval] = [x,y,0,xp,yp,meta]<br />
<br />
<br />
# Repaint all points <br />
def repaint(self):<br />
for value in self.shapes.values():<br />
x = value[0]<br />
y = value[1]<br />
self.create_oval(x-self.mark_size,y-self.mark_size,x+self.mark_size,y+self.mark_size,width=1,outline="black",fill="SkyBlue2")<br />
<br />
# Convert from pixel space to label space<br />
def convertToLabel(self,axis, value):<br />
<br />
# Defaultly use X-axis info<br />
label0 = self.xlabels[0]<br />
label1 = self.xlabels[1]<br />
spacing = self.spacingx<br />
min = self.xmin<br />
<br />
# Set info for Y-axis use<br />
if axis == "Y":<br />
label0 = self.ylabels[0]<br />
label1 = self.ylabels[1]<br />
spacing = self.spacingy<br />
min = self.ymin <br />
<br />
pixel = value - min<br />
label = pixel / spacing<br />
label = label0 + label * abs(label1 - label0)<br />
<br />
if axis == "Y":<br />
label = - label<br />
<br />
return label<br />
<br />
# Converts value from 'label' space to 'pixel' space<br />
def convertToPixel(self,axis, value):<br />
<br />
# Defaultly use X-axis info<br />
label0 = self.xlabels[0]<br />
label1 = self.xlabels[1]<br />
spacing = self.spacingx<br />
min = self.xmin<br />
<br />
# Set info for Y-axis use<br />
if axis == "Y":<br />
label0 = self.ylabels[0]<br />
label1 = self.ylabels[1]<br />
spacing = self.spacingy<br />
min = self.ymin <br />
<br />
<br />
# Get axis increment in 'label' space<br />
inc = abs(label1 - label0)<br />
<br />
# 'Label' difference from value and smallest label (label0)<br />
diff = float(value - label0)<br />
<br />
# Get whole number in 'label' space<br />
whole = int(diff / inc)<br />
<br />
# Get fraction number in 'label' space<br />
part = float(float(diff/inc) - whole)<br />
<br />
# Return 'pixel' position value<br />
pixel = whole * spacing + part * spacing<br />
<br />
# print "Pixel: %f * %f + %f * %f = %f" % (whole, spacing, part, spacing,pixel)<br />
<br />
# Reverse number by subtracting total number of pixels - value pixels<br />
if axis == "Y":<br />
tot_label_diff = float(self.ylabels[len(self.ylabels)- 1] - label0)<br />
tot_label_whole = int(tot_label_diff / inc)<br />
tot_label_part = float(float(tot_label_diff / inc) - tot_label_whole)<br />
tot_label_pix = tot_label_whole * spacing + tot_label_part *spacing<br />
<br />
pixel = tot_label_pix - pixel<br />
<br />
# Add min edge pixels<br />
pixel = pixel + min<br />
<br />
return pixel<br />
<br />
<br />
# Print out which data point you just clicked on..<br />
def pickWhich(self,event):<br />
<br />
# Find closest data point <br />
x = event.widget.canvasx(event.x)<br />
y = event.widget.canvasx(event.y)<br />
spot = event.widget.find_closest(x,y)<br />
<br />
# Print the shape's meta information corresponding with the shape that was picked<br />
if spot[0] in self.shapes:<br />
print "Residue(Ca): %s\n" % self.shapes[spot[0]][5][2]<br />
<br />
<br />
# Mouse Down Event<br />
def down(self,event):<br />
<br />
# Store x,y position<br />
self.lastx = event.x<br />
self.lasty = event.y<br />
<br />
# Find the currently selected item<br />
x = event.widget.canvasx(event.x)<br />
y = event.widget.canvasx(event.y)<br />
self.item = event.widget.find_closest(x,y)<br />
<br />
# Identify that the mouse is down<br />
self.down = 1<br />
<br />
# Mouse Up Event<br />
def up(self,event):<br />
<br />
# Get label space version of x,y<br />
labelx = self.convertToLabel("X",event.x)<br />
labely = self.convertToLabel("Y",event.y)<br />
<br />
# Convert new position into label space..<br />
if self.item[0] in self.shapes:<br />
self.shapes[self.item[0]][0] = event.x<br />
self.shapes[self.item[0]][1] = event.y<br />
self.shapes[self.item[0]][2] = 1<br />
self.shapes[self.item[0]][3] = labelx<br />
self.shapes[self.item[0]][4] = labely<br />
<br />
# Reset Flags<br />
self.item = (0,)<br />
self.down = 0<br />
<br />
<br />
# Mouse Drag(Move) Event<br />
def drag(self,event):<br />
<br />
# Check that mouse is down and item clicked is a valid data point<br />
if self.down and self.item[0] in self.shapes:<br />
<br />
self.move(self.item, event.x - self.lastx, event.y - self.lasty)<br />
<br />
self.lastx = event.x<br />
self.lasty = event.y<br />
<br />
<br />
def __init__(self):<br />
<br />
self.menuBar.addcascademenu('Plugin', 'PlotTools', 'Plot Tools',<br />
label='Plot Tools')<br />
self.menuBar.addmenuitem('PlotTools', 'command',<br />
'Launch Rama Plot',<br />
label='Rama Plot',<br />
command = lambda s=self: ramaplot())<br />
<br />
<br />
def ramaplot(x=0,y=0,meta=[],clear=0):<br />
global canvas<br />
global init<br />
<br />
# If no window is open<br />
if init == 0:<br />
rootframe=Tk()<br />
rootframe.title(' Dynamic Angle Plotting ')<br />
<br />
canvas = SimplePlot(rootframe,width=320,height=320)<br />
canvas.bind("<Button-2>",canvas.pickWhich)<br />
canvas.bind("<Button-3>",canvas.pickWhich)<br />
canvas.bind("<ButtonPress-1>",canvas.down)<br />
canvas.bind("<ButtonRelease-1>",canvas.up)<br />
canvas.bind("<Motion>",canvas.drag)<br />
canvas.pack(side=Tkinter.LEFT,fill="both",expand=1)<br />
canvas.axis(xint=150,xlabels=[-180,-150,-120,-90,-60,-30,0,30,60,90,120,150,180],ylabels=[-180,-150,-120,-90,-60,-30,0,30,60,90,120,150,180])<br />
canvas.update()<br />
init = 1<br />
else:<br />
canvas.plot(int(x), int(y),meta)<br />
<br />
<br />
# New Callback object, so that we can update the structure when phi,psi points are moved.<br />
class DynoRamaObject:<br />
global canvas<br />
<br />
def start(self,sel):<br />
<br />
# Get selection model<br />
model = cmd.get_model(sel)<br />
residues = ['dummy']<br />
resnames = ['dummy']<br />
phi = []<br />
psi = []<br />
dummy = []<br />
i = 0<br />
<br />
# Loop through each atom<br />
for at in model.atom:<br />
<br />
# Only plot once per residue<br />
if at.chain+":"+at.resn+":"+at.resi not in residues:<br />
residues.append(at.chain+":"+at.resn+":"+at.resi)<br />
resnames.append(at.resn+at.resi)<br />
dummy.append(i)<br />
i += 1<br />
<br />
# Check for a null chain id (some PDBs contain this) <br />
unit_select = ""<br />
if at.chain != "":<br />
unit_select = "chain "+str(at.chain)+" and "<br />
<br />
# Define selections for residue i-1, i and i+1 <br />
residue_def = unit_select+'resi '+str(at.resi)<br />
residue_def_prev = unit_select+'resi '+str(int(at.resi)-1)<br />
residue_def_next = unit_select+'resi '+str(int(at.resi)+1)<br />
<br />
try:<br />
# Store phi,psi residue definitions to pass on to plot routine<br />
phi_psi = [<br />
# Phi angles<br />
residue_def_prev+' and name C',<br />
residue_def+' and name N',<br />
residue_def+' and name CA',<br />
residue_def+' and name C',<br />
# Psi angles<br />
residue_def+' and name N',<br />
residue_def+' and name CA',<br />
residue_def+' and name C',<br />
residue_def_next+' and name N']<br />
<br />
# Compute phi/psi angle<br />
phi = cmd.get_dihedral(phi_psi[0],phi_psi[1],phi_psi[2],phi_psi[3])<br />
psi = cmd.get_dihedral(phi_psi[4],phi_psi[5],phi_psi[6],phi_psi[7])<br />
<br />
print "Plotting Phi,Psi: "+str(phi)+","+str(psi) <br />
ramaplot(phi,psi,meta=phi_psi)<br />
except:<br />
continue<br />
<br />
<br />
def __call__(self):<br />
<br />
# Loop through each item on plot to see if updated<br />
for key,value in canvas.shapes.items():<br />
dihedrals = value[5]<br />
<br />
# Look for update flag...<br />
if value[2]:<br />
<br />
# Set residue's phi,psi to new values<br />
print "Re-setting Phi,Psi: %s,%s" % (value[3],value[4]) <br />
cmd.set_dihedral(dihedrals[0],dihedrals[1],dihedrals[2],dihedrals[3],value[3]) <br />
cmd.set_dihedral(dihedrals[4],dihedrals[5],dihedrals[6],dihedrals[7],value[4]) <br />
<br />
value[2] = 0<br />
<br />
<br />
<br />
# The wrapper function, used to create the Ploting window and the PyMol callback object <br />
def rama(sel):<br />
rama = DynoRamaObject()<br />
rama.start(sel)<br />
cmd.load_callback(rama, "DynoRamaObject")<br />
cmd.zoom("all")<br />
<br />
<br />
# Extend these commands<br />
cmd.extend('rama',rama) <br />
cmd.extend('ramaplot',ramaplot)<br />
<br />
</source><br />
<br />
===ADDITIONAL RESOURCES===<br />
<br />
<br />
<br />
[[Category:Script_Library|DynoPlot]]<br />
[[Category:Structural_Biology_Scripts|DynoPlot]]</div>Newaccthttps://pymolwiki.org/index.php?title=Slerpy&diff=7721Slerpy2009-12-17T11:55:50Z<p>Newacct: </p>
<hr />
<div>= Manual for Slerpy.py =<br />
<br />
An extension to pymol that creates a moderately easy to use environment for doing keyframe animation. <br />
<br />
<br />
==General Use==<br />
<br />
At the pymol command line type:<br />
<br />
import slerpy<br />
<br />
This will load the extended commands. All commands in slerpy begin with the letter s. Pymol's tab autocomplete feature will work on the additional commands.<br />
<br />
==Important concepts==<br />
<br />
The main function of slerpy is to record a series of pymol views. A movie can then be created by interpolating between these views. A pymol view consists mostly of the camera orientation (that is, the orientation of the viewers eye with respect to the molecule). It also includes information about the clipping planes.<br />
<br />
It is important to realize that most slerpy commands act on the "current" view. You can navigate among views by using the sn, sp, and sgo commands. If you've changed the view around with the mouse or you just want to know the number of the current view you can get back to the current view with the sc command.<br />
<br />
Pymol views do not contain information about how pymol objects and selections are displayed. If you just want to create a movie which moves around a single representation of a molecule then all you need to do is record the set of views that define the tour of the molecule.<br />
<br />
If, on the other hand, you want to change the representation or change which items are displayed you will need to add actions to some of your views. An action is any set of pymol commands. Actions can be associated with any view in the series recorded by slerpy. The ''sscene'' command inserts a new view and simultaneously creates a pymol scene and the action to display it. The scene will include all of the objects and representations visible at the time the command was issued.<br />
<br />
In order to control the rate of motion between the defined views in a slerpy movie, you can control the number of frames used in each interpolation. When a view is saved in slerpy it is associated by default with a transition of 50 frames to the next view. The number of frames in the transition can be altered with the ''ssetf'' command in slerpy.<br />
<br />
The views and actions stored by slerpy can (and should) be saved to a key file with the ''swrite'' command. They can then be retrieved with the sread command. Note that swrite saves the current pymol state in a .pse file but sread does not read in the .pse file. If you're starting a new pymol session to continue work on an existing movie you should load the pse file before doing an sread.<br />
<br />
==Quick Start Tutorial==<br />
<br />
If you haven't installed slerpy yet see [[#Installation|Installation]]<br />
<br />
;Step 1: You probably want to start off in a nice clean working directory that just has the coordinate files you want to work with.<br />
<br />
;Step 2: Read in your molecule(s) and create the various selections and representations that you want to include in the movie.<br />
<br />
;Step 3: At the pymol prompt, type:<br />
<br />
import slerpy<br />
<br />
;Step 4: Get your molecule in exactly the orientation and representation that you want to use for the beginning of your movie.<br />
<br />
;Step 5: Type:<br />
<br />
sinsert<br />
<br />
;Step 6: Using the mouse, move your molecule to the next orientation that you want to use. When you record the movie, the camera orientation will be interpolated between each consecutive pair of views. This can include changes in rotation, zooming, clipping etc.<br />
<br />
:Loop back to Step 5. Continue this until you've got all your orientations stored.<br />
<br />
:You can check how any set of transitions will look at any time by using the ''sshow'' command (see [[#Command Reference|Command Reference]] for details).<br />
<br />
:You can adjust the rate of any transition using the ''ssetf'' command<br />
<br />
;Step 7A: Add any actions to your views using the saction command. Any number of pymol commands can be strung together separated by semicolons. If, for example, you want to change your protein from a cartoon to a surface and add a ligand when you get to view 5 you would do the following (assuming you've defined the pymol selections prot and lig):<br />
<br />
sgo 5<br />
saction "hide cartoon, prot; show surface, prot; show sticks, lig"<br />
<br />
;Step 7B (Alternative using scenes):<br />
<br />
sgo 5<br />
<br />
:Now use the gui to create the representation you want and then:<br />
<br />
sscene<br />
<br />
;Step 8: Save everything. Save your slerpy views and actions as well as a pse file of your current pymol session:<br />
<br />
swrite mymovie<br />
<br />
This will create mymovie.key, which has all of the views, frame counts, actions etc. and mymovie.pse, the associated pymol session file.<br />
<br />
;Step 9: Record the movie! Type:<br />
<br />
srecord<br />
<br />
:You can then play the movie by typing the standard pymol command ''mplay'' or by clicking the play button in pymol.<br />
<br />
;Step 10: If you save the pymol session again, the pse file will contain the movie which can then be shown immediately after startup without running slerpy.py. Note that pymol will warn you when you load a pse file that contains a movie.<br />
<br />
;Step 11: If you want to, the movie can be exported using the mpng command (see the pymol [http://pymol.sourceforge.net/newman/ref/S1000comref.html#2_105 documentation]). Also, see the useful article [[Making_Movies|Making Movies]].<br />
<br />
==Tips and Tricks==<br />
<br />
===Converting scenes to movies===<br />
<br />
You can just step through the scenes and type sscene for each one. This will create a duplicate slerpy scene for each of the scenes you'd already saved but that's not such a disaster. Be sure to swrite when you're done.<br />
<br />
Note that there is some overhead associated with recalling scenes. To avoid pauses at view transitions, I prefer to actually issue the set of show and hide commands that will generate the scene rather than using the above method.<br />
<br />
===Starting off right===<br />
<br />
It's a bit of a pain, but I like to associate with the first frame of the movie an action list that hides everything and then turns on all the objects that I want to have visible at the beginning. This ensures that when your movie loops back to the beginning it will look the same as it did the first time through. For example:<br />
<br />
sgo 0<br />
saction "hide everything; show lines, prot; show surface, activesite; show sticks, ligand"<br />
<br />
Alternatively, start your slerpy work with an ''sscene''.<br />
<br />
===Live pymol presentations during a talk===<br />
Be sure to run your movie once it's been opened and before your presentation if you're presenting in pymol. This will ensure that any objects that don't appear until the middle of the movie are available in memory and won't need to be rebuilt while your audience waits.<br />
<br />
Of course showing your movie from within pymol allows you to show movies in stereo if you've got a presentation system that allows this. If you pass out stereo glasses first it's guaranteed that everyone will remember your talk...<br />
<br />
===Pausing on a view===<br />
<br />
Just sgo to the view you want to stay on for a while and do an sinsert. This will insert a new view with the same orientation etc as the one you were just on. You can adjust the length of the pause by changing the number of frames for the transistion between these two identical views using the ssetf command.<br />
<br />
===Morphing and multi-state models===<br />
<br />
Morphs and multi-conformation models are represented in pymol as single objects with multiple states. Cycling through the states as an animation is very straightforward in pymol. Slerpy allows you to include this animation over the states of an object as a transition between slerpy views within the context of larger movie. This is done using the ''smorph'' command (see [[#Command Reference|Command Reference]]). ''smorph'' allows you to specify the starting and ending pymol state numbers to use during the transition from the current to the next view. It will often be appropriate to have the movie continue after the morph using the final state of the morphing model, that is, the conformation to which you morphed. Since the default for a typical slerpy view is to show the first state of an object, you'll probably need to have available, in addition to your multi-state model, a single-state object containing the final conformation. You can then hide the multistate object and show the single-state final conformation as an action associated with the final view of your morphing sequence.<br />
<br />
To generate morphs you can use the [http://www.delanoscientific.com/rigimol.html rigimol] program provided by Warren as part of the incentive pymol package for subscribers or use [http://alpha2.bmc.uu.se/usf/mol_morph.html lsqman] from Gerard Kleywegt.<br />
<br />
==Command Reference==<br />
<br />
Note that it is essential to understand that slerpy uses the concept of a current or active view. This is the element in the list to which most commands are applied. It is not necessarily the view that is currently visible on the screen. It is advisable to use the sc command frequently to make sure you really know which view your command is being applied to.<br />
<br />
'''saction ''string'':''' Assoiciates the pymol commands in ''string'' with the current view. ''string'' must be enclosed in quotes and must contain only valid pymol commands separated by semicolons.<br />
<br />
'''sappend''': Add the currently displayed view at the end of the list of views in slerpy<br />
<br />
'''sappendaction ''string'':''' Adds the action(s) in ''string'' to the list of actions associated with the current view<br />
<br />
'''sc''': Go to the slerpy active view<br />
<br />
'''scrossfade ''startobject, endobject'':''' During the transition from the current view to the next view ''startobject'' will fade out and'' endobject'' will fade in. The two objects must be shown as sticks. They must be objects, not merely selections, as of pymol 0.99.<br />
<br />
'''sdelaction''': Deletes the action associated with the current view. Be sure you're sure which view you're on before you use this. This will also delete any actions etc. associated with the view so be careful.<br />
<br />
'''sdelete''': Remove the slerpy active view from the list of views to be interpolated.<br />
<br />
'''sdeletesetting: '''Remove the setting interpolation for the current view.<br />
<br />
'''sdumpactions: '''List all actions by frame.<br />
<br />
'''sgo ''n'':''' Change the slerpy active view to view ''n''.<br />
<br />
'''sinsert''': Add the currently displayed view after the slerpy active view.<br />
<br />
'''sinterpsetting ''setting, selection, startval, endval'' :''' The pymol setting ''setting'' will be interpolated linearly from ''startval'' to ''endval'' during the transition from the current view to the next view. You can only interpolate one setting per transition. This is the hard way to, for example, fade out an object:<br />
<br />
sinterpsetting stick_transparency, lig, 0.0, 1.0<br />
<br />
'''slist''': List all views stored for interpolation. Also lists the number of frames in each transition.<br />
<br />
'''smorph ''startmodel,endmodel'':''' The transition from the current frame to the next frame will consist of one frame per pymol state starting with state ''startmodel'' and ending with state ''endmodel''. Subsequent frames (i.e. from subsequent views) will revert to state 1. The state numbers apply to currently visible objects so you will most likely want to have an object with your starting conformation, an object with your multi-state morphing model, and an object with your final conformation. You would then sgo to the frame where you want the morph to start and add an action to hide the starting conformation object and show the multi-model morphing object, do an smorph 1,30 or whatever the number of states in your morph is, append another frame and give it an action where the multi-state model is hidden and the final conformation is shown.<br />
<br />
'''sn''': Go to the next view<br />
<br />
'''sp''': Go to the previous view.<br />
<br />
'''sread ''filename'':''' Restore all the information written with swrite. Does not read in the pse file (to avoid inadvertantly writing over some new selections, scenes or whatever).<br />
<br />
'''srecord''': Records the movie<br />
<br />
'''sreplace''': Replace the slerpy current view with the currently displayed view.<br />
<br />
'''sscene''': Add a the currently displayed view after the slerpy active view and create a scene to go with it. The current pymol state, including which objects are displayed and how they are shown will be captured.<br />
<br />
'''ssetf''': Set the number of frames to use in the transition from the slerpy active view to the next view<br />
<br />
'''ssetupview ''n'':''' This attempts to make sure that all objects are displayed (or not) as they would be when view ''n'' is arrived at in the movie. It goes through and executes all of the sactions from all preceeding views. For some reason this doesn't always work in complex cases.<br />
<br />
'''sshow ''n,m'':''' This command records and shows a segment of the movie showing the transitions starting with view n and ending with view m. If the arguments m and n are omitted the transition from the current view to the next view will be shown.<br />
<br />
'''swrite ''filename'':''' Writes all the information used by slerpy to a file ''filename''.key. It also writes a pymol session file ''filename''.pse containing all of your current objects, selections etc. The format of the .key file is supposed to be human readable and it can be convenient to edit this file rather than using saction over and over. After editing it by hand be sure to do an sread.<br />
<br />
==Why is it called slerpy?==<br />
<br />
slerp is an acronym of sorts for spherical linear interpolation. The transition between two views approximates spherical linear interpolation of the their camera positions using quaternions. See the Wikipedia [http://en.wikipedia.org/wiki/Slerp article] on slerps.<br />
<br />
=Script Files=<br />
<br />
==Installation==<br />
<br />
To install, copy (by pasting into a text editor) the following two python code segments to files named slerpy.py and movs.py, respectively. Place these files in the pymol/modules/pymol/ directory created by the pymol installation.<br />
<br />
If you don't have write priviledges in the pymol installation directories you can just copy these files to the working directory from which pymol will be run. <br />
<br />
==Code==<br />
<br />
===slerpy.py===<br />
<br />
:The command definitions for slerpy<br />
<br />
<source lang="python"><br />
################################################################################<br />
#slerpy.py - Command definition routines for slerpy<br />
#Copyright (C) 2006 Joel Bard<br />
#<br />
#This program is free software; you can redistribute it and/or<br />
#modify it under the terms of the GNU General Public License<br />
#as published by the Free Software Foundation; either version 2<br />
#of the License, or (at your option) any later version.<br />
#<br />
#This program is distributed in the hope that it will be useful,<br />
#but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br />
#GNU General Public License for more details.<br />
#<br />
#You should have received a copy of the GNU General Public License<br />
#along with this program; if not, write to the Free Software<br />
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br />
#################################################################################<br />
<br />
from pymol import cmd<br />
import movs<br />
<br />
def readViews( filename ):<br />
#obsolete<br />
vfile = open( filename, 'r')<br />
views = [] #a list of views each of which is a list of 18 numbers<br />
vstrings = vfile.readlines()<br />
for vstring in vstrings:<br />
vals = vstring.split()<br />
view = [float(v) for v in vals]<br />
views.append( view )<br />
vfile.close()<br />
return views<br />
<br />
def readFrames( filename ):<br />
#obsolete<br />
ffile = open( filename, 'r' )<br />
frames = []<br />
fstrings = ffile.readlines()<br />
for fstring in fstrings:<br />
frames.append( int(fstring) )<br />
ffile.close()<br />
return frames<br />
<br />
def readActions( filename ):<br />
#obsolete<br />
#actions are stored in file where<br />
#for each line, the first 4 chars are the view index<br />
#associated with the action and the rest of the<br />
#line is the pymol command to be executed<br />
#upon reading, a dictionary is returned<br />
#with view indices as keys and actions as values<br />
actions = {}<br />
try:<br />
afile = open( filename, 'r' )<br />
except:<br />
print "No actions for this project"<br />
return actions<br />
astrings = afile.readlines()<br />
for astring in astrings:<br />
try:<br />
aindex = int(astring[:4])<br />
action = astring[4:]<br />
actions[ aindex ] = action[:-1]<br />
except:<br />
print "empty line"<br />
afile.close()<br />
return actions<br />
<br />
def readModels( filename ):<br />
#obsolete<br />
models = {}<br />
try:<br />
mfile = open( filename, 'r' )<br />
except:<br />
print "No models for this project"<br />
return models<br />
mstrings = mfile.readlines()<br />
for mstring in mstrings:<br />
try:<br />
mindex = int(mstring[:4])<br />
model = mstring[4:]<br />
models[ mindex ] = model[:-1]<br />
except:<br />
print "empty line"<br />
mfile.close()<br />
return models<br />
<br />
def readSettings( filename ):<br />
#obsolete<br />
settings = {}<br />
try:<br />
sfile = open( filename, 'r' )<br />
except:<br />
print "No settings for this project"<br />
return settings<br />
sstrings = sfile.readlines()<br />
for sstring in sstrings:<br />
try:<br />
sindex = int(sstring[:4])<br />
scommas = sstring[4:]<br />
settingName,selection,startVal,endVal = scommas.split(',')<br />
setting = [settingName,selection,float(startVal),float(endVal)]<br />
settings[sindex] = setting<br />
except:<br />
print "unable to parse setting"<br />
sfile.close()<br />
return settings<br />
<br />
def readScenes( filename ):<br />
#obsolete<br />
global scene_counter<br />
<br />
scene_counter = 0<br />
scenes = {}<br />
try:<br />
sfile = open( filename, 'r' )<br />
except:<br />
print "No scenes file for this project"<br />
return scenes<br />
sstrings = sfile.readlines()<br />
for sstring in sstrings:<br />
try:<br />
sindex = int(sstring[:4])<br />
scene = sstring[4:]<br />
scenes[ sindex ] = scene[:-1]<br />
scene_counter += 1<br />
#print "reading scene", sstring, sindex, scene<br />
except:<br />
print "empty line"<br />
sfile.close()<br />
return scenes<br />
<br />
def read_all( fileroot ):<br />
#obsolete in favor of readKeyViewFile<br />
global views<br />
global frames<br />
global actions<br />
global cur_view<br />
global cur_index<br />
global scenes<br />
global models<br />
global settings<br />
<br />
views = readViews( fileroot+".txt" )<br />
frames = readFrames( fileroot+".frm")<br />
actions = readActions( fileroot+".act")<br />
scenes = readScenes( fileroot+".scn")<br />
models = readModels( fileroot+".mod")<br />
settings = readSettings( fileroot+".set")<br />
cur_view = views[0]<br />
cur_index = 0<br />
show_cur()<br />
<br />
def print_view( view ):<br />
for i in range(0,6):<br />
for j in range(0,3):<br />
print "%12.6f"% view[ 3*i+j ] ,<br />
print<br />
<br />
def show_next():<br />
global cur_index<br />
global cur_view<br />
global views<br />
if cur_index == len( views )-1:<br />
print "No more views."<br />
return<br />
cur_index += 1<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def show_prev():<br />
global cur_index<br />
global cur_view<br />
global views<br />
if cur_index == 0:<br />
print "No more views."<br />
return<br />
cur_index -= 1<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def show_cur():<br />
global cur_index<br />
global cur_view<br />
global views<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def go_to_view( arg=0 ):<br />
global cur_index<br />
global cur_view<br />
global views<br />
n = int( arg )<br />
if n < 0 or n >= len(views):<br />
print "Index out of range."<br />
return<br />
cur_index = n<br />
cur_view = views[n]<br />
cmd.set_view( cur_view )<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ", cur_index<br />
<br />
def insert_current():<br />
#insert the current view into the list after the view<br />
#in views[cur_index]<br />
#set frames to default<br />
global cur_index<br />
global cur_view<br />
global views<br />
global frames<br />
global actions<br />
global scenes<br />
global settings<br />
global models<br />
global fades<br />
<br />
cur_index += 1<br />
cur_view = cmd.get_view()<br />
views.insert( cur_index, [cv for cv in cur_view] )<br />
frames.insert( cur_index, 50 )<br />
<br />
#deal with actions dictionary<br />
actions = incKeyAbove( actions, cur_index )<br />
scenes = incKeyAbove( scenes, cur_index )<br />
settings = incKeyAbove( settings, cur_index )<br />
models = incKeyAbove( models, cur_index )<br />
fades = incKeyAbove( fades, cur_index )<br />
<br />
print "New view:"<br />
print_view( cur_view )<br />
print "Inserted view with index", cur_index, "and a 50 frame transition"<br />
<br />
def append_view():<br />
global views<br />
global frames<br />
global cur_index<br />
global cur_view<br />
<br />
cur_index = len(views)<br />
cur_view = cmd.get_view()<br />
views.append( [cv for cv in cur_view] )<br />
frames.append( 50 )<br />
<br />
print "New view: "<br />
print_view( cur_view )<br />
print "Appended view with index", cur_index, "and a 50 frame transition"<br />
print "The current view is", cur_index<br />
<br />
def incKeyAbove( dict, index ):<br />
tempDict = {}<br />
for key, val in dict.iteritems():<br />
if key >= index:<br />
newkey = key + 1<br />
tempDict[newkey] = val<br />
else:<br />
tempDict[key] = val<br />
return tempDict<br />
<br />
def decKeyAbove( dict, index ):<br />
tempDict = {}<br />
for key, val in dict.iteritems():<br />
if key > index:<br />
newkey = key - 1<br />
tempDict[newkey] = val<br />
else:<br />
tempDict[key] = val<br />
return tempDict<br />
<br />
def delete_current():<br />
#remove the current view from the list<br />
#show the previous view<br />
global cur_index<br />
global cur_view<br />
global views<br />
global actions<br />
global scenes<br />
global settings<br />
global models<br />
global frames<br />
global fades<br />
<br />
del views[cur_index]<br />
del frames[cur_index]<br />
if cur_index in actions:<br />
del actions[cur_index]<br />
if cur_index in scenes:<br />
del scenes[cur_index]<br />
if cur_index in settings:<br />
del settings[cur_index]<br />
<br />
#deal with dictionaries<br />
actions = decKeyAbove( actions, cur_index )<br />
scenes = decKeyAbove( scenes, cur_index )<br />
settings = decKeyAbove( settings, cur_index )<br />
models = decKeyAbove( models, cur_index ) <br />
fades = decKeyAbove( fades, cur_index )<br />
<br />
print "View number",cur_index,"deleted."<br />
if cur_index > 0:<br />
cur_index -= 1<br />
cur_view = views[cur_index]<br />
cmd.set_view( cur_view )<br />
print "Current view is number",cur_index<br />
<br />
def delete_settings():<br />
global settings<br />
global cur_index<br />
del settings[cur_index]<br />
<br />
def replace_current():<br />
global cur_index<br />
global cur_view<br />
global views<br />
cur_view = cmd.get_view()<br />
views[cur_index] = [cv for cv in cur_view]<br />
<br />
def insert_scene():<br />
global views<br />
global actions<br />
global settings<br />
global frames<br />
global cur_index<br />
global cur_view<br />
global scenes<br />
global scene_counter<br />
global models<br />
global fades<br />
<br />
cur_index += 1<br />
cur_view = cmd.get_view()<br />
views.insert( cur_index, [cv for cv in cur_view] )<br />
frames.insert( cur_index, 50 )<br />
<br />
#deal with dictionaries<br />
actions = incKeyAbove( actions, cur_index )<br />
scenes = incKeyAbove( scenes, cur_index )<br />
settings = incKeyAbove( settings, cur_index )<br />
models = incKeyAbove( models, cur_index )<br />
fades = incKeyAbove( fades, cur_index )<br />
<br />
#this stuff has to be done after the above<br />
#find a free scene name<br />
i = 1<br />
found = 1<br />
while found == 1:<br />
found = 0<br />
for sname in scenes.values():<br />
print "|"+sname+"|"<br />
if sname == "slerpy_"+str(i):<br />
found = 1<br />
break<br />
if found == 1:<br />
i += 1<br />
else:<br />
break<br />
newname = "slerpy_"+str(i)<br />
<br />
scene_counter += 1<br />
cmd.scene( newname, "store" )<br />
scenes[ cur_index ] = newname<br />
actions[ cur_index ] = "scene "+newname<br />
<br />
print "New view:"<br />
print_view( cur_view )<br />
print "Inserted view with index", cur_index, "and a 50 frame transition"<br />
print "Added scene",newname<br />
<br />
def write_views( filename ):<br />
#deprecated in favor of key files<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
<br />
viewfile = open( filename+".txt", 'w')<br />
for view in views:<br />
for v in view:<br />
viewfile.write( str(v) + " " )<br />
viewfile.write('\n')<br />
viewfile.close()<br />
<br />
framefile = open( filename+".frm", 'w' )<br />
for frame in frames:<br />
framefile.write( str( frame )+'\n' )<br />
framefile.close()<br />
<br />
actionfile = open( filename+".act", 'w' )<br />
for key,action in actions.iteritems():<br />
keystring = str( key )<br />
actionfile.write( keystring.rjust(4)+action + '\n' )<br />
actionfile.close()<br />
<br />
scenefile = open( filename+".scn", 'w' )<br />
for key,scene in scenes.iteritems():<br />
keystring = str( key )<br />
scenefile.write( keystring.rjust(4)+scene + '\n' )<br />
scenefile.close()<br />
<br />
modelfile = open( filename+".mod", 'w' )<br />
for key,model in models.iteritems():<br />
keystring = str( key )<br />
modelfile.write( keystring.rjust(4)+model + '\n' )<br />
modelfile.close()<br />
<br />
settingsfile = open( filename+".set", 'w' )<br />
for key,setting in settings.iteritems():<br />
keystring = str( key )<br />
settingName, selection, startVal, endVal = setting<br />
settingsfile.write( "%s%s,%s,%f,%f\n" % (keystring.rjust(4), settingName, selection, startVal, endVal))<br />
settingsfile.close()<br />
cmd.save( filename+".pse" )<br />
<br />
print "Wrote files", filename+".txt,",filename+".frm,",filename+".pse, and",filename+".act"<br />
<br />
def writeKeyViewFile( filename ):<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
<br />
keyviewfile = open( filename + ".key", 'w' )<br />
for i,view in enumerate(views):<br />
keyviewfile.write( "VIEW: %4d " % i )<br />
for v in view:<br />
keyviewfile.write( str(v) + " " )<br />
keyviewfile.write('\n')<br />
keyviewfile.write( "FRAMES: %d\n" % frames[i] )<br />
if i in actions:<br />
keyviewfile.write( "ACTIONS: %s\n" % actions[i] )<br />
if i in scenes:<br />
keyviewfile.write( "SCENES: %s\n" % scenes[i] )<br />
if i in models:<br />
keyviewfile.write( "MODELS: %s\n" % models[i] )<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
keyviewfile.write( "SETTINGS: %s, %s, %f, %f\n" % (settingName, selection, startVal, endVal))<br />
if i in fades:<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
keyviewfile.write( "FADES: %s, %s, %d\n" % (startVisSelection, endVisSelection, sticksOnly)) <br />
keyviewfile.write("\n")<br />
keyviewfile.close()<br />
cmd.save( filename + ".pse" )<br />
print "Wrote files " , filename + ".key", filename + ".pse"<br />
<br />
def readKeyViewFile( filename ):<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
global scene_counter<br />
<br />
views = []<br />
frames = []<br />
actions = {}<br />
scenes = {}<br />
models = {}<br />
settings = {}<br />
fades = {}<br />
scene_counter = 0<br />
<br />
if filename.endswith(".key"): filename = filename[:-4]<br />
keyviewfile = open( filename + ".key", 'r' )<br />
viewstrings = keyviewfile.readlines()<br />
keyviewfile.close()<br />
viewindex = 0<br />
for line in viewstrings:<br />
if line.startswith("VIEW: "):<br />
viewindex = int( line[6:10] )<br />
vals = line[10:].split()<br />
view = [float(v) for v in vals]<br />
views.append( view )<br />
if line.startswith("FRAMES: "):<br />
frames.append( int( line[8:] ) )<br />
if line.startswith("ACTIONS: "):<br />
actions[ viewindex ] = line[9:-1]<br />
if line.startswith("SCENES: "):<br />
scenes[ viewindex ] = line[8:-1]<br />
scene_counter += 1<br />
if line.startswith("MODELS: "):<br />
models[ viewindex ] = line[8:-1]<br />
if line.startswith("SETTINGS: "):<br />
settingName,selection,startVal,endVal = line[10:-1].split(',')<br />
settings[ viewindex ] = [settingName,selection,float(startVal),float(endVal)]<br />
if line.startswith( "FADES: " ):<br />
startVisSelection, endVisSelection, sticksOnly = line[7:-1].split(',')<br />
fades[ viewindex ] = [startVisSelection, endVisSelection, int(sticksOnly) ]<br />
cur_view = views[0]<br />
cur_index = 0<br />
show_cur()<br />
<br />
def set_frames_current( arg=50 ):<br />
global frames<br />
global cur_index<br />
frames[cur_index] = int(arg)<br />
<br />
def list_frames():<br />
global frames<br />
global views<br />
global actions<br />
global models<br />
global settings<br />
<br />
f=0<br />
for i,view in enumerate(views[:-1]):<br />
if i in actions:<br />
a = actions[i]<br />
else:<br />
a = ""<br />
if i in models:<br />
m = "States: " + models[i]<br />
else:<br />
m = ""<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
s = "Settings: %s %s %f %f" % (settingName, selection, startVal, endVal)<br />
else:<br />
s = ""<br />
print "View",i,"to",i+1,"Frames ",f,"to",f+frames[i],a,m,s<br />
f += frames[i]<br />
<br />
def add_action_current( cmd ):<br />
global cur_index<br />
global actions<br />
actions[cur_index] = cmd[1:-1] #strip off quotes<br />
<br />
def append_action_current( cmd ):<br />
global cur_index<br />
global actions<br />
actions[cur_index] += ";" + cmd[1:-1]<br />
<br />
def clear_action_current():<br />
global actions<br />
global cur_index<br />
del actions[cur_index]<br />
<br />
def list_actions():<br />
global actions<br />
for i,a in actions.iteritems():<br />
print i,a<br />
<br />
def morph_models( start_model, end_model ):<br />
global cur_index<br />
global frames<br />
global models<br />
models[cur_index] = "%s -%s" % (start_model, end_model)<br />
frames[cur_index] = abs(int(end_model) - int(start_model)) + 1<br />
<br />
def interpolate_settings( setting, selection, startval, endval ):<br />
global cur_index<br />
global settings<br />
settingEntry = [setting, selection, float(startval), float(endval)]<br />
settings[cur_index] = settingEntry <br />
<br />
def crossfade( startVisSelection, endVisSelection, sticksOnly = 1 ):<br />
#cross fade the specified objects, vary stick transparency only if stickOnly=1<br />
global cur_index<br />
global fades<br />
fades[cur_index] = [startVisSelection, endVisSelection, int(sticksOnly) ]<br />
<br />
def setup_view( index ):<br />
for i in range( int(index)+1 ):<br />
if i in actions:<br />
print "Executing %s from actions %d" % (actions[i],i)<br />
cmd.do( actions[i] )<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
action = "set %s, %f, %s;" % (settingName, endVal, selection)<br />
print "Executing %s from settings %d" % (action,i)<br />
cmd.do( action )<br />
if i in fades:<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
action = "set stick_transparency, 0, %s; set stick_transparency, 1, %s;" % (endVisSelection, startVisSelection)<br />
print "Executing %s from fades %d" % (action, i)<br />
cmd.do( action )<br />
<br />
def show_transition(start_index=0, end_index=0):<br />
#show the transition from the current view to the next view<br />
global frames<br />
global views<br />
global cur_index<br />
global actions<br />
global models<br />
if start_index == 0 and end_index == 0:<br />
if cur_index >= len(views)-1:<br />
print "Current view is last in sequence."<br />
return<br />
start_index=cur_index<br />
end_index=cur_index+1<br />
else:<br />
start_index = int(start_index)<br />
end_index = int(end_index)<br />
ftot = 0<br />
setcommand = ""<br />
i = start_index<br />
for nframes in frames[start_index:end_index]:<br />
#ftot += nframes<br />
if i in models:<br />
setcommand += " " + models[i] + " "<br />
else:<br />
setcommand += " 1 x%i" % nframes<br />
i += 1<br />
<br />
# cmd.mset("1 x%i" % ftot)<br />
cmd.mset( setcommand )<br />
start_frame = 1<br />
#first do all actions that happen up to this point to make sure<br />
#things look the way they should<br />
first_action = ""<br />
for i in range( start_index ):<br />
if i in actions:<br />
first_action += actions[i] + ';'<br />
#print "Executing %s from actions %d" % (actions[i],i)<br />
#cmd.do( actions[i] )<br />
if i in settings:<br />
settingName, selection, startVal, endVal = settings[i]<br />
action = "set %s, %f, %s;" % (settingName, endVal, selection)<br />
first_action += action<br />
#print "Executing %s from settings %d" % (action,i)<br />
#cmd.do( action )<br />
if i in fades:<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
action = "set stick_transparency, 0, %s; set stick_transparency, 1, %s;" % (endVisSelection, startVisSelection)<br />
first_action += action<br />
#print "Executing %s from fades %d" % (action, i)<br />
#cmd.do( action )<br />
for i in range( start_index, end_index ):<br />
if i in settings:<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame, settings[i] )<br />
elif i in fades:<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame, fades[i] )<br />
else:<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame )<br />
#add an action<br />
if start_frame == 1:<br />
mdo_cmd = first_action<br />
if i in actions:<br />
mdo_cmd += actions[i]+";"<br />
#mdo_cmd += "set_view("+str(views[i])+")"<br />
print mdo_cmd<br />
cmd.mdo(start_frame, mdo_cmd)<br />
elif i in actions:<br />
mdo_cmd = actions[i]+";set_view("+str(views[i])+")"<br />
cmd.mdo(start_frame, mdo_cmd)<br />
#print mdo_cmd<br />
start_frame += frames[i]<br />
cmd.frame(1)<br />
cmd.mplay()<br />
<br />
def make_all():<br />
#make the whole movie<br />
global views<br />
global frames<br />
global models<br />
<br />
#first get total number of frames<br />
ftot = 0<br />
setcommand = ""<br />
for i,nframes in enumerate(frames[:-1]):<br />
ftot += nframes<br />
if i in models:<br />
setcommand += " " + models[i] + " "<br />
else:<br />
setcommand += " 1 x%i" % nframes<br />
<br />
#initialize movie<br />
#cmd.mset("1 x%i" % ftot)<br />
#cmd.mset("1 x50 1 -30 30 x20")<br />
cmd.mset( setcommand )<br />
<br />
#loop through views<br />
start_view = views[0][:]<br />
first_frame = 1<br />
for i,view in enumerate(views[1:]):<br />
end_view = view[:]<br />
if i in settings:<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame, settings[i] )<br />
elif i in fades:<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame, fades[i] )<br />
else:<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame )<br />
#add an action<br />
if i in actions:<br />
mdo_cmd = actions[i]#+";set_view ("+str( views[i] )+")"<br />
print mdo_cmd<br />
cmd.mdo(first_frame, mdo_cmd)<br />
first_frame += frames[i]<br />
start_view = end_view[:]<br />
cmd.frame(1)<br />
<br />
## views = readViews( "viewfile.txt" )<br />
## frames = readFrames( "viewfile.frm" )<br />
## actions = readActions( "viewfile.act" )<br />
##print "Length ",len(views)<br />
#for v in views:<br />
# print v<br />
#cur_view = views[0]<br />
views = []<br />
frames = []<br />
models = {}<br />
actions = {}<br />
scenes = {}<br />
settings = {}<br />
fades = {}<br />
scene_counter = 0<br />
cur_index = -1<br />
cmd.set( "scene_animation_duration","0" )<br />
#cmd.set_view( cur_view )<br />
<br />
cmd.extend("sn", show_next )<br />
cmd.extend("sp", show_prev )<br />
cmd.extend("sc", show_cur )<br />
cmd.extend("sinsert", insert_current )<br />
cmd.extend("sdelete", delete_current )<br />
cmd.extend("sreplace", replace_current )<br />
cmd.extend("sappend", append_view )<br />
cmd.extend("sscene", insert_scene )<br />
cmd.extend("sgo", go_to_view )<br />
cmd.extend("sreadold", read_all )<br />
cmd.extend("swriteold", write_views )<br />
cmd.extend("slist", list_frames )<br />
cmd.extend("ssetf", set_frames_current )<br />
cmd.extend("sshow", show_transition )<br />
cmd.extend("srecord", make_all )<br />
cmd.extend("saction", add_action_current )<br />
cmd.extend("sdelaction", clear_action_current )<br />
cmd.extend("sdumpactions", list_actions )<br />
cmd.extend("sappendaction", append_action_current )<br />
cmd.extend("smorph", morph_models )<br />
cmd.extend("sinterpsetting", interpolate_settings )<br />
cmd.extend("sdeletesetting", delete_settings )<br />
cmd.extend("scrossfade", crossfade )<br />
cmd.extend("swrite", writeKeyViewFile )<br />
cmd.extend("sread", readKeyViewFile )<br />
cmd.extend("ssetupview", setup_view )<br />
</source><br />
<br />
===movs.py===<br />
<br />
:Math and animation routines for slerpy<br />
<br />
<source lang="python"><br />
##################################################################################<br />
#movs.py - Math and animation routines for slerpy<br />
#Copyright (C) 2006 Joel Bard<br />
#<br />
#This program is free software; you can redistribute it and/or<br />
#modify it under the terms of the GNU General Public License<br />
#as published by the Free Software Foundation; either version 2<br />
#of the License, or (at your option) any later version.<br />
#<br />
#This program is distributed in the hope that it will be useful,<br />
#but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br />
#GNU General Public License for more details.<br />
#<br />
#You should have received a copy of the GNU General Public License<br />
#along with this program; if not, write to the Free Software<br />
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br />
#################################################################################<br />
<br />
from pymol import cmd,stored<br />
from math import *<br />
<br />
def rmat2quat( M ):<br />
#M is a list of 9 values being the elements of the rotation matrix in row order<br />
T = M[0] + M[4] + M[8] + 1<br />
print "Trace ",T<br />
if T>0:<br />
S = 0.5 / sqrt(T)<br />
W = 0.25/S<br />
X = (M[7] - M[5])*S<br />
Y = (M[2] - M[6])*S<br />
Z = (M[3] - M[1])*S<br />
else:<br />
if M[0] > M[4] and M[0] > M[8]:<br />
S = sqrt( 1.0 + M[0] - M[4] - M[8]) * 2<br />
X = 0.25 * S<br />
Y = (M[1] + M[3])/S<br />
Z = (M[2] + M[6])/S<br />
W = (M[5] - M[7])/S<br />
elif M[4] > M[8]:<br />
S = sqrt( 1.0 + M[4] - M[0] - M[8] ) * 2<br />
X = (M[1] + M[3])/S<br />
Y = 0.25 * S<br />
Z = (M[5] + M[7])/S<br />
W = (M[2] - M[6])/S<br />
else:<br />
S = sqrt( 1.0 + M[8] - M[0] - M[4]) * 2<br />
X = (M[2] + M[6])/S<br />
Y = (M[5] + M[7])/S<br />
Z = 0.25 * S<br />
W = (M[1] - M[3])/S<br />
return [X,Y,Z,W]<br />
<br />
def quat2rmat( Q ):<br />
#Q is a list of 4 values being the quaternion X Y Z W<br />
X=Q[0]<br />
Y=Q[1]<br />
Z=Q[2]<br />
W=Q[3]<br />
xx = X*X<br />
xy = X*Y<br />
xz = X*Z<br />
xw = X*W<br />
yy = Y*Y<br />
yz = Y*Z<br />
yw = Y*W<br />
zz = Z*Z<br />
zw = Z*W<br />
<br />
M= [1.0]*9<br />
M[0] = 1 - 2 * ( yy + zz )<br />
M[1] = 2 * ( xy - zw )<br />
M[2] = 2 * ( xz + yw )<br />
M[3] = 2 * ( xy + zw )<br />
M[4] = 1 - 2 * ( xx + zz )<br />
M[5] = 2 * ( yz - xw )<br />
M[6] = 2 * ( xz - yw )<br />
M[7] = 2 * ( yz + xw )<br />
M[8] = 1 - 2 * ( xx + yy )<br />
return M<br />
<br />
def quatconj( Q ):<br />
return [-Q[0],-Q[1],-Q[2],Q[3]]<br />
<br />
def quatmag( Q ):<br />
s = 0.0<br />
QC = quatconj(Q)<br />
for x in range(4):<br />
s += Q[x]*Q[x]<br />
print s<br />
return sqrt(s)<br />
<br />
def quatnorm( Q ):<br />
m = quatmag( Q )<br />
return [q/m for q in Q]<br />
<br />
def quatdotprod( q1, q2 ):<br />
dp = 0<br />
for i in range(4):<br />
dp += q1[i]*q2[i]<br />
return dp<br />
<br />
def vectnorm( V ):<br />
mag = 0.0<br />
for x in V:<br />
mag += x*x<br />
mag = sqrt(mag)<br />
return [x/mag for x in V]<br />
<br />
def quat2axisangle( Q ):<br />
#returns list where 0..2 are rot axis and 3 is angle<br />
qn = quatnorm( Q )<br />
cos_a = Q[3]<br />
angle = acos( cos_a ) * 2<br />
sin_a = sqrt( 1.0 - cos_a * cos_a )<br />
if fabs( sin_a ) < 0.000005:<br />
sin_a = 1<br />
ax_an = [ q/sin_a for q in Q[0:3] ]<br />
ax_an.append( angle )<br />
return ax_an<br />
<br />
def axisangle2quat( ax_an ):<br />
#ax_an is a list with axis coordinates followed by rotation angle<br />
axn = vectnorm( ax_an[:3] )<br />
angle = ax_an[3]<br />
sin_a = sin( angle / 2 )<br />
cos_a = cos( angle / 2 )<br />
Q = [ x * sin_a for x in axn ]<br />
Q.append( cos_a )<br />
return Q<br />
<br />
def rmat2axisangle( M ):<br />
q = rmat2quat( M )<br />
return quat2axisangle( q )<br />
<br />
def axisangle2rmat( a ):<br />
q = axisangle2quat( a )<br />
return quat2rmat( q )<br />
<br />
def animate_transition( start_view, end_view, nframes, first_frame, settings = [] ):<br />
#print "Views"<br />
#print start_view,'\n',end_view<br />
<br />
cview = start_view[:]<br />
cmd.set_view( start_view )<br />
<br />
#get initial and final quaternions for interpolation<br />
#print start_view[0:9]<br />
#get quaternions<br />
qstart = rmat2quat( start_view[0:9] )<br />
qend = rmat2quat( end_view[0:9] )<br />
<br />
#test for long way vs. short way<br />
if quatdotprod( qstart,qend ) < 0:<br />
qstart = [-q for q in qstart]<br />
<br />
axan_start = quat2axisangle( qstart )<br />
axan_end = quat2axisangle( qend )<br />
<br />
axan_cur = axan_start[:]<br />
frame_start = first_frame<br />
frame_end = frame_start + nframes<br />
doFade = 0<br />
doSetting = 0<br />
if len( settings ) == 4:<br />
settingName, selection, startVal, endVal = settings<br />
settingStep = (endVal-startVal)/float(nframes)<br />
print "Setting step ", settingStep<br />
doSetting = 1<br />
elif len( settings ) == 3:<br />
startVisSelection, endVisSelection, sticksOnly = settings<br />
settingStep = 1.0/float(nframes)<br />
doFade = 1<br />
for f in range( frame_start , frame_end):<br />
#get rotmat<br />
#using angle axis<br />
<br />
for i in range(4):<br />
axan_cur[i] = axan_cur[i] + (axan_end[i]-axan_start[i])/nframes<br />
newmat = axisangle2rmat( axan_cur )<br />
#print cview<br />
for i in range(9):<br />
cview[i] = newmat[i]<br />
<br />
mdo_cmd = "set_view (["<br />
for i in range(18):<br />
if i>8:<br />
cview[i] = cview[i]+(end_view[i]-start_view[i])/nframes<br />
mdo_cmd += "%12.7f,"% cview[i]<br />
mdo_cmd = mdo_cmd[:-1]+"])"<br />
if doSetting: <br />
val = float(f-frame_start)*settingStep + startVal <br />
print val;<br />
mdo_cmd += "; set %s, %f, %s" % (settingName, val, selection)<br />
print mdo_cmd;<br />
#print "mdo ", mdo_cmd<br />
if doFade:<br />
val = float(f-frame_start)*settingStep<br />
otherVal = 1.0 - val<br />
mdo_cmd += "; set stick_transparency, %f, %s; set stick_transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
if not sticksOnly:<br />
#comment out surface transparency interpolation due to problem with transparent sticks in front of <br />
#transparent surfaces (get black holes)<br />
# mdo_cmd += "; set transparency, %f, %s; set transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
mdo_cmd += "; set cartoon_transparency, %f, %s; set cartoon_transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
cmd.mdo(f,mdo_cmd)<br />
<br />
</source><br />
[[Category:Script_Library|Slerpy]]<br />
[[Category:Math_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Transform_odb.py&diff=7670Transform odb.py2009-11-27T08:16:53Z<p>Newacct: </p>
<hr />
<div><source lang="python"><br />
from pymol import cmd<br />
import pymol<br />
import os<br />
import re<br />
<br />
def __init__(self):<br />
cmd.extend('transform_odb', transform_odb)<br />
<br />
# Creates a new object name from selection after transforming it with O-style matrix<br />
# found in matrix_file<br />
# Author: Mark Saper <saper@umich.edu><br />
<br />
def transform_odb( name, selection, matrix_file='matrix.odb', transpose=0):<br />
<br />
# open the file for reading<br />
matrix_file = os.path.expanduser(matrix_file)<br />
matrix_file = os.path.expandvars(matrix_file)<br />
theInFile = open ( matrix_file,"r")<br />
<br />
# what we'll store the results in<br />
theMatrix = []<br />
<br />
# read every line in the file and ...<br />
for theCurrLine in theInFile.readlines():<br />
<br />
#print theCurrLine[0]<br />
if (theCurrLine) and (theCurrLine[0] != '!') and (theCurrLine[0] != '.'):<br />
# if the line isn't blank, make a list of items seperated by tabs<br />
theNewRow = theCurrLine.split ()<br />
# add it in the matrix<br />
theMatrix.extend ( theNewRow )<br />
<br />
# change matrix to pymol unsupported format<br />
<br />
theMatrix = [ theMatrix[0], theMatrix[3], theMatrix[6], theMatrix[9],<br />
theMatrix[1], theMatrix[4], theMatrix[7], theMatrix[10],<br />
theMatrix [2], theMatrix [5], theMatrix[8], theMatrix[11], <br />
0.0, 0.0, 0.0, 0.0 ]<br />
theMatrix = [ float(x) for x in theMatrix] <br />
<br />
<br />
# close the file<br />
theInFile.close ()<br />
#<br />
r = cmd.create ( name, selection)<br />
<br />
r = cmd.transform_object( name, theMatrix, transpose=transpose)<br />
<br />
return r<br />
<br />
cmd.extend('transform_odb', transform_odb)<br />
</source><br />
[[Category:Script_Library|Transform_ODB]]<br />
[[Category:Math_Scripts]]<br />
[[Category:ThirdParty_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=MakeVinaCommand&diff=7669MakeVinaCommand2009-11-27T08:16:17Z<p>Newacct: </p>
<hr />
<div>= Overview =<br />
[http://vina.scripps.edu/ Vina] is a new, very fast, molecular docking program, written by Oleg Trott. In order to run Vina, you should have [http://mgltools.scripps.edu/downloads MGLTools1.5.4] installed (you need prepare_receptor4.py and prepare_ligand4.py). But, you don't need MGLTools for this script to run.<br />
<br />
To run Vina it needs to know the center of the protein and also its extents (size in XYZ directions). We can easily do this with PyMOL.<br />
<br />
Requirements:<br />
* [[COM]] -- simple script to get the center of mass of a selection<br />
<br />
Todo:<br />
* Commandline options<br />
* Robustness to vagaries of input<br />
* Usage & Help<br />
<br />
= Usage =<br />
<source lang="bash"><br />
pymol -cq ./makeVinaCommandFromProtein.py proteinFile ligandFile<br />
</source><br />
<br />
For high-throughput screening, where we compare each ligand to each protein, I typically wrap the script in a for-loop like:<br />
<source lang="bash"><br />
# foreach protein in my proteins directory<br />
for protein in proteinsDir/*; do<br />
<br />
# foreach ligand in my ligands directory<br />
for ligand in ligandsDir/*; do;<br />
<br />
# make a Vina command to run the protein vs the ligand.<br />
# note the backticks to run the output<br />
`pymol -cq ./makeVinaCommandFromProtein.py $protein $ligand | grep vina`;<br />
<br />
done;<br />
done;<br />
</source><br />
<br />
= The Code =<br />
<source lang="python"><br />
# -*- coding: utf-8 -*-<br />
#<br />
# makeVinaCommandFromProtein.py -- automatically make a valid Vina command from a PDB file and a ligand (name)<br />
#<br />
# Author: Jason Vertrees<br />
# Date : 2/2009<br />
#<br />
from pymol import cmd<br />
from sys import argv<br />
from os import path<br />
<br />
# try to keep PyMOL quiet<br />
cmd.feedback("disable","all","actions")<br />
cmd.feedback("disable","all","results")<br />
<br />
# prepare some output names<br />
protName= path.basename(argv[-2])<br />
ligName = path.basename(argv[-1])<br />
outName = protName.split(".")[0] + "." + ligName.split(".")[0] + ".docked.pdbqt"<br />
logName = protName.split(".")[0] + "." + ligName.split(".")[0] + ".log"<br />
<br />
# very unsafe commandline checking; needs updating<br />
cmd.load(argv[-2], protName)<br />
cmd.load(argv[-1], ligName)<br />
<br />
# remove the ligand before calculating the center of mass<br />
cmd.delete(ligName)<br />
<br />
# load center of mass script<br />
cmd.do("run /home/path/to/COM.py")<br />
<br />
# calculate the center of mass and extents<br />
(comX, comY, comZ) = COM(protName)<br />
((maxX, maxY, maxZ), (minX, minY, minZ)) = cmd.get_extent(protName)<br />
<br />
# print the command line<br />
print "vina --receptor ", protName, " --ligand ", ligName, "--center_x ", str(comX), " --center_y ", str(comY),\<br />
" --center_z ", str(comZ), " --size_x ", str(abs(maxX-minX)), " --size_y ", str(abs(maxY-minY)), " --size_z ", \<br />
str(abs(maxZ-minZ)), " --all ", outName , " --exhaustiveness 200 --log ", logName, " \n"<br />
</source><br />
<br />
= Example =<br />
<source lang="bash"><br />
# execute the script<br />
> pymol -cq ./makeVinaCommandFromProtein.py 1ia6_gh09.pdb glucose.pdb | grep vina<br />
<br />
# the output<br />
vina --receptor 1ia6_gh09.pdbqt --ligand glucose_dimer.pdbqt --center_x 1.86797851457 --center_y 17.7951449088 --center_z 65.2250072289 --size_x 55.9499988556 --size_y 49.7459993362 --size_z 58.1769981384 --all 1ia6_gh09.glucose_dimer.docked.pdbqt --exhaustiveness 100 --log 1ia6_gh09.glucose_dimer.log<br />
</source><br />
<br />
= See Also =<br />
* [[COM]] -- you need this script<br />
* [http://vina.scripps.edu/ Vina] -- the docking software<br />
<br />
[[Category:Script_Library|MakeVinaCommandFromProtein]]</div>Newaccthttps://pymolwiki.org/index.php?title=WriteSS&diff=7668WriteSS2009-11-27T08:14:58Z<p>Newacct: </p>
<hr />
<div>== Overview ==<br />
This script will write the secondary structural elements for each PDB file in some specified directory, for each alpha carbon in the protein, to an output text file. Residues without secondary structure definition will get a "." in the string.<br />
<br />
This is untested code and has little chance of working for anyone but me. Although, it does work for me.<br />
<br />
== Instructions ==<br />
# Copy the code to your machine<br />
# Find '''FIXME''' in the code below and change "files" to either a glob like the one already there (for a whole directory) or a list with one element (for just one file).<br />
# change the output filename. By default it's '''PDBCODE.ss'''.<br />
<br />
== The Code ==<br />
<source lang="python"><br />
import os<br />
import os.path<br />
import glob<br />
<br />
from pymol import cmd<br />
from pymol import stored<br />
from pymol import selector<br />
<br />
files = glob.glob("/tmp/thy_model/*.pdb")<br />
<br />
for file in files:<br />
pdbName = os.path.basename(file).split(".")[0]<br />
cmd.load(file, pdbName)<br />
outFile = open(pdbName + '.ss', 'wb')<br />
stored.ss = ""<br />
cmd.iterate( '(n. CA)', 'stored.ss = stored.ss + ("%1s"%ss)')<br />
for c in stored.ss:<br />
if c == " ":<br />
outFile.write('.')<br />
else:<br />
outFile.write(c)<br />
cmd.delete(pdbName)<br />
outFile.close()<br />
</source><br />
<br />
== Example ==<br />
<source lang="python"><br />
python ss.pym # my directory has 1d7p.pdb in it<br />
</source><br />
output for 1D7P.pdb:<br />
<br />
...............HHH.......SSS..SSSHHHHH..................................................................SS..SS..................................................<br />
<br />
<br />
[[Category:Script_Library|Write SS]]<br />
[[Category:Structural_Biology_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=CreateSecondaryStructure&diff=7667CreateSecondaryStructure2009-11-27T08:14:15Z<p>Newacct: </p>
<hr />
<div>===DESCRIPTION===<br />
To build a peptide sequence. <br />
<br />
===SETUP===<br />
run CreateSecondaryStructure.py<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv1.0, Windows platform<br />
*Many bugs to be found<br />
<br />
===USAGE===<br />
*seqInfo = getTableFromCsvFile("seqInfo.csv")<br />
with in the file something like:<br />
MET,-54,-47<br />
PRO,-54,-47<br />
<br />
*seqInfo = [['MET',-57,-47],['PRO',-57,-47]]<br />
*createPeptide(seqInfo)<br />
<br />
===EXAMPLES===<br />
seqInfo = [['MET',-57,-47],['PRO',-57,-47]]<br />
createPeptide(seqInfo)<br />
<br />
===SCRIPTS (CreateSecondaryStructures.py)===<br />
CreateSecondaryStructures.py <br />
<source lang="python"><br />
##############################################<br />
# Original Author: Dan Kulp<br />
# Date : 9/8/2005<br />
# MOdified by Jurgen F. Doreleijers<br />
# For Hamid Eghbalnia <br />
#<br />
#############################################<br />
# Call in window like : <br />
# @C:\Documents and Settings\jurgen.WHELK.000\workspace\Wattos\python\Wattos\Utils\CreateSecondaryStructures.py<br />
# Next line is a pymol directive<br />
python<br />
import urllib<br />
<br />
<br />
# Well I guess one can build a protein with it but the vdw contacts would be horrible.<br />
# Peptide needs to be at least 2 residues.<br />
def createPeptide(seqInfo):<br />
cmd.delete("all")<br />
# Creates residue TWO<br />
editor.attach_amino_acid('pk1',seqInfo[1][0]) <br />
# Creates residue ONE<br />
createSS('resi 2', sequence=seqInfo[0][0],terminal='N')<br />
print "found sequence info for number of residues: ", len(seqInfo)<br />
for i in range(2,len(seqInfo) ):<br />
# resn is the residue number of the new residue<br />
resn = i + 1<br />
print "Adding residue: ", resn, seqInfo[i][0]<br />
# Note that the previous residue is numbered i. <br />
resi = 'resi '+`i`<br />
createSS(resi, sequence=seqInfo[i][0])<br />
for i in range( len(seqInfo) ):<br />
resi = 'resi '+`i+1`<br />
# print "Setting backbone angles for residue: ", (i+1), seqInfo[i][0],seqInfo[i][1],seqInfo[i][2]<br />
set_phipsi(resi,seqInfo[i][1],seqInfo[i][2])<br />
<br />
# Create generic secondary structure, based off a selection<br />
def createSS(sel, sequence='ALA',repeat=1,terminal='C'):<br />
<br />
# Set selection<br />
selection = "%s and name %s" % (sel,terminal)<br />
<br />
# Pick atom for editing - interestingly only need to do this for the first addition<br />
cmd.edit(selection,None,None,None,pkresi=0,pkbond=0)<br />
<br />
# Array of residues<br />
seq = sequence.split(",")<br />
<br />
# Get residue numbering .. potential bug here if number is inconsistent.. (Only works at c-terminal)<br />
resi = int(cmd.get_model(sel).atom[0].resi) + 1<br />
# Loop and build new residues<br />
for i in range(1,repeat+1):<br />
for s in seq:<br />
# print "residue[%i]: %s %s" % (i,s,terminal)<br />
editor.attach_amino_acid('pk1',s)<br />
<br />
# Remove extra OXT carboxylate atom (OXT1, OXT2 ?) .. fix as needed<br />
if terminal == 'C':<br />
cmd.remove("%s and name OXT" % sel)<br />
<br />
<br />
def set_phipsi(sel,phi,psi):<br />
# Get atoms from selection<br />
atoms = cmd.get_model("byres ("+sel+")")<br />
<br />
# Loop through atoms in selection <br />
for at in atoms.atom:<br />
if at.name == "N":<br />
# Check for a null chain id (some PDBs contain this) <br />
unit_select = ""<br />
if not at.chain == "":<br />
unit_select = "chain "+str(at.chain)+" and "<br />
<br />
try:<br />
# Define residue selections <br />
residue_def_prev = unit_select+'resi '+str(int(at.resi)-1)<br />
residue_def = unit_select+'resi '+str(at.resi) <br />
# print "residue_def_prev: [%s]" % residue_def_prev<br />
# print "residue_def : [%s]" % residue_def<br />
if at.resn == "PRO":<br />
print "Skipping setting phi for PRO"<br />
else:<br />
old_phi = cmd.get_dihedral(residue_def_prev+' and name C',residue_def+' and name N', residue_def+' and name CA',residue_def+' and name C') <br />
cmd.set_dihedral( residue_def_prev+' and name C',residue_def+' and name N', residue_def+' and name CA',residue_def+' and name C' ,phi)<br />
print "Changed residue %4s %4s phi: from %6.1f to %6.1f" % (at.resn, at.resi, old_phi, float(phi)) <br />
except:<br />
<br />
print "Note skipping set of phi because of error; this is normal for a N-terminal residue"<br />
try:<br />
residue_def = unit_select+'resi '+str(at.resi)<br />
residue_def_next = unit_select+'resi '+str(int(at.resi)+1)<br />
# print "residue_def : [%s]" % residue_def<br />
# print "residue_def_next: [%s]" % residue_def_next<br />
old_psi = cmd.get_dihedral(residue_def +' and name N',residue_def+' and name CA',residue_def+' and name C', residue_def_next+' and name N')<br />
cmd.set_dihedral( residue_def +' and name N',residue_def+' and name CA',residue_def+' and name C', residue_def_next+' and name N',psi)<br />
print "Changed residue %4s %4s psi: from %6.1f to %6.1f" % (at.resn, at.resi, old_psi, float(psi)) <br />
except:<br />
print "Note skipping set of psi; this is normal for a C terminal residue"<br />
<br />
def getTableFromCsvFile(urlLocation):<br />
result = []<br />
r1 = urllib.urlopen(urlLocation)<br />
data = r1.read()<br />
r1.close() <br />
dataLines = data.split("\n") <br />
for dataLine in dataLines:<br />
if dataLine:<br />
result.append( dataLine.split(',') ) <br />
return result<br />
<br />
# next line is a pymol directive.<br />
python end<br />
<br />
os.chdir("C:\Documents and Settings\jurgen.WHELK.000\workspace\Wattos\python\Wattos\Utils")<br />
seqInfo = getTableFromCsvFile("seqInfo.csv")<br />
createPeptide(seqInfo)<br />
<br />
</source><br />
<br />
<br />
[[Category:Script_Library|CreateSecondaryStructure]]<br />
[[Category:Structural_Biology_Scripts|CreateSecondaryStructure]]</div>Newaccthttps://pymolwiki.org/index.php?title=Wfmesh&diff=7666Wfmesh2009-11-27T08:13:52Z<p>Newacct: </p>
<hr />
<div>===DESCRIPTION===<br />
This script will create an object for any Wavefront(.OBJ) mesh file. This is a way to extend the number of objects you can use. Also, you have more control over the coloring, transformations, etc than the CGOs. Although there are a number of these obj files on the web, you can also easily created them with open source tools ([http://www.openfx.org OpenFX], [http://synapses.mcg.edu/tools/xroads/xroads.stm Crossroads3D]). It takes literally, 2 min to get an object created and then loaded into pymol. Simply open OpenFX Designer, click File->Insert->Model, then choose any of the models (or create your own of course!), then export it as .3ds file. Then open the .3ds file from Crossroads3D and export as Wavefront OBJ. <br />
<br />
*createWFMesh - create a mesh object from Wavefront (*.obj) formated file<br />
<br />
===IMAGES===<br />
[[Image:Starwars_pymol.png|thumb|left|Star Wars Anyone?]]<br />
[[Image:Torus_pymol.png|thumb|left|A Torus, as an example shape you could do. Notice polygon normals are being used...need smoothing!]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
[[Category:ThirdParty_Scripts]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
===SETUP===<br />
Simply "run WFMesh.py"<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform, should work on linux as well.<br />
*Coloring is fixed for grey and sections of mesh are stored, but not used.<br />
*Simple opengl calls; not optimized (display lists, etc) or anything.<br />
*Vertex Normal code is broken, so normals are per polygon right now.<br />
*Post problems in the discussion page, on 'my talk' page or just email me : dwkulp@mail.med.upenn.edu<br />
<br />
<br />
===USAGE===<br />
createWFObj file, name [,translate=[0,0,0]] [,flip=0]<br />
<br />
===EXAMPLES===<br />
createWFObj "ship.obj" "Ship"<br />
createWFObj "torus.obj" "Torus" flip=1 # Flip = 1, if OBJ created by openFX, crossroads3D combination<br />
createWFObj "torus.obj" "Torus" translate=[10,10,0] flip=1 <br />
<br />
===REFERENCES===<br />
[http://www.openfx.org OpenFX]<br />
[http://synapses.mcg.edu/tools/xroads/xroads.stm Crossroads3D]<br />
<br />
===SCRIPTS (WFMesh.py)===<br />
WFMesh.py<br />
<source lang="python"><br />
###############################################<br />
# File: WFObj.py<br />
# Author: Dan Kulp<br />
# Creation Date: 5/13/05<br />
#<br />
# Notes:<br />
# Create openGL objects from a wavefront (obj) file<br />
###############################################<br />
<br />
import os<br />
import re<br />
import math<br />
from pymol.opengl.gl import *<br />
from pymol.callback import Callback<br />
<br />
<br />
# Wrapper Function, to create a given WFObj with a specific name (flip = 1 if OpenFX + Crossroads used)<br />
def createWFObj(file, name,translate=[0,0,0],flip=0):<br />
obj = WFMesh(file,translate,flip)<br />
cmd.load_callback(obj,name)<br />
<br />
<br />
# Class for Wavefront Mesh<br />
class WFMesh(Callback):<br />
<br />
verts = [] # list of vertices<br />
polys = [] # list of poylgons<br />
pnorms = [] # list of polynomal normals<br />
vnorms = {} # dict. of vertex normals<br />
vavenorms = [] # list of vertex normals, redundant -- I'm far froma python pro.<br />
sections = {} # list of sections of mesh<br />
<br />
# Read mesh into memory<br />
def readOBJ(self,file):<br />
if os.path.exists(file):<br />
input = open(file,'r')<br />
for line in input:<br />
dat = re.split("\s+", line)<br />
<br />
# Find vertex line<br />
if line[0] == 'v' and line[1] != 't' and line[1] != 'n': self.verts.append([dat[1],dat[2],dat[3]])<br />
<br />
# Find polygon line<br />
if line[0] == 'f': self.polys.append([dat[1],dat[2],dat[3]])<br />
<br />
# Find section line<br />
if line[0] == 'g': self.sections[len(self.polys)] = dat[1] <br />
<br />
<br />
# Compute the normals for each polygon and each vertex <br />
def computeNorms(self):<br />
<br />
# Compute norms for each polygon<br />
for p in self.polys:<br />
v12 = [float(self.verts[int(p[1])-1][0]) - float(self.verts[int(p[0])-1][0]),\<br />
float(self.verts[int(p[1])-1][1]) - float(self.verts[int(p[0])-1][1]),\<br />
float(self.verts[int(p[1])-1][2]) - float(self.verts[int(p[0])-1][2]) \<br />
]<br />
<br />
v13 = [float(self.verts[int(p[2])-1][0]) - float(self.verts[int(p[0])-1][0]),\<br />
float(self.verts[int(p[2])-1][1]) - float(self.verts[int(p[0])-1][1]),\<br />
float(self.verts[int(p[2])-1][2]) - float(self.verts[int(p[0])-1][2]) \<br />
] <br />
<br />
# Compute poly normal<br />
polynorm = self.cross(v12,v13) <br />
norm = self.normalize(polynorm)<br />
<br />
<br />
# Files created by OpenFX, Crossroads combination need have their normals flipped <br />
if self.flip:<br />
norm[0] = -norm[0]<br />
norm[1] = -norm[1]<br />
norm[2] = -norm[2]<br />
<br />
# Append poly norm to polygonal norm array<br />
self.pnorms.append(norm)<br />
<br />
# Add norm to each vertexes norm..<br />
try:<br />
self.vnorms[int(p[0])-1] = [float(self.vnorms[int(p[0])-1][0]) + norm[0],<br />
float(self.vnorms[int(p[0])-1][1]) + norm[1],<br />
float(self.vnorms[int(p[0])-1][2]) + norm[2]<br />
]<br />
except:<br />
self.vnorms[int(p[0])-1] = [norm[0],norm[1],norm[2]]<br />
<br />
try: <br />
self.vnorms[int(p[1])-1] = [float(self.vnorms[int(p[1])-1][0]) + norm[0],<br />
float(self.vnorms[int(p[1])-1][1]) + norm[1],<br />
float(self.vnorms[int(p[1])-1][2]) + norm[2]<br />
]<br />
except:<br />
self.vnorms[int(p[1])-1] = [norm[0],norm[1],norm[2]]<br />
<br />
try:<br />
self.vnorms[int(p[2])-1] = [float(self.vnorms[int(p[1])-1][0]) + norm[0],<br />
float(self.vnorms[int(p[1])-1][1]) + norm[1],<br />
float(self.vnorms[int(p[1])-1][2]) + norm[2]<br />
]<br />
except:<br />
self.vnorms[int(p[2])-1] = [norm[0],norm[1],norm[2]]<br />
<br />
<br />
# Average out each vnorm..<br />
index = 0<br />
for v in self.vnorms.values():<br />
self.vavenorms.append([v[0]/4, v[1]/4, v[2]/4]) <br />
index += 1<br />
<br />
# Utility function to normalize a given vector<br />
def normalize(self,v):<br />
mag = v[0]*v[0]+v[1]*v[1]+v[2]*v[2]<br />
if mag <= 0:<br />
mag = 1<br />
else:<br />
mag = math.sqrt(mag)<br />
<br />
return [v[0]/mag, v[1]/mag,v[2]/mag]<br />
<br />
# Utility cross product function<br />
def cross(self,v1,v2):<br />
x = 0<br />
y = 1<br />
z = 2<br />
<br />
return [v1[y]*v2[z] - v1[z]*v2[y],\<br />
v1[z]*v2[x] - v1[x]*v2[z],\<br />
v1[x]*v2[y] - v1[y]*v2[x]<br />
]<br />
<br />
# Constructor<br />
def __init__(self, file,translate=[0,0,0],flip=0):<br />
self.verts = []<br />
self.polys = [] <br />
self.pnorms = []<br />
self.vnorms = {}<br />
self.vavenorms = []<br />
self.translate = translate<br />
self.flip = flip <br />
<br />
print "Read in file: "+str(file)<br />
self.readOBJ(file)<br />
print "Done reading in WFMesh, now compute norms"<br />
self.computeNorms()<br />
print "Done computing norms, now display WFMesh"<br />
<br />
# Draw Function<br />
def __call__(self):<br />
<br />
glColorMaterial(GL_FRONT, GL_DIFFUSE); <br />
glEnable(GL_COLOR_MATERIAL);<br />
glShadeModel(GL_SMOOTH);<br />
<br />
# Color Everything grey<br />
glColor3f(0.5,0.5,0.5);<br />
<br />
index = 0<br />
glPushMatrix()<br />
glTranslated(self.translate[0],self.translate[1],self.translate[2])<br />
for p in self.polys:<br />
glBegin(GL_POLYGON)<br />
glNormal3f(float(self.pnorms[index][0]),float(self.pnorms[index][1]),float(self.pnorms[index][2]))<br />
<br />
for i in range(0,len(p)):<br />
glVertex3f(float(self.verts[int(p[i])-1][0]),float(self.verts[int(p[i])-1][1]),float(self.verts[int(p[i])-1][2]))<br />
<br />
# Vertex Normals - not computed correctly, so commented out for now<br />
# norm = self.vnorms[int(p[i])-1]<br />
# glNormal3f(float(norm[0]),float(norm[1]),float(norm[2]))<br />
glEnd()<br />
index += 1<br />
glPopMatrix()<br />
<br />
<br />
<br />
<br />
<br />
cmd.extend("createWFObj", createWFObj)<br />
<br />
</source><br />
<br />
===ADDITIONAL RESOURCES===<br />
Torus.obj<br />
[http://pymolwiki.org/images/9/98/Torus.zip Torus.zip]<br />
<br />
<br />
[[Category:Script_Library|WFMesh]]</div>Newaccthttps://pymolwiki.org/index.php?title=FilterByMol&diff=7665FilterByMol2009-11-27T08:13:34Z<p>Newacct: </p>
<hr />
<div>== Overview ==<br />
This script filters through all the PDBs in the parent dir (you can easily the the directory it scans). For each molecule, it saves '''just''' the ligands/heteroatoms (excluding the waters). This gives you a simple way to filter through a database of proteins looking only at their ligands.<br />
<br />
This script, as noted below, works on the objects at the level of a '''molecule'''. While we can [[iterate]] over atom number (ID), residue number (resi), etc we do not have any such "MOLID". So, we provide this simple workaround. You might need this file because if you have a residue (like #111 from 3BEP) that consists of a molecule and an atom then there's no other way to save the separate pieces (of molecule/atom) into two (or more files). As you can see in the following listing, if we iterate over the hetero atoms (and not waters) in 3BEP we get,<br />
<source lang="python"><br />
PyMOL>iterate bymol het, print resi, resn, ID, chain, segi, alt<br />
111 5CY 6473 C <br />
111 5CY 6474 C <br />
111 5CY 6476 C <br />
111 5CY 6477 C <br />
111 5CY 6478 C <br />
111 5CY 6479 C <br />
111 5CY 6480 C <br />
111 5CY 6481 C <br />
111 5CY 6482 C <br />
111 5CY 6483 C <br />
111 5CY 6484 C <br />
111 5CY 6485 C <br />
111 5CY 6486 C <br />
111 5CY 6487 C <br />
111 5CY 6488 C <br />
111 5CY 6489 C <br />
111 5CY 6490 C <br />
</source><br />
which does not allow us to separate the two pieces.<br />
<br />
== The Code ==<br />
<source lang="python"><br />
python<br />
<br />
#<br />
# This simple script will filter through all PDBs in a directory, and for each one<br />
# save all the ligands/heterotoms (that aren't waters) to their own file. This<br />
# script operates at the level of molecules, not residues, atoms, etc. Thus, if<br />
# you have a ligand that PyMOL is treating as ONE residue, but is actually two<br />
# separate molecules, or a molecule and an atom, then you will get multiple files.<br />
#<br />
<br />
from glob import glob<br />
from os import path<br />
from pymol import stored<br />
<br />
theFiles = glob("../*.pdb");<br />
<br />
for f in theFiles:<br />
# load the file<br />
cmd.load(f);<br />
# remove the protein and waters<br />
cmd.remove("polymer or resn HOH");<br />
<br />
cmd.select("input", "all")<br />
cmd.select("processed", "none")<br />
mol_cnt = 0<br />
<br />
while cmd.count_atoms("input"):<br />
# filter through the selections, updating the lists<br />
cmd.select("current","bymolecule first input")<br />
cmd.select("processed","processed or current")<br />
cmd.select("input","input and not current")<br />
<br />
# prepare the output parameters<br />
curOut = path.basename(f).split(".")[0] + "_" + str(mol_cnt).zfill(5) + "_het.pdb"<br />
curSel = "current"<br />
<br />
# save the file<br />
cmd.save( curOut, curSel );<br />
print "Saved " + curSel + " to " + curOut<br />
<br />
mol_cnt = mol_cnt + 1;<br />
<br />
# remove all to move to next molecule<br />
cmd.delete("*"); <br />
<br />
python end<br />
</source><br />
<br />
[[Category:Script_Library]]<br />
[[Category:System_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Transform_odb&diff=7664Transform odb2009-11-27T08:13:08Z<p>Newacct: </p>
<hr />
<div>'''transform_odb''' transforms the coordinates of a selection and creates a new object with the transformed coordinates. The transformation matrix is read from a specified "O"-style tranformation matrix file (.odb) written by "O" or by any of the Uppsala Software Factory programs (from Gerard Klegweit) such as LSQMAN.<br />
<br />
===USAGE===<br />
transform_odb name, (selection), matrix_file [, transpose]<br />
<br />
* name = new or modified object that will contain transformed coordinates<br />
* selection = selection of atoms to transform<br />
* matrix_file = file name or path of .odb file containing a transformation matrix data block<br />
* transpose (default 0]<br />
<br />
===EXAMPLES===<br />
transform_odb moved_helix, ( mol1 and resi 200:220 ), move_helix.odb<br />
<br />
===USER COMMENTS===<br />
Please send questions or bug reports to Mark Saper, mailto:saper@umich.edu<br />
<br />
===SOURCE===<br />
<br />
<source lang="python"><br />
from pymol import cmd<br />
import pymol<br />
import os<br />
import re<br />
<br />
def __init__(self):<br />
cmd.extend('transform_odb', transform_odb)<br />
<br />
# Creates a new object name from selection after transforming it with O-style matrix<br />
# found in matrix_file<br />
# Author: Mark Saper <saper@umich.edu><br />
<br />
def transform_odb( name, selection, matrix_file='matrix.odb', transpose=0):<br />
<br />
# open the file for reading<br />
matrix_file = os.path.expanduser(matrix_file)<br />
matrix_file = os.path.expandvars(matrix_file)<br />
theInFile = open ( matrix_file,"r")<br />
<br />
# what we'll store the results in<br />
theMatrix = []<br />
<br />
# read every line in the file and ...<br />
for theCurrLine in theInFile.readlines():<br />
if (theCurrLine) and (theCurrLine[0] != '!') and (theCurrLine[0] != '.'):<br />
# if the line isn't blank, make a list of items seperated by tabs<br />
theNewRow = theCurrLine.split ()<br />
# add it in the matrix<br />
theMatrix.extend ( theNewRow )<br />
<br />
# change matrix to pymol unsupported format<br />
<br />
theMatrix = [ theMatrix[0], theMatrix[3], theMatrix[6], theMatrix[9],<br />
theMatrix[1], theMatrix[4], theMatrix[7], theMatrix[10],<br />
theMatrix [2], theMatrix [5], theMatrix[8], theMatrix[11], <br />
0.0, 0.0, 0.0, 0.0 ]<br />
theMatrix = [ float(x) for x in theMatrix] <br />
<br />
# close the file<br />
theInFile.close ()<br />
<br />
r = cmd.create ( name, selection)<br />
r = cmd.transform_object( name, theMatrix, transpose=transpose)<br />
<br />
return r<br />
<br />
cmd.extend('transform_odb', transform_odb)<br />
</source><br />
<br />
===SEE ALSO===<br />
[[transform_selection]], [[transform_object]]<br />
<br />
[[Category:Script Library|Transform odb]]<br />
[[Category:ThirdParty_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Pdbsurvey&diff=7663Pdbsurvey2009-11-27T08:12:50Z<p>Newacct: </p>
<hr />
<div>Hi everyone !<br />
<br />
I have created a script because I was tired of browsing the pdb for endless searches of structures relevant to my field. This scripts takes as input a text file in which you copied your favourite keywords, and the number of days you want to search back (by default, it will look at the structures added the last 50 days). It generates a report text file that contains the pdb id and name of the relevant structures that have been recently added. All you need to do is add 'run pdbsurvey.py' to your startup file, and create a text file called 'keywords.txt' with your keywords separated by an end-of-line character. Then you're ready to go. Just hit 'pdbsurvey' from within your PyMol instance, and the program returns the report file. The pdb ftp server is updated weekly.<br />
<br />
<source lang="python"><br />
from pymol import cmd<br />
<br />
def pdbsurvey(days=50):<br />
<br />
"""USAGE : pdbsurvey (<days>)<br />
Surveys the updates added to the PDB (ftp.rcsb.org) in the last<br />
50 days (or otherwise specified when calling this function) for<br />
entries that contain the words specified in the file<br />
keywords.txt.<br />
"""<br />
print days<br />
<br />
import ftplib<br />
import time<br />
import os<br />
<br />
<br />
<br />
def todaymerge():<br />
"""Puts today's date in a pdb format string.<br />
"""<br />
date=time.localtime()<br />
fyear="%i" %(date[0])<br />
fmonth="%i" %(date[1])<br />
if date[1]<10:<br />
fmonth="0"+"%i" %(date[1])<br />
fday="%i" %(date[2])<br />
if date[2]<10:<br />
fday="0"+"%i" %(date[2])<br />
dateS=fyear+fmonth+fday<br />
return dateS<br />
<br />
def file2list(filename):<br />
"""Low-level routine to brainlessly implement<br />
file.read().<br />
"""<br />
fq=open(filename,'rb')<br />
linesS=fq.read()<br />
fq.close()<br />
LIST=linesS.splitlines()<br />
return LIST<br />
<br />
def connect2pdb():<br />
"""Opens an anonymous socket to ftp://ftp.rcsb.org<br />
"""<br />
f=ftplib.FTP()<br />
f.connect ('ftp.rcsb.org')<br />
f.login ()<br />
print "Remote connection established","\n"<br />
return f<br />
<br />
def decrementdate(dateS):<br />
"""given a string date (pdb format yyyymmdd)<br />
this routine returns a string of the day before<br />
(sadly assuming that every month has 31 days, but<br />
no big deal here...).<br />
"""<br />
#decompose dateS into components<br />
yearS=dateS[0]+dateS[1]+dateS[2]+dateS[3]<br />
monthS=dateS[4]+dateS[5]<br />
dayS=dateS[6]+dateS[7]<br />
<br />
#convert each into integers<br />
yearI=int(yearS)<br />
monthI=int(monthS)<br />
dayI=int(dayS)<br />
<br />
#actual stuff<br />
dayI=dayI-1<br />
if dayI==0:<br />
dayI=31<br />
monthI=monthI-1<br />
if monthI==0:<br />
monthI=12<br />
yearI=yearI-1<br />
dayS="%i" %(dayI)<br />
monthS="%i" %(monthI)<br />
yearS="%i" %(yearI)<br />
if dayI<10:<br />
dayS="0"+dayS<br />
if monthI<10:<br />
monthS="0"+monthS<br />
#and finally...<br />
dateS=yearS+monthS+dayS<br />
return dateS<br />
<br />
def findlastdir(dateS,f,days):<br />
"""Puts the names of the "recent" directories in the<br />
list named "directoriesL".<br />
"""<br />
directoriesL=['']<br />
j=p=0<br />
while p<days:<br />
dateS=decrementdate(dateS)<br />
attempt="/pub/pdb/data/status/"+dateS<br />
try :<br />
f.cwd(attempt)<br />
directoriesL[j:j]=[attempt]<br />
j=j+1<br />
except :<br />
pass<br />
p=p+1<br />
directoriesL.pop()<br />
return directoriesL<br />
<br />
def compilinfile(directoriesL,f):<br />
"""lists all structures in the added.pdb files<br />
contained in the directories specified in directoriesL<br />
"""<br />
command="RETR added.pdb"<br />
handle=open("donotedit.dat","wrb")<br />
for k in directoriesL:<br />
f.cwd(k)<br />
print "Currently in directory ",f.pwd()<br />
f.retrbinary(command,handle.write)<br />
handle.close()<br />
return len(directoriesL)<br />
<br />
def listparser():<br />
"""Extracts the pdbids from donotedit.dat file,<br />
and stacks them into the list pdbidsL<br />
"""<br />
linesL=file2list("donotedit.dat")<br />
pdbidsL=[]<br />
for iter in linesL:<br />
pdbidsL.append(iter[57:61])<br />
for iter in pdbidsL:<br />
iter=iter.lower()<br />
pdbidsL.sort()<br />
return pdbidsL<br />
<br />
def currentrelease(f):<br />
"""Stores the content of cmpd_res.idx file<br />
This file contains the equivalencies pdbid<->title<br />
for all current entries of the PDB.<br />
"""<br />
command="RETR cmpd_res.idx"<br />
f.cwd("/pub/pdb/derived_data/index/")<br />
print "Currently in directory ",f.pwd()<br />
fq=open("dictionnary.dat",'wrb')<br />
f.retrbinary(command,fq.write)<br />
fq.close()<br />
dictL=file2list("dictionnary.dat")<br />
return dictL<br />
<br />
def extract(pdbidsL,dictL):<br />
"""Populates dictionnaryD with pdb entries found in the<br />
latest releases.<br />
"""<br />
dictionnaryD={}<br />
problemL=[]<br />
extractL=[dictionnaryD,problemL]<br />
for i in dictL:<br />
tempS=i[0:4].lower()<br />
for ii in pdbidsL:<br />
if ii == tempS:<br />
title=i[14:216]<br />
extractL[0][ii]=title<br />
if len(extractL[0].keys()) != len(pdbidsL):<br />
print "Dimension mismatch, seeking troublemaker..."<br />
for i in pdbidsL:<br />
equiv=0<br />
for ii in extractL[0].keys():<br />
if i==ii:<br />
equiv=equiv+1<br />
if equiv==0:<br />
extractL[1].append(i)<br />
return extractL<br />
<br />
def disconnectpdb(f):<br />
"""Diconnects the current ftp session<br />
"""<br />
f.quit()<br />
print "Remote connection terminated","\n"<br />
return f<br />
<br />
def releventries(dictionnaryD):<br />
"""Generates a cleaned dictionnary with only entries<br />
that have one or more keywords specified in the local<br />
user-defined keywords.txt file<br />
"""<br />
keywL=file2list("keywords.txt")<br />
relevdicD={}<br />
for i in keywL:<br />
for elem in dictionnaryD.keys():<br />
temp=dictionnaryD[elem]<br />
if temp.find(i) != -1:<br />
relevdicD[elem]=temp<br />
return relevdicD<br />
<br />
def diskcleanup(filelist=["donotedit.dat","dictionnary.dat"]):<br />
"""Lo-level disk cleanup to free up memory without the user<br />
"""<br />
for filename in filelist:<br />
command='DEL '+filename<br />
os.system(command)<br />
return "clean"<br />
<br />
<br />
<br />
<br />
print "Welcome in the auto-PDB updater !"<br />
<br />
print "Survey of updates made since",days,"days ago."<br />
<br />
print "Acquisition of local time..."<br />
dateS=todaymerge() #Initializes dateS<br />
print "today is ",dateS<br />
print "Connecting to remote ftp server..."<br />
f=connect2pdb() #Connect anonymously to ftp.rcsb.org<br />
<br />
print "Acquisition of latest added remote directories..."<br />
directoriesL=findlastdir(dateS,f,days) #Lists recent directories in directoriesL<br />
if len(directoriesL)==0:<br />
print "No updates have been found since",days,"ago. Starting over with 50 days ago."<br />
directoriesL=findlastdir(dateS,f,50)<br />
<br />
print "Acquisition of latest addedremote files..."<br />
updatesnumberI=compilinfile(directoriesL,f) #Concatenates the corresponding added.pdb into donotedit.dat<br />
<br />
print "Parsing of latest entries..."<br />
pdbidsL=listparser() #Recent names now present in the pdbidsL list (one name per element)<br />
<br />
print "Acquisition of the current pdb distribution..."<br />
dictL=currentrelease(f) #Populates dictL with the current entries of the PDB<br />
<br />
print "Parsing of the current pdb distribution into [code,title] tuples..."<br />
extractL=extract(pdbidsL,dictL) #generates the dictionnary of latest releases key:PDBid ; definition:pdbtitle<br />
<br />
print "Disconnection from the remote ftp server..."<br />
f=disconnectpdb(f) #Closes the ftp instance<br />
<br />
print "Extraction of the relevant entries..."<br />
relevdicD=releventries(extractL[0]) #Generates a subset of dictionnary D with criterion being "has keywords contained in keywords.txt in its title"<br />
<br />
print "Cleaning program-generated temporary files..."<br />
clean=diskcleanup() #Cleans the mess generated by the program<br />
<br />
reportL=[]<br />
reportL.append("\n")<br />
reportL.append("###############REPORT########################################\n")<br />
reportL.append("\n")<br />
lendictS="%i" %(len(dictL))<br />
chmilblik = 'The current pdb version (as of '+dateS+") has "+lendictS+" entries.\n"<br />
reportL.append(chmilblik)<br />
line="The most recent directory is : "+directoriesL[0]+".\n"<br />
reportL.append(line)<br />
updatesnumberS="%i" %(updatesnumberI)<br />
entriesnumber="%i" %(len(extractL[0].keys()))<br />
line="The "+updatesnumberS+" last updates ("+entriesnumber+" entries) have been examined.\n"<br />
reportL.append(line)<br />
diclengthS="%i" %(len(relevdicD.keys()))<br />
line=diclengthS+" are relevant to you :\n"<br />
reportL.append(line)<br />
for i in relevdicD.keys():<br />
entry=i+" : "+relevdicD[i]+"\n"<br />
reportL.append(entry)<br />
problemS=""<br />
for i in extractL[1]:<br />
problemS=i+";"+problemS<br />
problemS="["+problemS<br />
problemS=problemS.strip(";")<br />
problemS=problemS+"]"<br />
lineS="The entries "+problemS+" raised problems,"<br />
reportL.append(lineS)<br />
reportL.append("they should be examined manually.")<br />
reportL.append("\n")<br />
reportL.append("###############END OF REPORT#################################\n")<br />
report=open("report.aut","w")<br />
for elem in reportL:<br />
print elem<br />
elem=elem+'\n'<br />
report.writelines(elem)<br />
report.close()<br />
command2='start keywords.txt'<br />
command3='start report.aut'<br />
os.system(command2)<br />
os.system(command3)<br />
<br />
cmd.extend("pdbsurvey",pdbsurvey)<br />
</source><br />
<br />
Thank you for any feedback, ways of improving it,...<br />
<br />
[[Category:Script_Library]]<br />
[[Category:System_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=7662Rotamer Toggle2009-11-27T08:12:03Z<p>Newacct: </p>
<hr />
<div>===DESCRIPTION===<br />
Backbone-Dependent Rotamer library (Dunbrack, Cohen ; see ref) is imported into pymol giving access to this information. There are a number of different ways to use the data, I've only implemented a few as well as added extra functions that seemed useful.<br />
*Rotamer Menu - an added menu into menu.py, which displays the most common rotamers for the given(clicked) residue; you can also set the residue any of the common rotamers as well<br />
*colorRotamers - color rotamers by closest matching rotamer angles from database; i.e. color by how common each rotamer of selection, blue - red (least to most common).<br />
*set_rotamer - routine called by above menu, but can be called manually to set a specific residues side-chain angles<br />
*set_phipsi - set all phi,psi angles of given selection to given angles (useful for creating secondary structures)<br />
*createRotamerPDBs - create pdb for each rotamer of given selection ; filter by rotamer-probability<br />
<br />
===IMAGES===<br />
<gallery><br />
Image:RotamerMenu.png|Rotamer Menu for a GLN residue<br />
Image:GLURotamerComparison5.png|Rotamer Comparison of crystal structure and most common for GLU; just as an example<br />
</gallery><br />
<br />
Print out while selecting most common rotamer from above-left image (GLN residue):<br />
Given GLN:40 PHI,PSI (-171.626373291,-96.0500335693) : bin (-170,-100)<br />
CHIs: [179.18069458007812, 72.539344787597656, -47.217315673828125]<br />
Setting Chi1 to -176.9<br />
Setting Chi2 to 177.4<br />
Setting Chi3 to 0.7<br />
<br />
===SETUP===<br />
run "rotamers.py" and use functions from commandline.<br />
<br />
or<br />
<br />
To setup a rotamer menu inside the residue menu (default windows pymol installation):<br />
*copy rotamers.py to C:/Program Files/DeLano Scientific/PyMol/modules/pymol/rotamers.py<br />
*copy mymenu.py to C:/Program Files/DeLano Scientific/PyMol/modules/pymol/menu.py (WARNING : overwrites default menu.py - use at your own risk)<br />
*copy bbdep02.May.sortlib to C:/Program Files/DeLano Scientific/PyMol/modules/pymol/bbdep02.May.sortlib (or newer version of sorted bbdep)<br />
This is only one possible way to do this, I am sure there are many others. I'm not going to post the bbdep, but there is a link in the References section to Dunbrack's download page (get the "sorted" lib)<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform, Red Hat Linux 9.0 and Fedora Core 4. Will test v0.98 and MacOSX later on.<br />
*The way it's setup now, when you import rotamers , it will automatically read-in the rotamer database; this may not be what you want.<br />
*Post problems in the discussion page, on 'my talk' page or just email me : dwkulp@mail.med.upenn.edu<br />
<br />
TASKS TODO:<br />
*Rotamer Movie, using mset, etc create movie to watch cycle through rotamers<br />
*Code could be organized a bit better; due to time constraints this is good for now..<br />
<br />
TASKS DONE:<br />
*Store crystal structure in rotamer menu, so you can go back to original orientation<br />
<br />
===USAGE===<br />
colorRotamers selection<br />
set_rotamer selection, chi1_angle [,chi2_angle] [,chi3_angle] [,chi4_angle]<br />
set_phipsi selection phi_angle, psi_angle<br />
createRotamerPBDs selection [,ncutoff] [,pcutoff] [,prefix]<br />
<br />
===EXAMPLES===<br />
colorRotamers chain A<br />
set_rotamer resi 40, -60,-40 (only set chi1,chi2 angles)<br />
set_phipsi resi 10-40, -60,-60 (create an alpha-helical-like section)<br />
createRotamerPDBs resi 10-12, ncutoff=3 (create 9 PDBs; each with one of the 3 most probable rotamers for resi 10,11,12)<br />
createRotamerPDBs resi 14, pcutoff=0.4 (create a pdb file for each rotamer of residue 14 with probablity > 0.4)<br />
<br />
===REFERENCES===<br />
Dunbrack and Cohen. Protein Science 1997<br />
<br />
[http://dunbrack.fccc.edu/bbdep/index.php Dunbrack Lab Page (Contains backbone-dependent library)]<br />
<br />
===SCRIPTS (Rotamers.py ; MyMenu.py)===<br />
Rotamers.py <br />
<source lang="python"><br />
##################################################################<br />
# File: Rotamers.py<br />
# Author: Dan Kulp<br />
# Creation Date: 6/8/05<br />
# Contact: dwkulp@mail.med.upenn.edu<br />
#<br />
# Notes:<br />
# Incorporation of Rotamer library<br />
# readRotLib() - fills rotdat; <br />
# indexed by "RES:PHI_BIN:PSI_BIN".<br />
#<br />
# Three main functions:<br />
# 1. colorRotamers - colors according<br />
# to rotamer probablitity<br />
# 2. getBins(sel)<br />
# phi,psi bin for rotamer<br />
# 3. set_rotamer - set a side-chain <br />
# to a specific rotamer <br />
#<br />
# To setup a rotamer menu in the <br />
# right click, under "Residue"<br />
# 1. cp mymenu.py modules/pymol/menu.py<br />
# 2. cp rotamers.py modules/pymol/rotamers.py (update ROTLIB)<br />
#<br />
# Requirements:<br />
# set ROTLIB to path for rotamer library<br />
# Reference: <br />
# Dunbrack and Cohen. Protein Science 1997<br />
####################################################################<br />
<br />
import colorsys,sys<br />
import re<br />
import editing<br />
import os<br />
import cmd<br />
import math<br />
<br />
# Path for library<br />
ROTLIB=os.environ['PYMOL_PATH']+"/modules/pymol/bbdep02.May.sortlib"<br />
<br />
# Place for library in memory..<br />
rotdat = {}<br />
<br />
def readRotLib(): <br />
# Column indexes in rotamer library..<br />
RES = 0<br />
PHI = 1<br />
PSI = 2<br />
PROB = 8<br />
CHI1 = 9<br />
CHI2 = 10<br />
CHI3 = 11<br />
CHI4 = 12<br />
<br />
if os.path.exists(ROTLIB):<br />
print "File exists: "+ROTLIB<br />
input = open(ROTLIB, 'r')<br />
for line in input:<br />
<br />
# Parse by whitespace (I believe format is white space and not fixed-width columns)<br />
dat = re.split("\s+",line)<br />
<br />
# Add to rotamer library in memory : <br />
# key format RES:PHI_BIN:PSI_BIN<br />
# value format PROB, CHI1, CHI2, CHI3, CHI4<br />
try:<br />
rotdat[dat[RES]+":"+dat[PHI]+":"+dat[PSI]].append([ dat[PROB], dat[CHI1], dat[CHI2], dat[CHI3], dat[CHI4] ])<br />
except KeyError:<br />
rotdat[dat[RES]+":"+dat[PHI]+":"+dat[PSI]] = [ [ dat[PROB], dat[CHI1], dat[CHI2], dat[CHI3], dat[CHI4] ] ]<br />
<br />
<br />
else:<br />
print "Couldn't find Rotamer library"<br />
<br />
<br />
# Atoms for each side-chain angle for each residue<br />
CHIS = {}<br />
CHIS["ARG"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","NE" ],<br />
["CG","CD","NE","CZ" ]<br />
]<br />
<br />
CHIS["ASN"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","OD2" ]<br />
]<br />
<br />
CHIS["ASP"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","OD1" ]<br />
]<br />
CHIS["CYS"] = [ ["N","CA","CB","SG" ]<br />
]<br />
CHIS["GLN"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","OE1"]<br />
]<br />
<br />
CHIS["GLU"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","OE1"]<br />
]<br />
<br />
CHIS["HIS"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","ND1"]<br />
]<br />
<br />
CHIS["ILE"] = [ ["N","CA","CB","CG1" ],<br />
["CA","CB","CG1","CD1" ]<br />
]<br />
<br />
CHIS["LEU"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1" ]<br />
]<br />
<br />
CHIS["LYS"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ],<br />
["CB","CG","CD","CE"],<br />
["CG","CD","CE","NZ"]<br />
]<br />
<br />
CHIS["MET"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","SD" ],<br />
["CB","CG","SD","CE"]<br />
]<br />
<br />
CHIS["PHE"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1" ]<br />
]<br />
<br />
CHIS["PRO"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD" ]<br />
]<br />
<br />
CHIS["SER"] = [ ["N","CA","CB","OG" ]<br />
]<br />
<br />
CHIS["THR"] = [ ["N","CA","CB","OG1" ]<br />
]<br />
<br />
CHIS["TRP"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1"]<br />
]<br />
<br />
CHIS["TYR"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1" ]<br />
]<br />
<br />
CHIS["VAL"] = [ ["N","CA","CB","CG1" ]<br />
]<br />
<br />
# Color Rotamer by side-chain angle position<br />
# 'bin' side-chain angles into closest<br />
def colorRotamers(sel):<br />
doRotamers(sel)<br />
<br />
# Utility function, to set phi,psi angles for a given selection<br />
# Note: Cartoon, Ribbon functionality will not display correctly after this<br />
def set_phipsi(sel, phi,psi):<br />
doRotamers(sel,angles=[phi,psi],type="set")<br />
<br />
# Set a rotamer, based on a selection, a restype and chi angles<br />
def set_rotamer(sel, chi1, chi2=0,chi3=0,chi4=0):<br />
at = cmd.get_model("byres ("+sel+")").atom[0]<br />
<br />
list = [chi1,chi2,chi3,chi4]<br />
for i in range(0,len(CHIS[at.resn])):<br />
print "Setting Chi"+str(i+1)+" to "+str(list[i])<br />
editing.set_dihedral(sel + ' and name '+CHIS[at.resn][i][0], <br />
sel + ' and name '+CHIS[at.resn][i][1], <br />
sel + ' and name '+CHIS[at.resn][i][2], <br />
sel + ' and name '+CHIS[at.resn][i][3], str(list[i])) <br />
<br />
# Remove some objects that got created<br />
cmd.delete("pk1")<br />
cmd.delete("pk2")<br />
cmd.delete("pkmol")<br />
<br />
# Get Phi,Psi bins for given selection<br />
# WARNING: assume selection is single residue (will only return first residue bins)<br />
def getBins(sel):<br />
return doRotamers(sel, type="bins")<br />
<br />
# Specific comparison operator for rotamer prob data <br />
def mycmp(first, second):<br />
return cmp( first[1], second[1])<br />
<br />
# Color Ramp...<br />
def rot_color(vals): <br />
nbins = 10<br />
vals.sort(mycmp)<br />
# print "End sort: "+str(len(vals))+" : "+str(nbins)<br />
<br />
<br />
# Coloring scheme...<br />
i = 0<br />
j = 0<br />
rgb = [0.0,0.0,0.0]<br />
sel_str = ""<br />
while i < len(vals):<br />
if int(len(vals)/nbins) == 0 or i % int(len(vals)/nbins) == 0:<br />
hsv = (colorsys.TWO_THIRD - colorsys.TWO_THIRD * float(j) / (nbins-1), 1.0, 1.0)<br />
<br />
#convert to rgb and append to color list<br />
rgb = colorsys.hsv_to_rgb(hsv[0],hsv[1],hsv[2])<br />
if j < nbins-1:<br />
j += 1 <br />
<br />
cmd.set_color("RotProbColor"+str(i), rgb)<br />
cmd.color("RotProbColor"+str(i), str(vals[i][0]))<br />
i += 1<br />
<br />
<br />
# Main function <br />
def doRotamers(sel,angles=[], type="color"): <br />
<br />
# Read in Rotamer library if not already done<br />
if len(rotdat) == 0:<br />
readRotLib()<br />
<br />
# Set up some variables..<br />
residues = ['dummy'] # Keep track of residues already done<br />
probs = [] # probability of each residue conformation<br />
phi = 0 # phi,psi angles of current residue<br />
psi = 0<br />
<br />
# Get atoms from selection<br />
atoms = cmd.get_model("byres ("+sel+")")<br />
<br />
# Loop through atoms in selection <br />
for at in atoms.atom:<br />
try:<br />
# Don't process Glycines or Alanines<br />
if not (at.resn == 'GLY' or at.resn == 'ALA'):<br />
if not at.chain+":"+at.resn+":"+at.resi in residues:<br />
residues.append(at.chain+":"+at.resn+":"+at.resi)<br />
<br />
# Check for a null chain id (some PDBs contain this) <br />
unit_select = ""<br />
if not at.chain == "":<br />
unit_select = "chain "+str(at.chain)+" and "<br />
<br />
# Define selections for residue i-1, i and i+1 <br />
residue_def = unit_select+'resi '+str(at.resi)<br />
residue_def_prev = unit_select+'resi '+str(int(at.resi)-1)<br />
residue_def_next = unit_select+'resi '+str(int(at.resi)+1)<br />
<br />
# Compute phi/psi angle<br />
<br />
phi = cmd.get_dihedral(residue_def_prev+' and name C',residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C',residue_def_next+' and name N')<br />
if type == "set":<br />
print "Changing "+at.resn+str(at.resi)+" from "+str(phi)+","+str(psi)+" to "+str(angles[0])+","+str(angles[1])<br />
cmd.set_dihedral(residue_def_prev+' and name C',residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name N',residue_def+' and name CA',residue_def+' and name C',residue_def_next+' and name N', angles[1])<br />
continue<br />
<br />
# Find correct 10x10 degree bin <br />
phi_digit = abs(int(phi)) - abs(int(phi/10)*10)<br />
psi_digit = abs(int(psi)) - abs(int(psi/10)*10)<br />
<br />
# Remember sign of phi,psi angles<br />
phi_sign = 1<br />
if phi < 0: phi_sign = -1<br />
<br />
psi_sign = 1<br />
if psi < 0: psi_sign = -1<br />
<br />
# Compute phi,psi bins<br />
phi_bin = int(math.floor(abs(phi/10))*10*phi_sign)<br />
if phi_digit >= 5: phi_bin = int(math.ceil(abs(phi/10))*10*phi_sign)<br />
<br />
psi_bin = int(math.floor(abs(psi/10))*10*psi_sign)<br />
if psi_digit >= 5: psi_bin = int(math.ceil(abs(psi/10))*10*psi_sign)<br />
<br />
print "Given "+at.resn+":"+at.resi+" PHI,PSI ("+str(phi)+","+str(psi)+") : bin ("+str(phi_bin)+","+str(psi_bin)+")"<br />
<br />
<br />
# Get current chi angle measurements<br />
chi = []<br />
for i in range(0,len(CHIS[at.resn])):<br />
chi.append(cmd.get_dihedral(residue_def + ' and name '+CHIS[at.resn][i][0], <br />
residue_def + ' and name '+CHIS[at.resn][i][1], <br />
residue_def + ' and name '+CHIS[at.resn][i][2], <br />
residue_def + ' and name '+CHIS[at.resn][i][3])) <br />
print "CHIs: "+str(chi)<br />
if type == 'bins':<br />
return [at.resn, phi_bin,psi_bin]<br />
<br />
# Compute probabilities for given chi angles<br />
prob = 0<br />
prob_box = 22 <br />
for item in range(0,len(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)])):<br />
print "Rotamer from db: "+str(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item])<br />
if chi[0]:<br />
if chi[0] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][1]) - (prob_box/2) and \<br />
chi[0] <= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][1]) + (prob_box/2):<br />
if len(chi) == 1:<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
if chi[1] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][2]) - (prob_box/2) and \<br />
float(chi[1] <= rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][2]) + (prob_box/2):<br />
if len(chi) == 2:<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
if chi[2] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][3]) - (prob_box/2) and \<br />
float(chi[2] <= rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][3]) + (prob_box/2):<br />
if len(chi) == 3:<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
if chi[3] >= float(rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][4]) - (prob_box/2) and \<br />
float(chi[3] <= rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][4]) + (prob_box/2):<br />
prob = rotdat[at.resn+":"+str(phi_bin)+":"+str(psi_bin)][item][0]<br />
break<br />
<br />
<br />
print "PROB OF ROTAMER: "+str(prob)<br />
print "---------------------------"<br />
probs.append([residue_def, prob])<br />
<br />
except:<br />
# probs.append([residue_def, -1])<br />
print "Exception found"<br />
continue<br />
<br />
# Color according to rotamer probability<br />
rot_color(probs) <br />
<br />
<br />
<br />
<br />
# Create PDB files containing most probable rotamers<br />
def createRotamerPDBs(sel,ncutoff=10,pcutoff=0,prefix="ROTAMER"):<br />
<br />
# Get atoms from selection<br />
atoms = cmd.get_model("byres ("+sel+")")<br />
<br />
# Set up some variables..<br />
residues = ['dummy'] # Keep track of residues already done<br />
<br />
# Loop through atoms in selection <br />
for at in atoms.atom:<br />
if at.resn == 'GLY' or at.resn == 'ALA' or "%s:%s:%s" % (at.chain,at.resn,at.resi) in residues:<br />
continue<br />
<br />
# Add to residue list (keep track of which ones we've done)<br />
residues.append("%s:%s:%s" % (at.chain,at.resn,at.resi))<br />
<br />
# Check for a null chain id (some PDBs contain this) <br />
unit_select = ""<br />
if not at.chain == "":<br />
unit_select = "chain "+str(at.chain)+" and "<br />
<br />
# Define selections for residue <br />
residue_def = unit_select+'resi '+str(at.resi)<br />
<br />
# Get bin (phi,psi) definitions for this residue<br />
bin = doRotamers(residue_def, type='bins')<br />
<br />
# Store crystal angle<br />
crystal_angles = [0.0,0.0,0.0,0.0]<br />
for angle in range(0,3):<br />
try:<br />
crystal_angles[angle] = bin[3][angle]<br />
except IndexError:<br />
break<br />
<br />
# Retreive list of rotamers for this phi,psi bin + residue type<br />
match_rotamers = rotdat["%s:%s:%s" % (bin[0],str(bin[1]),str(bin[2]))]<br />
<br />
count = 0<br />
for item in range(0, len(match_rotamers)):<br />
<br />
# Store probablity<br />
prob = match_rotamers[item][0]<br />
<br />
# Check cutoffs<br />
if float(prob) <= float(pcutoff):<br />
continue<br />
<br />
if float(count) >= float(ncutoff):<br />
break<br />
<br />
# Increment count<br />
count += 1<br />
<br />
# Output to screen ...<br />
print "Residue %s%s, rotamer %i, prob %s" % (str(at.resn),str(at.resi),int(item),str(prob))<br />
<br />
# Set to new rotamer<br />
set_rotamer(residue_def,match_rotamers[item][1],match_rotamers[item][2],match_rotamers[item][3],match_rotamers[item][4]) <br />
<br />
# Store in PDB file<br />
cmd.save("%s_%s%s_%i_%s.pdb" % (prefix,str(at.resn),str(at.resi),int(item),str(prob)))<br />
<br />
# Reset crystal angle<br />
set_rotamer(residue_def,crystal_angles[0],crystal_angles[1],crystal_angles[2],crystal_angles[3])<br />
<br />
# Uncommenting this is nice because it loads rotamer library upon startup<br />
# however, it slows the PyMOL loading process a lot<br />
# instead I've put this call into the menuing code..<br />
# readRotLib()<br />
<br />
cmd.extend('set_phipsi',set_phipsi)<br />
cmd.extend('set_rotamer',set_rotamer)<br />
cmd.extend('colorRotamers',colorRotamers)<br />
cmd.extend('createRotamerPDBs',createRotamerPDBs)<br />
<br />
</source><br />
<br />
MyMenu.py<br />
Since menu.py is copyrighted I can't post my edited version, but you can create it very simply by adding these two peices of code<br />
<br />
1. In the "pick_option(title,s,object=0)" function of menu.py add the following code after the first "result =" statement<br />
<source lang="python"><br />
# Edit dwkulp 6/11/05 , add a rotamer menu to residue menu<br />
if title == 'Residue':<br />
result.extend([[ 1, 'rotamers' , rotamer_menu(s)]])<br />
</source><br />
<br />
2. At the end of the file add this:<br />
<source lang="python"><br />
###############################################<br />
# Dan Kulp<br />
# Added Rotamer list to residue menu..<br />
# rotamer.py must be importable (I placed it in <br />
# the same directory as menu.py)<br />
###############################################<br />
<br />
import rotamers<br />
<br />
<br />
def rotamer_menu(s):<br />
# Check for rotamer library being loaded<br />
if not rotamers.rotdat:<br />
rotamers.readRotLib()<br />
# return [ [2, "Must run rotamers.py first",'']]<br />
<br />
# Check for valid rotamer residue..<br />
res = cmd.get_model("byres ("+s+")").atom[0].resn<br />
if not res in rotamers.CHIS.keys():<br />
return [ [2, "Residue: "+res+" not known sidechain or does not have rotamers", '']]<br />
<br />
# Get PHI,PSI bins for rotamer (also prints out current phi,psi, chi1,chi2,chi3,chi4)<br />
bins = rotamers.doRotamers(s,type='bins')<br />
<br />
# Add a title to the menu<br />
result = [ [2, bins[0]+' Rotamers in bin ('+str(bins[1])+','+str(bins[2])+')','' ], [1, ':::PROB,CHI1,CHI2,CHI3,CHI4:::','']]<br />
<br />
# Grab the entries for this residue and phi,psi bins<br />
match_rotamers = rotamers.rotdat[bins[0]+":"+str(bins[1])+":"+str(bins[2])]<br />
<br />
# Set max number of rotamers to display (probably should be somewhere 'higher up' in the code)<br />
max_rotamers = 10<br />
<br />
<br />
if len(match_rotamers) < max_rotamers:<br />
max_rotamers = len(match_rotamers)<br />
<br />
# Create menu entry for each possible rotamer<br />
for item in range(0,max_rotamers):<br />
result.append( [ 1, str(match_rotamers[item]), 'rotamers.set_rotamer("'+s+'","'\<br />
+str(match_rotamers[item][1])+'","'\<br />
+str(match_rotamers[item][2])+'","'\<br />
+str(match_rotamers[item][3])+'","'\<br />
+str(match_rotamers[item][4])+'")'])<br />
return result<br />
<br />
<br />
</source><br />
<br />
<br />
[[Category:Script_Library|Rotamer Toggle]]<br />
<br />
[[Category:Structural_Biology_Scripts|Rotamer Toggle]]</div>Newaccthttps://pymolwiki.org/index.php?title=Slerpy&diff=7661Slerpy2009-11-27T08:11:37Z<p>Newacct: </p>
<hr />
<div>= Manual for Slerpy.py =<br />
<br />
An extension to pymol that creates a moderately easy to use environment for doing keyframe animation. <br />
<br />
<br />
==General Use==<br />
<br />
At the pymol command line type:<br />
<br />
import slerpy<br />
<br />
This will load the extended commands. All commands in slerpy begin with the letter s. Pymol's tab autocomplete feature will work on the additional commands.<br />
<br />
==Important concepts==<br />
<br />
The main function of slerpy is to record a series of pymol views. A movie can then be created by interpolating between these views. A pymol view consists mostly of the camera orientation (that is, the orientation of the viewers eye with respect to the molecule). It also includes information about the clipping planes.<br />
<br />
It is important to realize that most slerpy commands act on the "current" view. You can navigate among views by using the sn, sp, and sgo commands. If you've changed the view around with the mouse or you just want to know the number of the current view you can get back to the current view with the sc command.<br />
<br />
Pymol views do not contain information about how pymol objects and selections are displayed. If you just want to create a movie which moves around a single representation of a molecule then all you need to do is record the set of views that define the tour of the molecule.<br />
<br />
If, on the other hand, you want to change the representation or change which items are displayed you will need to add actions to some of your views. An action is any set of pymol commands. Actions can be associated with any view in the series recorded by slerpy. The ''sscene'' command inserts a new view and simultaneously creates a pymol scene and the action to display it. The scene will include all of the objects and representations visible at the time the command was issued.<br />
<br />
In order to control the rate of motion between the defined views in a slerpy movie, you can control the number of frames used in each interpolation. When a view is saved in slerpy it is associated by default with a transition of 50 frames to the next view. The number of frames in the transition can be altered with the ''ssetf'' command in slerpy.<br />
<br />
The views and actions stored by slerpy can (and should) be saved to a key file with the ''swrite'' command. They can then be retrieved with the sread command. Note that swrite saves the current pymol state in a .pse file but sread does not read in the .pse file. If you're starting a new pymol session to continue work on an existing movie you should load the pse file before doing an sread.<br />
<br />
==Quick Start Tutorial==<br />
<br />
If you haven't installed slerpy yet see [[#Installation|Installation]]<br />
<br />
;Step 1: You probably want to start off in a nice clean working directory that just has the coordinate files you want to work with.<br />
<br />
;Step 2: Read in your molecule(s) and create the various selections and representations that you want to include in the movie.<br />
<br />
;Step 3: At the pymol prompt, type:<br />
<br />
import slerpy<br />
<br />
;Step 4: Get your molecule in exactly the orientation and representation that you want to use for the beginning of your movie.<br />
<br />
;Step 5: Type:<br />
<br />
sinsert<br />
<br />
;Step 6: Using the mouse, move your molecule to the next orientation that you want to use. When you record the movie, the camera orientation will be interpolated between each consecutive pair of views. This can include changes in rotation, zooming, clipping etc.<br />
<br />
:Loop back to Step 5. Continue this until you've got all your orientations stored.<br />
<br />
:You can check how any set of transitions will look at any time by using the ''sshow'' command (see [[#Command Reference|Command Reference]] for details).<br />
<br />
:You can adjust the rate of any transition using the ''ssetf'' command<br />
<br />
;Step 7A: Add any actions to your views using the saction command. Any number of pymol commands can be strung together separated by semicolons. If, for example, you want to change your protein from a cartoon to a surface and add a ligand when you get to view 5 you would do the following (assuming you've defined the pymol selections prot and lig):<br />
<br />
sgo 5<br />
saction "hide cartoon, prot; show surface, prot; show sticks, lig"<br />
<br />
;Step 7B (Alternative using scenes):<br />
<br />
sgo 5<br />
<br />
:Now use the gui to create the representation you want and then:<br />
<br />
sscene<br />
<br />
;Step 8: Save everything. Save your slerpy views and actions as well as a pse file of your current pymol session:<br />
<br />
swrite mymovie<br />
<br />
This will create mymovie.key, which has all of the views, frame counts, actions etc. and mymovie.pse, the associated pymol session file.<br />
<br />
;Step 9: Record the movie! Type:<br />
<br />
srecord<br />
<br />
:You can then play the movie by typing the standard pymol command ''mplay'' or by clicking the play button in pymol.<br />
<br />
;Step 10: If you save the pymol session again, the pse file will contain the movie which can then be shown immediately after startup without running slerpy.py. Note that pymol will warn you when you load a pse file that contains a movie.<br />
<br />
;Step 11: If you want to, the movie can be exported using the mpng command (see the pymol [http://pymol.sourceforge.net/newman/ref/S1000comref.html#2_105 documentation]). Also, see the useful article [[Making_Movies|Making Movies]].<br />
<br />
==Tips and Tricks==<br />
<br />
===Converting scenes to movies===<br />
<br />
You can just step through the scenes and type sscene for each one. This will create a duplicate slerpy scene for each of the scenes you'd already saved but that's not such a disaster. Be sure to swrite when you're done.<br />
<br />
Note that there is some overhead associated with recalling scenes. To avoid pauses at view transitions, I prefer to actually issue the set of show and hide commands that will generate the scene rather than using the above method.<br />
<br />
===Starting off right===<br />
<br />
It's a bit of a pain, but I like to associate with the first frame of the movie an action list that hides everything and then turns on all the objects that I want to have visible at the beginning. This ensures that when your movie loops back to the beginning it will look the same as it did the first time through. For example:<br />
<br />
sgo 0<br />
saction "hide everything; show lines, prot; show surface, activesite; show sticks, ligand"<br />
<br />
Alternatively, start your slerpy work with an ''sscene''.<br />
<br />
===Live pymol presentations during a talk===<br />
Be sure to run your movie once it's been opened and before your presentation if you're presenting in pymol. This will ensure that any objects that don't appear until the middle of the movie are available in memory and won't need to be rebuilt while your audience waits.<br />
<br />
Of course showing your movie from within pymol allows you to show movies in stereo if you've got a presentation system that allows this. If you pass out stereo glasses first it's guaranteed that everyone will remember your talk...<br />
<br />
===Pausing on a view===<br />
<br />
Just sgo to the view you want to stay on for a while and do an sinsert. This will insert a new view with the same orientation etc as the one you were just on. You can adjust the length of the pause by changing the number of frames for the transistion between these two identical views using the ssetf command.<br />
<br />
===Morphing and multi-state models===<br />
<br />
Morphs and multi-conformation models are represented in pymol as single objects with multiple states. Cycling through the states as an animation is very straightforward in pymol. Slerpy allows you to include this animation over the states of an object as a transition between slerpy views within the context of larger movie. This is done using the ''smorph'' command (see [[#Command Reference|Command Reference]]). ''smorph'' allows you to specify the starting and ending pymol state numbers to use during the transition from the current to the next view. It will often be appropriate to have the movie continue after the morph using the final state of the morphing model, that is, the conformation to which you morphed. Since the default for a typical slerpy view is to show the first state of an object, you'll probably need to have available, in addition to your multi-state model, a single-state object containing the final conformation. You can then hide the multistate object and show the single-state final conformation as an action associated with the final view of your morphing sequence.<br />
<br />
To generate morphs you can use the [http://www.delanoscientific.com/rigimol.html rigimol] program provided by Warren as part of the incentive pymol package for subscribers or use [http://alpha2.bmc.uu.se/usf/mol_morph.html lsqman] from Gerard Kleywegt.<br />
<br />
==Command Reference==<br />
<br />
Note that it is essential to understand that slerpy uses the concept of a current or active view. This is the element in the list to which most commands are applied. It is not necessarily the view that is currently visible on the screen. It is advisable to use the sc command frequently to make sure you really know which view your command is being applied to.<br />
<br />
'''saction ''string'':''' Assoiciates the pymol commands in ''string'' with the current view. ''string'' must be enclosed in quotes and must contain only valid pymol commands separated by semicolons.<br />
<br />
'''sappend''': Add the currently displayed view at the end of the list of views in slerpy<br />
<br />
'''sappendaction ''string'':''' Adds the action(s) in ''string'' to the list of actions associated with the current view<br />
<br />
'''sc''': Go to the slerpy active view<br />
<br />
'''scrossfade ''startobject, endobject'':''' During the transition from the current view to the next view ''startobject'' will fade out and'' endobject'' will fade in. The two objects must be shown as sticks. They must be objects, not merely selections, as of pymol 0.99.<br />
<br />
'''sdelaction''': Deletes the action associated with the current view. Be sure you're sure which view you're on before you use this. This will also delete any actions etc. associated with the view so be careful.<br />
<br />
'''sdelete''': Remove the slerpy active view from the list of views to be interpolated.<br />
<br />
'''sdeletesetting: '''Remove the setting interpolation for the current view.<br />
<br />
'''sdumpactions: '''List all actions by frame.<br />
<br />
'''sgo ''n'':''' Change the slerpy active view to view ''n''.<br />
<br />
'''sinsert''': Add the currently displayed view after the slerpy active view.<br />
<br />
'''sinterpsetting ''setting, selection, startval, endval'' :''' The pymol setting ''setting'' will be interpolated linearly from ''startval'' to ''endval'' during the transition from the current view to the next view. You can only interpolate one setting per transition. This is the hard way to, for example, fade out an object:<br />
<br />
sinterpsetting stick_transparency, lig, 0.0, 1.0<br />
<br />
'''slist''': List all views stored for interpolation. Also lists the number of frames in each transition.<br />
<br />
'''smorph ''startmodel,endmodel'':''' The transition from the current frame to the next frame will consist of one frame per pymol state starting with state ''startmodel'' and ending with state ''endmodel''. Subsequent frames (i.e. from subsequent views) will revert to state 1. The state numbers apply to currently visible objects so you will most likely want to have an object with your starting conformation, an object with your multi-state morphing model, and an object with your final conformation. You would then sgo to the frame where you want the morph to start and add an action to hide the starting conformation object and show the multi-model morphing object, do an smorph 1,30 or whatever the number of states in your morph is, append another frame and give it an action where the multi-state model is hidden and the final conformation is shown.<br />
<br />
'''sn''': Go to the next view<br />
<br />
'''sp''': Go to the previous view.<br />
<br />
'''sread ''filename'':''' Restore all the information written with swrite. Does not read in the pse file (to avoid inadvertantly writing over some new selections, scenes or whatever).<br />
<br />
'''srecord''': Records the movie<br />
<br />
'''sreplace''': Replace the slerpy current view with the currently displayed view.<br />
<br />
'''sscene''': Add a the currently displayed view after the slerpy active view and create a scene to go with it. The current pymol state, including which objects are displayed and how they are shown will be captured.<br />
<br />
'''ssetf''': Set the number of frames to use in the transition from the slerpy active view to the next view<br />
<br />
'''ssetupview ''n'':''' This attempts to make sure that all objects are displayed (or not) as they would be when view ''n'' is arrived at in the movie. It goes through and executes all of the sactions from all preceeding views. For some reason this doesn't always work in complex cases.<br />
<br />
'''sshow ''n,m'':''' This command records and shows a segment of the movie showing the transitions starting with view n and ending with view m. If the arguments m and n are omitted the transition from the current view to the next view will be shown.<br />
<br />
'''swrite ''filename'':''' Writes all the information used by slerpy to a file ''filename''.key. It also writes a pymol session file ''filename''.pse containing all of your current objects, selections etc. The format of the .key file is supposed to be human readable and it can be convenient to edit this file rather than using saction over and over. After editing it by hand be sure to do an sread.<br />
<br />
==Why is it called slerpy?==<br />
<br />
slerp is an acronym of sorts for spherical linear interpolation. The transition between two views approximates spherical linear interpolation of the their camera positions using quaternions. See the Wikipedia [http://en.wikipedia.org/wiki/Slerp article] on slerps.<br />
<br />
=Script Files=<br />
<br />
==Installation==<br />
<br />
To install, copy (by pasting into a text editor) the following two python code segments to files named slerpy.py and movs.py, respectively. Place these files in the pymol/modules/pymol/ directory created by the pymol installation.<br />
<br />
If you don't have write priviledges in the pymol installation directories you can just copy these files to the working directory from which pymol will be run. <br />
<br />
==Code==<br />
<br />
===slerpy.py===<br />
<br />
:The command definitions for slerpy<br />
<br />
<source lang="python"><br />
################################################################################<br />
#slerpy.py - Command definition routines for slerpy<br />
#Copyright (C) 2006 Joel Bard<br />
#<br />
#This program is free software; you can redistribute it and/or<br />
#modify it under the terms of the GNU General Public License<br />
#as published by the Free Software Foundation; either version 2<br />
#of the License, or (at your option) any later version.<br />
#<br />
#This program is distributed in the hope that it will be useful,<br />
#but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br />
#GNU General Public License for more details.<br />
#<br />
#You should have received a copy of the GNU General Public License<br />
#along with this program; if not, write to the Free Software<br />
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br />
#################################################################################<br />
<br />
from pymol import cmd<br />
import movs<br />
<br />
def readViews( filename ):<br />
#obsolete<br />
vfile = open( filename, 'r')<br />
views = [] #a list of views each of which is a list of 18 numbers<br />
vstrings = vfile.readlines()<br />
for vstring in vstrings:<br />
vals = vstring.split()<br />
view = [float(v) for v in vals]<br />
views.append( view )<br />
vfile.close()<br />
return views<br />
<br />
def readFrames( filename ):<br />
#obsolete<br />
ffile = open( filename, 'r' )<br />
frames = []<br />
fstrings = ffile.readlines()<br />
for fstring in fstrings:<br />
frames.append( int(fstring) )<br />
ffile.close()<br />
return frames<br />
<br />
def readActions( filename ):<br />
#obsolete<br />
#actions are stored in file where<br />
#for each line, the first 4 chars are the view index<br />
#associated with the action and the rest of the<br />
#line is the pymol command to be executed<br />
#upon reading, a dictionary is returned<br />
#with view indices as keys and actions as values<br />
actions = {}<br />
try:<br />
afile = open( filename, 'r' )<br />
except:<br />
print "No actions for this project"<br />
return actions<br />
astrings = afile.readlines()<br />
for astring in astrings:<br />
try:<br />
aindex = int(astring[:4])<br />
action = astring[4:]<br />
actions[ aindex ] = action[:-1]<br />
except:<br />
print "empty line"<br />
afile.close()<br />
return actions<br />
<br />
def readModels( filename ):<br />
#obsolete<br />
models = {}<br />
try:<br />
mfile = open( filename, 'r' )<br />
except:<br />
print "No models for this project"<br />
return models<br />
mstrings = mfile.readlines()<br />
for mstring in mstrings:<br />
try:<br />
mindex = int(mstring[:4])<br />
model = mstring[4:]<br />
models[ mindex ] = model[:-1]<br />
except:<br />
print "empty line"<br />
mfile.close()<br />
return models<br />
<br />
def readSettings( filename ):<br />
#obsolete<br />
settings = {}<br />
try:<br />
sfile = open( filename, 'r' )<br />
except:<br />
print "No settings for this project"<br />
return settings<br />
sstrings = sfile.readlines()<br />
for sstring in sstrings:<br />
try:<br />
sindex = int(sstring[:4])<br />
scommas = sstring[4:]<br />
settingName,selection,startVal,endVal = scommas.split(',')<br />
setting = [settingName,selection,float(startVal),float(endVal)]<br />
settings[sindex] = setting<br />
except:<br />
print "unable to parse setting"<br />
sfile.close()<br />
return settings<br />
<br />
def readScenes( filename ):<br />
#obsolete<br />
global scene_counter<br />
<br />
scene_counter = 0<br />
scenes = {}<br />
try:<br />
sfile = open( filename, 'r' )<br />
except:<br />
print "No scenes file for this project"<br />
return scenes<br />
sstrings = sfile.readlines()<br />
for sstring in sstrings:<br />
try:<br />
sindex = int(sstring[:4])<br />
scene = sstring[4:]<br />
scenes[ sindex ] = scene[:-1]<br />
scene_counter += 1<br />
#print "reading scene", sstring, sindex, scene<br />
except:<br />
print "empty line"<br />
sfile.close()<br />
return scenes<br />
<br />
def read_all( fileroot ):<br />
#obsolete in favor of readKeyViewFile<br />
global views<br />
global frames<br />
global actions<br />
global cur_view<br />
global cur_index<br />
global scenes<br />
global models<br />
global settings<br />
<br />
views = readViews( fileroot+".txt" )<br />
frames = readFrames( fileroot+".frm")<br />
actions = readActions( fileroot+".act")<br />
scenes = readScenes( fileroot+".scn")<br />
models = readModels( fileroot+".mod")<br />
settings = readSettings( fileroot+".set")<br />
cur_view = views[0]<br />
cur_index = 0<br />
show_cur()<br />
<br />
def print_view( view ):<br />
for i in range(0,6):<br />
for j in range(0,3):<br />
print "%12.6f"% view[ 3*i+j ] ,<br />
print<br />
<br />
def show_next():<br />
global cur_index<br />
global cur_view<br />
global views<br />
if( cur_index == len( views )-1 ):<br />
print "No more views."<br />
return<br />
cur_index += 1<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def show_prev():<br />
global cur_index<br />
global cur_view<br />
global views<br />
if( cur_index == 0 ):<br />
print "No more views."<br />
return<br />
cur_index -= 1<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def show_cur():<br />
global cur_index<br />
global cur_view<br />
global views<br />
cur_view = views[ cur_index ]<br />
cmd.set_view(cur_view)<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ",cur_index<br />
<br />
def go_to_view( arg=0 ):<br />
global cur_index<br />
global cur_view<br />
global views<br />
n = int( arg )<br />
if n < 0 or n > len(views)-1:<br />
print "Index out of range."<br />
return<br />
cur_index = n<br />
cur_view = views[n]<br />
cmd.set_view( cur_view )<br />
print "Matrix: "<br />
print_view( cur_view )<br />
print "Showing view number ", cur_index<br />
<br />
def insert_current():<br />
#insert the current view into the list after the view<br />
#in views[cur_index]<br />
#set frames to default<br />
global cur_index<br />
global cur_view<br />
global views<br />
global frames<br />
global actions<br />
global scenes<br />
global settings<br />
global models<br />
global fades<br />
<br />
cur_index += 1<br />
cur_view = cmd.get_view()<br />
views.insert( cur_index, [cv for cv in cur_view] )<br />
frames.insert( cur_index, 50 )<br />
<br />
#deal with actions dictionary<br />
actions = incKeyAbove( actions, cur_index )<br />
scenes = incKeyAbove( scenes, cur_index )<br />
settings = incKeyAbove( settings, cur_index )<br />
models = incKeyAbove( models, cur_index )<br />
fades = incKeyAbove( fades, cur_index )<br />
<br />
print "New view:"<br />
print_view( cur_view )<br />
print "Inserted view with index", cur_index, "and a 50 frame transition"<br />
<br />
def append_view():<br />
global views<br />
global frames<br />
global cur_index<br />
global cur_view<br />
<br />
cur_index = len(views)<br />
cur_view = cmd.get_view()<br />
views.append( [cv for cv in cur_view] )<br />
frames.append( 50 )<br />
<br />
print "New view: "<br />
print_view( cur_view )<br />
print "Appended view with index", cur_index, "and a 50 frame transition"<br />
print "The current view is", cur_index<br />
<br />
def incKeyAbove( dict, index ):<br />
tempDict = {}<br />
for key, val in dict.iteritems():<br />
if key >= index:<br />
newkey = key + 1<br />
tempDict[newkey] = val<br />
else:<br />
tempDict[key] = val<br />
return tempDict<br />
<br />
def decKeyAbove( dict, index ):<br />
tempDict = {}<br />
for key, val in dict.iteritems():<br />
if key > index:<br />
newkey = key - 1<br />
tempDict[newkey] = val<br />
else:<br />
tempDict[key] = val<br />
return tempDict<br />
<br />
def delete_current():<br />
#remove the current view from the list<br />
#show the previous view<br />
global cur_index<br />
global cur_view<br />
global views<br />
global actions<br />
global scenes<br />
global settings<br />
global models<br />
global frames<br />
global fades<br />
<br />
del views[cur_index]<br />
del frames[cur_index]<br />
if actions.has_key( cur_index ):<br />
del actions[cur_index]<br />
if scenes.has_key( cur_index ):<br />
del scenes[cur_index]<br />
if settings.has_key( cur_index ):<br />
del settings[cur_index]<br />
<br />
#deal with dictionaries<br />
actions = decKeyAbove( actions, cur_index )<br />
scenes = decKeyAbove( scenes, cur_index )<br />
settings = decKeyAbove( settings, cur_index )<br />
models = decKeyAbove( models, cur_index ) <br />
fades = decKeyAbove( fades, cur_index )<br />
<br />
print "View number",cur_index,"deleted."<br />
if cur_index > 0:<br />
cur_index -= 1<br />
cur_view = views[cur_index]<br />
cmd.set_view( cur_view )<br />
print "Current view is number",cur_index<br />
<br />
def delete_settings():<br />
global settings<br />
global cur_index<br />
del settings[cur_index]<br />
<br />
def replace_current():<br />
global cur_index<br />
global cur_view<br />
global views<br />
cur_view = cmd.get_view()<br />
views[cur_index] = [cv for cv in cur_view]<br />
<br />
def insert_scene():<br />
global views<br />
global actions<br />
global settings<br />
global frames<br />
global cur_index<br />
global cur_view<br />
global scenes<br />
global scene_counter<br />
global models<br />
global fades<br />
<br />
cur_index += 1<br />
cur_view = cmd.get_view()<br />
views.insert( cur_index, [cv for cv in cur_view] )<br />
frames.insert( cur_index, 50 )<br />
<br />
#deal with dictionaries<br />
actions = incKeyAbove( actions, cur_index )<br />
scenes = incKeyAbove( scenes, cur_index )<br />
settings = incKeyAbove( settings, cur_index )<br />
models = incKeyAbove( models, cur_index )<br />
fades = incKeyAbove( fades, cur_index )<br />
<br />
#this stuff has to be done after the above<br />
#find a free scene name<br />
i = 1<br />
found = 1<br />
while found == 1:<br />
found = 0<br />
for sname in scenes.values():<br />
print "|"+sname+"|"<br />
if sname == "slerpy_"+str(i):<br />
found = 1<br />
break<br />
if found == 1:<br />
i += 1<br />
else:<br />
break<br />
newname = "slerpy_"+str(i)<br />
<br />
scene_counter += 1<br />
cmd.scene( newname, "store" )<br />
scenes[ cur_index ] = newname<br />
actions[ cur_index ] = "scene "+newname<br />
<br />
print "New view:"<br />
print_view( cur_view )<br />
print "Inserted view with index", cur_index, "and a 50 frame transition"<br />
print "Added scene",newname<br />
<br />
def write_views( filename ):<br />
#deprecated in favor of key files<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
<br />
viewfile = open( filename+".txt", 'w')<br />
for view in views:<br />
for v in view:<br />
viewfile.write( str(v) + " " )<br />
viewfile.write('\n')<br />
viewfile.close()<br />
<br />
framefile = open( filename+".frm", 'w' )<br />
for frame in frames:<br />
framefile.write( str( frame )+'\n' )<br />
framefile.close()<br />
<br />
actionfile = open( filename+".act", 'w' )<br />
for key,action in actions.iteritems():<br />
keystring = str( key )<br />
actionfile.write( keystring.rjust(4)+action + '\n' )<br />
actionfile.close()<br />
<br />
scenefile = open( filename+".scn", 'w' )<br />
for key,scene in scenes.iteritems():<br />
keystring = str( key )<br />
scenefile.write( keystring.rjust(4)+scene + '\n' )<br />
scenefile.close()<br />
<br />
modelfile = open( filename+".mod", 'w' )<br />
for key,model in models.iteritems():<br />
keystring = str( key )<br />
modelfile.write( keystring.rjust(4)+model + '\n' )<br />
modelfile.close()<br />
<br />
settingsfile = open( filename+".set", 'w' )<br />
for key,setting in settings.iteritems():<br />
keystring = str( key )<br />
settingName, selection, startVal, endVal = setting<br />
settingsfile.write( "%s%s,%s,%f,%f\n" % (keystring.rjust(4), settingName, selection, startVal, endVal))<br />
settingsfile.close()<br />
cmd.save( filename+".pse" )<br />
<br />
print "Wrote files", filename+".txt,",filename+".frm,",filename+".pse, and",filename+".act"<br />
<br />
def writeKeyViewFile( filename ):<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
<br />
keyviewfile = open( filename + ".key", 'w' )<br />
i=0<br />
for view in views:<br />
keyviewfile.write( "VIEW: %4d " % i )<br />
for v in view:<br />
keyviewfile.write( str(v) + " " )<br />
keyviewfile.write('\n')<br />
keyviewfile.write( "FRAMES: %d\n" % frames[i] )<br />
if actions.has_key( i ):<br />
keyviewfile.write( "ACTIONS: %s\n" % actions[i] )<br />
if scenes.has_key( i ):<br />
keyviewfile.write( "SCENES: %s\n" % scenes[i] )<br />
if models.has_key( i ):<br />
keyviewfile.write( "MODELS: %s\n" % models[i] )<br />
if settings.has_key( i ):<br />
settingName, selection, startVal, endVal = settings[i]<br />
keyviewfile.write( "SETTINGS: %s, %s, %f, %f\n" % (settingName, selection, startVal, endVal))<br />
if fades.has_key( i ):<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
keyviewfile.write( "FADES: %s, %s, %d\n" % (startVisSelection, endVisSelection, sticksOnly)) <br />
i += 1<br />
keyviewfile.write("\n")<br />
keyviewfile.close()<br />
cmd.save( filename + ".pse" )<br />
print "Wrote files " , filename + ".key", filename + ".pse"<br />
<br />
def readKeyViewFile( filename ):<br />
global views<br />
global frames<br />
global scenes<br />
global actions<br />
global settings<br />
global models<br />
global fades<br />
global scene_counter<br />
<br />
views = []<br />
frames = []<br />
actions = {}<br />
scenes = {}<br />
models = {}<br />
settings = {}<br />
fades = {}<br />
scene_counter = 0<br />
<br />
if filename[-4:] == ".key": filename = filename[:-4] <br />
keyviewfile = open( filename + ".key", 'r' )<br />
viewstrings = keyviewfile.readlines()<br />
keyviewfile.close()<br />
viewindex = 0<br />
for line in viewstrings:<br />
if line.startswith("VIEW: "):<br />
viewindex = int( line[6:10] )<br />
vals = line[10:].split()<br />
view = [float(v) for v in vals]<br />
views.append( view )<br />
if line.startswith("FRAMES: "):<br />
frames.append( int( line[8:] ) )<br />
if line.startswith("ACTIONS: "):<br />
actions[ viewindex ] = line[9:-1]<br />
if line.startswith("SCENES: "):<br />
scenes[ viewindex ] = line[8:-1]<br />
scene_counter += 1<br />
if line.startswith("MODELS: "):<br />
models[ viewindex ] = line[8:-1]<br />
if line.startswith("SETTINGS: "):<br />
settingName,selection,startVal,endVal = line[10:-1].split(',')<br />
settings[ viewindex ] = [settingName,selection,float(startVal),float(endVal)]<br />
if line.startswith( "FADES: " ):<br />
startVisSelection, endVisSelection, sticksOnly = line[7:-1].split(',')<br />
fades[ viewindex ] = [startVisSelection, endVisSelection, int(sticksOnly) ]<br />
cur_view = views[0]<br />
cur_index = 0<br />
show_cur()<br />
<br />
def set_frames_current( arg=50 ):<br />
global frames<br />
global cur_index<br />
frames[cur_index] = int(arg)<br />
<br />
def list_frames():<br />
global frames<br />
global views<br />
global actions<br />
global models<br />
global settings<br />
<br />
i=0<br />
f=0<br />
for view in views[:-1]:<br />
if actions.has_key( i ):<br />
a = actions[i]<br />
else:<br />
a = ""<br />
if models.has_key( i ):<br />
m = "States: " + models[i]<br />
else:<br />
m = ""<br />
if settings.has_key( i ):<br />
settingName, selection, startVal, endVal = settings[i]<br />
s = "Settings: %s %s %f %f" % (settingName, selection, startVal, endVal)<br />
else:<br />
s = ""<br />
print "View",i,"to",i+1,"Frames ",f,"to",f+frames[i],a,m,s<br />
f += frames[i]<br />
i += 1<br />
<br />
def add_action_current( cmd ):<br />
global cur_index<br />
global actions<br />
actions[cur_index] = cmd[1:-1] #strip off quotes<br />
<br />
def append_action_current( cmd ):<br />
global cur_index<br />
global actions<br />
actions[cur_index] += ";" + cmd[1:-1]<br />
<br />
def clear_action_current():<br />
global actions<br />
global cur_index<br />
del actions[cur_index]<br />
<br />
def list_actions():<br />
global actions<br />
for i,a in actions.iteritems():<br />
print i,a<br />
<br />
def morph_models( start_model, end_model ):<br />
global cur_index<br />
global frames<br />
global models<br />
models[cur_index] = "%s -%s" % (start_model, end_model)<br />
frames[cur_index] = abs(int(end_model) - int(start_model)) + 1<br />
<br />
def interpolate_settings( setting, selection, startval, endval ):<br />
global cur_index<br />
global settings<br />
settingEntry = [setting, selection, float(startval), float(endval)]<br />
settings[cur_index] = settingEntry <br />
<br />
def crossfade( startVisSelection, endVisSelection, sticksOnly = 1 ):<br />
#cross fade the specified objects, vary stick transparency only if stickOnly=1<br />
global cur_index<br />
global fades<br />
fades[cur_index] = [startVisSelection, endVisSelection, int(sticksOnly) ]<br />
<br />
def setup_view( index ):<br />
for i in range( 0, int(index)+1 ):<br />
if actions.has_key(i):<br />
print "Executing %s from actions %d" % (actions[i],i)<br />
cmd.do( actions[i] )<br />
if settings.has_key(i):<br />
settingName, selection, startVal, endVal = settings[i]<br />
action = "set %s, %f, %s;" % (settingName, endVal, selection)<br />
print "Executing %s from settings %d" % (action,i)<br />
cmd.do( action )<br />
if fades.has_key(i):<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
action = "set stick_transparency, 0, %s; set stick_transparency, 1, %s;" % (endVisSelection, startVisSelection)<br />
print "Executing %s from fades %d" % (action, i)<br />
cmd.do( action )<br />
<br />
def show_transition(start_index=0, end_index=0):<br />
#show the transition from the current view to the next view<br />
global frames<br />
global views<br />
global cur_index<br />
global actions<br />
global models<br />
if( start_index == 0 and end_index == 0 ):<br />
if cur_index >= len(views)-1:<br />
print "Current view is last in sequence."<br />
return<br />
start_index=cur_index<br />
end_index=cur_index+1<br />
else:<br />
start_index = int(start_index)<br />
end_index = int(end_index)<br />
ftot = 0<br />
setcommand = ""<br />
i = start_index<br />
for nframes in frames[start_index:end_index]:<br />
#ftot += nframes<br />
if models.has_key(i):<br />
setcommand += " " + models[i] + " "<br />
else:<br />
setcommand += " 1 x%i" % nframes<br />
i += 1<br />
<br />
# cmd.mset("1 x%i" % ftot)<br />
cmd.mset( setcommand )<br />
start_frame = 1<br />
#first do all actions that happen up to this point to make sure<br />
#things look the way they should<br />
first_action = ""<br />
for i in range( 0, start_index ):<br />
if actions.has_key(i):<br />
first_action += actions[i] + ';'<br />
#print "Executing %s from actions %d" % (actions[i],i)<br />
#cmd.do( actions[i] )<br />
if settings.has_key(i):<br />
settingName, selection, startVal, endVal = settings[i]<br />
action = "set %s, %f, %s;" % (settingName, endVal, selection)<br />
first_action += action<br />
#print "Executing %s from settings %d" % (action,i)<br />
#cmd.do( action )<br />
if fades.has_key(i):<br />
startVisSelection, endVisSelection, sticksOnly = fades[i]<br />
action = "set stick_transparency, 0, %s; set stick_transparency, 1, %s;" % (endVisSelection, startVisSelection)<br />
first_action += action<br />
#print "Executing %s from fades %d" % (action, i)<br />
#cmd.do( action )<br />
for i in range( start_index, end_index ):<br />
if settings.has_key(i):<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame, settings[i] )<br />
elif fades.has_key(i):<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame, fades[i] )<br />
else:<br />
movs.animate_transition( views[i], views[i+1], frames[i], start_frame )<br />
#add an action<br />
if start_frame == 1:<br />
mdo_cmd = first_action<br />
if actions.has_key(i):<br />
mdo_cmd += actions[i]+";"<br />
#mdo_cmd += "set_view("+str(views[i])+")"<br />
print mdo_cmd<br />
cmd.mdo(start_frame, mdo_cmd)<br />
elif actions.has_key(i):<br />
mdo_cmd = actions[i]+";set_view("+str(views[i])+")"<br />
cmd.mdo(start_frame, mdo_cmd)<br />
#print mdo_cmd<br />
start_frame += frames[i]<br />
cmd.frame(1)<br />
cmd.mplay()<br />
<br />
def make_all():<br />
#make the whole movie<br />
global views<br />
global frames<br />
global models<br />
<br />
#first get total number of frames<br />
ftot = 0<br />
i = 0<br />
setcommand = ""<br />
for nframes in frames[:-1]:<br />
ftot += nframes<br />
if models.has_key(i):<br />
setcommand += " " + models[i] + " "<br />
else:<br />
setcommand += " 1 x%i" % nframes<br />
i += 1<br />
<br />
#initialize movie<br />
#cmd.mset("1 x%i" % ftot)<br />
#cmd.mset("1 x50 1 -30 30 x20")<br />
cmd.mset( setcommand )<br />
<br />
#loop through views<br />
start_view = views[0][:]<br />
i = 0<br />
first_frame = 1<br />
for view in views[1:]:<br />
end_view = view[:]<br />
if settings.has_key(i):<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame, settings[i] )<br />
elif fades.has_key(i):<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame, fades[i] )<br />
else:<br />
movs.animate_transition( start_view, end_view, frames[i], first_frame )<br />
#add an action<br />
if actions.has_key(i):<br />
mdo_cmd = actions[i]#+";set_view ("+str( views[i] )+")"<br />
print mdo_cmd<br />
cmd.mdo(first_frame, mdo_cmd)<br />
first_frame += frames[i]<br />
i += 1<br />
start_view = end_view[:]<br />
cmd.frame(1)<br />
<br />
## views = readViews( "viewfile.txt" )<br />
## frames = readFrames( "viewfile.frm" )<br />
## actions = readActions( "viewfile.act" )<br />
##print "Length ",len(views)<br />
#for v in views:<br />
# print v<br />
#cur_view = views[0]<br />
views = []<br />
frames = []<br />
models = {}<br />
actions = {}<br />
scenes = {}<br />
settings = {}<br />
fades = {}<br />
scene_counter = 0<br />
cur_index = -1<br />
cmd.set( "scene_animation_duration","0" )<br />
#cmd.set_view( cur_view )<br />
<br />
cmd.extend("sn", show_next )<br />
cmd.extend("sp", show_prev )<br />
cmd.extend("sc", show_cur )<br />
cmd.extend("sinsert", insert_current )<br />
cmd.extend("sdelete", delete_current )<br />
cmd.extend("sreplace", replace_current )<br />
cmd.extend("sappend", append_view )<br />
cmd.extend("sscene", insert_scene )<br />
cmd.extend("sgo", go_to_view )<br />
cmd.extend("sreadold", read_all )<br />
cmd.extend("swriteold", write_views )<br />
cmd.extend("slist", list_frames )<br />
cmd.extend("ssetf", set_frames_current )<br />
cmd.extend("sshow", show_transition )<br />
cmd.extend("srecord", make_all )<br />
cmd.extend("saction", add_action_current )<br />
cmd.extend("sdelaction", clear_action_current )<br />
cmd.extend("sdumpactions", list_actions )<br />
cmd.extend("sappendaction", append_action_current )<br />
cmd.extend("smorph", morph_models )<br />
cmd.extend("sinterpsetting", interpolate_settings )<br />
cmd.extend("sdeletesetting", delete_settings )<br />
cmd.extend("scrossfade", crossfade )<br />
cmd.extend("swrite", writeKeyViewFile )<br />
cmd.extend("sread", readKeyViewFile )<br />
cmd.extend("ssetupview", setup_view )<br />
</source><br />
<br />
===movs.py===<br />
<br />
:Math and animation routines for slerpy<br />
<br />
<source lang="python"><br />
##################################################################################<br />
#movs.py - Math and animation routines for slerpy<br />
#Copyright (C) 2006 Joel Bard<br />
#<br />
#This program is free software; you can redistribute it and/or<br />
#modify it under the terms of the GNU General Public License<br />
#as published by the Free Software Foundation; either version 2<br />
#of the License, or (at your option) any later version.<br />
#<br />
#This program is distributed in the hope that it will be useful,<br />
#but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the<br />
#GNU General Public License for more details.<br />
#<br />
#You should have received a copy of the GNU General Public License<br />
#along with this program; if not, write to the Free Software<br />
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br />
#################################################################################<br />
<br />
from pymol import cmd,stored<br />
from math import *<br />
<br />
def rmat2quat( M ):<br />
#M is a list of 9 values being the elements of the rotation matrix in row order<br />
T = M[0] + M[4] + M[8] + 1<br />
print "Trace ",T<br />
if T>0:<br />
S = 0.5 / sqrt(T)<br />
W = 0.25/S<br />
X = (M[7] - M[5])*S<br />
Y = (M[2] - M[6])*S<br />
Z = (M[3] - M[1])*S<br />
else:<br />
if( M[0] > M[4] and M[0] > M[8] ):<br />
S = sqrt( 1.0 + M[0] - M[4] - M[8]) * 2<br />
X = 0.25 * S<br />
Y = (M[1] + M[3])/S<br />
Z = (M[2] + M[6])/S<br />
W = (M[5] - M[7])/S<br />
elif M[4] > M[8]:<br />
S = sqrt( 1.0 + M[4] - M[0] - M[8] ) * 2<br />
X = (M[1] + M[3])/S<br />
Y = 0.25 * S<br />
Z = (M[5] + M[7])/S<br />
W = (M[2] - M[6])/S<br />
else:<br />
S = sqrt( 1.0 + M[8] - M[0] - M[4]) * 2<br />
X = (M[2] + M[6])/S<br />
Y = (M[5] + M[7])/S<br />
Z = 0.25 * S<br />
W = (M[1] - M[3])/S<br />
return [X,Y,Z,W]<br />
<br />
def quat2rmat( Q ):<br />
#Q is a list of 4 values being the quaternion X Y Z W<br />
X=Q[0]<br />
Y=Q[1]<br />
Z=Q[2]<br />
W=Q[3]<br />
xx = X*X<br />
xy = X*Y<br />
xz = X*Z<br />
xw = X*W<br />
yy = Y*Y<br />
yz = Y*Z<br />
yw = Y*W<br />
zz = Z*Z<br />
zw = Z*W<br />
<br />
M= [1.0]*9<br />
M[0] = 1 - 2 * ( yy + zz )<br />
M[1] = 2 * ( xy - zw )<br />
M[2] = 2 * ( xz + yw )<br />
M[3] = 2 * ( xy + zw )<br />
M[4] = 1 - 2 * ( xx + zz )<br />
M[5] = 2 * ( yz - xw )<br />
M[6] = 2 * ( xz - yw )<br />
M[7] = 2 * ( yz + xw )<br />
M[8] = 1 - 2 * ( xx + yy )<br />
return M<br />
<br />
def quatconj( Q ):<br />
return [-Q[0],-Q[1],-Q[2],Q[3]]<br />
<br />
def quatmag( Q ):<br />
s = 0.0<br />
QC = quatconj(Q)<br />
for x in range(0,4):<br />
s += Q[x]*Q[x]<br />
print s<br />
return sqrt(s)<br />
<br />
def quatnorm( Q ):<br />
m = quatmag( Q )<br />
return [q/m for q in Q]<br />
<br />
def quatdotprod( q1, q2 ):<br />
dp = 0<br />
for i in range(0,4):<br />
dp += q1[i]*q2[i]<br />
return dp<br />
<br />
def vectnorm( V ):<br />
mag = 0.0<br />
for x in V:<br />
mag += x*x<br />
mag = sqrt(mag)<br />
return [x/mag for x in V]<br />
<br />
def quat2axisangle( Q ):<br />
#returns list where 0..2 are rot axis and 3 is angle<br />
qn = quatnorm( Q )<br />
cos_a = Q[3]<br />
angle = acos( cos_a ) * 2<br />
sin_a = sqrt( 1.0 - cos_a * cos_a )<br />
if( fabs( sin_a ) < 0.000005 ):<br />
sin_a = 1<br />
ax_an = [ q/sin_a for q in Q[0:3] ]<br />
ax_an.append( angle )<br />
return ax_an<br />
<br />
def axisangle2quat( ax_an ):<br />
#ax_an is a list with axis coordinates followed by rotation angle<br />
axn = vectnorm( ax_an[:3] )<br />
angle = ax_an[3]<br />
sin_a = sin( angle / 2 )<br />
cos_a = cos( angle / 2 )<br />
Q = [ x * sin_a for x in axn ]<br />
Q.append( cos_a )<br />
return Q<br />
<br />
def rmat2axisangle( M ):<br />
q = rmat2quat( M )<br />
return quat2axisangle( q )<br />
<br />
def axisangle2rmat( a ):<br />
q = axisangle2quat( a )<br />
return quat2rmat( q )<br />
<br />
def animate_transition( start_view, end_view, nframes, first_frame, settings = [] ):<br />
#print "Views"<br />
#print start_view,'\n',end_view<br />
<br />
cview = start_view[:]<br />
cmd.set_view( start_view )<br />
<br />
#get initial and final quaternions for interpolation<br />
#print start_view[0:9]<br />
#get quaternions<br />
qstart = rmat2quat( start_view[0:9] )<br />
qend = rmat2quat( end_view[0:9] )<br />
<br />
#test for long way vs. short way<br />
if( quatdotprod( qstart,qend ) < 0 ):<br />
qstart = [-q for q in qstart]<br />
<br />
axan_start = quat2axisangle( qstart )<br />
axan_end = quat2axisangle( qend )<br />
<br />
axan_cur = axan_start[:]<br />
frame_start = first_frame<br />
frame_end = frame_start + nframes<br />
doFade = 0<br />
doSetting = 0<br />
if len( settings ) == 4:<br />
settingName, selection, startVal, endVal = settings<br />
settingStep = (endVal-startVal)/float(nframes)<br />
print "Setting step ", settingStep<br />
doSetting = 1<br />
elif len( settings ) == 3:<br />
startVisSelection, endVisSelection, sticksOnly = settings<br />
settingStep = 1.0/float(nframes)<br />
doFade = 1<br />
for f in range( frame_start , frame_end):<br />
#get rotmat<br />
#using angle axis<br />
<br />
for i in range(0,4):<br />
axan_cur[i] = axan_cur[i] + (axan_end[i]-axan_start[i])/nframes<br />
newmat = axisangle2rmat( axan_cur )<br />
#print cview<br />
for i in range(0,9):<br />
cview[i] = newmat[i]<br />
<br />
mdo_cmd = "set_view (["<br />
for i in range(0,18):<br />
if( i>8 ):<br />
cview[i] = cview[i]+(end_view[i]-start_view[i])/nframes<br />
mdo_cmd += "%12.7f,"% cview[i]<br />
mdo_cmd = mdo_cmd[:-1]+"])"<br />
if doSetting: <br />
val = float(f-frame_start)*settingStep + startVal <br />
print val;<br />
mdo_cmd += "; set %s, %f, %s" % (settingName, val, selection)<br />
print mdo_cmd;<br />
#print "mdo ", mdo_cmd<br />
if doFade:<br />
val = float(f-frame_start)*settingStep<br />
otherVal = 1.0 - val<br />
mdo_cmd += "; set stick_transparency, %f, %s; set stick_transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
if not sticksOnly:<br />
#comment out surface transparency interpolation due to problem with transparent sticks in front of <br />
#transparent surfaces (get black holes)<br />
# mdo_cmd += "; set transparency, %f, %s; set transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
mdo_cmd += "; set cartoon_transparency, %f, %s; set cartoon_transparency, %f, %s" % ( val, startVisSelection, otherVal, endVisSelection )<br />
cmd.mdo(f,mdo_cmd)<br />
<br />
</source><br />
[[Category:Script_Library|Slerpy]]<br />
[[Category:Math_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=SuperSymSource&diff=7660SuperSymSource2009-11-27T08:06:28Z<p>Newacct: </p>
<hr />
<div>This page contains source files for the [[SuperSym]] plugin. For documentation and use instructions, see [[SuperSym]].<br />
<br />
==Source Code==<br />
<br />
File: SuperSymPlugin v1.1.py<br />
<source lang="python"><br />
from Tkinter import *<br />
import tkSimpleDialog<br />
import tkMessageBox<br />
import tkColorChooser<br />
import tkFileDialog<br />
import sys<br />
import re<br />
from pymol import stored, cmd, selector<br />
import math<br />
from cctbx import sgtbx, uctbx<br />
import numpy as N<br />
from numpy.linalg import *<br />
from cctbx import uctbx, sgtbx<br />
from pymol.cgo import *<br />
from pymol.vfont import plain<br />
<br />
<br />
def __init__(self):<br />
#MAIN<br />
self.menuBar.addcascademenu('Plugin','SuperSym')<br />
#DEFAULT SET BUILD<br />
self.menuBar.addmenuitem('SuperSym', 'command', 'Default Symmetry Partner Set',<br />
label = 'Default Symmetry Partner Set', <br />
command = lambda s = self: symDialog(s, 0))<br />
#UNIT CELL BUILD<br />
self.menuBar.addmenuitem('SuperSym', 'command', 'Draw Unit Cell',<br />
label = 'Draw Unit Cell', <br />
command = lambda s = self: cellDialog(s))<br />
#SYM SUBMENU<br />
self.menuBar.addcascademenu('SuperSym', 'Build Symmetry Partners')<br />
<br />
self.menuBar.addmenuitem('Build Symmetry Partners', 'command', 'Cell [0,0,0] (default)', <br />
label = 'Cell [0,0,0] (default)', <br />
command = lambda s = self: symDialog(s, 0))<br />
<br />
self.menuBar.addmenuitem('Build Symmetry Partners', 'command', 'Cell [x,y,z] (custom)',<br />
label = 'Cell [x,y,z] (custom)', <br />
command = lambda s = self: symDialog(s, 1))<br />
<br />
self.menuBar.addmenuitem('Build Symmetry Partners', 'command', '2x2x2 Block',<br />
label = '2x2x2 Block', <br />
command = lambda s = self: symDialog(s, 2))<br />
<br />
self.menuBar.addmenuitem('Build Symmetry Partners', 'command', '3x3x3 Block',<br />
label = '3x3x3 Block', <br />
command = lambda s = self: symDialog(s, 3))<br />
<br />
self.menuBar.addmenuitem('Build Symmetry Partners', 'command', 'By Partner',<br />
label = 'By Partner', <br />
command = lambda s = self: symDialog(s, 4))<br />
#COLOR SUBMENU<br />
self.menuBar.addcascademenu('SuperSym', 'Coloring')<br />
<br />
self.menuBar.addmenuitem('Coloring', 'command', 'Default Rainbow',<br />
label = 'Default Rainbow', <br />
command = lambda s = self: colorDialog(s, 0))<br />
<br />
self.menuBar.addmenuitem('Coloring', 'command', 'Select color for each operation',<br />
label = 'Select color for each operation', <br />
command = lambda s = self: colorDialog(s, 1))<br />
<br />
self.menuBar.addmenuitem('Coloring', 'command', 'Select one color for custom set of operations',<br />
label = 'Select one color for custom set of operations', <br />
command = lambda s = self: colorDialog(s, 2))<br />
#GRAPHICS SUBMENU<br />
self.menuBar.addcascademenu('SuperSym', 'Graphics')<br />
<br />
self.menuBar.addmenuitem('Graphics', 'command', 'Lines',<br />
label = 'Lines', <br />
command = lambda s = self: graphicsDialog(s, 0))<br />
<br />
self.menuBar.addmenuitem('Graphics', 'command', 'Ribbon',<br />
label = 'Ribbon', <br />
command = lambda s = self: graphicsDialog(s, 1))<br />
self.menuBar.addmenuitem('Graphics', 'command', 'Cartoon',<br />
label = 'Cartoon',<br />
command = lambda s = self: graphicsDialog(s, 2))<br />
self.menuBar.addmenuitem('Graphics', 'command', 'Sphere Surface (best for printing)',<br />
label = 'Sphere Surface (best for printing)', <br />
command = lambda s = self: graphicsDialog(s, 3))<br />
<br />
self.menuBar.addmenuitem('Graphics', 'command', 'Surface (high load render)',<br />
label = 'Surface (high load render)', <br />
command = lambda s = self: graphicsDialog(s, 4))<br />
#SYM AXES SUBMENU<br />
self.menuBar.addcascademenu('SuperSym', 'Symmetry Axes')<br />
<br />
self.menuBar.addmenuitem('Symmetry Axes', 'command', 'Build Axes',<br />
label = 'Build Axes', <br />
command = lambda s = self: axesDialog(s))<br />
#ADD OTHER SYMMETRY AXES OPTION HERE<br />
self.menuBar.addmenuitem('SuperSym', 'command', 'Move symmetry partners',<br />
label = 'Move symmetry partners',<br />
command = lambda s = self: cellShiftInfo(s))<br />
self.menuBar.addmenuitem('SuperSym', 'command', 'About',<br />
label = 'About',<br />
command = lambda s = self: aboutInfo(s))<br />
self.menuBar.addmenuitem('SuperSym', 'command', 'Help',<br />
label = 'Help',<br />
command = lambda s = self: helpInfo(s))<br />
cmd.cell_shift = cell_shift<br />
cmd.get_operations = get_operations<br />
cmd.get_matrix = get_orthogonalization_matrix<br />
cmd.symset = symset<br />
cmd.cell_shift_helper = cell_shift_helper<br />
cmd.set_key("ALT-6", cell_shift_proxyX1)<br />
cmd.set_key("ALT-4", cell_shift_proxyX2) <br />
cmd.set_key("ALT-8", cell_shift_proxyY1) <br />
cmd.set_key("ALT-2", cell_shift_proxyY2) <br />
cmd.set_key("ALT-5", cell_shift_proxyZ1) <br />
cmd.set_key("ALT-1", cell_shift_proxyZ2)<br />
<br />
<br />
'''<br />
symDialog: Dialog generator and command issuer for generating symmetry partners<br />
<br />
This function is called by SuperSymMenu when any symmetry partner generating option is<br />
selected. It creates dialog windows and receives user input for symmetry generation parameters.<br />
<br />
@app -- identifies the GUI interface to build dialog boxes onto.<br />
@mode -- determines specific treatment of symmetry building command<br />
'''<br />
def symDialog(app, mode):<br />
prefix = tkSimpleDialog.askstring('Prefix',<br />
'Enter desired prefix for these partners:', parent=app.root)<br />
object = tkSimpleDialog.askstring('Object',<br />
'Enter object to generate partners from:', parent=app.root)<br />
if (mode == 0): #make default symmetry set in cell [0,0,0]<br />
symset(prefix, object)<br />
if (mode == 1): #make symmetry set in custom cell<br />
cell = tkSimpleDialog.askstring('Cell',<br />
'Enter lattice cell coordinates separated by commas (ex:x,y,z):', parent = app.root)<br />
x,y,z = cell.split(',')<br />
x,y,z = int(x),int(y),int(z)<br />
symset(prefix, object, x, y, z)<br />
if mode == 2: #make 2x2x2 block of symmetry sets<br />
for i in range(2):<br />
for j in range(2):<br />
for k in range(2):<br />
symset(prefix, object, i, j, k)<br />
if mode == 3: #make 3x3x3 block of symmetry sets<br />
for i in range(-1,2):<br />
for j in range(-1,2):<br />
for k in range(-1,2):<br />
symset(prefix, object, i, j, k)<br />
if mode == 4: #select individual partners by operation and cell<br />
ops = get_operations(object)<br />
opString = ""<br />
for i in range(len(ops)):<br />
opString = opString + str(i) + " : " + ops[i] + "\n"<br />
opIndeces = tkSimpleDialog.askstring("Symmetry Operations", opString +<br />
"Enter numbers of desired operations separated by commas (ex:0,2,9)", parent = app.root) <br />
opListStrings = opIndeces.split(",")<br />
opList = []<br />
for op in opListStrings:<br />
opList.append(int(op))<br />
cell = tkSimpleDialog.askstring('Cell',<br />
'Enter lattice cell coordinates separated by commas (ex:x,y,z):', parent = app.root)<br />
x,y,z = cell.split(',')<br />
x,y,z = int(x),int(y),int(z)<br />
symset(prefix, object, x,y,z, opList)<br />
<br />
'''<br />
colorDialog: Dialog generator for coloring commands<br />
<br />
This function colors sets of symmetry partners defined by the user in the<br />
dialog which it generates.<br />
<br />
@app -- identifies root menu calling this function<br />
@mode -- determines coloring scheme to execute<br />
'''<br />
def colorDialog(app, mode):<br />
prefix = tkSimpleDialog.askstring('Prefix',<br />
'Enter the prefix of symmetry partners to color', parent = app.root)<br />
if mode == 0: #standard rainbow by symmetry operation<br />
colors = ["red", "orange", "yellow", "green", "blue", "purple",<br />
"salmon", "grey", "pink", "teal", "brown", "br0", "aquamarine", <br />
"deepolive", "dirtyviolet", "slate", "br4", "darksalmon", "br7",<br />
"chocolate", "firebrick", "brightorange"]<br />
for i in range(10):<br />
try: #required because PyMOL inappropriately throws an exception<br />
#when the cmd.color() function colors no objects<br />
cmd.color(colors[i], prefix + "0" + str(i) + "*")<br />
except:<br />
pass #allows us to move on to next symmetry operator<br />
for i in range(10,20):<br />
try: #required because PyMOL inappropriately throws an exception<br />
#when the cmd.color() function colors no objects<br />
cmd.color(colors[i], prefix + str(i) + "*")<br />
except:<br />
pass #allows us to move on to next symmetry operator<br />
if mode == 1: #specify for each symmetry operation<br />
cmd.iterate_state(1, prefix + "*", "stored.tmpObject = model")<br />
ops = get_operations(stored.tmpObject)<br />
opString = ""<br />
for i in range(len(ops)):<br />
opString = opString + str(i) + " : " + ops[i] + "\n"<br />
opIndeces = tkSimpleDialog.askstring("Symmetry Operations", opString +<br />
"Enter numbers of desired operations separated by commas (ex:0,2,9) or all", parent = app.root) <br />
if opIndeces == "all":<br />
opList = []<br />
for i in range(len(ops)):<br />
opList.append(i)<br />
else:<br />
opList = opIndeces.split(",")<br />
opStringList = opString.split("\n")<br />
for i in opList:<br />
try:<br />
if int(i) < 10:<br />
cmd.color("white", prefix + "0" + str(i) + "*")<br />
cmd.center(prefix + "0" + str(i) + "*")<br />
if int(i) > 9:<br />
cmd.color("white", prefix + str(i) + "*")<br />
cmd.center(prefix + str(i) + "*")<br />
<br />
except:<br />
pass<br />
tempColor = tkColorChooser.askcolor(title = "Color for " + opStringList[int(i)] + " (currently white)",<br />
parent = app.root)[0]<br />
rgb = []<br />
for value in tempColor:<br />
value = float(value)<br />
value = value/255<br />
rgb.append(value)<br />
cmd.set_color("tempColor", rgb)<br />
try:<br />
if int(i) < 10:<br />
cmd.color("tempColor", prefix + "0" + str(i) + "*")<br />
if int(i) > 9:<br />
cmd.color("tempColor", prefix + str(i) + "*")<br />
except:<br />
pass<br />
if mode == 2: #monochrome for a set of operations<br />
cmd.iterate_state(1, prefix + "*", "stored.tmpObject = model")<br />
ops = get_operations(stored.tmpObject)<br />
opString = ""<br />
for i in range(len(ops)):<br />
opString = opString + str(i) + " : " + ops[i] + "\n"<br />
opIndeces = tkSimpleDialog.askstring("Symmetry Operations", opString +<br />
"Enter numbers of desired operations separated by commas (ex:0,2,9) or all", parent = app.root) <br />
if opIndeces == 'all':<br />
opList = []<br />
for i in range(len(ops)):<br />
opList.append(i)<br />
else:<br />
opList = opIndeces.split(",")<br />
opStringList = opString.split("\n")<br />
tempColor = tkColorChooser.askcolor(parent = app.root)[0]<br />
rgb = []<br />
for value in tempColor:<br />
value = float(value)<br />
value = value/255<br />
rgb.append(value)<br />
cmd.set_color("tempColor", rgb)<br />
for i in opList:<br />
try:<br />
if int(i) < 10:<br />
cmd.color("tempColor", prefix + "0" + str(i) + "*")<br />
if int(i) > 9:<br />
cmd.color("tempColor", prefix + str(i) + "*")<br />
except:<br />
pass<br />
'''<br />
graphicsDialog: Dialog generator for graphics commands<br />
<br />
This function sets visual representations for sets of symmetry partners.<br />
<br />
@app -- identifies root menu<br />
@mode -- determines type of representation to show<br />
'''<br />
def graphicsDialog(app, mode):<br />
prefix = tkSimpleDialog.askstring('Prefix',<br />
'Enter prefix of symmetry partners to display', parent = app.root)<br />
cmd.hide("everything", prefix + "*")<br />
if mode == 0: # show lines<br />
cmd.show("lines", prefix + "*")<br />
if mode == 1: # show ribbon<br />
cmd.show("ribbon", prefix + "*")<br />
if mode == 2: # show cartoon<br />
cmd.show("cartoon", prefix + "*")<br />
if mode == 3: # sphere surface<br />
objSel = prefix + "*"<br />
findSurfaceResidues(objSel, 3.5, "surface")<br />
cmd.set("sphere_scale", 1.8)<br />
cmd.show("spheres", "surface")<br />
if mode == 4: # regular surface<br />
cmd.show("surface", prefix + "*")<br />
<br />
'''<br />
cellDialog: dialog proxy for draw_cell<br />
<br />
This function generates a unit cell representation<br />
FUTURE IMPLEMENTATIONS: select which lattice coordinates to generate unit cell for<br />
<br />
@app -- identifies root menu<br />
'''<br />
def cellDialog(app):<br />
object = tkSimpleDialog.askstring('Object',<br />
'Enter object to generate cell for:', parent = app.root)<br />
if tkMessageBox.askyesno('3D Printing', 'Going to print this model?', parent = app.root):<br />
draw_cell(object, 3.0)<br />
else:<br />
draw_cell(object)<br />
<br />
'''<br />
axesDialog: dialog proxy for draw_symops_cctbx<br />
<br />
This function generates one set of symmetry axes for a given object<br />
FUTURE IMPLEMENTATIONS: select individual axes to generate, attach to model for 3D printing,<br />
generate axes for multiple unit cells<br />
<br />
@app -- identifies root menu<br />
'''<br />
def axesDialog(app):<br />
object = tkSimpleDialog.askstring('Object',<br />
'Enter object to generate symmetry axes for:', parent = app.root)<br />
if tkMessageBox.askyesno('3D Printing', 'Going to print this model?', parent = app.root):<br />
draw_symops(object, 2.0)<br />
else:<br />
draw_symops(object)<br />
<br />
'''<br />
cellShiftInfo: displays info for using cell_shift hotkeys<br />
<br />
@app -- identifies root menu<br />
'''<br />
def cellShiftInfo(app):<br />
tkMessageBox.showinfo('Cell Shifting',<br />
"To shift a symmetry partner, simply click to select any part of it (select only one partner at a time). \n\n" +<br />
"Next, hold ALT and press the numpad key corresponding to the axis direction you\'d like to move. \n\n" +<br />
"Key assignments:\n" +<br />
"A (x) axis: down--4, up--6 \n" +<br />
"B (y) axis: down--2, up--8 \n" +<br />
"C (z) axis: down--1, up--5", parent = app.root)<br />
tkMessageBox.showwarning('Caution', 'Only attempt to shift symmetry partners created by SuperSym.'+<br />
'Attempting to shift any other object will result in errors.')<br />
<br />
def aboutInfo(app):<br />
tkMessageBox.showinfo('About',<br />
'SuperSym v1.0\nDeveloped by Stuart Ballard (srballard@wisc.edu)\nDepartment of Biochemistry\n'+<br />
'University of Wisconsin-Madison', parent = app.root)<br />
def helpInfo(app):<br />
tkMessageBox.showinfo('Help',<br />
'For documentation see http://pymolwiki.org/index.php/SuperSym', parent = app.root)<br />
<br />
'''<br />
symset: generates up to one full set of symmetry partners for a given object in a given lattice position<br />
<br />
1. Obtain all essential symmetry information from CCTBX. This includes the space group, unit cell parameters,<br />
and fractional coordinates corresponding to symmetry operations.<br />
2. Generate transformation matrices to translate coordinates from orthogonal to fractional, and back.<br />
3. <br />
'''<br />
def symset(prefix = "sym", object = -1, x=0,y=0,z=0, opList = []):<br />
if object == -1:<br />
object = cmd.get_names()[0]<br />
cell = [float(x),float(y),float(z)]<br />
view = cmd.get_view()<br />
cmd.show("lines", object)<br />
sgInfo = cmd.get_symmetry(object)<br />
raw_ops = []<br />
for s in sgtbx.space_group_info(sgInfo[6]).group():<br />
raw_ops.append(str(s))<br />
if (len(opList) == 0):<br />
for i in range(len(raw_ops)):<br />
opList.append(i)<br />
opMatrices = []<br />
vars = ["x","y","z"]<br />
i = 0<br />
j = 0<br />
k = 0<br />
#CREATE 4X4 MATRICES FOR SYMMETRY OPERATORS<br />
for raw_op in raw_ops:<br />
ops = raw_op.split(",")<br />
matrix = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,1]]<br />
for j in range(len(ops)):<br />
for k in range(len(vars)):<br />
index = ops[j].find(vars[k])<br />
if index != -1:<br />
if index == 0:<br />
matrix[k][j] = 1<br />
elif ops[j][index - 1] == "-":<br />
matrix[k][j] = -1<br />
else:<br />
matrix[k][j] = 1<br />
index = ops[j].find("/")<br />
if index != -1:<br />
matrix[3][j] = float(ops[j][index - 1]) / float(ops[j][index + 1])<br />
opMatrices.append(matrix)<br />
i=i+1<br />
a,b,c,alpha,beta,gamma = sgInfo[0:6]<br />
ca = math.cos(math.radians(alpha))<br />
cb = math.cos(math.radians(beta))<br />
cg = math.cos(math.radians(gamma))<br />
sb = math.sin(math.radians(beta))<br />
sg = math.sin(math.radians(gamma))<br />
fracToOrt = N.array([[a, b * cg, c * cb, 0.0], <br />
[0.0, b * sg, c * (ca - cb * cg) / sg, 0.0], <br />
[0.0, 0.0, c * sb * math.sqrt(1.0 - ((cb * cg - ca) / (sb * sg))**2), 0.0],<br />
[0.0,0.0,0.0,1.0]])<br />
fracToOrt = fracToOrt.transpose()<br />
ortToFrac = inv(fracToOrt)<br />
stored.atoms = []<br />
cmd.iterate_state(1,object,"stored.atoms.append([x,y,z,1])")<br />
stored.atoms = N.array(stored.atoms)<br />
fracCoords = N.dot(stored.atoms,ortToFrac)<br />
for i in opList:<br />
try:<br />
op = opMatrices[i]<br />
except:<br />
print "Bad symmetry partner numbers. Try again."<br />
quit()<br />
if i > 9:<br />
copy = prefix + str(i) + "_" + str(x) + "_" + str(y) + "_" + str(z)<br />
else:<br />
copy = prefix + "0" + str(i) + "_" + str(x) + "_" + str(y) + "_" + str(z)<br />
cmd.copy(copy, object)<br />
newCoordsFrac = N.dot(fracCoords, op)<br />
stored.newCoords = N.dot(newCoordsFrac, fracToOrt)<br />
stored.j = 0<br />
cmd.alter_state(1,copy,"x,y,z = stored.newCoords[stored.j][0], stored.newCoords[stored.j][1], stored.newCoords[stored.j][2]; stored.j = stored.j + 1")<br />
xSum=ySum=zSum=0.0<br />
for k in range(len(newCoordsFrac)):<br />
xSum = newCoordsFrac[k][0] + xSum<br />
ySum = newCoordsFrac[k][1] + ySum<br />
zSum = newCoordsFrac[k][2] + zSum<br />
center = N.array([xSum,ySum,zSum])<br />
center = center/len(stored.newCoords)<br />
shift = [-math.floor(center[0]) + cell[0], -math.floor(center[1]) + cell[1], -math.floor(center[2]) + cell[2]]<br />
cell_shift(copy,shift[0],shift[1],shift[2],0)<br />
'''<br />
#COPIES COORDINATES OF EACH ATOM TO CORRESPONDING ONE IN GIVEN SYMMETRY PARTNER<br />
#cmd.alter_state(1, copy, "x,y,z = cmd.sym_partner([x,y,z], stored.tmpOp)")<br />
#MOVES SYMMETRY PARTNER TO PROPER LATTICE COORDINATES AND CORRECTS FOR NATIVE LATTICE POSITION ERROR<br />
#stored.xSum,stored.ySum,stored.zSum = 0.0,0.0,0.0<br />
#atoms = cmd.count_atoms(copy)<br />
#cmd.iterate_state(1, copy, "stored.xSum = stored.xSum + x; stored.ySum = stored.ySum + y; stored.zSum = stored.zSum + z")<br />
#xMean = (stored.xSum / atoms)<br />
#yMean = (stored.ySum / atoms)<br />
#zMean = (stored.zSum / atoms)<br />
#xError, yError, zError = N.dot(N.array([xMean,yMean,zMean]), stored.ortToFrac)<br />
#dX,dY,dZ = -math.floor(xError) + cell[0], -math.floor(yError) + cell[1], -math.floor(zError) + cell[2]<br />
#cell_shift(copy,dX,dY,dZ, 0)<br />
'''<br />
cmd.hide("everything", object)<br />
cmd.set_view(view)<br />
<br />
'''<br />
def sym_partner(coords, op):<br />
fracCoords = N.dot(N.array(coords), stored.ortToFrac)<br />
op = op.replace("x", "(" + str(fracCoords[0]) + ")")<br />
op = op.replace("y", "(" + str(fracCoords[1]) + ")")<br />
op = op.replace("z", "(" + str(fracCoords[2]) + ")")<br />
op = op.split(",")<br />
for i in range(3):<br />
index = op[i].find("/")<br />
if index != -1:<br />
if len(op[i]) == index + 2:<br />
op[i] = op[i][0:index - 1] + str(float(op[i][index - 1]) / float(op[i][index + 1]))<br />
else:<br />
op[i] = op[i][0:index - 1] + str(float(op[i][index - 1]) / float(op[i][index + 1])) + op[i][index + 2:]<br />
op[i] = eval(op[i])<br />
return N.dot(N.array(op), stored.fracToOrt)<br />
'''<br />
<br />
<br />
def cell_shift_proxyX1():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, 1,0,0)<br />
def cell_shift_proxyX2():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, -1,0,0)<br />
def cell_shift_proxyY1():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, 0,1,0)<br />
def cell_shift_proxyY2():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, 0,-1,0)<br />
def cell_shift_proxyZ1():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, 0,0,1)<br />
def cell_shift_proxyZ2():<br />
cmd.iterate_state(1, "sele", "stored.tmpObject = model")<br />
cell_shift(stored.tmpObject, 0,0,-1)<br />
<br />
def cell_shift(object, dX, dY, dZ, rename = 1):<br />
if rename:<br />
oldName = object.split("_")<br />
oldPre = oldName[0]<br />
oldX = int(oldName[1])<br />
oldY = int(oldName[2])<br />
oldZ = int(oldName[3])<br />
newX = "_" + str(int(dX) + oldX)<br />
newY = "_" + str(int(dY) + oldY)<br />
newZ = "_" + str(int(dZ) + oldZ)<br />
newName = oldPre + newX + newY + newZ<br />
#if cmd.get_names().find(newName) != -1:<br />
# print "Symmetry partner already exists in destination position!"<br />
# quit()<br />
cmd.set_name(object, newName)<br />
object = newName<br />
stored.shift = [float(dX),float(dY),float(dZ)]<br />
stored.sgInfo = cmd.get_symmetry(object)<br />
a,b,c,alpha,beta,gamma = stored.sgInfo[0:6]<br />
ca = math.cos(math.radians(alpha))<br />
cb = math.cos(math.radians(beta))<br />
cg = math.cos(math.radians(gamma))<br />
sb = math.sin(math.radians(beta))<br />
sg = math.sin(math.radians(gamma))<br />
stored.fracToOrt = N.array([[a, b * cg, c * cb], <br />
[0.0, b * sg, c * (ca - cb * cg) / sg], <br />
[0.0, 0.0, c * sb * math.sqrt(1.0 - ((cb * cg - ca) / (sb * sg))**2)]])<br />
stored.fracToOrt = stored.fracToOrt.transpose()<br />
stored.ortToFrac = inv(stored.fracToOrt)<br />
cmd.cell_shift_helper = cell_shift_helper<br />
cmd.alter_state(1, object, "x,y,z = cmd.cell_shift_helper([x,y,z],stored.shift)")<br />
<br />
def cell_shift_helper(coords, shift):<br />
fracCoords = N.dot(N.array(coords), stored.ortToFrac)<br />
for i in range(3):<br />
fracCoords[i] = fracCoords[i] + shift[i]<br />
coords = N.dot(N.array(fracCoords), stored.fracToOrt)<br />
return coords[0], coords[1], coords[2]<br />
<br />
def get_operations(object):<br />
raw_ops = []<br />
sgInfo = cmd.get_symmetry(object)<br />
for s in sgtbx.space_group_info(sgInfo[6]).group():<br />
raw_ops.append(str(s))<br />
return raw_ops <br />
<br />
def get_orthogonalization_matrix(object, quiet = 0):<br />
a,b,c,alpha,beta,gamma = cmd.get_symmetry(object)[0:6]<br />
ca = math.cos(math.radians(alpha))<br />
cb = math.cos(math.radians(beta))<br />
cg = math.cos(math.radians(gamma))<br />
sb = math.sin(math.radians(beta))<br />
sg = math.sin(math.radians(gamma))<br />
fracToOrt = N.array([[a, b * cg, c * cb], <br />
[0.0, b * sg, c * (ca - cb * cg) / sg], <br />
[0.0, 0.0, c * sb * math.sqrt(1.0 - ((cb * cg - ca) / (sb * sg))**2)]])<br />
if not quiet:<br />
print fracToOrt<br />
print inv(fracToOrt)<br />
return fracToOrt<br />
<br />
# -*- coding: utf-8 -*-<br />
def findSurfaceResidues(objSel="(all)", cutoff=2.5, selName = 0):<br />
"""<br />
findSurfaceResidues<br />
finds those residues on the surface of a protein<br />
that have at least 'cutoff' exposed A**2 surface area.<br />
<br />
PARAMS<br />
objSel (string)<br />
the object or selection in which to find<br />
exposed residues<br />
DEFAULT: (all)<br />
<br />
cutoff (float)<br />
your cutoff of what is exposed or not. <br />
DEFAULT: 2.5 Ang**2<br />
<br />
asSel (boolean)<br />
make a selection out of the residues found<br />
<br />
RETURNS<br />
(list: (chain, resv ) )<br />
A Python list of residue numbers corresponding<br />
to those residues w/more exposure than the cutoff.<br />
<br />
"""<br />
tmpObj="__tmp"<br />
cmd.create( tmpObj, objSel + " and polymer");<br />
cmd.set("dot_solvent");<br />
cmd.get_area(selection=tmpObj, load_b=1)<br />
<br />
# threshold on what one considers an "exposed" atom (in A**2):<br />
cmd.remove( tmpObj + " and b < " + str(cutoff) )<br />
<br />
stored.tmp_dict = {}<br />
cmd.iterate(tmpObj, "stored.tmp_dict[(chain,resv)]=1")<br />
exposed = stored.tmp_dict.keys()<br />
exposed.sort()<br />
<br />
cmd.select(selName, objSel + " in " + tmpObj )<br />
cmd.delete(tmpObj)<br />
<br />
return exposed<br />
<br />
#CELL DRAWING<br />
<br />
def set_to_zero(a):<br />
if abs(a) < 1e-10:<br />
a=0<br />
return a<br />
<br />
def draw_cell(obj,radius=1.0,mode=0):<br />
"""<br />
From pymol issue the "run draw_cell.py" command to load the script,<br />
then issue the "draw_cell(object,<optional radius>)" command <br />
to actually run it and create the cgo object showing the unit cell<br />
border for the space group specified by molecular object 'object'.<br />
<br />
e.g. load 1avv.pdb<br />
run draw_cell.py<br />
draw_cell 1avv 0.5 (or draw_cell('1avv',.5))<br />
<br />
see also help(draw_cell_param) to draw the cell border for <br />
user-defined cell dimensions (i.e. not loaded from a pdb file)<br />
<br />
See also "help(draw_cell_param) to draw the cell border by<br />
specifying the unit cell parameters directly (i.e. not loaded from<br />
a pdb file).<br />
"""<br />
radius=float(radius)<br />
cell_info=cmd.get_symmetry(obj)<br />
draw_cell_param(cell_info[0:6],radius,mode)<br />
<br />
def draw_cell_param(cell_param_list,radius=1.0,mode=0):<br />
"""<br />
If you wish to draw the unit cell border for any cell without the<br />
need to load a pdb file, then do this:<br />
<br />
e.g. run draw_cell.py<br />
draw_cell_param((45.2,45.2,70.8,90.,90.,120.),0.5)<br />
<br />
to generate the cell border for this trigonal space group "p 31 2 1"<br />
with a radius of 0.5A. Labels for the origin, and A, B and C axes<br />
will appear as well. The perimeter of the cell is colored with the<br />
RGB components corresponding to the A,B,C components.<br />
"""<br />
<br />
U=uctbx.unit_cell((cell_param_list))<br />
<br />
vert_000 = map(set_to_zero,U.orthogonalize((0.,0.,0)))<br />
vert_100 = map(set_to_zero,U.orthogonalize((1.,0.,0)))<br />
vert_010 = map(set_to_zero,U.orthogonalize((0.,1.,0)))<br />
vert_001 = map(set_to_zero,U.orthogonalize((0.,0.,1)))<br />
vert_110 = map(set_to_zero,U.orthogonalize((1.,1.,0)))<br />
vert_011 = map(set_to_zero,U.orthogonalize((0.,1.,1)))<br />
vert_101 = map(set_to_zero,U.orthogonalize((1.,0.,1)))<br />
vert_111 = map(set_to_zero,U.orthogonalize((1.,1.,1)))<br />
<br />
# vert_000 = map(None,U.orthogonalize((0.,0.,0)))<br />
# vert_100 = map(None,U.orthogonalize((1.,0.,0)))<br />
# vert_010 = map(None,U.orthogonalize((0.,1.,0)))<br />
# vert_001 = map(None,U.orthogonalize((0.,0.,1)))<br />
# vert_110 = map(None,U.orthogonalize((1.,1.,0)))<br />
# vert_011 = map(None,U.orthogonalize((0.,1.,1)))<br />
# vert_101 = map(None,U.orthogonalize((1.,0.,1)))<br />
# vert_111 = map(None,U.orthogonalize((1.,1.,1)))<br />
<br />
#print vert_000<br />
<br />
#CYLINDER = ['CYLINDER']<br />
#radius = [0.2]<br />
#print radius<br />
cell = [] <br />
cell.append(CYLINDER)<br />
cell = cell + vert_000 + vert_100 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_000 + vert_010 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_000 + vert_001 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_100 + vert_110 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_100 + vert_101 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_010 + vert_110 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_010 + vert_011 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_001 + vert_101 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_001 + vert_011 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_110 + vert_111 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_101 + vert_111 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(CYLINDER)<br />
cell = cell + vert_011 + vert_111 + [radius] + [1,1,1] + [1,1,1]<br />
cell.append(SPHERE)<br />
cell = cell + vert_000 + [radius]<br />
cell.append(SPHERE)<br />
cell = cell + vert_001 + [radius]<br />
cell.append(SPHERE)<br />
cell = cell + vert_010 + [radius]<br />
cell.append(SPHERE)<br />
cell = cell + vert_011 + [radius]<br />
cell.append(SPHERE)<br />
cell = cell + vert_100 + [radius]<br />
cell.append(SPHERE)<br />
cell = cell + vert_101 + [radius]<br />
cell.append(SPHERE)<br />
cell = cell + vert_110 + [radius]<br />
cell.append(SPHERE)<br />
cell = cell + vert_111 + [radius]<br />
<br />
cmd.load_cgo(cell,"cell")<br />
#return cell<br />
<br />
if mode == 1:<br />
text = [COLOR, 1.0, 0.0, 1.0,]<br />
<br />
#wire_text(text,plain,[-5.,-5.,-1],'Origin',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])<br />
#wire_text(text,plain,map(None,U.orthogonalize((1.05,0.0,0.0))),'A',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])<br />
#wire_text(text,plain,map(None,U.orthogonalize((0.0,1.05,0.0))),'B',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])<br />
#wire_text(text,plain,map(None,U.orthogonalize((0.0,0.0,1.05))),'C',[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]])<br />
<br />
cyl_text(text,plain,[-5.,-5.,-1],'Origin',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[1.0,0.0,1.0])<br />
cyl_text(text,plain,map(None,U.orthogonalize((1.05,0.0,0.0))),'A',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[1.0,0.0,0.0])<br />
cyl_text(text,plain,map(None,U.orthogonalize((0.0,1.05,0.0))),'B',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[0.0,1.0,0.0])<br />
cyl_text(text,plain,map(None,U.orthogonalize((0.0,0.0,1.05))),'C',0.20,axes=[[3.0,0.0,0.0],[0.0,3.0,0.0],[0.0,0.0,3.0]],color=[0.0,0.0,1.0])<br />
<br />
cmd.load_cgo(text,'text')<br />
<br />
<br />
#AXES DRAWING<br />
#! /usr/bin/env python<br />
# Copyright (c) 2004 Robert L. Campbell<br />
<br />
#import string, math<br />
<br />
def set_to_zero(a):<br />
if abs(a) < 1e-10:<br />
a=0<br />
return a<br />
<br />
def draw_symbol(start,end,symb,color,radius=0.2):<br />
degtorad = N.pi/180.<br />
costhirty = N.cos(30.0*degtorad)<br />
sinthirty = N.sin(30.0*degtorad)<br />
symb_obj = []<br />
<br />
if symb == '2' or symb == '2^1':<br />
pass<br />
<br />
elif symb == '3' or symb == '3^1' or symb == '3^2':<br />
symb_obj = [ BEGIN, TRIANGLES, COLOR ] + color<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([start]) + N.array([radius, 0, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([start]) + N.array([-radius*sinthirty, radius*costhirty, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([start]) + N.array([-radius*sinthirty, -radius*costhirty, 0]))[0].tolist()<br />
<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([end]) + N.array([radius, 0, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([end]) + N.array([-radius*sinthirty, radius*costhirty, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([end]) + N.array([-radius*sinthirty, -radius*costhirty, 0]))[0].tolist()<br />
symb_obj.append(END)<br />
<br />
elif symb == '4' or symb == '4^1' or symb == '4^2' or symb == '4^3':<br />
symb_obj = [ BEGIN, TRIANGLES, COLOR ] + color<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([start]) + N.array([radius, radius, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([start]) + N.array([-radius, radius, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([start]) + N.array([-radius, -radius, 0]))[0].tolist()<br />
<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([start]) + N.array([radius, radius, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([start]) + N.array([radius, -radius, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([start]) + N.array([-radius, -radius, 0]))[0].tolist()<br />
<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([end]) + N.array([radius, radius, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([end]) + N.array([-radius, radius, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([end]) + N.array([-radius, -radius, 0]))[0].tolist()<br />
<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([end]) + N.array([radius, radius, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([end]) + N.array([radius, -radius, 0]))[0].tolist()<br />
symb_obj.append(VERTEX)<br />
symb_obj = symb_obj + (N.array([end]) + N.array([-radius, -radius, 0]))[0].tolist()<br />
symb_obj.append(END)<br />
<br />
elif symb == '6' or symb == '6^1' or symb == '6^2' or symb == '6^3' or symb == '6^4' or symb == '6^5':<br />
# hexagons still need to be created :)<br />
pass<br />
<br />
return symb_obj<br />
<br />
def draw_symops(obj,radius=0.2,extension=0):<br />
"""<br />
From pymol issue the "run draw_symops_cctbx.py" command to load the script,<br />
then issue the "draw_symops(object,<optional radius>,<optional extension>)" command <br />
to actually run it and create the cgo object.<br />
<br />
e.g. load 1avv.pdb<br />
run draw_symops_cctbx.py<br />
draw_symops 1avv, 0.5, .2 <br />
or draw_symops('1avv',.5,.2)<br />
or draw_symops 1avv, radius=.5, extension=.2<br />
<br />
The different axis types appear as different objects on the PyMOL menu so they can be turned<br />
on and off individually.<br />
<br />
See also help(draw_symops_param) to draw operators by specifying the space group <br />
and cell dimensions directly (i.e. not loaded from a pdb file)<br />
<br />
The 'extension' parameter is a fractional increase in the length of each symmetry<br />
operator axis drawn. i.e. a value of 0 is the default and a value of .2 increases<br />
the length by 20% at each end<br />
"""<br />
radius=float(radius)<br />
extension=float(extension)<br />
cell_info=cmd.get_symmetry(obj)<br />
draw_symops_param(cell_info[0:6],cell_info[6],radius,extension)<br />
<br />
def draw_symops_param(cell_param_list,sg,radius=0.2,extension=0):<br />
"""<br />
If you wish to draw the symmetry operators for any cell without the need to load a<br />
pdb file, then do this:<br />
<br />
e.g. run draw_symops_cctbx.py<br />
draw_symops_param((45.2,45.2,70.8,90.,90.,120.),'p3121',0.5,0.1)<br />
<br />
to generate the symmetry operators for this trigonal space group "p 31 2 1"<br />
of radius .5 with 10% added as an extension at each end.<br />
"""<br />
radius=float(radius)<br />
extension=float(extension)<br />
<br />
U=uctbx.unit_cell((cell_param_list))<br />
<br />
#rotation axes<br />
# "2" "yellow",<br />
# "3" "orange",<br />
# "4" "mauve",<br />
# "6" "purple",<br />
<br />
#screw axes (all sub_1 axes are green)<br />
# "21" "green",<br />
# "31" "green",<br />
# "32" "lime",<br />
# "41" "green",<br />
# "42" "cyan",<br />
# "43" "iceblue",<br />
# "61" "green",<br />
# "62" "silver",<br />
# "63" "cyan",<br />
# "64" "iceblue",<br />
# "65" "blue",<br />
<br />
color = {<br />
"2" : [1.0, 1.0, 0.0],<br />
"3" : [1.0, 0.5, 0.0],<br />
"4" : [1.0, 0.5, 1.0],<br />
"6" : [1.0, 0.0, 1.0],<br />
"2^1" : [0.0, 1.0, 0.0],<br />
"3^1" : [0.0, 1.0, 0.0],<br />
"3^2" : [0.5, 1.0, 0.5],<br />
"4^1" : [0.0, 1.0, 0.0],<br />
"4^2" : [0.0, 1.0, 1.0],<br />
"4^3" : [0.5, 0.5, 1.0],<br />
"6^1" : [0.0, 1.0, 0.0],<br />
"6^2" : [0.8, 0.8, 0.8],<br />
"6^3" : [0.0, 1.0, 1.0],<br />
"6^4" : [0.5, 0.5, 1.0],<br />
"6^5" : [0.0, 0.0, 1.0],<br />
}<br />
<br />
sg = sg.upper()<br />
symop_axes = get_all_axes(sg,extension=extension)<br />
<br />
#CYLINDER = 'CYLINDER'<br />
ax_obj = {}<br />
#vert_obj = []<br />
<br />
#debug_out = open('debug.log','w')<br />
<br />
if symop_axes:<br />
for i in range(len(symop_axes)):<br />
#print symop_axes[i]<br />
start = map(set_to_zero,U.orthogonalize(map(None,symop_axes[i]['start'])))<br />
end = map(set_to_zero,U.orthogonalize(map(None,symop_axes[i]['end'])))<br />
###############################################################################<br />
# Tried rounding off start and end values in order to understand why axes go <br />
# missing in the drawing, but seem to be present in the cgo. Doesn't help!<br />
# e.g. for space group 'p23' one of the 3-fold rotations is missing (0,0,0 -> x,-x,x)<br />
# changing one cell axis to something ever so slightly different recovers the axis<br />
# e.g. set cell to be (30.00001,30.,30.,90.,90.,90) and it works!<br />
# start = map(lambda x: round(x,3),U.orthogonalize(symop_axes[i]['start']))<br />
# end = map(lambda x: round(x,3),U.orthogonalize(symop_axes[i]['end']))<br />
###############################################################################<br />
color_ax = color[symop_axes[i]['symb']]<br />
symb_ax = symop_axes[i]['symb']<br />
<br />
#print "axis: ",symb_ax, start, end<br />
if ax_obj.has_key(symb_ax):<br />
ax_obj[symb_ax].append(CYLINDER)<br />
else:<br />
ax_obj[symb_ax] = [CYLINDER]<br />
<br />
ax_obj[symb_ax] = ax_obj[symb_ax] + start + end + [radius]<br />
ax_obj[symb_ax] = ax_obj[symb_ax] + color[symb_ax] + color[symb_ax]<br />
ax_obj[symb_ax] = ax_obj[symb_ax] + draw_symbol(start,end,symb_ax,color[symb_ax],radius*6.)<br />
<br />
# #######################################################################################<br />
# # Debugging output to try to understand why some axes go missing in the drawing.<br />
# # They don't appear to be missing from the cgo object, though!<br />
# for xxx in ax_obj[symb_ax]:<br />
# if xxx == 9.0:<br />
# #print "\n\n",xxx<br />
# xxx = "\n\n" + str(xxx) + " "<br />
# debug_out.write(xxx)<br />
# else:<br />
# #print xxx<br />
# #xxx = "\n" + str(xxx) + " "<br />
# xxx = str(xxx) + " "<br />
# debug_out.write(xxx)<br />
# #print ax_obj[symb_ax]<br />
# debug_out.write("\n\n")<br />
# big_string = str(ax_obj)<br />
# debug_out.write(big_string)<br />
# # End of debugging output<br />
# #######################################################################################<br />
<br />
else:<br />
print "\nNo symmetry axes found for this space group: %s\n" % sg<br />
<br />
for key in ax_obj.keys():<br />
name=sg + "_" + key<br />
cmd.load_cgo(ax_obj[key],name)<br />
#debug_out.write("\n\n" + key + "\n" + str(ax_obj[key]))<br />
#return ax_obj<br />
<br />
#cmd.extend("draw_symops_param",draw_symops_param)<br />
<br />
#! /usr/bin/env python<br />
# List all axes in the unit cell.<br />
<br />
# usage:<br />
# python all_axes.py - show axes for the 230 reference settings.<br />
# python all_axes.py P2 - show axes for (e.g.) space group P2<br />
<br />
# RWGK = Ralf W. Grosse-Kunstleve<br />
# RWGK Some further refinement is required:<br />
# RWGK - List only the axes of highest order (e.g. only 4, not 4 and 2).<br />
# RWGK - List only the axes with the smallest intrinsic component<br />
# RWGK (e.g. list only 3(1), not both 3(1) and 3(2)).<br />
# RWGK See also: comment regarding shift_range below.<br />
<br />
def list_plus(lhs, rhs):<br />
return [l + r for l, r in zip(lhs, rhs)]<br />
<br />
def list_minus(lhs, rhs):<br />
return [l - r for l, r in zip(lhs, rhs)]<br />
<br />
def list_multiplies(lhs, rhs):<br />
return [l * r for l, r in zip(lhs, rhs)]<br />
<br />
def list_divides(lhs, rhs):<br />
return [l / r for l, r in zip(lhs, rhs)]<br />
<br />
def list_modulus(lhs, rhs):<br />
return [l % r for l, r in zip(lhs, rhs)]<br />
<br />
def list_dot_product(lhs, rhs=0):<br />
if (rhs == 0): rhs = lhs<br />
result = 0<br />
for l, r in zip(lhs, rhs): result += l * r<br />
return result<br />
<br />
def str_ev(EV):<br />
return "[%d,%d,%d]" % EV<br />
<br />
###def fract_2_dec(fraction):<br />
### list = fraction.split('/')<br />
### if len(list) == 2 and list[1] != 0:<br />
### decimal = float(list[0])/float(list[1])<br />
### else:<br />
### decimal = float(fraction)<br />
### return decimal<br />
<br />
def rlc_RTMxAnalysis(M):<br />
r_info = sgtbx.rot_mx_info(M.r())<br />
t_info = sgtbx.translation_part_info(M)<br />
t_intrinsic = t_info.intrinsic_part().mod_positive().as_double()<br />
t_shift = t_info.origin_shift().mod_positive().as_double()<br />
<br />
#End = list_plus(Start + map(None,r_info.ev()))<br />
####debug<br />
### trans = 0<br />
### length = 0<br />
####debug<br />
<br />
#if (r_info.type() == 1):<br />
if (r_info.type() < 2):<br />
#(rt, start, end) = ('1',(0,0,0),(0,0,0))<br />
return None<br />
#elif (r_info.type() == -1):<br />
# (rt, start, end) = (str(r_info.type()),t_shift,())<br />
elif (abs(r_info.type()) == 2):<br />
trans = reduce(lambda x,y:x+y,t_intrinsic)<br />
if trans == 0:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
(rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r)))<br />
#(rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r_info.ev())))<br />
else:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
(rt, start, end) = (str(r_info.type())+"^1",t_shift,tuple(list_plus(t_shift,r)))<br />
#(rt, start, end) = (str(r_info.type())+"^1",t_shift,tuple(list_plus(t_shift,r_info.ev())))<br />
elif (r_info.type() == 3):<br />
if (r_info.sense() >= 0) :<br />
# ignore opposite sense of rotation axes since they superimpose<br />
trans = N.sqrt(reduce(lambda x,y:x+y,(map(lambda x,y:(y-x)*(y-x),(0,0,0),t_intrinsic))))<br />
# trans = N.sqrt(t_intrinsic[0]**2 + t_intrinsic[1]**2 + t_intrinsic[2]**2)<br />
if trans == 0:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
# fudge to make sure that PyMOL actually draws the axis (move it slightly off [1,-1,1]) !!!<br />
r[0] = r[0]*1.000001<br />
(rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r)))<br />
#(rt, start, end) = (str(r_info.type()),t_shift, tuple(list_plus(t_shift,r_info.ev())))<br />
else:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
#(rt, start, end) = (str(r_info.type())+ "^" + subscript ,t_shift,tuple(list_plus(t_shift,r)))<br />
(start, end) = (t_shift,tuple(list_plus(t_shift,r)))<br />
length = N.sqrt(reduce(lambda x,y:x+y,(map(lambda x,y:(y-x)*(y-x),start, end))))<br />
<br />
# r_info.sense() for 3^1 and 3^2 seems always to be "1" ???<br />
# if r_info.sense() < 0:<br />
# subscript = str(1-r_info.sense())<br />
# else:<br />
# subscript = str(r_info.sense())<br />
<br />
# use ratio of trans to length to get the correct axis symbol:<br />
# fudged the value to get the right numbers. (using length/2., rather than length/3.)<br />
if trans < length*0.5 :<br />
subscript = '1'<br />
else:<br />
subscript = '2'<br />
<br />
rt = str(r_info.type())+ "^" + subscript <br />
#(rt, start, end) = (str(r_info.type()) + "^" + subscript,t_shift, tuple(list_plus(t_shift,r_info.ev())))<br />
### print "Type, sense, Start, End, length, trans", rt, r_info.sense(), start, end, length, trans<br />
# print "type: %s, sense: %s, trans: %s, length: %s," % (r_info.type(), r_info.sense(), trans, length)<br />
# print "(rt, start, end)", (rt,start,end)<br />
else:<br />
return None<br />
#return (r_info.type(),r_info.ev(), t_intrinsic, t_shift)<br />
elif (r_info.sense() > 0):<br />
# ignore opposite sense of rotation axes since they superimpose<br />
trans = reduce(lambda x,y:x+y,t_intrinsic)<br />
if trans == 0:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
(rt, start, end) = (str(r_info.type()),t_shift,tuple(list_plus(t_shift,r)))<br />
#(rt, start, end) = (str(r_info.type()),t_shift, tuple(list_plus(t_shift,r_info.ev())))<br />
else:<br />
maxr = max([abs(x) for x in r_info.ev()])<br />
r = [float(x)/maxr for x in r_info.ev()]<br />
subscript = str(int(trans*r_info.type()+.5)) # add 0.5 to fix rounding errors<br />
(rt, start, end) = (str(r_info.type())+ "^" + subscript ,t_shift,tuple(list_plus(t_shift,r)))<br />
#(rt, start, end) = (str(r_info.type()) + "^" + subscript,t_shift, tuple(list_plus(t_shift,r_info.ev())))<br />
#return (r_info.type(),r_info.ev(), t_intrinsic, t_shift)<br />
else:<br />
return None<br />
# print "type: %s, sense: %s, trans: %s, length: %s," % (r_info.type(), r_info.sense(), trans, length),<br />
# print "(rt, start, end)", (rt,start,end)<br />
return (rt, start, end)<br />
<br />
def get_all_axes(space_group_symbol=None, space_group_info=None, extension=0):<br />
assert space_group_symbol is None or space_group_info is None<br />
shift_range = 1 # RWGK Works for the 230 reference settings; it is not<br />
# RWGK clear to me (rwgk) what value is needed in general.<br />
if (space_group_symbol is not None):<br />
space_group_info = sgtbx.space_group_info(symbol=space_group_symbol)<br />
#space_group_info.show_summary()<br />
<br />
axes_dict = {}<br />
for smx in space_group_info.group():<br />
r = smx.r()<br />
t = smx.t()<br />
shift = [0,0,0]<br />
for shift[0] in range(-shift_range,shift_range+1):<br />
for shift[1] in range(-shift_range,shift_range+1):<br />
for shift[2] in range(-shift_range,shift_range+1):<br />
ts = t.plus(sgtbx.tr_vec(shift, 1)).new_denominator(t.den())<br />
m = sgtbx.rt_mx(r, ts)<br />
#print m<br />
rtmxanal = rlc_RTMxAnalysis(m)<br />
#print r, t, shift, ts, m<br />
if rtmxanal:<br />
#print rtmxanal<br />
axes_dict[rtmxanal] = 0<br />
axes_list = axes_dict.keys()<br />
axes_list.sort()<br />
<br />
# reject nonenantiomorphic space groups<br />
if len(axes_list) > 0 and not re.compile("[A-z]").search(space_group_symbol[1:]):<br />
try:<br />
sgtbx.space_group_info(space_group_symbol).show_summary(), <br />
#print len(axes_list), space_group_symbol<br />
except:<br />
print space_group, space_group_symbol<br />
print<br />
sys.exit(1)<br />
axes = []<br />
for a in axes_list:<br />
if len(a) == 3 and len(a[1]) == 3 and len(a[2]) == 3:<br />
tmp_dict = {}<br />
print "%4s %7.4f %7.4f %7.4f %7.4f %7.4f %7.4f " % (a[0],a[1][0],a[1][1],a[1][2],a[2][0],a[2][1],a[2][2])<br />
tmp_dict['symb'] = a[0]<br />
start_array = N.asarray(a[1])<br />
end_array = N.asarray(a[2])<br />
start_vec = start_array - (end_array - start_array)*extension<br />
end_vec = end_array + (end_array - start_array)*extension<br />
tmp_dict['start'] = start_vec<br />
tmp_dict['end'] = end_vec<br />
#rlc# tmp_dict['start'] = a[1]<br />
#rlc# tmp_dict['end'] = a[2]<br />
axes.append(tmp_dict)<br />
else:<br />
print a<br />
else:<br />
return None<br />
<br />
return axes<br />
<br />
if (__name__ == "__main__"):<br />
import sys<br />
if (len(sys.argv) == 1):<br />
for i in range(230):<br />
get_all_axes(i + 1)<br />
else:<br />
for symbol in sys.argv[1:]:<br />
get_all_axes(symbol)<br />
</source></div>Newaccthttps://pymolwiki.org/index.php?title=LoadDir&diff=7659LoadDir2009-11-27T08:05:39Z<p>Newacct: </p>
<hr />
<div>== Overview == <br />
Load all files of the suffix '''suff''' from the directory '''dirName''', where '''suff''' and '''dirName''' are function parameters.<br />
<br />
== Install ==<br />
# copy the source below to the a file called "loadDir.pml" somewhere on your computer<br />
# load the file with "run /your/path/toLoadDir/loadDir.pml"<br />
# run loadDir. See examples below.<br />
<br />
== Examples ==<br />
<source lang="python"><br />
# load the script<br />
run ~/loadDir.pml<br />
<br />
# load all SD files from /tmp<br />
loadDir /tmp, sdf<br />
loadDir /tmp, .sdf<br />
loadDir /tmp, *.sdf<br />
# even stupid stuff works; hopefully as one would want.<br />
# load all PDBs from /tmp<br />
loadDir /tmp, foo.woo.pdb<br />
<br />
# load all the PDBs in all the directories under ./binders/ERK<br />
loadDir ./binders/ERK/*, .pdb<br />
<br />
# load the PDBs into groups: now we can load all the files in the tree under<br />
# ./ERK into the group "ERK" and the files from ./SYK into the group "SYK"<br />
loadDir ./binders/ERK/*, .pdb, group=ERKb<br />
loadDir ./binders/SYK/*, .pdb, group=SYKb<br />
</source><br />
<br />
== The Code ==<br />
<source lang="python"><br />
from glob import glob<br />
from os.path import sep, basename<br />
<br />
def loadDir(dirName=".", suff="pdb", group=None):<br />
"""<br />
Loads all files with the suffix suff (the input parameter) from the directory dirName).<br />
<br />
dirName: directory path<br />
suff: file suffix. Should be simply "pdb" or "sdf" or similar. Will accept the<br />
wildcard and dot in case the user doesn't read this. So, "*.pdb", ".pdb",<br />
and "pdb" should work. The suffix can be anything valid that PyMOL knows<br />
how to natively load.<br />
group: groupName to add the files to.<br />
<br />
example:<br />
# load all the PDBs in the current directory<br />
loadDir<br />
<br />
# load all SD files from /tmp<br />
loadDir /tmp, "sdf"<br />
<br />
notes:<br />
make sure you call this script w/o quotes around your parameters:<br />
loadDir ., .pdb<br />
as opposed to<br />
loadDir ".", "*.pdb"<br />
Use the former.<br />
"""<br />
<br />
g = dirName + sep + "*." + suff.split(".")[-1]<br />
<br />
for c in glob( g ):<br />
cmd.load(c)<br />
<br />
if ( group != None ):<br />
cmd.group( group, basename(c).split(".")[0], "add" )<br />
<br />
cmd.extend("loadDir", loadDir)<br />
</source><br />
<br />
[[Category:Script_Library|LoadDir]]<br />
[[Category:System_Scripts]]</div>Newaccthttps://pymolwiki.org/index.php?title=DrawBoundingBox&diff=7658DrawBoundingBox2009-11-27T08:03:07Z<p>Newacct: </p>
<hr />
<div>= Overview =<br />
Draws a bounding box around a given selection.<br />
<br />
<gallery><br />
Image:DrawMinBB.png|Example of a bounding box<br />
Image:bb_with_padding.png|Two bounding boxes, one with 0 padding, the other with 10 Ang padding.<br />
</gallery><br />
<br />
= Example =<br />
<source lang="python"><br />
run ~/drawBoundingBox.py<br />
fetch 1jsd<br />
drawBoundingBox 1jsd, r=0.33, g=0.80<br />
<br />
# example from above w/padding, draw it light blue<br />
drawBoundingBox padding=10, r=0.5, g=0.8, b=1.0<br />
</source><br />
<br />
= Installation =<br />
Just copy the source to your computer. Then run<br />
<source lang="python"><br />
run /path/to/drawBoundingBox.py<br />
</source><br />
<br />
<source lang="python"><br />
# -*- coding: utf-8 -*- <br />
from pymol.cgo import * <br />
from pymol import cmd <br />
from random import randint <br />
<br />
#############################################################################<br />
# <br />
# drawBoundingBox.py -- Draws a box surrounding a selection <br />
#<br />
# <br />
# AUTHOR: Jason Vertrees <br />
# DATE : 2/20/2009 <br />
# NOTES : See comments below. <br />
# <br />
#############################################################################<br />
def drawBoundingBox(selection="(all)", padding=0.0, linewidth=2.0, r=1.0, g=1.0, b=1.0): <br />
""" <br />
DESCRIPTION <br />
Given selection, draw the bounding box around it. <br />
<br />
USAGE:<br />
drawBoundingBox [selection, [padding, [linewidth, [r, [g, b]]]]]<br />
<br />
PARAMETERS:<br />
selection, the selection to enboxen. :-)<br />
defaults to (all)<br />
<br />
padding, defaults to 0<br />
<br />
linewidth, width of box lines<br />
defaults to 2.0<br />
<br />
r, red color component, valid range is [0.0, 1.0]<br />
defaults to 1.0 <br />
<br />
g, green color component, valid range is [0.0, 1.0]<br />
defaults to 1.0 <br />
<br />
b, blue color component, valid range is [0.0, 1.0]<br />
defaults to 1.0 <br />
<br />
RETURNS<br />
string, the name of the CGO box<br />
<br />
NOTES<br />
* This function creates a randomly named CGO box that minimally spans the protein. The<br />
user can specify the width of the lines, the padding and also the color. <br />
""" <br />
<br />
([minX, minY, minZ],[maxX, maxY, maxZ]) = cmd.get_extent(selection)<br />
<br />
print "Box dimensions (%.2f, %.2f, %.2f)" % (maxX-minX, maxY-minY, maxZ-minZ)<br />
<br />
minX = minX - float(padding)<br />
minY = minY - float(padding)<br />
minZ = minZ - float(padding)<br />
maxX = maxX + float(padding)<br />
maxY = maxY + float(padding)<br />
maxZ = maxZ + float(padding)<br />
<br />
if padding != 0:<br />
print "Box dimensions + padding (%.2f, %.2f, %.2f)" % (maxX-minX, maxY-minY, maxZ-minZ)<br />
<br />
boundingBox = [<br />
LINEWIDTH, float(linewidth),<br />
<br />
BEGIN, LINES,<br />
COLOR, float(r), float(g), float(b),<br />
<br />
VERTEX, minX, minY, minZ, #1<br />
VERTEX, minX, minY, maxZ, #2<br />
<br />
VERTEX, minX, maxY, minZ, #3<br />
VERTEX, minX, maxY, maxZ, #4<br />
<br />
VERTEX, maxX, minY, minZ, #5<br />
VERTEX, maxX, minY, maxZ, #6<br />
<br />
VERTEX, maxX, maxY, minZ, #7<br />
VERTEX, maxX, maxY, maxZ, #8<br />
<br />
<br />
VERTEX, minX, minY, minZ, #1<br />
VERTEX, maxX, minY, minZ, #5<br />
<br />
VERTEX, minX, maxY, minZ, #3<br />
VERTEX, maxX, maxY, minZ, #7<br />
<br />
VERTEX, minX, maxY, maxZ, #4<br />
VERTEX, maxX, maxY, maxZ, #8<br />
<br />
VERTEX, minX, minY, maxZ, #2<br />
VERTEX, maxX, minY, maxZ, #6<br />
<br />
<br />
VERTEX, minX, minY, minZ, #1<br />
VERTEX, minX, maxY, minZ, #3<br />
<br />
VERTEX, maxX, minY, minZ, #5<br />
VERTEX, maxX, maxY, minZ, #7<br />
<br />
VERTEX, minX, minY, maxZ, #2<br />
VERTEX, minX, maxY, maxZ, #4<br />
<br />
VERTEX, maxX, minY, maxZ, #6<br />
VERTEX, maxX, maxY, maxZ, #8<br />
<br />
END<br />
]<br />
<br />
boxName = "box_" + str(randint(0,10000))<br />
while boxName in cmd.get_names():<br />
boxName = "box_" + str(randint(0,10000))<br />
<br />
cmd.load_cgo(boundingBox,boxName)<br />
return boxName<br />
<br />
cmd.extend ("drawBoundingBox", drawBoundingBox)<br />
</source><br />
<br />
= See Also =<br />
[[Bounding_Box]]<br />
<br />
<br />
[[Category:Script_Library|DrawMinBoundingBox]]<br />
[[Category:Math_Scripts]]<br />
[[Category:CGO]]</div>Newaccthttps://pymolwiki.org/index.php?title=AutoMultiFit&diff=7657AutoMultiFit2009-11-27T08:01:26Z<p>Newacct: </p>
<hr />
<div>= OVERVIEW =<br />
[[AutoMultiFit]] will fit all given chain(s) in all given state(s) to any other given chain(s) in any other given state(s) for some given selection within a homo-oligomer. So, if you have an MD trajectory or NMR ensemble of a tertramer, for example, over 20 states this program could calculate the RMS values for residues 10-30 in chain A's state 17, against all of chain C. Or all states in all chains against each other.<br />
<br />
See the notes in the code for usage.<br />
<br />
= The Code =<br />
<source lang="python"><br />
#<br />
# autoMultiFit.py -- Given a homo-oligomer in N-states, fit any combination of chains across states<br />
#<br />
# AUTHOR: Jason Vertrees<br />
# DATE : 2009-11-02<br />
#<br />
import pymol<br />
from pymol import cmd<br />
<br />
def autoMultiFit(sel, fromChain="*", fromState="*", toChain="*", toState="*", verbose=None):<br />
"""<br />
FUNCTION<br />
Given a homo-oligomer in N-states (say from MD), fit any<br />
combination of chains/selections across states. See Usage, Examples and Notes.<br />
<br />
USAGE<br />
autoMultiFit sel, [fromChain[, fromState[, toChain[, toState[, verbose ]]]]]<br />
<br />
sel<br />
The selection that must exist in all chains (what you're fitting)<br />
<br />
fromChain<br />
Fit from this chain, leave blank or use '*' for all chains;<br />
<br />
fromState<br />
Fit from this state, leave blank or use '*' for all states;<br />
<br />
toChain<br />
Fit to this chain only, use '*' or leave blank for all chains;<br />
<br />
toState<br />
Fit to this state only, use '*' or leave blank for all states<br />
<br />
verbose<br />
If turned on, this prints the fit for all pairs; this could be VERY slow.<br />
<br />
RETURNS<br />
A hash of hashes of hashes of hashes. :-) Access the results like this:<br />
<br />
fitValues = autoMultiFit( mySelection )<br />
#fitValues[fromChain][fromState][toChain][toState]<br />
# to get the result of the fit from chain A, state 4 to chain C, state 17 type,<br />
fitValues['A']['4']['C']['17']<br />
<br />
EXAMPLES<br />
* Fit ALL chains to each other across ALL STATES for PDB 2kb1<br />
autoMultiFit 2kb1<br />
<br />
* Fit chain A's residue 22-34 against all states<br />
autoMutliFit 2kb1 and i. 22-34, fromChain=A<br />
<br />
* Fit chain A, B and C's residues 8-17, states 10 and 11, against chain D's state 8<br />
myVals = autoMultiFit("2kb1 and i. 8-17", fromChain="a b c", fromState="10 11", toChain="d", toState=8)<br />
myVals['B']['10']['D']['8']<br />
<br />
NOTES<br />
* The return value uses UPPERCASE and STRINGS for ALL hash keys, so if you used chain 'a' it will<br />
be 'A' in the map; if you used 'chainXX' it will be 'CHAINXX' in the map.<br />
* Continuing from the above note, all statese are accessible by their strings, so '17' gets state<br />
17 from the hash, not just the number 17.<br />
* This can be very slow: it's O( nFromChains * nFromStates * nToChains * nToStates )<br />
* fromChain, toChain, fromStates and toStates can all be single values, like "8", they can be a SPACE<br />
separated list of values, like "2 4 5", or they can be "*" which means ALL.<br />
"""<br />
<br />
fromChain = processChain(fromChain,sel)<br />
fromState = processState(fromState, sel)<br />
toChain = processChain(toChain, sel)<br />
toState = processState(toState, sel)<br />
<br />
res = {}<br />
<br />
for frC in fromChain:<br />
res[frC] = {}<br />
for frS in fromState:<br />
res[frC][str(frS)] = {}<br />
cmd.create( "__tmpA", sel + " and c. " + frC, frS, 1 )<br />
for toC in toChain:<br />
res[frC][str(frS)][toC] = {}<br />
for toS in toState:<br />
cmd.create("__tmpB", sel + " and c. " + toC, toS, 1 )<br />
curVal = cmd.pair_fit( "__tmpA", "__tmpB", quiet=1 )<br />
res[frC][str(frS)][toC][str(toS)] = curVal<br />
if verbose!=None:<br />
print "Pair Fitted: from (chain: %s, state: %s) to (chain: %s, states %s) with RMSD %s" % (frC, frS, toC, toS, curVal)<br />
cmd.delete("__tmpB")<br />
cmd.delete("__tmpA")<br />
return res<br />
<br />
def processChain(ch, sel):<br />
"""Turn a string-based space separated list into an array of chains"""<br />
if ch == "*":<br />
# just in case<br />
return map(str.upper, cmd.get_chains(sel))<br />
else:<br />
return map(str.upper, processTextList(ch))<br />
<br />
def processState(st, sel):<br />
"""Tur a string-based space separated list into an array of states"""<br />
if st == "*":<br />
# assumes that if there is a state X, there is a state, X-1<br />
return range(cmd.count_states(sel))<br />
else:<br />
return map(int, processTextList(st))<br />
<br />
def processTextList(t):<br />
""" make a space-separated list into a real Python list, eg.<br />
input: a b c d<br />
output: [ 'a', 'b', 'c', 'd' ]<br />
"""<br />
t = str(t).split()<br />
return t<br />
<br />
<br />
if __name__ == "__main__":<br />
assert processTextList( "a b c d" ) == ['a', 'b', 'c', 'd']<br />
assert processTextList( " 1 45 s s s s j p k") == [ '1', '45', 's', 's', 's', 's', 'j', 'p', 'k' ]<br />
<br />
assert processChain( "a b c dd", "blankSel" ) == ["a", "b", "c", "dd"]<br />
assert processState( "1 2 3 44 5", "blankSel" ) == [ 1, 2, 3, 44, 5 ]<br />
<br />
<br />
cmd.extend( "autoMultiFit", autoMultiFit )<br />
</source><br />
<br />
<br />
<br />
<br />
<br />
<br />
[[Category:Script_Library]]<br />
[[Category:Structural_Biology_Script]]</div>Newaccthttps://pymolwiki.org/index.php?title=Kabsch&diff=7656Kabsch2009-11-27T07:58:18Z<p>Newacct: </p>
<hr />
<div>==Intro==<br />
The Kabsch algorithm uses linear and vector algebra to find the optimal rotation and translation of two sets of points in N-dimensional space as to minimize the RMSD between them. The following program is a Python implementation of the Kabsch algorithm.<br />
<br />
This program when called will align the two selections, optimally, convert the proteins in the selection to ribbons and change the color of the selections to show the matched alignments.<br />
<br />
'''WHAT THIS DOESN'T DO''': This program does NOT provide a pairwise alignment of two structures from scratch. You have to tell it what the equivlanced items are. See [[Cealign]].<br />
<br />
'''NOTE:''' This has '''NOT''' been tested on any other machine than mine, by me. It works on all PyMols 0.97 and newer (haven't tested earlier versions) and I use Python 2.3's Numeric Version 23.3.<br />
<br />
'''NOTE:''' I have added new Kabsch code. The new code uses SVD, and fixed an old bug. For ease of use, try the new code (requires numpy, though).<br />
<br />
==To use==<br />
<br />
# Save this script to Kabsch.py<br />
# Open PyMol<br />
# Load the alignment script: '''run Kabsch.py''' (The command '''optAlign''' is now defined in PyMol.)<br />
# Load your proteins<br />
# Align the proper segments (see below examples)<br />
<br />
To align two equivalent sets of residues do:<br />
<source lang="python"><br />
optAlign SEL1 and n. CA and i. a-b, SEL2 and n. CA and i. c-d<br />
</source><br />
where<br />
* '''SEL1''' is the first protein<br />
* '''a-b''' is the range of residues to align in the first protein<br />
* '''SEL2''' is the second protein<br />
* '''c-d''' is the range of residues to align in the second protein<br />
<br />
===Caveats===<br />
* Ensure that you're equivalencing '''N''' atoms to '''N''' atoms (run [[Count_Atoms]] over your two selections to ensure they are the same length).<br />
* Sometimes PyMol doesn't seem to superimpose them right the first time. Hit the up-arrow and rerun the program if this happens. It always superimposes the correctly the second time. I think it has something to do with the orientation. I'll fix this when I find the error.<br />
* The RMSD is only between the equivlanced atoms. Use PyMol's [[Rms_Cur]] if you want a full RMSD.<br />
* Make sure your atom selections are numbered correctly. Many times PDB files start residue numbers at something other than 0 or 1. To ensure you're aligning the right things, do <source lang="python">set seq_view,1</source> to turn on the sequence viewer and double check your residue numbers. If a protein has residue one numbered as something other than one, say 2064, simply run <source lang="python">alter (SEL), resi=str(int(resi)-2064)</source> and then <source lang="python">sort</source> where '''SEL''' is the name of the protein and 2064 is the offset to adjust by. Your protein will now work as needed. See [[Alter]]. This capability is also provided in a script; See [[zero_residues]].<br><br />
<br />
== Notes ==<br />
<ol><li>Windows users are having problems running the script. Python tells them first off "TypeError: Can't convert rank-0 arrays to Python scalars." The fix to that breaks some code in Numeric -- which I don't maintain.</li><br><br />
<li>However, to make this work, you can change the code in <b>Numeric.py</b> supplied with Pymol, located in the folder "<Pymol Home>\modules\Numeric\" (for example: "C:\Program Files\DeLano Scientific\PyMOL\modules\Numeric").<br><br><br />
Essentially, you need to search for the line: <source lang="python"> if axis2 < 0: axis2 = axis1 + n # (should be around line 250) </source> and replace it with: <source lang="python">if axis2 < 0: axis2 = axis2 + n </source></li></ol><br />
<br />
===Examples===<br />
optAlign 1cll and n. CA and i. 4-20+30-60, 1ggz and n. CA and i. 4-20+30-60<br />
<br />
optAlign 1kao and n. CA and i. 20-50, 1ctq and n. CA and i. 20-50<br />
<br />
<gallery><br />
Image:OptAlign1.png|1cll and 1ggz loaded<br />
Image:OptAlign2.png|1cll and 1ggz aligned to residues 5-50+55-80 shown in red<br />
</gallery><br />
<br />
Kabsch can also align hetero-atoms:<br />
<source lang="python"><br />
load 1cll.pdb<br />
load 1ggz.pdb<br />
optAlign 1cll and e. CA, 1ggz and e. CA<br />
</source><br />
The above aligns the 4 Calciums in each structure.<br />
<br />
==The Code==<br />
<source lang="python"><br />
#!python<br />
<br />
##############################################################################<br />
#<br />
# @SUMMARY: -- QKabsch.py. A python implementation of the optimal superposition<br />
# of two sets of vectors as proposed by Kabsch 1976 & 1978.<br />
#<br />
# @AUTHOR: Jason Vertrees<br />
# @COPYRIGHT: Jason Vertrees (C), 2005-2007<br />
# @LICENSE: Released under GPL:<br />
# This program is free software; you can redistribute it and/or modify<br />
# it under the terms of the GNU General Public License as published by<br />
# the Free Software Foundation; either version 2 of the License, or<br />
# (at your option) any later version.<br />
# This program is distributed in the hope that it will be useful, but WITHOUT<br />
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS<br />
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.<br />
#<br />
# You should have received a copy of the GNU General Public License along with<br />
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin<br />
# Street, Fifth Floor, Boston, MA 02110-1301, USA <br />
#<br />
# DATE : 2007-01-01<br />
# REV : 2<br />
# REQUIREMENTS: numpy<br />
#<br />
#############################################################################<br />
from array import *<br />
<br />
# system stuff<br />
import os<br />
import copy<br />
<br />
# pretty printing<br />
import pprint<br />
<br />
# for importing as a plugin into PyMol<br />
from pymol import cmd<br />
from pymol import stored<br />
from pymol import selector<br />
<br />
# using numpy for linear algebra<br />
import numpy<br />
<br />
def optAlign( sel1, sel2 ):<br />
"""<br />
optAlign performs the Kabsch alignment algorithm upon the alpha-carbons of two selections.<br />
Example: optAlign MOL1 and i. 20-40, MOL2 and i. 102-122<br />
Example 2: optAlign 1GGZ and i. 4-146 and n. CA, 1CLL and i. 4-146 and n. CA<br />
<br />
Two RMSDs are returned. One comes from the Kabsch algorithm and the other from<br />
PyMol based upon your selections.<br />
<br />
By default, this program will optimally align the ALPHA CARBONS of the selections provided.<br />
To turn off this feature remove the lines between the commented "REMOVE ALPHA CARBONS" below.<br />
<br />
@param sel1: First PyMol selection with N-atoms<br />
@param sel2: Second PyMol selection with N-atoms<br />
"""<br />
cmd.reset()<br />
<br />
# make the lists for holding coordinates<br />
# partial lists<br />
stored.sel1 = []<br />
stored.sel2 = []<br />
# full lists<br />
stored.mol1 = []<br />
stored.mol2 = []<br />
<br />
# -- CUT HERE<br />
sel1 = sel1 + " and N. CA"<br />
sel2 = sel2 + " and N. CA"<br />
# -- CUT HERE<br />
<br />
# Get the selected coordinates. We<br />
# align these coords.<br />
cmd.iterate_state(1, selector.process(sel1), "stored.sel1.append([x,y,z])")<br />
cmd.iterate_state(1, selector.process(sel2), "stored.sel2.append([x,y,z])")<br />
<br />
# get molecule name<br />
mol1 = cmd.identify(sel1,1)[0][0]<br />
mol2 = cmd.identify(sel2,1)[0][0]<br />
<br />
# Get all molecule coords. We do this because<br />
# we have to rotate the whole molcule, not just<br />
# the aligned selection<br />
cmd.iterate_state(1, mol1, "stored.mol1.append([x,y,z])")<br />
cmd.iterate_state(1, mol2, "stored.mol2.append([x,y,z])")<br />
<br />
# check for consistency<br />
assert( len(stored.sel1) == len(stored.sel2))<br />
L = len(stored.sel1)<br />
assert( L > 0 )<br />
<br />
# must alway center the two proteins to avoid<br />
# affine transformations. Center the two proteins<br />
# to their selections.<br />
COM1 = numpy.sum(stored.sel1,axis=0) / float(L)<br />
COM2 = numpy.sum(stored.sel2,axis=0) / float(L)<br />
stored.sel1 = stored.sel1 - COM1<br />
stored.sel2 = stored.sel2 - COM2<br />
<br />
# Initial residual, see Kabsch.<br />
E0 = numpy.sum( numpy.sum(stored.sel1 * stored.sel1,axis=0),axis=0) + numpy.sum( numpy.sum(stored.sel2 * stored.sel2,axis=0),axis=0)<br />
<br />
#<br />
# This beautiful step provides the answer. V and Wt are the orthonormal<br />
# bases that when multiplied by each other give us the rotation matrix, U.<br />
# S, (Sigma, from SVD) provides us with the error! Isn't SVD great!<br />
V, S, Wt = numpy.linalg.svd( numpy.dot( numpy.transpose(stored.sel2), stored.sel1))<br />
<br />
# we already have our solution, in the results from SVD.<br />
# we just need to check for reflections and then produce<br />
# the rotation. V and Wt are orthonormal, so their det's<br />
# are +/-1.<br />
reflect = float(str(float(numpy.linalg.det(V) * numpy.linalg.det(Wt))))<br />
<br />
if reflect == -1.0:<br />
S[-1] = -S[-1]<br />
V[:,-1] = -V[:,-1]<br />
<br />
RMSD = E0 - (2.0 * sum(S))<br />
RMSD = numpy.sqrt(abs(RMSD / L))<br />
<br />
#U is simply V*Wt<br />
U = numpy.dot(V, Wt)<br />
<br />
# rotate and translate the molecule<br />
stored.sel2 = numpy.dot((stored.mol2 - COM2), U)<br />
stored.sel2 = stored.sel2.tolist()<br />
# center the molecule<br />
stored.sel1 = stored.mol1 - COM1<br />
stored.sel1 = stored.sel1.tolist()<br />
<br />
# let PyMol know about the changes to the coordinates<br />
cmd.alter_state(1,mol1,"(x,y,z)=stored.sel1.pop(0)")<br />
cmd.alter_state(1,mol2,"(x,y,z)=stored.sel2.pop(0)")<br />
<br />
print "RMSD=%f" % RMSD<br />
<br />
# make the alignment OBVIOUS<br />
cmd.hide('everything')<br />
cmd.show('ribbon', sel1 + ' or ' + sel2)<br />
cmd.color('gray70', mol1 )<br />
cmd.color('paleyellow', mol2 )<br />
cmd.color('red', 'visible')<br />
cmd.show('ribbon', 'not visible')<br />
cmd.center('visible')<br />
cmd.orient()<br />
cmd.zoom('visible')<br />
<br />
cmd.extend("optAlign", optAlign) <br />
<br />
</source><br />
<br />
=== The Old Code ===<br />
<br />
<source lang="python"><br />
#!python<br />
<br />
##############################################################################<br />
#<br />
# @SUMMARY: -- Kabsch.py. A python implementation of the optimal superposition<br />
# of two sets of vectors as proposed by Kabsch 1976 & 1978.<br />
#<br />
# @AUTHOR: Jason Vertrees<br />
# @COPYRIGHT: Jason Vertrees (C), 2005-2007<br />
# @LICENSE: Released under GPL:<br />
# This program is free software; you can redistribute it and/or modify<br />
# it under the terms of the GNU General Public License as published by<br />
# the Free Software Foundation; either version 2 of the License, or<br />
# (at your option) any later version.<br />
# This program is distributed in the hope that it will be useful, but WITHOUT<br />
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS<br />
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.<br />
#<br />
# You should have received a copy of the GNU General Public License along with<br />
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin<br />
# Street, Fifth Floor, Boston, MA 02110-1301, USA <br />
#<br />
# DATE : 2005-04-07<br />
# REV : 2<br />
# NOTES: Updated RMSD, notes, cleaned up the code a little.<br />
#<br />
#############################################################################<br />
# math imports<br />
import math<br />
import Numeric<br />
import LinearAlgebra<br />
import Matrix<br />
<br />
from array import *<br />
<br />
# system stuff<br />
import os<br />
import copy<br />
<br />
# pretty printing<br />
import pprint<br />
<br />
# for importing as a plugin into PyMol<br />
#import tkSimpleDialog<br />
#import tkMessageBox<br />
from pymol import cmd<br />
from pymol import stored<br />
from pymol import selector<br />
<br />
class kabsch:<br />
"""<br />
Kabsch alignment of two set of vectors to produce and optimal alignemnt.<br />
<br />
Steps<br />
===== <br />
1. Calculate the center of mass for each protein. Then, move the protein<br />
to its center of mass. We choose as a convention, to use the origin as <br />
the center of mass of the first set of coordinates. This will allow us to<br />
return one translation vector, instead of two.<br />
<br />
Update: Since any rotation around a point that's not the origin, is in fact<br />
an affine rotation. So, to beat that, we translate both to the center.<br />
<br />
NAME: superpose(c1, c2)<br />
POST: T is now defined.<br />
<br />
2. Calculate the matrix, R, by (eq7, 1976). r_{i,j} = sum_n w_n * y_{ni} * x_{nj},<br />
where y_{ni} is the ith component of the vector y_n.<br />
NAME: calcR<br />
POST: R is now defined<br />
<br />
3. Calculate RtR (R-transpose * R).<br />
NAME: calcRtR<br />
POST: RtR is now defined<br />
<br />
4. Calculate the corresponding eigenpairs for RtR, and sort them accordingly:<br />
m1 >= m2 >= m3; set v3 = v1 x v2 to ensure a RHS<br />
NAME: calcEigenPairs<br />
POST: The eigen pairs are calculated, sorted such that m1 >= m2 >= m3 and<br />
v3 = v1 x v2.<br />
<br />
5. Calculate R*v_k and normalize the first two vectors to obtain b_1, b_2 and set<br />
b_3 = b_1 x b_2. This also takes care of m1 > m2 = 0. <br />
NAME: calcBVectors<br />
POST: b-Vectors are defined and returned<br />
<br />
6. Calculate U=(u_{ij})=(sum n b_{ki} * a_{kj}) to obtain the best rotation. Set<br />
sigma_3 = -1 if b3(Ra3) < 0 else sigma_3 = +1.<br />
NAME: calcU<br />
POST: U is defined<br />
<br />
7. Calculate the RMSD. The residual error is then<br />
The E = E0 - sqrt(m1) - sqrt(m2) - sigma_3(sqrt(m3)).<br />
NAME: calcRMSD<br />
POST: RMSD is computed.<br />
<br />
@note: This should be a static method that takes three parameters<br />
<br />
1. The first protein's coordinates, f. This program will <br />
accept coordinates in the form an array of 3D vectors/lists<br />
<br />
2. The second protein's coordinates, g.<br />
<br />
3. The array of integer pairs representing the pairs to align.<br />
Coordinates should be formatted as as array of 2D vectors/lists.<br />
<br />
<br />
<br />
"""<br />
<br />
def __init__(self):<br />
"""<br />
Constructor. @see kabsch.align.<br />
<br />
"""<br />
<br />
#<br />
# Instance Variables: All three of these will be updated<br />
# every time the user calls ~.align. Just to warn ya'.<br />
# <br />
# U, the rotation matrix<br />
self.U = []<br />
# T, the translation vector<br />
self.T = []<br />
# R, the RMSD<br />
self.R = -1.0<br />
<br />
#self.menuBar.addmenuitem('Plugin', 'command', 'Kabsch Align', label = "Align Selections to Optial RMSD", command = lamda s=self: fetchPDBDialog(s))<br />
<br />
<br />
def align(self, c1, c2, pairs):<br />
"""<br />
Finds the best alignment of c1 and c2's pairs resulting in<br />
the smallest possible RMSD.<br />
<br />
<br />
@note:<br />
- All weights in this first version are set to 1. Kabsch allows,<br />
differential weighting. In the future, I may extend to this option,<br />
and then pairs may become 3D (r1, r2, weight) or I may add another<br />
parameter.<br />
<br />
- Helper functions will soon be provided such that the user may<br />
just use this package alone to compute the rotation.<br />
<br />
@param c1: coordinats of the first vectors, as an array of 3D vectors.<br />
@type c1: Python list<br />
<br />
@param c2: coordinates of the second set of vectors, as an array of 3D vectors.<br />
@type c2: Python list<br />
<br />
@param pairs: the list of pairs as an array of 2D pairs.<br />
@type pairs: Python list of 2D lists.<br />
<br />
@return: U, the rotation matrix that gives the optimal rotation between the two proteins.<br />
<br />
T, the translation vector given to align the two objects centers of mass.<br />
<br />
R, the RMSD of the final rotation.<br />
"""<br />
<br />
#<br />
# First we move the center of mass of one protein, to the<br />
# center of mass of the other. This removes any translation<br />
# between the two.<br />
#<br />
T1, T2, c1, c2 = self.superpose(c1, c2)<br />
# Calculate the initial RMSD<br />
E0 = self.calcE0(c1, c2)<br />
# Calculate R via eq. 7.<br />
R = self.calcR(c1, c2)<br />
# Calculate R(transpose)*R<br />
RtR = self.calcRtR(R)<br />
# Determined the eigenpairs for the matrix RtR.<br />
eValues, eVectors = self.calcEigenPairs(RtR)<br />
# Determine the bVectors as required<br />
bVectors = self.calcBVectors(R, eVectors)<br />
# Calculate the roation matrix<br />
U = self.calcU(eVectors, bVectors)<br />
# Calculate the final RMSD using U.<br />
RMSD = self.calcRMSD(E0, eValues, eVectors, bVectors, R, len(c1))<br />
<br />
return U, T1, T2, RMSD, c1, c2<br />
<br />
<br />
def superpose(self, c1, c2 ):<br />
"""<br />
Calculate the center of mass for each protein. Then, move the protein<br />
to its center of mass. We choose as a convention, to use the origin as <br />
the center of mass of the first set of coordinates. This will allow us to<br />
return one translation vector, instead of two.<br />
(CORRECT)<br />
<br />
@precondition: c1 and c2 are well defined lists of N-dimensional points with length > 0.<br />
@postcondition: T is now defined.<br />
<br />
@param c1: coordinats of the first vectors, as an array of 3D vectors.<br />
@type c1: Python list<br />
<br />
@param c2: coordinates of the second set of vectors, as an array of 3D vectors.<br />
@type c2: Python list<br />
<br />
@return: T the translation vector.<br />
<br />
c2 one list of coordinates that of c2 translated to the COM of c1.<br />
<br />
"""<br />
<br />
# make sure we don't get bad data<br />
if (len(c1) != len(c2)):<br />
print "Two different length selections, with lengths, %d and %d." % (len(c1), len(c2))<br />
print "This algorithm must be used with selections of the same length." <br />
print "In PyMol, type 'count_atoms sel1' where sel1 are your selections to find out their lengths."<br />
print "Example: optAlign MOL1 and i. 20-40, MOL2 and i. 102-122"<br />
print "Example 2: optAlign 1GGZ and i. 4-146 and n. CA, 1CLL and i. 4-146 and n. CA"<br />
<br />
<br />
assert(len(c1) == len(c2) != 0)<br />
<br />
L = len(c1)<br />
<br />
#<br />
# Centers of Mass<br />
#<br />
c1COM = Numeric.zeros((3,1), Numeric.Float64)<br />
c2COM = Numeric.zeros((3,1), Numeric.Float64)<br />
<br />
# calculate the CsOM <br />
for i in range(0, L):<br />
for j in range(0,3):<br />
c1COM[j] = c1COM[j] + c1[i][j]<br />
c2COM[j] = c2COM[j] + c2[i][j]<br />
<br />
T1 = - c1COM / L<br />
T2 = - c2COM / L<br />
<br />
# move everything back to the origin.<br />
for i in range(0, L):<br />
for j in range(0,3):<br />
c1[i][j] = c1[i][j] + T1[j]<br />
c2[i][j] = c2[i][j] + T2[j]<br />
<br />
return T1, T2, c1, c2<br />
<br />
<br />
def calcR( self, c1, c2 ):<br />
"""<br />
Calculate the matrix, R, by (eq7, 1976). M{r_{i,j} = sum_n w_n * y_{ni} * x_{nj}},<br />
where M{y_{ni}} is the ith component of the vector M{y_n}.<br />
(CORRECT)<br />
<br />
@param c1: coordinats of the first vectors, as an array of 3D vectors.<br />
@type c1: Python list<br />
<br />
@param c2: coordinates of the second set of vectors, as an array of 3D vectors.<br />
@type c2: Python list<br />
<br />
@postcondition: R is now defined.<br />
<br />
@return: R<br />
@rtype : 3x3 matrix<br />
<br />
"""<br />
<br />
# Create the 3x3 matrix<br />
R = Numeric.zeros((3,3), Numeric.Float64)<br />
L = len(c1)<br />
<br />
for k in range(0, L):<br />
for i in range(0, 3):<br />
for j in range(0, 3):<br />
R[i][j] = R[i][j] + (c2[k][i] * c1[k][j])<br />
<br />
# return R the 3x3 PSD Matrix.<br />
return R<br />
<br />
<br />
def calcRtR( self, R ):<br />
"""<br />
Calculate RtR (R-transpose * R).<br />
(CORRECT)<br />
<br />
@param R: Matrix<br />
@type R: 3x3 Matrix<br />
<br />
@precondition: R is a the well formed matrix as per Kabsch.<br />
@postcondition: RtR is now defined<br />
<br />
@return: M{R^tR}<br />
@rtype : 3x3 matrix<br />
<br />
"""<br />
<br />
RtR = Numeric.matrixmultiply(Numeric.transpose(R), R)<br />
<br />
return RtR<br />
<br />
<br />
def calcEigenPairs( self, RtR ):<br />
"""<br />
Calculate the corresponding eigenpairs for RtR, and sort them accordingly:<br />
M{m1 >= m2 >= m3}; set M{v3 = v1 x v2} to ensure a RHS<br />
(CORRECT)<br />
<br />
@postcondition: The eigen pairs are calculated, sorted such that M{m1 >= m2 >= m3} and<br />
M{v3 = v1 x v2}.<br />
<br />
@param RtR: 3x3 Matrix of M{R^t * R}.<br />
@type RtR: 3x3 Matrix<br />
@return : Eigenpairs for the RtR matrix.<br />
@rtype : List of stuff<br />
<br />
"""<br />
<br />
eVal, eVec = LinearAlgebra.eigenvectors(RtR)<br />
<br />
# This is cool. We sort it using Numeric.sort(eVal)<br />
# then we reverse it using nifty-crazy ass notation [::-1].<br />
eVal2 = Numeric.sort(eVal)[::-1]<br />
eVec2 = [[],[],[]] #Numeric.zeros((3,3), Numeric.Float64)<br />
<br />
# Map the vectors to their appropriate owners <br />
if ( eVal2[0] == eVal[0]):<br />
eVec2[0] = eVec[0]<br />
if ( eVal2[1] == eVal[1] ):<br />
eVec2[1] = eVec[1]<br />
eVec2[2] = eVec[2]<br />
else:<br />
eVec2[1] = eVec[2]<br />
eVec2[2] = eVec[1]<br />
elif( eVal2[0] == eVal[1]):<br />
eVec2[0] = eVec[1]<br />
if ( eVal2[1] == eVal[0] ):<br />
eVec2[1] = eVec[0]<br />
eVec2[2] = eVec[2]<br />
else:<br />
eVec2[1] = eVec[2]<br />
eVec2[2] = eVec[0]<br />
elif( eVal2[0] == eVal[2]):<br />
eVec2[0] = eVec[2]<br />
if ( eVal2[1] == eVal[1] ):<br />
eVec2[1] = eVec[1]<br />
eVec2[2] = eVec[0]<br />
else:<br />
eVec2[1] = eVec[0]<br />
eVec2[2] = eVec[1]<br />
<br />
eVec2[2][0] = eVec2[0][1]*eVec2[1][2] - eVec2[0][2]*eVec2[1][1]<br />
eVec2[2][1] = eVec2[0][2]*eVec2[1][0] - eVec2[0][0]*eVec2[1][2]<br />
eVec2[2][2] = eVec2[0][0]*eVec2[1][1] - eVec2[0][1]*eVec2[1][0]<br />
<br />
return [eVal2, eVec2]<br />
<br />
<br />
def calcBVectors( self, R, eVectors ):<br />
"""<br />
Calculate M{R*a_k} and normalize the first two vectors to obtain M{b_1, b_2} and set<br />
M{b_3 = b_1 x b_2}. This also takes care of {m2 > m3 = 0}. <br />
(CORRECT)<br />
<br />
@postcondition: b-Vectors are defined and returned<br />
<br />
@return: The three B-vectors<br />
@rtype: List of 3D vectors (Python LOL).<br />
"""<br />
<br />
bVectors = Numeric.zeros((3,3), Numeric.Float64)<br />
<br />
for i in range(0,3):<br />
bVectors[i] = Numeric.matrixmultiply(R, eVectors[i])<br />
<br />
bVectors[0] = bVectors[0] / Numeric.sqrt(Numeric.add.reduce(bVectors[0]**2))<br />
bVectors[1] = bVectors[1] / Numeric.sqrt(Numeric.add.reduce(bVectors[1]**2))<br />
bVectors[2] = bVectors[2] / Numeric.sqrt(Numeric.add.reduce(bVectors[2]**2))<br />
<br />
bVectors[2][0] = bVectors[0][1]*bVectors[1][2] - bVectors[0][2]*bVectors[1][1]<br />
bVectors[2][1] = bVectors[0][2]*bVectors[1][0] - bVectors[0][0]*bVectors[1][2]<br />
bVectors[2][2] = bVectors[0][0]*bVectors[1][1] - bVectors[0][1]*bVectors[1][0]<br />
<br />
return bVectors<br />
<br />
<br />
<br />
def calcU( self, eVectors, bVectors ):<br />
"""<br />
Calculate M{U=(u_{ij})=(sum n b_{ki} * a_{kj})} to obtain the best rotation. Set<br />
M{sigma_3 = -1 if b3(Ra3) < 0 else sigma_3 = +1}.<br />
(CORRECT)<br />
<br />
@postcondition: U is defined<br />
<br />
@param eVectors: Eigenvectors for the system.<br />
@type eVectors: Eigenvectors<br />
<br />
@param bVectors: BVectors as described by Kabsch.<br />
@type bVectors: BVectors<br />
<br />
@return: U the rotation matrix.<br />
@rtype :3x3 matrix.<br />
<br />
"""<br />
<br />
U = Numeric.zeros((3,3), Numeric.Float64)<br />
<br />
for k in range(0,3):<br />
for i in range(0,3):<br />
for j in range(0,3):<br />
U[i][j] = U[i][j] + Numeric.matrixmultiply(bVectors[k][i], eVectors[k][j])<br />
<br />
return U<br />
<br />
<br />
def calcE0( self, c1, c2 ):<br />
"""<br />
Calculates the initial RMSD, which Kacbsch called E0.<br />
(CORRECT)<br />
<br />
@param c1: coordinats of the first vectors, as an array of 3D vectors.<br />
@type c1: Python list<br />
<br />
@param c2: coordinates of the second set of vectors, as an array of 3D vectors.<br />
@type c2: Python list<br />
<br />
@return: E0 the initial RMSD.<br />
@rtype : float.<br />
<br />
"""<br />
<br />
E0 = 0.0<br />
<br />
L = len(c1)<br />
for i in range( 0, L ):<br />
for j in range(0, 3):<br />
E0 = E0 + 0.5*( (c1[i][j]*c1[i][j])+(c2[i][j]*c2[i][j]))<br />
<br />
return E0<br />
<br />
def calcRMSD( self, E0, eValues, eVectors, bVectors, R, N):<br />
"""<br />
Calculate the RMSD. The residual error is then<br />
The M{E = E0 - sqrt(m1) - sqrt(m2) - sigma_3(sqrt(m3))}.<br />
<br />
@param E0: Initial RMSD as calculated in L{calcE0}.<br />
@type E0: float.<br />
<br />
@param eVectors: Eigenvectors as calculated from L{calcEigenPairs}<br />
@type eVectors: vectors, dammit!<br />
<br />
@param bVectors: B-vectors as calc. from L{calcBVectors}<br />
@type bVectors: More vectors.<br />
<br />
@param R: The matrix R, from L{calcR}.<br />
@type R: 3x3 matrix. <br />
<br />
@param N: Number of equivalenced points<br />
@type N: integer<br />
<br />
@postcondition: RMSD is computed.<br />
@return: The RMSD.<br />
<br />
"""<br />
sigma3 = 0<br />
if ( Numeric.matrixmultiply(bVectors[2], Numeric.matrixmultiply( R, eVectors[2])) < 0):<br />
sigma3 = -1<br />
else:<br />
sigma3 = 1<br />
<br />
E = math.sqrt( 2*(E0 - math.sqrt(eValues[0]) - math.sqrt(eValues[1]) - sigma3*(math.sqrt(eValues[2]))) / N)<br />
<br />
return E<br />
<br />
<br />
def calcSimpleRMSD( self, c1, c2 ):<br />
"""<br />
Calculates the usual concept of RMSD between two set of points. The CalcRMSD above<br />
sticks to Kabsch's alignment method protocol and calculates something much different.<br />
@see kabsch.calcRMSD<br />
<br />
@param c1: List of points #1<br />
@type c1: LOL<br />
<br />
@param c2: List of points #2<br />
@type c2: LOL<br />
<br />
@return: RMSD between the two<br />
<br />
"""<br />
<br />
RMSD = 0.0<br />
for i in range(0, len(c1)):<br />
for j in range(0,3):<br />
RMSD = RMSD + (c2[i][j]-c1[i][j])**2<br />
<br />
RMSD = RMSD / len(c1)<br />
RMSD = Numeric.sqrt(RMSD)<br />
return RMSD<br />
<br />
<br />
#####################################################################<br />
#<br />
# UTIL Functions<br />
def rotatePoints(self, U, c2):<br />
"""<br />
Rotate all points in c2 based on the rotation matrix U.<br />
<br />
@param U: 3x3 Rotation matrix<br />
@type U: 3x3 matrix<br />
<br />
@param c2: List of points to rotate<br />
@type c2: List of 3D vectors<br />
<br />
@return: List of rotated points<br />
<br />
"""<br />
<br />
L = len(c2)<br />
<br />
for n in range(0,L):<br />
c2[n][0] = c2[n][0] * U[0][0] + c2[n][1] * U[1][0] + c2[n][2] * U[2][0]<br />
c2[n][1] = c2[n][0] * U[0][1] + c2[n][1] * U[1][1] + c2[n][2] * U[2][1]<br />
c2[n][2] = c2[n][0] * U[0][2] + c2[n][1] * U[1][2] + c2[n][2] * U[2][2]<br />
<br />
return c2<br />
<br />
def writeU( self, U, fileName ):<br />
"""<br />
Convenience function. Writes U to disk.<br />
<br />
"""<br />
<br />
if ( len(fileName) == 0 ):<br />
fileName = "./U"<br />
<br />
outFile = open( fileName, "wb")<br />
for i in range(0,3):<br />
for j in range(0,3):<br />
outFile.write( str(U[i][j]).ljust(20) )<br />
outFile.write("\n")<br />
outFile.close() <br />
<br />
<br />
<br />
def optAlign( sel1, sel2 ):<br />
"""<br />
optAlign performs the Kabsch alignment algorithm upon the alpha-carbons of two selections.<br />
Example: optAlign MOL1 and i. 20-40, MOL2 and i. 102-122<br />
Example 2: optAlign 1GGZ and i. 4-146 and n. CA, 1CLL and i. 4-146 and n. CA<br />
<br />
Two RMSDs are returned. One comes from the Kabsch algorithm and the other from<br />
PyMol based upon your selections.<br />
<br />
By default, this program will optimally align the ALPHA CARBONS of the selections provided.<br />
To turn off this feature remove the lines between the commented "REMOVE ALPHA CARBONS" below.<br />
<br />
@param sel1: First PyMol selection with N-atoms<br />
@param sel2: Second PyMol selection with N-atoms<br />
"""<br />
cmd.reset()<br />
<br />
# make the lists for holding coordinates<br />
# partial lists<br />
stored.sel1 = []<br />
stored.sel2 = []<br />
# full lists<br />
stored.mol1 = []<br />
stored.mol2 = []<br />
<br />
# now put the coordinates into a list<br />
# partials<br />
<br />
# -- REMOVE ALPHA CARBONS<br />
sel1 = sel1 + " and N. CA"<br />
sel2 = sel2 + " and N. CA"<br />
# -- REMOVE ALPHA CARBONS<br />
<br />
cmd.iterate_state(1, selector.process(sel1), "stored.sel1.append([x,y,z])")<br />
cmd.iterate_state(1, selector.process(sel2), "stored.sel2.append([x,y,z])")<br />
# full molecule<br />
mol1 = cmd.identify(sel1,1)[0][0]<br />
mol2 = cmd.identify(sel2,1)[0][0]<br />
cmd.iterate_state(1, mol1, "stored.mol1.append([x,y,z])")<br />
cmd.iterate_state(1, mol2, "stored.mol2.append([x,y,z])")<br />
<br />
K = kabsch()<br />
U, T1, T2, RMSD, c1, c2 = K.align(stored.sel1, stored.sel2, [])<br />
<br />
stored.mol2 = map(lambda v:[T2[0]+((v[0]*U[0][0])+(v[1]*U[1][0])+(v[2]*U[2][0])),T2[1]+((v[0]*U[0][1])+(v[1]*U[1][1])+(v[2]*U[2][1])),T2[2]+((v[0]*U[0][2])+(v[1]*U[1][2])+(v[2]*U[2][2]))],stored.mol2)<br />
#stored.mol1 = map(lambda v:[ v[0]+T1[0], v[1]+T1[1], v[2]+T1[2] ], stored.mol1)<br />
stored.mol1 = map(lambda v:[ v[0]+T1[0], v[1]+T1[1], v[2]+T1[2] ], stored.mol1)<br />
<br />
cmd.alter_state(1,mol1,"(x,y,z)=stored.mol1.pop(0)")<br />
cmd.alter_state(1,mol2,"(x,y,z)=stored.mol2.pop(0)")<br />
cmd.alter( 'all',"segi=''")<br />
cmd.alter('all', "chain=''")<br />
print "RMSD=%f" % cmd.rms_cur(sel1, sel2)<br />
print "MY RMSD=%f" % RMSD<br />
cmd.hide('everything')<br />
cmd.show('ribbon', sel1 + ' or ' + sel2)<br />
cmd.color('gray70', mol1 )<br />
cmd.color('paleyellow', mol2 )<br />
cmd.color('red', 'visible')<br />
cmd.show('ribbon', 'not visible')<br />
cmd.center('visible')<br />
cmd.orient()<br />
cmd.zoom('visible')<br />
<br />
cmd.extend("optAlign", optAlign) <br />
</source><br />
<br />
==References==<br />
'''[Kabsch, 1976]''' Kabsch, W. (1976).<br />
A solution for the best rotation to relate two sets of vectors.<br />
''Acta. Crystal'', 32A:922-923.<br />
<br />
'''[Kabsch, 1978]''' Kabsch, W. (1978).<br />
A discussion of the solution for the best rotation to related two sets of vectors.<br />
''Acta. Crystal'', 34A:827-828.<br />
<br />
<br />
[[Category:Script_Library|Kabsch Alignment]]<br />
[[Category:Structure_Alignment|Kabsch Alignment]]</div>Newacct