Example #1
0
def isomorphic_radical_graphs(gra):
    """ Generate a set of graphs that are isomorphic to a graph
        of a radical species
    """

    # Determine useful keys
    symbols = atom_symbols(gra)
    unsat_keys = unsaturated_atom_keys(gra)
    unsat_key = next(iter(unsat_keys))
    h_atm_key = max(symbols.keys()) + 1

    iso_gras = []
    for aidx, symbol in enumerate(symbols.values()):
        # Loop over saturated (non-radical) heavy atoms
        if symbol != 'H' and aidx != unsat_key:

            # Add hydrogen atom to radical atom
            new_graph = add_atom_explicit_hydrogen_keys(
                gra, {unsat_key: [h_atm_key]})

            # Remove hydrogen from saturated atom
            neighbors = atom_neighbor_keys(new_graph)
            for neigh in neighbors[aidx]:
                if symbols[neigh] == 'H':
                    aneighbor = neigh
                    break
            new_graph = remove_atoms(new_graph, [aneighbor])

            # Test to see if new radical species is the same as the original
            inv_atm_key_dct = full_isomorphism(gra, new_graph)
            if inv_atm_key_dct:
                iso_gras.append(new_graph)

    return iso_gras
Example #2
0
def _radical_graph_isomorphisms(gra):
    """ Generate a set of graphs where the radical has been migrated to a
        new atom and then calculate the isomorphism between the input
        graph and all of the new graphs generated by moving the radical
    """

    # Determine useful keys
    symbols = atom_symbols(gra)
    unsat_keys = unsaturated_atom_keys(gra)
    unsat_key = next(iter(unsat_keys))
    h_atm_key = max(symbols.keys()) + 1

    new_gras, isomorphisms = [], []
    for aidx, symbol in enumerate(symbols.values()):

        # Loop over saturated (non-radical) heavy atoms
        if symbol != 'H' and aidx != unsat_key:

            # Add hydrogen atom to radical atom
            new_graph = add_atom_explicit_hydrogen_keys(
                gra, {unsat_key: [h_atm_key]})

            # Remove hydrogen from saturated atom
            neighbors = atoms_neighbor_atom_keys(new_graph)
            for neigh in neighbors[aidx]:
                if symbols[neigh] == 'H':
                    aneighbor = neigh
                    break
            new_graph = remove_atoms(new_graph, [aneighbor])

            # Build lists to return
            new_gras.append(new_graph)
            isomorphisms.append(full_isomorphism(gra, new_graph))

    return tuple(zip(new_gras, isomorphisms))
Example #3
0
def hydrogen_migration(rct_gras, prd_gras):
    """ find a hydrogen migration transformation

    Hydrogen migrations are identified by adding a hydrogen to an unsaturated
    site of the reactant and adding a hydrogen to an unsaturated site of the
    product and seeing if they match up. If so, we have a hydrogen migration
    between these two sites.
    """
    _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) == 1 and not is_triv:
        gra1, = rct_gras
        gra2, = prd_gras
        h_atm_key1 = max(atom_keys(gra1)) + 1
        h_atm_key2 = max(atom_keys(gra2)) + 1

        atm_keys1 = unsaturated_atom_keys(gra1)
        atm_keys2 = unsaturated_atom_keys(gra2)
        for atm_key1, atm_key2 in itertools.product(atm_keys1, atm_keys2):
            gra1_h = add_atom_explicit_hydrogen_keys(gra1,
                                                     {atm_key1: [h_atm_key1]})
            gra2_h = add_atom_explicit_hydrogen_keys(gra2,
                                                     {atm_key2: [h_atm_key2]})

            inv_atm_key_dct = full_isomorphism(gra2_h, gra1_h)
            if inv_atm_key_dct:
                tra = trans.from_data(
                    rxn_class=par.REACTION_CLASS.HYDROGEN_MIGRATION,
                    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]
                    }])
                tras.append(tra)

                rct_idxs = (0, )
                prd_idxs = (0, )

    tras = tuple(tras)

    return tras, rct_idxs, prd_idxs
Example #4
0
def prod_addition(x_gra, y_gra):
    """ products of addition
    """

    prod_gras = tuple()

    shift = len(automol.graph.atoms(x_gra))
    y_gra = automol.graph.transform_keys(y_gra, lambda x: x + shift)

    x_keys = unsaturated_atom_keys(x_gra)
    y_keys = unsaturated_atom_keys(y_gra)

    for x_key, y_key in itertools.product(x_keys, y_keys):
        xy_gra = add_bonds(union(x_gra, y_gra), [{x_key, y_key}])
        prod_gras += ((xy_gra, ), )

    return _unique_gras(prod_gras)
Example #5
0
def addition(rct_gras, prd_gras):
    """ find an addition transformation

    Additions are identified by joining an unsaturated site on one reactant to
    an unsaturated site on the other. If the result matches the products, this
    is an addition 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) == 2 and len(prd_gras) == 1 and not is_triv:
        x_gra, y_gra = rct_gras
        prd_gra, = prd_gras
        x_atm_keys = unsaturated_atom_keys(x_gra)
        y_atm_keys = unsaturated_atom_keys(y_gra)

        for x_atm_key, y_atm_key in itertools.product(x_atm_keys, y_atm_keys):
            xy_gra = add_bonds(union(x_gra, y_gra), [{x_atm_key, y_atm_key}])

            atm_key_dct = full_isomorphism(xy_gra, prd_gra)
            if atm_key_dct:
                tra = trans.from_data(rxn_class=par.REACTION_CLASS.ADDITION,
                                      frm_bnd_keys=[{x_atm_key, y_atm_key}],
                                      brk_bnd_keys=[])
                tras.append(tra)

                # sort the reactants so that the largest species is first
                rct_idxs = _argsort_reactants(rct_gras)
                prd_idxs = (0, )

    tras = tuple(tras)
    return tras, rct_idxs, prd_idxs
Example #6
0
def ring_forming_scission(rct_gras, prd_gras):
    """ find a ring forming reaction that eliminates a radical group
    """
    _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:
        rgra, = rct_gras
        pgra1, pgra2 = prd_gras
        pgra = automol.graph.union(pgra1, pgra2)
        rad_atm_keys = unsaturated_atom_keys(rgra)
        atms, bnds = rgra
        ngb_atms = automol.graph.atom_neighbor_keys(rgra)

        for rad_atm in rad_atm_keys:
            for xatm in atms:
                if (xatm != rad_atm and atms[xatm][1] != 'H'
                        and xatm not in ngb_atms[rad_atm] and not tras):
                    for natm in ngb_atms[xatm]:
                        if natm != rad_atm:
                            xgra = atms.copy(), bnds.copy()
                            xgra = add_bonds(xgra,
                                             [frozenset({rad_atm, xatm})])
                            xgra = remove_bonds(xgra,
                                                [frozenset({xatm, natm})])
                            atm_key_dct = full_isomorphism(xgra, pgra)
                            if atm_key_dct:
                                tra = trans.from_data(
                                    rxn_class=(
                                        par.REACTION_CLASS.RING_FORM_SCISSION),
                                    frm_bnd_keys=[{rad_atm, xatm}],
                                    brk_bnd_keys=[
                                        {xatm, natm},
                                    ])
                                tras.append(tra)
                                break

                # sort the reactants so that the largest species is first
        rct_idxs = (0, )
        prd_idxs = _argsort_reactants(prd_gras)
        tras = tuple(tras)

    return tras, rct_idxs, prd_idxs
Example #7
0
def _partial_hydrogen_abstraction(qh_gra, q_gra):
    rets = []

    h_atm_key = max(atom_keys(q_gra)) + 1
    uns_atm_keys = unsaturated_atom_keys(q_gra)
    for atm_key in uns_atm_keys:
        q_gra_h = add_atom_explicit_hydrogen_keys(q_gra,
                                                  {atm_key: [h_atm_key]})
        inv_atm_key_dct = full_isomorphism(q_gra_h, qh_gra)
        if inv_atm_key_dct:
            qh_q_atm_key = inv_atm_key_dct[atm_key]
            qh_h_atm_key = inv_atm_key_dct[h_atm_key]
            q_q_atm_key = atm_key
            rets.append((qh_q_atm_key, qh_h_atm_key, q_q_atm_key))

    return rets
Example #8
0
def rot_permutated_geoms(geo, frm_bnd_keys=(), brk_bnd_keys=()):
    """ Convert an input geometry to a list of geometries
        corresponding to the rotational permuations of all the terminal groups.
        :param geo: molecular geometry
        :type geo: automol molecular geometry data structure
        :param frm_bnd_keys: keys denoting atoms forming bond in TS
        :type frm_bnd_keys: frozenset(int)
        :param brk_bnd_keys: keys denoting atoms breaking bond in TS
        :type brk_bnd_keys: frozenset(int)
        :rtype: tuple(automol geom data structure)
    """

    # Set saddle based on frm and brk keys existing
    saddle = bool(frm_bnd_keys or brk_bnd_keys)

    gra = automol.convert.geom.graph(geo, stereo=False)
    term_atms = {}
    all_hyds = []
    neighbor_dct = atoms_neighbor_atom_keys(gra)
    ts_atms = []
    for bnd in frm_bnd_keys:
        ts_atms.extend(list(bnd))
    for bnd in brk_bnd_keys:
        ts_atms.extend(list(bnd))

    # determine if atom is a part of a double bond
    unsat_atms = unsaturated_atom_keys(gra)
    if not saddle:
        rad_atms = sing_res_dom_radical_atom_keys(gra)
        res_rad_atms = resonance_dominant_radical_atom_keys(gra)
        rad_atms = [atm for atm in rad_atms if atm not in res_rad_atms]
    else:
        rad_atms = []

    gra = gra[0]
    for atm in gra:
        if gra[atm][0] == 'H':
            all_hyds.append(atm)
    for atm in gra:
        if atm in unsat_atms and atm not in rad_atms:
            pass
        else:
            if atm not in ts_atms:
                nonh_neighs = []
                h_neighs = []
                neighs = neighbor_dct[atm]
                for nei in neighs:
                    if nei in all_hyds:
                        h_neighs.append(nei)
                    else:
                        nonh_neighs.append(nei)
                if len(nonh_neighs) < 2 and len(h_neighs) > 1:
                    term_atms[atm] = h_neighs
    geo_final_lst = [geo]
    for atm in term_atms:
        hyds = term_atms[atm]
        geo_lst = []
        for geom in geo_final_lst:
            geo_lst.extend(_swap_for_one(geom, hyds))
        geo_final_lst = geo_lst

    return geo_final_lst
Example #9
0
def end_group_symmetry_factor(geo, frm_bnd_keys=(), brk_bnd_keys=()):
    """ Determine sym factor for terminal groups in a geometry
        :param geo: molecular geometry
        :type geo: automol molecular geometry data structure
        :param frm_bnd_keys: keys denoting atoms forming bond in TS
        :type frm_bnd_keys: frozenset(int)
        :param brk_bnd_keys: keys denoting atoms breaking bond in TS
        :type brk_bnd_keys: frozenset(int)
        :rtype: (automol geom data structure, float)
    """

    # Set saddle based on frm and brk keys existing
    saddle = bool(frm_bnd_keys or brk_bnd_keys)

    gra = automol.convert.geom.graph(geo, stereo=False)
    term_atms = {}
    all_hyds = []
    neighbor_dct = atoms_neighbor_atom_keys(gra)

    ts_atms = []
    for bnd in frm_bnd_keys:
        ts_atms.extend(list(bnd))
    for bnd in brk_bnd_keys:
        ts_atms.extend(list(bnd))
    # determine if atom is a part of a double bond
    unsat_atms = unsaturated_atom_keys(gra)
    if not saddle:
        rad_atms = sing_res_dom_radical_atom_keys(gra)
        res_rad_atms = resonance_dominant_radical_atom_keys(gra)
        rad_atms = [atm for atm in rad_atms if atm not in res_rad_atms]
    else:
        rad_atms = []

    gra = gra[0]
    for atm in gra:
        if gra[atm][0] == 'H':
            all_hyds.append(atm)
    for atm in gra:
        if atm in unsat_atms and atm not in rad_atms:
            pass
        else:
            if atm not in ts_atms:
                nonh_neighs = []
                h_neighs = []
                neighs = neighbor_dct[atm]
                for nei in neighs:
                    if nei in all_hyds:
                        h_neighs.append(nei)
                    else:
                        nonh_neighs.append(nei)
                if len(nonh_neighs) == 1 and len(h_neighs) > 1:
                    term_atms[atm] = h_neighs
    factor = 1.
    remove_atms = []
    for atm in term_atms:
        hyds = term_atms[atm]
        if len(hyds) > 1:
            factor *= len(hyds)
            remove_atms.extend(hyds)
    geo = trans.remove_coordinates(geo, remove_atms)

    return geo, factor, remove_atms