Exemple #1
0
    def _get_pam5_strand_atoms_in_bond_direction(self, inputAtomList = ()): 
        """
        Return a list of sugar atoms in a fixed direction -- from 5' to 3'
        
        @param inputAtomList: An optional argument. If its not provided, this
               method will return a list of all atoms within the strand, 
               in the strand's bond direction. Otherwise, it will just return 
               the list <inputAtomList> whose atoms are ordered in the strand's
               bond direction. 
        @type inputAtomList: list  (with default value as an empty tuple)

        @note: this is a stub and we can modify it so that
        it can accept other direction i.e. 3' to 5' , as an argument.

        [I think at most one atom at each end can be a bondpoint,
         so we could revise this code to remove them before returning.
         bruce 080205]

        piotr 080411: This is a helper method for  
        'get_strand_atoms_in_bond_direction'. It is called for PAM5
        models and should be replaced by a properly modified caller method.
        Only bondpoints ('X') and sugar atoms ('Ss3', Ss5') are preserved.

        @warning: for a ring, this uses an arbitrary start atom in self
                  (so it is not yet useful in that case). ### VERIFY

        @note: this would return all atoms from an entire strand (chain or ring)
               even if it spanned multiple chunks.

        @TODO:  THIS method is copied over from chunk class. with a minor modification
        To be revised. See self.getStrandSequence() for a comment. 
        """ 
        startAtom = None
        atomList = []
        
        rawAtomList = []
        if inputAtomList:
            rawAtomList = inputAtomList
        else:
            for c in self.members:
                if isinstance(c, DnaStrandChunk):
                    rawAtomList.extend(c.atoms.itervalues())
                    

        #Choose startAtom randomly (make sure that it's a Sugar atom 
        # and not a bondpoint)
        for atm in rawAtomList:
            if atm.element.symbol == 'Ss3' or \
               atm.element.symbol == 'Ss5':
                startAtom = atm
                break        

        if startAtom is None:
            print_compact_stack("bug: no Sugar atom (Ss3 or Ss5) found: " )
            return []

        #Build one list in each direction, detecting a ring too 

        #ringQ decides whether the first returned list forms a ring. 
        #This needs a better name in bond_chains.grow_directional_bond_chain
        ringQ = False        
        atomList_direction_1 = []
        atomList_direction_2 = []     

        b = None  
        bond_direction = 0
        for bnd in startAtom.directional_bonds():
            if not bnd.is_open_bond(): # (this assumes strand length > 1)
                #Determine the bond_direction from the 'startAtom'
                direction = bnd.bond_direction_from(startAtom)
                if direction in (1, -1):                    
                    b = bnd
                    bond_direction = direction
                    break

        if b is None or bond_direction == 0:
            return []         

        #Find out the list of new atoms and bonds in the direction 
        #from bond b towards 'startAtom' . This can either be 3' to 5' direction 
        #(i.e. bond_direction = -1 OR the reverse direction 
        # Later, we will check  the bond direction and do appropriate things. 
        #(things that will decide which list (atomList_direction_1 or 
        #atomList_direction_2) should  be prepended in atomList so that it has 
        #atoms ordered from 5' to 3' end. 

        # 'atomList_direction_1' does NOT include 'startAtom'.
        # See a detailed explanation below on how atomList_direction_a will be 
        # used, based on bond_direction
        ringQ, listb, atomList_direction_1 = grow_directional_bond_chain(b, startAtom)

        del listb # don't need list of bonds

        if ringQ:
            # The 'ringQ' returns True So its it's a 'ring'.
            #First add 'startAtom' (as its not included in atomList_direction_1)
            atomList.append(startAtom)
            #extend atomList with remaining atoms
            atomList.extend(atomList_direction_1)            
        else:       
            #Its not a ring. Now we need to make sure to include atoms in the 
            #direction_2 (if any) from the 'startAtom' . i.e. we need to grow 
            #the directional bond chain in the opposite direction. 

            other_atom = b.other(startAtom)
            if not other_atom.is_singlet():  
                ringQ, listb, atomList_direction_2 = grow_directional_bond_chain(b, other_atom)
                assert not ringQ #bruce 080205
                del listb
                #See a detailed explanation below on how 
                #atomList_direction_2 will be used based on 'bond_direction'
                atomList_direction_2.insert(0, other_atom)

            atomList = [] # not needed but just to be on a safer side.

            if bond_direction == 1:
                # 'bond_direction' is the direction *away from* startAtom and 
                # along the bond 'b' declared above. . 

                # This can be represented by the following sketch --
                # (3'end) <--1 <-- 2 <-- 3 <-- 4 <-- (5' end)

                # Let startAtom be '2' and bond 'b' be directional bond between 
                # 1 and 2. In this case, the direction of bond *away* from 
                # '2' and along 2  = bond direction of bond 'b' and thus 
                # atoms traversed along bond_direction = 1 lead us to 3' end. 

                # Now, 'atomList_direction_1'  is computed by 'growing' (expanding)
                # a bond chain  in the direction that goes from bond b 
                # *towards* startAtom. That is, in this case it is the opposite 
                # direction of one specified by 'bond_direction'.  The last atom
                # in atomList_direction_1 is the (5' end) atom.
                # Note that atomList_direction_1 doesn't include 'startAtom'
                # Therefore, to get atomList ordered from 5'to 3' end we must
                #reverse atomList_direction_1 , then append startAtom to the 
                #atomList (as its not included in atomList_direction_1) and then 
                #extend atoms from atomList_direction_2. 

                #What is atomList_direction_2 ?  It is the list of atoms 
                #obtained by growing bond chain from bond b, in the direction of 
                #atom 1 (atom 1 is the 'other atom' of the bond) . In this case 
                #these are the atoms in the direction same as 'bond_direction'
                #starting from atom 1. Thus the atoms in the list are already 
                #arranged from 5' to 3' end. (also note that after computing 
                #the atomList_direction_2, we also prepend 'atom 1' as the 
                #first atom in that list. See the code above that does that.                 
                atomList_direction_1.reverse()                
                atomList.extend(atomList_direction_1)
                atomList.append(startAtom)
                atomList.extend(atomList_direction_2)                

            else:     
                #See a detailed explanation above. 
                #Here, bond_direction == -1. 

                # This can be represented by the following sketch --
                # (5'end) --> 1 --> 2 --> 3 --> 4 --> (3' end)

                #bond b is the bond betweern atoms 1 and 2. 
                #startAtom remains the same ..i.e. atom 2. 

                #As you can notice from the sketch, the bond_direction is 
                #direction *away* from 2, along bond b and it leads us to 
                # 5' end. 

                #based on how atomList_direction_2 (explained earlier), it now 
                #includes atoms begining at 1 and ending at 5' end. So 
                #we must reverse atomList_direction_2 now to arrange them 
                #from 5' to 3' end. 
                atomList_direction_2.reverse()
                atomList.extend(atomList_direction_2)
                atomList.append(startAtom)
                atomList.extend(atomList_direction_1)

        # Note: the bondpoint atoms are NOT included.
        # ONLY consecutive sugar stoms are returned.
        # piotr 080411

        # extract only sugar atoms or bondpoints
        # the bondpoints are extracted to make the method compatible
        # with get_strand_atoms_in_bond_direction
        def filter_sugars(atm):
            return atm.element.symbol == 'Ss3' or \
                   atm.element.symbol == 'Ss5' or \
                   atm.element.symbol == 'X'

        atomList = filter(filter_sugars, atomList)
        return atomList   
    def _get_pam5_strand_atoms_in_bond_direction(self, inputAtomList=()):
        """
        Return a list of sugar atoms in a fixed direction -- from 5' to 3'
        
        @param inputAtomList: An optional argument. If its not provided, this
               method will return a list of all atoms within the strand, 
               in the strand's bond direction. Otherwise, it will just return 
               the list <inputAtomList> whose atoms are ordered in the strand's
               bond direction. 
        @type inputAtomList: list  (with default value as an empty tuple)

        @note: this is a stub and we can modify it so that
        it can accept other direction i.e. 3' to 5' , as an argument.

        [I think at most one atom at each end can be a bondpoint,
         so we could revise this code to remove them before returning.
         bruce 080205]

        piotr 080411: This is a helper method for  
        'get_strand_atoms_in_bond_direction'. It is called for PAM5
        models and should be replaced by a properly modified caller method.
        Only bondpoints ('X') and sugar atoms ('Ss3', Ss5') are preserved.

        @warning: for a ring, this uses an arbitrary start atom in self
                  (so it is not yet useful in that case). ### VERIFY

        @note: this would return all atoms from an entire strand (chain or ring)
               even if it spanned multiple chunks.

        @TODO:  THIS method is copied over from chunk class. with a minor modification
        To be revised. See self.getStrandSequence() for a comment. 
        """
        startAtom = None
        atomList = []

        rawAtomList = []
        if inputAtomList:
            rawAtomList = inputAtomList
        else:
            for c in self.members:
                if isinstance(c, DnaStrandChunk):
                    rawAtomList.extend(c.atoms.itervalues())

        #Choose startAtom randomly (make sure that it's a Sugar atom
        # and not a bondpoint)
        for atm in rawAtomList:
            if atm.element.symbol == 'Ss3' or \
               atm.element.symbol == 'Ss5':
                startAtom = atm
                break

        if startAtom is None:
            print_compact_stack("bug: no Sugar atom (Ss3 or Ss5) found: ")
            return []

        #Build one list in each direction, detecting a ring too

        #ringQ decides whether the first returned list forms a ring.
        #This needs a better name in bond_chains.grow_directional_bond_chain
        ringQ = False
        atomList_direction_1 = []
        atomList_direction_2 = []

        b = None
        bond_direction = 0
        for bnd in startAtom.directional_bonds():
            if not bnd.is_open_bond():  # (this assumes strand length > 1)
                #Determine the bond_direction from the 'startAtom'
                direction = bnd.bond_direction_from(startAtom)
                if direction in (1, -1):
                    b = bnd
                    bond_direction = direction
                    break

        if b is None or bond_direction == 0:
            return []

        #Find out the list of new atoms and bonds in the direction
        #from bond b towards 'startAtom' . This can either be 3' to 5' direction
        #(i.e. bond_direction = -1 OR the reverse direction
        # Later, we will check  the bond direction and do appropriate things.
        #(things that will decide which list (atomList_direction_1 or
        #atomList_direction_2) should  be prepended in atomList so that it has
        #atoms ordered from 5' to 3' end.

        # 'atomList_direction_1' does NOT include 'startAtom'.
        # See a detailed explanation below on how atomList_direction_a will be
        # used, based on bond_direction
        ringQ, listb, atomList_direction_1 = grow_directional_bond_chain(
            b, startAtom)

        del listb  # don't need list of bonds

        if ringQ:
            # The 'ringQ' returns True So its it's a 'ring'.
            #First add 'startAtom' (as its not included in atomList_direction_1)
            atomList.append(startAtom)
            #extend atomList with remaining atoms
            atomList.extend(atomList_direction_1)
        else:
            #Its not a ring. Now we need to make sure to include atoms in the
            #direction_2 (if any) from the 'startAtom' . i.e. we need to grow
            #the directional bond chain in the opposite direction.

            other_atom = b.other(startAtom)
            if not other_atom.is_singlet():
                ringQ, listb, atomList_direction_2 = grow_directional_bond_chain(
                    b, other_atom)
                assert not ringQ  #bruce 080205
                del listb
                #See a detailed explanation below on how
                #atomList_direction_2 will be used based on 'bond_direction'
                atomList_direction_2.insert(0, other_atom)

            atomList = []  # not needed but just to be on a safer side.

            if bond_direction == 1:
                # 'bond_direction' is the direction *away from* startAtom and
                # along the bond 'b' declared above. .

                # This can be represented by the following sketch --
                # (3'end) <--1 <-- 2 <-- 3 <-- 4 <-- (5' end)

                # Let startAtom be '2' and bond 'b' be directional bond between
                # 1 and 2. In this case, the direction of bond *away* from
                # '2' and along 2  = bond direction of bond 'b' and thus
                # atoms traversed along bond_direction = 1 lead us to 3' end.

                # Now, 'atomList_direction_1'  is computed by 'growing' (expanding)
                # a bond chain  in the direction that goes from bond b
                # *towards* startAtom. That is, in this case it is the opposite
                # direction of one specified by 'bond_direction'.  The last atom
                # in atomList_direction_1 is the (5' end) atom.
                # Note that atomList_direction_1 doesn't include 'startAtom'
                # Therefore, to get atomList ordered from 5'to 3' end we must
                #reverse atomList_direction_1 , then append startAtom to the
                #atomList (as its not included in atomList_direction_1) and then
                #extend atoms from atomList_direction_2.

                #What is atomList_direction_2 ?  It is the list of atoms
                #obtained by growing bond chain from bond b, in the direction of
                #atom 1 (atom 1 is the 'other atom' of the bond) . In this case
                #these are the atoms in the direction same as 'bond_direction'
                #starting from atom 1. Thus the atoms in the list are already
                #arranged from 5' to 3' end. (also note that after computing
                #the atomList_direction_2, we also prepend 'atom 1' as the
                #first atom in that list. See the code above that does that.
                atomList_direction_1.reverse()
                atomList.extend(atomList_direction_1)
                atomList.append(startAtom)
                atomList.extend(atomList_direction_2)

            else:
                #See a detailed explanation above.
                #Here, bond_direction == -1.

                # This can be represented by the following sketch --
                # (5'end) --> 1 --> 2 --> 3 --> 4 --> (3' end)

                #bond b is the bond betweern atoms 1 and 2.
                #startAtom remains the same ..i.e. atom 2.

                #As you can notice from the sketch, the bond_direction is
                #direction *away* from 2, along bond b and it leads us to
                # 5' end.

                #based on how atomList_direction_2 (explained earlier), it now
                #includes atoms begining at 1 and ending at 5' end. So
                #we must reverse atomList_direction_2 now to arrange them
                #from 5' to 3' end.
                atomList_direction_2.reverse()
                atomList.extend(atomList_direction_2)
                atomList.append(startAtom)
                atomList.extend(atomList_direction_1)

        # Note: the bondpoint atoms are NOT included.
        # ONLY consecutive sugar stoms are returned.
        # piotr 080411

        # extract only sugar atoms or bondpoints
        # the bondpoints are extracted to make the method compatible
        # with get_strand_atoms_in_bond_direction
        def filter_sugars(atm):
            return atm.element.symbol == 'Ss3' or \
                   atm.element.symbol == 'Ss5' or \
                   atm.element.symbol == 'X'

        atomList = filter(filter_sugars, atomList)
        return atomList