@@ -4442,24 +4442,29 @@ def extract_source_from_comments(self, reaction):
4442
4442
"""
4443
4443
lines = reaction .kinetics .comment .split ('\n ' )
4444
4444
4445
- exact = False
4445
+ exact_rule = False
4446
4446
template = None
4447
4447
rules = None
4448
4448
training_entries = None
4449
4449
degeneracy = 1
4450
4450
4451
- regex = r"\[(.*)\]" # only hit outermost brackets
4451
+ training_reaction_pattern = r'Matched reaction\s*(\d+).*in.*training'
4452
+ degeneracy_pattern = r'Multiplied by reaction path degeneracy\s*(\d+)'
4453
+
4452
4454
for line in lines :
4453
- if line .startswith ('Matched' ):
4455
+ training_matches = re .search (training_reaction_pattern , line )
4456
+ degeneracy_matches = re .search (degeneracy_pattern , line )
4457
+
4458
+ if training_matches is not None :
4454
4459
# Source of the kinetics is from training reaction
4455
- training_reaction_index = int (line . split ()[ 2 ] )
4460
+ training_reaction_index = int (training_matches . group ( 1 ) )
4456
4461
depository = self .get_training_depository ()
4457
4462
training_entry = depository .entries [training_reaction_index ]
4458
4463
# Perform sanity check that the training reaction's label matches that of the comments
4459
4464
if training_entry .label not in line :
4460
- raise AssertionError ('Reaction {0 } uses kinetics from training reaction {1 } '
4461
- 'but does not match the training reaction {1 } from the '
4462
- '{2 } family.'. format ( reaction , training_reaction_index , self . label ) )
4465
+ raise AssertionError (f 'Reaction { reaction } uses kinetics from training reaction { training_reaction_index } '
4466
+ f 'but does not match the training reaction { training_reaction_index } from the '
4467
+ f' { self . label } family.' )
4463
4468
4464
4469
# Sometimes the matched kinetics could be in the reverse direction.....
4465
4470
if reaction .is_isomorphic (training_entry .item , either_direction = False , save_order = self .save_order ):
@@ -4468,34 +4473,34 @@ def extract_source_from_comments(self, reaction):
4468
4473
reverse = True
4469
4474
return True , [self .label , training_entry , reverse ]
4470
4475
4471
- elif line .startswith ('Exact match' ):
4472
- exact = True
4473
- elif line .startswith ('Estimated' ):
4474
- pass
4475
- elif line .startswith ('Multiplied by' ):
4476
- degeneracy = float (line .split ()[- 1 ])
4476
+ if 'Exact match found for rate rule' in line :
4477
+ exact_rule = True
4478
+ if degeneracy_matches is not None :
4479
+ degeneracy = float (degeneracy_matches .group (1 ))
4477
4480
4478
4481
# Extract the rate rule information
4479
4482
full_comment_string = reaction .kinetics .comment .replace ('\n ' , ' ' )
4480
-
4483
+ autogen_node_search_pattern = r'Estimated from node (.*)'
4481
4484
# The rate rule string is right after the phrase 'for rate rule'
4482
- rate_rule_string = full_comment_string .split ("for rate rule" , 1 )[1 ].strip ()
4483
-
4484
- if rate_rule_string [0 ] == '[' :
4485
- # Get the contents of the capture group in the regex
4486
- # Remove any spaces which may be left over as a result of a line break
4487
- template_label = re .split (regex , rate_rule_string )[1 ].replace (' ' , '' )
4485
+ template_pattern = r"for rate rule \[(.*)\]" # only hit outermost brackets
4486
+ autogen_node_matches = re .search (autogen_node_search_pattern , full_comment_string )
4487
+ template_matches = re .search (template_pattern , full_comment_string )
4488
+ if autogen_node_matches is not None : # autogenerated trees
4489
+ template_str = autogen_node_matches .group (1 ).split ('Multiplied by reaction path degeneracy' )[0 ].strip ()
4490
+ tokens = template_str .split ()
4491
+ if len (tokens ) == 2 : # The node was probably split because wordwrap was turned off
4492
+ assert len (template_str ) > 115 , 'The node name is too short to have been broken up by the chemkin writer'
4493
+ template_str = '' .join (tokens )
4494
+ elif len (tokens ) > 2 : # warn the user the node is probably wrong
4495
+ raise ValueError (f'The node name { template_str } has multiple spaces and cannot be parsed for reaction { reaction } .' )
4496
+ template = self .retrieve_template ([template_str ])
4497
+ elif template_matches is not None : # hand-built trees
4498
+ template_label = template_matches .group (1 )
4499
+ template = self .retrieve_template (template_label .split (';' ))
4488
4500
else :
4489
- # If this has the line 'From training reaction # for rate rule node1;node2'
4490
- template_label = rate_rule_string .split ()[0 ]
4491
-
4492
- template = self .retrieve_template (template_label .split (';' ))
4501
+ raise ValueError (f'Could not find rate rule in comments for reaction { reaction } .' )
4493
4502
rules , training_entries = self .get_sources_for_template (template )
4494
-
4495
- if not template :
4496
- raise ValueError ('Could not extract kinetics source from comments for reaction {}.' .format (reaction ))
4497
-
4498
- source_dict = {'template' : template , 'degeneracy' : degeneracy , 'exact' : exact ,
4503
+ source_dict = {'template' : template , 'degeneracy' : degeneracy , 'exact' : exact_rule ,
4499
4504
'rules' : rules , 'training' : training_entries }
4500
4505
4501
4506
# Source of the kinetics is from rate rules
0 commit comments