Esempio n. 1
0
    def test_helium(self):
        """
        adjlist: Test that the adjlist reading and writing works with Helium.
        """
        smiles = '[He]'
        inchi = 'InChI=1S/He'
        adjlist = '1 He u0 p1 c0'
        adjlist_old = '1 He 0'
        adjlist_intermediate = '1 He 0 1'

        mol_smiles = Molecule().from_smiles(smiles)
        mol_inchi = Molecule().from_inchi(inchi)
        mol = Molecule().from_adjacency_list(adjlist)
        mol_old = Molecule().from_adjacency_list(adjlist_old)
        mol_intermediate = Molecule().from_adjacency_list(adjlist_intermediate)

        # Isomorphic check
        self.assertTrue(mol_smiles.is_isomorphic(mol))
        self.assertTrue(mol_smiles.is_isomorphic(mol_inchi))
        self.assertTrue(mol_smiles.is_isomorphic(mol_old))
        self.assertTrue(mol_smiles.is_isomorphic(mol_intermediate))

        # Adjlist check
        self.assertEqual(mol_smiles.to_adjacency_list().strip(), adjlist)
        self.assertEqual(mol_inchi.to_adjacency_list().strip(), adjlist)
        self.assertEqual(mol.to_adjacency_list().strip(), adjlist)
        self.assertEqual(mol_old.to_adjacency_list().strip(), adjlist)
        self.assertEqual(mol_intermediate.to_adjacency_list().strip(), adjlist)

        self.assertEqual(mol.to_smiles(), smiles)
        self.assertEqual(mol.to_inchi(), 'InChI=1S/He')
Esempio n. 2
0
    def test_adjacency_list(self):
        """
        adjlist: Check the adjacency list read/write functions for a full molecule.
        """
        molecule1 = Molecule().from_adjacency_list("""
        1  C u0 {2,D} {7,S} {8,S}
        2  C u0 {1,D} {3,S} {9,S}
        3  C u0 {2,S} {4,D} {10,S}
        4  C u0 {3,D} {5,S} {11,S}
        5  C u1 {4,S} {6,S} {12,S}
        6  C u0 {5,S} {13,S} {14,S} {15,S}
        7  H u0 {1,S}
        8  H u0 {1,S}
        9  H u0 {2,S}
        10 H u0 {3,S}
        11 H u0 {4,S}
        12 H u0 {5,S}
        13 H u0 {6,S}
        14 H u0 {6,S}
        15 H u0 {6,S}
        """)
        molecule2 = Molecule().from_smiles('C=CC=C[CH]C')
        self.assertTrue(molecule1.is_isomorphic(molecule2))
        self.assertTrue(molecule2.is_isomorphic(molecule1))

        # Test that charges are correctly stored and written with adjacency lists
        adjlist3 = """
1 C u0 p1 c-1 {2,T}
2 O u0 p1 c+1 {1,T}
"""
        molecule3 = Molecule().from_adjacency_list(adjlist3)
        self.assertEquals(molecule3.atoms[0].charge, -1)
        self.assertEquals(molecule3.atoms[1].charge, 1)
        adjlist4 = molecule3.to_adjacency_list()
        self.assertEquals(adjlist3.strip(), adjlist4.strip())
Esempio n. 3
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())
Esempio n. 4
0
def test_isotope_subgraph_isomorphism_molecule_and_group():
    """
    Checks that subgraph isomorphism works with enriched molecules and groups
    """
    methanei = Molecule().from_adjacency_list("""
    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().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 H u0 p0 c0 {1,S}
    """)
    group_methane = Group().from_adjacency_list("""
    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.is_subgraph_isomorphic(group_methane))
    assert_true(methane.is_subgraph_isomorphic(group_methane))
    assert_false(methanei.is_isomorphic(methane))
Esempio n. 5
0
    def test_to_adjacency_list(self):
        """
        adjlist: Test the Molecule.to_adjacency_list() 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().from_adjacency_list(adjlist)
        molecule2 = Molecule().from_adjacency_list(inter_adjlist)
        adjlist_1 = molecule.to_adjacency_list(remove_h=False)
        self.assertEqual(adjlist_1, molecule2.to_adjacency_list())
        new_molecule = Molecule().from_adjacency_list(adjlist_1)
        self.assertTrue(molecule.is_isomorphic(new_molecule))
Esempio n. 6
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))
Esempio n. 7
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().from_adjacency_list(adjlist)
        mol2 = Molecule(smiles=smiles)
        self.assertTrue(mol1.is_isomorphic(mol2),
                        "Parsing SMILES={!r} gave unexpected molecule\n{}".format(smiles, mol2.to_adjacency_list()))
Esempio n. 8
0
    def test_lone_pair_retention(self):
        """Test that we don't lose any lone pairs on round trip RDKit conversion."""
        mol = Molecule().from_adjacency_list("""
1 C u0 p0 c0 {2,D} {3,S} {4,S}
2 O u0 p2 c0 {1,D}
3 H u0 p0 c0 {1,S}
4 H u0 p0 c0 {1,S}
""")
        rdmol = to_rdkit_mol(mol)

        mol2 = from_rdkit_mol(Molecule(), rdmol)
        self.assertTrue(mol.is_isomorphic(mol2))
Esempio n. 9
0
 def test_from_old_adjacency_list6(self):
     """
     Test we can read an old style adjacency list with implicit hydrogens 1
     """
     adjlist = """
     1 C 4T
     """
     adjlist_new = """
     1 C u2 p1 c0 
     """
     molecule = Molecule().from_adjacency_list(adjlist)
     molecule_new = Molecule().from_adjacency_list(adjlist_new)
     self.assertTrue(molecule.is_isomorphic(molecule_new))
Esempio n. 10
0
def test_multiplicity_mol_not_specified_mol_not_specified():
    """
    Both multiplicities not set.
    """
    mol = Molecule().from_adjacency_list("""
    1 C u2 p0 c0
    """, saturate_h=True)

    mol2 = Molecule().from_adjacency_list("""
    1 C u2 p0 c0
    """, saturate_h=True)

    assert_true(mol.is_isomorphic(mol2))
    assert_true(len(mol.find_isomorphism(mol2)) > 0)
Esempio n. 11
0
 def test_from_old_adjacency_list5(self):
     """
     Test we can read an old style adjacency list with implicit hydrogens 5
     """
     adjlist = """
     1 C 2S {2,T}
     2 O 2S {1,T}
     """
     adjlist_new = """
     1 C u0 p1 c-1 {2,T}
     2 O u0 p1 c+1 {1,T}
     """
     molecule = Molecule().from_adjacency_list(adjlist)
     molecule_new = Molecule().from_adjacency_list(adjlist_new)
     self.assertTrue(molecule.is_isomorphic(molecule_new))
Esempio n. 12
0
 def test_from_old_adjacency_list2(self):
     """
     Test we can read an old style adjacency list with implicit hydrogens 2
     """
     adjlist = """
     1 C 2S
     """
     adjlist_new = """
     1 C u0 p1 c0 {2,S} {3,S}
     2 H u0 p0 c0 {1,S}
     3 H u0 p0 c0 {1,S}
     """
     molecule = Molecule().from_adjacency_list(adjlist)
     molecule_new = Molecule().from_adjacency_list(adjlist_new)
     self.assertTrue(molecule.is_isomorphic(molecule_new))
Esempio n. 13
0
def test_multiplicity_mol_mol_identical_multiplicity():
    """
    identical multiplicity for both molecules set by user.
    """
    mol = Molecule().from_adjacency_list("""
    multiplicity 3
    1 C u2 p0 c0
    """, saturate_h=True)

    mol2 = Molecule().from_adjacency_list("""
    multiplicity 3
    1 C u2 p0 c0
    """, saturate_h=True)

    assert_true(mol.is_isomorphic(mol2))
    assert_true(len(mol.find_isomorphism(mol2)) > 0)
Esempio n. 14
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)
Esempio n. 15
0
    def verify_output_file(self):
        """
        Check's that an output file exists and was successful.
        
        Returns a boolean flag that states whether a successful MOPAC simulation already exists for the molecule with the 
        given (augmented) InChI Key.
        
        The definition of finding a successful simulation is based on these criteria:
        1) finding an output file with the file name equal to the InChI Key
        2) NOT finding any of the keywords that are denote a calculation failure
        3) finding all the keywords that denote a calculation success.
        4) finding a match between the InChI of the given molecule and the InchI found in the calculation files
        5) checking that the optimized geometry, when connected by single bonds, is isomorphic with self.molecule (converted to single bonds)
        
        If any of the above criteria is not matched, False will be returned.
        If all succeed, then it will return True.
        """
        if not os.path.exists(self.output_file_path):
            logging.debug("Output file {0} does not (yet) exist.".format(
                self.output_file_path))
            return False

        inchi_found = False  # flag (1 or 0) indicating whether an InChI was found in the log file

        # Initialize dictionary with "False"s
        success_keys_found = dict([(key, False) for key in self.successKeys])

        with open(self.output_file_path) as outputFile:
            for line in outputFile:
                line = line.strip()

                for element in self.failureKeys:  # search for failure keywords
                    if element in line:
                        logging.error(
                            "MOPAC output file contains the following error: {0}"
                            .format(element))
                        return False

                for element in self.successKeys:  # search for success keywords
                    if element in line:
                        success_keys_found[element] = True

                if "InChI=" in line:
                    log_file_inchi = line  # output files should take up to 240 characters of the name in the input file
                    inchi_found = True
                    if self.unique_id_long in log_file_inchi:
                        pass
                    elif self.unique_id_long.startswith(log_file_inchi):
                        logging.info(
                            "InChI too long to check, but beginning matches so assuming OK."
                        )

                    else:
                        logging.warning(
                            "InChI in log file ({0}) didn't match that in geometry "
                            "({1}).".format(log_file_inchi,
                                            self.unique_id_long))
                        # Use only up to first 80 characters to match due to MOPAC bug which deletes 81st character of InChI string
                        if self.unique_id_long.startswith(log_file_inchi[:80]):
                            logging.warning(
                                "but the beginning matches so it's probably just a truncation problem."
                            )

        # Check that ALL 'success' keywords were found in the file.
        if not all(success_keys_found.values()):
            logging.error(
                'Not all of the required keywords for success were found in the output file!'
            )
            return False

        if not inchi_found:
            logging.error(
                "No InChI was found in the MOPAC output file {0}".format(
                    self.output_file_path))
            return False

        # Compare the optimized geometry to the original molecule
        qm_data = self.parse()
        cclib_mol = Molecule()
        cclib_mol.from_xyz(qm_data.atomicNumbers, qm_data.atomCoords.value)
        test_mol = self.molecule.to_single_bonds()
        if not cclib_mol.is_isomorphic(test_mol):
            logging.info(
                "Incorrect connectivity for optimized geometry in file {0}".
                format(self.output_file_path))
            return False

        logging.info("Successful {1} quantum result in {0}".format(
            self.output_file_path, self.__class__.__name__))
        return True
Esempio n. 16
0
    def test_various_spin_adjlists(self):
        """
        adjlist: Test that molecules with old or intermediate adjacency list formats containing unusual 
        spin states can get converted to the proper new adjlist format.
        """

        adjlist_2s = """
1 C 2S 0 {2,S} {3,S}
2 H 0  0 {1,S}
3 H 0  0 {1,S}
"""
        adjlist_2s_new = """
1 C u0 p1 c0  {2,S} {3,S}
2 H u0 p0 c0  {1,S}
3 H u0 p0 c0  {1,S}
"""
        mol_2s = Molecule().from_adjacency_list(adjlist_2s)
        mol_2s_new = Molecule().from_adjacency_list(adjlist_2s_new)
        self.assertTrue(mol_2s.is_isomorphic(mol_2s_new))

        adjlist_2t = """
1 C 2T 0 {2,S} {3,S}
2 H 0  0 {1,S}
3 H 0  0 {1,S}
"""
        adjlist_2t_new = """
1 C u2 p0 c0  {2,S} {3,S}
2 H u0 p0 c0  {1,S}
3 H u0 p0 c0  {1,S}
"""
        mol_2t = Molecule().from_adjacency_list(adjlist_2t)
        mol_2t_new = Molecule().from_adjacency_list(adjlist_2t_new)
        self.assertTrue(mol_2t.is_isomorphic(mol_2t_new))

        adjlist_3d = """
1 C 3D 0 {2,S}
2 H 0  0 {1,S}
"""
        adjlist_3d_new = """
1 C u1 p1 c0  {2,S}
2 H u0 p0 c0  {1,S}
"""
        mol_3d = Molecule().from_adjacency_list(adjlist_3d)
        mol_3d_new = Molecule().from_adjacency_list(adjlist_3d_new)
        self.assertTrue(mol_3d.is_isomorphic(mol_3d_new))

        adjlist_3q = """
1 N 3Q 1
"""
        adjlist_3q_new = """
1 N u3 p1 c0 
"""
        mol_3q = Molecule().from_adjacency_list(adjlist_3q)
        mol_3q_new = Molecule().from_adjacency_list(adjlist_3q_new)
        self.assertTrue(mol_3q.is_isomorphic(mol_3q_new))

        adjlist_4s = """
1 C 4S 0
        """
        adjlist_4s_new = """
1 C u0 p2 c0
"""
        mol_4s = Molecule().from_adjacency_list(adjlist_4s)
        mol_4s_new = Molecule().from_adjacency_list(adjlist_4s_new)
        self.assertTrue(mol_4s.is_isomorphic(mol_4s_new))

        adjlist_4t = """
1 C 4T 0
"""
        adjlist_4t_new = """
1 C u2 p1 c0
"""
        mol_4t = Molecule().from_adjacency_list(adjlist_4t)
        mol_4t_new = Molecule().from_adjacency_list(adjlist_4t_new)
        self.assertTrue(mol_4t.is_isomorphic(mol_4t_new))

        adjlist_4v = """
1 C 4V 0
"""
        adjlist_4v_new = """
1 C u4 p0 c0        
"""
        mol_4v = Molecule().from_adjacency_list(adjlist_4v)
        mol_4v_new = Molecule().from_adjacency_list(adjlist_4v_new)
        self.assertTrue(mol_4v.is_isomorphic(mol_4v_new))