https://pymolwiki.org/api.php?action=feedcontributions&user=Tmwsiy&feedformat=atomPyMOLWiki - User contributions [en]2024-03-29T12:33:55ZUser contributionsMediaWiki 1.35.7https://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=4834Rotamer Toggle2008-03-13T18:25:48Z<p>Tmwsiy: </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 string<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>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=4816Rotamer Toggle2008-03-13T02:06:00Z<p>Tmwsiy: </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 />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 string<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 CA',residue_def+' and name N',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 CA',residue_def+' and name N',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>Tmwsiyhttps://pymolwiki.org/index.php?title=Label_font_id&diff=3411Label font id2006-09-06T13:01:40Z<p>Tmwsiy: /* Syntax */</p>
<hr />
<div>== Overview ==<br />
Set which fonts PyMol uses to render labels.<br />
<br />
== Syntax ==<br />
<source lang="python"><br />
set label_font_id, 10 # use font no. 10<br />
set label_font_id, 11 # use font no. 11<br />
set label_font_id, 12 # use font no. 12<br />
</source><br />
<br />
Note: available font ids 10-16.</div>Tmwsiyhttps://pymolwiki.org/index.php?title=CreateSecondaryStructure&diff=3280CreateSecondaryStructure2005-10-12T12:31:32Z<p>Tmwsiy: </p>
<hr />
<div><br />
*Many bugs found, need to be worked out before further use... stay tuned.<br />
<br />
===DESCRIPTION===<br />
To enable growing of a peptide sequence of one of the terminals. The growing can be set to any secondary structure (phi,psi pairing). Only extendHelix is currently implemented, but it should be rather simple to add more functions in or tweak the existing ones.<br />
<br />
Functions:<br />
*extendHelix<br />
*createSS<br />
*set_phipsi<br />
<br />
===SETUP===<br />
run CreateSecondaryStructure.py<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform<br />
*N-terminal growing doesn't work: adds residues, but doesn't set angles correctly<br />
*Many bugs found, need to be worked out before further use... stay tuned.<br />
<br />
===USAGE===<br />
extendHelix selection,sequence,repeat [, phi] [, psi] [, terminal ]<br />
set_phipsi selection, phi, psi<br />
<br />
===EXAMPLES===<br />
extendHelix('resi 1371', 'ALA,GLN,HIS,ALA', 5)<br />
set_phipsi('resi 1371', -60, -60)<br />
<br />
===SCRIPTS (CreateSecondaryStructures.py)===<br />
CreateSecondaryStructures.py <br />
<source lang="python"><br />
<br />
##############################################<br />
# Author: Dan Kulp<br />
# Date : 9/8/2005<br />
#<br />
#<br />
# Notes: <br />
# - Simple builds a string of residues<br />
# and sets the phi,psi angles.<br />
# - No energies are computed.<br />
# - This will generate a starting point.<br />
# - Defaultly grows from C-term, <br />
# - N-term growing currently broken<br />
#############################################<br />
<br />
import string<br />
<br />
# Wrapper Functions...<br />
print "extendHelix(selection,sequence,repeat)"<br />
print "Example:\n\t extendHelix('resi 1371', 'ALA,GLN,HIS,ALA', 5)"<br />
print "Note: simple build of residue type and phi,psi angle; no energy computed" <br />
<br />
def extendHelix(sel,seq,repeat=1,phi=-60,psi=-60,terminal='C'):<br />
createSS(sel,seq,repeat,phi,psi,string.upper(terminal))<br />
cmd.select("extendedHelix","all")<br />
cmd.deselect()<br />
cmd.save("./extendedHelix.pdb","extendedHelix")<br />
<br />
<br />
# Create generic secondary structure, based off a selection<br />
def createSS(sel, sequence='ALA',repeat='1',phi=-60,psi=-60,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 = string.split(sequence,",")<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 />
<br />
# Loop and build new residues<br />
for i in range(1,repeat+1):<br />
for s in seq:<br />
print "residue[%i]: %s" % (i,s)<br />
editor.attach_amino_acid('pk1',s)<br />
<br />
# Loop and set phi,psi angles for new residues<br />
if terminal == 'N':<br />
resi -= repeat<br />
<br />
for i in range(0,repeat+1):<br />
for s in seq:<br />
set_phipsi("resi %i" % (resi), phi,psi)<br />
resi += 1<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 />
<br />
# Set up some variables..<br />
residues = ['dummy'] # Keep track of residues already done<br />
probs = [] # probability of each residue conformation<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 at.resn == 'GLY' or at.chain+":"+at.resn+":"+at.resi in residues:<br />
continue<br />
<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 />
old_phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
old_psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<br />
<br />
print "Changing "+at.resn+str(at.resi)+" from "+str(old_phi)+","+str(old_psi)+" to "+str(phi)+","+str(psi)<br />
<br />
cmd.set_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',phi)<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', psi)<br />
<br />
except:<br />
print "Exception Thrown"<br />
continue<br />
<br />
<br />
<br />
<br />
</source><br />
<br />
<br />
[[Category:Script_Library|CreateSecondaryStructure]]<br />
<br />
[[Category:Structural_Biology_Scripts|CreateSecondaryStructure]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=3060Rotamer Toggle2005-09-19T14:40:08Z<p>Tmwsiy: /* NOTES / STATUS */</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 />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 string<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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=1081Rotamer Toggle2005-09-19T14:39:01Z<p>Tmwsiy: /* SETUP */</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 />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 and on Red Hat Linux 9.0. Will test v0.98 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 string<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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=1080Rotamer Toggle2005-09-19T13:43:21Z<p>Tmwsiy: /* SCRIPTS (Rotamers.py ; MyMenu.py) */</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 />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 />
Simply "import rotamers" and use the functions manually.<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 />
<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform and on Red Hat Linux 9.0. Will test v0.98 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 string<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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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>Tmwsiyhttps://pymolwiki.org/index.php?title=Peptide_Sequence&diff=3263Peptide Sequence2005-09-16T13:34:07Z<p>Tmwsiy: /* Other Sources */</p>
<hr />
<div>=Building a Peptide Sequence From Hand=<br />
There are more than one method in PyMol for building a peptide sequence from hand. First, you may simply hold down the '''alt''' ('''option''' on Mac) key and type in the one-letter code for the sequence. Secondly, you can write a script like the following<br />
<source lang="python"><br />
for aa in "DCAHWLGELVWCT": cmd._alt(string.lower(aa))<br />
</source><br />
which will build the amino acid sequence "DCAHWLGELVWCT".<br />
<br />
==Other Sources==<br />
Robert Campbell has notified us of [http://adelie.biochem.queensu.ca/~rlc/work/pymol his two scripts] to solve the problem. You can apparently specify phi/psi angles, too. Look for '''build_seq.py''' and '''build_seq_phi_psi.py'''.<br />
<br />
Also check out [[CreateSecondaryStructure]] , which you can build repeating units of different types of secondary structure (a-helix,b-sheets, loops,etc) (Dan Kulp)<br />
<br />
In addition, [[Rotamer Toggle]] can set the sidechains to different rotamers or specific side-chain angle sets. (Dan Kulp)</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Peptide_Sequence&diff=1073Peptide Sequence2005-09-16T13:33:39Z<p>Tmwsiy: /* Other Sources */</p>
<hr />
<div>=Building a Peptide Sequence From Hand=<br />
There are more than one method in PyMol for building a peptide sequence from hand. First, you may simply hold down the '''alt''' ('''option''' on Mac) key and type in the one-letter code for the sequence. Secondly, you can write a script like the following<br />
<source lang="python"><br />
for aa in "DCAHWLGELVWCT": cmd._alt(string.lower(aa))<br />
</source><br />
which will build the amino acid sequence "DCAHWLGELVWCT".<br />
<br />
==Other Sources==<br />
Robert Campbell has notified us of [http://adelie.biochem.queensu.ca/~rlc/work/pymol his two scripts] to solve the problem. You can apparently specify phi/psi angles, too. Look for '''build_seq.py''' and '''build_seq_phi_psi.py'''.<br />
<br />
Also check out [[CreateSecondaryStructure]] , which you can build repeating units of different types of secondary structure (a-helix,b-sheets, loops,etc) (by Dan Kulp)<br />
<br />
In addition, [[Rotamer Toggle]] can set the sidechains to different rotamers or specific side-chain angle sets. (by Dan Kulp)</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Peptide_Sequence&diff=1072Peptide Sequence2005-09-16T13:33:04Z<p>Tmwsiy: /* Other Sources */</p>
<hr />
<div>=Building a Peptide Sequence From Hand=<br />
There are more than one method in PyMol for building a peptide sequence from hand. First, you may simply hold down the '''alt''' ('''option''' on Mac) key and type in the one-letter code for the sequence. Secondly, you can write a script like the following<br />
<source lang="python"><br />
for aa in "DCAHWLGELVWCT": cmd._alt(string.lower(aa))<br />
</source><br />
which will build the amino acid sequence "DCAHWLGELVWCT".<br />
<br />
==Other Sources==<br />
Robert Campbell has notified us of [http://adelie.biochem.queensu.ca/~rlc/work/pymol his two scripts] to solve the problem. You can apparently specify phi/psi angles, too. Look for '''build_seq.py''' and '''build_seq_phi_psi.py'''.<br />
<br />
Also check out [[CreateSecondaryStructure]] , which you can build repeating units of different types of secondary structure (a-helix,b-sheets, loops,etc) (by me, Dan Kulp)<br />
<br />
In addition, [[Rotamer Toggle]] can set the sidechains to different rotamers or specific side-chain angle sets. (by me, Dan Kulp)</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Peptide_Sequence&diff=1071Peptide Sequence2005-09-16T13:32:48Z<p>Tmwsiy: /* Other Sources */</p>
<hr />
<div>=Building a Peptide Sequence From Hand=<br />
There are more than one method in PyMol for building a peptide sequence from hand. First, you may simply hold down the '''alt''' ('''option''' on Mac) key and type in the one-letter code for the sequence. Secondly, you can write a script like the following<br />
<source lang="python"><br />
for aa in "DCAHWLGELVWCT": cmd._alt(string.lower(aa))<br />
</source><br />
which will build the amino acid sequence "DCAHWLGELVWCT".<br />
<br />
==Other Sources==<br />
Robert Campbell has notified us of [http://adelie.biochem.queensu.ca/~rlc/work/pymol his two scripts] to solve the problem. You can apparently specify phi/psi angles, too. Look for '''build_seq.py''' and '''build_seq_phi_psi.py'''.<br />
<br />
Also check out [[CreateSecondaryStructure]] , which you can build repeating units of different types of secondary structure (a-helix,b-sheets, loops,etc) (by me, Dan Kulp)<br />
In addition, [[Rotamer Toggle]] can set the sidechains to different rotamers or specific side-chain angle sets. (by me, Dan Kulp)</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Peptide_Sequence&diff=1070Peptide Sequence2005-09-16T13:32:16Z<p>Tmwsiy: /* Other Sources */</p>
<hr />
<div>=Building a Peptide Sequence From Hand=<br />
There are more than one method in PyMol for building a peptide sequence from hand. First, you may simply hold down the '''alt''' ('''option''' on Mac) key and type in the one-letter code for the sequence. Secondly, you can write a script like the following<br />
<source lang="python"><br />
for aa in "DCAHWLGELVWCT": cmd._alt(string.lower(aa))<br />
</source><br />
which will build the amino acid sequence "DCAHWLGELVWCT".<br />
<br />
==Other Sources==<br />
Robert Campbell has notified us of [http://adelie.biochem.queensu.ca/~rlc/work/pymol his two scripts] to solve the problem. You can apparently specify phi/psi angles, too. Look for '''build_seq.py''' and '''build_seq_phi_psi.py'''.<br />
Also check out [[CreateSecondaryStructure]] , which you can build repeating units of different types of secondary structure (a-helix,b-sheets, loops,etc)<br />
In addition, [[Rotamer Toggle]] can set the sidechains to different rotamers or specific side-chain angle sets.</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Peptide_Sequence&diff=1069Peptide Sequence2005-09-16T13:31:38Z<p>Tmwsiy: /* Other Sources */</p>
<hr />
<div>=Building a Peptide Sequence From Hand=<br />
There are more than one method in PyMol for building a peptide sequence from hand. First, you may simply hold down the '''alt''' ('''option''' on Mac) key and type in the one-letter code for the sequence. Secondly, you can write a script like the following<br />
<source lang="python"><br />
for aa in "DCAHWLGELVWCT": cmd._alt(string.lower(aa))<br />
</source><br />
which will build the amino acid sequence "DCAHWLGELVWCT".<br />
<br />
==Other Sources==<br />
Robert Campbell has notified us of [http://adelie.biochem.queensu.ca/~rlc/work/pymol his two scripts] to solve the problem. You can apparently specify phi/psi angles, too. Look for '''build_seq.py''' and '''build_seq_phi_psi.py'''.<br />
Also check out [[CreateSecondaryStructure]] , which you can build repeating units of different types of secondary structure (a-helix,b-sheets, loops,etc) also [[RotamerToggle]] can set the sidechains to different rotamers or specific side-chain angle sets.</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=1079Rotamer Toggle2005-09-15T21:50:40Z<p>Tmwsiy: /* EXAMPLES */</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 />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 />
Simply "import rotamers" and use the functions manually.<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 />
<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform and on Red Hat Linux 9.0. Will test v0.98 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 string<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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=1067Rotamer Toggle2005-09-15T21:48:08Z<p>Tmwsiy: /* USAGE */</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 />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 />
Simply "import rotamers" and use the functions manually.<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 />
<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform and on Red Hat Linux 9.0. Will test v0.98 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 />
<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 string<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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=1066Rotamer Toggle2005-09-15T21:46:52Z<p>Tmwsiy: /* DESCRIPTION */</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 />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 />
Simply "import rotamers" and use the functions manually.<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 />
<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform and on Red Hat Linux 9.0. Will test v0.98 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 />
<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 />
<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 string<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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=1065Rotamer Toggle2005-09-15T21:45:23Z<p>Tmwsiy: /* SCRIPTS (Rotamers.py ; MyMenu.py) */</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 />
===IMAGES===<br />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 />
Simply "import rotamers" and use the functions manually.<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 />
<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform and on Red Hat Linux 9.0. Will test v0.98 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 />
<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 />
<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 string<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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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>Tmwsiyhttps://pymolwiki.org/index.php?title=CreateSecondaryStructure&diff=1105CreateSecondaryStructure2005-09-09T02:23:23Z<p>Tmwsiy: </p>
<hr />
<div>===DESCRIPTION===<br />
To enable growing of a peptide sequence of one of the terminals. The growing can be set to any secondary structure (phi,psi pairing). Only extendHelix is currently implemented, but it should be rather simple to add more functions in or tweak the existing ones.<br />
<br />
Functions:<br />
*extendHelix<br />
*createSS<br />
*set_phipsi<br />
<br />
===SETUP===<br />
run CreateSecondaryStructure.py<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform<br />
*N-terminal growing doesn't work: adds residues, but doesn't set angles correctly<br />
<br />
===USAGE===<br />
extendHelix selection,sequence,repeat [, phi] [, psi] [, terminal ]<br />
set_phipsi selection, phi, psi<br />
<br />
===EXAMPLES===<br />
extendHelix('resi 1371', 'ALA,GLN,HIS,ALA', 5)<br />
set_phipsi('resi 1371', -60, -60)<br />
<br />
===SCRIPTS (CreateSecondaryStructures.py)===<br />
CreateSecondaryStructures.py <br />
<source lang="python"><br />
<br />
##############################################<br />
# Author: Dan Kulp<br />
# Date : 9/8/2005<br />
#<br />
#<br />
# Notes: <br />
# - Simple builds a string of residues<br />
# and sets the phi,psi angles.<br />
# - No energies are computed.<br />
# - This will generate a starting point.<br />
# - Defaultly grows from C-term, <br />
# - N-term growing currently broken<br />
#############################################<br />
<br />
import string<br />
<br />
# Wrapper Functions...<br />
print "extendHelix(selection,sequence,repeat)"<br />
print "Example:\n\t extendHelix('resi 1371', 'ALA,GLN,HIS,ALA', 5)"<br />
print "Note: simple build of residue type and phi,psi angle; no energy computed" <br />
<br />
def extendHelix(sel,seq,repeat=1,phi=-60,psi=-60,terminal='C'):<br />
createSS(sel,seq,repeat,phi,psi,string.upper(terminal))<br />
cmd.select("extendedHelix","all")<br />
cmd.deselect()<br />
cmd.save("./extendedHelix.pdb","extendedHelix")<br />
<br />
<br />
# Create generic secondary structure, based off a selection<br />
def createSS(sel, sequence='ALA',repeat='1',phi=-60,psi=-60,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 = string.split(sequence,",")<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 />
<br />
# Loop and build new residues<br />
for i in range(1,repeat+1):<br />
for s in seq:<br />
print "residue[%i]: %s" % (i,s)<br />
editor.attach_amino_acid('pk1',s)<br />
<br />
# Loop and set phi,psi angles for new residues<br />
if terminal == 'N':<br />
resi -= repeat<br />
<br />
for i in range(0,repeat+1):<br />
for s in seq:<br />
set_phipsi("resi %i" % (resi), phi,psi)<br />
resi += 1<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 />
<br />
# Set up some variables..<br />
residues = ['dummy'] # Keep track of residues already done<br />
probs = [] # probability of each residue conformation<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 at.resn == 'GLY' or at.chain+":"+at.resn+":"+at.resi in residues:<br />
continue<br />
<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 />
old_phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
old_psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<br />
<br />
print "Changing "+at.resn+str(at.resi)+" from "+str(old_phi)+","+str(old_psi)+" to "+str(phi)+","+str(psi)<br />
<br />
cmd.set_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',phi)<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', psi)<br />
<br />
except:<br />
print "Exception Thrown"<br />
continue<br />
<br />
<br />
<br />
<br />
</source><br />
<br />
<br />
[[Category:Script_Library|CreateSecondaryStructure]]<br />
<br />
[[Category:Structural_Biology_Scripts|CreateSecondaryStructure]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=CreateSecondaryStructure&diff=1061CreateSecondaryStructure2005-09-09T02:22:06Z<p>Tmwsiy: </p>
<hr />
<div>===DESCRIPTION===<br />
To enable growing of a peptide sequence of one of the terminals. The growing can be set to any secondary structure (phi,psi pairing). Only extendHelix is currently implemented, but it should be rather simple to add more functions in or tweak the existing ones.<br />
<br />
Functions:<br />
*extendHelix<br />
*createSS<br />
*set_phipsi<br />
<br />
===IMAGES===<br />
<br />
===SETUP===<br />
run CreateSecondaryStructure.py<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform<br />
*N-terminal growing doesn't work: adds residues, but doesn't set angles correctly<br />
<br />
===USAGE===<br />
extendHelix selection,sequence,repeat [, phi] [, psi] [, terminal ]<br />
set_phipsi selection, phi, psi<br />
<br />
===EXAMPLES===<br />
extendHelix('resi 1371', 'ALA,GLN,HIS,ALA', 5)<br />
set_phipsi('resi 1371', -60, -60)<br />
<br />
===SCRIPTS (CreateSecondaryStructures.py)===<br />
CreateSecondaryStructures.py <br />
<source lang="python"><br />
<br />
##############################################<br />
# Author: Dan Kulp<br />
# Date : 9/8/2005<br />
#<br />
#<br />
# Notes: <br />
# - Simple builds a string of residues<br />
# and sets the phi,psi angles.<br />
# - No energies are computed.<br />
# - This will generate a starting point.<br />
# - Defaultly grows from C-term, <br />
# - N-term growing currently broken<br />
#############################################<br />
<br />
import string<br />
<br />
# Wrapper Functions...<br />
print "extendHelix(selection,sequence,repeat)"<br />
print "Example:\n\t extendHelix('resi 1371', 'ALA,GLN,HIS,ALA', 5)"<br />
print "Note: simple build of residue type and phi,psi angle; no energy computed" <br />
<br />
def extendHelix(sel,seq,repeat=1,phi=-60,psi=-60,terminal='C'):<br />
createSS(sel,seq,repeat,phi,psi,string.upper(terminal))<br />
cmd.select("extendedHelix","all")<br />
cmd.deselect()<br />
cmd.save("./extendedHelix.pdb","extendedHelix")<br />
<br />
<br />
# Create generic secondary structure, based off a selection<br />
def createSS(sel, sequence='ALA',repeat='1',phi=-60,psi=-60,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 = string.split(sequence,",")<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 />
<br />
# Loop and build new residues<br />
for i in range(1,repeat+1):<br />
for s in seq:<br />
print "residue[%i]: %s" % (i,s)<br />
editor.attach_amino_acid('pk1',s)<br />
<br />
# Loop and set phi,psi angles for new residues<br />
if terminal == 'N':<br />
resi -= repeat<br />
<br />
for i in range(0,repeat+1):<br />
for s in seq:<br />
set_phipsi("resi %i" % (resi), phi,psi)<br />
resi += 1<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 />
<br />
# Set up some variables..<br />
residues = ['dummy'] # Keep track of residues already done<br />
probs = [] # probability of each residue conformation<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 at.resn == 'GLY' or at.chain+":"+at.resn+":"+at.resi in residues:<br />
continue<br />
<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 />
old_phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
old_psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<br />
<br />
print "Changing "+at.resn+str(at.resi)+" from "+str(old_phi)+","+str(old_psi)+" to "+str(phi)+","+str(psi)<br />
<br />
cmd.set_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',phi)<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', psi)<br />
<br />
except:<br />
print "Exception Thrown"<br />
continue<br />
<br />
<br />
<br />
<br />
</source><br />
<br />
<br />
[[Category:Script_Library|CreateSecondaryStructure]]<br />
<br />
[[Category:Structural_Biology_Scripts|CreateSecondaryStructure]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Category:Structural_Biology_Scripts&diff=3085Category:Structural Biology Scripts2005-09-09T02:13:22Z<p>Tmwsiy: </p>
<hr />
<div>This page is a sub-category of scripts for Structural Biology Applications.<br />
<br />
* [[Rotamer Toggle]] -- Toggle through the most common side chain rotamers and/or color by rotamer probability (Dunbrack's Backbone-depenedent library)<br />
* [[DynoPlot]] -- Generic dynamic plotting utility; Interactive Ramachandran Plots.<br />
* [[CreateSecondaryStructure]] -- Grow a helix,strand or loop from ends of proteins<br />
<br />
[[Category:Script_Library]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=1064Rotamer Toggle2005-09-08T13:54:54Z<p>Tmwsiy: </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 />
===IMAGES===<br />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 />
Simply "import rotamers" and use the functions manually.<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 />
<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform and on Red Hat Linux 9.0. Will test v0.98 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 />
<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 />
<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 string<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], 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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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 />
<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 />
<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 />
</source><br />
<br />
<br />
[[Category:Script_Library|Rotamer Toggle]]<br />
<br />
[[Category:Structural_Biology_Scripts|Rotamer Toggle]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=DynoPlot&diff=3276DynoPlot2005-08-30T17:50:09Z<p>Tmwsiy: </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 />
[[Image:RamaPlotInitComposite.png|thumb|left|Initial Ramachandran plot of 1ENV]]<br />
[[Image:RamaPlotBentComposite.png|thumb|left|Modified pose and plot of 1ENV]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
===SETUP===<br />
place the DynoPlot.py script into PYMOL_PATH/modules/pmg_tk/startup/ , where PYMOL_PATH on Windows is defaulted to C:/Program Files/DeLano Scientific/PyMol/<br />
start/restart PyMol<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 = 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 = 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 key,value in self.shapes.items():<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 self.shapes.has_key(spot[0]):<br />
print "Residue(Ca): %s\n" % str(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.shapes.has_key(self.item[0]):<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.shapes.has_key(self.item[0]):<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 not at.chain+":"+at.resn+":"+at.resi 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 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 />
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: "+str(value[3])+","+str(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 />
<br />
[[Category:Structural_Biology_Scripts|DynoPlot]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=User_talk:Tmwsiy&diff=1057User talk:Tmwsiy2005-08-30T16:31:56Z<p>Tmwsiy: </p>
<hr />
<div></div>Tmwsiyhttps://pymolwiki.org/index.php?title=User_talk:Inchoate&diff=3279User talk:Inchoate2005-08-30T15:58:39Z<p>Tmwsiy: </p>
<hr />
<div>Jason,<br />
Conserning the Kabsch alogrithm.... Can you take two sets of vectors with different numbers in each set and have it loop over the larger set?<br />
<br />
For instance,<br />
I have CA and CB positions for 4 residues (residues aren't sequential), could I find the optimal RMSD between the 4 residue CA_CB set and a another protein (well, it's own CA_CB set) ?<br />
<br />
I haven't looked at the code, but I figured you are more familiar with it.<br />
<br />
Thanks,<br />
Dan</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Align&diff=1256Align2005-08-30T12:42:31Z<p>Tmwsiy: </p>
<hr />
<div>===DESCRIPTION===<br />
'''align''' performs a sequence alignment followed by a structural alignment, and then carrys out zero or more cycles of refinement in order to reject structural outliers found during the fit.<br />
<br />
===USAGE===<br />
<source lang="python"><br />
align (source), (target) [,cutoff [,cycles [,gap [,extend \<br />
[,skip [,object [,matrix [, quiet ]]]]]]]]<br />
</source><br />
<br />
===PYMOL API===<br />
<source lang="python"><br />
cmd.align( string source, string target, float cutoff=2.0,<br />
int cycles=2, float gap=-10.0, float extend=-0.5,<br />
int skip=0, string object=None, string matrix="BLOSUM62",<br />
int quiet=1 )<br />
</source><br />
<br />
===NOTE===<br />
If object is not None, then align will create an object which indicates which atoms were paired between the two structures<br />
<br />
===EXAMPLES===<br />
<source lang="python"><br />
align prot1////CA, prot2, object=alignment<br />
</source><br />
<br />
===SEE ALSO===<br />
[[Cmd fit|fit]], [[Cmd rms|rms]], [[Cmd rms_cur|rms_cur]], [[Cmd intra_rms|intra_rms]], [[Cmd intra_rms_cur|intra_rms_cur]], [[Cmd pair_fit|pair_fit]]<br />
<br />
[[Category:Commands|align]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=DynoPlot&diff=1058DynoPlot2005-08-29T13:55:20Z<p>Tmwsiy: </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 />
[[Image:RamaPlotInitComposite.png|thumb|left|Initial Ramachandran plot of 1ENV]]<br />
[[Image:RamaPlotBentComposite.png|thumb|left|Modified pose and plot of 1ENV]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
===SETUP===<br />
place the DynoPlot.py script into PYMOL_PATH/modules/pmg_tk/startup/ , where PYMOL_PATH on Windows is defaulted to C:/Program Files/DeLano Scientific/PyMol/<br />
start/restart PyMol<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 (WFMesh.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 = 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 = 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 key,value in self.shapes.items():<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 self.shapes.has_key(spot[0]):<br />
print "Residue(Ca): %s\n" % str(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.shapes.has_key(self.item[0]):<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.shapes.has_key(self.item[0]):<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 not at.chain+":"+at.resn+":"+at.resi 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 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 />
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: "+str(value[3])+","+str(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 />
<br />
[[Category:Structural_Biology_Scripts|DynoPlot]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=DynoPlot&diff=1054DynoPlot2005-08-29T13:54:57Z<p>Tmwsiy: </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 />
[[Image:RamaPlotInitComposite.png|thumb|left|Initial Ramachandran plot of 1ENV]]<br />
[[Image:RamaPlotBentComposite.png|thumb|left|Modified pose and plot of 1ENV]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
===SETUP===<br />
place the DynoPlot.py script into PYMOL_PATH/modules/pmg_tk/startup/ , where PYMOL_PATH on Windows is defaulted to C:/Program Files/DeLano Scientific/PyMol/<br />
start/restart PyMol<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 (WFMesh.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 = 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 = 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 key,value in self.shapes.items():<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 self.shapes.has_key(spot[0]):<br />
print "Residue(Ca): %s\n" % str(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.shapes.has_key(self.item[0]):<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.shapes.has_key(self.item[0]):<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 not at.chain+":"+at.resn+":"+at.resi 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 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 />
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: "+str(value[3])+","+str(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 />
<br />
[[Category:Structural_Biology_Scripts|DynoPlot]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Main_Page&diff=1103Main Page2005-08-29T13:51:48Z<p>Tmwsiy: /* News */</p>
<hr />
<div>== PyMol Wiki Home ==<br />
You have reached the home of the PyMolWiki, a user-driven web-oriented CMS.<br />
<br />
We provide<br />
* updates on [http://pymol.sf.net PyMol]<br />
* a stable user-oriented documentation base<br />
* a thorough treatment of the PyMol program<br />
* feature-rich scripts for general PyMol use<br />
<br />
==News==<br />
* Added [[DynoPlot]] script for plotting data within PyMol; an interactive Ramachandran plot.<br />
* Added [[Kabsch]] script for optimal alignment of two sets of vectors.<br />
* Some details have been released about [[0.99beta11]]'s release and new features.<br />
* A new map function is in the beta build, [[Map_Trim]].<br />
* Details on how to build [[Peptide_Sequence| peptide sequences]] and [[Nucleic_Acid_Sequence| nucleic acid sequences]] by hand.<br />
* New [[Transform_odb]] script to transform coordinates with .odb file from O or LSQMAN<br />
<br />
<br />
See our [[Older_News]].<br />
<br />
== Links of Interest ==<br />
* [[TOPTOC|Top Level Table of Contents]]<br />
* [[:Category:FAQ|Frequently Asked Questions]] -- new!<br />
* [[PyMolWiki:Community_Portal| How to get involved!]] -- read me if you want to add something<br />
* [[:Category:Script Library| Script Library]] -- add one! (rTools info!)<br />
* [[:Category:Commands|PyMol Commands]] (>130 documented!)<br />
* [[:Special:Allpages| All Pages]]<br />
* [[:Category:Plugins|Plugins]]<br />
* [[:Special:Categories| See All Categories]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=DynoPlot&diff=1053DynoPlot2005-08-29T13:48:41Z<p>Tmwsiy: </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 />
[[Image:RamaPlotInitComposite.png|thumb|left|Initial Ramachandran plot of 1ENV]]<br />
[[Image:RamaPlotBentComposite.png|thumb|left|Modified pose and plot of 1ENV]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
===SETUP===<br />
place the DynoPlot.py script into PYMOL_PATH/modules/pmg_tk/startup/ , where PYMOL_PATH on Windows is defaulted to C:/Program Files/DeLano Scientific/PyMol/<br />
start/restart PyMol<br />
<br />
===NOTES / STATUS===<br />
Tested on Windows, PyMol version 0.97<br />
This is an initial version, which needs some work. <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 (WFMesh.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 = 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 = 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 key,value in self.shapes.items():<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 self.shapes.has_key(spot[0]):<br />
print "Residue(Ca): %s\n" % str(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.shapes.has_key(self.item[0]):<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.shapes.has_key(self.item[0]):<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 not at.chain+":"+at.resn+":"+at.resi 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 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 />
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: "+str(value[3])+","+str(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 />
<br />
[[Category:Structural_Biology_Scripts|DynoPlot]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=File:RamaPlotBentComposite.png&diff=3278File:RamaPlotBentComposite.png2005-08-29T13:47:01Z<p>Tmwsiy: A modified pose and plot of 1ENV</p>
<hr />
<div>A modified pose and plot of 1ENV</div>Tmwsiyhttps://pymolwiki.org/index.php?title=File:RamaPlotInitComposite.png&diff=3277File:RamaPlotInitComposite.png2005-08-29T13:45:32Z<p>Tmwsiy: Screenshot of initial ramachandran plot for 1ENV</p>
<hr />
<div>Screenshot of initial ramachandran plot for 1ENV</div>Tmwsiyhttps://pymolwiki.org/index.php?title=DynoPlot&diff=1051DynoPlot2005-08-29T13:27:56Z<p>Tmwsiy: </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 />
<br />
===SETUP===<br />
place the DynoPlot.py script into PYMOL_PATH/modules/pmg_tk/startup/ , where PYMOL_PATH on Windows is defaulted to C:/Program Files/DeLano Scientific/PyMol/<br />
start/restart PyMol<br />
<br />
===NOTES / STATUS===<br />
Tested on Windows, PyMol version 0.97<br />
This is an initial version, which needs some work. <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 (WFMesh.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 = 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 = 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 key,value in self.shapes.items():<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 self.shapes.has_key(spot[0]):<br />
print "Residue(Ca): %s\n" % str(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.shapes.has_key(self.item[0]):<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.shapes.has_key(self.item[0]):<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 not at.chain+":"+at.resn+":"+at.resi 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 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 />
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: "+str(value[3])+","+str(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 />
<br />
[[Category:Structural_Biology_Scripts|DynoPlot]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Category:Structural_Biology_Scripts&diff=1060Category:Structural Biology Scripts2005-08-29T13:26:46Z<p>Tmwsiy: </p>
<hr />
<div>This page is a sub-category of scripts for Structural Biology Applications.<br />
<br />
* [[Rotamer Toggle]] -- Toggle through the most common side chain rotamers and/or color by rotamer probability (Dunbrack's Backbone-depenedent library)<br />
* [[DynoPlot]] -- Generic dynamic plotting utility; Interactive Ramachandran Plots.<br />
<br />
[[Category:Script_Library]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=DynoPlot&diff=1050DynoPlot2005-08-29T13:25:28Z<p>Tmwsiy: </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 />
<br />
===SETUP===<br />
place the DynoPlot.py script into PYMOL_PATH/modules/pmg_tk/startup/ , where PYMOL_PATH on Windows is defaulted to C:/Program Files/DeLano Scientific/PyMol/<br />
start/restart PyMol<br />
<br />
===NOTES / STATUS===<br />
Tested on Windows, PyMol version 0.97<br />
This is an initial version, which needs some work. <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 (WFMesh.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 = 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 = 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 key,value in self.shapes.items():<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 self.shapes.has_key(spot[0]):<br />
print "Residue(Ca): %s\n" % str(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.shapes.has_key(self.item[0]):<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.shapes.has_key(self.item[0]):<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 not at.chain+":"+at.resn+":"+at.resi 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 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 />
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: "+str(value[3])+","+str(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]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Category:Structural_Biology_Scripts&diff=1049Category:Structural Biology Scripts2005-08-29T13:09:58Z<p>Tmwsiy: </p>
<hr />
<div>This page is a sub-category of scripts for Structural Biology Applications.<br />
<br />
* [[Dunbrack's Rotamers]] -- Toggle through the most common side chain rotamers and/or color by rotamer probability (Dunbrack's Backbone-depenedent library)<br />
* [[DynoPlot]] -- Generic dynamic plotting utility; Interactive Ramachandran Plots.<br />
<br />
[[Category:Script_Library]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=1059Rotamer Toggle2005-08-17T02:33:48Z<p>Tmwsiy: /* SCRIPTS (Rotamers.py ; MyMenu.py) */</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 />
===IMAGES===<br />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 />
Simply "import rotamers" and use the functions manually.<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 />
<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform and on Red Hat Linux 9.0. Will test v0.98 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 />
<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 />
<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 string<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], 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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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 />
<br />
<br />
readRotLib()<br />
<br />
cmd.extend('set_phipsi',set_phipsi)<br />
cmd.extend('set_rotamer',set_rotamer)<br />
cmd.extend('colorRotamers',colorRotamers)<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 />
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 />
</source><br />
<br />
<br />
[[Category:Script_Library|Rotamer Toggle]]<br />
<br />
[[Category:Structural_Biology_Scripts|Rotamer Toggle]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=1020Rotamer Toggle2005-08-17T02:33:12Z<p>Tmwsiy: /* SCRIPTS (Rotamers.py ; MyMenu.py) */</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 />
===IMAGES===<br />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 />
Simply "import rotamers" and use the functions manually.<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 />
<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform and on Red Hat Linux 9.0. Will test v0.98 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 />
<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 />
<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 string<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 />
CHIS["TRP"] = [ ["N","CA","CB","CG" ],<br />
["CA","CB","CG","CD1"]<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], 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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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 />
<br />
<br />
readRotLib()<br />
<br />
cmd.extend('set_phipsi',set_phipsi)<br />
cmd.extend('set_rotamer',set_rotamer)<br />
cmd.extend('colorRotamers',colorRotamers)<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 />
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 />
</source><br />
<br />
<br />
[[Category:Script_Library|Rotamer Toggle]]<br />
<br />
[[Category:Structural_Biology_Scripts|Rotamer Toggle]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Category:Structural_Biology_Scripts&diff=1048Category:Structural Biology Scripts2005-08-17T02:29:59Z<p>Tmwsiy: </p>
<hr />
<div>This page is a sub-category of scripts for Structural Biology Applications.<br />
<br />
* [[Rotamer Toggle]] -- Toggle through the most common side chain rotamers (Dunbrack's Backbone-depenedent library)<br />
<br />
[[Category:Script_Library]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=1019Rotamer Toggle2005-05-23T15:04:31Z<p>Tmwsiy: </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 />
===IMAGES===<br />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 />
Simply "import rotamers" and use the functions manually.<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 />
<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform and on Red Hat Linux 9.0. Will test v0.98 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 />
<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 />
<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 string<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","CG" ]<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 />
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], 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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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 />
<br />
<br />
readRotLib()<br />
<br />
cmd.extend('set_phipsi',set_phipsi)<br />
cmd.extend('set_rotamer',set_rotamer)<br />
cmd.extend('colorRotamers',colorRotamers)<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 />
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 />
</source><br />
<br />
<br />
[[Category:Script_Library|Rotamer Toggle]]<br />
<br />
[[Category:Structural_Biology_Scripts|Rotamer Toggle]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Get_Model&diff=1275Get Model2005-05-19T14:54:43Z<p>Tmwsiy: </p>
<hr />
<div>===DESCRIPTION===<br />
"get_model" returns a model object.<br />
<br />
===PYMOL API===<br />
<source lang="python"><br />
cmd.get_model(string "selection" )<br />
</source><br />
<br />
===USAGE===<br />
cmd.get_model("chain A")<br />
<br />
===NOTES===<br />
It can be useful to loop through all the atoms of a selection (rather than using the iterate command)<br />
<source lang="python"><br />
atoms = cmd.get_model("chain A")<br />
for at in atoms.atom:<br />
print "ATOM DEFINITION: "+at.chain+" "+at.resn+" "+str(at.resi)+" "+at.name+" "+str(at.index)<br />
</source><br />
<br />
===SEE ALSO===<br />
<br />
[[Category:Commands|get_model]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Get_Model&diff=830Get Model2005-05-19T14:54:17Z<p>Tmwsiy: </p>
<hr />
<div>===DESCRIPTION===<br />
"get_model" returns a model object.<br />
<br />
===PYMOL API===<br />
<source lang="python"><br />
cmd.get_model(string "selection" )<br />
</source><br />
<br />
===USAGE===<br />
cmd.get_model("chain A")<br />
<br />
===NOTES===<br />
It can be useful to loop through all the atoms of a selection (rather than using the iterate command)<br />
<br />
atoms = cmd.get_model("chain A")<br />
for at in atoms.atom:<br />
print "ATOM DEFINITION: "+at.chain+" "+at.resn+" "+str(at.resi)+" "+at.name+" "+str(at.index)<br />
<br />
<br />
===SEE ALSO===<br />
<br />
[[Category:Commands|get_model]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Get_Model&diff=829Get Model2005-05-19T14:54:00Z<p>Tmwsiy: </p>
<hr />
<div>===DESCRIPTION===<br />
"get_model" returns a model object.<br />
<br />
===PYMOL API===<br />
<source lang="python"><br />
cmd.get_model( [string: "selection"] )<br />
</source><br />
<br />
===USAGE===<br />
cmd.get_model("chain A")<br />
<br />
===NOTES===<br />
It can be useful to loop through all the atoms of a selection (rather than using the iterate command)<br />
<br />
atoms = cmd.get_model("chain A")<br />
for at in atoms.atom:<br />
print "ATOM DEFINITION: "+at.chain+" "+at.resn+" "+str(at.resi)+" "+at.name+" "+str(at.index)<br />
<br />
<br />
===SEE ALSO===<br />
<br />
[[Category:Commands|get_model]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Rotamer_Toggle&diff=833Rotamer Toggle2005-05-17T20:23:16Z<p>Tmwsiy: </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 />
===IMAGES===<br />
[[Image:RotamerMenu.png|thumb|left|Rotamer Menu for a GLN residue]]<br />
[[Image:GLURotamerComparison5.png|thumb|left|Rotamer Comparison of crystal structure and most common for GLU; just as an example]]<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<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 />
Simply "import rotamers" and use the functions manually.<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 />
<br />
<br />
===NOTES / STATUS===<br />
*Tested on Pymolv0.97, Windows platform and on Red Hat Linux 9.0. Will test v0.98 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 />
*Rotamer Movie, using mset, etc create movie to watch cycle through rotamers<br />
*Store crystal structure in rotamer menu, so you can go back to original orientation<br />
*Code could be organized a bit better; due to time constraints this is good for 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 />
colorRotamers selection<br />
set_rotamer selection, chi1_angle [,chi2_angle] [,chi3_angle] [,chi4_angle]<br />
set_phipsi selection phi_angle, psi_angle<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 />
<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 string<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","CG" ]<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 />
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], 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 />
phi = cmd.get_dihedral(residue_def+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C')<br />
psi = cmd.get_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB')<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+' and name CB',residue_def+' and name CA',residue_def+' and name N',residue_def_prev+' and name C',angles[0])<br />
cmd.set_dihedral(residue_def+' and name O',residue_def+' and name C',residue_def+' and name CA',residue_def+' and name CB', 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 />
<br />
<br />
readRotLib()<br />
<br />
cmd.extend('set_phipsi',set_phipsi)<br />
cmd.extend('set_rotamer',set_rotamer)<br />
cmd.extend('colorRotamers',colorRotamers)<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 />
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 />
</source><br />
<br />
<br />
[[Category:Script_Library|Rotamer Toggle]]<br />
<br />
[[Category:Structural_Biology_Scripts|Rotamer Toggle]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Wfmesh&diff=2968Wfmesh2005-05-17T03:35:59Z<p>Tmwsiy: </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 />
<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 string<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>Tmwsiyhttps://pymolwiki.org/index.php?title=File:Torus.zip&diff=3232File:Torus.zip2005-05-17T03:33:37Z<p>Tmwsiy: </p>
<hr />
<div></div>Tmwsiyhttps://pymolwiki.org/index.php?title=Wfmesh&diff=827Wfmesh2005-05-16T17:38:38Z<p>Tmwsiy: </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 />
<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 string<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 />
Once I figure out how to add files besides images I'll upload this file for demo purposes.<br />
<br />
[[Category:Script_Library|WFMesh]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=User_talk:Tree&diff=1483User talk:Tree2005-05-16T17:36:57Z<p>Tmwsiy: </p>
<hr />
<div>Testing...<br />
<br />
Jason,<br />
I fixed the url for my webpage, thanks for the catch. Is this where I am suppose to post responses ?<br />
<br />
http://dwkulp.homelinux.net/tiki/tiki-index.php<br />
<br />
~Dan<br />
<br />
------------<br />
<br />
Jason,<br />
I was wondering how I could upload other files besides images. When I tried to upload a file with .obj or .txt extension I got a message saying that the file was a bad image format. Do you know anything about this? <br />
~Dan</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Wfmesh&diff=819Wfmesh2005-05-16T13:16:17Z<p>Tmwsiy: </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 />
<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 "torus.obj" "Torus" translate=[10,10,0] flip=1 # Flip = 1, if OBJ created by openFX, crossroads3D combination<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 string<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 />
Once I figure out how to add files besides images I'll upload this file for demo purposes.<br />
<br />
[[Category:Script_Library|WFMesh]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Category:Script_Library&diff=837Category:Script Library2005-05-16T12:59:42Z<p>Tmwsiy: </p>
<hr />
<div>* [[Show aromatics]] -- This script will display a backbone "worm" for your protein, with all of the sidechains for aromatic residues displayed as green "sticks". Usage: Save this as "show_aromatics.pml", load your protein in PyMOL, and run the script (select "Run" from the "File" menu). (PyMOL script; TStout)<br />
<br />
* [[Show hydrophobics]] -- This script will display a backbone "worm" for your protein, with all of the sidechains for hydrophobic residues displayed as orange "sticks". Usage: Same as "show aromatics". (PyMOL script; TStout)<br />
<br />
* [[Show charged]] -- This script will display a backbone "worm" for your protein, with all of the sidechains for charged residues displayed as red (negative) or blue (posititve) "sticks". Usage: Same as "show aromatics". (PyMOL script; TStout)<br />
<br />
* [[Show hydrophilic]] -- This script will display a backbone "worm" for your protein, with all of the sidechains for hydrophilic residues displayed as green "sticks". Usage: Same as "show aromatics". (PyMOL script; TStout)<br />
<br />
* [[Perp Maker]] -- Creates a perpendicular plane through the center of your protein with respect to the camera's current position. (If you translate the protein towards the camera a bit, you get a nice surface, sometimes.) A stupid little script I wrote in response to a request a few months ago (and it doesn't even conform to the request!) Load a protein, run the script (read the documentation in the script). (Jason Vertrees/[[User:Tree|Tree]])<br />
<br />
* [[Axes]] -- Creates a 3D-CGO object that shows the three coordinate axes.<br />
<br />
* [[CGO Text]] -- Creates a 3D-CGO text object.<br />
<br />
* [[List Selection]] -- Prints a list of all residues in a selection (both Python and .pml).<br />
<br />
* [[List Colors]] -- Lists the color of all residues in a selection (both Python and .pml).<br />
<br />
* [[List Secondary Structures]] -- Secondary structures (both predefined and those calculated with the 'dss' command) can be exported as a long string ('HHHHLLLLSSS').<br />
<br />
* [[Split Movement]] -- Moves two parts of one object into different directions.<br />
<br />
* [[Selection Exists]] -- Python method that returns true if a selection of a given name exists.<br />
<br />
* [[Get Coordinates I]] -- Retrieves atom coordinates as Python objects.<br />
<br />
* [[Get Coordinates II]] -- Retrieves atom coordinates as Python array (list object).<br />
<br />
* [[grepset]] -- List all settings matching a given keyword.<br />
<br />
* [[Measure Distance]] -- Measures the distance between two atoms (Python script).<br />
<br />
* [[Read PDB-String]] -- Parses a string in PDB format to a PyMOL object.<br />
<br />
* [[Color Objects]] -- Colors all objects differently (Python script).<br />
<br />
* [[Key Wait]] -- Process key events in a Python script.<br />
<br />
* [[Bounding Box]] -- Create a bounding box around a selection (Python script; requires numarray and Scientific; gilleain)<br />
<br />
* [[pdbsurvey]] -- Surveys the pdb for recently added structures that are relevant to a user-specified keywords list (in a text file)<br />
<br />
* [[TransformSelectionByCameraView]] -- Transforms the selection by the camera view.<br />
<br />
* [[WFMesh]] -- Imports wavefront object mesh files; Starwars as an example!<br />
<br />
[[Category:Scripting|Script Library]]</div>Tmwsiyhttps://pymolwiki.org/index.php?title=Category:Script_Library&diff=805Category:Script Library2005-05-16T12:54:22Z<p>Tmwsiy: </p>
<hr />
<div>* [[Show aromatics]] -- This script will display a backbone "worm" for your protein, with all of the sidechains for aromatic residues displayed as green "sticks". Usage: Save this as "show_aromatics.pml", load your protein in PyMOL, and run the script (select "Run" from the "File" menu). (PyMOL script; TStout)<br />
<br />
* [[Show hydrophobics]] -- This script will display a backbone "worm" for your protein, with all of the sidechains for hydrophobic residues displayed as orange "sticks". Usage: Same as "show aromatics". (PyMOL script; TStout)<br />
<br />
* [[Show charged]] -- This script will display a backbone "worm" for your protein, with all of the sidechains for charged residues displayed as red (negative) or blue (posititve) "sticks". Usage: Same as "show aromatics". (PyMOL script; TStout)<br />
<br />
* [[Show hydrophilic]] -- This script will display a backbone "worm" for your protein, with all of the sidechains for hydrophilic residues displayed as green "sticks". Usage: Same as "show aromatics". (PyMOL script; TStout)<br />
<br />
* [[Perp Maker]] -- Creates a perpendicular plane through the center of your protein with respect to the camera's current position. (If you translate the protein towards the camera a bit, you get a nice surface, sometimes.) A stupid little script I wrote in response to a request a few months ago (and it doesn't even conform to the request!) Load a protein, run the script (read the documentation in the script). (Jason Vertrees/[[User:Tree|Tree]])<br />
<br />
* [[Axes]] -- Creates a 3D-CGO object that shows the three coordinate axes.<br />
<br />
* [[CGO Text]] -- Creates a 3D-CGO text object.<br />
<br />
* [[List Selection]] -- Prints a list of all residues in a selection (both Python and .pml).<br />
<br />
* [[List Colors]] -- Lists the color of all residues in a selection (both Python and .pml).<br />
<br />
* [[List Secondary Structures]] -- Secondary structures (both predefined and those calculated with the 'dss' command) can be exported as a long string ('HHHHLLLLSSS').<br />
<br />
* [[Split Movement]] -- Moves two parts of one object into different directions.<br />
<br />
* [[Selection Exists]] -- Python method that returns true if a selection of a given name exists.<br />
<br />
* [[Get Coordinates I]] -- Retrieves atom coordinates as Python objects.<br />
<br />
* [[Get Coordinates II]] -- Retrieves atom coordinates as Python array (list object).<br />
<br />
* [[grepset]] -- List all settings matching a given keyword.<br />
<br />
* [[Measure Distance]] -- Measures the distance between two atoms (Python script).<br />
<br />
* [[Read PDB-String]] -- Parses a string in PDB format to a PyMOL object.<br />
<br />
* [[Color Objects]] -- Colors all objects differently (Python script).<br />
<br />
* [[Key Wait]] -- Process key events in a Python script.<br />
<br />
* [[Bounding Box]] -- Create a bounding box around a selection (Python script; requires numarray and Scientific; gilleain)<br />
<br />
* [[pdbsurvey]] -- Surveys the pdb for recently added structures that are relevant to a user-specified keywords list (in a text file)<br />
<br />
* [[TransformSelectionByCameraView]] -- Transforms the selection by the camera view.<br />
<br />
* [[WFMesh]] -- Allow import of wavefront object mesh files; Starwars as an example!<br />
<br />
[[Category:Scripting|Script Library]]</div>Tmwsiy