def zmatrix_coordinate_names(zrxn, zma): """ Get the Z-matrix coordinate names for the forming and breaking bonds of a reaction It is not always guaranteed that the bond keys will be present in the transition state Z-Matrix. For these cases, the name will be returned as None. :param zrxn: a Reaction object :rtype: str """ def _zma_names(zma, bnd_keys): _names = () for keys in bnd_keys: try: name = distance_coordinate_name(zma, *keys) except AssertionError: name = None _names += (name,) return _names frm_bnd_keys = ts.forming_bond_keys(zrxn.forward_ts_graph) brk_bnd_keys = ts.breaking_bond_keys(zrxn.forward_ts_graph) return (_zma_names(zma, frm_bnd_keys), _zma_names(zma, brk_bnd_keys))
def ring_forming_scission_scan_coordinate(rxn, zma): """ Obtain the scan coordinate for a ring-forming scission :param rxn: a Reaction object :returns: the name of the scan coordinate in the z-matrix :rtype: str """ brk_bnd_key, = ts.breaking_bond_keys(rxn.forward_ts_graph) scan_name = automol.zmat.distance_coordinate_name(zma, *brk_bnd_key) return scan_name
def elimination_ts_zmatrix(rxn, ts_geo): """ z-matrix for an elimination transition state geometry :param rxn: a Reaction object :param ts_geo: a transition state geometry """ rxn = rxn.copy() # 1. Get keys to linear or near-linear atoms lin_idxs = list(automol.geom.linear_atoms(ts_geo)) # 2. Add dummy atoms over the linear atoms rcts_gra = ts.reactants_graph(rxn.forward_ts_graph) geo, dummy_key_dct = automol.geom.insert_dummies_on_linear_atoms( ts_geo, lin_idxs=lin_idxs, gra=rcts_gra) # 3. Add dummy atoms to the Reaction object as well rxn = add_dummy_atoms(rxn, dummy_key_dct) # 4. Generate a z-matrix for the geometry rng_keys, = ts.forming_rings_atom_keys(rxn.forward_ts_graph) frm_bnd_key, = ts.forming_bond_keys(rxn.forward_ts_graph) # Drop one of the breaking bonds from the z-matrix by sorting the ring atom # keys to exclude it. If one of the breaking bonds intersects with the # forming bond, choose the other one. brk_bnd_keys = sorted(ts.breaking_bond_keys(rxn.forward_ts_graph), key=lambda x: len(x & frm_bnd_key)) brk_bnd_key = brk_bnd_keys[0] # Cycle the ring keys such that the atom closest to the forming bond is the # beginning of the ring and the other atom is the end if brk_bnd_key & frm_bnd_key: key1, = brk_bnd_key & frm_bnd_key key2, = brk_bnd_key - frm_bnd_key else: path = automol.graph.shortest_path_between_groups( rxn.forward_ts_graph, brk_bnd_key, frm_bnd_key) key1, = brk_bnd_key & set(path) key2, = brk_bnd_key - set(path) rng_keys = automol.graph.cycle_ring_atom_key_to_front(rng_keys, key1, end_key=key2) vma, zma_keys = automol.graph.vmat.vmatrix(rxn.forward_ts_graph, rng_keys=rng_keys) zma_geo = automol.geom.from_subset(geo, zma_keys) zma = automol.zmat.from_geometry(vma, zma_geo) return zma, zma_keys, dummy_key_dct
def hydrogen_abstraction_atom_keys(rxn): """ Obtain the atoms involved in a hydrogen abstraction, sorted in canonical order. :param rxn: the reaction object :type rxn: Reaction :returns: the attacking atom, the transferring atom, the donating atom :rtype: (int, int, int) """ frm_bnd_key, = ts.forming_bond_keys(rxn.forward_ts_graph) brk_bnd_key, = ts.breaking_bond_keys(rxn.forward_ts_graph) hyd_key, = frm_bnd_key & brk_bnd_key att_key, = frm_bnd_key - brk_bnd_key don_key, = brk_bnd_key - frm_bnd_key return att_key, hyd_key, don_key
def substitution_atom_keys(rxn): """ Obtain the atoms involved in a substitution reaction, sorted in canonical order. :param rxn: the reaction object :type rxn: Reaction :returns: the attacking atom, the transferring atom, the leaving atom :rtype: (int, int, int) """ frm_bnd_key, = ts.forming_bond_keys(rxn.forward_ts_graph) brk_bnd_key, = ts.breaking_bond_keys(rxn.forward_ts_graph) tra_key, = frm_bnd_key & brk_bnd_key att_key, = frm_bnd_key - brk_bnd_key lea_key, = brk_bnd_key - frm_bnd_key return att_key, tra_key, lea_key
def hydrogen_abstraction_is_sigma(rxn): """ Is this a sigma radical hydrogen abstraction? :param rxn: the reaction object :type rxn: Reaction :rtype: bool """ assert rxn.class_ == ReactionClass.Typ.HYDROGEN_ABSTRACTION tsg = rxn.forward_ts_graph rct_gra = automol.graph.ts.reactants_graph(tsg) sig_rad_keys = automol.graph.sigma_radical_atom_keys(rct_gra) brk_bnd_key, = ts.breaking_bond_keys(tsg) frm_bnd_key, = ts.forming_bond_keys(tsg) rad_key, = frm_bnd_key - brk_bnd_key return rad_key in sig_rad_keys
def elimination_breaking_bond_keys(rxn): """ Obtain the breaking bonds for an elimination reaction, sorted in canonical order. :param rxn: the reaction object :type rxn: Reaction :returns: the breaking bond keys :rtype: (frozenset[int], frozenset[int]) """ assert rxn.class_ == par.ReactionClass.ELIMINATION # Choose the breaking bond with the fewest neighbors, to get the terminal # atom if there is one. tsg = rxn.forward_ts_graph brk_bnd_keys = reversed(sorted(ts.breaking_bond_keys(tsg), key=sorted)) brk_bnd_keys = sorted(brk_bnd_keys, key=lambda x: automol.graph.atom_count( automol.graph.bond_neighborhood(tsg, x))) return tuple(brk_bnd_keys)
def insertion_forming_bond_keys(rxn): """ Obtain the forming bonds for an insertion reaction, sorted in canonical order. :param rxn: the reaction object :type rxn: Reaction :returns: the forming bond keys :rtype: (frozenset[int], frozenset[int]) """ assert rxn.class_ == par.ReactionClass.INSERTION brk_bnd_key, = ts.breaking_bond_keys(rxn.forward_ts_graph) # Choose the forming bond that doesn't intersect with the breaking bond, if # one of them does frm_bnd_keys = sorted(ts.forming_bond_keys(rxn.forward_ts_graph), key=sorted) frm_bnd_keys = sorted(frm_bnd_keys, key=lambda x: len(x & brk_bnd_key)) return tuple(frm_bnd_keys)
def hydrogen_migration_atom_keys(rxn): """ Obtain the atoms involved in a hydrogen migration reaction, sorted in canonical order. :param rxn: the reaction object :type rxn: Reaction :returns: the attacking atom, the transferring atom, the donating atom, and a neighbor to the attacking atom along the chain to the donating atom :rtype: (int, int, int, int) """ frm_bnd_key, = ts.forming_bond_keys(rxn.forward_ts_graph) brk_bnd_key, = ts.breaking_bond_keys(rxn.forward_ts_graph) tra_key, = frm_bnd_key & brk_bnd_key att_key, = frm_bnd_key - brk_bnd_key don_key, = brk_bnd_key - frm_bnd_key gra = ts.reactants_graph(rxn.forward_ts_graph) path = automol.graph.shortest_path_between_atoms(gra, att_key, don_key) ngb_key = automol.graph.atom_neighbor_atom_key( gra, att_key, incl_atm_keys=path) return att_key, tra_key, don_key, ngb_key
def elimination_breaking_bond_keys(rxn): """ Obtain the breaking bonds for an elimination reaction, sorted in canonical order. :param rxn: the reaction object :type rxn: Reaction :returns: the breaking bond keys :rtype: (frozenset[int], frozenset[int]) """ assert rxn.class_ == ReactionClass.Typ.ELIMINATION tsg = rxn.forward_ts_graph frm_bnd_key, = ts.forming_bond_keys(tsg) brk_bnd_keys = ts.breaking_bond_keys(tsg) brk_bnd_key1, brk_bnd_key2 = brk_bnd_keys symbs = automol.graph.atom_symbols(tsg) if len(frm_bnd_key | brk_bnd_key1 | brk_bnd_key2) > 3: # for ring_size > 3: use brk-bnd that doesn't involve atoms in frm bond scn_brk_bnd_key = None for brk_bnd_key in brk_bnd_keys: if not frm_bnd_key & brk_bnd_key: scn_brk_bnd_key = brk_bnd_key else: # if one brk bnd doesn't have H, use that, else use arbitrary brk bnd scn_brk_bnd_key = None for brk_bnd_key in brk_bnd_keys: brk_symbs = tuple(symbs[key] for key in brk_bnd_key1) if 'H' not in brk_symbs: scn_brk_bnd_key = brk_bnd_key break if scn_brk_bnd_key is None: scn_brk_bnd_key = brk_bnd_key1 brk_bnd_key1 = scn_brk_bnd_key brk_bnd_key2, = brk_bnd_keys - {brk_bnd_key1} return brk_bnd_key1, brk_bnd_key2