def set_label_reactants_products(self): """A helper function for settings the label, reactants, and products attributes for a Reaction""" # first make sure that reactants and products labels are defines (most often used) if self.reactants is None or self.products is None: if self.label: if self.arrow not in self.label: raise ReactionError('A reaction label must contain an arrow ("{0}")'.format(self.arrow)) reactants, products = self.label.split(self.arrow) if self.plus in reactants: self.reactants = reactants.split(self.plus) else: self.reactants = [reactants] if self.plus in products: self.products = products.split(self.plus) else: self.products = [products] elif self.rmg_reaction is not None: self.reactants = [r.label for r in self.rmg_reaction.reactants] self.products = [p.label for p in self.rmg_reaction.products] if not self.label: if self.reactants is not None and self.products is not None: self.label = self.arrow.join([self.plus.join(r for r in self.reactants), self.plus.join(p for p in self.products)]) elif self.r_species is not None and self.p_species is not None: self.label = self.arrow.join([self.plus.join(r.label for r in self.r_species), self.plus.join(p.label for p in self.p_species)]) elif self.rmg_reaction is not None: # this will probably never be executed, but OK to keep self.label = self.arrow.join([self.plus.join(r.label for r in self.rmg_reaction.reactants), self.plus.join(p.label for p in self.rmg_reaction.products)]) if self.rmg_reaction is None: self.rmg_reaction_from_arc_species() elif not self.label and (self.reactants is None or self.products is None): raise ReactionError('Either a label or reactants and products lists must be specified')
def determine_rxn_multiplicity(self): """A helper function for determining the surface multiplicity""" if self.multiplicity is None: ordered_multiplicity_list = list() if len(self.r_species): if len(self.r_species) == 1: self.multiplicity = self.r_species[0].multiplicity elif len(self.r_species) == 2: ordered_multiplicity_list = sorted([self.r_species[0].multiplicity, self.r_species[1].multiplicity]) elif len(self.r_species) == 3: ordered_multiplicity_list = sorted([self.r_species[0].multiplicity, self.r_species[1].multiplicity, self.r_species[2].multiplicity]) elif self.rmg_reaction is not None: if len(self.rmg_reaction.reactants) == 1: self.multiplicity = self.rmg_reaction.reactants[0].molecule[0].multiplicity elif len(self.rmg_reaction.reactants) == 2: ordered_multiplicity_list = sorted([self.rmg_reaction.reactants[0].molecule[0].multiplicity, self.rmg_reaction.reactants[1].molecule[0].multiplicity]) elif len(self.rmg_reaction.reactants) == 3: ordered_multiplicity_list = sorted([self.rmg_reaction.reactants[0].molecule[0].multiplicity, self.rmg_reaction.reactants[1].molecule[0].multiplicity, self.rmg_reaction.reactants[2].molecule[0].multiplicity]) if self.multiplicity is None: if ordered_multiplicity_list == [1, 1]: self.multiplicity = 1 # S + S = D elif ordered_multiplicity_list == [1, 2]: self.multiplicity = 2 # S + D = D elif ordered_multiplicity_list == [2, 2]: self.multiplicity = 1 # D + D = S or T logging.warn('ASSUMING a multiplicity of 1 (singlet) for reaction {0}'.format(self.label)) elif ordered_multiplicity_list == [1, 3]: self.multiplicity = 3 # S + T = T elif ordered_multiplicity_list == [2, 3]: self.multiplicity = 2 # D + T = D or Q logging.warn('ASSUMING a multiplicity of 2 (doublet) for reaction {0}'.format(self.label)) elif ordered_multiplicity_list == [3, 3]: self.multiplicity = 3 # T + T = S or T or quintet logging.warn('ASSUMING a multiplicity of 3 (triplet) for reaction {0}'.format(self.label)) elif ordered_multiplicity_list == [1, 1, 1]: self.multiplicity = 1 # S + S + S = S elif ordered_multiplicity_list == [1, 1, 2]: self.multiplicity = 2 # S + S + D = D elif ordered_multiplicity_list == [1, 1, 3]: self.multiplicity = 3 # S + S + T = T elif ordered_multiplicity_list == [1, 2, 2]: self.multiplicity = 1 # S + D + D = S or T logging.warn('ASSUMING a multiplicity of 1 (singlet) for reaction {0}'.format(self.label)) elif ordered_multiplicity_list == [2, 2, 2]: self.multiplicity = 2 # D + D + D = D or T or Q logging.warn('ASSUMING a multiplicity of 2 (doublet) for reaction {0}'.format(self.label)) elif ordered_multiplicity_list == [1, 2, 3]: self.multiplicity = 2 # S + D + T = D or T logging.warn('ASSUMING a multiplicity of 2 (doublet) for reaction {0}'.format(self.label)) else: raise ReactionError('Could not determine multiplicity for reaction {0}, please input it.'.format( self.multiplicity)) logging.info('Setting multiplicity of reaction {0} to {1}'.format(self.label, self.multiplicity))
def __init__(self, label='', reactants=None, products=None, ts_label=None, rmg_reaction=None, ts_methods=None, ts_xyz_guess=None, multiplicity=None, charge=0, reaction_dict=None): self.arrow = ' <=> ' self.plus = ' + ' self.r_species = list() self.p_species = list() self.kinetics = None self.rmg_kinetics = None self.long_kinetic_description = '' self.family = None self.family_own_reverse = 0 self.ts_label = ts_label self.dh_rxn298 = None self.rmg_reactions = None if reaction_dict is not None: # Reading from a dictionary self.from_dict(reaction_dict=reaction_dict) else: # Not reading from a dictionary self.label = label self.index = None self.ts_species = None self.multiplicity = multiplicity self.charge = charge if self.multiplicity is not None and not isinstance( self.multiplicity, int): raise InputError( 'Reaction multiplicity must be an integer, got {0} of type {1}.' .format(self.multiplicity, type(self.multiplicity))) self.reactants = reactants self.products = products self.rmg_reaction = rmg_reaction if self.rmg_reaction is None and ( self.reactants is None or self.products is None) and not self.label: raise InputError( 'Cannot determine reactants and/or products labels for reaction {0}' .format(self.label)) self.set_label_reactants_products() self.ts_methods = ts_methods if ts_methods is not None else default_ts_methods self.ts_methods = [tsm.lower() for tsm in self.ts_methods] self.ts_xyz_guess = ts_xyz_guess if ts_xyz_guess is not None else list( ) if len(self.reactants) > 3 or len(self.products) > 3: raise ReactionError( 'An ARC Reaction can have up to three reactants / products. got {0} reactants' ' and {1} products for reaction {2}.'.format( len(self.reactants), len(self.products), self.label))
def check_attributes(self): """Check that the Reaction object is defined correctly""" self.set_label_reactants_products() if not self.label: raise ReactionError('A reaction seems to not be defined correctly') if self.arrow not in self.label: raise ReactionError( 'A reaction label must include a double ended arrow with spaces on both' ' sides: "{0}". Got:{1}'.format(self.arrow, self.label)) if '+' in self.label and self.plus not in self.label: raise ReactionError( 'Reactants or products in a reaction label must separated with {0} (has spaces on both' ' sides). Got:{1}'.format(self.plus, self.label)) species_labels = self.label.split(self.arrow) reactants = species_labels[0].split(self.plus) products = species_labels[1].split(self.plus) if self.reactants is not None: for reactant in reactants: if reactant not in self.reactants: raise ReactionError( 'Reactant {0} from the reaction label {1} not in self.reactants ({2})' .format(reactant, self.label, self.reactants)) for reactant in self.reactants: if reactant not in reactants: raise ReactionError( 'Reactant {0} not in the reaction label ({1})'.format( reactant, self.label)) if self.products is not None: for product in products: if product not in self.products: raise ReactionError( 'Product {0} from the reaction label {1} not in self.products ({2})' .format(product, self.label, self.products)) for product in self.products: if product not in products: raise ReactionError( 'Product {0} not in the reaction label ({1})'.format( product, self.label)) if self.r_species is not None: for reactant in self.r_species: if reactant.label not in self.reactants: raise ReactionError( 'Reactant {0} from not in self.reactants ({1})'.format( reactant.label, self.reactants)) for reactant in reactants: if reactant not in [r.label for r in self.r_species]: raise ReactionError( 'Reactant {0} from the reaction label {1} not in self.r_species ({2})' .format(reactant, self.label, [r.label for r in self.r_species])) for reactant in self.reactants: if reactant not in [r.label for r in self.r_species]: raise ReactionError( 'Reactant {0} not in n self.r_species ({1})'.format( reactant, [r.label for r in self.r_species])) if self.p_species is not None: for product in self.p_species: if product.label not in self.products: raise ReactionError( 'Product {0} from not in self.products ({1})'.format( product.label, self.reactants)) for product in products: if product not in [p.label for p in self.p_species]: raise ReactionError( 'Product {0} from the reaction label {1} not in self.p_species ({2})' .format(product, self.label, [p.label for p in self.p_species])) for product in self.products: if product not in [p.label for p in self.p_species]: raise ReactionError( 'Product {0} not in n self.p_species ({1})'.format( product, [p.label for p in self.p_species]))