Esempio n. 1
0
    def find_species(self, identifier):
        """Find species based on provided identifier"""
        if identifier in self.species:
            # This is a Species object
            return identifier
        elif identifier in self.species_dict:
            # This is a species label
            return self.species_dict[identifier]
        else:
            try:
                spc = Species(molecule=[Molecule().fromSMILES(identifier)])
            except ValueError:
                try:
                    spc = Species(molecule=[Molecule().fromInChI(identifier)])
                except ValueError:
                    raise ValueError(
                        'Unable to interpret provided identifier {0} as '
                        'species label, SMILES, or InChI.'.format(identifier))

            spc.generate_resonance_structures()

            for species in self.species_dict.itervalues():
                if spc.isIsomorphic(species):
                    return species
            else:
                raise ValueError(
                    'Unable to find any species matching the identifier {0}.'.
                    format(identifier))
Esempio n. 2
0
    def test_singlet_vs_closed_shell(self):
        adjlist_singlet = """
1 C u0 p0 c0 {2,D} {3,S} {4,S}
2 C u0 p0 c0 {1,D} {3,S} {5,S}
3 C u0 p1 c0 {1,S} {2,S}
4 H u0 p0 c0 {1,S}
5 H u0 p0 c0 {2,S}
        """

        adjlist_closed_shell = """
1 C u0 p0 c0 {2,D} {3,S} {4,S}
2 C u0 p0 c0 {1,D} {3,D}
3 C u0 p0 c0 {1,S} {2,D} {5,S}
4 H u0 p0 c0 {1,S}
5 H u0 p0 c0 {3,S}
        """

        singlet = Species(molecule=[Molecule().fromAdjacencyList(adjlist_singlet)])
        singlet.generate_resonance_structures()
        closed_shell = Species(molecule=[Molecule().fromAdjacencyList(adjlist_closed_shell)])
        closed_shell.generate_resonance_structures()

        singlet_aug_inchi = singlet.getAugmentedInChI()
        closed_shell_aug_inchi = closed_shell.getAugmentedInChI()
        self.assertTrue(singlet_aug_inchi != closed_shell_aug_inchi)
Esempio n. 3
0
    def compare(self, inchi, u_indices=None, p_indices=None):
        u_layer = U_LAYER_PREFIX + U_LAYER_SEPARATOR.join(map(
            str, u_indices)) if u_indices else None
        p_layer = P_LAYER_PREFIX + P_LAYER_SEPARATOR.join(map(
            str, p_indices)) if p_indices else None

        aug_inchi = compose_aug_inchi(inchi, u_layer, p_layer)

        mol = from_augmented_inchi(Molecule(), aug_inchi)
        ConsistencyChecker.check_multiplicity(mol.get_radical_count(),
                                              mol.multiplicity)

        for at in mol.atoms:
            ConsistencyChecker.check_partial_charge(at)

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

        ignore_prefix = r"(InChI=1+)(S*)/"
        aug_inchi_expected = re.split(ignore_prefix, aug_inchi)[-1]
        aug_inchi_computed = re.split(ignore_prefix,
                                      spc.get_augmented_inchi())[-1]
        self.assertEquals(aug_inchi_expected, aug_inchi_computed)

        return mol
Esempio n. 4
0
    def loadEntry(self,
                  index,
                  label,
                  solvent,
                  molecule=None,
                  reference=None,
                  referenceType='',
                  shortDesc='',
                  longDesc='',
                  ):
        spc = molecule
        if molecule is not None:
            try:
                spc = Species().fromSMILES(molecule)
            except:
                logging.debug("Solvent '{0}' does not have a valid SMILES '{1}'" .format(label, molecule))
                try:
                    spc = Species().fromAdjacencyList(molecule)
                except:
                    logging.error("Can't understand '{0}' in solute library '{1}'".format(molecule, self.name))
                    raise
            spc.generate_resonance_structures()

        self.entries[label] = Entry(
            index = index,
            label = label,
            item = spc,
            data = solvent,
            reference = reference,
            referenceType = referenceType,
            shortDesc = shortDesc,
            longDesc = longDesc.strip(),
        )
Esempio n. 5
0
    def loadEntry(self,
                  index,
                  label,
                  solvent,
                  molecule=None,
                  reference=None,
                  referenceType='',
                  shortDesc='',
                  longDesc='',
                  ):
        spc = molecule
        if molecule is not None:
            try:
                spc = Species().fromSMILES(molecule)
            except:
                logging.debug("Solvent '{0}' does not have a valid SMILES '{1}'" .format(label, molecule))
                try:
                    spc = Species().fromAdjacencyList(molecule)
                except:
                    logging.error("Can't understand '{0}' in solute library '{1}'".format(molecule, self.name))
                    raise
            spc.generate_resonance_structures()

        self.entries[label] = Entry(
            index = index,
            label = label,
            item = spc,
            data = solvent,
            reference = reference,
            referenceType = referenceType,
            shortDesc = shortDesc,
            longDesc = longDesc.strip(),
        )
Esempio n. 6
0
    def test_singlet_vs_closed_shell(self):
        adjlist_singlet = """
1 C u0 p0 c0 {2,D} {3,S} {4,S}
2 C u0 p0 c0 {1,D} {3,S} {5,S}
3 C u0 p1 c0 {1,S} {2,S}
4 H u0 p0 c0 {1,S}
5 H u0 p0 c0 {2,S}
        """

        adjlist_closed_shell = """
1 C u0 p0 c0 {2,D} {3,S} {4,S}
2 C u0 p0 c0 {1,D} {3,D}
3 C u0 p0 c0 {1,S} {2,D} {5,S}
4 H u0 p0 c0 {1,S}
5 H u0 p0 c0 {3,S}
        """

        singlet = Species(
            molecule=[Molecule().fromAdjacencyList(adjlist_singlet)])
        singlet.generate_resonance_structures()
        closed_shell = Species(
            molecule=[Molecule().fromAdjacencyList(adjlist_closed_shell)])
        closed_shell.generate_resonance_structures()

        singlet_aug_inchi = singlet.getAugmentedInChI()
        closed_shell_aug_inchi = closed_shell.getAugmentedInChI()
        self.assertTrue(singlet_aug_inchi != closed_shell_aug_inchi)
Esempio n. 7
0
    def test_calculate_degeneracy_for_non_reactive_molecule(self):
        """
        tests that the calculateDegeneracy method gets the degeneracy correct for unreactive molecules
        and that __generateReactions work correctly with the react_non_reactive flag set to `True`.
        """
        from rmgpy.data.rmg import getDB
        from rmgpy.data.kinetics.family import TemplateReaction

        adjlist = [
            '''
        multiplicity 2
        1 H u1 p0 c0''', '''
        multiplicity 2
        1 O u1 p1 c+1 {2,D}
        2 N u0 p2 c-1 {1,D}''', '''
        1 O u0 p1 c+1 {2,D} {3,S}
        2 N u0 p2 c-1 {1,D}
        3 H u0 p0 c0 {1,S}'''
        ]

        family = getDB('kinetics').families['R_Recombination']
        r1 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[0])])
        r2 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[1])
                               ])  # r2 is not the representative structure of
        # NO, but it is the correct structure participating in this reaction
        p1 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[2])])
        r2.generate_resonance_structures(keep_isomorphic=True)

        rxn = TemplateReaction(reactants=[r1, r2], products=[p1])
        rxn.degeneracy = family.calculateDegeneracy(rxn)
        self.assertEqual(rxn.degeneracy, 1)
    def test_calculate_degeneracy_for_non_reactive_molecule(self):
        """
        tests that the calculateDegeneracy method gets the degeneracy correct for unreactive molecules
        and that __generateReactions work correctly with the react_non_reactive flag set to `True`.
        """
        from rmgpy.data.rmg import getDB
        from rmgpy.data.kinetics.family import TemplateReaction

        adjlist = ['''
        multiplicity 2
        1 H u1 p0 c0''',
                   '''
        multiplicity 2
        1 O u1 p1 c+1 {2,D}
        2 N u0 p2 c-1 {1,D}''',
                   '''
        1 O u0 p1 c+1 {2,D} {3,S}
        2 N u0 p2 c-1 {1,D}
        3 H u0 p0 c0 {1,S}''']

        family = getDB('kinetics').families['R_Recombination']
        r1 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[0])])
        r2 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[1])])  # r2 is not the representative structure of
        # NO, but it is the correct structure participating in this reaction
        p1 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[2])])
        r2.generate_resonance_structures(keep_isomorphic=True)

        rxn = TemplateReaction(reactants=[r1, r2], products=[p1])
        rxn.degeneracy = family.calculateDegeneracy(rxn)
        self.assertEqual(rxn.degeneracy, 1)
Esempio n. 9
0
 def testResonaceIsomersRepresented(self):
     "Test that both resonance forms of 1-penten-3-yl are printed by __repr__"
     spec = Species().fromSMILES('C=C[CH]CC')
     spec.generate_resonance_structures()
     exec('spec2 = {0!r}'.format(spec))
     self.assertEqual(len(spec.molecule), len(spec2.molecule))
     for i, j in zip(spec.molecule, spec2.molecule):
         self.assertTrue(j.isIsomorphic(i), msg='i is not isomorphic with j, where i is {} and j is {}'.format(i.toSMILES(), j.toSMILES()))
Esempio n. 10
0
    def compare(self, adjlist, aug_inchi):
        spc = Species(molecule=[Molecule().from_adjacency_list(adjlist)])
        spc.generate_resonance_structures()

        ignore_prefix = r"(InChI=1+)(S*)/"

        exp = re.split(ignore_prefix, aug_inchi)[-1]
        comp = re.split(ignore_prefix, spc.get_augmented_inchi())[-1]
        self.assertEquals(exp, comp)
    def compare(self, adjlist, aug_inchi):
        spc = Species(molecule=[Molecule().fromAdjacencyList(adjlist)])
        spc.generate_resonance_structures()

        ignore_prefix = r"(InChI=1+)(S*)/"

        exp = re.split(ignore_prefix, aug_inchi)[-1]
        comp = re.split(ignore_prefix, spc.getAugmentedInChI())[-1]
        self.assertEquals(exp, comp)
Esempio n. 12
0
    def test_check_for_existing_species_for_bi_aromatics(self):
        """
        Test RMG check_for_existing_species can correctly check isomorphism for biaromatics.
        In this test, DPP is a species already stored in rmg species_dict, mol_test is a newly
        created molecule which has one kekulized benzene ring and one double_bond-single_bond
        benzene ring.
        """

        rmg_test = RMG()
        rmg_test.reaction_model = CoreEdgeReactionModel()
        DPP = Species().from_smiles('C1=CC=C(C=C1)CCCC1C=CC=CC=1')
        DPP.generate_resonance_structures()
        formula = DPP.molecule[0].get_formula()
        if formula in rmg_test.reaction_model.species_dict:
            rmg_test.reaction_model.species_dict[formula].append(DPP)
        else:
            rmg_test.reaction_model.species_dict[formula] = [DPP]

        mol_test = Molecule().from_adjacency_list(
"""
1     C u0 p0 c0 {2,S} {3,S} {16,S} {17,S}
2     C u0 p0 c0 {1,S} {4,S} {18,S} {19,S}
3     C u0 p0 c0 {1,S} {5,S} {20,S} {21,S}
4     C u0 p0 c0 {2,S} {6,B} {7,B}
5     C u0 p0 c0 {3,S} {8,D} {9,S}
6     C u0 p0 c0 {4,B} {10,B} {22,S}
7     C u0 p0 c0 {4,B} {12,B} {24,S}
8     C u0 p0 c0 {5,D} {14,S} {27,S}
9     C u0 p0 c0 {5,S} {15,D} {28,S}
10    C u0 p0 c0 {6,B} {11,B} {23,S}
11    C u0 p0 c0 {10,B} {12,B} {25,S}
12    C u0 p0 c0 {7,B} {11,B} {26,S}
13    C u0 p0 c0 {14,D} {15,S} {29,S}
14    C u0 p0 c0 {8,S} {13,D} {30,S}
15    C u0 p0 c0 {9,D} {13,S} {31,S}
16    H u0 p0 c0 {1,S}
17    H u0 p0 c0 {1,S}
18    H u0 p0 c0 {2,S}
19    H u0 p0 c0 {2,S}
20    H u0 p0 c0 {3,S}
21    H u0 p0 c0 {3,S}
22    H u0 p0 c0 {6,S}
23    H u0 p0 c0 {10,S}
24    H u0 p0 c0 {7,S}
25    H u0 p0 c0 {11,S}
26    H u0 p0 c0 {12,S}
27    H u0 p0 c0 {8,S}
28    H u0 p0 c0 {9,S}
29    H u0 p0 c0 {13,S}
30    H u0 p0 c0 {14,S}
31    H u0 p0 c0 {15,S}
""")
        spec = rmg_test.reaction_model.check_for_existing_species(mol_test)
        self.assertIsNotNone(spec)
Esempio n. 13
0
 def test_resonace_isomers_represented(self):
     """Test that both resonance forms of 1-penten-3-yl are printed by __repr__"""
     spec = Species().from_smiles('C=C[CH]CC')
     spec.generate_resonance_structures()
     namespace = {}
     exec('spec2 = {0!r}'.format(spec), globals(), namespace)
     self.assertIn('spec2', namespace)
     spec2 = namespace['spec2']
     self.assertEqual(len(spec.molecule), len(spec2.molecule))
     for i, j in zip(spec.molecule, spec2.molecule):
         self.assertTrue(j.is_isomorphic(i),
                         msg='i is not isomorphic with j, where i is {} and j is {}'.format(i.to_smiles(),
                                                                                            j.to_smiles()))
Esempio n. 14
0
    def predict_thermo(self, smiles):

        if self.kernel_type == 'GA':
            spec = Species().fromSMILES(smiles)
            spec.generate_resonance_structures()

            thermo = self.kernel.getThermoDataFromGroups(spec)

            return thermo

        else:
            raise Exception('Kernel type {0} not supported yet.'.format(
                self.kernel_type))
Esempio n. 15
0
def ensure_species(input_list, resonance=False, keepIsomorphic=False):
    """
    The input list of :class:`Species` or :class:`Molecule` objects is modified
    in place to only have :class:`Species` objects. Returns None.
    """
    for index, item in enumerate(input_list):
        if isinstance(item, Molecule):
            new_item = Species(molecule=[item])
        elif isinstance(item, Species):
            new_item = item
        else:
            raise TypeError('Only Molecule or Species objects can be handled.')
        if resonance:
            new_item.generate_resonance_structures(
                keepIsomorphic=keepIsomorphic)
        input_list[index] = new_item
Esempio n. 16
0
def check_isomorphism(mol1, mol2, filter_structures=True):
    """
    Converts `mol1` and `mol2` which are RMG:Molecule objects into RMG:Species object
    and generate resonance structures. Then check Species isomorphism.
    Return True if one of the molecules in the Species derived from `mol1`
    is isomorphic to  one of the molecules in the Species derived from `mol2`.
    `filter_structures` is being passes to Species.generate_resonance_structures().
    make copies of the molecules, since isIsomorphic() changes atom orders
    """
    mol1.reactive, mol2.reactive = True, True
    mol1_copy = mol1.copy(deep=True)
    mol2_copy = mol2.copy(deep=True)
    spc1 = Species(molecule=[mol1_copy])
    spc1.generate_resonance_structures(keep_isomorphic=False, filter_structures=filter_structures)
    spc2 = Species(molecule=[mol2_copy])
    spc2.generate_resonance_structures(keep_isomorphic=False, filter_structures=filter_structures)
    return spc1.isIsomorphic(spc2)
Esempio n. 17
0
    def test_check_for_existing_reaction_eliminates_identical_reactions_without_duplicate_flag(
            self):
        """
        Test that check_for_existing_reaction eliminates reactions with different templates and duplicate=false
        """
        cerm = CoreEdgeReactionModel()

        # make species' objects
        spcA = Species().from_smiles('[H]')
        spcB = Species().from_smiles('C=C[CH2]C')
        spcC = Species().from_smiles('C=C=CC')
        spcD = Species().from_smiles('[H][H]')
        spcA.label = '[H]'
        spcB.label = 'C=C[CH2]C'
        spcC.label = 'C=C=CC'
        spcD.label = '[H][H]'
        spcB.generate_resonance_structures()

        cerm.add_species_to_core(spcA)
        cerm.add_species_to_core(spcB)
        cerm.add_species_to_core(spcC)
        cerm.add_species_to_core(spcD)

        reaction_in_model = TemplateReaction(reactants=[spcA, spcB],
                                             products=[spcC, spcD],
                                             family='H_Abstraction',
                                             template=['Csd', 'H'],
                                             duplicate=False)
        reaction_in_model.reactants.sort()
        reaction_in_model.products.sort()

        reaction_to_add = TemplateReaction(reactants=[spcA, spcB],
                                           products=[spcC, spcD],
                                           family='H_Abstraction',
                                           template=['Cs12345', 'H'],
                                           duplicate=False)
        cerm.add_reaction_to_core(reaction_in_model)
        cerm.register_reaction(reaction_in_model)

        found, rxn = cerm.check_for_existing_reaction(reaction_to_add)

        self.assertTrue(
            found,
            'check_for_existing_reaction failed to eliminate reactions without duplicate tag'
        )
Esempio n. 18
0
def ensure_species(input_list, resonance=False, keepIsomorphic=False):
    """
    Given an input list of molecules or species, return a list with only
    species objects.
    """
    output_list = []
    for item in input_list:
        if isinstance(item, Molecule):
            new_item = Species(molecule=[item])
        elif isinstance(item, Species):
            new_item = item
        else:
            raise TypeError('Only Molecule or Species objects can be handled.')
        if resonance:
            new_item.generate_resonance_structures(keepIsomorphic=keepIsomorphic)
        output_list.append(new_item)

    return output_list
Esempio n. 19
0
    def test_deterministic_reaction_template_matching(self):
        """
        Test RMG work flow can match reaction template for kinetics estimation 
        deterministically. 

        In this test, a change of molecules order in a reacting species should 
        not change the reaction template matched.

        However, this is inherently impossible with the existing reaction
        generation algorithm. Currently, the first reaction will be the one
        that is kept if the reactions are identical. If different templates
        are a result of different transition states, all are kept.
        
        {O=C-[C]=C, [O]-C=C=C} -> H + C=C=C=O
        """

        # react
        spc = Species().from_smiles("O=C[C]=C")
        spc.generate_resonance_structures()
        new_reactions = react_species((spc, ))

        # try to pick out the target reaction
        mol_H = Molecule().from_smiles("[H]")
        mol_C3H2O = Molecule().from_smiles("C=C=C=O")

        target_rxns = find_target_rxns_containing(mol_H, mol_C3H2O,
                                                  new_reactions)
        self.assertEqual(len(target_rxns), 2)

        # reverse the order of molecules in spc
        spc.molecule = list(reversed(spc.molecule))

        # react again
        new_reactions_reverse = []
        new_reactions_reverse.extend(react_species((spc, )))

        # try to pick out the target reaction
        target_rxns_reverse = find_target_rxns_containing(
            mol_H, mol_C3H2O, new_reactions_reverse)
        self.assertEqual(len(target_rxns_reverse), 2)

        # whatever order of molecules in spc, the reaction template matched should be same
        self.assertEqual(target_rxns[0].template,
                         target_rxns_reverse[0].template)
Esempio n. 20
0
def ensure_species(input_list, resonance=False, keep_isomorphic=False):
    """
    The input list of :class:`Species` or :class:`Molecule` objects is modified
    in place to only have :class:`Species` objects. Returns None.
    """
    for index, item in enumerate(input_list):
        if isinstance(item, Molecule):
            new_item = Species(molecule=[item])
        elif isinstance(item, Species):
            new_item = item
        else:
            raise TypeError('Only Molecule or Species objects can be handled.')
        if resonance:
            if not any([mol.reactive for mol in new_item.molecule]):
                # if generating a reaction containing a Molecule with a reactive=False flag (e.g., for degeneracy
                # calculations), that was now converted into a Species, first mark as reactive=True
                new_item.molecule[0].reactive = True
            new_item.generate_resonance_structures(keep_isomorphic=keep_isomorphic)
        input_list[index] = new_item
Esempio n. 21
0
def ensure_species(input_list, resonance=False, keep_isomorphic=False):
    """
    The input list of :class:`Species` or :class:`Molecule` objects is modified
    in place to only have :class:`Species` objects. Returns None.
    """
    for index, item in enumerate(input_list):
        if isinstance(item, Molecule):
            new_item = Species(molecule=[item])
        elif isinstance(item, Species):
            new_item = item
        else:
            raise TypeError('Only Molecule or Species objects can be handled.')
        if resonance:
            if not any([mol.reactive for mol in new_item.molecule]):
                # if generating a reaction containing a Molecule with a reactive=False flag (e.g., for degeneracy
                # calculations), that was now converted into a Species, first mark as reactive=True
                new_item.molecule[0].reactive = True
            new_item.generate_resonance_structures(keep_isomorphic=keep_isomorphic)
        input_list[index] = new_item
Esempio n. 22
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().fromAdjacencyList(adjlist)
        
        spc = Species(molecule=[mol])
        spc.generate_resonance_structures()
        aug_inchi = spc.getAugmentedInChI()

        self.assertEqual(Species(molecule=[Molecule().fromAugmentedInChI(aug_inchi)]).isIsomorphic(spc), True)
Esempio n. 23
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)
Esempio n. 24
0
    def test_check_for_existing_reaction_eliminates_identical_reactions(self):
        """
        Test that check_for_existing_reaction catches identical reactions.
        """
        cerm = CoreEdgeReactionModel()

        # make species' objects
        spcA = Species().from_smiles('[H]')
        spcB = Species().from_smiles('C=C[CH2]C')
        spcC = Species().from_smiles('C=C=CC')
        spcD = Species().from_smiles('[H][H]')
        spcA.label = '[H]'
        spcB.label = 'C=C[CH2]C'
        spcC.label = 'C=C=CC'
        spcD.label = '[H][H]'
        spcB.generate_resonance_structures()

        cerm.add_species_to_core(spcA)
        cerm.add_species_to_core(spcB)
        cerm.add_species_to_core(spcC)
        cerm.add_species_to_core(spcD)

        reaction_in_model = TemplateReaction(reactants=[spcA, spcB],
                                             products=[spcC, spcD],
                                             family='H_Abstraction',
                                             template=['Csd', 'H'])
        reaction_in_model.reactants.sort()
        reaction_in_model.products.sort()

        reaction_to_add = TemplateReaction(reactants=[spcA, spcB],
                                           products=[spcC, spcD],
                                           family='H_Abstraction',
                                           template=['Csd', 'H'])
        cerm.add_reaction_to_core(reaction_in_model)
        cerm.register_reaction(reaction_in_model)

        found, rxn = cerm.check_for_existing_reaction(reaction_to_add)

        self.assertTrue(
            found,
            'check_for_existing_reaction failed to identify existing reaction')
Esempio n. 25
0
    def test_add_atom_labels_for_reaction_2(self):
        """Test that addAtomLabelsForReaction can identify reactions with identical references
        The molecule [CH]=C=C has resonance in this reaction"""
        from rmgpy.data.rmg import getDB
        s1 = Species().fromSMILES('C=C=C')
        s2 = Species().fromSMILES('C=C=[CH]')
        s3 = Species().fromSMILES('C#CC')
        s2.generate_resonance_structures()
        reactants = [s1, s2]
        products = [s2, s3]
        reaction = TemplateReaction(reactants=reactants,
                                    products=products,
                                    family='H_Abstraction')
        family = getDB('kinetics').families['H_Abstraction']
        print reaction.reactants
        print reaction.products
        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,
            'wrong number of labels found {0}'.format(found_labels))
        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)
Esempio n. 26
0
    def compare(self, inchi, u_indices=None, p_indices = None):        
        u_layer = U_LAYER_PREFIX + U_LAYER_SEPARATOR.join(map(str, u_indices)) if u_indices else None
        p_layer = P_LAYER_PREFIX + P_LAYER_SEPARATOR.join(map(str, p_indices)) if p_indices else None

        aug_inchi = compose_aug_inchi(inchi, u_layer, p_layer)

        mol = fromAugmentedInChI(Molecule(), aug_inchi)
        ConsistencyChecker.check_multiplicity(mol.getRadicalCount(), mol.multiplicity)

        for at in mol.atoms:
            ConsistencyChecker.check_partial_charge(at)
        
        spc = Species(molecule=[mol])
        spc.generate_resonance_structures()

        ignore_prefix = r"(InChI=1+)(S*)/"
        aug_inchi_expected = re.split(ignore_prefix, aug_inchi)[-1]
        aug_inchi_computed = re.split(ignore_prefix, spc.getAugmentedInChI())[-1]
        self.assertEquals(aug_inchi_expected, aug_inchi_computed)

        return mol
Esempio n. 27
0
def combine_spc_list(spc_list1, spc_list2, same_source=True, resonance=True):
    """
    Combine two species list used in ARC input files
    
    Args:
        spc_list1 (list): One of the list containing species info for ARC input files
        spc_list2 (list): The other list
        same_source (bool): If two lists are generated using the 
                            same set of chemkin file and species dictionary
        resonance (bool): Generate resonance structures when checking isomorphism 
    
    Returns:
        spc_list (list): A list contains all of the species in spc_list1 and 
                         spc_list2
    """
    # If same source, then just compare the label
    if same_source:
        spc_list = spc_list1 + spc_list2
        spc_list = list(set(spc_list))
    # If not same source, compare the structure
    else:
        spc_list = list()
        for spc in spc_list1:
            if 'smiles' in spc.keys():
                spc_list.append(Species().from_smiles(spc['smiles']))
            elif 'adjlist' in spc.keys():
                spc_list.append(Species().from_adjacency_list(spc['adjlist']))
        for spc in spc_list2:
            if 'smiles' in spc.keys():
                species = Species().from_smiles(spc['smiles'])
            elif 'adjlist' in spc.keys():
                species = Species().from_adjacency_list(spc['adjlist'])
            if resonance:
                species.generate_resonance_structures()
            for species1 in spc_list:
                if species1.is_isomorphic(species):
                    break
            else:
                spc_list.append(spc)
    return spc_list
    def test_add_atom_labels_for_reaction_2(self):
        """Test that addAtomLabelsForReaction can identify reactions with identical references
        The molecule [CH]=C=C has resonance in this reaction"""
        from rmgpy.data.rmg import getDB
        s1 = Species().fromSMILES('C=C=C')
        s2 = Species().fromSMILES('C=C=[CH]')
        s3 = Species().fromSMILES('C#CC')
        s2.generate_resonance_structures()
        reactants = [s1,s2]
        products = [s2,s3]
        reaction = TemplateReaction(reactants =reactants,
                                    products = products,
                                    family = 'H_Abstraction')
        family = getDB('kinetics').families['H_Abstraction']
        print reaction.reactants
        print reaction.products
        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,'wrong number of labels found {0}'.format(found_labels))
        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)
Esempio n. 29
0
def generate_isotopomers(spc, N=1):
    """
    Generate all isotopomers of the parameter species by adding max. N carbon isotopes to the
    atoms of the species.
    """

    mol = spc.molecule[0]
    isotope = get_element(6, 13)

    mols = []
    add_isotope(0, N, mol, mols, isotope)

    spcs = []
    for isomol in mols:
        isotopomer = Species(molecule=[isomol],
                             thermo=deepcopy(spc.thermo),
                             transport_data=spc.transport_data,
                             reactive=spc.reactive)
        isotopomer.generate_resonance_structures(keep_isomorphic=True)
        spcs.append(isotopomer)

    # do not retain identical species:
    filtered = []
    while spcs:
        candidate = spcs.pop()
        unique = True
        for isotopomer in filtered:
            if isotopomer.is_isomorphic(candidate):
                unique = False
                break
        if unique:
            filtered.append(candidate)

    if spc.thermo:
        for isotopomer in filtered:
            correct_entropy(isotopomer, spc)

    return filtered
Esempio n. 30
0
def getReactionForEntry(entry, database):
    """
    Return a Reaction object for a given entry that uses Species instead of
    Molecules (so that we can compute the reaction thermo).
    """
    reaction = Reaction(reactants=[], products=[])
    for molecule in entry.item.reactants:
        molecule.makeHydrogensExplicit()
        reactant = Species(molecule=[molecule], label=molecule.toSMILES())
        reactant.generate_resonance_structures()
        reactant.thermo = generateThermoData(reactant, database)
        reaction.reactants.append(reactant)
    for molecule in entry.item.products:
        molecule.makeHydrogensExplicit()
        product = Species(molecule=[molecule], label=molecule.toSMILES())
        product.generate_resonance_structures()
        product.thermo = generateThermoData(product, database)
        reaction.products.append(product)

    reaction.kinetics = entry.data
    reaction.degeneracy = entry.item.degeneracy

    return reaction
Esempio n. 31
0
    def test_is_isomorphic_strict(self):
        """Test that the strict argument to Species.is_isomorphic works"""
        spc1 = Species(smiles='[CH2]C1=CC=CC2=C1C=CC1=C2C=CC=C1')
        spc2 = Species(smiles='C=C1C=CC=C2C1=C[CH]C1=C2C=CC=C1')
        spc3 = Species(smiles='[CH2]C1=CC2=C(C=C1)C1=C(C=CC=C1)C=C2')

        self.assertFalse(spc1.is_isomorphic(spc2, strict=True))
        self.assertTrue(spc1.is_isomorphic(spc2, strict=False))
        self.assertFalse(spc1.is_isomorphic(spc3, strict=True))
        self.assertFalse(spc1.is_isomorphic(spc3, strict=False))

        spc1.generate_resonance_structures()
        spc2.generate_resonance_structures()
        spc3.generate_resonance_structures()

        self.assertTrue(spc1.is_isomorphic(spc2, strict=True))
        self.assertTrue(spc1.is_isomorphic(spc2, strict=False))
        self.assertFalse(spc1.is_isomorphic(spc3, strict=True))
        self.assertFalse(spc1.is_isomorphic(spc3, strict=False))
    def getForwardReactionForFamilyEntry(self, entry, family, thermoDatabase):
        """
        For a given `entry` for a reaction of the given reaction `family` (the
        string label of the family), return the reaction with kinetics and
        degeneracy for the "forward" direction as defined by the reaction 
        family. For families that are their own reverse, the direction the
        kinetics is given in will be preserved. If the entry contains 
        functional groups for the reactants, assume that it is given in the 
        forward direction and do nothing. Returns the reaction in the direction
        consistent with the reaction family template, and the matching template.
        Note that the returned reaction will have its kinetics and degeneracy
        set appropriately.
        
        In order to reverse the reactions that are given in the reverse of the
        direction the family is defined, we need to compute the thermodynamics
        of the reactants and products. For this reason you must also pass
        the `thermoDatabase` to use to generate the thermo data.
        """
        reaction = None; template = None

        # Get the indicated reaction family
        try:
            groups = self.families[family].groups
        except KeyError:
            raise ValueError('Invalid value "{0}" for family parameter.'.format(family))

        if all([(isinstance(reactant, Group) or isinstance(reactant, LogicNode)) for reactant in entry.item.reactants]):
            # The entry is a rate rule, containing functional groups only
            # By convention, these are always given in the forward direction and
            # have kinetics defined on a per-site basis
            reaction = Reaction(
                reactants = entry.item.reactants[:],
                products = [],
                specificCollider = entry.item.specificCollider,
                kinetics = entry.data,
                degeneracy = 1,
            )
            template = [groups.entries[label] for label in entry.label.split(';')]

        elif (all([isinstance(reactant, Molecule) for reactant in entry.item.reactants]) and
            all([isinstance(product, Molecule) for product in entry.item.products])):
            # The entry is a real reaction, containing molecules
            # These could be defined for either the forward or reverse direction
            # and could have a reaction-path degeneracy

            reaction = Reaction(reactants=[], products=[])
            for molecule in entry.item.reactants:
                reactant = Species(molecule=[molecule])
                reactant.generate_resonance_structures()
                reactant.thermo = thermoDatabase.getThermoData(reactant)
                reaction.reactants.append(reactant)
            for molecule in entry.item.products:
                product = Species(molecule=[molecule])
                product.generate_resonance_structures()
                product.thermo = thermoDatabase.getThermoData(product)
                reaction.products.append(product)

            # Generate all possible reactions involving the reactant species
            generatedReactions = self.generate_reactions_from_families([reactant.molecule for reactant in reaction.reactants], [], only_families=[family])

            # Remove from that set any reactions that don't produce the desired reactants and products
            forward = []; reverse = []
            for rxn in generatedReactions:
                if (isomorphic_species_lists(reaction.reactants, rxn.reactants)
                        and isomorphic_species_lists(reaction.products, rxn.products)):
                    forward.append(rxn)
                if (isomorphic_species_lists(reaction.reactants, rxn.products)
                        and isomorphic_species_lists(reaction.products, rxn.reactants)):
                    reverse.append(rxn)

            # We should now know whether the reaction is given in the forward or
            # reverse direction
            if len(forward) == 1 and len(reverse) == 0:
                # The reaction is in the forward direction, so use as-is
                reaction = forward[0]
                template = reaction.template
                # Don't forget to overwrite the estimated kinetics from the database with the kinetics for this entry
                reaction.kinetics = entry.data
            elif len(reverse) == 1 and len(forward) == 0:
                # The reaction is in the reverse direction
                # First fit Arrhenius kinetics in that direction
                Tdata = 1000.0 / numpy.arange(0.5, 3.301, 0.1, numpy.float64)
                kdata = numpy.zeros_like(Tdata)
                for i in range(Tdata.shape[0]):
                    kdata[i] = entry.data.getRateCoefficient(Tdata[i]) / reaction.getEquilibriumConstant(Tdata[i])
                try:
                    kunits = ('s^-1', 'm^3/(mol*s)', 'm^6/(mol^2*s)')[len(reverse[0].reactants)-1]
                except IndexError:
                    raise NotImplementedError('Cannot reverse reactions with {} products'.format(
                                              len(reverse[0].reactants)))
                kinetics = Arrhenius().fitToData(Tdata, kdata, kunits, T0=1.0)
                kinetics.Tmin = entry.data.Tmin
                kinetics.Tmax = entry.data.Tmax
                kinetics.Pmin = entry.data.Pmin
                kinetics.Pmax = entry.data.Pmax
                # Now flip the direction
                reaction = reverse[0]
                reaction.kinetics = kinetics
                template = reaction.template
            elif len(reverse) > 0 and len(forward) > 0:
                print 'FAIL: Multiple reactions found for {0!r}.'.format(entry.label)
            elif len(reverse) == 0 and len(forward) == 0:
                print 'FAIL: No reactions found for "%s".' % (entry.label)
            else:
                print 'FAIL: Unable to estimate kinetics for {0!r}.'.format(entry.label)

        assert reaction is not None
        assert template is not None
        return reaction, template
Esempio n. 33
0
    def __init__(self, smiles=[], rmg_species=None):
        """
        A class that holds information for Species object
        """

        assert isinstance(smiles, list)

        self._conformers = None

        if ((len(smiles) != 0) and rmg_species):
            # Provide both a list of smiles and an rmg_species
            assert isinstance(
                rmg_species,
                (rmgpy.molecule.Molecule,
                 rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            else:
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            smiles_list = []
            for rmg_mol in rmg_species.molecule:
                smiles_list.append(rmg_mol.toSMILES())

            for s in smiles_list:
                if s in smiles:
                    continue
                if not(s in smiles):
                    smiles.append(s)

            assert len(smiles) == len(
                smiles_list), "The list of smiles presented does not match the possible species provided"

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif (rmg_species and (len(smiles) == 0)):
            # RMG species provided, but not smiles

            assert isinstance(
                rmg_species,
                (rmgpy.molecule.Molecule,
                 rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            else:
                try:
                    rmg_species.generate_resonance_structures()
                except:
                    logging.info(
                        "Could not generate resonance structures for this species... Using molecule provided")

            smiles = []
            for rmg_mol in rmg_species.molecule:
                smiles.append(rmg_mol.toSMILES())

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif ((not rmg_species) and (len(smiles) != 0)):
            # smiles provided but not species

            species_list = []
            for smile in smiles:
                molecule = RMGMolecule(SMILES=smile)
                species_list.append(molecule.generate_resonance_structures())

            if len(smiles) != 1:
                got_one = False
                for s1 in species_list:
                    for s2 in species_list:
                        for m1 in s1:
                            for m2 in s2:
                                if m1.isIsomorphic(m2):
                                    got_one = True
                assert got_one, "SMILESs provided describe different species"

            smiles_list = []
            for mol in species_list[0]:
                smiles_list.append(mol.toSMILES())

            self.smiles = smiles_list
            self.rmg_species = species_list[0]

        else:
            self.smiles = []
            self.rmg_species = rmg_species
    def test_restart_thermo(self):
        """
        Test restarting ARC through the ARC class in main.py via the input_dict argument of the API
        Rather than through ARC.py. Check that all files are in place and the log file content.
        """
        restart_path = os.path.join(ARC_PATH, 'arc', 'testing', 'restart',
                                    '1_restart_thermo', 'restart.yml')
        input_dict = read_yaml_file(path=restart_path)
        project = 'arc_project_for_testing_delete_after_usage_restart_thermo'
        project_directory = os.path.join(ARC_PATH, 'Projects', project)
        input_dict['project'], input_dict[
            'project_directory'] = project, project_directory
        arc1 = ARC(**input_dict)
        arc1.execute()
        self.assertEqual(arc1.freq_scale_factor, 0.988)

        self.assertTrue(
            os.path.isfile(
                os.path.join(project_directory, 'output', 'thermo.info')))
        with open(os.path.join(project_directory, 'output', 'thermo.info'),
                  'r') as f:
            thermo_dft_ccsdtf12_bac = False
            for line in f.readlines():
                if 'thermo_DFT_CCSDTF12_BAC' in line:
                    thermo_dft_ccsdtf12_bac = True
                    break
        self.assertTrue(thermo_dft_ccsdtf12_bac)

        with open(
                os.path.join(
                    project_directory,
                    'arc_project_for_testing_delete_after_usage_restart_thermo.info'
                ), 'r') as f:
            sts, n2h3, oet, lot, ap = False, False, False, False, False
            for line in f.readlines():
                if 'Considered the following species and TSs:' in line:
                    sts = True
                elif 'Species N2H3' in line:
                    n2h3 = True
                elif 'Overall time since project initiation:' in line:
                    oet = True
                elif 'Levels of theory used:' in line:
                    lot = True
                elif 'ARC project arc_project_for_testing_delete_after_usage_restart_thermo' in line:
                    ap = True
        self.assertTrue(sts)
        self.assertTrue(n2h3)
        self.assertTrue(oet)
        self.assertTrue(lot)
        self.assertTrue(ap)

        with open(os.path.join(project_directory, 'arc.log'), 'r') as f:
            aei, ver, git, spc, rtm, ldb, therm, src, ter =\
                False, False, False, False, False, False, False, False, False
            for line in f.readlines():
                if 'ARC execution initiated on' in line:
                    aei = True
                elif '#   Version:' in line:
                    ver = True
                elif 'The current git HEAD for ARC is:' in line:
                    git = True
                elif 'Considering species: CH3CO2_rad' in line:
                    spc = True
                elif 'All jobs for species N2H3 successfully converged. Run time' in line:
                    rtm = True
                elif 'Loading the RMG database...' in line:
                    ldb = True
                elif 'Thermodynamics for H2O2' in line:
                    therm = True
                elif 'Sources of thermoproperties determined by RMG for the parity plots:' in line:
                    src = True
                elif 'ARC execution terminated on' in line:
                    ter = True
        self.assertTrue(aei)
        self.assertTrue(ver)
        self.assertTrue(git)
        self.assertTrue(spc)
        self.assertTrue(rtm)
        self.assertTrue(ldb)
        self.assertTrue(therm)
        self.assertTrue(src)
        self.assertTrue(ter)

        self.assertTrue(
            os.path.isfile(
                os.path.join(project_directory, 'output',
                             'thermo_parity_plots.pdf')))

        status = read_yaml_file(
            os.path.join(project_directory, 'output', 'status.yml'))
        self.assertEqual(
            status['CH3CO2_rad']['isomorphism'],
            'opt passed isomorphism check; '
            'Conformers optimized and compared at b3lyp/6-31g(d,p) empiricaldispersion=gd3bj; '
        )
        self.assertTrue(status['CH3CO2_rad']['job_types']['sp'])

        with open(
                os.path.join(project_directory, 'output', 'Species', 'H2O2',
                             'arkane', 'species_dictionary.txt'), 'r') as f:
            lines = f.readlines()
        adj_list = ''
        for line in lines:
            if 'H2O2' not in line:
                adj_list += line
            if line == '\n':
                break
        mol1 = Molecule().from_adjacency_list(adj_list)
        self.assertEqual(mol1.to_smiles(), 'OO')

        thermo_library_path = os.path.join(
            project_directory, 'output', 'RMG libraries', 'thermo',
            'arc_project_for_testing_delete_after_usage_restart_thermo.py')
        new_thermo_library_path = os.path.join(
            rmg_settings['database.directory'], 'thermo', 'libraries',
            'arc_project_for_testing_delete_after_usage_restart_thermo.py')
        # copy the generated library to RMG-database
        shutil.copyfile(thermo_library_path, new_thermo_library_path)
        db = RMGDatabase()
        db.load(
            path=rmg_settings['database.directory'],
            thermo_libraries=[
                'arc_project_for_testing_delete_after_usage_restart_thermo'
            ],
            transport_libraries=[],
            reaction_libraries=[],
            seed_mechanisms=[],
            kinetics_families='none',
            kinetics_depositories=[],
            statmech_libraries=None,
            depository=False,
            solvation=False,
            testing=True,
        )

        spc2 = Species(smiles='CC([O])=O')
        spc2.generate_resonance_structures()
        spc2.thermo = db.thermo.get_thermo_data(spc2)
        self.assertAlmostEqual(spc2.get_enthalpy(298), -212439.26998495663, 1)
        self.assertAlmostEqual(spc2.get_entropy(298), 283.3972662956835, 1)
        self.assertAlmostEqual(spc2.get_heat_capacity(1000), 118.751379824224,
                               1)
        self.assertTrue(
            'arc_project_for_testing_delete_after_usage_restart_thermo' in
            spc2.thermo.comment)

        # delete the generated library from RMG-database
        os.remove(new_thermo_library_path)
    def testaddReverseAttribute(self):
        """
        tests that the addReverseAttribute method gets the reverse degeneracy correct
        """
        from rmgpy.data.rmg import getDB
        from rmgpy.data.kinetics.family import TemplateReaction
        adjlist = ['''
        multiplicity 2
        1 H u0 p0 c0 {7,S}
        2 H u0 p0 c0 {4,S}
        3 C u1 p0 c0 {5,S} {7,S} {8,S}
        4 C u0 p0 c0 {2,S} {6,S} {7,D}
        5 H u0 p0 c0 {3,S}
        6 H u0 p0 c0 {4,S}
        7 C u0 p0 c0 {1,S} {3,S} {4,D}
        8 H u0 p0 c0 {3,S}
        ''',
          '''
        1 C u0 p0 c0 {2,S} {4,S} {5,S} {6,S}
        2 C u0 p0 c0 i13 {1,S} {3,D} {7,S}
        3 C u0 p0 c0 {2,D} {8,S} {9,S}
        4 H u0 p0 c0 {1,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}
        9 H u0 p0 c0 {3,S}
        ''',
                '''
        multiplicity 2
        1 H u0 p0 c0 {7,S}
        2 H u0 p0 c0 {4,S}
        3 C u1 p0 c0 {5,S} {7,S} {8,S}
        4 C u0 p0 c0 {2,S} {6,S} {7,D}
        5 H u0 p0 c0 {3,S}
        6 H u0 p0 c0 {4,S}
        7 C u0 p0 c0 i13 {1,S} {3,S} {4,D}
        8 H u0 p0 c0 {3,S}
        ''',
          '''
        1 C u0 p0 c0 {2,S} {4,S} {5,S} {6,S}
        2 C u0 p0 c0 {1,S} {3,D} {7,S}
        3 C u0 p0 c0 {2,D} {8,S} {9,S}
        4 H u0 p0 c0 {1,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}
        9 H u0 p0 c0 {3,S}
        '''
          ]
        family = getDB('kinetics').families['H_Abstraction']
        r1 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[0])])
        r2 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[1])])
        p1 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[2])])
        p2 = Species(molecule=[Molecule().fromAdjacencyList(adjlist[3])])
        r1.generate_resonance_structures(keep_isomorphic=True)
        p1.generate_resonance_structures(keep_isomorphic=True)

        rxn = TemplateReaction(reactants=[r1, r2], products=[p1, p2])
        
        rxn.degeneracy = family.calculateDegeneracy(rxn)
        self.assertEqual(rxn.degeneracy, 6)
        
        family.addReverseAttribute(rxn)
        
        self.assertEqual(rxn.reverse.degeneracy, 6)
Esempio n. 36
0
    def test_restart(self):
        """
        Test restarting ARC through the ARC class in main.py via the input_dict argument of the API
        Rather than through ARC.py. Check that all files are in place and tst file content.
        """
        restart_path = os.path.join(arc_path, 'arc', 'testing', 'restart(H,H2O2,N2H3,CH3CO2).yml')
        project = 'arc_project_for_testing_delete_after_usage2'
        project_directory = os.path.join(arc_path, 'Projects', project)
        arc1 = ARC(project=project, ess_settings=dict(),
                   input_dict=restart_path, project_directory=project_directory)
        arc1.execute()

        with open(os.path.join(project_directory, 'output', 'thermo.info'), 'r') as f:
            thermo_sft_ccsdtf12_bac = False
            for line in f.readlines():
                if 'thermo_DFT_CCSDTF12_BAC' in line:
                    thermo_sft_ccsdtf12_bac = True
                    break
        self.assertTrue(thermo_sft_ccsdtf12_bac)

        with open(os.path.join(project_directory, 'arc_project_for_testing_delete_after_usage2.info'), 'r') as f:
            sts, n2h3, oet, lot, ap = False, False, False, False, False
            for line in f.readlines():
                if 'Considered the following species and TSs:' in line:
                    sts = True
                elif 'Species N2H3' in line:
                    n2h3 = True
                elif 'Overall time since project initiation:' in line:
                    oet = True
                elif 'Levels of theory used:' in line:
                    lot = True
                elif 'ARC project arc_project_for_testing_delete_after_usage2' in line:
                    ap = True
        self.assertTrue(sts)
        self.assertTrue(n2h3)
        self.assertTrue(oet)
        self.assertTrue(lot)
        self.assertTrue(ap)

        with open(os.path.join(project_directory, 'arc.log'), 'r') as f:
            aei, ver, git, spc, rtm, ldb, therm, src, ter = False, False, False, False, False, False, False, False, False
            for line in f.readlines():
                if 'ARC execution initiated on' in line:
                    aei = True
                elif '#   Version:' in line:
                    ver = True
                elif 'The current git HEAD for ARC is:' in line:
                    git = True
                elif 'Considering species: CH3CO2_rad' in line:
                    spc = True
                elif 'All jobs for species N2H3 successfully converged. Run time: 1:16:03' in line:
                    rtm = True
                elif 'Loading the RMG database...' in line:
                    ldb = True
                elif 'Thermodynamics for H2O2:' in line:
                    therm = True
                elif 'Sources of thermoproperties determined by RMG for the parity plots:' in line:
                    src = True
                elif 'ARC execution terminated on' in line:
                    ter = True
        self.assertTrue(aei)
        self.assertTrue(ver)
        self.assertTrue(git)
        self.assertTrue(spc)
        self.assertTrue(rtm)
        self.assertTrue(ldb)
        self.assertTrue(therm)
        self.assertTrue(src)
        self.assertTrue(ter)

        self.assertTrue(os.path.isfile(os.path.join(project_directory, 'output', 'thermo_parity_plots.pdf')))

        with open(os.path.join(project_directory, 'output', 'Species', 'H2O2', 'species_dictionary.txt'), 'r') as f:
            lines = f.readlines()
        adj_list = str(''.join([line for line in lines if (line and 'H2O2' not in line)]))
        mol1 = Molecule().fromAdjacencyList(adj_list)
        self.assertEqual(mol1.toSMILES(), str('OO'))

        thermo_library_path = os.path.join(project_directory, 'output', 'RMG libraries', 'thermo',
                                           'arc_project_for_testing_delete_after_usage2.py')
        new_thermo_library_path = os.path.join(settings['database.directory'], 'thermo', 'libraries',
                                               'arc_project_for_testing_delete_after_usage2.py')
        # copy the generated library to RMG-database
        shutil.copyfile(thermo_library_path, new_thermo_library_path)
        db = RMGDatabase()
        db.load(
            path=settings['database.directory'],
            thermoLibraries=[str('arc_project_for_testing_delete_after_usage2')],
            transportLibraries=[],
            reactionLibraries=[],
            seedMechanisms=[],
            kineticsFamilies='none',
            kineticsDepositories=[],
            statmechLibraries=None,
            depository=False,
            solvation=False,
            testing=True,
        )

        spc2 = Species().fromSMILES(str('CC([O])=O'))
        spc2.generate_resonance_structures()
        spc2.thermo = db.thermo.getThermoData(spc2)
        self.assertAlmostEqual(spc2.getEnthalpy(298), -178003.44650359568, 1)
        self.assertAlmostEqual(spc2.getEntropy(298), 283.5983103176096, 1)
        self.assertAlmostEqual(spc2.getHeatCapacity(1000), 118.99753808225603, 1)
        self.assertTrue('arc_project_for_testing_delete_after_usage2' in spc2.thermo.comment)

        # delete the generated library from RMG-database
        os.remove(new_thermo_library_path)
Esempio n. 37
0
    def __init__(self, smiles=[], rmg_species=None):

        assert isinstance(smiles, list)

        self._conformers = None

        if ((len(smiles) != 0) and rmg_species):
            # Provide both a list of smiles and an rmg_species
            assert isinstance(rmg_species,
                              (rmgpy.molecule.Molecule, rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                rmg_species.generate_resonance_structures()

            else:
                rmg_species.generate_resonance_structures()

            smiles_list = []
            for rmg_mol in rmg_species.molecule:
                smiles_list.append(rmg_mol.toSMILES())

            for s in smiles_list:
                if s in smiles:
                    continue
                if not (s in smiles):
                    smiles.append(s)

            assert len(smiles) == len(
                smiles_list
            ), "The list of smiles presented does not match the possible species provided"

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif (rmg_species and (len(smiles) == 0)):
            # RMG species provided, but not smiles

            assert isinstance(rmg_species,
                              (rmgpy.molecule.Molecule, rmgpy.species.Species))

            if isinstance(rmg_species, rmgpy.molecule.Molecule):
                rmg_species = RMGSpecies(molecule=[rmg_species])
                rmg_species.generate_resonance_structures()

            else:
                rmg_species.generate_resonance_structures()

            smiles = []
            for rmg_mol in rmg_species.molecule:
                smiles.append(rmg_mol.toSMILES())

            self.smiles = smiles
            self.rmg_species = rmg_species

        elif ((not rmg_species) and (len(smiles) != 0)):
            # smiles provided but not species

            species_list = []
            for smile in smiles:
                molecule = RMGMolecule(SMILES=smile)
                s = RMGSpecies(molecule=[molecule])
                s.generate_resonance_structures()
                species_list.append(s)

            for s1 in species_list:
                for s2 in species_list:
                    assert s1.isIsomorphic(
                        s2), "SMILESs provided describe different species"

            self.smiles = smiles
            self.rmg_species = species_list[0]

        else:
            self.smiles = []
            self.rmg_species = rmg_species
Esempio n. 38
0
 def testResonanceIsomersGenerated(self):
     "Test that 1-penten-3-yl makes 2-penten-1-yl resonance isomer"
     spec = Species().fromSMILES('C=C[CH]CC')
     spec.generate_resonance_structures()
     self.assertEquals(len(spec.molecule), 2)
     self.assertEquals(spec.molecule[1].toSMILES(), "[CH2]C=CCC")
Esempio n. 39
0
    def getForwardReactionForFamilyEntry(self, entry, family, thermoDatabase):
        """
        For a given `entry` for a reaction of the given reaction `family` (the
        string label of the family), return the reaction with kinetics and
        degeneracy for the "forward" direction as defined by the reaction 
        family. For families that are their own reverse, the direction the
        kinetics is given in will be preserved. If the entry contains 
        functional groups for the reactants, assume that it is given in the 
        forward direction and do nothing. Returns the reaction in the direction
        consistent with the reaction family template, and the matching template.
        Note that the returned reaction will have its kinetics and degeneracy
        set appropriately.
        
        In order to reverse the reactions that are given in the reverse of the
        direction the family is defined, we need to compute the thermodynamics
        of the reactants and products. For this reason you must also pass
        the `thermoDatabase` to use to generate the thermo data.
        """
        def matchSpeciesToMolecules(species, molecules):
            if len(species) == len(molecules) == 1:
                return species[0].isIsomorphic(molecules[0])
            elif len(species) == len(molecules) == 2:
                if species[0].isIsomorphic(
                        molecules[0]) and species[1].isIsomorphic(
                            molecules[1]):
                    return True
                elif species[0].isIsomorphic(
                        molecules[1]) and species[1].isIsomorphic(
                            molecules[0]):
                    return True
            return False

        reaction = None
        template = None

        # Get the indicated reaction family
        try:
            groups = self.families[family].groups
        except KeyError:
            raise ValueError(
                'Invalid value "{0}" for family parameter.'.format(family))

        if all([(isinstance(reactant, Group)
                 or isinstance(reactant, LogicNode))
                for reactant in entry.item.reactants]):
            # The entry is a rate rule, containing functional groups only
            # By convention, these are always given in the forward direction and
            # have kinetics defined on a per-site basis
            reaction = Reaction(
                reactants=entry.item.reactants[:],
                products=[],
                specificCollider=entry.item.specificCollider,
                kinetics=entry.data,
                degeneracy=1,
            )
            template = [
                groups.entries[label] for label in entry.label.split(';')
            ]

        elif (all([
                isinstance(reactant, Molecule)
                for reactant in entry.item.reactants
        ]) and all(
            [isinstance(product, Molecule)
             for product in entry.item.products])):
            # The entry is a real reaction, containing molecules
            # These could be defined for either the forward or reverse direction
            # and could have a reaction-path degeneracy

            reaction = Reaction(reactants=[], products=[])
            for molecule in entry.item.reactants:
                reactant = Species(molecule=[molecule])
                reactant.generate_resonance_structures()
                reactant.thermo = thermoDatabase.getThermoData(reactant)
                reaction.reactants.append(reactant)
            for molecule in entry.item.products:
                product = Species(molecule=[molecule])
                product.generate_resonance_structures()
                product.thermo = thermoDatabase.getThermoData(product)
                reaction.products.append(product)

            # Generate all possible reactions involving the reactant species
            generatedReactions = self.generate_reactions_from_families(
                [reactant.molecule for reactant in reaction.reactants], [],
                only_families=[family])

            # Remove from that set any reactions that don't produce the desired reactants and products
            forward = []
            reverse = []
            for rxn in generatedReactions:
                if matchSpeciesToMolecules(
                        reaction.reactants,
                        rxn.reactants) and matchSpeciesToMolecules(
                            reaction.products, rxn.products):
                    forward.append(rxn)
                if matchSpeciesToMolecules(
                        reaction.reactants,
                        rxn.products) and matchSpeciesToMolecules(
                            reaction.products, rxn.reactants):
                    reverse.append(rxn)

            # We should now know whether the reaction is given in the forward or
            # reverse direction
            if len(forward) == 1 and len(reverse) == 0:
                # The reaction is in the forward direction, so use as-is
                reaction = forward[0]
                template = reaction.template
                # Don't forget to overwrite the estimated kinetics from the database with the kinetics for this entry
                reaction.kinetics = entry.data
            elif len(reverse) == 1 and len(forward) == 0:
                # The reaction is in the reverse direction
                # First fit Arrhenius kinetics in that direction
                Tdata = 1000.0 / numpy.arange(0.5, 3.301, 0.1, numpy.float64)
                kdata = numpy.zeros_like(Tdata)
                for i in range(Tdata.shape[0]):
                    kdata[i] = entry.data.getRateCoefficient(
                        Tdata[i]) / reaction.getEquilibriumConstant(Tdata[i])
                kunits = 'm^3/(mol*s)' if len(
                    reverse[0].reactants) == 2 else 's^-1'
                kinetics = Arrhenius().fitToData(Tdata, kdata, kunits, T0=1.0)
                kinetics.Tmin = entry.data.Tmin
                kinetics.Tmax = entry.data.Tmax
                kinetics.Pmin = entry.data.Pmin
                kinetics.Pmax = entry.data.Pmax
                # Now flip the direction
                reaction = reverse[0]
                reaction.kinetics = kinetics
                template = reaction.template
            elif len(reverse) > 0 and len(forward) > 0:
                print 'FAIL: Multiple reactions found for {0!r}.'.format(
                    entry.label)
            elif len(reverse) == 0 and len(forward) == 0:
                print 'FAIL: No reactions found for "%s".' % (entry.label)
            else:
                print 'FAIL: Unable to estimate kinetics for {0!r}.'.format(
                    entry.label)

        assert reaction is not None
        assert template is not None
        return reaction, template
Esempio n. 40
0
 def test_resonance_isomers_generated(self):
     """Test that 1-penten-3-yl makes 2-penten-1-yl resonance isomer"""
     spec = Species().from_smiles('C=C[CH]CC')
     spec.generate_resonance_structures()
     self.assertEquals(len(spec.molecule), 2)
     self.assertEquals(spec.molecule[1].to_smiles(), "[CH2]C=CCC")
Esempio n. 41
0
 def testResonanceIsomersGenerated(self):
     "Test that 1-penten-3-yl makes 2-penten-1-yl resonance isomer"
     spec = Species().fromSMILES('C=C[CH]CC')
     spec.generate_resonance_structures()
     self.assertEquals(len(spec.molecule), 2)
     self.assertEquals(spec.molecule[1].toSMILES(), "[CH2]C=CCC")