def test_Intra_R_Add_Exo_scission(self): """ Test that the Intra_R_Add_Exo_scission family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['Intra_R_Add_Exo_scission'] reactants = [ Molecule().fromAdjacencyList(""" multiplicity 2 1 *3 C u0 p0 c0 {2,S} {8,S} {11,S} {12,S} 2 *2 C u0 p0 c0 {1,S} {3,B} {4,B} 3 C u0 p0 c0 {2,B} {5,B} {13,S} 4 C u0 p0 c0 {2,B} {7,B} {17,S} 5 C u0 p0 c0 {3,B} {6,B} {14,S} 6 C u0 p0 c0 {5,B} {7,B} {15,S} 7 C u0 p0 c0 {4,B} {6,B} {16,S} 8 *1 C u1 p0 c0 {1,S} {9,S} {18,S} 9 C u0 p0 c0 {8,S} {10,T} 10 C u0 p0 c0 {9,T} {19,S} 11 H u0 p0 c0 {1,S} 12 H u0 p0 c0 {1,S} 13 H u0 p0 c0 {3,S} 14 H u0 p0 c0 {5,S} 15 H u0 p0 c0 {6,S} 16 H u0 p0 c0 {7,S} 17 H u0 p0 c0 {4,S} 18 H u0 p0 c0 {8,S} 19 H u0 p0 c0 {10,S} """) ] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 *3 C u0 p0 c0 {2,S} {8,S} {9,S} {11,S} 2 *2 C u0 p0 c0 {1,S} {3,B} {4,B} 3 C u0 p0 c0 {2,B} {5,B} {12,S} 4 C u0 p0 c0 {2,B} {7,B} {16,S} 5 C u0 p0 c0 {3,B} {6,B} {13,S} 6 C u0 p0 c0 {5,B} {7,B} {14,S} 7 C u0 p0 c0 {4,B} {6,B} {15,S} 8 *1 C u1 p0 c0 {1,S} {17,S} {18,S} 9 C u0 p0 c0 {1,S} {10,T} 10 C u0 p0 c0 {9,T} {19,S} 11 H u0 p0 c0 {1,S} 12 H u0 p0 c0 {3,S} 13 H u0 p0 c0 {5,S} 14 H u0 p0 c0 {6,S} 15 H u0 p0 c0 {7,S} 16 H u0 p0 c0 {4,S} 17 H u0 p0 c0 {8,S} 18 H u0 p0 c0 {8,S} 19 H u0 p0 c0 {10,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def test_Intra_R_Add_Exo_scission(self): """ Test that the Intra_R_Add_Exo_scission family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['Intra_R_Add_Exo_scission'] reactants = [Molecule().fromAdjacencyList(""" multiplicity 2 1 *3 C u0 p0 c0 {2,S} {8,S} {11,S} {12,S} 2 *2 C u0 p0 c0 {1,S} {3,B} {4,B} 3 C u0 p0 c0 {2,B} {5,B} {13,S} 4 C u0 p0 c0 {2,B} {7,B} {17,S} 5 C u0 p0 c0 {3,B} {6,B} {14,S} 6 C u0 p0 c0 {5,B} {7,B} {15,S} 7 C u0 p0 c0 {4,B} {6,B} {16,S} 8 *1 C u1 p0 c0 {1,S} {9,S} {18,S} 9 C u0 p0 c0 {8,S} {10,T} 10 C u0 p0 c0 {9,T} {19,S} 11 H u0 p0 c0 {1,S} 12 H u0 p0 c0 {1,S} 13 H u0 p0 c0 {3,S} 14 H u0 p0 c0 {5,S} 15 H u0 p0 c0 {6,S} 16 H u0 p0 c0 {7,S} 17 H u0 p0 c0 {4,S} 18 H u0 p0 c0 {8,S} 19 H u0 p0 c0 {10,S} """)] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 *3 C u0 p0 c0 {2,S} {8,S} {9,S} {11,S} 2 *2 C u0 p0 c0 {1,S} {3,B} {4,B} 3 C u0 p0 c0 {2,B} {5,B} {12,S} 4 C u0 p0 c0 {2,B} {7,B} {16,S} 5 C u0 p0 c0 {3,B} {6,B} {13,S} 6 C u0 p0 c0 {5,B} {7,B} {14,S} 7 C u0 p0 c0 {4,B} {6,B} {15,S} 8 *1 C u1 p0 c0 {1,S} {17,S} {18,S} 9 C u0 p0 c0 {1,S} {10,T} 10 C u0 p0 c0 {9,T} {19,S} 11 H u0 p0 c0 {1,S} 12 H u0 p0 c0 {3,S} 13 H u0 p0 c0 {5,S} 14 H u0 p0 c0 {6,S} 15 H u0 p0 c0 {7,S} 16 H u0 p0 c0 {4,S} 17 H u0 p0 c0 {8,S} 18 H u0 p0 c0 {8,S} 19 H u0 p0 c0 {10,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def test_12_shiftC(self): """ Test that the 1,2_shiftC family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['1,2_shiftC'] reactants = [ Molecule().fromAdjacencyList(""" multiplicity 2 1 *2 C u0 p0 c0 {2,S} {3,S} {8,S} {9,S} 2 *1 C u0 p0 c0 {1,S} {10,S} {11,S} {12,S} 3 *3 C u1 p0 c0 {1,S} {4,S} {5,S} 4 C u0 p0 c0 {3,S} {6,D} {13,S} 5 C u0 p0 c0 {3,S} {7,D} {14,S} 6 C u0 p0 c0 {4,D} {7,S} {15,S} 7 C u0 p0 c0 {5,D} {6,S} {16,S} 8 H u0 p0 c0 {1,S} 9 H u0 p0 c0 {1,S} 10 H u0 p0 c0 {2,S} 11 H u0 p0 c0 {2,S} 12 H u0 p0 c0 {2,S} 13 H u0 p0 c0 {4,S} 14 H u0 p0 c0 {5,S} 15 H u0 p0 c0 {6,S} 16 H u0 p0 c0 {7,S} """) ] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 *2 C u0 p0 c0 {2,S} {3,S} {4,S} {7,S} 2 *1 C u0 p0 c0 {1,S} {8,S} {9,S} {10,S} 3 C u0 p0 c0 {1,S} {5,D} {11,S} 4 C u0 p0 c0 {1,S} {6,D} {12,S} 5 C u0 p0 c0 {3,D} {6,S} {13,S} 6 C u0 p0 c0 {4,D} {5,S} {14,S} 7 *3 C u1 p0 c0 {1,S} {15,S} {16,S} 8 H u0 p0 c0 {2,S} 9 H u0 p0 c0 {2,S} 10 H u0 p0 c0 {2,S} 11 H u0 p0 c0 {3,S} 12 H u0 p0 c0 {4,S} 13 H u0 p0 c0 {5,S} 14 H u0 p0 c0 {6,S} 15 H u0 p0 c0 {7,S} 16 H u0 p0 c0 {7,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def test_Intra_ene_reaction(self): """ Test that the Intra_ene_reaction family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['Intra_ene_reaction'] reactants = [ Molecule().fromAdjacencyList(""" 1 *1 C u0 p0 c0 {2,S} {3,S} {4,S} {10,S} 2 *5 C u0 p0 c0 {1,S} {5,D} {6,S} 3 *2 C u0 p0 c0 {1,S} {7,D} {11,S} 4 C u0 p0 c0 {1,S} {8,D} {12,S} 5 *4 C u0 p0 c0 {2,D} {7,S} {13,S} 6 C u0 p0 c0 {2,S} {9,D} {15,S} 7 *3 C u0 p0 c0 {3,D} {5,S} {14,S} 8 C u0 p0 c0 {4,D} {9,S} {17,S} 9 C u0 p0 c0 {6,D} {8,S} {16,S} 10 *6 H u0 p0 c0 {1,S} 11 H u0 p0 c0 {3,S} 12 H u0 p0 c0 {4,S} 13 H u0 p0 c0 {5,S} 14 H u0 p0 c0 {7,S} 15 H u0 p0 c0 {6,S} 16 H u0 p0 c0 {9,S} 17 H u0 p0 c0 {8,S} """) ] expectedProduct = Molecule().fromAdjacencyList(""" 1 *2 C u0 p0 c0 {2,D} {3,S} {4,S} 2 *3 C u0 p0 c0 {1,D} {5,S} {6,S} 3 *1 C u0 p0 c0 {1,S} {7,S} {11,S} {10,S} 4 C u0 p0 c0 {1,S} {8,D} {12,S} 5 *4 C u0 p0 c0 {2,S} {7,D} {13,S} 6 C u0 p0 c0 {2,S} {9,D} {15,S} 7 *5 C u0 p0 c0 {3,S} {5,D} {14,S} 8 C u0 p0 c0 {4,D} {9,S} {17,S} 9 C u0 p0 c0 {6,D} {8,S} {16,S} 10 *6 H u0 p0 c0 {3,S} 11 H u0 p0 c0 {3,S} 12 H u0 p0 c0 {4,S} 13 H u0 p0 c0 {5,S} 14 H u0 p0 c0 {7,S} 15 H u0 p0 c0 {6,S} 16 H u0 p0 c0 {9,S} 17 H u0 p0 c0 {8,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def test_12_shiftC(self): """ Test that the 1,2_shiftC family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['1,2_shiftC'] reactants = [Molecule().fromAdjacencyList(""" multiplicity 2 1 *2 C u0 p0 c0 {2,S} {3,S} {8,S} {9,S} 2 *1 C u0 p0 c0 {1,S} {10,S} {11,S} {12,S} 3 *3 C u1 p0 c0 {1,S} {4,S} {5,S} 4 C u0 p0 c0 {3,S} {6,D} {13,S} 5 C u0 p0 c0 {3,S} {7,D} {14,S} 6 C u0 p0 c0 {4,D} {7,S} {15,S} 7 C u0 p0 c0 {5,D} {6,S} {16,S} 8 H u0 p0 c0 {1,S} 9 H u0 p0 c0 {1,S} 10 H u0 p0 c0 {2,S} 11 H u0 p0 c0 {2,S} 12 H u0 p0 c0 {2,S} 13 H u0 p0 c0 {4,S} 14 H u0 p0 c0 {5,S} 15 H u0 p0 c0 {6,S} 16 H u0 p0 c0 {7,S} """)] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 *2 C u0 p0 c0 {2,S} {3,S} {4,S} {7,S} 2 *1 C u0 p0 c0 {1,S} {8,S} {9,S} {10,S} 3 C u0 p0 c0 {1,S} {5,D} {11,S} 4 C u0 p0 c0 {1,S} {6,D} {12,S} 5 C u0 p0 c0 {3,D} {6,S} {13,S} 6 C u0 p0 c0 {4,D} {5,S} {14,S} 7 *3 C u1 p0 c0 {1,S} {15,S} {16,S} 8 H u0 p0 c0 {2,S} 9 H u0 p0 c0 {2,S} 10 H u0 p0 c0 {2,S} 11 H u0 p0 c0 {3,S} 12 H u0 p0 c0 {4,S} 13 H u0 p0 c0 {5,S} 14 H u0 p0 c0 {6,S} 15 H u0 p0 c0 {7,S} 16 H u0 p0 c0 {7,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def test_Intra_ene_reaction(self): """ Test that the Intra_ene_reaction family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['Intra_ene_reaction'] reactants = [Molecule().fromAdjacencyList(""" 1 *1 C u0 p0 c0 {2,S} {3,S} {4,S} {10,S} 2 *5 C u0 p0 c0 {1,S} {5,D} {6,S} 3 *2 C u0 p0 c0 {1,S} {7,D} {11,S} 4 C u0 p0 c0 {1,S} {8,D} {12,S} 5 *4 C u0 p0 c0 {2,D} {7,S} {13,S} 6 C u0 p0 c0 {2,S} {9,D} {15,S} 7 *3 C u0 p0 c0 {3,D} {5,S} {14,S} 8 C u0 p0 c0 {4,D} {9,S} {17,S} 9 C u0 p0 c0 {6,D} {8,S} {16,S} 10 *6 H u0 p0 c0 {1,S} 11 H u0 p0 c0 {3,S} 12 H u0 p0 c0 {4,S} 13 H u0 p0 c0 {5,S} 14 H u0 p0 c0 {7,S} 15 H u0 p0 c0 {6,S} 16 H u0 p0 c0 {9,S} 17 H u0 p0 c0 {8,S} """)] expectedProduct = Molecule().fromAdjacencyList(""" 1 *2 C u0 p0 c0 {2,D} {3,S} {4,S} 2 *3 C u0 p0 c0 {1,D} {5,S} {6,S} 3 *1 C u0 p0 c0 {1,S} {7,S} {11,S} {10,S} 4 C u0 p0 c0 {1,S} {8,D} {12,S} 5 *4 C u0 p0 c0 {2,S} {7,D} {13,S} 6 C u0 p0 c0 {2,S} {9,D} {15,S} 7 *5 C u0 p0 c0 {3,S} {5,D} {14,S} 8 C u0 p0 c0 {4,D} {9,S} {17,S} 9 C u0 p0 c0 {6,D} {8,S} {16,S} 10 *6 H u0 p0 c0 {3,S} 11 H u0 p0 c0 {3,S} 12 H u0 p0 c0 {4,S} 13 H u0 p0 c0 {5,S} 14 H u0 p0 c0 {7,S} 15 H u0 p0 c0 {6,S} 16 H u0 p0 c0 {9,S} 17 H u0 p0 c0 {8,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def test_intra_substitutionS_isomerization(self): """ Test that the intra_substitutionS_isomerization family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['intra_substitutionS_isomerization'] reactants = [ Molecule().fromAdjacencyList(""" multiplicity 2 1 *2 C u0 p0 c0 {3,S} {4,S} {5,S} {6,S} 2 C u0 p0 c0 {3,S} {7,S} {8,S} {9,S} 3 *3 C u1 p0 c0 {1,S} {2,S} {10,S} 4 *1 S u0 p2 c0 {1,S} {11,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 {2,S} 9 H u0 p0 c0 {2,S} 10 H u0 p0 c0 {3,S} 11 H u0 p0 c0 {4,S} """) ] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 *2 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 *3 C u1 p0 c0 {1,S} {9,S} {10,S} 4 *1 S u0 p2 c0 {1,S} {11,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} 9 H u0 p0 c0 {3,S} 10 H u0 p0 c0 {3,S} 11 H u0 p0 c0 {4,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def test_6_membered_central_CC_shift(self): """ Test that the 6_membered_central_C-C_shift family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['6_membered_central_C-C_shift'] reactants = [ Molecule().fromAdjacencyList(""" 1 *3 C u0 p0 c0 {2,S} {3,S} {7,S} {8,S} 2 *4 C u0 p0 c0 {1,S} {4,S} {9,S} {10,S} 3 *2 C u0 p0 c0 {1,S} {5,T} 4 *5 C u0 p0 c0 {2,S} {6,T} 5 *1 C u0 p0 c0 {3,T} {11,S} 6 *6 C u0 p0 c0 {4,T} {12,S} 7 H u0 p0 c0 {1,S} 8 H u0 p0 c0 {1,S} 9 H u0 p0 c0 {2,S} 10 H u0 p0 c0 {2,S} 11 H u0 p0 c0 {5,S} 12 H u0 p0 c0 {6,S} """) ] expectedProduct = Molecule().fromAdjacencyList(""" 1 *3 C u0 p0 c0 {2,S} {5,D} {7,S} 2 *4 C u0 p0 c0 {1,S} {6,D} {8,S} 3 *1 C u0 p0 c0 {5,D} {9,S} {10,S} 4 *6 C u0 p0 c0 {6,D} {11,S} {12,S} 5 *2 C u0 p0 c0 {1,D} {3,D} 6 *5 C u0 p0 c0 {2,D} {4,D} 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 {3,S} 11 H u0 p0 c0 {4,S} 12 H u0 p0 c0 {4,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def test_intra_substitutionS_isomerization(self): """ Test that the intra_substitutionS_isomerization family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['intra_substitutionS_isomerization'] reactants = [Molecule().fromAdjacencyList(""" multiplicity 2 1 *2 C u0 p0 c0 {3,S} {4,S} {5,S} {6,S} 2 C u0 p0 c0 {3,S} {7,S} {8,S} {9,S} 3 *3 C u1 p0 c0 {1,S} {2,S} {10,S} 4 *1 S u0 p2 c0 {1,S} {11,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 {2,S} 9 H u0 p0 c0 {2,S} 10 H u0 p0 c0 {3,S} 11 H u0 p0 c0 {4,S} """)] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 *2 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 *3 C u1 p0 c0 {1,S} {9,S} {10,S} 4 *1 S u0 p2 c0 {1,S} {11,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} 9 H u0 p0 c0 {3,S} 10 H u0 p0 c0 {3,S} 11 H u0 p0 c0 {4,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def test_6_membered_central_CC_shift(self): """ Test that the 6_membered_central_C-C_shift family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['6_membered_central_C-C_shift'] reactants = [Molecule().fromAdjacencyList(""" 1 *3 C u0 p0 c0 {2,S} {3,S} {7,S} {8,S} 2 *4 C u0 p0 c0 {1,S} {4,S} {9,S} {10,S} 3 *2 C u0 p0 c0 {1,S} {5,T} 4 *5 C u0 p0 c0 {2,S} {6,T} 5 *1 C u0 p0 c0 {3,T} {11,S} 6 *6 C u0 p0 c0 {4,T} {12,S} 7 H u0 p0 c0 {1,S} 8 H u0 p0 c0 {1,S} 9 H u0 p0 c0 {2,S} 10 H u0 p0 c0 {2,S} 11 H u0 p0 c0 {5,S} 12 H u0 p0 c0 {6,S} """)] expectedProduct = Molecule().fromAdjacencyList(""" 1 *3 C u0 p0 c0 {2,S} {5,D} {7,S} 2 *4 C u0 p0 c0 {1,S} {6,D} {8,S} 3 *1 C u0 p0 c0 {5,D} {9,S} {10,S} 4 *6 C u0 p0 c0 {6,D} {11,S} {12,S} 5 *2 C u0 p0 c0 {1,D} {3,D} 6 *5 C u0 p0 c0 {2,D} {4,D} 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 {3,S} 11 H u0 p0 c0 {4,S} 12 H u0 p0 c0 {4,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def testReactBenzeneBond(self): """ Test that hydrogen addition to benzene (w/ benzene bonds) returns kekulized product. """ family = self.database.families['R_Addition_MultipleBond'] reactants = [ Molecule().fromAdjacencyList(""" 1 *1 C u0 p0 c0 {2,B} {6,B} {7,S} 2 *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} """), Molecule().fromAdjacencyList("1 *3 H u1 p0 c0") ] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 C u0 p0 c0 {2,S} {6,S} {7,S} {13,S} 2 C u1 p0 c0 {1,S} {3,S} {8,S} 3 C u0 p0 c0 {2,S} {4,D} {9,S} 4 C u0 p0 c0 {3,D} {5,S} {10,S} 5 C u0 p0 c0 {4,S} {6,D} {11,S} 6 C u0 p0 c0 {1,S} {5,D} {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} 13 H u0 p0 c0 {1,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) self.assertTrue(expectedProduct.isIsomorphic(products[0]))
def testReactBenzeneBond(self): """ Test that hydrogen addition to benzene (w/ benzene bonds) returns kekulized product. """ family = self.database.families['R_Addition_MultipleBond'] reactants = [Molecule().fromAdjacencyList(""" 1 *1 C u0 p0 c0 {2,B} {6,B} {7,S} 2 *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} """), Molecule().fromAdjacencyList("1 *3 H u1 p0 c0")] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 C u0 p0 c0 {2,S} {6,S} {7,S} {13,S} 2 C u1 p0 c0 {1,S} {3,S} {8,S} 3 C u0 p0 c0 {2,S} {4,D} {9,S} 4 C u0 p0 c0 {3,D} {5,S} {10,S} 5 C u0 p0 c0 {4,S} {6,D} {11,S} 6 C u0 p0 c0 {1,S} {5,D} {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} 13 H u0 p0 c0 {1,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) self.assertTrue(expectedProduct.isIsomorphic(products[0]))
def check_isomorphic(conformer): """ Compares whatever is in the log file 'f' to the SMILES of the passed in 'conformer' """ starting_molecule = RMGMolecule(SMILES=conformer.smiles) starting_molecule = starting_molecule.toSingleBonds() atoms = self.read_log(os.path.join(scratch_dir, f)) test_molecule = RMGMolecule() test_molecule.fromXYZ(atoms.arrays["numbers"], atoms.arrays["positions"]) if not starting_molecule.isIsomorphic(test_molecule): logging.info( "Output geometry of {} is not isomorphic with input geometry" .format(calc.label)) return False else: logging.info("{} was successful and was validated!".format( calc.label)) return True
def verifyOutputFile(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.outputFilePath): logging.debug("Output file {0} does not (yet) exist.".format(self.outputFilePath)) return False InChIMatch=False #flag (1 or 0) indicating whether the InChI in the file matches InChIaug this can only be 1 if InChIFound is also 1 InChIFound=False #flag (1 or 0) indicating whether an InChI was found in the log file # Initialize dictionary with "False"s successKeysFound = dict([(key, False) for key in self.successKeys]) with open(self.outputFilePath) 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: successKeysFound[element] = True if "InChI=" in line: logFileInChI = line #output files should take up to 240 characters of the name in the input file InChIFound = True if self.uniqueIDlong in logFileInChI: InChIMatch = True elif self.uniqueIDlong.startswith(logFileInChI): logging.info("InChI too long to check, but beginning matches so assuming OK.") InChIMatch = True else: logging.warning("InChI in log file ({0}) didn't match that in geometry ({1}).".format(logFileInChI, self.uniqueIDlong)) # Use only up to first 80 characters to match due to MOPAC bug which deletes 81st character of InChI string if self.uniqueIDlong.startswith(logFileInChI[:80]): logging.warning("but the beginning matches so it's probably just a truncation problem.") InChIMatch = True # Check that ALL 'success' keywords were found in the file. if not all( successKeysFound.values() ): logging.error('Not all of the required keywords for success were found in the output file!') return False if not InChIFound: logging.error("No InChI was found in the MOPAC output file {0}".format(self.outputFilePath)) return False if not InChIMatch: #InChIs do not match (most likely due to limited name length mirrored in log file (240 characters), but possibly due to a collision) return self.checkForInChiKeyCollision(logFileInChI) # Not yet implemented! # Compare the optimized geometry to the original molecule qmData = self.parse() cclibMol = Molecule() cclibMol.fromXYZ(qmData.atomicNumbers, qmData.atomCoords.value) testMol = self.molecule.toSingleBonds() if not cclibMol.isIsomorphic(testMol): logging.info("Incorrect connectivity for optimized geometry in file {0}".format(self.outputFilePath)) return False logging.info("Successful {1} quantum result in {0}".format(self.outputFilePath, self.__class__.__name__)) return True #InChIs do not match (most likely due to limited name length mirrored in log file (240 characters), but possibly due to a collision) return self.checkForInChiKeyCollision(logFileInChI) # Not yet implemented!
def verifyOutputFile(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.outputFilePath): logging.debug("Output file {0} does not (yet) exist.".format( self.outputFilePath)) return False InChIFound = False #flag (1 or 0) indicating whether an InChI was found in the log file # Initialize dictionary with "False"s successKeysFound = dict([(key, False) for key in self.successKeys]) with open(self.outputFilePath) 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: successKeysFound[element] = True if "InChI=" in line: logFileInChI = line #output files should take up to 240 characters of the name in the input file InChIFound = True if self.uniqueIDlong in logFileInChI: pass elif self.uniqueIDlong.startswith(logFileInChI): 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(logFileInChI, self.uniqueIDlong)) # Use only up to first 80 characters to match due to MOPAC bug which deletes 81st character of InChI string if self.uniqueIDlong.startswith(logFileInChI[: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(successKeysFound.values()): logging.error( 'Not all of the required keywords for success were found in the output file!' ) return False if not InChIFound: logging.error( "No InChI was found in the MOPAC output file {0}".format( self.outputFilePath)) return False # Compare the optimized geometry to the original molecule qmData = self.parse() cclibMol = Molecule() cclibMol.fromXYZ(qmData.atomicNumbers, qmData.atomCoords.value) testMol = self.molecule.toSingleBonds() if not cclibMol.isIsomorphic(testMol): logging.info( "Incorrect connectivity for optimized geometry in file {0}". format(self.outputFilePath)) return False logging.info("Successful {1} quantum result in {0}".format( self.outputFilePath, self.__class__.__name__)) return True
def calculate_conformer(self, conformer, calculator): if isinstance(calculator, Gaussian): calc = calculator.get_conformer_calc(conformer=conformer, convergence='Tight') else: calc = calculator.get_conformer_calc(conformer=conformer) scratch = calculator.scratch scratch_dir = os.path.join(calculator.scratch, "species", conformer.smiles, "conformers") f = calc.label + ".log" if not os.path.exists(os.path.join(scratch_dir, f)): logging.info("Submitting conformer calculation for {}".format( calc.label)) label = self.submit_conformer(conformer, calc, "general") while not self.check_complete(label): time.sleep(15) else: logging.info( "It appears that we already have a complete log file for {}". format(calc.label)) complete, converged = calculator.verify_output_file( os.path.join(scratch_dir, f)) if not complete: logging.info( "It seems that the file never completed for {} completed, running it again" .format(calc.label)) label = self.submit_conformer(conformer, calc, "general") while not self.check_complete(label): time.sleep(15) complete, converged = calculator.verify_output_file( os.path.join(scratch_dir, f)) if (complete and converged): logging.info("{} was successful and was validated!".format( calc.label)) atoms = self.read_log(os.path.join(scratch_dir, f)) starting_molecule = RMGMolecule(SMILES=conformer.smiles) starting_molecule = starting_molecule.toSingleBonds() test_molecule = RMGMolecule() test_molecule.fromXYZ(atoms.arrays["numbers"], atoms.arrays["positions"]) if not starting_molecule.isIsomorphic(test_molecule): logging.info( "Output geometry of {} is not isomorphic with input geometry" .format(calc.label)) result = False else: logging.info("{} was successful and was validated!".format( calc.label)) result = True if not complete: logging.info("It appears that {} was killed prematurely".format( calc.label)) result = False elif not converged: logging.info("{} did not converge".format(calc.label)) result = False if isinstance(calculator, Gaussian): if not calc.convergence.lower() in [ "tight", "verytight", "loose" ]: logging.info("{} failed QM optimization".format( calc.label)) else: logging.info( "Resubmitting {} with default convergence criteria". format(calc.label)) atoms = self.read_log(os.path.join(scratch_dir, f)) conformer.ase_molecule = atoms conformer.update_coords_from("ase") calc = calculator.get_conformer_calc(conformer, convergence="") logging.info( "Removing the old log file that didn't converge, restarting from last geometry" ) os.remove(os.path.join(scratch_dir, f)) label = self.submit_conformer(conformer, calc, "general") while not self.check_complete(label): time.sleep(15) scratch_dir = os.path.join(calculator.scratch, "species", conformer.smiles, "conformers") f = calc.label + ".log" if not os.path.exists(os.path.join(scratch_dir, f)): logging.info( "It seems that {} was never run...".format( calc.label)) result = False complete, converged = calculator.verify_output_file( os.path.join(scratch_dir, f)) if not complete: logging.info( "It appears that {} was killed prematurely".format( calc.label)) result = False elif not converged: logging.info("{} failed second QM optimization".format( calc.label)) result = False else: atoms = self.read_log(os.path.join(scratch_dir, f)) starting_molecule = RMGMolecule( SMILES=conformer.smiles) starting_molecule = starting_molecule.toSingleBonds() test_molecule = RMGMolecule() test_molecule.fromXYZ(atoms.arrays["numbers"], atoms.arrays["positions"]) if not starting_molecule.isIsomorphic(test_molecule): logging.info( "Output geometry of {} is not isomorphic with input geometry" .format(calc.label)) result = False else: logging.info( "{} was successful and was validated!".format( calc.label)) result = True if not result: fail_dir = os.path.join(scratch_dir, "failures") try: os.makedirs(os.path.join(scratch_dir, "failures")) except OSError: logging.info("{} already exists...".format(fail_dir)) move(os.path.join(scratch_dir, f), os.path.join(scratch_dir, "failures", f)) return False return True
def verifyOutputFile(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.outputFilePath): logging.debug("Output file {0} does not (yet) exist.".format( self.outputFilePath)) return False InChIMatch = False #flag (1 or 0) indicating whether the InChI in the file matches InChIaug this can only be 1 if InChIFound is also 1 InChIFound = False #flag (1 or 0) indicating whether an InChI was found in the log file # Initialize dictionary with "False"s successKeysFound = dict([(key, False) for key in self.successKeys]) with open(self.outputFilePath) 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: successKeysFound[element] = True if "InChI=" in line: logFileInChI = line #output files should take up to 240 characters of the name in the input file InChIFound = True if self.uniqueIDlong in logFileInChI: InChIMatch = True else: logging.warning( "InChI in log file ({0}) didn't match that in geometry ({1})." .format(logFileInChI, self.uniqueIDlong)) # Use only up to first 80 characters to match due to MOPAC bug which deletes 81st character of InChI string if self.uniqueIDlong.startswith(logFileInChI[:80]): logging.warning( "but the beginning matches so it's probably just a truncation problem." ) InChIMatch = True # Check that ALL 'success' keywords were found in the file. if not all(successKeysFound.values()): logging.error( 'Not all of the required keywords for success were found in the output file!' ) return False if not InChIFound: logging.error( "No InChI was found in the MOPAC output file {0}".format( self.outputFilePath)) return False if InChIMatch: # Compare the optimized geometry to the original molecule parser = cclib.parser.Mopac(self.outputFilePath) parser.logger.setLevel( logging.ERROR ) #cf. http://cclib.sourceforge.net/wiki/index.php/Using_cclib#Additional_information cclibData = parser.parse() cclibMol = Molecule() cclibMol.fromXYZ(cclibData.atomnos, cclibData.atomcoords[-1]) testMol = self.molecule.toSingleBonds() if cclibMol.isIsomorphic(testMol): logging.info( "Successful MOPAC quantum result found in {0}".format( self.outputFilePath)) # " + self.molfile.name + " ("+self.molfile.InChIAug+") has been found. This log file will be used.") return True else: logging.info( "Incorrect connectivity for optimized geometry in file {0}" .format(self.outputFilePath)) # " + self.molfile.name + " ("+self.molfile.InChIAug+") has been found. This log file will be used.") return False #InChIs do not match (most likely due to limited name length mirrored in log file (240 characters), but possibly due to a collision) return self.checkForInChiKeyCollision( logFileInChI) # Not yet implemented!
def verifyOutputFile(self): """ Check's that an output file exists and was successful. Returns a boolean flag that states whether a successful GAUSSIAN 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 are satisfied, it will return True. """ if not os.path.exists(self.outputFilePath): logging.info("Output file {0} does not exist.".format( self.outputFilePath)) return False InChIMatch = False #flag (1 or 0) indicating whether the InChI in the file matches InChIaug this can only be 1 if InChIFound is also 1 InChIFound = False #flag (1 or 0) indicating whether an InChI was found in the log file # Initialize dictionary with "False"s successKeysFound = dict([(key, False) for key in self.successKeys]) with open(self.outputFilePath) as outputFile: for line in outputFile: line = line.strip() for element in self.failureKeys: #search for failure keywords if element in line: logging.error( "Gaussian output file contains the following error: {0}" .format(element)) return False for element in self.successKeys: #search for success keywords if element in line: successKeysFound[element] = True if line.startswith("InChI="): logFileInChI = line #output files should take up to 240 characters of the name in the input file InChIFound = True if logFileInChI == self.geometry.uniqueIDlong: InChIMatch = True elif self.geometry.uniqueIDlong.startswith(logFileInChI): logging.info( "InChI too long to check, but beginning matches so assuming OK." ) InChIMatch = True else: logging.warning( "InChI in log file ({0}) didn't match that in geometry ({1})." .format(logFileInChI, self.geometry.uniqueIDlong)) if self.geometry.uniqueIDlong.startswith(logFileInChI): logging.warning( "but the beginning matches so it's probably just a truncation problem." ) InChIMatch = True # Check that ALL 'success' keywords were found in the file. if not all(successKeysFound.values()): logging.error( 'Not all of the required keywords for success were found in the output file!' ) return False if not InChIFound: logging.error( "No InChI was found in the Gaussian output file {0}".format( self.outputFilePath)) return False if not InChIMatch: #InChIs do not match (most likely due to limited name length mirrored in log file (240 characters), but possibly due to a collision) return self.checkForInChiKeyCollision( logFileInChI) # Not yet implemented! # Compare the optimized geometry to the original molecule qmData = self.parse() cclibMol = Molecule() cclibMol.fromXYZ(qmData.atomicNumbers, qmData.atomCoords.value) testMol = self.molecule.toSingleBonds() if not cclibMol.isIsomorphic(testMol): logging.info( "Incorrect connectivity for optimized geometry in file {0}". format(self.outputFilePath)) return False logging.info("Successful MOPAC quantum result found in {0}".format( self.outputFilePath)) return True
def test_intra_H_migration(self): """ Test that the intra_H_migration family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['intra_H_migration'] reactants = [Molecule().fromAdjacencyList(""" multiplicity 2 1 *2 C u0 p0 c0 {3,S} {11,S} {12,S} {13,S} 2 *4 C u0 p0 c0 {4,S} {5,S} {6,D} 3 *5 C u0 p0 c0 {1,S} {7,D} {14,S} 4 *1 C u1 p0 c0 {2,S} {8,S} {15,S} 5 C u0 p0 c0 {2,S} {10,D} {17,S} 6 *6 C u0 p0 c0 {2,D} {7,S} {19,S} 7 *7 C u0 p0 c0 {3,D} {6,S} {21,S} 8 C u0 p0 c0 {4,S} {9,D} {16,S} 9 C u0 p0 c0 {8,D} {10,S} {20,S} 10 C u0 p0 c0 {5,D} {9,S} {18,S} 11 *3 H u0 p0 c0 {1,S} 12 H u0 p0 c0 {1,S} 13 H u0 p0 c0 {1,S} 14 H u0 p0 c0 {3,S} 15 H u0 p0 c0 {4,S} 16 H u0 p0 c0 {8,S} 17 H u0 p0 c0 {5,S} 18 H u0 p0 c0 {10,S} 19 H u0 p0 c0 {6,S} 20 H u0 p0 c0 {9,S} 21 H u0 p0 c0 {7,S} """)] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 *1 C u1 p0 c0 {3,S} {12,S} {13,S} 2 *5 C u0 p0 c0 {4,S} {5,S} {6,D} 3 *4 C u0 p0 c0 {1,S} {7,D} {14,S} 4 *2 C u0 p0 c0 {2,S} {11,S} {8,S} {15,S} 5 C u0 p0 c0 {2,S} {10,D} {17,S} 6 *7 C u0 p0 c0 {2,D} {7,S} {19,S} 7 *6 C u0 p0 c0 {3,D} {6,S} {21,S} 8 C u0 p0 c0 {4,S} {9,D} {16,S} 9 C u0 p0 c0 {8,D} {10,S} {20,S} 10 C u0 p0 c0 {5,D} {9,S} {18,S} 11 *3 H u0 p0 c0 {4,S} 12 H u0 p0 c0 {1,S} 13 H u0 p0 c0 {1,S} 14 H u0 p0 c0 {3,S} 15 H u0 p0 c0 {4,S} 16 H u0 p0 c0 {8,S} 17 H u0 p0 c0 {5,S} 18 H u0 p0 c0 {10,S} 19 H u0 p0 c0 {6,S} 20 H u0 p0 c0 {9,S} 21 H u0 p0 c0 {7,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def testReactBenzeneBond2(self): """ Test that hydrogen addition to phenanthrene (w/ benzene bonds) returns kekulized product. """ family = self.database.families['R_Addition_MultipleBond'] reactants = [ Molecule().fromAdjacencyList(""" 1 *1 C u0 p0 c0 {2,B} {3,B} {6,B} 2 *2 C u0 p0 c0 {1,B} {4,B} {9,B} 3 C u0 p0 c0 {1,B} {5,B} {7,B} 4 C u0 p0 c0 {2,B} {8,B} {10,B} 5 C u0 p0 c0 {3,B} {11,B} {17,S} 6 C u0 p0 c0 {1,B} {12,B} {18,S} 7 C u0 p0 c0 {3,B} {8,B} {19,S} 8 C u0 p0 c0 {4,B} {7,B} {20,S} 9 C u0 p0 c0 {2,B} {13,B} {21,S} 10 C u0 p0 c0 {4,B} {14,B} {23,S} 11 C u0 p0 c0 {5,B} {12,B} {15,S} 12 C u0 p0 c0 {6,B} {11,B} {16,S} 13 C u0 p0 c0 {9,B} {14,B} {22,S} 14 C u0 p0 c0 {10,B} {13,B} {24,S} 15 H u0 p0 c0 {11,S} 16 H u0 p0 c0 {12,S} 17 H u0 p0 c0 {5,S} 18 H u0 p0 c0 {6,S} 19 H u0 p0 c0 {7,S} 20 H u0 p0 c0 {8,S} 21 H u0 p0 c0 {9,S} 22 H u0 p0 c0 {13,S} 23 H u0 p0 c0 {10,S} 24 H u0 p0 c0 {14,S} """), Molecule().fromAdjacencyList("1 *3 H u1 p0 c0") ] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 *1 C u0 p0 c0 {2,S} {3,S} {5,S} {15,S} 2 *2 C u1 p0 c0 {1,S} {4,S} {8,S} 3 C u0 p0 c0 {1,S} {6,S} {7,D} 4 C u0 p0 c0 {2,S} {9,D} {10,S} 5 C u0 p0 c0 {1,S} {11,D} {16,S} 6 C u0 p0 c0 {3,S} {12,D} {19,S} 7 C u0 p0 c0 {3,D} {9,S} {20,S} 8 C u0 p0 c0 {2,S} {13,D} {22,S} 9 C u0 p0 c0 {4,D} {7,S} {21,S} 10 C u0 p0 c0 {4,S} {14,D} {24,S} 11 C u0 p0 c0 {5,D} {12,S} {18,S} 12 C u0 p0 c0 {6,D} {11,S} {17,S} 13 C u0 p0 c0 {8,D} {14,S} {23,S} 14 C u0 p0 c0 {10,D} {13,S} {25,S} 15 *3 H u0 p0 c0 {1,S} 16 H u0 p0 c0 {5,S} 17 H u0 p0 c0 {12,S} 18 H u0 p0 c0 {11,S} 19 H u0 p0 c0 {6,S} 20 H u0 p0 c0 {7,S} 21 H u0 p0 c0 {9,S} 22 H u0 p0 c0 {8,S} 23 H u0 p0 c0 {13,S} 24 H u0 p0 c0 {10,S} 25 H u0 p0 c0 {14,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) self.assertTrue(expectedProduct.isIsomorphic(products[0]))
def test_intra_H_migration(self): """ Test that the intra_H_migration family, which is its own reverse, returns a properly re-labeled product structure. """ family = self.database.families['intra_H_migration'] reactants = [ Molecule().fromAdjacencyList(""" multiplicity 2 1 *2 C u0 p0 c0 {3,S} {11,S} {12,S} {13,S} 2 *4 C u0 p0 c0 {4,S} {5,S} {6,D} 3 *5 C u0 p0 c0 {1,S} {7,D} {14,S} 4 *1 C u1 p0 c0 {2,S} {8,S} {15,S} 5 C u0 p0 c0 {2,S} {10,D} {17,S} 6 *6 C u0 p0 c0 {2,D} {7,S} {19,S} 7 *7 C u0 p0 c0 {3,D} {6,S} {21,S} 8 C u0 p0 c0 {4,S} {9,D} {16,S} 9 C u0 p0 c0 {8,D} {10,S} {20,S} 10 C u0 p0 c0 {5,D} {9,S} {18,S} 11 *3 H u0 p0 c0 {1,S} 12 H u0 p0 c0 {1,S} 13 H u0 p0 c0 {1,S} 14 H u0 p0 c0 {3,S} 15 H u0 p0 c0 {4,S} 16 H u0 p0 c0 {8,S} 17 H u0 p0 c0 {5,S} 18 H u0 p0 c0 {10,S} 19 H u0 p0 c0 {6,S} 20 H u0 p0 c0 {9,S} 21 H u0 p0 c0 {7,S} """) ] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 *1 C u1 p0 c0 {3,S} {12,S} {13,S} 2 *5 C u0 p0 c0 {4,S} {5,S} {6,D} 3 *4 C u0 p0 c0 {1,S} {7,D} {14,S} 4 *2 C u0 p0 c0 {2,S} {11,S} {8,S} {15,S} 5 C u0 p0 c0 {2,S} {10,D} {17,S} 6 *7 C u0 p0 c0 {2,D} {7,S} {19,S} 7 *6 C u0 p0 c0 {3,D} {6,S} {21,S} 8 C u0 p0 c0 {4,S} {9,D} {16,S} 9 C u0 p0 c0 {8,D} {10,S} {20,S} 10 C u0 p0 c0 {5,D} {9,S} {18,S} 11 *3 H u0 p0 c0 {4,S} 12 H u0 p0 c0 {1,S} 13 H u0 p0 c0 {1,S} 14 H u0 p0 c0 {3,S} 15 H u0 p0 c0 {4,S} 16 H u0 p0 c0 {8,S} 17 H u0 p0 c0 {5,S} 18 H u0 p0 c0 {10,S} 19 H u0 p0 c0 {6,S} 20 H u0 p0 c0 {9,S} 21 H u0 p0 c0 {7,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) mapping = {} for label, atom in expectedProduct.getLabeledAtoms().iteritems(): mapping[atom] = products[0].getLabeledAtom(label) self.assertTrue(expectedProduct.isIsomorphic(products[0], mapping))
def testReactBenzeneBond2(self): """ Test that hydrogen addition to phenanthrene (w/ benzene bonds) returns kekulized product. """ family = self.database.families['R_Addition_MultipleBond'] reactants = [Molecule().fromAdjacencyList(""" 1 *1 C u0 p0 c0 {2,B} {3,B} {6,B} 2 *2 C u0 p0 c0 {1,B} {4,B} {9,B} 3 C u0 p0 c0 {1,B} {5,B} {7,B} 4 C u0 p0 c0 {2,B} {8,B} {10,B} 5 C u0 p0 c0 {3,B} {11,B} {17,S} 6 C u0 p0 c0 {1,B} {12,B} {18,S} 7 C u0 p0 c0 {3,B} {8,B} {19,S} 8 C u0 p0 c0 {4,B} {7,B} {20,S} 9 C u0 p0 c0 {2,B} {13,B} {21,S} 10 C u0 p0 c0 {4,B} {14,B} {23,S} 11 C u0 p0 c0 {5,B} {12,B} {15,S} 12 C u0 p0 c0 {6,B} {11,B} {16,S} 13 C u0 p0 c0 {9,B} {14,B} {22,S} 14 C u0 p0 c0 {10,B} {13,B} {24,S} 15 H u0 p0 c0 {11,S} 16 H u0 p0 c0 {12,S} 17 H u0 p0 c0 {5,S} 18 H u0 p0 c0 {6,S} 19 H u0 p0 c0 {7,S} 20 H u0 p0 c0 {8,S} 21 H u0 p0 c0 {9,S} 22 H u0 p0 c0 {13,S} 23 H u0 p0 c0 {10,S} 24 H u0 p0 c0 {14,S} """), Molecule().fromAdjacencyList("1 *3 H u1 p0 c0")] expectedProduct = Molecule().fromAdjacencyList(""" multiplicity 2 1 *1 C u0 p0 c0 {2,S} {3,S} {5,S} {15,S} 2 *2 C u1 p0 c0 {1,S} {4,S} {8,S} 3 C u0 p0 c0 {1,S} {6,S} {7,D} 4 C u0 p0 c0 {2,S} {9,D} {10,S} 5 C u0 p0 c0 {1,S} {11,D} {16,S} 6 C u0 p0 c0 {3,S} {12,D} {19,S} 7 C u0 p0 c0 {3,D} {9,S} {20,S} 8 C u0 p0 c0 {2,S} {13,D} {22,S} 9 C u0 p0 c0 {4,D} {7,S} {21,S} 10 C u0 p0 c0 {4,S} {14,D} {24,S} 11 C u0 p0 c0 {5,D} {12,S} {18,S} 12 C u0 p0 c0 {6,D} {11,S} {17,S} 13 C u0 p0 c0 {8,D} {14,S} {23,S} 14 C u0 p0 c0 {10,D} {13,S} {25,S} 15 *3 H u0 p0 c0 {1,S} 16 H u0 p0 c0 {5,S} 17 H u0 p0 c0 {12,S} 18 H u0 p0 c0 {11,S} 19 H u0 p0 c0 {6,S} 20 H u0 p0 c0 {7,S} 21 H u0 p0 c0 {9,S} 22 H u0 p0 c0 {8,S} 23 H u0 p0 c0 {13,S} 24 H u0 p0 c0 {10,S} 25 H u0 p0 c0 {14,S} """) products = family.applyRecipe(reactants) self.assertEqual(len(products), 1) self.assertTrue(expectedProduct.isIsomorphic(products[0]))