Beispiel #1
0
def test_findCycles3():
    # test cycle detection on taxol merged rings only
    atoms, bonds = getGraphFromFile('Data/fuzedRings1.graph')
    from PyBabel.cycle import RingFinder
    rings = RingFinder()
    rings.findRings2(atoms, bonds)
    assert rings.ringCount==4
Beispiel #2
0
def test_findCycles1():
    # test cycle detection on taxol
    atoms, bonds = getGraphFromFile('Data/txp.graph')
    from PyBabel.cycle import RingFinder
    rings = RingFinder()
    rings.findRings2(atoms, bonds)
    assert rings.ringCount == 6
Beispiel #3
0
def test_findCycles1():
    # test cycle detection on taxol 
    atoms, bonds = getGraphFromFile('Data/txp.graph')
    from PyBabel.cycle import RingFinder
    rings = RingFinder()
    rings.findRings2(atoms, bonds)
    assert rings.ringCount==6
Beispiel #4
0
def test_findCycles2():
    # test cycle detection on modified taxol to have 5 membered ring
    atoms, bonds = getGraphFromFile('Data/fuzedRings2.graph')
    from PyBabel.cycle import RingFinder
    rings = RingFinder()
    rings.findRings2(atoms, bonds)
    assert rings.ringCount==4
Beispiel #5
0
def test_findCycles4():
    # test that atoms in cycles are ordered on taxol 
    atoms, bonds = getGraphFromFile('Data/txp.graph')
    from PyBabel.cycle import RingFinder
    rings = RingFinder()
    rings.findRings2(atoms, bonds)

    def hasBond(a1, a2, cycleHasBond):
        for b in cyclebonds:
            if b.atom1==a1 and b.atom2==a2:
                return 1
            elif b.atom1==a2 and b.atom2==a1:
                return 1
        return 0
    
    def isOrdered(cycleatoms, cyclebonds):

        def hasBond(a1, a2, cyclebonds):
            for b in cyclebonds:
                if b.atom1==a1 and b.atom2==a2:
                    return 1
                elif b.atom1==a2 and b.atom2==a1:
                    return 1
            return 0

        start = cycleatoms[0]
        for end in cycleatoms[1:]:
            if not hasBond(start, end, cyclebonds):
                return 0
            start = end
        return 1
    
    for r in rings.rings:
        assert isOrdered(r['atoms'], r['bonds'])
Beispiel #6
0
def test_findCycles3():
    # test cycle detection on taxol merged rings only
    atoms, bonds = getGraphFromFile('Data/fuzedRings1.graph')
    from PyBabel.cycle import RingFinder
    rings = RingFinder()
    rings.findRings2(atoms, bonds)
    assert rings.ringCount == 4
Beispiel #7
0
def test_findCycles2():
    # test cycle detection on modified taxol to have 5 membered ring
    atoms, bonds = getGraphFromFile('Data/fuzedRings2.graph')
    from PyBabel.cycle import RingFinder
    rings = RingFinder()
    rings.findRings2(atoms, bonds)
    assert rings.ringCount == 4
Beispiel #8
0
def test_findCycles4():
    # test that atoms in cycles are ordered on taxol
    atoms, bonds = getGraphFromFile('Data/txp.graph')
    from PyBabel.cycle import RingFinder
    rings = RingFinder()
    rings.findRings2(atoms, bonds)

    def hasBond(a1, a2, cycleHasBond):
        for b in cyclebonds:
            if b.atom1 == a1 and b.atom2 == a2:
                return 1
            elif b.atom1 == a2 and b.atom2 == a1:
                return 1
        return 0

    def isOrdered(cycleatoms, cyclebonds):
        def hasBond(a1, a2, cyclebonds):
            for b in cyclebonds:
                if b.atom1 == a1 and b.atom2 == a2:
                    return 1
                elif b.atom1 == a2 and b.atom2 == a1:
                    return 1
            return 0

        start = cycleatoms[0]
        for end in cycleatoms[1:]:
            if not hasBond(start, end, cyclebonds):
                return 0
            start = end
        return 1

    for r in rings.rings:
        assert isOrdered(r['atoms'], r['bonds'])
 def select(self, bnds, bondOrder=1):
     ats = self.getAtoms(bnds)
     mols = ats.top.uniq()
     atype = AtomHybridization()
     for m in mols:
         if not m.chains[0].hasBonds:
             m.buildBondsByDistance()
         allAts = m.chains.residues.atoms
         atype.assignHybridization(allAts)
         rf = RingFinder()
         rf.findRings2(allAts, allAts.bonds[0])
         bo = BondOrder()
         bo.assignBondOrder(allAts, allAts.bonds[0], rf)
     return BondSet(bnds.get(lambda x, ord=bondOrder: x.bondOrder==ord))
 def select(self, bnds, bondOrder=1):
     ats = self.getAtoms(bnds)
     mols = ats.top.uniq()
     atype = AtomHybridization()
     for m in mols:
         if not m.chains[0].hasBonds:
             m.buildBondsByDistance()
         allAts = m.chains.residues.atoms
         atype.assignHybridization(allAts)
         rf = RingFinder()
         rf.findRings2(allAts, allAts.bonds[0])
         bo = BondOrder()
         bo.assignBondOrder(allAts, allAts.bonds[0], rf)
     return BondSet(bnds.get(lambda x, ord=bondOrder: x.bondOrder == ord))
Beispiel #11
0
 def getLigandBondDict(self):
     ats = self.allAtoms
     babel = AtomHybridization()
     babel.assignHybridization(self.allAtoms)
     #typeBonds???
     #typeAtoms(ats)
     rf = RingFinder()
     rf.findRings2(ats, ats.bonds[0])
     ct = 1
     bondDict = {}
     for ring in rf.rings:
         bondDict[ct] = ring['bonds']
         for b in ring['bonds']:
             b.cyclenum = ct
         ct = ct + 1
     self.cyclecount = rf.ringCount
     self.bondDict = bondDict
 def getLigandBondDict(self):
     ats = self.allAtoms
     babel = AtomHybridization()
     babel.assignHybridization(self.allAtoms)
     #typeBonds???
     #typeAtoms(ats)
     rf = RingFinder()
     rf.findRings2(ats, ats.bonds[0])
     ct = 1
     bondDict = {}
     for ring in rf.rings:
         bondDict[ct] = ring['bonds']
         for b in ring['bonds']:
             b.cyclenum = ct
         ct = ct + 1
     self.cyclecount = rf.ringCount
     self.bondDict = bondDict
 def select(self, bnds):
     ats = self.getAtoms(bnds)
     rf = RingFinder()
     #nb maxSize of ring is 20 by default
     rf.findRings2(ats, bnds, maxSize=len(ats))
     ats = self.getAtoms(rf.allRingBonds)
     allAts = ats.top.uniq().allAtoms
     atype = AtomHybridization()
     atype.assignHybridization(allAts)
     bo = BondOrder()
     bo.assignBondOrder(allAts, allAts.bonds[0], rf)
     arom = Aromatic(rf)
     arom.find_aromatic_atoms(ats)
     aromatic_bnds = ats.bonds[0].get(lambda x: x.bondOrder=='aromatic')
     aromatic_ats = self.getAtoms(aromatic_bnds)
     aromatic_ats.aromatic = 1
     return aromatic_bnds
 def select(self, bnds):
     ats = self.getAtoms(bnds)
     rf = RingFinder()
     #nb maxSize of ring is 20 by default
     rf.findRings2(ats, bnds, maxSize=len(ats))
     ats = self.getAtoms(rf.allRingBonds)
     allAts = ats.top.uniq().allAtoms
     atype = AtomHybridization()
     atype.assignHybridization(allAts)
     bo = BondOrder()
     bo.assignBondOrder(allAts, allAts.bonds[0], rf)
     arom = Aromatic(rf)
     arom.find_aromatic_atoms(ats)
     aromatic_bnds = ats.bonds[0].get(lambda x: x.bondOrder == 'aromatic')
     aromatic_ats = self.getAtoms(aromatic_bnds)
     aromatic_ats.aromatic = 1
     return aromatic_bnds
 def select(self, bnds, detectAll=False):
     ats = self.getAtoms(bnds)
     rf = RingFinder()
     if self.useMaxSize:
         # increase maxSize of ring 
         rf.findRings2(ats, bnds, maxSize=len(ats))
     else:
         #limit maxSize of ring to default 20 
         rf.findRings2(ats, bnds)
     #check for connected cycles
     bonds= BondSet(rf.allRingBonds)
     if detectAll and len(rf.allRingBonds):
         ats = BondSet(rf.allRingBonds).getAtoms()
         ANS = {}
         for a in ats:
             for b in a.bonds:
                 if b.atom1 in ats and b.atom2 in ats:
                     ANS[b] = 1
         #return BondSet(rf.allRingBonds)
         bonds= BondSet(ANS.keys())
     return bonds
 def select(self, bnds, detectAll=False):
     ats = self.getAtoms(bnds)
     rf = RingFinder()
     if self.useMaxSize:
         # increase maxSize of ring
         rf.findRings2(ats, bnds, maxSize=len(ats))
     else:
         #limit maxSize of ring to default 20
         rf.findRings2(ats, bnds)
     #check for connected cycles
     bonds = BondSet(rf.allRingBonds)
     if detectAll and len(rf.allRingBonds):
         ats = BondSet(rf.allRingBonds).getAtoms()
         ANS = {}
         for a in ats:
             for b in a.bonds:
                 if b.atom1 in ats and b.atom2 in ats:
                     ANS[b] = 1
         #return BondSet(rf.allRingBonds)
         bonds = BondSet(ANS.keys())
     return bonds
Beispiel #17
0
    def addHydrogens(self, mol):
        #check for bonds
        if len(mol.allAtoms.bonds[0]) == 0:
            mol.buildBondsByDistance()
        bonds = mol.allAtoms.bonds[0]
        #could have preset babel_types
        #so check if allAtoms are already typed
        try:
            t = mol.allAtoms.babel_type
        except:
            #if all are not pretyped, type them
            babel = AtomHybridization()
            babel.assignHybridization(mol.allAtoms)

        if self.method == 'withBondOrder':
            mol.rings = RingFinder()
            mol.rings.findRings2(mol.allAtoms, mol.allAtoms.bonds[0])
            mol.rings.bondRings = {}
            for ind in xrange(len(mol.rings.rings)):
                r = mol.rings.rings[ind]
                for b in r['bonds']:
                    if not mol.rings.bondRings.has_key(b):
                        mol.rings.bondRings[b] = [
                            ind,
                        ]
                    else:
                        mol.rings.bondRings[b].append(ind)
            bo = BondOrder()
            bo.assignBondOrder(mol.allAtoms, bonds, mol.rings)
            mol.allAtoms._bndtyped = 1
            # do aromatic here
            arom = Aromatic(mol.rings)
            arom.find_aromatic_atoms(mol.allAtoms)

        hat = AddHydrogens().addHydrogens(mol.allAtoms, method=self.method)
        bondedAtomDict = {}  # key is heavy atom
        for a in hat:
            if bondedAtomDict.has_key(a[1]):
                bondedAtomDict[a[1]].append(a)
            else:
                bondedAtomDict[a[1]] = [a]

        # now create Atom object for hydrogens
        # and add the to the residues's atom list
        molNewHs = AtomSet([])  # list of created H atoms for this molecule
        heavyAtoms = AtomSet([])  # list of atoms that need new radii

        for heavyAtom, HatmsDscr in bondedAtomDict.items():
            #don't add hydrogens to carbons: polar Only!!!
            if self.htype != 'all' and heavyAtom.element == 'C':
                continue
            res = heavyAtom.parent
            # find where to insert H atom
            childIndex = res.children.index(heavyAtom) + 1

            # loop over H atoms description to be added
            # start at the end to number correctly
            l = len(HatmsDscr)
            for i in range(l - 1, -1, -1):
                a = HatmsDscr[i]
                # build H atom's name
                if len(heavyAtom.name) == 1:
                    name = 'H' + heavyAtom.name
                else:
                    name = 'H' + heavyAtom.name[1:]

                # if more than 1 H atom, add H atom index
                # for instance HD11, HD12, Hd13 (index is 1,2,3)
                if l > 1:
                    name = name + str(i + 1)

                # create the H atom object
                atom = Atom(name,
                            res,
                            top=heavyAtom.top,
                            chemicalElement='H',
                            childIndex=childIndex,
                            assignUniqIndex=0)

                # set atoms attributes
                atom._coords = [a[0]]
                if hasattr(a[1], 'segID'): atom.segID = a[1].segID
                atom.hetatm = 0
                atom.alternate = []
                #atom.element = 'H'
                atom.occupancy = 1.0
                atom.conformation = 0
                atom.temperatureFactor = 0.0
                atom.babel_atomic_number = a[2]
                atom.babel_type = a[3]
                atom.babel_organic = 1
                atom.radius = 1.2

                # create the Bond object bonding Hatom to heavyAtom
                bond = Bond(a[1], atom, bondOrder=1)

                # add the created atom the the list
                molNewHs.append(atom)
                # in case this new hydrogen atom ever ends up in pmv
                # HAVE TO CREATE THESE ENTRIES
                # create the color entries for all geoemtries
                # available for the heavyAtom
                for key, value in heavyAtom.colors.items():
                    atom.colors[key] = (0.0, 1.0, 1.0)
                    atom.opacities[key] = 1.0

        mol.allAtoms = mol.chains.residues.atoms
        if self.renumber:
            mol.allAtoms.number = range(1, len(mol.allAtoms) + 1)
        return len(molNewHs)
    def select(self, bnds, cutoff=7.5):
        cutoffValue = math.cos(cutoff*math.pi/180.)
        #print "cutoffValue=", cutoffValue
        aromaticCs = AtomSet([])
        atD = {}
        ctr = 1
        aromaticBnds = BondSet()

        #taken from autotorsCommands
        ats = self.getAtoms(bnds)
        rf = RingFinder()
        rf.findRings2(ats, bnds)
        cyclecount = rf.ringCount
        aromatic_cycles = []
        ct = 1
        for ring in rf.rings:
            blist = ring['bonds']
            for bnd in blist:
                at = bnd.atom1
                #next find the other bond in this cycle with at as one of the atoms:
                z2 = filter(lambda x:x!=bnd and x.atom1==at or x.atom2==at, blist)
                bnd.nextbond = z2[0]
                neighbor = z2[0].atom1
                if neighbor==at:
                    neighbor = z2[0].atom2
                bnd.next1 = neighbor
                #print "set ", bnd.atom1.name,'-', bnd.atom2.name,".next1 to ", neighbor.name
                #now each bond has 3 atoms specified for it: its own two and the next1 to atom1
                at1 = bnd.next1
                at2 = bnd.atom1
                at3 = bnd.atom2
                pt1 = at1.coords
                pt2 = at2.coords
                pt3 = at3.coords
                a1 = Numeric.subtract(pt2,pt1)
                b1 = Numeric.subtract(pt3,pt2)
                p = [a1[1]*b1[2]-a1[2]*b1[1],a1[2]*b1[0]-a1[0]*b1[2],a1[0]*b1[1]-a1[1]*b1[0]]
                result0 = Numeric.sqrt(p[0]*p[0]+p[1]*p[1]+p[2]*p[2])
                bnd.nrmsize = result0
                result1 = p
                bnd.nrms = result1
                #next find the other bond w/atom2:
                z2 = filter(lambda x,bnd=bnd, at2=bnd.atom2, blist=blist:x!=bnd and x.atom1==at2 or x.atom2==at2, blist)
                #finally, return the other atom in this bond
                bnd.nextbond2 = z2[0]
                if bnd.nextbond2==bnd:
                    bnd.nextbond2 = z2[1]
                #neighbor2 = self._getnxtAtom(b.atom2,b.nextbond2)
                neighbor2 = bnd.nextbond2.atom1
                if neighbor2==bnd.atom2:
                    neighbor2 = bnd.nextbond2.atom2
                bnd.next2 = neighbor2
                #next have to check whether the normals are parallel
                #check each pair in each bond, how to keep track??
                #have to get normal at b's atom2: so have to get next2 for this bond:
            #have to loop twice to make sure neighbor has nrms
            for bnd in blist:
                p = bnd.nrms
                psize = bnd.nrmsize
                q = bnd.nextbond2.nrms
                qsize = bnd.nextbond2.nrmsize
                #theta is the critical test for planarity:
                #if angle between 2 nrms is 0, atoms are planar
                #NB>test is comparing theta,cos(angle), w/zero
                bnd.theta = Numeric.dot(p,q)/(psize*qsize)
            #NB: REPEAT STUFF FROM HERE TO THE END IF aromaticCutOff changes
            ct = 0
            for bnd in blist:
                #these are values for the default 7.5degrees:
                #if theta>=0.997 or theta<=-0.997:
                #print bnd.atom1.name, '-', bnd.atom2.name, '->', bnd.theta 
                if bnd.theta>=cutoffValue or bnd.theta<=-cutoffValue:
                    bnd.posAromatic = 1
                    ct = ct + 1
                else:
                    bnd.posAromatic = 0
                #print ' posAromatic=', bnd.posAromatic
            #after checking all the bonds in current cycle, compare #posAromatic w/number
            if ct==len(blist):
                #print ctr," cycle is aromatic"
                #NB: only C=C bonds are considered aromatic 
                #    could change the name and autodock_element here....
                for bnd in blist:
                    # THIS IS WRONG!!!
                    #if bnd.atom1.element=='C' and bnd.atom2.element=='C':
                    #    aromaticBnds.append(bnd)
                    aromaticBnds.append(bnd)
            ctr = ctr + 1
            #print "len(aromaticBnds)=", len(aromaticBnds)
        #for b in aromaticBnds:
        #    print b.atom1.name, '-', b.atom2.name
        return aromaticBnds
Beispiel #19
0
 def detectPiInteractions(self, tolerance=0.95, debug=False, use_all_cycles=False):
     if debug: print("in detectPiInteractions")
     self.results['pi_pi'] = []        #stacked rings...?
     self.results['t_shaped'] = []     #one ring perpendicular to the other
     self.results['cation_pi'] = []    #
     self.results['pi_cation'] = []    #
     self.results['macro_cations'] = []#
     self.results['lig_cations'] = []  #
     #at this point have self.results
     if not len(self.results['lig_close_atoms']):
         return
     lig_atoms = self.results['lig_close_atoms'].parent.uniq().atoms
     macro_res = self.results['macro_close_atoms'].parent.uniq()
     if not len(macro_res):
         return
     macro_atoms = macro_res.atoms
     l_rf = RingFinder()
     #Ligand
     l_rf.findRings2(lig_atoms, lig_atoms.bonds[0])
     #rf.rings is list of dictionaries, one per ring, with keys 'bonds' and 'atoms'
     if debug: print("LIG: len(l_rf.rings)=", len(l_rf.rings))
     if not len(l_rf.rings):
         if debug: print("no lig rings found by l_rf!")
         return
     acbs = self.aromatic_cycle_bond_selector
     #acbs = AromaticCycleBondSelector()
     lig_rings = []
     for r in l_rf.rings:
         ring_bnds = r['bonds']
         if use_all_cycles: 
             lig_rings.append(ring_bnds)
         else:
             arom_bnds = acbs.select(ring_bnds)
             if len(arom_bnds)>4:
                 lig_rings.append(arom_bnds)
     if debug: print("LIG: len(lig_arom_rings)=", len(lig_rings))
     self.results['lig_rings'] = lig_rings
     self.results['lig_ring_atoms'] = AtomSet()
     #only check for pi-cation if lig_rings exist
     if len(lig_rings):
         macro_cations = self.results['macro_cations'] = self.getCations(macro_atoms)
         macro_cations = macro_cations.get(lambda x: x.element!='H')
         lig_ring_atoms = AtomSet()
         u = {}
         for r in lig_rings:
             for a in BondSet(r).getAtoms():
                 u[a] = 1
         if len(u): 
             lig_ring_atoms = AtomSet(list(u.keys()))
             lig_ring_atoms.sort()
             self.results['lig_ring_atoms'] = lig_ring_atoms
         if len(macro_cations):
             if debug: print("check distances from lig_rings to macro_cations here")
             #macro cations->lig rings
             pairDict2 = self.distanceSelector.select(lig_ring_atoms,macro_cations)
             z = {}
             for key,v in list(pairDict2.items()):
                 val = v.tolist()[0]
                 if val in macro_cations:
                     z[val] = [key]
             if len(z):
                 self.results['pi_cation'] = (list(z.items()))
             else:
                 self.results['pi_cation'] = []
     #check the distance between the rings and the macro_cations
     self.results['lig_cations'] = self.getCations(lig_atoms)
     lig_cations = self.results['lig_cations'] 
     #remove hydrogens
     lig_cations = lig_cations.get(lambda x: x.element!='H')
     #Macromolecule
     m_rf = RingFinder()
     m_rf.findRings2(macro_res.atoms, macro_res.atoms.bonds[0])
     #rf.rings is list of dictionaries, one per ring, with keys 'bonds' and 'atoms'
     if debug: print("MACRO: len(m_rf.rings)=", len(m_rf.rings))
     if not len(m_rf.rings):
         if debug: print("no macro rings found by m_rf!")
         return
     macro_rings = []
     for r in m_rf.rings:
         ring_bnds = r['bonds']
         if use_all_cycles: 
             macro_rings.append(ring_bnds)
         else:
             arom_bnds = acbs.select(ring_bnds)
             if len(arom_bnds)>4:
                 macro_rings.append(arom_bnds)
     if debug: print("len(macro_arom_rings)=", len(macro_rings))
     self.results['macro_rings'] = macro_rings
     self.results['macro_ring_atoms'] = AtomSet()
     #only check for pi-cation if macro_rings exist
     if len(macro_rings):
         macro_ring_atoms = AtomSet()
         u = {}
         for r in macro_rings:
             for a in BondSet(r).getAtoms(): #new method of bondSets
                 u[a] = 1
         if len(u):
             macro_ring_atoms = AtomSet(list(u.keys()))
             macro_ring_atoms.sort()
             self.results['macro_ring_atoms'] = macro_ring_atoms
         if len(lig_cations):
             if debug: print("check distances from macro_rings to lig_cations here")
             pairDict3 = self.distanceSelector.select(macro_ring_atoms,lig_cations)
             z = {}
             for x in list(pairDict3.items()):
                 #lig cations->macro rings
                 z.setdefault(x[1].tolist()[0], []).append(x[0])
             if len(z):
                 self.results['cation_pi'] = (list(z.items()))
             else:
                 self.results['cation_pi'] = []
             #macro_pi_atoms = AtomSet(pairDict3.keys())
             #l_cations = AtomSet()
             #for v in pairDict3.values():
             #    for x in v:
             #        l_cations.append(x)
             #self.results['cation_pi'] = pairDict3.items()
             #self.results['cation_pi'] = (l_cations, macro_pi_atoms)
     #check for intermol distance <6 Angstrom (J.ComputChem 29:275-279, 2009)
     #compare each lig_ring vs each macro_ring
     for lig_ring_bnds in lig_rings:
         lig_atoms = acbs.getAtoms(lig_ring_bnds)
         lig_atoms.sort()
         if debug: print("len(lig_atoms)=", len(lig_atoms))
         #---------------------------------
         # compute the normal to lig ring
         #---------------------------------
         a1 = numpy.array(lig_atoms[0].coords)
         a2 = numpy.array(lig_atoms[2].coords)
         a3 = numpy.array(lig_atoms[4].coords)
         if debug: print("a1,a2, a3=", a1.tolist(), a2.tolist(), a3.tolist())
         for macro_ring_bnds in macro_rings:
             macro_atoms = acbs.getAtoms(macro_ring_bnds)
             macro_atoms.sort()
             if debug: print("len(macro_atoms)=", len(macro_atoms))
             pD_dist = self.distanceSelectorWithCutoff.select(macro_ring_atoms, lig_atoms, cutoff=self.dist_cutoff)
             if not len(pD_dist[0]):
                 if debug: 
                     print("skipping ligand ring ", lig_rings.index(lig_ring_bnds), " vs ", end=' ')
                     print("macro ring", macro_rings.index(macro_ring_bnds))
                 continue
             #---------------------------------
             # compute the normal to macro ring
             #---------------------------------
             b1 = numpy.array(macro_atoms[0].coords)
             b2 = numpy.array(macro_atoms[2].coords)
             b3 = numpy.array(macro_atoms[4].coords)
             if debug: print("b1,b2, b3=", b1.tolist(), b2.tolist(), b3.tolist())
             # check for stacking 
             a2_1 = a2-a1
             a3_1 = a3-a1
             b2_1 = b2-b1
             b3_1 = b3-b1
             if debug: print("a2_1 = ", a2-a1)
             if debug: print("a3_1 = ", a3-a1)
             if debug: print("b2_1 = ", b2-b1)
             if debug: print("b3_1 = ", b3-b1)
             n1 = crossProduct(a3_1,a2_1) #to get the normal for the first ring
             n2 = crossProduct(b3_1,b2_1) #to get the normal for the second ring
             if debug: print("n1=", n1)
             if debug: print("n2=", n2)
             n1 = numpy.array(n1)
             n2 = numpy.array(n2)
             n1_dot_n2 = numpy.dot(n1,n2)
             if debug: print("n1_dot_n2", numpy.dot(n1,n2))
             if abs(n1_dot_n2) >= 1*tolerance: 
                 if debug: print("The rings are stacked vertically") 
                 new_result = (acbs.getAtoms(lig_ring_bnds), acbs.getAtoms(macro_ring_bnds))
                 self.results['pi_pi'].append(new_result)
             if abs(n1_dot_n2) <= 0.01*tolerance: 
                 if debug: print("The rings are stacked perpendicularly") 
                 new_result = (acbs.getAtoms(lig_ring_bnds), acbs.getAtoms(macro_ring_bnds))
                 self.results['t_shaped'].append(new_result)
 def detectPiInteractions(self, tolerance=0.95, debug=False, use_all_cycles=False):
     if debug: print "in detectPiInteractions"
     self.results['pi_pi'] = []        #stacked rings...?
     self.results['t_shaped'] = []     #one ring perpendicular to the other
     self.results['cation_pi'] = []    #
     self.results['pi_cation'] = []    #
     self.results['macro_cations'] = []#
     self.results['lig_cations'] = []  #
     #at this point have self.results
     lig_res = self.results['lig_close_res']
     if not len(lig_res):
         return
     lig_atoms = lig_res.atoms
     macro_res = self.results['macro_close_res']
     if not len(macro_res):
         return
     macro_atoms = macro_res.atoms
     l_rf = RingFinder()
     #Ligand
     l_rf.findRings2(lig_res.atoms, lig_res.atoms.bonds[0])
     #rf.rings is list of dictionaries, one per ring, with keys 'bonds' and 'atoms'
     if debug: print "LIG: len(l_rf.rings)=", len(l_rf.rings)
     if not len(l_rf.rings):
         if debug: print "no lig rings found by l_rf!"
         return
     acbs = AromaticCycleBondSelector()
     lig_rings = []
     for r in l_rf.rings:
         ring_bnds = r['bonds']
         if use_all_cycles: 
             lig_rings.append(ring_bnds)
         else:
             arom_bnds = acbs.select(ring_bnds)
             if len(arom_bnds)>4:
                 lig_rings.append(arom_bnds)
     if debug: print "LIG: len(lig_arom_rings)=", len(lig_rings)
     self.results['lig_rings'] = lig_rings
     self.results['lig_ring_atoms'] = AtomSet()
     #only check for pi-cation if lig_rings exist
     if len(lig_rings):
         macro_cations = self.results['macro_cations'] = self.getCations(macro_atoms)
         lig_ring_atoms = AtomSet()
         u = {}
         for r in lig_rings:
             for a in BondSet(r).getAtoms():
                 u[a] = 1
         if len(u): 
             lig_ring_atoms = AtomSet(u.keys())
             lig_ring_atoms.sort()
             self.results['lig_ring_atoms'] = lig_ring_atoms
         if len(macro_cations):
             if debug: print "check distances from lig_rings to macro_cations here"
             #macro cations->lig rings
             pairDict2 = self.distanceSelector.select(lig_ring_atoms,macro_cations)
             z = {}
             for key,v in pairDict2.items():
                 val = v.tolist()[0]
                 if val in macro_cations:
                     z[val] = [key]
             if len(z):
                 self.results['pi_cation'] = (z.items())
             else:
                 self.results['pi_cation'] = []
     #check the distance between the rings and the macro_cations
     self.results['lig_cations'] = self.getCations(lig_atoms)
     #Macromolecule
     m_rf = RingFinder()
     m_rf.findRings2(macro_res.atoms, macro_res.atoms.bonds[0])
     #rf.rings is list of dictionaries, one per ring, with keys 'bonds' and 'atoms'
     if debug: print "MACRO: len(m_rf.rings)=", len(m_rf.rings)
     if not len(m_rf.rings):
         if debug: print "no macro rings found by m_rf!"
         return
     macro_rings = []
     for r in m_rf.rings:
         ring_bnds = r['bonds']
         if use_all_cycles: 
             macro_rings.append(ring_bnds)
         else:
             arom_bnds = acbs.select(ring_bnds)
             if len(arom_bnds)>4:
                 macro_rings.append(arom_bnds)
     if debug: print "len(macro_arom_rings)=", len(macro_rings)
     self.results['macro_rings'] = macro_rings
     self.results['macro_ring_atoms'] = AtomSet()
     #only check for pi-cation if macro_rings exist
     if len(macro_rings):
         lig_cations = self.results['lig_cations'] = self.getCations(lig_atoms)
         macro_ring_atoms = AtomSet()
         u = {}
         for r in macro_rings:
             for a in BondSet(r).getAtoms(): #new method of bondSets
                 u[a] = 1
         if len(u):
             macro_ring_atoms = AtomSet(u.keys())
             macro_ring_atoms.sort()
             self.results['macro_ring_atoms'] = macro_ring_atoms
         if len(lig_cations):
             if debug: print "check distances from macro_rings to lig_cations here"
             pairDict3 = self.distanceSelector.select(macro_ring_atoms,lig_cations)
             z = {}
             for x in pairDict3.items():
                 #lig cations->macro rings
                 z.setdefault(x[1].tolist()[0], []).append(x[0])
             if len(z):
                 self.results['cation_pi'] = (z.items())
             else:
                 self.results['cation_pi'] = []
             #macro_pi_atoms = AtomSet(pairDict3.keys())
             #l_cations = AtomSet()
             #for v in pairDict3.values():
             #    for x in v:
             #        l_cations.append(x)
             #self.results['cation_pi'] = pairDict3.items()
             #self.results['cation_pi'] = (l_cations, macro_pi_atoms)
     #check for intermol distance <6 Angstrom (J.ComputChem 29:275-279, 2009)
     #compare each lig_ring vs each macro_ring
     for lig_ring_bnds in lig_rings:
         lig_atoms = acbs.getAtoms(lig_ring_bnds)
         lig_atoms.sort()
         if debug: print "len(lig_atoms)=", len(lig_atoms)
         #---------------------------------
         # compute the normal to lig ring
         #---------------------------------
         a1 = Numeric.array(lig_atoms[0].coords)
         a2 = Numeric.array(lig_atoms[2].coords)
         a3 = Numeric.array(lig_atoms[4].coords)
         if debug: print "a1,a2, a3=", a1.tolist(), a2.tolist(), a3.tolist()
         for macro_ring_bnds in macro_rings:
             macro_atoms = acbs.getAtoms(macro_ring_bnds)
             macro_atoms.sort()
             if debug: print "len(macro_atoms)=", len(macro_atoms)
             pD_dist = self.distanceSelectorWithCutoff.select(macro_ring_atoms, lig_atoms, cutoff=self.dist_cutoff)
             if not len(pD_dist[0]):
                 if debug: 
                     print "skipping ligand ring ", lig_rings.index(lig_ring_bnds), " vs ",
                     print "macro ring", macro_rings.index(macro_ring_bnds)
                 continue
             #---------------------------------
             # compute the normal to macro ring
             #---------------------------------
             b1 = Numeric.array(macro_atoms[0].coords)
             b2 = Numeric.array(macro_atoms[2].coords)
             b3 = Numeric.array(macro_atoms[4].coords)
             if debug: print "b1,b2, b3=", b1.tolist(), b2.tolist(), b3.tolist()
             # check for stacking 
             a2_1 = a2-a1
             a3_1 = a3-a1
             b2_1 = b2-b1
             b3_1 = b3-b1
             if debug: print "a2_1 = ", a2-a1
             if debug: print "a3_1 = ", a3-a1
             if debug: print "b2_1 = ", b2-b1
             if debug: print "b3_1 = ", b3-b1
             n1 = crossProduct(a3_1,a2_1) #to get the normal for the first ring
             n2 = crossProduct(b3_1,b2_1) #to get the normal for the second ring
             if debug: print "n1=", n1
             if debug: print "n2=", n2
             n1 = Numeric.array(n1)
             n2 = Numeric.array(n2)
             n1_dot_n2 = Numeric.dot(n1,n2)
             if debug: print "n1_dot_n2", Numeric.dot(n1,n2)
             if abs(n1_dot_n2) >= 1*tolerance: 
                 if debug: print "The rings are stacked vertically" 
                 new_result = (acbs.getAtoms(lig_ring_bnds), acbs.getAtoms(macro_ring_bnds))
                 self.results['pi_pi'].append(new_result)
             if abs(n1_dot_n2) <= 0.01*tolerance: 
                 if debug: print "The rings are stacked perpendicularly" 
                 new_result = (acbs.getAtoms(lig_ring_bnds), acbs.getAtoms(macro_ring_bnds))
                 self.results['t_shaped'].append(new_result)
    def select(self, bnds, cutoff=7.5):
        cutoffValue = math.cos(cutoff * math.pi / 180.)
        #print "cutoffValue=", cutoffValue
        aromaticCs = AtomSet([])
        atD = {}
        ctr = 1
        aromaticBnds = BondSet()

        #taken from autotorsCommands
        ats = self.getAtoms(bnds)
        rf = RingFinder()
        rf.findRings2(ats, bnds)
        cyclecount = rf.ringCount
        aromatic_cycles = []
        ct = 1
        for ring in rf.rings:
            blist = ring['bonds']
            for bnd in blist:
                at = bnd.atom1
                #next find the other bond in this cycle with at as one of the atoms:
                z2 = filter(
                    lambda x: x != bnd and x.atom1 == at or x.atom2 == at,
                    blist)
                bnd.nextbond = z2[0]
                neighbor = z2[0].atom1
                if neighbor == at:
                    neighbor = z2[0].atom2
                bnd.next1 = neighbor
                #print "set ", bnd.atom1.name,'-', bnd.atom2.name,".next1 to ", neighbor.name
                #now each bond has 3 atoms specified for it: its own two and the next1 to atom1
                at1 = bnd.next1
                at2 = bnd.atom1
                at3 = bnd.atom2
                pt1 = at1.coords
                pt2 = at2.coords
                pt3 = at3.coords
                a1 = Numeric.subtract(pt2, pt1)
                b1 = Numeric.subtract(pt3, pt2)
                p = [
                    a1[1] * b1[2] - a1[2] * b1[1],
                    a1[2] * b1[0] - a1[0] * b1[2],
                    a1[0] * b1[1] - a1[1] * b1[0]
                ]
                result0 = Numeric.sqrt(p[0] * p[0] + p[1] * p[1] + p[2] * p[2])
                bnd.nrmsize = result0
                result1 = p
                bnd.nrms = result1
                #next find the other bond w/atom2:
                z2 = filter(lambda x, bnd=bnd, at2=bnd.atom2, blist=blist: x !=
                            bnd and x.atom1 == at2 or x.atom2 == at2,
                            blist)
                #finally, return the other atom in this bond
                bnd.nextbond2 = z2[0]
                if bnd.nextbond2 == bnd:
                    bnd.nextbond2 = z2[1]
                #neighbor2 = self._getnxtAtom(b.atom2,b.nextbond2)
                neighbor2 = bnd.nextbond2.atom1
                if neighbor2 == bnd.atom2:
                    neighbor2 = bnd.nextbond2.atom2
                bnd.next2 = neighbor2
                #next have to check whether the normals are parallel
                #check each pair in each bond, how to keep track??
                #have to get normal at b's atom2: so have to get next2 for this bond:
            #have to loop twice to make sure neighbor has nrms
            for bnd in blist:
                p = bnd.nrms
                psize = bnd.nrmsize
                q = bnd.nextbond2.nrms
                qsize = bnd.nextbond2.nrmsize
                #theta is the critical test for planarity:
                #if angle between 2 nrms is 0, atoms are planar
                #NB>test is comparing theta,cos(angle), w/zero
                bnd.theta = Numeric.dot(p, q) / (psize * qsize)
            #NB: REPEAT STUFF FROM HERE TO THE END IF aromaticCutOff changes
            ct = 0
            for bnd in blist:
                #these are values for the default 7.5degrees:
                #if theta>=0.997 or theta<=-0.997:
                #print bnd.atom1.name, '-', bnd.atom2.name, '->', bnd.theta
                if bnd.theta >= cutoffValue or bnd.theta <= -cutoffValue:
                    bnd.posAromatic = 1
                    ct = ct + 1
                else:
                    bnd.posAromatic = 0
                #print ' posAromatic=', bnd.posAromatic
            #after checking all the bonds in current cycle, compare #posAromatic w/number
            if ct == len(blist):
                #print ctr," cycle is aromatic"
                #NB: only C=C bonds are considered aromatic
                #    could change the name and autodock_element here....
                for bnd in blist:
                    # THIS IS WRONG!!!
                    #if bnd.atom1.element=='C' and bnd.atom2.element=='C':
                    #    aromaticBnds.append(bnd)
                    aromaticBnds.append(bnd)
            ctr = ctr + 1
            #print "len(aromaticBnds)=", len(aromaticBnds)
        #for b in aromaticBnds:
        #    print b.atom1.name, '-', b.atom2.name
        return aromaticBnds