Sean,

get_dihedral is expensive because, in the general case, it requires evaluation 
of four atom selections - a process which is essentially order N with respect 
to the number of atoms currently loaded inside PyMOL.

As you've discovered, the easiest way to optimize performance is therefore to 
minimize the number of atoms present in PyMOL by removing all uninvolved atoms.

We are working on ways of improving selection performance, at least one of 
which will be present in 1.2 (the "domain" argument to the select command). 

Cheers,
Warren
________________________________________
From: Sean Law [mailto:magic...@hotmail.com] 
Sent: Tuesday, March 31, 2009 1:48 PM
To: pymol-users@lists.sourceforge.net
Subject: [PyMOL] get_dihedral bottleneck

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)
________________________________________
Communicate, update and plan on Windows Live Messenger. Get started today.


Reply via email to