From PyMOLWiki
Jump to: navigation, search


AutoMultiFit will fit all given chain(s) in all given state(s) to any other given chain(s) in any other given state(s) for some given selection within a homo-oligomer. So, if you have an MD trajectory or NMR ensemble of a tertramer, for example, over 20 states this program could calculate the RMS values for residues 10-30 in chain A's state 17, against all of chain C. Or all states in all chains against each other.

See the notes in the code for usage.

The Code

# -- Given a homo-oligomer in N-states, fit any combination of chains across states
# AUTHOR: Jason Vertrees
# DATE  : 2009-11-02
import pymol
from pymol import cmd

def autoMultiFit(sel, fromChain="*", fromState="*", toChain="*", toState="*", verbose=None):
      Given a homo-oligomer in N-states (say from MD), fit any
      combination of chains/selections across states. See Usage, Examples and Notes.

      autoMultiFit sel, [fromChain[, fromState[, toChain[, toState[, verbose ]]]]]

        The selection that must exist in all chains (what you're fitting)

        Fit from this chain, leave blank or use '*' for all chains;

        Fit from this state, leave blank or use '*' for all states;

        Fit to this chain only, use '*' or leave blank for all chains;

        Fit to this state only, use '*' or leave blank for all states

        If turned on, this prints the fit for all pairs; this could be VERY slow.

      A hash of hashes of hashes of hashes. :-)  Access the results like this:
      fitValues = autoMultiFit( mySelection )
      # to get the result of the fit from chain A, state 4 to chain C, state 17 type,
      * Fit ALL chains to each other across ALL STATES for PDB 2kb1
      autoMultiFit 2kb1

      * Fit chain A's residue 22-34 against all states
      autoMutliFit 2kb1 and i. 22-34, fromChain=A

      * Fit chain A, B and C's residues 8-17, states 10 and 11, against chain D's state 8
      myVals = autoMultiFit("2kb1 and i. 8-17", fromChain="a b c", fromState="10 11", toChain="d", toState=8)

        * The return value uses UPPERCASE and STRINGS for ALL hash keys, so if you used chain 'a' it will
          be 'A' in the map; if you used 'chainXX' it will be 'CHAINXX' in the map.
        * Continuing from the above note, all statese are accessible by their strings, so '17' gets state
          17 from the hash, not just the number 17.
        * This can be very slow: it's O( nFromChains * nFromStates * nToChains * nToStates )
        * fromChain, toChain, fromStates and toStates can all be single values, like "8", they can be a SPACE
          separated list of values, like "2 4 5", or they can be "*" which means ALL.

    fromChain = processChain(fromChain,sel)
    fromState = processState(fromState, sel)
    toChain   = processChain(toChain, sel)
    toState   = processState(toState, sel)

    res = {}

    for frC in fromChain:
        res[frC] = {}
        for frS in fromState:
            res[frC][str(frS)] = {}
            cmd.create( "__tmpA", sel + " and c. " + frC, frS, 1 )
            for toC in toChain:
                res[frC][str(frS)][toC] = {}
                for toS in toState:
                    cmd.create("__tmpB", sel + " and c. " + toC, toS, 1 )
                    curVal = cmd.pair_fit( "__tmpA", "__tmpB", quiet=1 )
                    res[frC][str(frS)][toC][str(toS)] = curVal
                    if verbose!=None:
                        print "Pair Fitted: from (chain: %s, state: %s) to (chain: %s, states %s) with RMSD %s" % (frC, frS, toC, toS, curVal)
    return res

def processChain(ch, sel):
    """Turn a string-based space separated list into an array of chains"""
    if ch == "*":
        # just in case
        return map(str.upper, cmd.get_chains(sel))
        return map(str.upper, processTextList(ch))

def processState(st, sel):
    """Tur a string-based space separated list into an array of states"""
    if st == "*":
        # assumes that if there is a state X, there is a state, X-1
        return range(cmd.count_states(sel))
        return map(int, processTextList(st))

def processTextList(t):
    """ make a space-separated list into a real Python list, eg.
    input: a b c d
    output: [ 'a', 'b', 'c', 'd' ]
    t = str(t).split()
    return t

if __name__ == "__main__":
    assert processTextList( "a b c d" ) == ['a', 'b', 'c', 'd']
    assert processTextList( " 1 45 s s s s j p k") == [ '1', '45', 's', 's', 's', 's', 'j', 'p', 'k' ]

    assert processChain( "a b c dd", "blankSel" ) == ["a", "b", "c", "dd"]
    assert processState( "1 2 3 44 5", "blankSel" ) == [ 1, 2, 3, 44, 5 ]

cmd.extend( "autoMultiFit", autoMultiFit )