@@ -1078,7 +1078,7 @@ def applyRecipe(self, reactantStructures, forward=True, unique=True):
10781078 # Return the product structures
10791079 return productStructures
10801080
1081- def __generateProductStructures (self , reactantStructures , maps , forward , ** options ):
1081+ def __generateProductStructures (self , reactantStructures , maps , forward , failsSpeciesConstraints = None ):
10821082 """
10831083 For a given set of `reactantStructures` and a given set of `maps`,
10841084 generate and return the corresponding product structures. The
@@ -1087,6 +1087,8 @@ def __generateProductStructures(self, reactantStructures, maps, forward, **optio
10871087 parameter is a list of mappings of the top-level tree node of each
10881088 *template* reactant to the corresponding *structure*. This function
10891089 returns a list of the product structures.
1090+ `failsSpeciesConstraints` is a function that accepts a :class:`Molecule`
1091+ structure and returns `True` if it is forbidden.
10901092 """
10911093
10921094 productStructuresList = []
@@ -1125,41 +1127,11 @@ def __generateProductStructures(self, reactantStructures, maps, forward, **optio
11251127 productStructures .reverse ()
11261128
11271129 # Apply the generated species constraints (if given)
1128- if options :
1129- explicitlyAllowedMolecules = options .get ('explicitlyAllowedMolecules' )
1130- maxCarbonAtoms = options .get ('maximumCarbonAtoms' , 1000000 )
1131- maxHydrogenAtoms = options .get ('maximumHydrogenAtoms' , 1000000 )
1132- maxOxygenAtoms = options .get ('maximumOxygenAtoms' , 1000000 )
1133- maxNitrogenAtoms = options .get ('maximumNitrogenAtoms' , 1000000 )
1134- maxSiliconAtoms = options .get ('maximumSiliconAtoms' , 1000000 )
1135- maxSulfurAtoms = options .get ('maximumSulfurAtoms' , 1000000 )
1136- maxHeavyAtoms = options .get ('maximumHeavyAtoms' , 1000000 )
1137- maxRadicals = options .get ('maximumRadicalElectrons' , 1000000 )
1130+ if failsSpeciesConstraints :
11381131 for struct in productStructures :
1139- allowed = False
1140- for molecule in explicitlyAllowedMolecules :
1141- if struct .isIsomorphic (molecule ):
1142- allowed = True
1143- break
1144- if allowed :
1145- continue
1146- H = struct .getNumAtoms ('H' )
1147- if struct .getNumAtoms ('C' ) > maxCarbonAtoms :
1148- raise ForbiddenStructureException ()
1149- if H > maxHydrogenAtoms :
1150- raise ForbiddenStructureException ()
1151- if struct .getNumAtoms ('O' ) > maxOxygenAtoms :
1152- raise ForbiddenStructureException ()
1153- if struct .getNumAtoms ('N' ) > maxNitrogenAtoms :
1154- raise ForbiddenStructureException ()
1155- if struct .getNumAtoms ('Si' ) > maxSiliconAtoms :
1156- raise ForbiddenStructureException ()
1157- if struct .getNumAtoms ('S' ) > maxSulfurAtoms :
1158- raise ForbiddenStructureException ()
1159- if len (struct .atoms ) - H > maxHeavyAtoms :
1160- raise ForbiddenStructureException ()
1161- if (struct .getNumberOfRadicalElectrons () > maxRadicals ) and (len (struct .atoms ) - H > 1 ):
1162- raise ForbiddenStructureException ()
1132+ if failsSpeciesConstraints (struct ):
1133+ raise ForbiddenStructureException ()
1134+
11631135
11641136 # Generate other possible electronic states
11651137 electronicStructuresList1 = []
@@ -1397,7 +1369,7 @@ def __matchReactantToTemplate(self, reactant, templateReactant):
13971369 elif isinstance (struct , Group ):
13981370 return reactant .findSubgraphIsomorphisms (struct )
13991371
1400- def generateReactions (self , reactants , ** options ):
1372+ def generateReactions (self , reactants , failsSpeciesConstraints = None ):
14011373 """
14021374 Generate all reactions between the provided list of one or two
14031375 `reactants`, which should be either single :class:`Molecule` objects
@@ -1410,12 +1382,12 @@ def generateReactions(self, reactants, **options):
14101382 reactionList = []
14111383
14121384 # Forward direction (the direction in which kinetics is defined)
1413- reactionList .extend (self .__generateReactions (reactants , forward = True , ** options ))
1385+ reactionList .extend (self .__generateReactions (reactants , forward = True , failsSpeciesConstraints = failsSpeciesConstraints ))
14141386
14151387 if self .ownReverse :
14161388 # for each reaction, make its reverse reaction and store in a 'reverse' attribute
14171389 for rxn in reactionList :
1418- reactions = self .__generateReactions (rxn .products , products = rxn .reactants , forward = True , ** options )
1390+ reactions = self .__generateReactions (rxn .products , products = rxn .reactants , forward = True , failsSpeciesConstraints = failsSpeciesConstraints )
14191391 if len (reactions ) != 1 :
14201392 logging .error ("Expecting one matching reverse reaction, not {0} in reaction family {1} for forward reaction {2}.\n " .format (len (reactions ), self .label , str (rxn )))
14211393 for reactant in rxn .reactants :
@@ -1429,7 +1401,7 @@ def generateReactions(self, reactants, **options):
14291401
14301402 else : # family is not ownReverse
14311403 # Reverse direction (the direction in which kinetics is not defined)
1432- reactionList .extend (self .__generateReactions (reactants , forward = False , ** options ))
1404+ reactionList .extend (self .__generateReactions (reactants , forward = False , failsSpeciesConstraints = failsSpeciesConstraints ))
14331405
14341406 # Return the reactions as containing Species objects, not Molecule objects
14351407 for reaction in reactionList :
@@ -1458,14 +1430,16 @@ def calculateDegeneracy(self, reaction):
14581430 raise Exception ('Unable to calculate degeneracy for reaction {0} in reaction family {1}.' .format (reaction , self .label ))
14591431 return reactions [0 ].degeneracy
14601432
1461- def __generateReactions (self , reactants , products = None , forward = True , ** options ):
1433+ def __generateReactions (self , reactants , products = None , forward = True , failsSpeciesConstraints = None ):
14621434 """
14631435 Generate a list of all of the possible reactions of this family between
14641436 the list of `reactants`. The number of reactants provided must match
14651437 the number of reactants expected by the template, or this function
14661438 will return an empty list. Each item in the list of reactants should
14671439 be a list of :class:`Molecule` objects, each representing a resonance
14681440 isomer of the species of interest.
1441+ `failsSpeciesConstraints` is an optional function that accepts a :class:`Molecule`
1442+ structure and returns `True` if it is forbidden.
14691443 """
14701444
14711445 rxnList = []; speciesList = []
@@ -1501,7 +1475,7 @@ def __generateReactions(self, reactants, products=None, forward=True, **options)
15011475 for map in mappings :
15021476 reactantStructures = [molecule ]
15031477 try :
1504- productStructuresList = self .__generateProductStructures (reactantStructures , [map ], forward , ** options )
1478+ productStructuresList = self .__generateProductStructures (reactantStructures , [map ], forward , failsSpeciesConstraints = failsSpeciesConstraints )
15051479 except ForbiddenStructureException :
15061480 pass
15071481 else :
@@ -1529,7 +1503,7 @@ def __generateReactions(self, reactants, products=None, forward=True, **options)
15291503 for mapB in mappingsB :
15301504 reactantStructures = [moleculeA , moleculeB ]
15311505 try :
1532- productStructuresList = self .__generateProductStructures (reactantStructures , [mapA , mapB ], forward , ** options )
1506+ productStructuresList = self .__generateProductStructures (reactantStructures , [mapA , mapB ], forward , failsSpeciesConstraints = failsSpeciesConstraints )
15331507 except ForbiddenStructureException :
15341508 pass
15351509 else :
@@ -1550,7 +1524,7 @@ def __generateReactions(self, reactants, products=None, forward=True, **options)
15501524 for mapB in mappingsB :
15511525 reactantStructures = [moleculeA , moleculeB ]
15521526 try :
1553- productStructuresList = self .__generateProductStructures (reactantStructures , [mapA , mapB ], forward , ** options )
1527+ productStructuresList = self .__generateProductStructures (reactantStructures , [mapA , mapB ], forward , failsSpeciesConstraints = failsSpeciesConstraints )
15541528 except ForbiddenStructureException :
15551529 pass
15561530 else :
0 commit comments