Пример #1
0
class TestGroup(unittest.TestCase):
    """
    Contains unit tests of the Graph class.
    """
    def setUp(self):
        self.adjlist = """
1 *2 [Cs,Cd] u0 {2,[S,D]} {3,S}
2 *1 [Os,Od] u0 {1,[S,D]}
3    R!H     u0 {1,S}
            """
        self.group = Group().fromAdjacencyList(self.adjlist)

    def testClearLabeledAtoms(self):
        """
        Test the Group.clearLabeledAtoms() method.
        """
        self.group.clearLabeledAtoms()
        for atom in self.group.atoms:
            self.assertEqual(atom.label, '')

    def testContainsLabeledAtom(self):
        """
        Test the Group.containsLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(self.group.containsLabeledAtom(atom.label))
        self.assertFalse(self.group.containsLabeledAtom('*3'))
        self.assertFalse(self.group.containsLabeledAtom('*4'))
        self.assertFalse(self.group.containsLabeledAtom('*5'))
        self.assertFalse(self.group.containsLabeledAtom('*6'))

    def testGetLabeledAtom(self):
        """
        Test the Group.getLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertEqual(atom, self.group.getLabeledAtom(atom.label))
        try:
            self.group.getLabeledAtom('*3')
            self.fail(
                'Unexpected successful return from Group.getLabeledAtom() with invalid atom label.'
            )
        except ValueError:
            pass

    def testGetLabeledAtoms(self):
        """
        Test the Group.getLabeledAtoms() method.
        """
        labeled = self.group.getLabeledAtoms()
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(atom.label in labeled)
                self.assertTrue(atom in labeled.values())
            else:
                self.assertFalse(atom.label in labeled)
                self.assertFalse(atom in labeled.values())

    def testFromAdjacencyList(self):
        """
        Test the Group.fromAdjacencyList() method.
        """
        atom1, atom2, atom3 = self.group.atoms
        self.assertTrue(self.group.hasBond(atom1, atom2))
        self.assertTrue(self.group.hasBond(atom1, atom3))
        self.assertFalse(self.group.hasBond(atom2, atom3))
        bond12 = atom1.bonds[atom2]
        bond13 = atom1.bonds[atom3]

        self.assertTrue(atom1.label == '*2')
        self.assertTrue(atom1.atomType[0].label in ['Cs', 'Cd'])
        self.assertTrue(atom1.atomType[1].label in ['Cs', 'Cd'])
        self.assertTrue(atom1.radicalElectrons == [0])

        self.assertTrue(atom2.label == '*1')
        self.assertTrue(atom2.atomType[0].label in ['Os', 'Od'])
        self.assertTrue(atom2.atomType[1].label in ['Os', 'Od'])
        self.assertTrue(atom2.radicalElectrons == [0])

        self.assertTrue(atom3.label == '')
        self.assertTrue(atom3.atomType[0].label == 'R!H')
        self.assertTrue(atom3.radicalElectrons == [0])

        self.assertTrue(bond12.order == [1, 2])
        self.assertTrue(bond13.isSingle())

    def testToAdjacencyList(self):
        """
        Test the Group.toAdjacencyList() method.
        """
        adjlist = self.group.toAdjacencyList()
        self.assertEqual(adjlist.strip(), self.adjlist.strip(), adjlist)

    def testIsIsomorphic(self):
        """
        Test the Group.isIsomorphic() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))

    def testFindIsomorphism(self):
        """
        Test the Group.findIsomorphism() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findIsomorphism(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].items():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))
            for atom3 in atom1.bonds:
                atom4 = result[0][atom3]
                self.assertTrue(atom4 in atom2.bonds)
                self.assertTrue(atom3.equivalent(atom4))
                bond1 = atom1.bonds[atom3]
                bond2 = atom2.bonds[atom4]
                self.assertTrue(bond1.equivalent(bond2))

    def testIsSubgraphIsomorphic(self):
        """
        Test the Group.isSubgraphIsomorphic() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isSubgraphIsomorphic(group))
        self.assertFalse(group.isIsomorphic(self.group))

    def testFindSubgraphIsomorphisms(self):
        """
        Test the Group.findSubgraphIsomorphisms() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findSubgraphIsomorphisms(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].iteritems():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))

    def testPickle(self):
        """
        Test that a Group object can be successfully pickled and
        unpickled with no loss of information.
        """
        import cPickle
        group = cPickle.loads(cPickle.dumps(self.group))

        self.assertEqual(len(self.group.atoms), len(group.atoms))
        for atom0, atom in zip(group.atoms, self.group.atoms):
            self.assertTrue(atom0.equivalent(atom))

        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))

    def testCreateAndConnectAtom(self):
        """
        Tests createAndConnectAtom method
        """
        adjlist1 = """
1  *1 C u0 {2,S}
2  *2 C u0 {1,S}
"""

        answer1 = """
1  *1 C  u0 {2,S} {3,B}
2  *2 C  u0 {1,S}
3     Cb u0 {1,B}
"""

        group1 = Group().fromAdjacencyList(adjlist1)
        answer1 = Group().fromAdjacencyList(answer1)
        atom1 = group1.getLabeledAtom("*1")
        newAtom = group1.createAndConnectAtom(atomtypes=["Cb"],
                                              connectingAtom=atom1,
                                              bondOrders=["B"])
        self.assertTrue(group1.isIsomorphic(answer1))

        answer2 = """
1  *1 C  u0 {2,S} {3,[S,D]}
2  *2 C  u0 {1,S}
3     [Cs,Cd] u0 {1,[S,D]}
"""

        #Test that wildcards work alright
        group2 = Group().fromAdjacencyList(adjlist1)
        answer2 = Group().fromAdjacencyList(answer2)
        atom1 = group2.getLabeledAtom("*1")
        newAtom = group2.createAndConnectAtom(atomtypes=["Cs", "Cd"],
                                              connectingAtom=atom1,
                                              bondOrders=["S", "D"])
        self.assertTrue(group2.isIsomorphic(answer2))

    def testAddImplicitAtomsFromAtomType(self):
        """
        test Group.addImplicitAtomsFromAtomType() method
        """
        #basic test adding oDouble
        adjlist1 = """
1  *1 CO u0
            """

        adjlist2 = """
1  *1 CO u0 {2,D}
2     O  u0 {1,D}
            """

        group1 = Group().fromAdjacencyList(adjlist1)
        group2 = Group().fromAdjacencyList(adjlist2)

        newGroup = group1.addImplicitAtomsFromAtomType()
        self.assertTrue(group2.isIsomorphic(newGroup))
        #testing the allDouble match (more complicated
        adjlist3 = """
1  *1 Cdd u0
            """

        adjlist4 = """
1  *1 Cdd u0 {2,D} {3,D}
2     C   u0 {1,D}
3     C   u0 {1,D}
            """
        group3 = Group().fromAdjacencyList(adjlist3)
        group4 = Group().fromAdjacencyList(adjlist4)

        newGroup = group3.addImplicitAtomsFromAtomType()
        self.assertTrue(group4.isIsomorphic(newGroup))
        #test adding a triple bond
        adjlist5 = """
1  *1 Ct u0
            """

        adjlist6 = """
1  *1 Ct u0 {2,T}
2     C   u0 {1,T}
            """
        group5 = Group().fromAdjacencyList(adjlist5)
        group6 = Group().fromAdjacencyList(adjlist6)

        newGroup = group5.addImplicitAtomsFromAtomType()
        self.assertTrue(group6.isIsomorphic(newGroup))
        #test addition of lone pairs
        adjlist7 = """
1  *1 N1d u0
            """

        adjlist8 = """
1  *1 N1d u0 p2 {2,D}
2     C   u0 {1,D}
            """
        group7 = Group().fromAdjacencyList(adjlist7)
        group8 = Group().fromAdjacencyList(adjlist8)

        newGroup = group7.addImplicitAtomsFromAtomType()
        self.assertTrue(group8.isIsomorphic(newGroup))

        #test multiple implicit atoms at a time
        adjlist9 = """
1  *1 Cd u0 {2,S}
2     Ct u0 {1,S}
            """

        adjlist10 = """
1  *1 C u0 {2,S} {3,D}
2     Ct u0 {1,S} {4,T}
3     C  u0 {1,D}
4     C  u0 {2,T}
            """
        group9 = Group().fromAdjacencyList(adjlist9)
        group10 = Group().fromAdjacencyList(adjlist10)

        newGroup = group9.addImplicitAtomsFromAtomType()
        self.assertTrue(group10.isIsomorphic(newGroup))

    def testClassifyBenzeneCarbons(self):
        """
        Tests the method classifyingBenzeneCarbons
        """

        #This tests that we classify Cb atom types correctly
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
"""
        group1 = Group().fromAdjacencyList(adjlist1)

        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2,
         connectedCbfs) = group1.classifyBenzeneCarbons()
        self.assertEquals(len(cbfAtomList), 0)
        for atom in group1.atoms:
            self.assertIn(atom, cbAtomList)

        #This tests that we classify Cbf atomtypes correctly
        adjlist2 = """
1 *1 Cbf u0
"""
        group2 = Group().fromAdjacencyList(adjlist2)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2,
         connectedCbfs) = group2.classifyBenzeneCarbons()
        self.assertIn(group2.atoms[0], cbfAtomList)
        self.assertIn(group2.atoms[0], cbfAtomList1)

        #This tests that we can classify Cb atoms based on bonding and not just atomtype
        adjlist3 = """
1 *1 C u0 {2,B}
2 *2 C u0 {1,B} {3,B}
3 *3 C u0 {2,B}
"""
        group3 = Group().fromAdjacencyList(adjlist3)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2,
         connectedCbfs) = group3.classifyBenzeneCarbons()
        for atom in group3.atoms:
            self.assertIn(atom, cbAtomList)

        #This tests that we can classify Cbf1 atoms based on bonding and not just atomtype
        adjlist4 = """
1 *1 C u0 {2,B} {3,B} {4,B}
2 *2 C u0 {1,B}
3 *3 C u0 {1,B}
4 *4 C u0 {1,B}
"""
        group4 = Group().fromAdjacencyList(adjlist4)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2,
         connectedCbfs) = group4.classifyBenzeneCarbons()
        self.assertEquals(len(cbfAtomList), 1)
        self.assertEquals(len(cbfAtomList1), 1)

        #This tests that we can classify Cbf2 atoms. In the following partial group, we should have:
        #one Cbf2 atom, two Cbf1 atoms, and 5 Cb atoms
        adjlist5 = """
1 *1 C u0 {2,B} {3,B} {4,B}
2 *2 C u0 {1,B} {5,B} {6,B}
3 *3 C u0 {1,B} {7,B} {8,B}
4 *4 C u0 {1,B}
5 *5 C u0 {2,B}
6 *6 C u0 {2,B}
7 *7 C u0 {3,B}
8 *8 C u0 {3,B}
"""
        group5 = Group().fromAdjacencyList(adjlist5)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2,
         connectedCbfs) = group5.classifyBenzeneCarbons()
        self.assertEquals(len(cbfAtomList1), 2)
        self.assertEquals(len(cbfAtomList2), 1)
        self.assertEquals(len(cbAtomList), 5)

        #Tests that we can classify connected Cbfs correctly. *1 should be connected to both *2 and *3
        atom1 = group5.getLabeledAtom("*1")
        atom2 = group5.getLabeledAtom("*2")
        atom3 = group5.getLabeledAtom("*3")
        self.assertIn(atom2, connectedCbfs[atom1])
        self.assertIn(atom3, connectedCbfs[atom1])
        self.assertIn(atom1, connectedCbfs[atom2])
        self.assertIn(atom1, connectedCbfs[atom3])

    def testSortByConnectivity(self):
        """
        Tests sortByConnectivity method
        """

        #Basic test, we should get *1, *3 *2
        adjlist1 = """
1 *1 C u0 {3,B}
2 *2 C u0 {3,B}
3 *3 C u0 {1,B} {2,B}
"""
        group1 = Group().fromAdjacencyList(adjlist1)
        orderedAtoms = group1.sortByConnectivity(group1.atoms)
        self.assertEquals([x.label for x in orderedAtoms], ["*1", "*3", "*2"])

        #Check a detached case, we should get *1, *3, *4, *2, *5
        adjlist2 = """
1 *1 C u0 {3,B}
2 *2 C u0 {4,S} {5,B}
3 *3 C u0 {1,B} {4,B}
4 *4 C u0 {3,B} {2,S}
5 *5 C u0 {2,B}
"""
        group2 = Group().fromAdjacencyList(adjlist2)
        orderedAtoms = group2.sortByConnectivity(group2.atoms)
        self.assertEquals([x.label for x in orderedAtoms],
                          ["*1", "*3", "*4", "*2", "*5"])

    def testAddImplicitBenzene(self):
        """
        Test the Group.addImplicitBenzene method
        """

        #tests it can make a benzene molecule
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
            """
        #tests it can make a bi-phenyl
        adjlist2 = """
1  *1 Cb u0 {2,S}
2  *2 Cb u0 {1,S}
            """
        #tests it can make a napthalene
        adjlist3 = """
1  *1 Cbf u0
            """

        #Test handling of Cbf2 atoms
        adjlist4 = """
1  *1 Cbf u0 p2 c0 {2,B}
2  *2 Cbf u0 p0 c0 {1,B} {3,B}
3  *3 Cbf u0 p0 c0 {2,B}
    """

        #test handling of heteroatoms and wildcards
        adjlist5 = """
1 *1 Cbf u0 {2,B} {3,B} {4,B}
2    R!H u0 {1,B}
3    R!H u0 {1,B}
4    R!H u0 {1,B}
    """
        adjlist6 = """
1  *1 Cbf u0 p2 c0 {2,B}
2  *2 Cb u0 p0 c0 {1,B} {3,B}
3  *3 Cb u0 p0 c0 {2,B} {4,S}
4  *4 O u0 p0 c0 {3,S}
    """

        adjlist7 = """
1 *1 Cb u0 {4,B}
2 *2 Cb u0 {3,B}
3 *3 Cb u0 {4,B} {2,B}
4 *4 Cb u0 {1,B} {3,B}
"""

        benzene = """
1 C u0 {2,B} {6,B}
2 C u0 {1,B} {3,B}
3 C u0 {2,B} {4,B}
4 C u0 {3,B} {5,B}
5 C u0 {4,B} {6,B}
6 C u0 {5,B} {1,B}
        """

        biphenyl = """
1  C u0 {2,B} {6,B} {7,S}
2  C u0 {1,B} {3,B}
3  C u0 {2,B} {4,B}
4  C u0 {3,B} {5,B}
5  C u0 {4,B} {6,B}
6  C u0 {5,B} {1,B}
7  C u0 {8,B} {12,B} {1,S}
8  C u0 {7,B} {9,B}
9  C u0 {8,B} {10,B}
10 C u0 {9,B} {11,B}
11 C u0 {10,B} {12,B}
12  C u0 {11,B} {7,B}
        """

        naphthalene = """
1  C u0 {2,B} {10,B}
2  C u0 {1,B} {3,B}
3  C u0 {2,B} {4,B}
4  C u0 {3,B} {5,B} {9,B}
5  C u0 {4,B} {6,B}
6  C u0 {5,B} {7,B}
7  C u0 {6,B} {8,B}
8  C u0 {7,B} {9,B}
9  C u0 {4,B} {8,B} {10,B}
10 C u0 {1,B} {9,B}
        """

        phenanthrene = """
1  Cbf u0 p2 c0 {2,B} {7,B} {11,B}
2  Cbf u0 p0 c0 {1,B} {3,B} {5,B}
3  Cbf u0 p0 c0 {2,B} {4,B} {6,B}
4  C   u0 {3,B} {8,B} {14,B}
5  C   u0 {2,B} {9,B}
6  C   u0 {3,B} {12,B}
7  C   u0 {1,B} {8,B}
8  C   u0 {4,B} {7,B}
9  C   u0 {5,B} {10,B}
10 C   u0 {9,B} {11,B}
11 C   u0 {1,B} {10,B}
12 C   u0 {6,B} {13,B}
13 C   u0 {12,B} {14,B}
14 C   u0 {4,B} {13,B}
    """

        answer5 = """
1  *1 Cbf u0 {2,B} {3,B} {4,B}
2     R!H u0 {1,B} {5,B}
3     R!H u0 {1,B} {7,B} {10,B}
4     R!H u0 {1,B} {8,B}
5     Cb  u0 {2,B} {6,B}
6     Cb  u0 {5,B} {7,B}
7     Cb  u0 {3,B} {6,B}
8     Cb  u0 {4,B} {9,B}
9     Cb  u0 {8,B} {10,B}
10    Cb  u0 {3,B} {9,B}
"""
        answer6 = """
1  *1 Cbf u0 p2 c0 {2,B} {5,B} {8,B}
2  *2 Cb  u0 p0 c0 {1,B} {3,B} {11,B}
3  *3 Cb  u0 p0 c0 {2,B} {4,S} {7,B}
4  *4 O   u0 p0 c0 {3,S}
5     Cb  u0 {1,B} {6,B}
6     Cb  u0 {5,B} {7,B}
7     Cb  u0 {3,B} {6,B}
8     Cb  u0 {1,B} {9,B}
9     Cb  u0 {8,B} {10,B}
10    Cb  u0 {9,B} {11,B}
11    Cb  u0 {2,B} {10,B}
"""

        group1 = Group().fromAdjacencyList(adjlist1)
        group2 = Group().fromAdjacencyList(adjlist2)
        group3 = Group().fromAdjacencyList(adjlist3)
        group4 = Group().fromAdjacencyList(adjlist4)
        group5 = Group().fromAdjacencyList(adjlist5)
        group6 = Group().fromAdjacencyList(adjlist6)
        group7 = Group().fromAdjacencyList(adjlist7)

        benzeneGroup = Group().fromAdjacencyList(benzene)
        biphenylGroup = Group().fromAdjacencyList(biphenyl)
        naphthaleneGroup = Group().fromAdjacencyList(naphthalene)
        phenanthreneGroup = Group().fromAdjacencyList(phenanthrene)
        answer5 = Group().fromAdjacencyList(answer5)
        answer6 = Group().fromAdjacencyList(answer6)

        group1 = group1.addImplicitBenzene()
        self.assertTrue(benzeneGroup.isIsomorphic(group1))
        group2 = group2.addImplicitBenzene()
        self.assertTrue(biphenylGroup.isIsomorphic(group2))
        group3 = group3.addImplicitBenzene()
        self.assertTrue(naphthaleneGroup.isIsomorphic(group3))
        group4 = group4.addImplicitBenzene()
        self.assertTrue(phenanthreneGroup.isIsomorphic(group4))
        group5 = group5.addImplicitBenzene()
        self.assertTrue(answer5.isIsomorphic(group5))
        group6 = group6.addImplicitBenzene()
        self.assertTrue(answer6.isIsomorphic(group6))
        group7 = group7.addImplicitBenzene()
        self.assertTrue(benzeneGroup.isIsomorphic(group7))

    def testMakeSampleMolecule(self):
        """
        Test the Group.makeSampleMolecule method
        """

        # result = self.group.makeSampleMolecule()
        # print result.multiplicity
        # self.assertTrue(result.isIsomorphic(Molecule().fromSMILES('OCC')))

        #tests adding implicit atoms
        adjlist1 = """
1  *1 Cd u0
            """

        group1 = Group().fromAdjacencyList(adjlist1)
        result1 = group1.makeSampleMolecule()
        self.assertTrue(result1.isIsomorphic(Molecule().fromSMILES('C=C')))

        #test creating implicit benzene atoms
        adjlist2 = """
1  *1 Cbf u0 {2,B}
2     Cbf u0 {1,B}
            """

        group2 = Group().fromAdjacencyList(adjlist2)
        result2 = group2.makeSampleMolecule()
        naphthaleneMolecule = Molecule().fromSMILES('C1=CC=C2C=CC=CC2=C1')
        resonanceList2 = naphthaleneMolecule.generateResonanceIsomers()
        self.assertTrue(any([result2.isIsomorphic(x) for x in resonanceList2]))

        #test the creation of a charged species
        adjlist3 = """
1  *1 N5s u0
        """

        group3 = Group().fromAdjacencyList(adjlist3)
        result3 = group3.makeSampleMolecule()
        self.assertTrue(result3.isIsomorphic(Molecule().fromSMILES('[NH4+]')))

        #test creation of charged species when some single bonds present
        adjlist4 = """
1 *2 [N5s,N5d] u0 {2,S} {3,S}
2 *3 R!H       u1 {1,S}
3 *4 H         u0 {1,S}
"""
        group4 = Group().fromAdjacencyList(adjlist4)
        result4 = group4.makeSampleMolecule()
        self.assertTrue(
            result4.isIsomorphic(Molecule().fromSMILES('[NH3+][CH2]')))

    def testIsBenzeneExplicit(self):
        """
        Test the Group.isBenzeneExplicit method
        """
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
        """
        group1 = Group().fromAdjacencyList(adjlist1)
        self.assertFalse(group1.isBenzeneExplicit())

        benzene = """
1 C u0 {2,B} {6,B}
2 C u0 {1,B} {3,B}
3 C u0 {2,B} {4,B}
4 C u0 {3,B} {5,B}
5 C u0 {4,B} {6,B}
6 C u0 {5,B} {1,B}
        """
        benzene = Group().fromAdjacencyList(benzene)
        self.assertTrue(benzene.isBenzeneExplicit())

    def test_repr_png(self):
        """Test that a png representation can be created."""
        adjlist = """
1 *1 [C,Cd,Ct,CO,CS,Cb] u1 {2,[S,D,T,B]}
2 *2 [C,Cd,Ct,CO,CS,Cb] u0 {1,[S,D,T,B]} {3,[S,D,T,B]}
3 *3 [C,Cd,Ct,CO,CS,Cb] u0 {2,[S,D,T,B]} {4,[S,D,T,B]}
4 *4 [C,Cd,Ct,CO,CS,Cb] u0 {3,[S,D,T,B]}
        """
        group = Group().fromAdjacencyList(adjlist)
        result = group._repr_png_()
        self.assertIsNotNone(result)

    def testDrawGroup(self):
        """Test that the draw method returns the expected pydot graph."""
        adjlist = """
1 *1 [C,Cd,Ct,CO,CS,Cb] u1 {2,[S,D,T,B]}
2 *2 [C,Cd,Ct,CO,CS,Cb] u0 {1,[S,D,T,B]} {3,[S,D,T,B]}
3 *3 [C,Cd,Ct,CO,CS,Cb] u0 {2,[S,D,T,B]} {4,[S,D,T,B]}
4 *4 [C,Cd,Ct,CO,CS,Cb] u0 {3,[S,D,T,B]}
        """
        # Use of tabs in the expected string is intentional
        expected = """
graph G {
	graph [dpi=52];
	node [label="\N"];
	1	 [fontname=Helvetica,
		fontsize=16,
		label="*1 C,Cd,Ct,CO,CS,Cb"];
	2	 [fontname=Helvetica,
		fontsize=16,
		label="*2 C,Cd,Ct,CO,CS,Cb"];
	1 -- 2	 [fontname=Helvetica,
		fontsize=16,
		label="S,D,T,B"];
	3	 [fontname=Helvetica,
		fontsize=16,
		label="*3 C,Cd,Ct,CO,CS,Cb"];
	2 -- 3	 [fontname=Helvetica,
		fontsize=16,
		label="S,D,T,B"];
	4	 [fontname=Helvetica,
		fontsize=16,
		label="*4 C,Cd,Ct,CO,CS,Cb"];
	3 -- 4	 [fontname=Helvetica,
		fontsize=16,
		label="S,D,T,B"];
}
        """
        group = Group().fromAdjacencyList(adjlist)
        result = group.draw('canon')
        self.assertEqual(''.join(result.split()), ''.join(expected.split()))
Пример #2
0
class TestGroup(unittest.TestCase):
    """
    Contains unit tests of the Graph class.
    """
    def setUp(self):
        self.adjlist = """
1 *2 [Cs,Cd] u0 {2,[S,D]} {3,S}
2 *1 [Os,Od] u0 {1,[S,D]}
3    R!H     u0 {1,S}
            """
        self.group = Group().fromAdjacencyList(self.adjlist)

    def testClearLabeledAtoms(self):
        """
        Test the Group.clearLabeledAtoms() method.
        """
        self.group.clearLabeledAtoms()
        for atom in self.group.atoms:
            self.assertEqual(atom.label, '')

    def testContainsLabeledAtom(self):
        """
        Test the Group.containsLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(self.group.containsLabeledAtom(atom.label))
        self.assertFalse(self.group.containsLabeledAtom('*3'))
        self.assertFalse(self.group.containsLabeledAtom('*4'))
        self.assertFalse(self.group.containsLabeledAtom('*5'))
        self.assertFalse(self.group.containsLabeledAtom('*6'))

    def testGetLabeledAtom(self):
        """
        Test the Group.getLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertEqual(atom, self.group.getLabeledAtom(atom.label))
        try:
            self.group.getLabeledAtom('*3')
            self.fail(
                'Unexpected successful return from Group.getLabeledAtom() with invalid atom label.'
            )
        except ValueError:
            pass

    def testGetLabeledAtoms(self):
        """
        Test the Group.getLabeledAtoms() method.
        """
        labeled = self.group.getLabeledAtoms()
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(atom.label in labeled)
                self.assertTrue(atom in labeled.values())
            else:
                self.assertFalse(atom.label in labeled)
                self.assertFalse(atom in labeled.values())

    def testFromAdjacencyList(self):
        """
        Test the Group.fromAdjacencyList() method.
        """
        atom1, atom2, atom3 = self.group.atoms
        self.assertTrue(self.group.hasBond(atom1, atom2))
        self.assertTrue(self.group.hasBond(atom1, atom3))
        self.assertFalse(self.group.hasBond(atom2, atom3))
        bond12 = atom1.bonds[atom2]
        bond13 = atom1.bonds[atom3]

        self.assertTrue(atom1.label == '*2')
        self.assertTrue(atom1.atomType[0].label in ['Cs', 'Cd'])
        self.assertTrue(atom1.atomType[1].label in ['Cs', 'Cd'])
        self.assertTrue(atom1.radicalElectrons == [0])

        self.assertTrue(atom2.label == '*1')
        self.assertTrue(atom2.atomType[0].label in ['Os', 'Od'])
        self.assertTrue(atom2.atomType[1].label in ['Os', 'Od'])
        self.assertTrue(atom2.radicalElectrons == [0])

        self.assertTrue(atom3.label == '')
        self.assertTrue(atom3.atomType[0].label == 'R!H')
        self.assertTrue(atom3.radicalElectrons == [0])

        self.assertTrue(bond12.order == ['S', 'D'])
        self.assertTrue(bond13.order == ['S'])

    def testToAdjacencyList(self):
        """
        Test the Group.toAdjacencyList() method.
        """
        adjlist = self.group.toAdjacencyList()
        self.assertEqual(adjlist.strip(), self.adjlist.strip(), adjlist)

    def testIsIsomorphic(self):
        """
        Test the Group.isIsomorphic() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))

    def testFindIsomorphism(self):
        """
        Test the Group.findIsomorphism() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findIsomorphism(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].items():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))
            for atom3 in atom1.bonds:
                atom4 = result[0][atom3]
                self.assertTrue(atom4 in atom2.bonds)
                self.assertTrue(atom3.equivalent(atom4))
                bond1 = atom1.bonds[atom3]
                bond2 = atom2.bonds[atom4]
                self.assertTrue(bond1.equivalent(bond2))

    def testIsSubgraphIsomorphic(self):
        """
        Test the Group.isSubgraphIsomorphic() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isSubgraphIsomorphic(group))
        self.assertFalse(group.isIsomorphic(self.group))

    def testFindSubgraphIsomorphisms(self):
        """
        Test the Group.findSubgraphIsomorphisms() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findSubgraphIsomorphisms(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].iteritems():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))

    def testPickle(self):
        """
        Test that a Group object can be successfully pickled and
        unpickled with no loss of information.
        """
        import cPickle
        group = cPickle.loads(cPickle.dumps(self.group))

        self.assertEqual(len(self.group.atoms), len(group.atoms))
        for atom0, atom in zip(group.atoms, self.group.atoms):
            self.assertTrue(atom0.equivalent(atom))

        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))
Пример #3
0
class TestGroup(unittest.TestCase):
    """
    Contains unit tests of the Graph class.
    """

    def setUp(self):
        self.adjlist = """
1 *2 [Cs,Cd] u0 {2,[S,D]} {3,S}
2 *1 [Os,Od] u0 {1,[S,D]}
3    R!H     u0 {1,S}
            """
        self.group = Group().fromAdjacencyList(self.adjlist)
        
    def testClearLabeledAtoms(self):
        """
        Test the Group.clearLabeledAtoms() method.
        """
        self.group.clearLabeledAtoms()
        for atom in self.group.atoms:
            self.assertEqual(atom.label, '')

    def testContainsLabeledAtom(self):
        """
        Test the Group.containsLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(self.group.containsLabeledAtom(atom.label))
        self.assertFalse(self.group.containsLabeledAtom('*3'))
        self.assertFalse(self.group.containsLabeledAtom('*4'))
        self.assertFalse(self.group.containsLabeledAtom('*5'))
        self.assertFalse(self.group.containsLabeledAtom('*6'))
        
    def testGetLabeledAtom(self):
        """
        Test the Group.getLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertEqual(atom, self.group.getLabeledAtom(atom.label))
        try:
            self.group.getLabeledAtom('*3')
            self.fail('Unexpected successful return from Group.getLabeledAtom() with invalid atom label.')
        except ValueError:
            pass
            
    def testGetLabeledAtoms(self):
        """
        Test the Group.getLabeledAtoms() method.
        """
        labeled = self.group.getLabeledAtoms()
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(atom.label in labeled)
                self.assertTrue(atom in labeled.values())
            else:
                self.assertFalse(atom.label in labeled)
                self.assertFalse(atom in labeled.values())

    def testFromAdjacencyList(self):
        """
        Test the Group.fromAdjacencyList() method.
        """
        atom1, atom2, atom3 = self.group.atoms
        self.assertTrue(self.group.hasBond(atom1,atom2))
        self.assertTrue(self.group.hasBond(atom1,atom3))
        self.assertFalse(self.group.hasBond(atom2,atom3))
        bond12 = atom1.bonds[atom2]
        bond13 = atom1.bonds[atom3]
           
        self.assertTrue(atom1.label == '*2')
        self.assertTrue(atom1.atomType[0].label in ['Cs','Cd'])
        self.assertTrue(atom1.atomType[1].label in ['Cs','Cd'])
        self.assertTrue(atom1.radicalElectrons == [0])
        
        self.assertTrue(atom2.label == '*1')
        self.assertTrue(atom2.atomType[0].label in ['Os','Od'])
        self.assertTrue(atom2.atomType[1].label in ['Os','Od'])
        self.assertTrue(atom2.radicalElectrons == [0])
        
        self.assertTrue(atom3.label == '')
        self.assertTrue(atom3.atomType[0].label == 'R!H')
        self.assertTrue(atom3.radicalElectrons == [0])

        self.assertTrue(bond12.order == [1,2])
        self.assertTrue(bond13.isSingle())

    def testToAdjacencyList(self):
        """
        Test the Group.toAdjacencyList() method.
        """
        adjlist = self.group.toAdjacencyList()
        self.assertEqual(adjlist.strip(), self.adjlist.strip(),adjlist)

    def testIsIsomorphic(self):
        """
        Test the Group.isIsomorphic() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))
        
    def testFindIsomorphism(self):
        """
        Test the Group.findIsomorphism() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findIsomorphism(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].items():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))
            for atom3 in atom1.bonds:
                atom4 = result[0][atom3]
                self.assertTrue(atom4 in atom2.bonds)
                self.assertTrue(atom3.equivalent(atom4))
                bond1 = atom1.bonds[atom3]
                bond2 = atom2.bonds[atom4]
                self.assertTrue(bond1.equivalent(bond2))
        
    def testIsSubgraphIsomorphic(self):
        """
        Test the Group.isSubgraphIsomorphic() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isSubgraphIsomorphic(group))
        self.assertFalse(group.isIsomorphic(self.group))
        
    def testFindSubgraphIsomorphisms(self):
        """
        Test the Group.findSubgraphIsomorphisms() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findSubgraphIsomorphisms(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].iteritems():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))
        
    def testPickle(self):
        """
        Test that a Group object can be successfully pickled and
        unpickled with no loss of information.
        """
        import cPickle
        group = cPickle.loads(cPickle.dumps(self.group))
        
        self.assertEqual(len(self.group.atoms), len(group.atoms))
        for atom0, atom in zip(group.atoms, self.group.atoms):
            self.assertTrue(atom0.equivalent(atom))

        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))

    def testCreateAndConnectAtom(self):
        """
        Tests createAndConnectAtom method
        """
        adjlist1 = """
1  *1 C u0 {2,S}
2  *2 C u0 {1,S}
"""

        answer1 = """
1  *1 C  u0 {2,S} {3,B}
2  *2 C  u0 {1,S}
3     Cb u0 {1,B}
"""

        group1 = Group().fromAdjacencyList(adjlist1)
        answer1 = Group().fromAdjacencyList(answer1)
        atom1 = group1.getLabeledAtom("*1")
        newAtom = group1.createAndConnectAtom(atomtypes = ["Cb"], connectingAtom = atom1, bondOrders = ["B"])
        self.assertTrue(group1.isIsomorphic(answer1))

        answer2 = """
1  *1 C  u0 {2,S} {3,[S,D]}
2  *2 C  u0 {1,S}
3     [Cs,Cd] u0 {1,[S,D]}
"""

        #Test that wildcards work alright
        group2 = Group().fromAdjacencyList(adjlist1)
        answer2 = Group().fromAdjacencyList(answer2)
        atom1 = group2.getLabeledAtom("*1")
        newAtom = group2.createAndConnectAtom(atomtypes = ["Cs", "Cd"], connectingAtom = atom1, bondOrders = ["S","D"])
        self.assertTrue(group2.isIsomorphic(answer2))



    def testAddImplicitAtomsFromAtomType(self):
        """
        test Group.addImplicitAtomsFromAtomType() method
        """
        #basic test adding oDouble
        adjlist1 = """
1  *1 CO u0
            """

        adjlist2 = """
1  *1 CO u0 {2,D}
2     O  u0 {1,D}
            """

        group1 = Group().fromAdjacencyList(adjlist1)
        group2 = Group().fromAdjacencyList(adjlist2)

        newGroup = group1.addImplicitAtomsFromAtomType()
        self.assertTrue(group2.isIsomorphic(newGroup))
        #testing the allDouble match (more complicated
        adjlist3 = """
1  *1 Cdd u0
            """

        adjlist4 = """
1  *1 Cdd u0 {2,D} {3,D}
2     C   u0 {1,D}
3     C   u0 {1,D}
            """
        group3 = Group().fromAdjacencyList(adjlist3)
        group4 = Group().fromAdjacencyList(adjlist4)

        newGroup =group3.addImplicitAtomsFromAtomType()
        self.assertTrue(group4.isIsomorphic(newGroup))
        #test adding a triple bond
        adjlist5 = """
1  *1 Ct u0
            """

        adjlist6 = """
1  *1 Ct u0 {2,T}
2     C   u0 {1,T}
            """
        group5 = Group().fromAdjacencyList(adjlist5)
        group6 = Group().fromAdjacencyList(adjlist6)

        newGroup =group5.addImplicitAtomsFromAtomType()
        self.assertTrue(group6.isIsomorphic(newGroup))
        #test addition of lone pairs
        adjlist7 = """
1  *1 N1d u0
            """

        adjlist8 = """
1  *1 N1d u0 p2 {2,D}
2     C   u0 {1,D}
            """
        group7 = Group().fromAdjacencyList(adjlist7)
        group8 = Group().fromAdjacencyList(adjlist8)

        newGroup = group7.addImplicitAtomsFromAtomType()
        self.assertTrue(group8.isIsomorphic(newGroup))

        #test multiple implicit atoms at a time
        adjlist9 = """
1  *1 Cd u0 {2,S}
2     Ct u0 {1,S}
            """

        adjlist10 = """
1  *1 C u0 {2,S} {3,D}
2     Ct u0 {1,S} {4,T}
3     C  u0 {1,D}
4     C  u0 {2,T}
            """
        group9 = Group().fromAdjacencyList(adjlist9)
        group10 = Group().fromAdjacencyList(adjlist10)

        newGroup =group9.addImplicitAtomsFromAtomType()
        self.assertTrue(group10.isIsomorphic(newGroup))

    def testClassifyBenzeneCarbons(self):
        """
        Tests the method classifyingBenzeneCarbons
        """

        #This tests that we classify Cb atom types correctly
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
"""
        group1 = Group().fromAdjacencyList(adjlist1)

        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2, connectedCbfs)=group1.classifyBenzeneCarbons()
        self.assertEquals(len(cbfAtomList), 0)
        for atom in group1.atoms:
            self.assertIn(atom, cbAtomList)

        #This tests that we classify Cbf atomtypes correctly
        adjlist2 = """
1 *1 Cbf u0
"""
        group2 = Group().fromAdjacencyList(adjlist2)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2, connectedCbfs)=group2.classifyBenzeneCarbons()
        self.assertIn(group2.atoms[0], cbfAtomList)
        self.assertIn(group2.atoms[0], cbfAtomList1)

        #This tests that we can classify Cb atoms based on bonding and not just atomtype
        adjlist3 = """
1 *1 C u0 {2,B}
2 *2 C u0 {1,B} {3,B}
3 *3 C u0 {2,B}
"""
        group3 = Group().fromAdjacencyList(adjlist3)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2, connectedCbfs)=group3.classifyBenzeneCarbons()
        for atom in group3.atoms:
            self.assertIn(atom, cbAtomList)

        #This tests that we can classify Cbf1 atoms based on bonding and not just atomtype
        adjlist4 = """
1 *1 C u0 {2,B} {3,B} {4,B}
2 *2 C u0 {1,B}
3 *3 C u0 {1,B}
4 *4 C u0 {1,B}
"""
        group4 = Group().fromAdjacencyList(adjlist4)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2, connectedCbfs)=group4.classifyBenzeneCarbons()
        self.assertEquals(len(cbfAtomList), 1)
        self.assertEquals(len(cbfAtomList1), 1)

        #This tests that we can classify Cbf2 atoms. In the following partial group, we should have:
        #one Cbf2 atom, two Cbf1 atoms, and 5 Cb atoms
        adjlist5 = """
1 *1 C u0 {2,B} {3,B} {4,B}
2 *2 C u0 {1,B} {5,B} {6,B}
3 *3 C u0 {1,B} {7,B} {8,B}
4 *4 C u0 {1,B}
5 *5 C u0 {2,B}
6 *6 C u0 {2,B}
7 *7 C u0 {3,B}
8 *8 C u0 {3,B}
"""
        group5 = Group().fromAdjacencyList(adjlist5)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2, connectedCbfs)=group5.classifyBenzeneCarbons()
        self.assertEquals(len(cbfAtomList1), 2)
        self.assertEquals(len(cbfAtomList2), 1)
        self.assertEquals(len(cbAtomList), 5)

        #Tests that we can classify connected Cbfs correctly. *1 should be connected to both *2 and *3
        atom1 = group5.getLabeledAtom("*1")
        atom2 = group5.getLabeledAtom("*2")
        atom3 = group5.getLabeledAtom("*3")
        self.assertIn(atom2, connectedCbfs[atom1])
        self.assertIn(atom3, connectedCbfs[atom1])
        self.assertIn(atom1, connectedCbfs[atom2])
        self.assertIn(atom1, connectedCbfs[atom3])

    def testSortByConnectivity(self):
        """
        Tests sortByConnectivity method
        """

        #Basic test, we should get *1, *3 *2
        adjlist1 = """
1 *1 C u0 {3,B}
2 *2 C u0 {3,B}
3 *3 C u0 {1,B} {2,B}
"""
        group1 = Group().fromAdjacencyList(adjlist1)
        orderedAtoms = group1.sortByConnectivity(group1.atoms)
        self.assertEquals([x.label for x in orderedAtoms], ["*1", "*3", "*2"])

        #Check a detached case, we should get *1, *3, *4, *2, *5
        adjlist2 = """
1 *1 C u0 {3,B}
2 *2 C u0 {4,S} {5,B}
3 *3 C u0 {1,B} {4,B}
4 *4 C u0 {3,B} {2,S}
5 *5 C u0 {2,B}
"""
        group2 = Group().fromAdjacencyList(adjlist2)
        orderedAtoms = group2.sortByConnectivity(group2.atoms)
        self.assertEquals([x.label for x in orderedAtoms], ["*1", "*3", "*4", "*2", "*5"])


    def testAddImplicitBenzene(self):
        """
        Test the Group.addImplicitBenzene method
        """

        #tests it can make a benzene molecule
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
            """
        #tests it can make a bi-phenyl
        adjlist2 = """
1  *1 Cb u0 {2,S}
2  *2 Cb u0 {1,S}
            """
        #tests it can make a napthalene
        adjlist3 = """
1  *1 Cbf u0
            """

        #Test handling of Cbf2 atoms
        adjlist4 = """
1  *1 Cbf u0 p2 c0 {2,B}
2  *2 Cbf u0 p0 c0 {1,B} {3,B}
3  *3 Cbf u0 p0 c0 {2,B}
    """

        #test handling of heteroatoms and wildcards
        adjlist5 = """
1 *1 Cbf u0 {2,B} {3,B} {4,B}
2    R!H u0 {1,B}
3    R!H u0 {1,B}
4    R!H u0 {1,B}
    """
        adjlist6 = """
1  *1 Cbf u0 p2 c0 {2,B}
2  *2 Cb u0 p0 c0 {1,B} {3,B}
3  *3 Cb u0 p0 c0 {2,B} {4,S}
4  *4 O u0 p0 c0 {3,S}
    """

        adjlist7="""
1 *1 Cb u0 {4,B}
2 *2 Cb u0 {3,B}
3 *3 Cb u0 {4,B} {2,B}
4 *4 Cb u0 {1,B} {3,B}
"""

        benzene ="""
1 C u0 {2,B} {6,B}
2 C u0 {1,B} {3,B}
3 C u0 {2,B} {4,B}
4 C u0 {3,B} {5,B}
5 C u0 {4,B} {6,B}
6 C u0 {5,B} {1,B}
        """

        biphenyl ="""
1  C u0 {2,B} {6,B} {7,S}
2  C u0 {1,B} {3,B}
3  C u0 {2,B} {4,B}
4  C u0 {3,B} {5,B}
5  C u0 {4,B} {6,B}
6  C u0 {5,B} {1,B}
7  C u0 {8,B} {12,B} {1,S}
8  C u0 {7,B} {9,B}
9  C u0 {8,B} {10,B}
10 C u0 {9,B} {11,B}
11 C u0 {10,B} {12,B}
12  C u0 {11,B} {7,B}
        """

        naphthalene ="""
1  C u0 {2,B} {10,B}
2  C u0 {1,B} {3,B}
3  C u0 {2,B} {4,B}
4  C u0 {3,B} {5,B} {9,B}
5  C u0 {4,B} {6,B}
6  C u0 {5,B} {7,B}
7  C u0 {6,B} {8,B}
8  C u0 {7,B} {9,B}
9  C u0 {4,B} {8,B} {10,B}
10 C u0 {1,B} {9,B}
        """

        phenanthrene = """
1  Cbf u0 p2 c0 {2,B} {7,B} {11,B}
2  Cbf u0 p0 c0 {1,B} {3,B} {5,B}
3  Cbf u0 p0 c0 {2,B} {4,B} {6,B}
4  C   u0 {3,B} {8,B} {14,B}
5  C   u0 {2,B} {9,B}
6  C   u0 {3,B} {12,B}
7  C   u0 {1,B} {8,B}
8  C   u0 {4,B} {7,B}
9  C   u0 {5,B} {10,B}
10 C   u0 {9,B} {11,B}
11 C   u0 {1,B} {10,B}
12 C   u0 {6,B} {13,B}
13 C   u0 {12,B} {14,B}
14 C   u0 {4,B} {13,B}
    """

        answer5 = """
1  *1 Cbf u0 {2,B} {3,B} {4,B}
2     R!H u0 {1,B} {5,B}
3     R!H u0 {1,B} {7,B} {10,B}
4     R!H u0 {1,B} {8,B}
5     Cb  u0 {2,B} {6,B}
6     Cb  u0 {5,B} {7,B}
7     Cb  u0 {3,B} {6,B}
8     Cb  u0 {4,B} {9,B}
9     Cb  u0 {8,B} {10,B}
10    Cb  u0 {3,B} {9,B}
"""
        answer6="""
1  *1 Cbf u0 p2 c0 {2,B} {5,B} {8,B}
2  *2 Cb  u0 p0 c0 {1,B} {3,B} {11,B}
3  *3 Cb  u0 p0 c0 {2,B} {4,S} {7,B}
4  *4 O   u0 p0 c0 {3,S}
5     Cb  u0 {1,B} {6,B}
6     Cb  u0 {5,B} {7,B}
7     Cb  u0 {3,B} {6,B}
8     Cb  u0 {1,B} {9,B}
9     Cb  u0 {8,B} {10,B}
10    Cb  u0 {9,B} {11,B}
11    Cb  u0 {2,B} {10,B}
"""

        group1 = Group().fromAdjacencyList(adjlist1)
        group2 = Group().fromAdjacencyList(adjlist2)
        group3 = Group().fromAdjacencyList(adjlist3)
        group4 = Group().fromAdjacencyList(adjlist4)
        group5 = Group().fromAdjacencyList(adjlist5)
        group6 = Group().fromAdjacencyList(adjlist6)
        group7 = Group().fromAdjacencyList(adjlist7)

        benzeneGroup = Group().fromAdjacencyList(benzene)
        biphenylGroup = Group().fromAdjacencyList(biphenyl)
        naphthaleneGroup = Group().fromAdjacencyList(naphthalene)
        phenanthreneGroup = Group().fromAdjacencyList(phenanthrene)
        answer5 = Group().fromAdjacencyList(answer5)
        answer6 = Group().fromAdjacencyList(answer6)

        group1 = group1.addImplicitBenzene()
        self.assertTrue(benzeneGroup.isIsomorphic(group1))
        group2 = group2.addImplicitBenzene()
        self.assertTrue(biphenylGroup.isIsomorphic(group2))
        group3 = group3.addImplicitBenzene()
        self.assertTrue(naphthaleneGroup.isIsomorphic(group3))
        group4 = group4.addImplicitBenzene()
        self.assertTrue(phenanthreneGroup.isIsomorphic(group4))
        group5 = group5.addImplicitBenzene()
        self.assertTrue(answer5.isIsomorphic(group5))
        group6 = group6.addImplicitBenzene()
        self.assertTrue(answer6.isIsomorphic(group6))
        group7 = group7.addImplicitBenzene()
        self.assertTrue(benzeneGroup.isIsomorphic(group7))

    def testMakeSampleMolecule(self):
        """
        Test the Group.makeSampleMolecule method
        """

        # result = self.group.makeSampleMolecule()
        # print result.multiplicity
        # self.assertTrue(result.isIsomorphic(Molecule().fromSMILES('OCC')))

        #tests adding implicit atoms
        adjlist1 = """
1  *1 Cd u0
            """

        group1 = Group().fromAdjacencyList(adjlist1)
        result1 = group1.makeSampleMolecule()
        self.assertTrue(result1.isIsomorphic(Molecule().fromSMILES('C=C')))

        #test creating implicit benzene atoms
        adjlist2 = """
1  *1 Cbf u0 {2,B}
2     Cbf u0 {1,B}
            """

        group2 = Group().fromAdjacencyList(adjlist2)
        result2 = group2.makeSampleMolecule()
        naphthaleneMolecule = Molecule().fromSMILES('C1=CC=C2C=CC=CC2=C1')
        resonanceList2=naphthaleneMolecule.generateResonanceIsomers()
        self.assertTrue(any([result2.isIsomorphic(x) for x in resonanceList2]))

        #test the creation of a charged species
        adjlist3 = """
1  *1 N5s u0
        """

        group3 = Group().fromAdjacencyList(adjlist3)
        result3 = group3.makeSampleMolecule()
        self.assertTrue(result3.isIsomorphic(Molecule().fromSMILES('[NH4+]')))

        #test creation of charged species when some single bonds present
        adjlist4 = """
1 *2 [N5s,N5d] u0 {2,S} {3,S}
2 *3 R!H       u1 {1,S}
3 *4 H         u0 {1,S}
"""
        group4 = Group().fromAdjacencyList(adjlist4)
        result4 = group4.makeSampleMolecule()
        self.assertTrue(result4.isIsomorphic(Molecule().fromSMILES('[NH3+][CH2]')))

    def testIsBenzeneExplicit(self):
        """
        Test the Group.isBenzeneExplicit method
        """
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
        """
        group1 = Group().fromAdjacencyList(adjlist1)
        self.assertFalse(group1.isBenzeneExplicit())

        benzene ="""
1 C u0 {2,B} {6,B}
2 C u0 {1,B} {3,B}
3 C u0 {2,B} {4,B}
4 C u0 {3,B} {5,B}
5 C u0 {4,B} {6,B}
6 C u0 {5,B} {1,B}
        """
        benzene = Group().fromAdjacencyList(benzene)
        self.assertTrue(benzene.isBenzeneExplicit())

    def test_repr_png(self):
        """Test that a png representation can be created."""
        adjlist = """
1 *1 [C,Cd,Ct,CO,CS,Cb] u1 {2,[S,D,T,B]}
2 *2 [C,Cd,Ct,CO,CS,Cb] u0 {1,[S,D,T,B]} {3,[S,D,T,B]}
3 *3 [C,Cd,Ct,CO,CS,Cb] u0 {2,[S,D,T,B]} {4,[S,D,T,B]}
4 *4 [C,Cd,Ct,CO,CS,Cb] u0 {3,[S,D,T,B]}
        """
        group = Group().fromAdjacencyList(adjlist)
        result = group._repr_png_()
        self.assertIsNotNone(result)
Пример #4
0
class TestGroup(unittest.TestCase):
    """
    Contains unit tests of the Graph class.
    """

    def setUp(self):
        self.adjlist = """
1 *2 [Cs,Cd] u0 {2,[S,D]} {3,S}
2 *1 [Os,Od] u0 {1,[S,D]}
3    R!H     u0 {1,S}
            """
        self.group = Group().fromAdjacencyList(self.adjlist)
        
    def testClearLabeledAtoms(self):
        """
        Test the Group.clearLabeledAtoms() method.
        """
        self.group.clearLabeledAtoms()
        for atom in self.group.atoms:
            self.assertEqual(atom.label, '')

    def testContainsLabeledAtom(self):
        """
        Test the Group.containsLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(self.group.containsLabeledAtom(atom.label))
        self.assertFalse(self.group.containsLabeledAtom('*3'))
        self.assertFalse(self.group.containsLabeledAtom('*4'))
        self.assertFalse(self.group.containsLabeledAtom('*5'))
        self.assertFalse(self.group.containsLabeledAtom('*6'))
        
    def testGetLabeledAtom(self):
        """
        Test the Group.getLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertEqual(atom, self.group.getLabeledAtom(atom.label))
        try:
            self.group.getLabeledAtom('*3')
            self.fail('Unexpected successful return from Group.getLabeledAtom() with invalid atom label.')
        except ValueError:
            pass
            
    def testGetLabeledAtoms(self):
        """
        Test the Group.getLabeledAtoms() method.
        """
        labeled = self.group.getLabeledAtoms()
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(atom.label in labeled)
                self.assertTrue(atom in labeled.values())
            else:
                self.assertFalse(atom.label in labeled)
                self.assertFalse(atom in labeled.values())

    def testFromAdjacencyList(self):
        """
        Test the Group.fromAdjacencyList() method.
        """
        atom1, atom2, atom3 = self.group.atoms
        self.assertTrue(self.group.hasBond(atom1,atom2))
        self.assertTrue(self.group.hasBond(atom1,atom3))
        self.assertFalse(self.group.hasBond(atom2,atom3))
        bond12 = atom1.bonds[atom2]
        bond13 = atom1.bonds[atom3]
           
        self.assertTrue(atom1.label == '*2')
        self.assertTrue(atom1.atomType[0].label in ['Cs','Cd'])
        self.assertTrue(atom1.atomType[1].label in ['Cs','Cd'])
        self.assertTrue(atom1.radicalElectrons == [0])
        
        self.assertTrue(atom2.label == '*1')
        self.assertTrue(atom2.atomType[0].label in ['Os','Od'])
        self.assertTrue(atom2.atomType[1].label in ['Os','Od'])
        self.assertTrue(atom2.radicalElectrons == [0])
        
        self.assertTrue(atom3.label == '')
        self.assertTrue(atom3.atomType[0].label == 'R!H')
        self.assertTrue(atom3.radicalElectrons == [0])

        self.assertTrue(bond12.order == ['S','D'])
        self.assertTrue(bond13.order == ['S'])

    def testToAdjacencyList(self):
        """
        Test the Group.toAdjacencyList() method.
        """
        adjlist = self.group.toAdjacencyList()
        self.assertEqual(adjlist.strip(), self.adjlist.strip(),adjlist)

    def testIsIsomorphic(self):
        """
        Test the Group.isIsomorphic() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))
        
    def testFindIsomorphism(self):
        """
        Test the Group.findIsomorphism() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findIsomorphism(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].items():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))
            for atom3 in atom1.bonds:
                atom4 = result[0][atom3]
                self.assertTrue(atom4 in atom2.bonds)
                self.assertTrue(atom3.equivalent(atom4))
                bond1 = atom1.bonds[atom3]
                bond2 = atom2.bonds[atom4]
                self.assertTrue(bond1.equivalent(bond2))
        
    def testIsSubgraphIsomorphic(self):
        """
        Test the Group.isSubgraphIsomorphic() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isSubgraphIsomorphic(group))
        self.assertFalse(group.isIsomorphic(self.group))
        
    def testFindSubgraphIsomorphisms(self):
        """
        Test the Group.findSubgraphIsomorphisms() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findSubgraphIsomorphisms(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].iteritems():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))
        
    def testPickle(self):
        """
        Test that a Group object can be successfully pickled and
        unpickled with no loss of information.
        """
        import cPickle
        group = cPickle.loads(cPickle.dumps(self.group))
        
        self.assertEqual(len(self.group.atoms), len(group.atoms))
        for atom0, atom in zip(group.atoms, self.group.atoms):
            self.assertTrue(atom0.equivalent(atom))

        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))
Пример #5
0
class TestGroup(unittest.TestCase):
    """
    Contains unit tests of the Graph class.
    """

    def setUp(self):
        self.adjlist = """
1 *2 [Cs,Cd] u0 {2,[S,D]} {3,S}
2 *1 [Os,Od] u0 {1,[S,D]}
3    R!H     u0 {1,S}
            """
        self.group = Group().fromAdjacencyList(self.adjlist)
        
    def testClearLabeledAtoms(self):
        """
        Test the Group.clearLabeledAtoms() method.
        """
        self.group.clearLabeledAtoms()
        for atom in self.group.atoms:
            self.assertEqual(atom.label, '')

    def testContainsLabeledAtom(self):
        """
        Test the Group.containsLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(self.group.containsLabeledAtom(atom.label))
        self.assertFalse(self.group.containsLabeledAtom('*3'))
        self.assertFalse(self.group.containsLabeledAtom('*4'))
        self.assertFalse(self.group.containsLabeledAtom('*5'))
        self.assertFalse(self.group.containsLabeledAtom('*6'))
        
    def testGetLabeledAtom(self):
        """
        Test the Group.getLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertEqual(atom, self.group.getLabeledAtom(atom.label))
        try:
            self.group.getLabeledAtom('*3')
            self.fail('Unexpected successful return from Group.getLabeledAtom() with invalid atom label.')
        except ValueError:
            pass
            
    def testGetLabeledAtoms(self):
        """
        Test the Group.getLabeledAtoms() method.
        """
        labeled = self.group.getLabeledAtoms()
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(atom.label in labeled)
                self.assertTrue(atom in labeled.values())
            else:
                self.assertFalse(atom.label in labeled)
                self.assertFalse(atom in labeled.values())

    def testFromAdjacencyList(self):
        """
        Test the Group.fromAdjacencyList() method.
        """
        atom1, atom2, atom3 = self.group.atoms
        self.assertTrue(self.group.hasBond(atom1,atom2))
        self.assertTrue(self.group.hasBond(atom1,atom3))
        self.assertFalse(self.group.hasBond(atom2,atom3))
        bond12 = atom1.bonds[atom2]
        bond13 = atom1.bonds[atom3]
           
        self.assertTrue(atom1.label == '*2')
        self.assertTrue(atom1.atomType[0].label in ['Cs','Cd'])
        self.assertTrue(atom1.atomType[1].label in ['Cs','Cd'])
        self.assertTrue(atom1.radicalElectrons == [0])
        
        self.assertTrue(atom2.label == '*1')
        self.assertTrue(atom2.atomType[0].label in ['Os','Od'])
        self.assertTrue(atom2.atomType[1].label in ['Os','Od'])
        self.assertTrue(atom2.radicalElectrons == [0])
        
        self.assertTrue(atom3.label == '')
        self.assertTrue(atom3.atomType[0].label == 'R!H')
        self.assertTrue(atom3.radicalElectrons == [0])

        self.assertTrue(bond12.order == ['S','D'])
        self.assertTrue(bond13.order == ['S'])

    def testToAdjacencyList(self):
        """
        Test the Group.toAdjacencyList() method.
        """
        adjlist = self.group.toAdjacencyList()
        self.assertEqual(adjlist.strip(), self.adjlist.strip(),adjlist)

    def testIsIsomorphic(self):
        """
        Test the Group.isIsomorphic() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))
        
    def testFindIsomorphism(self):
        """
        Test the Group.findIsomorphism() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findIsomorphism(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].items():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))
            for atom3 in atom1.bonds:
                atom4 = result[0][atom3]
                self.assertTrue(atom4 in atom2.bonds)
                self.assertTrue(atom3.equivalent(atom4))
                bond1 = atom1.bonds[atom3]
                bond2 = atom2.bonds[atom4]
                self.assertTrue(bond1.equivalent(bond2))
        
    def testIsSubgraphIsomorphic(self):
        """
        Test the Group.isSubgraphIsomorphic() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isSubgraphIsomorphic(group))
        self.assertFalse(group.isIsomorphic(self.group))
        
    def testFindSubgraphIsomorphisms(self):
        """
        Test the Group.findSubgraphIsomorphisms() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findSubgraphIsomorphisms(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].iteritems():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))
        
    def testPickle(self):
        """
        Test that a Group object can be successfully pickled and
        unpickled with no loss of information.
        """
        import cPickle
        group = cPickle.loads(cPickle.dumps(self.group))
        
        self.assertEqual(len(self.group.atoms), len(group.atoms))
        for atom0, atom in zip(group.atoms, self.group.atoms):
            self.assertTrue(atom0.equivalent(atom))

        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))

    def testAddImplicitAtomsFromAtomType(self):
        """
        test Group.addImplicitAtomsFromAtomType() method
        """
        #basic test adding oDouble
        adjlist1 = """
1  *1 CO u0
            """

        adjlist2 = """
1  *1 CO u0 {2,D}
2     O  u0 {1,D}
            """

        group1 = Group().fromAdjacencyList(adjlist1)
        group2 = Group().fromAdjacencyList(adjlist2)

        newGroup = group1.addImplicitAtomsFromAtomType()
        self.assertTrue(group2.isIsomorphic(newGroup))
        #testing the allDouble match (more complicated
        adjlist3 = """
1  *1 Cdd u0
            """

        adjlist4 = """
1  *1 Cdd u0 {2,D} {3,D}
2     C   u0 {1,D}
3     C   u0 {1,D}
            """
        group3 = Group().fromAdjacencyList(adjlist3)
        group4 = Group().fromAdjacencyList(adjlist4)

        newGroup =group3.addImplicitAtomsFromAtomType()
        self.assertTrue(group4.isIsomorphic(newGroup))
        #test adding a triple bond
        adjlist5 = """
1  *1 Ct u0
            """

        adjlist6 = """
1  *1 Ct u0 {2,T}
2     C   u0 {1,T}
            """
        group5 = Group().fromAdjacencyList(adjlist5)
        group6 = Group().fromAdjacencyList(adjlist6)

        newGroup =group5.addImplicitAtomsFromAtomType()
        self.assertTrue(group6.isIsomorphic(newGroup))
        #test addition of lone pairs
        adjlist7 = """
1  *1 N1d u0
            """

        adjlist8 = """
1  *1 N1d u0 p2 {2,D}
2     C   u0 {1,D}
            """
        group7 = Group().fromAdjacencyList(adjlist7)
        group8 = Group().fromAdjacencyList(adjlist8)

        newGroup = group7.addImplicitAtomsFromAtomType()
        self.assertTrue(group8.isIsomorphic(newGroup))

        #test multiple implicit atoms at a time
        adjlist9 = """
1  *1 Cd u0 {2,S}
2     Ct u0 {1,S}
            """

        adjlist10 = """
1  *1 C u0 {2,S} {3,D}
2     Ct u0 {1,S} {4,T}
3     C  u0 {1,D}
4     C  u0 {2,T}
            """
        group9 = Group().fromAdjacencyList(adjlist9)
        group10 = Group().fromAdjacencyList(adjlist10)

        newGroup =group9.addImplicitAtomsFromAtomType()
        self.assertTrue(group10.isIsomorphic(newGroup))

    def testAddImplicitBenzene(self):
        """
        Test the Group.addImplicitBenzene method
        """

        #tests it can make a benzene molecule
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
            """
        #tests it can make a bi-phenyl
        adjlist2 = """
1  *1 Cb u0 {2,S}
2  *2 Cb u0 {1,S}
            """
        #tests it can make a napthalene
        adjlist3 = """
1  *1 Cbf u0
            """

        #Test handling of Cbf2 atoms
        adjlist4 = """
1  *1 Cbf u0 p2 c0 {2,B}
2  *2 Cbf u0 p0 c0 {1,B} {3,B}
3  *3 Cbf u0 p0 c0 {2,B}
    """

        #test handling of heteroatoms and wildcards
        adjlist5 = """
1 *1 Cbf u0 {2,B} {3,B} {4,B}
2    R!H u0 {1,B}
3    R!H u0 {1,B}
4    R!H u0 {1,B}
    """
        adjlist6 = """
1  *1 Cbf u0 p2 c0 {2,B}
2  *2 Cb u0 p0 c0 {1,B} {3,B}
3  *3 Cb u0 p0 c0 {2,B} {4,S}
4  *4 O u0 p0 c0 {3,S}
    """

        benzene ="""
1 C u0 {2,B} {6,B}
2 C u0 {1,B} {3,B}
3 C u0 {2,B} {4,B}
4 C u0 {3,B} {5,B}
5 C u0 {4,B} {6,B}
6 C u0 {5,B} {1,B}
        """

        biphenyl ="""
1  C u0 {2,B} {6,B} {7,S}
2  C u0 {1,B} {3,B}
3  C u0 {2,B} {4,B}
4  C u0 {3,B} {5,B}
5  C u0 {4,B} {6,B}
6  C u0 {5,B} {1,B}
7  C u0 {8,B} {12,B} {1,S}
8  C u0 {7,B} {9,B}
9  C u0 {8,B} {10,B}
10 C u0 {9,B} {11,B}
11 C u0 {10,B} {12,B}
12  C u0 {11,B} {7,B}
        """

        naphthalene ="""
1  C u0 {2,B} {10,B}
2  C u0 {1,B} {3,B}
3  C u0 {2,B} {4,B}
4  C u0 {3,B} {5,B} {9,B}
5  C u0 {4,B} {6,B}
6  C u0 {5,B} {7,B}
7  C u0 {6,B} {8,B}
8  C u0 {7,B} {9,B}
9  C u0 {4,B} {8,B} {10,B}
10 C u0 {1,B} {9,B}
        """

        phenanthrene = """
1  Cbf u0 p2 c0 {2,B} {7,B} {11,B}
2  Cbf u0 p0 c0 {1,B} {3,B} {5,B}
3  Cbf u0 p0 c0 {2,B} {4,B} {6,B}
4  C   u0 {3,B} {8,B} {14,B}
5  C   u0 {2,B} {9,B}
6  C   u0 {3,B} {12,B}
7  C   u0 {1,B} {8,B}
8  C   u0 {4,B} {7,B}
9  C   u0 {5,B} {10,B}
10 C   u0 {9,B} {11,B}
11 C   u0 {1,B} {10,B}
12 C   u0 {6,B} {13,B}
13 C   u0 {12,B} {14,B}
14 C   u0 {4,B} {13,B}
    """

        answer5 = """
1  *1 Cbf u0 {2,B} {3,B} {4,B}
2     R!H u0 {1,B} {5,B}
3     R!H u0 {1,B} {7,B} {10,B}
4     R!H u0 {1,B} {8,B}
5     Cb  u0 {2,B} {6,B}
6     Cb  u0 {5,B} {7,B}
7     Cb  u0 {3,B} {6,B}
8     Cb  u0 {4,B} {9,B}
9     Cb  u0 {8,B} {10,B}
10    Cb  u0 {3,B} {9,B}
"""
        answer6="""
1  *1 Cbf u0 p2 c0 {2,B} {5,B} {8,B}
2  *2 Cb  u0 p0 c0 {1,B} {3,B} {11,B}
3  *3 Cb  u0 p0 c0 {2,B} {4,S} {7,B}
4  *4 O   u0 p0 c0 {3,S}
5     Cb  u0 {1,B} {6,B}
6     Cb  u0 {5,B} {7,B}
7     Cb  u0 {3,B} {6,B}
8     Cb  u0 {1,B} {9,B}
9     Cb  u0 {8,B} {10,B}
10    Cb  u0 {9,B} {11,B}
11    Cb  u0 {2,B} {10,B}
"""

        group1 = Group().fromAdjacencyList(adjlist1)
        group2 = Group().fromAdjacencyList(adjlist2)
        group3 = Group().fromAdjacencyList(adjlist3)
        group4 = Group().fromAdjacencyList(adjlist4)
        group5 = Group().fromAdjacencyList(adjlist5)
        group6 = Group().fromAdjacencyList(adjlist6)

        benzeneGroup = Group().fromAdjacencyList(benzene)
        biphenylGroup = Group().fromAdjacencyList(biphenyl)
        naphthaleneGroup = Group().fromAdjacencyList(naphthalene)
        phenanthreneGroup = Group().fromAdjacencyList(phenanthrene)
        answer5 = Group().fromAdjacencyList(answer5)
        answer6 = Group().fromAdjacencyList(answer6)

        group1 = group1.addImplicitBenzene()
        self.assertTrue(benzeneGroup.isIsomorphic(group1))
        group2 = group2.addImplicitBenzene()
        self.assertTrue(biphenylGroup.isIsomorphic(group2))
        group3 = group3.addImplicitBenzene()
        self.assertTrue(naphthaleneGroup.isIsomorphic(group3))
        group4 = group4.addImplicitBenzene()
        self.assertTrue(phenanthreneGroup.isIsomorphic(group4))
        group5 = group5.addImplicitBenzene()
        self.assertTrue(answer5.isIsomorphic(group5))
        group6 = group6.addImplicitBenzene()
        self.assertTrue(answer6.isIsomorphic(group6))

    def testMakeSampleMolecule(self):
        """
        Test the Group.makeSampleMolecule method
        """

        # result = self.group.makeSampleMolecule()
        # print result.multiplicity
        # self.assertTrue(result.isIsomorphic(Molecule().fromSMILES('OCC')))

        #tests adding implicit atoms
        adjlist1 = """
1  *1 Cd u0
            """

        group1 = Group().fromAdjacencyList(adjlist1)
        result1 = group1.makeSampleMolecule()
        self.assertTrue(result1.isIsomorphic(Molecule().fromSMILES('C=C')))

        #test creating implicit benzene atoms
        adjlist2 = """
1  *1 Cbf u0 {2,B}
2     Cbf u0 {1,B}
            """

        group2 = Group().fromAdjacencyList(adjlist2)
        result2 = group2.makeSampleMolecule()
        naphthaleneMolecule = Molecule().fromSMILES('C1=CC=C2C=CC=CC2=C1')
        resonanceList2=naphthaleneMolecule.generateResonanceIsomers()
        self.assertTrue(any([result2.isIsomorphic(x) for x in resonanceList2]))

        #test the creation of a charged species
        adjlist3 = """
1  *1 N5s u0
        """

        group3 = Group().fromAdjacencyList(adjlist3)
        result3 = group3.makeSampleMolecule()
        self.assertTrue(result3.isIsomorphic(Molecule().fromSMILES('[NH4+]')))

    def testIsBenzeneExplicit(self):
        """
        Test the Group.isBenzeneExplicit method
        """
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
        """
        group1 = Group().fromAdjacencyList(adjlist1)
        self.assertFalse(group1.isBenzeneExplicit())

        benzene ="""
1 C u0 {2,B} {6,B}
2 C u0 {1,B} {3,B}
3 C u0 {2,B} {4,B}
4 C u0 {3,B} {5,B}
5 C u0 {4,B} {6,B}
6 C u0 {5,B} {1,B}
        """
        benzene = Group().fromAdjacencyList(benzene)
        self.assertTrue(benzene.isBenzeneExplicit())
Пример #6
0
class TestGroup(unittest.TestCase):
    """
    Contains unit tests of the Graph class.
    """

    def setUp(self):
        self.adjlist = """
1 *2 [Cs,Cd] u0 {2,[S,D]} {3,S}
2 *1 [Os,Od] u0 {1,[S,D]}
3    R!H     u0 {1,S}
            """
        self.group = Group().fromAdjacencyList(self.adjlist)
        
    def testClearLabeledAtoms(self):
        """
        Test the Group.clearLabeledAtoms() method.
        """
        self.group.clearLabeledAtoms()
        for atom in self.group.atoms:
            self.assertEqual(atom.label, '')

    def testContainsLabeledAtom(self):
        """
        Test the Group.containsLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(self.group.containsLabeledAtom(atom.label))
        self.assertFalse(self.group.containsLabeledAtom('*3'))
        self.assertFalse(self.group.containsLabeledAtom('*4'))
        self.assertFalse(self.group.containsLabeledAtom('*5'))
        self.assertFalse(self.group.containsLabeledAtom('*6'))
        
    def testGetLabeledAtom(self):
        """
        Test the Group.getLabeledAtom() method.
        """
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertEqual(atom, self.group.getLabeledAtom(atom.label))
        try:
            self.group.getLabeledAtom('*3')
            self.fail('Unexpected successful return from Group.getLabeledAtom() with invalid atom label.')
        except ValueError:
            pass
            
    def testGetLabeledAtoms(self):
        """
        Test the Group.getLabeledAtoms() method.
        """
        labeled = self.group.getLabeledAtoms()
        for atom in self.group.atoms:
            if atom.label != '':
                self.assertTrue(atom.label in labeled)
                self.assertTrue(atom in labeled.values())
            else:
                self.assertFalse(atom.label in labeled)
                self.assertFalse(atom in labeled.values())

    def testFromAdjacencyList(self):
        """
        Test the Group.fromAdjacencyList() method.
        """
        atom1, atom2, atom3 = self.group.atoms
        self.assertTrue(self.group.hasBond(atom1,atom2))
        self.assertTrue(self.group.hasBond(atom1,atom3))
        self.assertFalse(self.group.hasBond(atom2,atom3))
        bond12 = atom1.bonds[atom2]
        bond13 = atom1.bonds[atom3]
           
        self.assertTrue(atom1.label == '*2')
        self.assertTrue(atom1.atomType[0].label in ['Cs','Cd'])
        self.assertTrue(atom1.atomType[1].label in ['Cs','Cd'])
        self.assertTrue(atom1.radicalElectrons == [0])
        
        self.assertTrue(atom2.label == '*1')
        self.assertTrue(atom2.atomType[0].label in ['Os','Od'])
        self.assertTrue(atom2.atomType[1].label in ['Os','Od'])
        self.assertTrue(atom2.radicalElectrons == [0])
        
        self.assertTrue(atom3.label == '')
        self.assertTrue(atom3.atomType[0].label == 'R!H')
        self.assertTrue(atom3.radicalElectrons == [0])

        self.assertTrue(bond12.order == [1,2])
        self.assertTrue(bond13.isSingle())

    def testToAdjacencyList(self):
        """
        Test the Group.toAdjacencyList() method.
        """
        adjlist = self.group.toAdjacencyList()
        self.assertEqual(adjlist.strip(), self.adjlist.strip(),adjlist)

    def testIsIsomorphic(self):
        """
        Test the Group.isIsomorphic() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))
        
    def testFindIsomorphism(self):
        """
        Test the Group.findIsomorphism() method.
        """
        adjlist = """
1  *1 [Os,Od] u0 {3,[S,D]}
2     R!H     u0 {3,S}
3  *2 [Cs,Cd] u0 {1,[S,D]} {2,S}
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findIsomorphism(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].items():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))
            for atom3 in atom1.bonds:
                atom4 = result[0][atom3]
                self.assertTrue(atom4 in atom2.bonds)
                self.assertTrue(atom3.equivalent(atom4))
                bond1 = atom1.bonds[atom3]
                bond2 = atom2.bonds[atom4]
                self.assertTrue(bond1.equivalent(bond2))
        
    def testIsSubgraphIsomorphic(self):
        """
        Test the Group.isSubgraphIsomorphic() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        self.assertTrue(self.group.isSubgraphIsomorphic(group))
        self.assertFalse(group.isIsomorphic(self.group))
        
    def testFindSubgraphIsomorphisms(self):
        """
        Test the Group.findSubgraphIsomorphisms() method.
        """
        adjlist = """
1  *1 [Cs,Cd] u0
            """
        group = Group().fromAdjacencyList(adjlist)
        result = self.group.findSubgraphIsomorphisms(group)
        self.assertEqual(len(result), 1)
        for atom1, atom2 in result[0].iteritems():
            self.assertTrue(atom1 in self.group.atoms)
            self.assertTrue(atom2 in group.atoms)
            self.assertTrue(atom1.equivalent(atom2))
        
    def testPickle(self):
        """
        Test that a Group object can be successfully pickled and
        unpickled with no loss of information.
        """
        import cPickle
        group = cPickle.loads(cPickle.dumps(self.group))
        
        self.assertEqual(len(self.group.atoms), len(group.atoms))
        for atom0, atom in zip(group.atoms, self.group.atoms):
            self.assertTrue(atom0.equivalent(atom))

        self.assertTrue(self.group.isIsomorphic(group))
        self.assertTrue(group.isIsomorphic(self.group))

    def testCreateAndConnectAtom(self):
        """
        Tests createAndConnectAtom method
        """
        adjlist1 = """
1  *1 C u0 {2,S}
2  *2 C u0 {1,S}
"""

        answer1 = """
1  *1 C  u0 {2,S} {3,B}
2  *2 C  u0 {1,S}
3     Cb u0 {1,B}
"""

        group1 = Group().fromAdjacencyList(adjlist1)
        answer1 = Group().fromAdjacencyList(answer1)
        atom1 = group1.getLabeledAtom("*1")
        newAtom = group1.createAndConnectAtom(atomtypes = ["Cb"], connectingAtom = atom1, bondOrders = ["B"])
        self.assertTrue(group1.isIsomorphic(answer1))

        answer2 = """
1  *1 C  u0 {2,S} {3,[S,D]}
2  *2 C  u0 {1,S}
3     [Cs,Cd] u0 {1,[S,D]}
"""

        #Test that wildcards work alright
        group2 = Group().fromAdjacencyList(adjlist1)
        answer2 = Group().fromAdjacencyList(answer2)
        atom1 = group2.getLabeledAtom("*1")
        newAtom = group2.createAndConnectAtom(atomtypes = ["Cs", "Cd"], connectingAtom = atom1, bondOrders = ["S","D"])
        self.assertTrue(group2.isIsomorphic(answer2))



    def testAddImplicitAtomsFromAtomType(self):
        """
        test Group.addImplicitAtomsFromAtomType() method
        """
        #basic test adding oDouble
        adjlist1 = """
1  *1 CO u0
            """

        adjlist2 = """
1  *1 CO u0 {2,D}
2     O  u0 {1,D}
            """

        group1 = Group().fromAdjacencyList(adjlist1)
        group2 = Group().fromAdjacencyList(adjlist2)

        newGroup = group1.addImplicitAtomsFromAtomType()
        self.assertTrue(group2.isIsomorphic(newGroup))
        #testing the allDouble match (more complicated
        adjlist3 = """
1  *1 Cdd u0
            """

        adjlist4 = """
1  *1 Cdd u0 {2,D} {3,D}
2     C   u0 {1,D}
3     C   u0 {1,D}
            """
        group3 = Group().fromAdjacencyList(adjlist3)
        group4 = Group().fromAdjacencyList(adjlist4)

        newGroup =group3.addImplicitAtomsFromAtomType()
        self.assertTrue(group4.isIsomorphic(newGroup))
        #test adding a triple bond
        adjlist5 = """
1  *1 Ct u0
            """

        adjlist6 = """
1  *1 Ct u0 {2,T}
2     C   u0 {1,T}
            """
        group5 = Group().fromAdjacencyList(adjlist5)
        group6 = Group().fromAdjacencyList(adjlist6)

        newGroup =group5.addImplicitAtomsFromAtomType()
        self.assertTrue(group6.isIsomorphic(newGroup))
        #test addition of lone pairs
        adjlist7 = """
1  *1 N1d u0
            """

        adjlist8 = """
1  *1 N1d u0 p2 {2,D}
2     C   u0 {1,D}
            """
        group7 = Group().fromAdjacencyList(adjlist7)
        group8 = Group().fromAdjacencyList(adjlist8)

        newGroup = group7.addImplicitAtomsFromAtomType()
        self.assertTrue(group8.isIsomorphic(newGroup))

        #test multiple implicit atoms at a time
        adjlist9 = """
1  *1 Cd u0 {2,S}
2     Ct u0 {1,S}
            """

        adjlist10 = """
1  *1 C u0 {2,S} {3,D}
2     Ct u0 {1,S} {4,T}
3     C  u0 {1,D}
4     C  u0 {2,T}
            """
        group9 = Group().fromAdjacencyList(adjlist9)
        group10 = Group().fromAdjacencyList(adjlist10)

        newGroup =group9.addImplicitAtomsFromAtomType()
        self.assertTrue(group10.isIsomorphic(newGroup))

    def testClassifyBenzeneCarbons(self):
        """
        Tests the method classifyingBenzeneCarbons
        """

        #This tests that we classify Cb atom types correctly
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
"""
        group1 = Group().fromAdjacencyList(adjlist1)

        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2, connectedCbfs)=group1.classifyBenzeneCarbons()
        self.assertEquals(len(cbfAtomList), 0)
        for atom in group1.atoms:
            self.assertIn(atom, cbAtomList)

        #This tests that we classify Cbf atomtypes correctly
        adjlist2 = """
1 *1 Cbf u0
"""
        group2 = Group().fromAdjacencyList(adjlist2)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2, connectedCbfs)=group2.classifyBenzeneCarbons()
        self.assertIn(group2.atoms[0], cbfAtomList)
        self.assertIn(group2.atoms[0], cbfAtomList1)

        #This tests that we can classify Cb atoms based on bonding and not just atomtype
        adjlist3 = """
1 *1 C u0 {2,B}
2 *2 C u0 {1,B} {3,B}
3 *3 C u0 {2,B}
"""
        group3 = Group().fromAdjacencyList(adjlist3)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2, connectedCbfs)=group3.classifyBenzeneCarbons()
        for atom in group3.atoms:
            self.assertIn(atom, cbAtomList)

        #This tests that we can classify Cbf1 atoms based on bonding and not just atomtype
        adjlist4 = """
1 *1 C u0 {2,B} {3,B} {4,B}
2 *2 C u0 {1,B}
3 *3 C u0 {1,B}
4 *4 C u0 {1,B}
"""
        group4 = Group().fromAdjacencyList(adjlist4)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2, connectedCbfs)=group4.classifyBenzeneCarbons()
        self.assertEquals(len(cbfAtomList), 1)
        self.assertEquals(len(cbfAtomList1), 1)

        #This tests that we can classify Cbf2 atoms. In the following partial group, we should have:
        #one Cbf2 atom, two Cbf1 atoms, and 5 Cb atoms
        adjlist5 = """
1 *1 C u0 {2,B} {3,B} {4,B}
2 *2 C u0 {1,B} {5,B} {6,B}
3 *3 C u0 {1,B} {7,B} {8,B}
4 *4 C u0 {1,B}
5 *5 C u0 {2,B}
6 *6 C u0 {2,B}
7 *7 C u0 {3,B}
8 *8 C u0 {3,B}
"""
        group5 = Group().fromAdjacencyList(adjlist5)
        (cbAtomList, cbfAtomList, cbfAtomList1, cbfAtomList2, connectedCbfs)=group5.classifyBenzeneCarbons()
        self.assertEquals(len(cbfAtomList1), 2)
        self.assertEquals(len(cbfAtomList2), 1)
        self.assertEquals(len(cbAtomList), 5)

        #Tests that we can classify connected Cbfs correctly. *1 should be connected to both *2 and *3
        atom1 = group5.getLabeledAtom("*1")
        atom2 = group5.getLabeledAtom("*2")
        atom3 = group5.getLabeledAtom("*3")
        self.assertIn(atom2, connectedCbfs[atom1])
        self.assertIn(atom3, connectedCbfs[atom1])
        self.assertIn(atom1, connectedCbfs[atom2])
        self.assertIn(atom1, connectedCbfs[atom3])

    def testSortByConnectivity(self):
        """
        Tests sortByConnectivity method
        """

        #Basic test, we should get *1, *3 *2
        adjlist1 = """
1 *1 C u0 {3,B}
2 *2 C u0 {3,B}
3 *3 C u0 {1,B} {2,B}
"""
        group1 = Group().fromAdjacencyList(adjlist1)
        orderedAtoms = group1.sortByConnectivity(group1.atoms)
        self.assertEquals([x.label for x in orderedAtoms], ["*1", "*3", "*2"])

        #Check a detached case, we should get *1, *3, *4, *2, *5
        adjlist2 = """
1 *1 C u0 {3,B}
2 *2 C u0 {4,S} {5,B}
3 *3 C u0 {1,B} {4,B}
4 *4 C u0 {3,B} {2,S}
5 *5 C u0 {2,B}
"""
        group2 = Group().fromAdjacencyList(adjlist2)
        orderedAtoms = group2.sortByConnectivity(group2.atoms)
        self.assertEquals([x.label for x in orderedAtoms], ["*1", "*3", "*4", "*2", "*5"])


    def testAddImplicitBenzene(self):
        """
        Test the Group.addImplicitBenzene method
        """

        #tests it can make a benzene molecule
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
            """
        #tests it can make a bi-phenyl
        adjlist2 = """
1  *1 Cb u0 {2,S}
2  *2 Cb u0 {1,S}
            """
        #tests it can make a napthalene
        adjlist3 = """
1  *1 Cbf u0
            """

        #Test handling of Cbf2 atoms
        adjlist4 = """
1  *1 Cbf u0 p2 c0 {2,B}
2  *2 Cbf u0 p0 c0 {1,B} {3,B}
3  *3 Cbf u0 p0 c0 {2,B}
    """

        #test handling of heteroatoms and wildcards
        adjlist5 = """
1 *1 Cbf u0 {2,B} {3,B} {4,B}
2    R!H u0 {1,B}
3    R!H u0 {1,B}
4    R!H u0 {1,B}
    """
        adjlist6 = """
1  *1 Cbf u0 p2 c0 {2,B}
2  *2 Cb u0 p0 c0 {1,B} {3,B}
3  *3 Cb u0 p0 c0 {2,B} {4,S}
4  *4 O u0 p0 c0 {3,S}
    """

        adjlist7="""
1 *1 Cb u0 {4,B}
2 *2 Cb u0 {3,B}
3 *3 Cb u0 {4,B} {2,B}
4 *4 Cb u0 {1,B} {3,B}
"""

        benzene ="""
1 C u0 {2,B} {6,B}
2 C u0 {1,B} {3,B}
3 C u0 {2,B} {4,B}
4 C u0 {3,B} {5,B}
5 C u0 {4,B} {6,B}
6 C u0 {5,B} {1,B}
        """

        biphenyl ="""
1  C u0 {2,B} {6,B} {7,S}
2  C u0 {1,B} {3,B}
3  C u0 {2,B} {4,B}
4  C u0 {3,B} {5,B}
5  C u0 {4,B} {6,B}
6  C u0 {5,B} {1,B}
7  C u0 {8,B} {12,B} {1,S}
8  C u0 {7,B} {9,B}
9  C u0 {8,B} {10,B}
10 C u0 {9,B} {11,B}
11 C u0 {10,B} {12,B}
12  C u0 {11,B} {7,B}
        """

        naphthalene ="""
1  C u0 {2,B} {10,B}
2  C u0 {1,B} {3,B}
3  C u0 {2,B} {4,B}
4  C u0 {3,B} {5,B} {9,B}
5  C u0 {4,B} {6,B}
6  C u0 {5,B} {7,B}
7  C u0 {6,B} {8,B}
8  C u0 {7,B} {9,B}
9  C u0 {4,B} {8,B} {10,B}
10 C u0 {1,B} {9,B}
        """

        phenanthrene = """
1  Cbf u0 p2 c0 {2,B} {7,B} {11,B}
2  Cbf u0 p0 c0 {1,B} {3,B} {5,B}
3  Cbf u0 p0 c0 {2,B} {4,B} {6,B}
4  C   u0 {3,B} {8,B} {14,B}
5  C   u0 {2,B} {9,B}
6  C   u0 {3,B} {12,B}
7  C   u0 {1,B} {8,B}
8  C   u0 {4,B} {7,B}
9  C   u0 {5,B} {10,B}
10 C   u0 {9,B} {11,B}
11 C   u0 {1,B} {10,B}
12 C   u0 {6,B} {13,B}
13 C   u0 {12,B} {14,B}
14 C   u0 {4,B} {13,B}
    """

        answer5 = """
1  *1 Cbf u0 {2,B} {3,B} {4,B}
2     R!H u0 {1,B} {5,B}
3     R!H u0 {1,B} {7,B} {10,B}
4     R!H u0 {1,B} {8,B}
5     Cb  u0 {2,B} {6,B}
6     Cb  u0 {5,B} {7,B}
7     Cb  u0 {3,B} {6,B}
8     Cb  u0 {4,B} {9,B}
9     Cb  u0 {8,B} {10,B}
10    Cb  u0 {3,B} {9,B}
"""
        answer6="""
1  *1 Cbf u0 p2 c0 {2,B} {5,B} {8,B}
2  *2 Cb  u0 p0 c0 {1,B} {3,B} {11,B}
3  *3 Cb  u0 p0 c0 {2,B} {4,S} {7,B}
4  *4 O   u0 p0 c0 {3,S}
5     Cb  u0 {1,B} {6,B}
6     Cb  u0 {5,B} {7,B}
7     Cb  u0 {3,B} {6,B}
8     Cb  u0 {1,B} {9,B}
9     Cb  u0 {8,B} {10,B}
10    Cb  u0 {9,B} {11,B}
11    Cb  u0 {2,B} {10,B}
"""

        group1 = Group().fromAdjacencyList(adjlist1)
        group2 = Group().fromAdjacencyList(adjlist2)
        group3 = Group().fromAdjacencyList(adjlist3)
        group4 = Group().fromAdjacencyList(adjlist4)
        group5 = Group().fromAdjacencyList(adjlist5)
        group6 = Group().fromAdjacencyList(adjlist6)
        group7 = Group().fromAdjacencyList(adjlist7)

        benzeneGroup = Group().fromAdjacencyList(benzene)
        biphenylGroup = Group().fromAdjacencyList(biphenyl)
        naphthaleneGroup = Group().fromAdjacencyList(naphthalene)
        phenanthreneGroup = Group().fromAdjacencyList(phenanthrene)
        answer5 = Group().fromAdjacencyList(answer5)
        answer6 = Group().fromAdjacencyList(answer6)

        group1 = group1.addImplicitBenzene()
        self.assertTrue(benzeneGroup.isIsomorphic(group1))
        group2 = group2.addImplicitBenzene()
        self.assertTrue(biphenylGroup.isIsomorphic(group2))
        group3 = group3.addImplicitBenzene()
        self.assertTrue(naphthaleneGroup.isIsomorphic(group3))
        group4 = group4.addImplicitBenzene()
        self.assertTrue(phenanthreneGroup.isIsomorphic(group4))
        group5 = group5.addImplicitBenzene()
        self.assertTrue(answer5.isIsomorphic(group5))
        group6 = group6.addImplicitBenzene()
        self.assertTrue(answer6.isIsomorphic(group6))
        group7 = group7.addImplicitBenzene()
        self.assertTrue(benzeneGroup.isIsomorphic(group7))

    def testPickWildcards(self):
        """
        Test the Group.pickWildCards function
        """
        #The following tests are for picking optimal bond orders when there are bond wilcards
        #test that Cb/Cbf atoms with [D,B] chooses [B] instead of [D] bonds
        adjlist1 = """
    1 *1 R!H       u1 {2,[D,B]}
    2 *2 [Cbf,Cdd] u0 {1,[D,B]} {3,[D,B]}
    3 *3 [Cb,Cd]   u0 {2,[D,B]} {4,S}
    4 *4 R!H       u0 {3,S} {5,S}
    5 *5 H         u0 {4,S}
"""
        group1 = Group().fromAdjacencyList(adjlist1)
        group1.pickWildcards()
        atoms = group1.atoms
        self.assertTrue(atoms[0].bonds[atoms[1]].isBenzene())
        self.assertTrue(atoms[1].bonds[atoms[2]].isBenzene())

        adjlist2 = """
    1 *1 R!H       u1 {2,[S,D]} {4,[S,D]}
    2 *2 [CO,Cdd]  u0 {1,[S,D]} {3,[S,D]}
    3 *3 [Od,Cd]   u0 {2,[S,D]}
    4 *4 [Cdd,Cd]  u0 {1,[S,D]}
"""
        group2 = Group().fromAdjacencyList(adjlist2)
        group2.pickWildcards()
        atoms = group2.atoms
        self.assertTrue(atoms[1].bonds[atoms[2]].isDouble)
        self.assertTrue(atoms[0].bonds[atoms[3]].isDouble)

    def testMakeSampleMolecule(self):
        """
        Test the Group.makeSampleMolecule method
        """

        def performSampMoleComparison(adjlist, answer_smiles):
            """
            Creates a sample molecule from the adjlist and returns if it is isomorphic to a molecule created from
            the inputted smiles
            """
            group = Group().fromAdjacencyList(adjlist)
            result = group.makeSampleMolecule()
            return (result.isIsomorphic(Molecule().fromSMILES(answer_smiles)))
########################################################################################################################
        #tests adding implicit atoms
        adjlist = """
1  *1 Cd u0
            """
        answer_smiles = 'C=C'
        self.assertTrue(performSampMoleComparison(adjlist, answer_smiles))

        #test creating implicit benzene atoms
        adjlist2 = """
1  *1 Cbf u0 {2,B}
2     Cbf u0 {1,B}
            """

        group2 = Group().fromAdjacencyList(adjlist2)
        result2 = group2.makeSampleMolecule()
        naphthaleneMolecule = Molecule().fromSMILES('C1=CC=C2C=CC=CC2=C1')
        resonanceList2=naphthaleneMolecule.generateResonanceIsomers()
        self.assertTrue(any([result2.isIsomorphic(x) for x in resonanceList2]))

        #test the creation of a positively charged species
        adjlist = """
1  *1 N5s u0
        """
        answer_smiles = '[NH4+]'
        self.assertTrue(performSampMoleComparison(adjlist, answer_smiles))

        #test the creation of a negatively charged species
        #commented out until new nitrogen atom types added in
#         adjlist = """
# 1  *1 N2s u0
#         """
#         answer_smiles = '[NH2-]'
#         self.assertTrue(performSampMoleComparison(adjlist, answer_smiles))

        #test creation of charged species when some single bonds present
        adjlist = """
1 *2 [N5s,N5d] u0 {2,S} {3,S}
2 *3 R!H       u1 {1,S}
3 *4 H         u0 {1,S}
"""
        answer_smiles = '[NH3+][CH2]'
        self.assertTrue(performSampMoleComparison(adjlist, answer_smiles))

    def testIsBenzeneExplicit(self):
        """
        Test the Group.isBenzeneExplicit method
        """
        adjlist1 = """
1  *1 Cb u0 {2,B}
2  *2 Cb u0 {1,B}
        """
        group1 = Group().fromAdjacencyList(adjlist1)
        self.assertFalse(group1.isBenzeneExplicit())

        benzene ="""
1 C u0 {2,B} {6,B}
2 C u0 {1,B} {3,B}
3 C u0 {2,B} {4,B}
4 C u0 {3,B} {5,B}
5 C u0 {4,B} {6,B}
6 C u0 {5,B} {1,B}
        """
        benzene = Group().fromAdjacencyList(benzene)
        self.assertTrue(benzene.isBenzeneExplicit())

    def test_repr_png(self):
        """Test that a png representation can be created."""
        adjlist = """
1 *1 [C,Cd,Ct,CO,CS,Cb] u1 {2,[S,D,T,B]}
2 *2 [C,Cd,Ct,CO,CS,Cb] u0 {1,[S,D,T,B]} {3,[S,D,T,B]}
3 *3 [C,Cd,Ct,CO,CS,Cb] u0 {2,[S,D,T,B]} {4,[S,D,T,B]}
4 *4 [C,Cd,Ct,CO,CS,Cb] u0 {3,[S,D,T,B]}
        """
        group = Group().fromAdjacencyList(adjlist)
        result = group._repr_png_()
        self.assertIsNotNone(result)

    def testDrawGroup(self):
        """Test that the draw method returns the expected pydot graph."""
        adjlist = """
1 *1 [C,Cd,Ct,CO,CS,Cb] u1 {2,[S,D,T,B]}
2 *2 [C,Cd,Ct,CO,CS,Cb] u0 {1,[S,D,T,B]} {3,[S,D,T,B]}
3 *3 [C,Cd,Ct,CO,CS,Cb] u0 {2,[S,D,T,B]} {4,[S,D,T,B]}
4 *4 [C,Cd,Ct,CO,CS,Cb] u0 {3,[S,D,T,B]}
        """
        # Use of tabs in the expected string is intentional
        expected = """
graph G {
	graph [dpi=52];
	node [label="\N"];
	1	 [fontname=Helvetica,
		fontsize=16,
		label="*1 C,Cd,Ct,CO,CS,Cb"];
	2	 [fontname=Helvetica,
		fontsize=16,
		label="*2 C,Cd,Ct,CO,CS,Cb"];
	1 -- 2	 [fontname=Helvetica,
		fontsize=16,
		label="S,D,T,B"];
	3	 [fontname=Helvetica,
		fontsize=16,
		label="*3 C,Cd,Ct,CO,CS,Cb"];
	2 -- 3	 [fontname=Helvetica,
		fontsize=16,
		label="S,D,T,B"];
	4	 [fontname=Helvetica,
		fontsize=16,
		label="*4 C,Cd,Ct,CO,CS,Cb"];
	3 -- 4	 [fontname=Helvetica,
		fontsize=16,
		label="S,D,T,B"];
}
        """
        group = Group().fromAdjacencyList(adjlist)
        result = group.draw('canon')
        self.assertEqual(''.join(result.split()), ''.join(expected.split()))

    def testMergeGroups(self):
        """
        Test the mergeGroups() function
        """
        #basic test of merging a backbone and end group
        backbone1 = Group().fromAdjacencyList("""
1 *1 R!H u1 {2,S}
2 *4 R!H u0 {1,S} {3,S}
3 *6 R!H u0 {2,S} {4,S}
4 *5 R!H u0 {3,S} {5,S}
5 *2 R!H u0 {4,S} {6,S}
6 *3 H   u0 {5,S}
""")

        end1 = Group().fromAdjacencyList("""
1 *2 Cs u0 {2,S} {3,S}
2 *3 H  u0 {1,S}
3    S  u0 {1,S}
""")
        desiredMerge1 = Group().fromAdjacencyList("""
1 *1 R!H u1 {2,S}
2 *4 R!H u0 {1,S} {3,S}
3 *6 R!H u0 {2,S} {4,S}
4 *5 R!H u0 {3,S} {5,S}
5 *2 Cs  u0 {4,S} {6,S} {7,S}
6 *3 H   u0 {5,S}
7    S   u0 {5,S}
""")

        mergedGroup = backbone1.mergeGroups(end1)
        self.assertTrue(mergedGroup.isIdentical(desiredMerge1))

        #test it works when there is a cyclical structure to the backbone

        backbone2 = Group().fromAdjacencyList("""
1 *1 R!H u1 {2,S} {4,S}
2 *4 R!H u0 {1,S} {3,S}
3 *2 R!H u0 {2,S} {4,S}
4 *3 R!H u0 {3,S} {1,S}
""")

        end2 = Group().fromAdjacencyList("""
1 *2 Os u0 {2,S}
2 *3 Cs u0 {1,S}
""")
        desiredMerge2 = Group().fromAdjacencyList("""
1 *1 R!H u1 {2,S} {4,S}
2 *4 R!H u0 {1,S} {3,S}
3 *2 Os u0 {2,S} {4,S}
4 *3 Cs u0 {3,S} {1,S}
""")
        mergedGroup = backbone2.mergeGroups(end2)
        self.assertTrue(mergedGroup.isIdentical(desiredMerge2))