Hi PyMol-Community,

I have been looking for a PyMOL command to calculate the ribose sugar pucker 
information (in DNA) but have not found anything.  Thus, I began writing a 
simple Python script that is supposed to take a selection, determine whether or 
not it contains a ribose sugar ring, and then calculate the phase, amplitude, 
and pucker orientation for each nucleotide residue within the selection.  The 
completed script works just fine (see the script below) but it slows down 
significantly in performance when calling cmd.get_dihedral (at least, my crude 
debugging method using print statements has identified the culprit to be the 
get_dihedral command) with a LARGE protein-DNA complex (160,000 atoms) loaded.  
However, if I only load the DNA (with no protein), the performance is lightning 
fast.  Can anybody help me improve the overall performance or suggest an 
alternative?  Thanks in advance!

Sean




=========================================================

from pymol.cgo import *    # get constants
from math import *
from pymol import cmd

def pucker(selection):

    # Author: Sean Law
    # Institute: Michigan State University
    # E-mail: s...@msu.edu
    
    obj_name = selection
    objects = cmd.get_names(selection)
    for obj in objects:
        if (obj == selection):
            obj_name=obj
    sel=cmd.get_model(selection)
    first=1
    old=" "
    oldchain=" "
    residue={}
    count=0
    for atom in sel.atom:
        new=atom.chain+" "+str(atom.resi)
        newchain=atom.chain+" "+atom.segi
        if (not (oldchain == newchain) and first):
            print " " #Blank line to separate chain output
            print "%6s  %6s  %8s  Residue" % ("Phase", "Amp", "Pucker")
        if (not(new == old) and (not first)):
            #Check that all 5 atoms exist
            if(len(residue) == 5):
                #Calculate pucker
                info = pseudo(residue)
                print info+"  "+old
            else:
                print "There is no sugar in this residue"
            if (not (oldchain == newchain)):
                print " " #Blank line to separate chain output
                print "%6s  %6s  %8s  Residue" % ("Phase", "Amp", "Pucker")
            #Clear values
            residue={}
            #Store new value
            store_atom(atom,residue,obj_name)
        else:
            store_atom(atom,residue,obj_name)
        first=0
        old=new
        oldchain=newchain
    #Final Residue
    #Calculate dihedrals for final residue
    if (len(residue) == 5):
        #Calculate pucker for final residue
        info = pseudo(residue)
        print info+"  "+old
    else:
        print "There is no sugar in this residue"
    return

def sele_exists(sele):
    return sele in cmd.get_names("selections");

def pseudo(residue):
    other=2*(sin(math.radians(36.0))+sin(math.radians(72.0)))
    
theta0=cmd.get_dihedral(residue['C4*'],residue['O4*'],residue['C1*'],residue['C2*'])
    
theta1=cmd.get_dihedral(residue['O4*'],residue['C1*'],residue['C2*'],residue['C3*'])
    
theta2=cmd.get_dihedral(residue['C1*'],residue['C2*'],residue['C3*'],residue['C4*'])
    
theta3=cmd.get_dihedral(residue['C2*'],residue['C3*'],residue['C4*'],residue['O4*'])
    
theta4=cmd.get_dihedral(residue['C3*'],residue['C4*'],residue['O4*'],residue['C1*'])
    
#phase=atan2((theta4+theta1)-(theta3+theta0),2*theta2*(sin(math.radians(36.0))+sin(math.radians(72.0))))
    phase=atan2((theta4+theta1)-(theta3+theta0),theta2*other)
    amplitude=theta2/cos(phase)
    phase=math.degrees(phase)
    if (phase < 0):
        phase=phase+360 # 0 <= Phase < 360
    #Determine pucker
    if (phase < 36):
        pucker = "C3'-endo"
    elif (phase < 72):
        pucker = "C4'-exo"
    elif (phase <108):
        pucker = "O4'-endo"
    elif (phase < 144):
        pucker = "C1'-exo"
    elif (phase < 180):
        pucker = "C2'-endo"
    elif (phase < 216):
        pucker = "C3'-exo"
    elif (phase < 252):
        pucker = "C4'-endo"
    elif (phase < 288):
        pucker = "O4'-exo"
    elif (phase < 324):
        pucker = "C1'-endo"
    elif (phase < 360):
        pucker = "C2'-exo"
    else:
        pucker = "Phase is out of range"
    info = "%6.2f  %6.2f  %8s" % (phase, amplitude, pucker)
    return info
    

def store_atom(atom,residue,obj_name):
    if (atom.name == "O4'" or atom.name == "O4*"):
        residue['O4*'] = str(atom_sele(atom,obj_name))
    elif (atom.name == "C1'" or atom.name == "C1*"):
        residue['C1*'] = str(atom_sele(atom,obj_name))
    elif (atom.name == "C2'" or atom.name == "C2*"):
        residue['C2*'] = str(atom_sele(atom,obj_name))
    elif (atom.name == "C3'" or atom.name == "C3*"):
        residue['C3*'] = str(atom_sele(atom,obj_name))
    elif (atom.name == "C4'" or atom.name == "C4*"):
        residue['C4*'] = str(atom_sele(atom,obj_name))
    return

def atom_sele(atom,obj_name):
    atom_sele = ""
    if (not (obj_name == "")):
        atom_sele = atom_sele+obj_name+" & "
           if (not (atom.segi == "")):
        atom_sele = atom_sele+"segi "+atom.segi+" & "
           if (not (atom.chain == "")):
        atom_sele = atom_sele+"chain "+atom.chain+" & "
    if (not (atom.resn == "")):
        atom_sele = atom_sele+"resn "+atom.resn+" & "
    if (not (atom.resi == "")):
        atom_sele = atom_sele+"resi "+str(atom.resi)+" & "
    if (not (atom.name == "")):
        atom_sele = atom_sele+"name "+atom.name
    return atom_sele

cmd.extend("pucker",pucker)

_________________________________________________________________
Reinvent how you stay in touch with the new Windows Live Messenger.
http://go.microsoft.com/?linkid=9650731

Reply via email to