def addition(xgr1, xgr2): """ find an addition transformation """ assert xgr1 == _explicit(xgr1) and xgr2 == _explicit(xgr2) tra = None xgrs1 = _connected_components(xgr1) xgrs2 = _connected_components(xgr2) if len(xgrs1) == 2 and len(xgrs2) == 1: x_xgr, y_xgr = xgrs1 xgr2, = xgrs2 x_atm_keys = _unsaturated_atom_keys(x_xgr) y_atm_keys = _unsaturated_atom_keys(y_xgr) # xgeo = geometry(xgr2) for x_atm_key, y_atm_key in itertools.product(x_atm_keys, y_atm_keys): xy_xgr = add_bonds(_union(x_xgr, y_xgr), [{x_atm_key, y_atm_key}]) # xgeo = geometry(xy_xgr) atm_key_dct = _full_isomorphism(xy_xgr, xgr2) if atm_key_dct: tra = from_data('addition', frm_bnd_keys=[{x_atm_key, y_atm_key}], brk_bnd_keys=[]) return tra
def proton_migration(xgr1, xgr2): """ find a proton migration transformation """ assert xgr1 == _explicit(xgr1) and xgr2 == _explicit(xgr2) tras = [] xgrs1 = _connected_components(xgr1) xgrs2 = _connected_components(xgr2) h_atm_key1 = max(_atom_keys(xgr1)) + 1 h_atm_key2 = max(_atom_keys(xgr2)) + 1 if len(xgrs1) == 1 and len(xgrs2) == 1: xgr1, = xgrs1 xgr2, = xgrs2 atm_keys1 = _unsaturated_atom_keys(xgr1) atm_keys2 = _unsaturated_atom_keys(xgr2) for atm_key1, atm_key2 in itertools.product(atm_keys1, atm_keys2): xgr1_h = _add_atom_explicit_hydrogen_keys(xgr1, {atm_key1: [h_atm_key1]}) xgr2_h = _add_atom_explicit_hydrogen_keys(xgr2, {atm_key2: [h_atm_key2]}) inv_atm_key_dct = _full_isomorphism(xgr2_h, xgr1_h) if inv_atm_key_dct: tras.append( from_data( frm_bnd_keys=[{atm_key1, inv_atm_key_dct[h_atm_key2]}], brk_bnd_keys=[{ inv_atm_key_dct[atm_key2], inv_atm_key_dct[h_atm_key2] }])) if len(tras) < 1: tras = None return tras
def is_stereo_compatible(tra, sgr1, sgr2): """ is this transformation compatible with the reactant/product stereo assignments? """ cgr1 = without_stereo_parities(sgr1) cgr2 = without_stereo_parities(sgr2) atm_key_dct = _full_isomorphism(apply(tra, cgr1), cgr2) # determine the stereo centers which are preserved in the transformation sgr1 = _relabel(sgr1, atm_key_dct) atm_keys = sorted(atom_stereo_keys(sgr1) & atom_stereo_keys(sgr2)) bnd_keys = sorted(bond_stereo_keys(sgr1) & bond_stereo_keys(sgr2)) atm_pars1 = dict_.values_by_key(atom_stereo_parities(sgr1), atm_keys) atm_pars2 = dict_.values_by_key(atom_stereo_parities(sgr2), atm_keys) bnd_pars1 = dict_.values_by_key(bond_stereo_parities(sgr1), bnd_keys) bnd_pars2 = dict_.values_by_key(bond_stereo_parities(sgr2), bnd_keys) atm_ngb_keys_dct1 = atom_neighbor_keys(sgr1) atm_ngb_keys_dct2 = atom_neighbor_keys(sgr2) ret = True for atm_key, par1, par2 in zip(atm_keys, atm_pars1, atm_pars2): atm_ngb_keys1 = stereo_sorted_atom_neighbor_keys( sgr1, atm_key, atm_ngb_keys_dct1[atm_key]) atm_ngb_keys2 = stereo_sorted_atom_neighbor_keys( sgr2, atm_key, atm_ngb_keys_dct2[atm_key]) if _permutation_parity(atm_ngb_keys1, atm_ngb_keys2): ret &= (par1 == par2) else: ret &= (par1 != par2) for bnd_key, par1, par2 in zip(bnd_keys, bnd_pars1, bnd_pars2): atm1_key, atm2_key = bnd_key atm1_ngb_key1 = stereo_sorted_atom_neighbor_keys( sgr1, atm1_key, atm_ngb_keys_dct1[atm1_key] - {atm2_key})[0] atm2_ngb_key1 = stereo_sorted_atom_neighbor_keys( sgr1, atm2_key, atm_ngb_keys_dct1[atm2_key] - {atm1_key})[0] atm1_ngb_key2 = stereo_sorted_atom_neighbor_keys( sgr2, atm1_key, atm_ngb_keys_dct2[atm1_key] - {atm2_key})[0] atm2_ngb_key2 = stereo_sorted_atom_neighbor_keys( sgr2, atm2_key, atm_ngb_keys_dct2[atm2_key] - {atm1_key})[0] if not ((atm1_ngb_key1 != atm1_ngb_key2) ^ (atm2_ngb_key1 != atm2_ngb_key2)): ret &= (par1 == par2) else: ret &= (par1 != par2) return ret
def _reverse(tra, xgr1, xgr2): frm_bnd_keys = formed_bond_keys(tra) brk_bnd_keys = broken_bond_keys(tra) atm_key_dct = _full_isomorphism(apply(tra, xgr1), xgr2) rev_frm_bnd_keys = [ frozenset(map(atm_key_dct.__getitem__, bnd_key)) for bnd_key in brk_bnd_keys ] rev_brk_bnd_keys = [ frozenset(map(atm_key_dct.__getitem__, bnd_key)) for bnd_key in frm_bnd_keys ] rev_tra = from_data(frm_bnd_keys=rev_frm_bnd_keys, brk_bnd_keys=rev_brk_bnd_keys) return rev_tra
def _substitution(atmsA, neighsA, bndsA, atmsB, neighsB, xgr1, xgr2): for atmi in atmsA: if _is_heavy(atmi, atmsA): i_neighs = neighsA[atmi] for atmj in i_neighs: bnd_break_key_ij = _get_bnd_key(atmi, atmj, bndsA) new_xgr = automol.graph.remove_bonds(xgr1, [bnd_break_key_ij]) for atmk in atmsB: if atmk != atmi and atmk != atmj: # and not atmi in neighsB[atmk] and not atmj in neighsB[atmk]: bnd_form_key_ik = frozenset({atmi, atmk}) newnew_xgr = automol.graph.add_bonds( new_xgr, [bnd_form_key_ik]) atm_key_dct = _full_isomorphism(newnew_xgr, xgr2) if atm_key_dct: tra = [[bnd_form_key_ik], [bnd_break_key_ij]] return tra
def _substitution(atmsa, neighsa, bndsa, atmsb, xgr1, xgr2): ret_tra = None for atmi in atmsa: if _is_heavy(atmi, atmsa): i_neighs = neighsa[atmi] for atmj in i_neighs: bnd_break_key_ij = _get_bnd_key(atmi, atmj, bndsa) new_xgr = remove_bonds(xgr1, [bnd_break_key_ij]) for atmk in atmsb: if atmk not in (atmi, atmj): bnd_form_key_ik = frozenset({atmi, atmk}) newnew_xgr = add_bonds(new_xgr, [bnd_form_key_ik]) atm_key_dct = _full_isomorphism(newnew_xgr, xgr2) if atm_key_dct: tra = [[bnd_form_key_ik], [bnd_break_key_ij]] ret_tra = tra return ret_tra
def _partial_hydrogen_abstraction(qh_xgr, q_xgr): tra = None h_atm_key = max(_atom_keys(q_xgr)) + 1 #rad_atm_keys = _resonance_dominant_radical_atom_keys(q_xgr) uns_atm_keys = automol.graph.unsaturated_atom_keys(q_xgr) for atm_key in uns_atm_keys: #for atm_key in rad_atm_keys: q_xgr_h = _add_atom_explicit_hydrogen_keys(q_xgr, {atm_key: [h_atm_key]}) inv_atm_key_dct = _full_isomorphism(q_xgr_h, qh_xgr) if inv_atm_key_dct: brk_bnd_keys = [ frozenset( {inv_atm_key_dct[atm_key], inv_atm_key_dct[h_atm_key]}) ] tra = from_data(frm_bnd_keys=[], brk_bnd_keys=brk_bnd_keys) return tra
def _insertion(atmsA, neighsA, bndsA, atmsB, neighsB, xgr1, xgr2): """Do the insertion for an order of reactants """ for i in atmsA: if _is_heavy(i, atmsA): i_neighs = neighsA[i] for j in i_neighs: bnd_break_key_ij = _get_bnd_key(i, j, bndsA) new_xgr = automol.graph.remove_bonds(xgr1, [bnd_break_key_ij]) for k in atmsB: if _is_heavy( k, atmsB) and k != i and k != j and not i in neighsB[ k] and not j in neighsB[k]: bnd_form_key_ik = {i, k} bnd_form_key_jk = {j, k} newnew_xgr = automol.graph.add_bonds( new_xgr, [bnd_form_key_ik, bnd_form_key_jk]) atm_key_dct = _full_isomorphism(newnew_xgr, xgr2) if atm_key_dct: tra = [[bnd_form_key_ik, bnd_form_key_jk], [bnd_break_key_ij]] return tra
def _insertion(atmsa, neighsa, bndsa, atmsb, neighsb, xgr1, xgr2): """Do the insertion for an order of reactants """ ret_tra = None for i in atmsa: if _is_heavy(i, atmsa): i_neighs = neighsa[i] for j in i_neighs: bnd_break_key_ij = _get_bnd_key(i, j, bndsa) new_xgr = remove_bonds(xgr1, [bnd_break_key_ij]) for k in atmsb: if _is_heavy(k, atmsb) and (k != i and k != j and i not in neighsb[k] and j not in neighsb[k]): bnd_form_key_ik = {i, k} bnd_form_key_jk = {j, k} newnew_xgr = add_bonds( new_xgr, [bnd_form_key_ik, bnd_form_key_jk]) atm_key_dct = _full_isomorphism(newnew_xgr, xgr2) if atm_key_dct: tra = [[bnd_form_key_ik, bnd_form_key_jk], [bnd_break_key_ij]] ret_tra = tra return ret_tra
def elimination(xgr1, xgr2): """identifies elimination reactions """ assert xgr1 == _explicit(xgr1) and xgr2 == _explicit(xgr2) tra = None xgrs1 = _connected_components(xgr1) xgrs2 = _connected_components(xgr2) tras = [] if len(xgrs1) == 1 and len(xgrs2) == 2: atms = atoms(xgr1) neighs = atom_neighbor_keys(xgr1) bnds = bond_keys(xgr1) radicals = _resonance_dominant_radical_atom_keys(xgr1) lonepairs = atom_lone_pair_counts(xgr1) for atmi in atms: i_neighs = neighs[atmi] for atmj in i_neighs: bnd_break_key_ij = _get_bnd_key(atmi, atmj, bnds) new_xgr = remove_bonds(xgr1, [bnd_break_key_ij]) new_xgrs = _connected_components(new_xgr) if len(new_xgrs) == 2: xgra, xgrb = new_xgrs atmsa = atoms(xgra) if atmi not in atmsa.keys(): xgrb, xgra = xgra, xgrb atmsa = atoms(xgra) neighsa = atom_neighbor_keys(xgra) atmsb = atoms(xgrb) neighs_i = neighsa[atmi] for atmk in atmsb: if atmk in radicals: for atml in neighs_i: neighs_l = neighsa[atml] if atml != atmj: bnd_break_key_il = _get_bnd_key( atmi, atml, bnds) bnd_form_key_kl = frozenset({atmk, atml}) newnew_xgr = remove_bonds( new_xgr, [bnd_break_key_il]) newnew_xgr = add_bonds( newnew_xgr, [bnd_form_key_kl]) atm_key_dct = _full_isomorphism( newnew_xgr, xgr2) if atm_key_dct: tra = [[bnd_form_key_kl], [ bnd_break_key_ij, bnd_break_key_il ]] return tra for atmm in neighs_l: if atmm != atmi: bnd_break_key_lm = _get_bnd_key( atml, atmm, bnds) bnd_form_key_km = frozenset( {atmk, atmm}) newnew_xgr = remove_bonds( new_xgr, [bnd_break_key_lm]) newnew_xgr = add_bonds( newnew_xgr, [bnd_form_key_km]) atm_key_dct = _full_isomorphism( newnew_xgr, xgr2) if atm_key_dct: tras.append([[bnd_form_key_km], [ bnd_break_key_ij, bnd_break_key_lm ]]) for atmi in atms: i_neighs = neighs[atmi] print('atmi test:', atmi) print('i_neighs test:', i_neighs) for atmj in i_neighs: bnd_break_key_ij = _get_bnd_key(atmi, atmj, bnds) new_xgr = remove_bonds(xgr1, [bnd_break_key_ij]) new_xgrs = _connected_components(new_xgr) if len(new_xgrs) == 2: xgra, xgrb = new_xgrs atmsa = atoms(xgra) if atmi not in atmsa.keys(): xgrb, xgra = xgra, xgrb atmsa = atoms(xgra) neighsa = atom_neighbor_keys(xgra) atmsb = atoms(xgrb) neighs_i = neighsa[atmi] print('len atmsb test:', len(atmsb)) for atmk in atmsb: if lonepairs[atmk] > 0 or len(atmsb) == 1: # if lonepairs[atmk] > 0: for atml in neighs_i: neighs_l = neighsa[atml] if atml != atmj: bnd_break_key_il = _get_bnd_key( atmi, atml, bnds) bnd_form_key_kl = frozenset({atmk, atml}) newnew_xgr = remove_bonds( new_xgr, [bnd_break_key_il]) newnew_xgr = add_bonds( newnew_xgr, [bnd_form_key_kl]) atm_key_dct = _full_isomorphism( newnew_xgr, xgr2) if atm_key_dct: tra = [[bnd_form_key_kl], [ bnd_break_key_ij, bnd_break_key_il ]] return tra for atmm in neighs_l: if atmm != atmi: bnd_break_key_lm = _get_bnd_key( atml, atmm, bnds) bnd_form_key_km = frozenset( {atmk, atmm}) newnew_xgr = remove_bonds( new_xgr, [bnd_break_key_lm]) newnew_xgr = add_bonds( newnew_xgr, [bnd_form_key_km]) atm_key_dct = _full_isomorphism( newnew_xgr, xgr2) if atm_key_dct: tras.append([[bnd_form_key_km], [ bnd_break_key_ij, bnd_break_key_lm ]]) if len(tras) < 1: tras = None return tras
def elimination(xgr1, xgr2): """identifies elimination reactions """ assert xgr1 == _explicit(xgr1) and xgr2 == _explicit(xgr2) tra = None xgrs1 = _connected_components(xgr1) xgrs2 = _connected_components(xgr2) tras = [] if len(xgrs1) == 1 and len(xgrs2) == 2: atms = automol.graph.atoms(xgr1) neighs = automol.graph.atom_neighbor_keys(xgr1) bnds = automol.graph.bond_keys(xgr1) lonepairs = automol.graph.atom_lone_pair_counts(xgr1) for atmi in atms: i_neighs = neighs[atmi] for atmj in i_neighs: bnd_break_key_ij = _get_bnd_key(atmi, atmj, bnds) new_xgr = automol.graph.remove_bonds(xgr1, [bnd_break_key_ij]) new_xgrs = _connected_components(new_xgr) if len(new_xgrs) == 2: xgrA, xgrB = new_xgrs atmsA = automol.graph.atoms(xgrA) if atmi not in atmsA.keys(): xgrB, xgrA = xgrA, xgrB atmsA = automol.graph.atoms(xgrA) neighsA = automol.graph.atom_neighbor_keys(xgrA) atmsB = automol.graph.atoms(xgrB) neighs_i = neighsA[atmi] for atmk in atmsB: if lonepairs[atmk] > 0: for atml in neighs_i: neighs_l = neighsA[atml] if atml != atmj: bnd_break_key_il = _get_bnd_key( atmi, atml, bnds) bnd_form_key_kl = frozenset({atmk, atml}) newnew_xgr = automol.graph.remove_bonds( new_xgr, [bnd_break_key_il]) newnew_xgr = automol.graph.add_bonds( newnew_xgr, [bnd_form_key_kl]) atm_key_dct = _full_isomorphism( newnew_xgr, xgr2) if atm_key_dct: tra = [[bnd_form_key_kl], [ bnd_break_key_ij, bnd_break_key_il ]] return tra for atmm in neighs_l: if atmm != atmi: bnd_break_key_lm = _get_bnd_key( atml, atmm, bnds) bnd_form_key_km = frozenset( {atmk, atmm}) newnew_xgr = automol.graph.remove_bonds( new_xgr, [bnd_break_key_lm]) newnew_xgr = automol.graph.add_bonds( newnew_xgr, [bnd_form_key_km]) atm_key_dct = _full_isomorphism( newnew_xgr, xgr2) if atm_key_dct: tras.append([[bnd_form_key_km], [ bnd_break_key_ij, bnd_break_key_lm ]]) if len(tras) < 1: tras = None return tras