def insertion(rct_gras, prd_gras): """ find a insertion transformation Implemented as the reverse of an elimination transformation. """ tras = [] rev_tras, prd_idxs, rct_idxs = elimination(prd_gras, rct_gras) if rev_tras: rct_gra = union_from_sequence(rct_gras) prd_gra = union_from_sequence(prd_gras) tras = [trans.reverse(tra, prd_gra, rct_gra) for tra in rev_tras] tras = tuple(set(tras)) return tras, rct_idxs, prd_idxs
def beta_scission(rct_gras, prd_gras): """ find a beta scission transformation Implemented as the reverse of an addition reaction. """ tras = [] rev_tras, prd_idxs, rct_idxs = addition(prd_gras, rct_gras) if rev_tras: rct_gra = union_from_sequence(rct_gras) prd_gra = union_from_sequence(prd_gras) tras = [trans.reverse(tra, prd_gra, rct_gra) for tra in rev_tras] tras = tuple(set(tras)) return tras, rct_idxs, prd_idxs
def substitution(rct_gras, prd_gras): """ find an substitution transformation Substitutions are identified by breaking one bond in the reactants and one bond from the products and checking for isomorphism. """ _assert_is_valid_reagent_graph_list(rct_gras) _assert_is_valid_reagent_graph_list(prd_gras) tras = [] rct_idxs = None prd_idxs = None is_triv = is_trivial_reaction(rct_gras, prd_gras) if len(rct_gras) == 2 and len(prd_gras) == 2 and not is_triv: rct_gra = union_from_sequence(rct_gras) prd_gra = union_from_sequence(prd_gras) rct_bnd_keys = bond_keys(rct_gra) prd_bnd_keys = bond_keys(prd_gra) for rct_bnd_key, prd_bnd_key in itertools.product( rct_bnd_keys, prd_bnd_keys): rct_gra_ = remove_bonds(rct_gra, [rct_bnd_key]) prd_gra_ = remove_bonds(prd_gra, [prd_bnd_key]) inv_atm_key_dct = full_isomorphism(prd_gra_, rct_gra_) if inv_atm_key_dct: brk_bnd_key = rct_bnd_key frm_bnd_key = frozenset( map(inv_atm_key_dct.__getitem__, prd_bnd_key)) tra = trans.from_data( rxn_class=par.REACTION_CLASS.SUBSTITUTION, frm_bnd_keys=[frm_bnd_key], brk_bnd_keys=[brk_bnd_key]) tras.append(tra) rct_idxs = _argsort_reactants(rct_gras) prd_idxs = _argsort_reactants(prd_gras) tras = tuple(set(tras)) return tras, rct_idxs, prd_idxs
def elimination(rct_gras, prd_gras): """ find an elimination transformation Eliminations are identified by breaking two bonds from the reactant, forming three fragments. This will form one "central fragment" with two break sites and two "end fragments" with one break site each. If the central fragment plus the two end fragments, joined at their break sites, matches the products, this is an elimination reaction. """ _assert_is_valid_reagent_graph_list(rct_gras) _assert_is_valid_reagent_graph_list(prd_gras) tras = [] rct_idxs = None prd_idxs = None is_triv = is_trivial_reaction(rct_gras, prd_gras) if len(rct_gras) == 1 and len(prd_gras) == 2 and not is_triv: rct_gra, = rct_gras rct_bnd_keys = bond_keys(rct_gra) # Loop over pairs of bonds and break them. Then, if this forms three # fragments, join the two end fragments and compare the result to the # products. for brk_bnd_key1, brk_bnd_key2 in itertools.combinations(rct_bnd_keys, r=2): rct_gra_ = remove_bonds(rct_gra, [brk_bnd_key1, brk_bnd_key2]) # Find the central fragment, which is the one connected to both # break sites. If there's a loop there may not be a central # fragment, in which case this function will return None. cent_frag_atm_keys = _central_fragment_atom_keys( rct_gra_, brk_bnd_key1, brk_bnd_key2) if cent_frag_atm_keys is not None: atm1_key, = brk_bnd_key1 - cent_frag_atm_keys atm2_key, = brk_bnd_key2 - cent_frag_atm_keys frm_bnd_key = frozenset({atm1_key, atm2_key}) rct_gra_ = add_bonds(rct_gra_, [frm_bnd_key]) prd_gra = union_from_sequence(prd_gras) atm_key_dct = full_isomorphism(rct_gra_, prd_gra) if atm_key_dct: tra = trans.from_data( rxn_class=par.REACTION_CLASS.ELIMINATION, frm_bnd_keys=[frm_bnd_key], brk_bnd_keys=[brk_bnd_key1, brk_bnd_key2]) tras.append(tra) rct_idxs = (0, ) cent_prd_atm_keys = frozenset( map(atm_key_dct.__getitem__, cent_frag_atm_keys)) if cent_prd_atm_keys <= atom_keys(prd_gras[0]): prd_idxs = (0, 1) else: assert cent_prd_atm_keys <= atom_keys(prd_gras[1]) prd_idxs = (1, 0) tras = tuple(tras) return tras, rct_idxs, prd_idxs
def is_ring_system(gra): """ is this graph a ring system? """ return union_from_sequence(rings(gra), check=False) == gra