def generateReactions(database, reactants, products=None, only_families=None, resonance=True): """ Generate the reactions (and associated kinetics) for a given set of `reactants` and an optional set of `products`. A list of reactions is returned, with a reaction for each matching kinetics entry in any part of the database. This means that the same reaction may appear multiple times with different kinetics in the output. If `only_families` is a list of strings, only those labeled families are used: no libraries and no RMG-Java kinetics are returned. """ from rmgpy.rmg.model import getFamilyLibraryObject # get RMG-py reactions reaction_list = database.kinetics.generate_reactions(reactants, products, only_families=only_families, resonance=resonance) if len(reactants) == 1: # if only one reactant, react it with itself bimolecularly, with RMG-py # the java version already does this (it includes A+A reactions when you react A) reactants2 = [reactants[0], reactants[0]] reaction_list.extend(database.kinetics.generate_reactions(reactants2, products, only_families=only_families, resonance=resonance)) # get RMG-py kinetics reaction_data_list = [] template_reactions = [] for reaction in reaction_list: # If the reaction already has kinetics (e.g. from a library), # assume the kinetics are satisfactory if reaction.kinetics is not None: reaction_data_list.append(reaction) else: # Set the reaction kinetics # Only reactions from families should be missing kinetics assert isinstance(reaction, TemplateReaction) # Determine if we've already processed an isomorphic reaction with a different template duplicate = False for t_rxn in template_reactions: if reaction.isIsomorphic(t_rxn): assert set(reaction.template) != set(t_rxn.template), 'There should not be duplicate reactions with identical templates.' duplicate = True break else: # We haven't encountered this reaction yet, so add it to the list template_reactions.append(reaction) # Get all of the kinetics for the reaction family = getFamilyLibraryObject(reaction.family) kineticsList = family.getKinetics(reaction, templateLabels=reaction.template, degeneracy=reaction.degeneracy, returnAllKinetics=True) if family.ownReverse and hasattr(reaction,'reverse'): kineticsListReverse = family.getKinetics(reaction.reverse, templateLabels=reaction.reverse.template, degeneracy=reaction.reverse.degeneracy, returnAllKinetics=True) for kinetics, source, entry, isForward in kineticsListReverse: for kinetics0, source0, entry0, isForward0 in kineticsList: if source0 is not None and source is not None and entry0 is entry and isForward != isForward0: # We already have this estimate from the forward direction, so don't duplicate it in the results break else: kineticsList.append([kinetics, source, entry, not isForward]) # We're done with the "reverse" attribute, so delete it to save a bit of memory delattr(reaction,'reverse') # Make a new reaction object for each kinetics result for kinetics, source, entry, isForward in kineticsList: if duplicate and source != 'rate rules': # We've already processed this reaction with a different template, # so we only need the new rate rule estimates continue if isForward: reactant_species = reaction.reactants[:] product_species = reaction.products[:] else: reactant_species = reaction.products[:] product_species = reaction.reactants[:] if source == 'rate rules' or source == 'group additivity': rxn = TemplateReaction( reactants = reactant_species, products = product_species, kinetics = kinetics, degeneracy = reaction.degeneracy, reversible = reaction.reversible, family = reaction.family, estimator = source, template = reaction.template, ) else: rxn = DepositoryReaction( reactants = reactant_species, products = product_species, kinetics = kinetics, degeneracy = reaction.degeneracy, reversible = reaction.reversible, depository = source, family = reaction.family, entry = entry, ) reaction_data_list.append(rxn) return reaction_data_list
def generateReactions(database, reactants, products=None, only_families=None): """ Generate the reactions (and associated kinetics) for a given set of `reactants` and an optional set of `products`. A list of reactions is returned, with a reaction for each matching kinetics entry in any part of the database. This means that the same reaction may appear multiple times with different kinetics in the output. If the RMG-Java server is running, this function will also query it for reactions and kinetics. If `only_families` is a list of strings, only those labeled families are used: no libraries and no RMG-Java kinetics are returned. """ from rmgpy.rmg.model import getFamilyLibraryObject # get RMG-py reactions reactionList = [] if only_families is None: # Not restricted to certain families, so also check libraries. reactionList.extend( database.kinetics.generateReactionsFromLibraries( reactants, products)) reactionList.extend( database.kinetics.generateReactionsFromFamilies( reactants, products, only_families=only_families)) if len(reactants) == 1: # if only one reactant, react it with itself bimolecularly, with RMG-py # the java version already does this (it includes A+A reactions when you react A) reactants2 = [reactants[0], reactants[0]] if only_families is None: # Not restricted to certain families, so also check libraries. reactionList.extend( database.kinetics.generateReactionsFromLibraries( reactants2, products)) reactionList.extend( database.kinetics.generateReactionsFromFamilies( reactants2, products, only_families=only_families)) # get RMG-py kinetics reactionList0 = reactionList reactionList = [] for reaction in reactionList0: # If the reaction already has kinetics (e.g. from a library), # assume the kinetics are satisfactory if reaction.kinetics is not None: reactionList.append(reaction) else: # Set the reaction kinetics # Only reactions from families should be missing kinetics assert isinstance(reaction, TemplateReaction) # Get all of the kinetics for the reaction family = getFamilyLibraryObject(reaction.family) kineticsList = family.getKinetics(reaction, templateLabels=reaction.template, degeneracy=reaction.degeneracy, returnAllKinetics=True) if family.ownReverse and hasattr(reaction, 'reverse'): kineticsListReverse = family.getKinetics( reaction.reverse, templateLabels=reaction.reverse.template, degeneracy=reaction.reverse.degeneracy, returnAllKinetics=True) for kinetics, source, entry, isForward in kineticsListReverse: for kinetics0, source0, entry0, isForward0 in kineticsList: if source0 is not None and source is not None and entry0 is entry and isForward != isForward0: # We already have this estimate from the forward direction, so don't duplicate it in the results break else: kineticsList.append( [kinetics, source, entry, not isForward]) # We're done with the "reverse" attribute, so delete it to save a bit of memory delattr(reaction, 'reverse') # Make a new reaction object for each kinetics result for kinetics, source, entry, isForward in kineticsList: if isForward: reactant_species = reaction.reactants[:] product_species = reaction.products[:] else: reactant_species = reaction.products[:] product_species = reaction.reactants[:] if source == 'rate rules' or source == 'group additivity': rxn = TemplateReaction( reactants=reactant_species, products=product_species, kinetics=kinetics, degeneracy=reaction.degeneracy, reversible=reaction.reversible, family=reaction.family, estimator=source, ) else: rxn = DepositoryReaction( reactants=reactant_species, products=product_species, kinetics=kinetics, degeneracy=reaction.degeneracy, reversible=reaction.reversible, depository=source, family=reaction.family, entry=entry, ) reactionList.append(rxn) # get RMG-java reactions if only_families is None: # Not restricted to certain families, so also check RMG-Java. rmgJavaReactionList = getRMGJavaKinetics(reactants, products) else: rmgJavaReactionList = [] for rxn in itertools.chain(reactionList, rmgJavaReactionList): rxn.reactants = [ Species(molecule=[mol]) if isinstance(mol, Molecule) else mol for mol in rxn.reactants ] rxn.products = [ Species(molecule=[mol]) if isinstance(mol, Molecule) else mol for mol in rxn.products ] return reactionList, rmgJavaReactionList
def generateReactions(database, reactants, products=None, only_families=None): """ Generate the reactions (and associated kinetics) for a given set of `reactants` and an optional set of `products`. A list of reactions is returned, with a reaction for each matching kinetics entry in any part of the database. This means that the same reaction may appear multiple times with different kinetics in the output. If the RMG-Java server is running, this function will also query it for reactions and kinetics. If `only_families` is a list of strings, only those labeled families are used: no libraries and no RMG-Java kinetics are returned. """ from rmgpy.rmg.model import getFamilyLibraryObject # get RMG-py reactions reactionList = [] if only_families is None: # Not restricted to certain families, so also check libraries. reactionList.extend(database.kinetics.generateReactionsFromLibraries(reactants, products)) reactionList.extend(database.kinetics.generateReactionsFromFamilies(reactants, products, only_families=only_families)) if len(reactants) == 1: # if only one reactant, react it with itself bimolecularly, with RMG-py # the java version already does this (it includes A+A reactions when you react A) reactants2 = [reactants[0], reactants[0]] if only_families is None: # Not restricted to certain families, so also check libraries. reactionList.extend(database.kinetics.generateReactionsFromLibraries(reactants2, products)) reactionList.extend(database.kinetics.generateReactionsFromFamilies(reactants2, products, only_families=only_families)) # get RMG-py kinetics reactionList0 = reactionList; reactionList = [] for reaction in reactionList0: # If the reaction already has kinetics (e.g. from a library), # assume the kinetics are satisfactory if reaction.kinetics is not None: reactionList.append(reaction) else: # Set the reaction kinetics # Only reactions from families should be missing kinetics assert isinstance(reaction, TemplateReaction) # Get all of the kinetics for the reaction family = getFamilyLibraryObject(reaction.family) kineticsList = family.getKinetics(reaction, template=reaction.template, degeneracy=reaction.degeneracy, returnAllKinetics=True) if family.ownReverse and hasattr(reaction,'reverse'): kineticsListReverse = family.getKinetics(reaction.reverse, template=reaction.reverse.template, degeneracy=reaction.reverse.degeneracy, returnAllKinetics=True) for kinetics, source, entry, isForward in kineticsListReverse: for kinetics0, source0, entry0, isForward0 in kineticsList: if source0 is not None and source is not None and entry0 is entry and isForward != isForward0: # We already have this estimate from the forward direction, so don't duplicate it in the results break else: kineticsList.append([kinetics, source, entry, not isForward]) # We're done with the "reverse" attribute, so delete it to save a bit of memory delattr(reaction,'reverse') # Make a new reaction object for each kinetics result for kinetics, source, entry, isForward in kineticsList: if isForward: reactant_species = reaction.reactants[:] product_species = reaction.products[:] else: reactant_species = reaction.products[:] product_species = reaction.reactants[:] if source == 'rate rules' or source == 'group additivity': rxn = TemplateReaction( reactants = reactant_species, products = product_species, kinetics = kinetics, degeneracy = reaction.degeneracy, reversible = reaction.reversible, family = reaction.family, estimator = source, ) else: rxn = DepositoryReaction( reactants = reactant_species, products = product_species, kinetics = kinetics, degeneracy = reaction.degeneracy, reversible = reaction.reversible, depository = source, family = reaction.family, entry = entry, ) reactionList.append(rxn) # get RMG-java reactions if only_families is None: # Not restricted to certain families, so also check RMG-Java. rmgJavaReactionList = getRMGJavaKinetics(reactants, products) else: rmgJavaReactionList = [] return reactionList, rmgJavaReactionList
def generateReactions(database, reactants, products=None, only_families=None, resonance=True): """ Generate the reactions (and associated kinetics) for a given set of `reactants` and an optional set of `products`. A list of reactions is returned, with a reaction for each matching kinetics entry in any part of the database. This means that the same reaction may appear multiple times with different kinetics in the output. If `only_families` is a list of strings, only those labeled families are used: no libraries and no RMG-Java kinetics are returned. """ from rmgpy.rmg.model import getFamilyLibraryObject # get RMG-py reactions reaction_list = database.kinetics.generate_reactions( reactants, products, only_families=only_families, resonance=resonance) if len(reactants) == 1: # if only one reactant, react it with itself bimolecularly, with RMG-py # the java version already does this (it includes A+A reactions when you react A) reactants2 = [reactants[0], reactants[0]] reaction_list.extend( database.kinetics.generate_reactions(reactants2, products, only_families=only_families, resonance=resonance)) # get RMG-py kinetics reaction_data_list = [] template_reactions = [] for reaction in reaction_list: # If the reaction already has kinetics (e.g. from a library), # assume the kinetics are satisfactory if reaction.kinetics is not None: reaction_data_list.append(reaction) else: # Set the reaction kinetics # Only reactions from families should be missing kinetics assert isinstance(reaction, TemplateReaction) # Determine if we've already processed an isomorphic reaction with a different template duplicate = False for t_rxn in template_reactions: if reaction.isIsomorphic(t_rxn): assert set(reaction.template) != set( t_rxn.template ), 'There should not be duplicate reactions with identical templates.' duplicate = True break else: # We haven't encountered this reaction yet, so add it to the list template_reactions.append(reaction) # Get all of the kinetics for the reaction family = getFamilyLibraryObject(reaction.family) kineticsList = family.getKinetics(reaction, templateLabels=reaction.template, degeneracy=reaction.degeneracy, returnAllKinetics=True) if family.ownReverse and hasattr(reaction, 'reverse'): kineticsListReverse = family.getKinetics( reaction.reverse, templateLabels=reaction.reverse.template, degeneracy=reaction.reverse.degeneracy, returnAllKinetics=True) for kinetics, source, entry, isForward in kineticsListReverse: for kinetics0, source0, entry0, isForward0 in kineticsList: if source0 is not None and source is not None and entry0 is entry and isForward != isForward0: # We already have this estimate from the forward direction, so don't duplicate it in the results break else: kineticsList.append( [kinetics, source, entry, not isForward]) # We're done with the "reverse" attribute, so delete it to save a bit of memory delattr(reaction, 'reverse') # Make a new reaction object for each kinetics result for kinetics, source, entry, isForward in kineticsList: if duplicate and source != 'rate rules': # We've already processed this reaction with a different template, # so we only need the new rate rule estimates continue if isForward: reactant_species = reaction.reactants[:] product_species = reaction.products[:] else: reactant_species = reaction.products[:] product_species = reaction.reactants[:] if source == 'rate rules' or source == 'group additivity': rxn = TemplateReaction( reactants=reactant_species, products=product_species, kinetics=kinetics, degeneracy=reaction.degeneracy, reversible=reaction.reversible, family=reaction.family, estimator=source, template=reaction.template, ) else: rxn = DepositoryReaction( reactants=reactant_species, products=product_species, kinetics=kinetics, degeneracy=reaction.degeneracy, reversible=reaction.reversible, depository=source, family=reaction.family, entry=entry, ) reaction_data_list.append(rxn) return reaction_data_list
def pathwayGenerator(reactants, products, rmg, only_families): genRxn = database.kinetics.generateReactionsFromFamilies # LOOP starts newReactions = [] rxt_mol_mutation_num = 1 pdt_mol_mutation_num = 1 for reactant in reactants: rxt_mol_mutation_num *= len(reactant.molecule) for product in products: pdt_mol_mutation_num *= len(product.molecule) for mutation_i in range(rxt_mol_mutation_num): rxts_mol = [spc.molecule[mutation_i%(len(spc.molecule))] for spc in reactants] for mutation_j in range(pdt_mol_mutation_num): pdts_mol = [spc.molecule[mutation_j%(len(spc.molecule))] for spc in products] newReactions.extend(genRxn(reactants=rxts_mol,\ products=pdts_mol, only_families=only_families)) rmg.reactionModel.newSpeciesList = [] rmg.reactionModel.newReactionList = [] rmg.reactionModel.processNewReactions(newReactions, reactants) # gen thermo and transport for new species for spec in rmg.reactionModel.newSpeciesList: if not spec.hasThermo(): spec.generateThermoData(database) spec.generateTransportData(database) for reaction in rmg.reactionModel.newReactionList: family = getFamilyLibraryObject(reaction.family) # If the reaction already has kinetics (e.g. from a library), # assume the kinetics are satisfactory if reaction.kinetics is None: # Set the reaction kinetics kinetics, source, entry, isForward = rmg.reactionModel.generateKinetics(reaction) reaction.kinetics = kinetics # Flip the reaction direction if the kinetics are defined in the reverse direction if not isForward: reaction.reactants, reaction.products = reaction.products, reaction.reactants reaction.pairs = [(p,r) for r,p in reaction.pairs] if family.ownReverse and hasattr(reaction,'reverse'): if not isForward: reaction.template = reaction.reverse.template # We're done with the "reverse" attribute, so delete it to save a bit of memory delattr(reaction,'reverse') # For new reactions, convert ArrheniusEP to Arrhenius, and fix barrier heights. # self.newReactionList only contains *actually* new reactions, all in the forward direction. for reaction in rmg.reactionModel.newReactionList: # convert KineticsData to Arrhenius forms if isinstance(reaction.kinetics, KineticsData): reaction.kinetics = reaction.kinetics.toArrhenius() # correct barrier heights of estimated kinetics if isinstance(reaction,TemplateReaction) or isinstance(reaction,DepositoryReaction): # i.e. not LibraryReaction reaction.fixBarrierHeight() # also converts ArrheniusEP to Arrhenius. if rmg.reactionModel.pressureDependence and reaction.isUnimolecular(): # If this is going to be run through pressure dependence code, # we need to make sure the barrier is positive. reaction.fixBarrierHeight(forcePositive=True)