def test_isotopic_molecule_2(self):
        """Test that we can generate an InChI for an isotopic molecule."""
        mol = Molecule().fromSMILES('[13CH3]C')

        inchi = 'InChI=1S/C2H6/c1-2/h1-2H3/i1+1'

        self.assertEqual(mol.toInChI(), inchi)
    def test_disconnected_molecule(self):
        """Test that we can generate an InChI for a disconnected molecule."""
        mol = Molecule().fromSMILES('CCCCO.C=O')

        inchi = 'InChI=1S/C4H10O.CH2O/c1-2-3-4-5;1-2/h5H,2-4H2,1H3;1H2'

        self.assertEqual(mol.toInChI(), inchi)
Example #3
0
def getAdjacencyList(request, identifier):
    """
    Returns an adjacency list of the species corresponding to `identifier`.
    
    `identifier` should be something recognized by NCI resolver, eg.
    SMILES, InChI, CACTVS, chemical name, etc.
    
    The NCI resolver has some bugs regarding reading SMILES of radicals.
    E.g. it thinks CC[CH] is CCC, so we first try to use the identifier
    directly as a SMILES string, and only pass it through the resolver
    if that does not work. 
    """
    if identifier.strip() == '':
        return HttpResponse('', mimetype="text/plain")
    from rmgpy.molecule.molecule import Molecule
    molecule = Molecule()
    try:
        # try using the string as a SMILES directly
        molecule.fromSMILES(str(identifier))
    except IOError:
        # try converting it to a SMILES using the NCI chemical resolver 
        url = "http://cactus.nci.nih.gov/chemical/structure/{0}/smiles".format(urllib.quote(identifier))
        try:
            f = urllib2.urlopen(url, timeout=5)
        except urllib2.URLError, e:
            return HttpResponseNotFound("404: Couldn't identify {0}. NCI resolver responded {1} to request for {2}".format(identifier, e, url))
        smiles = f.read()
        molecule.fromSMILES(smiles)
Example #4
0
 def testAromaticNaphthalene(self):
     """
     Test the Molecule.isAromatic() method for Naphthalene.
     """
     m = Molecule().fromSMILES('C12C(C=CC=C1)=CC=CC=2')
     isomers = m.generateResonanceIsomers()
     self.assertTrue(any(isomer.isAromatic() for isomer in isomers))
    def testAtomSymmetryNumberEthanewithDeuteriumTritium(self):
        """
        Test the Molecule.calculateAtomSymmetryNumber() on CC(D)(T)

        This is meant to test whether chirality is accounted for, which
        should half the symmetry term.

        The total number is 1.5 because the methyl group contributes *3 and
        the chiral center contributes *0.5
        """
        molecule = Molecule().fromAdjacencyList(
"""
1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S}
2 C u0 p0 c0 {1,S} {6,S} {7,S} {8,S}
3 D u0 p0 c0 {1,S}
4 T u0 p0 c0 {1,S}
5 H u0 p0 c0 {1,S}
6 H u0 p0 c0 {2,S}
7 H u0 p0 c0 {2,S}
8 H u0 p0 c0 {2,S}

""")
        symmetryNumber = 1
        for atom in molecule.atoms:
            if not molecule.isAtomInCycle(atom):
                symmetryNumber *= calculateAtomSymmetryNumber(molecule, atom)
        self.assertAlmostEqual(symmetryNumber, 1.5)
def test_isomorphism_sulfurGroup_sulfurMolecule():
    """
    Test isormophism check of a CS group vs. a sulfur containing molecule
    """
    gp1 = Group().fromAdjacencyList("""
1 S  u0 {2,S} {3,S}
2 H  u0 {1,S}
3 C u0 {1,S} {4,D}
4 S  u0 {3,D}
""")
    
    gp2 = Group().fromAdjacencyList("""
1 S  u0 {2,S} {3,S}
2 H  u0 {1,S}
3 CS u0 {1,S} {4,D}
4 S  u0 {3,D}
""")
    
    mol = Molecule().fromAdjacencyList("""
1 S  0 {2,S} {3,S}
2 H  0 {1,S}
3 C 0 {1,S} {4,D} {5,S}
4 S 0 {3,D}
5 H 0 {3,S}
""")
    assert_true(mol.isSubgraphIsomorphic(gp1))
    
    assert_true(mol.isSubgraphIsomorphic(gp2))
Example #7
0
    def testToAdjacencyList(self):
        """
        adjlist: Test the Molecule.toAdjacencyList() method.
        """
        inter_adjlist = """
1 *1 C 1 0  {2,S} {3,S} {4,S}
2    H 0 0  {1,S}
3    H 0 0  {1,S}
4 *2 N 0 0 {1,S} {5,S} {6,D}
5    O 0 3 {4,S}
6    O 0 2 {4,D}
            """
            
        adjlist = """
1 *1 C u1 p0 c0  {2,S} {3,S} {4,S}
2    H u0 p0 c0  {1,S}
3    H u0 p0 c0  {1,S}
4 *2 N u0 p0 c+1 {1,S} {5,S} {6,D}
5    O u0 p3 c-1 {4,S}
6    O u0 p2 c0  {4,D}
            """
        molecule = Molecule().fromAdjacencyList(adjlist)
        molecule2 = Molecule().fromAdjacencyList(inter_adjlist)
        adjlist_1 = molecule.toAdjacencyList(removeH=False)
        self.assertEqual(adjlist_1,molecule2.toAdjacencyList())
        newMolecule = Molecule().fromAdjacencyList(adjlist_1)
        self.assertTrue(molecule.isIsomorphic(newMolecule))
def test_isotope_subgraph_isomorphism_molecule_and_group():
    """
    Checks that subgraph isomorphism works with enriched molecules and groups
    """
    methanei = Molecule().fromAdjacencyList("""
    1 C u0 p0 c0 i13 {2,S} {3,S} {4,S} {5,S}
    2 H u0 p0 c0 {1,S}
    3 H u0 p0 c0 {1,S}
    4 H u0 p0 c0 {1,S}
    5 H u0 p0 c0 {1,S}
    """)
    methane = Molecule().fromAdjacencyList("""
    1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S}
    2 H u0 p0 c0 {1,S}
    3 H u0 p0 c0 {1,S}
    4 H u0 p0 c0 {1,S}
    5 H u0 p0 c0 {1,S}
    """)
    group_methane = Group().fromAdjacencyList("""
    1 C  u0 {2,S} {3,S} {4,S} {5,S}
    2 H  u0 {1,S}
    3 H  u0 {1,S}
    4 H  u0 {1,S}
    5 H  u0 {1,S}
    """)
    assert_true(methanei.isSubgraphIsomorphic(group_methane))
    assert_true(methane.isSubgraphIsomorphic(group_methane))
    assert_false(methanei.isIsomorphic(methane))
Example #9
0
    def testAddPolyRingCorrectionThermoDataFromHeuristicUsingAlkaneTricyclic(self):

        # create testing molecule
        smiles = 'C1CC2CCCC3C(C1)C23'
        mol = Molecule().fromSMILES(smiles)
        
        # extract polyring from the molecule
        polyring = mol.getDisparateRings()[1][0]

        thermoData = ThermoData(
            Tdata = ([300,400,500,600,800,1000,1500],"K"),
            Cpdata = ([0.0,0.0,0.0,0.0,0.0,0.0,0.0],"J/(mol*K)"),
            H298 = (0.0,"kJ/mol"),
            S298 = (0.0,"J/(mol*K)"),
        )

        self.database._ThermoDatabase__addPolyRingCorrectionThermoDataFromHeuristic(
            thermoData, polyring)

        ringGroups, polycyclicGroups = self.database.getRingGroupsFromComments(thermoData)

        ringGroupLabels = [ringGroup.label for ringGroup in ringGroups]
        polycyclicGroupLabels = [polycyclicGroup.label for polycyclicGroup in polycyclicGroups]

        self.assertIn('Cyclohexane', ringGroupLabels)
        self.assertIn('Cyclopropane', ringGroupLabels)
        self.assertIn('s2_6_6_ane', polycyclicGroupLabels)
        self.assertIn('s2_3_6_ane', polycyclicGroupLabels)
Example #10
0
    def testBicyclicDecompositionForPolyringUsingAlkaneTricyclic(self):

        # create testing molecule
        smiles = 'C1CC2CCCC3C(C1)C23'
        mol = Molecule().fromSMILES(smiles)
        
        # extract polyring from the molecule
        polyring = mol.getDisparateRings()[1][0]

        bicyclicList, ringOccurancesDict = bicyclicDecompositionForPolyring(polyring)

        # 1st test: number of cores
        self.assertEqual(len(bicyclicList), 3)

        # 2nd test: ringOccurancesDict
        ringInCoreOccurances = sorted(ringOccurancesDict.values())
        expectedRingInCoreOccurances = [2, 2, 2]
        self.assertEqual(ringInCoreOccurances, expectedRingInCoreOccurances)

        # 3rd test: size of each bicyclic core
        bicyclicSizes = sorted([len(bicyclic.atoms) for bicyclic in bicyclicList])
        expectedBicyclicSizes = [7, 7, 10]
        self.assertEqual(bicyclicSizes, expectedBicyclicSizes)

        # 4th test: bond info for members of each core
        aromaticBondNumInBicyclics = []
        for bicyclic in bicyclicList:
            aromaticBondNum = len(findAromaticBondsFromSubMolecule(bicyclic))
            aromaticBondNumInBicyclics.append(aromaticBondNum)
        aromaticBondNumInBicyclics = sorted(aromaticBondNumInBicyclics)
        expectedAromaticBondNumInBicyclics = [0, 0, 0]
        self.assertEqual(aromaticBondNumInBicyclics, expectedAromaticBondNumInBicyclics)
Example #11
0
 def testAromaticCyclohexane(self):
     """
     Test the Molecule.isAromatic() method for Cyclohexane.
     """
     m = Molecule().fromSMILES('C1CCCCC1')
     isomers = m.generateResonanceIsomers()
     self.assertFalse(any(isomer.isAromatic() for isomer in isomers))
Example #12
0
 def testIsomorphism(self):
     """
     Check the graph isomorphism functions.
     """
     molecule1 = Molecule().fromSMILES('C=CC=C[CH]C')
     molecule2 = Molecule().fromSMILES('C[CH]C=CC=C')
     self.assertTrue(molecule1.isIsomorphic(molecule2))
     self.assertTrue(molecule2.isIsomorphic(molecule1))
Example #13
0
 def testRadicalCH2(self):
     """
     Test that the species [CH2] has two radical electrons and a spin multiplicity of 3.
     """
     molecule = Molecule().fromSMILES('[CH2]')
     self.assertEqual(molecule.atoms[0].radicalElectrons, 2)
     self.assertEqual(molecule.multiplicity, 3)
     self.assertEqual(molecule.getRadicalCount(), 2)
Example #14
0
 def testFromOldAdjacencyList1(self):
     """
     Test we can read an old style adjacency list with implicit hydrogens 1
     """
     adjList = """
     1 O 0 
     """  # should be Water
     molecule = Molecule().fromAdjacencyList(adjList)  
     self.assertEqual(molecule.getFormula(), 'H2O')
Example #15
0
 def testFromIntermediateAdjacencyList1(self):
     """
     Test we can read an intermediate style adjacency list with implicit hydrogens 1
     """
     adjList = """
     1 O 0 2
     """  # should be Water
     molecule = Molecule().fromAdjacencyList(adjList, saturateH=True)  
     self.assertEqual(molecule.getFormula(), 'H2O')
Example #16
0
def methyl_in_ethane():
    """
        12 possible ways to put CH3 in H3C-CH3:
        
        2 possibilities for the carbon atom
        
        3! possibilities to organize the 3 H-atoms.
        
        total = 2 * 3! = 12
        
        """
    
    adjlist_mol = """
        1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S}
        2 C u0 p0 c0 {1,S} {6,S} {7,S} {8,S}
        3 H u0 p0 c0 {1,S}
        4 H u0 p0 c0 {1,S}
        5 H u0 p0 c0 {1,S}
        6 H u0 p0 c0 {2,S}
        7 H u0 p0 c0 {2,S}
        8 H u0 p0 c0 {2,S}
        """
    #mol = Group().fromAdjacencyList(adjlist_mol)
    mol=  Molecule().fromAdjacencyList(adjlist_mol)
    
    adjlist_group = """
        1 C ux p0 c0 {2,S} {3,S} {4,S}
        2 H u0 p0 c0 {1,S}
        3 H u0 p0 c0 {1,S}
        4 H u0 p0 c0 {1,S}
        """
    group = Group().fromAdjacencyList(adjlist_group)
    
    
    K= np.zeros((4,8))
    R= np.zeros((8,4))
    
    result = mol.findSubgraphIsomorphisms(group)
    
    
    for i, match in enumerate(result):
        print 'Match no: {}'.format(i)
        
        for k,v in match.iteritems():
            
            molatno = mol.atoms.index(k)
            gratno = group.atoms.index(v)
            print 'Mol atom number: {}, Group atom number: {}'.format(molatno, gratno)
            K[gratno,molatno]= K[gratno,molatno]+1
            R[molatno,gratno]= R[molatno,gratno]+1
    
    K= K / (len(result))
    R= R / (len(result))
    
    print K
    print R
    return result
Example #17
0
 def compare(self, adjlist, smiles):
     """
     Compare result of parsing an adjacency list and a SMILES string.
     
     The adjacency list is presumed correct and this is to test the SMILES parser.
     """
     mol1 = Molecule().fromAdjacencyList(adjlist)
     mol2 = Molecule(SMILES=smiles)
     self.assertTrue(mol1.isIsomorphic(mol2), "Parsing SMILES={!r} gave unexpected molecule\n{}".format(smiles, mol2.toAdjacencyList()))
Example #18
0
 def testAugmentedInChI(self):
     """
     Test that Augmented InChI generation is printing the /mult layer
     """
     mol = Molecule().fromAdjacencyList("""
         1     C     u1 p0 c0 {2,S}
         2     C     u1 p0 c0 {1,S}
     """, saturateH=True)
     
     self.assertEqual(mol.toAugmentedInChI(), 'InChI=1S/C2H4/c1-2/h1-2H2/mult3')
 def clean_detergent(self):
     """
     Return molecular representation of input detergent structure        """
     try:
         detergent = Molecule()
         detergent.fromAdjacencyList(str(self.cleaned_data['detergent']))
     except Exception, e:
         import traceback
         traceback.print_exc(e)
         raise forms.ValidationError('Invalid SMILES entry.')
def test_isomorphism_R():
    mol = Molecule().fromAdjacencyList("""
    1 C u0 p0 c0
    """, saturateH=True)
    
    gp = Group().fromAdjacencyList("""
    1 R u0 p0 c0
    """)
    
    assert_true(len(mol.findSubgraphIsomorphisms(gp)) > 0)
 def testAtomSymmetryNumberEthane(self):
     """
     Test the Molecule.calculateAtomSymmetryNumber() on CC
     """
     molecule = Molecule().fromSMILES('CC')
     symmetryNumber = 1
     for atom in molecule.atoms:
         if not molecule.isAtomInCycle(atom):
             symmetryNumber *= calculateAtomSymmetryNumber(molecule, atom)
     self.assertEqual(symmetryNumber, 9)
    def testSpeciesSymmetryNumberIsNotMoleculeSymmetryNumber(self):
        """
        Tests that the species symmetry number can be different from the molecule symmetry number

        This molecule's resonance isomer hybrid should return more symmetry
        than the base molecule object.
        """
        molecule = Molecule().fromSMILES('C[CH]C=CC')
        species = Species(molecule=[molecule])
        self.assertEqual(molecule.getSymmetryNumber() * 2, species.getSymmetryNumber())
 def testAtomSymmetryNumberMethyl(self):
     """
     Test the Molecule.calculateAtomSymmetryNumber() on [CH3]
     """
     molecule = Molecule().fromSMILES('[CH3]')
     symmetryNumber = 1
     for atom in molecule.atoms:
         if not molecule.isAtomInCycle(atom):
             symmetryNumber *= calculateAtomSymmetryNumber(molecule, atom)
     self.assertEqual(symmetryNumber, 6)
Example #24
0
 def testAugmentedInChIKey(self):
     """
     Test that Augmented InChI Key generation is printing the mult layer
     """
     mol = Molecule().fromAdjacencyList("""
         1     C     u1 p0 c0 {2,S}
         2     C     u1 p0 c0 {1,S}
     """, saturateH=True)
     
     self.assertEqual(mol.toAugmentedInChIKey(), 'VGGSQFUCUMXWEO-UHFFFAOYSAmult3')
Example #25
0
 def testSSSR(self):
     """
     Test the Molecule.getSmallestSetOfSmallestRings() method with a complex
     polycyclic molecule.
     """
     molecule = Molecule()
     molecule.fromSMILES('C(CC1C(C(CCCCCCCC)C1c1ccccc1)c1ccccc1)CCCCCC')
     #http://cactus.nci.nih.gov/chemical/structure/C(CC1C(C(CCCCCCCC)C1c1ccccc1)c1ccccc1)CCCCCC/image
     sssr = molecule.getSmallestSetOfSmallestRings()
     self.assertEqual( len(sssr), 3)
Example #26
0
 def testIsInCycleEthane(self):
     """
     Test the Molecule.isInCycle() method with ethane.
     """
     molecule = Molecule().fromSMILES('CC')
     for atom in molecule.atoms:
         self.assertFalse(molecule.isAtomInCycle(atom))
     for atom1 in molecule.atoms:
         for atom2, bond in atom1.bonds.items():
             self.assertFalse(molecule.isBondInCycle(bond))
Example #27
0
 def testGetSymmetryNumber(self):
     """
     Test that the symmetry number getter works properly
     """
     
     mol = Molecule().fromSMILES('C')
     
     self.assertEquals(12, mol.getSymmetryNumber())
     
     empty = Molecule()
     self.assertEquals(1, empty.getSymmetryNumber())
class TestVF2(unittest.TestCase):
    """
    Contains unit tests of the methods for computing symmetry numbers for a
    given Molecule object.
    """

    def setUp(self):
        self.vf2 = VF2()
        self.mol = Molecule().fromSMILES("CC(=O)C[CH2]")
        self.mol2 = self.mol.copy(deep=True)

    def test_import_graph(self):
        """Test that we can add graphs to the object and that they are sorted"""

        self.mol.sortVertices()
        
        ordered_original_connectivity_order = [getVertexConnectivityValue(atom) for atom in self.mol.atoms]

        self.vf2.graphA = self.mol
        self.vf2.graphB = self.mol2
        
        final_connectivity_order = [getVertexConnectivityValue(atom) for atom in self.vf2.graphA.atoms]
        final_connectivity_order2 = [getVertexConnectivityValue(atom) for atom in self.vf2.graphB.atoms]

        testing.assert_array_equal(final_connectivity_order,final_connectivity_order2)
        testing.assert_array_equal(final_connectivity_order,ordered_original_connectivity_order)

    def test_feasible(self):
        """
        Test that feasibility returns correct values on highly functional molecule
        
        `feasible` method isn't perfect in assigning values but it should do a good
        job on highly functional values
        """
        
        self.vf2.graphA = self.mol
        self.vf2.graphB = self.mol2

        for atom1 in self.vf2.graphA.atoms:
            for atom2 in self.vf2.graphB.atoms:
                # same connectivity values should result in `feasible` being true
                if getVertexConnectivityValue(atom1) == getVertexConnectivityValue(atom2):
                    self.assertTrue(self.vf2.feasible(atom1, atom2))
                else: # different connectivity values should return false
                    self.assertFalse(self.vf2.feasible(atom1, atom2))

    def test_clear_mapping(self):
        """Test that vertex mapping is cleared after isomorphism."""
        self.vf2.isIsomorphic(self.mol, self.mol2, None)

        for atom in self.mol.atoms:
            self.assertIsNone(atom.mapping)
            self.assertFalse(atom.terminal)
Example #29
0
    def testToOldAjacencyList(self):
        """
        adjlist: Check that we can convert back to old style adjacency list
        """
        molecule2 = Molecule().fromSMILES('C=CC=C[CH]C')
        string = """1 C 0 {2,D}
2 C 0 {1,D} {3,S}
3 C 0 {2,S} {4,D}
4 C 0 {3,D} {5,S}
5 C 1 {4,S} {6,S}
6 C 0 {5,S}"""
        self.assertEqual(molecule2.toAdjacencyList(removeH=True,oldStyle=True).strip(),string.strip())
 def clean_reactant1(self):
     """
     Custom validation for the reactant1 field to ensure that a valid
     adjacency list has been provided.
     """
     try:
         molecule = Molecule()
         molecule.fromAdjacencyList(str(self.cleaned_data['reactant1']))
     except Exception, e:
         import traceback
         traceback.print_exc(e)
         raise forms.ValidationError('Invalid adjacency list.')
Example #31
0
 def test_bond_symmetry_number_acetylene(self):
     """
     Test the Molecule.calculate_bond_symmetry_number() on C#C
     """
     molecule = Molecule().from_smiles('C#C')
     symmetry_number = 1
     for atom1 in molecule.atoms:
         for atom2 in list(atom1.bonds):
             if molecule.atoms.index(atom1) < molecule.atoms.index(atom2):
                 symmetry_number *= calculate_bond_symmetry_number(
                     molecule, atom1, atom2)
     self.assertEqual(symmetry_number, 2)
Example #32
0
def rmg_mol_from_inchi(inchi):
    """
    Generate an RMG Molecule object from InChI
    """
    try:
        rmg_mol = Molecule().fromInChI(str(inchi))
    except (AtomTypeError, ValueError) as e:
        logging.warning(
            'Got the following Error when trying to create an RMG Molecule object from '
            'InChI:\n{0}'.format(e.message))
        return None
    return rmg_mol
Example #33
0
 def testBondSymmetryNumberAllyl(self):
     """
     Test the Molecule.calculateBondSymmetryNumber() on [CH2]C=C
     """
     spc = Species(molecule=[Molecule().fromSMILES('[CH2]C=C')])
     molecule = spc.getResonanceHybrid()
     symmetryNumber = 1
     for atom1 in molecule.atoms:
         for atom2 in atom1.bonds:
             if molecule.atoms.index(atom1) < molecule.atoms.index(atom2):
                 symmetryNumber *= calculateBondSymmetryNumber(molecule, atom1, atom2)
     self.assertEqual(symmetryNumber, 1)
Example #34
0
    def testSubgraphIsomorphism(self):
        """
        Check the graph isomorphism functions.
        """
        molecule = Molecule().fromSMILES('C=CC=C[CH]C')
        group = Group().fromAdjacencyList("""
        1 Cd u0 p0 c0 {2,D}
        2 Cd u0 p0 c0 {1,D}
        """)

        self.assertTrue(molecule.isSubgraphIsomorphic(group))
        mapping = molecule.findSubgraphIsomorphisms(group)
        self.assertTrue(
            len(mapping) == 4,
            "len(mapping) = %d, should be = 4" % (len(mapping)))
        for map in mapping:
            self.assertTrue(
                len(map) == min(len(molecule.atoms), len(group.atoms)))
            for key, value in map.iteritems():
                self.assertTrue(key in molecule.atoms)
                self.assertTrue(value in group.atoms)
Example #35
0
    def test_surface_molecule_ob(self):
        """Test InChI generation for a surface molecule using OpenBabel"""
        mol = Molecule().from_adjacency_list("""
1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S}
2 H u0 p0 c0 {1,S}
3 H u0 p0 c0 {1,S}
4 H u0 p0 c0 {1,S}
5 X u0 p0 c0 {1,S}
""")
        smiles = 'C[Pt]'

        self.assertEqual(to_smiles(mol, backend='openbabel'), smiles)
Example #36
0
    def test_surface_molecule_ob(self):
        """Test InChI generation for a surface molecule using OpenBabel"""
        mol = Molecule().from_adjacency_list("""
1 C u0 p0 c0 {2,S} {3,S} {4,S} {5,S}
2 H u0 p0 c0 {1,S}
3 H u0 p0 c0 {1,S}
4 H u0 p0 c0 {1,S}
5 X u0 p0 c0 {1,S}
""")
        inchi = 'InChI=1S/CH3.Pt/h1H3;'

        self.assertEqual(to_inchi(mol, backend='openbabel'), inchi)
Example #37
0
def createMolecule(element, u1, c1):
    from rmgpy.molecule.adjlist import InvalidAdjacencyListError
    adjlist = get_molecule_string(element, u1, c1)
    logging.info('Creating molecule: {0}'.format(adjlist))
    mol = None
    try:
        mol = Molecule().fromAdjacencyList(adjlist)
    except (ValueError, InvalidAdjacencyListError):
        # Either a non-neutral molecule, incompatible multiplcity, or an improper valence
        # was assigned with this combination.
        pass
    return mol, adjlist
Example #38
0
 def testBondSymmetryNumberAcetylene(self):
     """
     Test the Molecule.calculateBondSymmetryNumber() on C#C
     """
     molecule = Molecule().fromSMILES('C#C')
     symmetryNumber = 1
     for atom1 in molecule.atoms:
         for atom2 in atom1.bonds:
             if molecule.atoms.index(atom1) < molecule.atoms.index(atom2):
                 symmetryNumber *= calculateBondSymmetryNumber(
                     molecule, atom1, atom2)
     self.assertEqual(symmetryNumber, 2)
Example #39
0
 def test_atom_symmetry_number_allyl(self):
     """
     Test the Molecule.calculate_atom_symmetry_number() on [CH2]C=C
     """
     spc = Species(molecule=[Molecule().from_smiles('[CH2]C=C')])
     molecule = spc.get_resonance_hybrid()
     symmetry_number = 1
     for atom in molecule.atoms:
         if not molecule.is_atom_in_cycle(atom):
             symmetry_number *= calculate_atom_symmetry_number(
                 molecule, atom)
     self.assertEqual(symmetry_number, 2)
Example #40
0
 def testSymmetryContributionRadicals(self):
     """
     Test that the symmetry contribution is correctly added for radicals
     estimated via the HBI method. 
     """
     spc = Species(molecule=[Molecule().fromSMILES('[CH3]')])
     
     thermoData_lib = self.database.getThermoDataFromLibraries(spc)[0]
     
     thermoData_ga = self.database.getThermoDataFromGroups(spc)
     
     self.assertAlmostEqual(thermoData_lib.getEntropy(298.), thermoData_ga.getEntropy(298.), 0)
Example #41
0
    def test_singlet_vs_triplet(self):
        adjlist_singlet = """
        1 C u0 p1 c0 {2,S} {3,S}
        2 H u0 p0 c0 {1,S}
        3 H u0 p0 c0 {1,S}
        """

        adjlist_triplet = """
        multiplicity 3
        1 C u2 p0 c0 {2,S} {3,S}
        2 H u0 p0 c0 {1,S}
        3 H u0 p0 c0 {1,S}
        """

        singlet = Species(
            molecule=[Molecule().from_adjacency_list(adjlist_singlet)])
        triplet = Species(
            molecule=[Molecule().from_adjacency_list(adjlist_triplet)])
        singlet_aug_inchi = singlet.get_augmented_inchi()
        triplet_aug_inchi = triplet.get_augmented_inchi()
        self.assertTrue(singlet_aug_inchi != triplet_aug_inchi)
Example #42
0
    def test_add_atom_labels_for_reaction(self):
        """Test that addAtomLabelsForReaction can identify reactions with resonance
        The molecule [CH]=C=C has resonance in this reaction"""
        from rmgpy.data.rmg import getDB
        reactants = [
            Molecule().fromSMILES('C=C=C'),
            Molecule().fromSMILES('[CH]=C=C'),
        ]
        products = [
            Molecule().fromSMILES('C#C[CH2]'),
            Molecule().fromSMILES('C#CC'),
        ]
        reaction = TemplateReaction(reactants =reactants,
                                    products = products,
                                    family = 'H_Abstraction')
        reaction.ensure_species(reactant_resonance=True, product_resonance=True)
        family = getDB('kinetics').families['H_Abstraction']
        family.addAtomLabelsForReaction(reaction, output_with_resonance=False)

        # test that the reaction has labels
        found_labels = []
        for species in reaction.reactants:
            for atom in species.molecule[0].atoms:
                if atom.label != '':
                    found_labels.append(atom.label)
        self.assertEqual(len(found_labels), 3)
        self.assertIn('*1',found_labels)
        self.assertIn('*2',found_labels)
        self.assertIn('*3',found_labels)

        # test for the products too
        found_labels = []
        for species in reaction.products:
            for atom in species.molecule[0].atoms:
                if atom.label != '':
                    found_labels.append(atom.label)
        self.assertEqual(len(found_labels), 3)
        self.assertIn('*1',found_labels)
        self.assertIn('*2',found_labels)
        self.assertIn('*3',found_labels)
Example #43
0
def test_isomorphism_wrong_mapping():
    """
    Checks isomorphism finds things not isomorphic if given a wrong mapping.
    """
    # These molecules are not isomorphic
    n1butane = Molecule().from_adjacency_list("""
        1 *1 X u0 p0 c0 {2,S}
        2 *2 C u0 p0 c0 {1,S} {3,S} {5,S} {6,S}
        3 *3 C u0 p0 c0 {2,S} {4,S} {7,S} {8,S}
        4 *4 H u0 p0 c0 {3,S}
        5    H u0 p0 c0 {2,S}
        6    H u0 p0 c0 {2,S}
        7    H u0 p0 c0 {3,S}
        8    C u0 p0 c0 {3,S} {9,S} {10,S} {11,S}
        9    H u0 p0 c0 {8,S}
        10   H u0 p0 c0 {8,S}
        11   C u0 p0 c0 {8,S} {12,S} {13,S} {14,S}
        12   H u0 p0 c0 {11,S}
        13   H u0 p0 c0 {11,S}
        14   H u0 p0 c0 {11,S}
        """)

    n2butane = Molecule().from_adjacency_list("""
        1 *1 X u0 p0 c0 {3,S}
        2 *2 C u0 p0 c0 {3,S} {5,S} {6,S} {4,S}
        3 *3 C u0 p0 c0 {2,S} {1,S} {7,S} {8,S}
        4 *4 H u0 p0 c0 {2,S}
        5    H u0 p0 c0 {2,S}
        6    H u0 p0 c0 {2,S}
        7    H u0 p0 c0 {3,S}
        8    C u0 p0 c0 {3,S} {9,S} {10,S} {11,S}
        9    H u0 p0 c0 {8,S}
        10   H u0 p0 c0 {8,S}
        11   C u0 p0 c0 {8,S} {12,S} {13,S} {14,S}
        12   H u0 p0 c0 {11,S}
        13   H u0 p0 c0 {11,S}
        14   H u0 p0 c0 {11,S}
        """)
    assert_false(n1butane.is_isomorphic(n2butane))
    assert_false(n1butane.is_isomorphic(n2butane, generate_initial_map=True))
    
    mapping = {}
    for label in ['*1', '*2', '*3', '*4']:
        mapping[n1butane.get_labeled_atoms(label)[0]] = n2butane.get_labeled_atoms(label)[0]
    assert_false(n1butane.is_isomorphic(n2butane, initial_map=mapping))
Example #44
0
    def testIsAromaticRing(self):

        # create testing rings
        smiles1 = 'C1CCC1'
        smiles2 = 'C1CCCCC1'
        adj3 = """1  C u0 p0 c0 {2,B} {6,B} {7,S}
2  C u0 p0 c0 {1,B} {3,B} {8,S}
3  C u0 p0 c0 {2,B} {4,B} {9,S}
4  C u0 p0 c0 {3,B} {5,B} {10,S}
5  C u0 p0 c0 {4,B} {6,B} {11,S}
6  C u0 p0 c0 {1,B} {5,B} {12,S}
7  H u0 p0 c0 {1,S}
8  H u0 p0 c0 {2,S}
9  H u0 p0 c0 {3,S}
10 H u0 p0 c0 {4,S}
11 H u0 p0 c0 {5,S}
12 H u0 p0 c0 {6,S}
        """
        mol1 = Molecule().fromSMILES(smiles1)
        mol2 = Molecule().fromSMILES(smiles2)
        mol3 = Molecule().fromAdjacencyList(adj3)
        ring1mol = Molecule(
            atoms=[atom for atom in mol1.atoms if atom.isNonHydrogen()])
        ring2mol = Molecule(
            atoms=[atom for atom in mol2.atoms if atom.isNonHydrogen()])
        ring3mol = Molecule(
            atoms=[atom for atom in mol3.atoms if atom.isNonHydrogen()])

        # check with expected results
        self.assertEqual(isAromaticRing(ring1mol), False)
        self.assertEqual(isAromaticRing(ring2mol), False)
        self.assertEqual(isAromaticRing(ring3mol), True)
Example #45
0
def getAdjacencyList(request, identifier):
    """
    Returns an adjacency list of the species corresponding to `identifier`.
    
    `identifier` should be something recognized by NCI resolver, eg.
    SMILES, InChI, CACTVS, chemical name, etc.
    
    The NCI resolver has some bugs regarding reading SMILES of radicals.
    E.g. it thinks CC[CH] is CCC, so we first try to use the identifier
    directly as a SMILES string, and only pass it through the resolver
    if that does not work. 
    """
    if identifier.strip() == '':
        return HttpResponse('', mimetype="text/plain")
    from rmgpy.molecule.molecule import Molecule
    molecule = Molecule()
    try:
        # try using the string as a SMILES directly
        molecule.fromSMILES(str(identifier))
    except (IOError, ValueError):
        # try converting it to a SMILES using the NCI chemical resolver
        url = "http://cactus.nci.nih.gov/chemical/structure/{0}/smiles".format(
            urllib.quote(identifier))
        try:
            f = urllib2.urlopen(url, timeout=5)
        except urllib2.URLError, e:
            return HttpResponseNotFound(
                "404: Couldn't identify {0}. NCI resolver responded {1} to request for {2}"
                .format(identifier, e, url))
        smiles = f.read()
        molecule.fromSMILES(smiles)
Example #46
0
    def testAtomSymmetryNumberWithTwoChiralCenters(self):
        """
        Test the Molecule.calculateAtomSymmetryNumber() on [CH2]CC([CH2])C(C)C=C

        This is meant to test whether chirality is accounted for, which
        should half the symmetry term.

        The molecule has one methyl group (*3), two CH2dot groups (*2 each), and
        two chiral centers (*0.5), leading to a total atom symmetry number of 3
        """
        molecule = Molecule().fromAdjacencyList("""
multiplicity 3
1  C u1 p0 c0 {2,S} {3,S} {4,S}
2  H u0 p0 c0 {1,S}
3  H u0 p0 c0 {1,S}
4  C u0 p0 c0 {1,S} {5,S} {13,S} {14,S}
5  C u0 p0 c0 {4,S} {6,S} {9,S} {15,S}
6  C u1 p0 c0 {5,S} {7,S} {8,S}
7  H u0 p0 c0 {6,S}
8  H u0 p0 c0 {6,S}
9  C u0 p0 c0 {5,S} {10,S} {11,S} {16,S}
10 C u0 p0 c0 {9,S} {17,S} {18,S} {19,S}
11 C u0 p0 c0 {9,S} {12,D} {20,S}
12 C u0 p0 c0 {11,D} {21,S} {22,S}
13 H u0 p0 c0 {4,S}
14 H u0 p0 c0 {4,S}
15 H u0 p0 c0 {5,S}
16 H u0 p0 c0 {9,S}
17 H u0 p0 c0 {10,S}
18 H u0 p0 c0 {10,S}
19 H u0 p0 c0 {10,S}
20 H u0 p0 c0 {11,S}
21 H u0 p0 c0 {12,S}
22 H u0 p0 c0 {12,S}
""")
        symmetryNumber = 1
        for atom in molecule.atoms:
            if not molecule.isAtomInCycle(atom):
                symmetryNumber *= calculateAtomSymmetryNumber(molecule, atom)
        self.assertAlmostEqual(symmetryNumber, 3)
Example #47
0
    def testBicyclicDecompositionForPolyringUsingPyrene(self):

        # create testing molecule: Pyrene with two ring of aromatic version
        # the other two ring of kekulized version
        #
        # creating it seems not natural in RMG, that's because
        # RMG cannot parse the adjacencyList of that isomer correctly
        # so here we start with pyrene radical and get the two aromatic ring isomer
        # then saturate it.
        smiles = '[C]1C=C2C=CC=C3C=CC4=CC=CC=1C4=C23'
        spe = Species().fromSMILES(smiles)
        spe.generateResonanceIsomers()
        for mol in spe.molecule:
            sssr0 = mol.getSmallestSetOfSmallestRings()
            aromaticRingNum = 0
            for sr0 in sssr0:
                sr0mol = Molecule(atoms=sr0)
                if isAromaticRing(sr0mol):
                    aromaticRingNum += 1
            if aromaticRingNum == 2:
                break
        mol.saturate()

        # extract polyring from the molecule
        polyring = mol.getDisparateRings()[1][0]

        bicyclicList, ringOccurancesDict = bicyclicDecompositionForPolyring(
            polyring)

        # 1st test: number of cores
        self.assertEqual(len(bicyclicList), 5)

        # 2nd test: ringOccurancesDict
        ringInCoreOccurances = sorted(ringOccurancesDict.values())
        expectedRingInCoreOccurances = [2, 2, 3, 3]
        self.assertEqual(ringInCoreOccurances, expectedRingInCoreOccurances)

        # 3rd test: size of each bicyclic core
        bicyclicSizes = sorted(
            [len(bicyclic.atoms) for bicyclic in bicyclicList])
        expectedBicyclicSizes = [10, 10, 10, 10, 10]
        self.assertEqual(bicyclicSizes, expectedBicyclicSizes)

        # 4th test: bond info for members of each core
        aromaticBondNumInBicyclics = []
        for bicyclic in bicyclicList:
            aromaticBondNum = len(findAromaticBondsFromSubMolecule(bicyclic))
            aromaticBondNumInBicyclics.append(aromaticBondNum)
        aromaticBondNumInBicyclics = sorted(aromaticBondNumInBicyclics)
        expectedAromaticBondNumInBicyclics = [0, 6, 6, 6, 11]
        self.assertEqual(aromaticBondNumInBicyclics,
                         expectedAromaticBondNumInBicyclics)
Example #48
0
def testMultiplicity_mol_mol_distinct_multiplicity():
    '''
    distinct multiplicity for both molecules set by user.
    '''
    mol = Molecule().fromAdjacencyList("""
    multiplicity 1
    1 C u1 p0 c0 {2,S}
    2 C u0 p0 c0 {1,S} {3,S}
    3 C u1 p0 c0 {2,S}
    """,
                                       saturateH=True)

    mol2 = Molecule().fromAdjacencyList("""
    multiplicity 3
    1 C u1 p0 c0 {2,S}
    2 C u0 p0 c0 {1,S} {3,S}
    3 C u1 p0 c0 {2,S}
    """,
                                        saturateH=True)

    assert_false(mol.isIsomorphic(mol2))
    assert_false(len(mol.findIsomorphism(mol2)) > 0)
Example #49
0
 def identifySpecies(species_dict, molecule):
     """
     Given a species_dict list and the species adjacency list, identifies
     whether species is found in the list and returns its name if found.
     """
     resonance_isomers = molecule.generate_resonance_structures()
     for name, adjlist in species_dict:
         list_molecule = Molecule().from_adjacency_list(adjlist,
                                                        saturate_h=True)
         for isomer in resonance_isomers:
             if isomer.is_isomorphic(list_molecule):
                 return name
     return False
Example #50
0
 def testSMILES(self):
     """
     Test that we can generate a few SMILES strings as expected
     """
     import rmgpy.molecule
     test_strings = [
         '[C-]#[O+]', '[C]', '[CH]', 'OO', '[H][H]', '[H]', '[He]', '[O]',
         'O', '[CH3]', 'C', '[OH]', 'CCC', 'CC', 'N#N', '[O]O', 'C[CH2]',
         '[Ar]', 'CCCC', 'O=C=O', '[C]#N'
     ]
     for s in test_strings:
         molecule = Molecule(SMILES=s)
         self.assertEqual(s, molecule.toSMILES())
Example #51
0
class ConverterTest(unittest.TestCase):
    def setUp(self):
        """Function run before each test in this class."""
        self.test_mols = [
            Molecule().from_smiles('C'),
            Molecule().from_smiles('O'),
            Molecule().from_smiles('N'),
            Molecule().from_smiles('S'),
            Molecule().from_smiles('[CH2]C'),
            Molecule().from_smiles('[CH]C'),
            Molecule().from_smiles('C=CC=C'),
            Molecule().from_smiles('C#C[CH2]'),
            Molecule().from_smiles('c1ccccc1'),
            Molecule().from_smiles('[13CH3]C'),
            Molecule().from_smiles('O=CCO').generate_h_bonded_structures()[0],
        ]
        self.test_Hbond_free_mol = Molecule().from_smiles('O=CCO')

    def test_rdkit_round_trip(self):
        """Test conversion to and from RDKitMol"""
        for mol in self.test_mols:
            rdkit_mol = to_rdkit_mol(mol)
            new_mol = from_rdkit_mol(Molecule(), rdkit_mol)
            self.assertTrue(
                mol.is_isomorphic(new_mol)
                or self.test_Hbond_free_mol.is_isomorphic(new_mol))
            self.assertEqual(mol.get_element_count(),
                             new_mol.get_element_count())

    def test_ob_round_trip(self):
        """Test conversion to and from OBMol"""
        for mol in self.test_mols:
            ob_mol = to_ob_mol(mol)
            new_mol = from_ob_mol(Molecule(), ob_mol)
            self.assertTrue(
                mol.is_isomorphic(new_mol)
                or self.test_Hbond_free_mol.is_isomorphic(new_mol))
            self.assertEqual(mol.get_element_count(),
                             new_mol.get_element_count())
Example #52
0
    def test_atom_mapping_2(self):
        """Test that to_rdkit_mol returns correct indices and atom mappings when hydrogens are removed."""
        adjlist = """
1 H u0 p0 c0 {2,S}
2 C u0 p0 c0 {1,S} {3,S} {4,S} {5,S}
3 H u0 p0 c0 {2,S}
4 H u0 p0 c0 {2,S}
5 O u0 p2 c0 {2,S} {6,S}
6 H u0 p0 c0 {5,S}
        """

        mol = Molecule().from_adjacency_list(adjlist)
        rdkitmol, rd_atom_indices = to_rdkit_mol(mol, remove_h=True, return_mapping=True)

        heavy_atoms = [at for at in mol.atoms if at.number != 1]
        for at1 in heavy_atoms:
            for at2 in heavy_atoms:
                if mol.has_bond(at1, at2):
                    try:
                        rdkitmol.GetBondBetweenAtoms(rd_atom_indices[at1], rd_atom_indices[at2])
                    except RuntimeError:
                        self.fail("RDKit failed in finding the bond in the original atom!")
Example #53
0
def test_multiplicity_mol_mol_distinct_multiplicity():
    """
    distinct multiplicity for both molecules set by user.
    """
    mol = Molecule().from_adjacency_list("""
    multiplicity 1
    1 C u1 p0 c0 {2,S}
    2 C u0 p0 c0 {1,S} {3,S}
    3 C u1 p0 c0 {2,S}
    """,
                                         saturate_h=True)

    mol2 = Molecule().from_adjacency_list("""
    multiplicity 3
    1 C u1 p0 c0 {2,S}
    2 C u0 p0 c0 {1,S} {3,S}
    3 C u1 p0 c0 {2,S}
    """,
                                          saturate_h=True)

    assert_false(mol.is_isomorphic(mol2))
    assert_false(len(mol.find_isomorphism(mol2)) > 0)
Example #54
0
    def test_separate_transition_states_generated_regardless_of_reactant_order(
            self):
        """
        ensure rxns with multiple transition states are kept as separate reactions
        
        this test uses C[C]=C + C=C[CH2] -> C=C=C + C=CC as an example. 
        This reaction should have two transition states, which should occur regardless
        of the order .
        """
        molA = Molecule().fromSMILES('C=[C]C')
        molB = Molecule().fromSMILES('C=C[CH2]')
        molC = Molecule().fromSMILES('C=C=C')
        molD = Molecule().fromSMILES('C=CC')
        reactionList = database.kinetics.families[
            'Disproportionation']._KineticsFamily__generateReactions(
                [molA, molB], products=[molC, molD])

        swapped_reactionList = database.kinetics.families[
            'Disproportionation']._KineticsFamily__generateReactions(
                [molB, molA], products=[molC, molD])

        # eliminate rxns that do not match products
        templates = {}
        for rxn in reactionList:
            try:
                templates[rxn.template[0]] += 1
            except KeyError:
                templates[rxn.template[0]] = 1
        reverseTemplates = {}
        for rxn in swapped_reactionList:
            try:
                reverseTemplates[rxn.template[0]] += 1
            except KeyError:
                reverseTemplates[rxn.template[0]] = 1

        self.assertEqual(
            reverseTemplates, templates,
            'The reaction output did not output all the transition states in either order of reactants'
        )
Example #55
0
    def test_aromatic_resonance_structures(self):
        """Test that different resonance structures give identical InChIs."""
        mol = Molecule().from_adjacency_list("""
multiplicity 2
1  C u0 p0 c0 {2,D} {14,S} {18,S}
2  C u0 p0 c0 {1,D} {3,S} {19,S}
3  C u0 p0 c0 {2,S} {4,D} {20,S}
4  C u0 p0 c0 {3,D} {5,S} {13,S}
5  C u0 p0 c0 {4,S} {6,S} {14,D}
6  C u0 p0 c0 {5,S} {7,D} {21,S}
7  C u0 p0 c0 {6,D} {8,S} {22,S}
8  C u0 p0 c0 {7,S} {9,D} {13,S}
9  C u0 p0 c0 {8,D} {10,S} {23,S}
10 C u0 p0 c0 {9,S} {11,D} {24,S}
11 C u0 p0 c0 {10,D} {12,S} {25,S}
12 C u0 p0 c0 {11,S} {13,D} {26,S}
13 C u0 p0 c0 {4,S} {8,S} {12,D}
14 C u0 p0 c0 {1,S} {5,D} {15,S}
15 C u1 p0 c0 {14,S} {16,S} {17,S}
16 H u0 p0 c0 {15,S}
17 H u0 p0 c0 {15,S}
18 H u0 p0 c0 {1,S}
19 H u0 p0 c0 {2,S}
20 H u0 p0 c0 {3,S}
21 H u0 p0 c0 {6,S}
22 H u0 p0 c0 {7,S}
23 H u0 p0 c0 {9,S}
24 H u0 p0 c0 {10,S}
25 H u0 p0 c0 {11,S}
26 H u0 p0 c0 {12,S}
""")
        res = mol.generate_resonance_structures()

        inchi_list = [struct.to_inchi() for struct in res]

        expected_inchi = 'InChI=1S/C15H11/c1-11-5-4-8-15-13(11)10-9-12-6-2-3-7-14(12)15/h2-10H,1H2'

        for inchi in inchi_list:
            self.assertEqual(inchi, expected_inchi)
Example #56
0
    def test_ccco_triplet(self):

        adjlist = """
        multiplicity 3
1 C u0 p0 c0 {2,D} {5,S} {6,S}
2 C u0 p0 c0 {1,D} {3,S} {7,S}
3 C u1 p0 c0 {2,S} {4,S} {8,S}
4 O u1 p2 c0 {3,S}
5 H u0 p0 c0 {1,S}
6 H u0 p0 c0 {1,S}
7 H u0 p0 c0 {2,S}
8 H u0 p0 c0 {3,S}
        """
        mol = Molecule().from_adjacency_list(adjlist)

        spc = Species(molecule=[mol])
        spc.generate_resonance_structures()
        aug_inchi = spc.get_augmented_inchi()

        self.assertEqual(
            Species(molecule=[Molecule().from_augmented_inchi(aug_inchi)
                              ]).is_isomorphic(spc), True)
Example #57
0
    def testIsPolyringPartialMatched(self):

        # create testing molecule
        smiles = 'C1CC2CCCC3CCCC(C1)C23'
        mol = Molecule().fromSMILES(smiles)
        polyring = [atom for atom in mol.atoms if atom.isNonHydrogen()]

        # create matched group
        matched_group = self.database.groups['polycyclic'].entries[
            'PolycyclicRing'].item

        # test
        self.assertTrue(isPolyringPartialMatched(polyring, matched_group))
Example #58
0
 def test_bond_symmetry_number_allyl(self):
     """
     Test the Molecule.calculate_bond_symmetry_number() on [CH2]C=C
     """
     spc = Species(molecule=[Molecule().from_smiles('[CH2]C=C')])
     molecule = spc.get_resonance_hybrid()
     symmetry_number = 1
     for atom1 in molecule.atoms:
         for atom2 in atom1.bonds:
             if molecule.atoms.index(atom1) < molecule.atoms.index(atom2):
                 symmetry_number *= calculate_bond_symmetry_number(
                     molecule, atom1, atom2)
     self.assertEqual(symmetry_number, 1)
Example #59
0
 def testIsomorphism(self):
     """
     Check the graph isomorphism functions.
     """
     molecule1 = Molecule().fromSMILES('C=CC=C[CH]C')
     molecule2 = Molecule().fromSMILES('C[CH]C=CC=C')
     self.assertTrue(molecule1.isIsomorphic(molecule2))
     self.assertTrue(molecule2.isIsomorphic(molecule1))
Example #60
0
    def testPickle(self):
        """
        Test that a Molecule object can be successfully pickled and
        unpickled with no loss of information.
        """
        molecule0 = Molecule().fromSMILES('C=CC=C[CH2]C')
        molecule0.updateAtomTypes()
        molecule0.updateConnectivityValues()
        import cPickle
        molecule = cPickle.loads(cPickle.dumps(molecule0))

        self.assertEqual(len(molecule0.atoms), len(molecule.atoms))
        self.assertEqual(molecule0.getFormula(), molecule.getFormula())
        self.assertTrue(molecule0.isIsomorphic(molecule))
        self.assertTrue(molecule.isIsomorphic(molecule0))