예제 #1
0
def test__from_data():
    """ test getters
    """
    cgr = automol.graph.from_data(
        atm_symb_dct=graph.atom_symbols(C8H13O_CGR),
        bnd_keys=graph.bond_keys(C8H13O_CGR),
        atm_imp_hyd_vlc_dct=(
            graph.atom_implicit_hydrogen_valences(C8H13O_CGR)),
    )
    assert cgr == C8H13O_CGR

    rgr = automol.graph.from_data(
        atm_symb_dct=graph.atom_symbols(C8H13O_RGR),
        bnd_keys=graph.bond_keys(C8H13O_RGR),
        atm_imp_hyd_vlc_dct=(
            graph.atom_implicit_hydrogen_valences(C8H13O_RGR)),
        bnd_ord_dct=graph.bond_orders(C8H13O_RGR),
    )
    assert rgr == C8H13O_RGR

    sgr = automol.graph.from_data(
        atm_symb_dct=graph.atom_symbols(C8H13O_SGR),
        bnd_keys=graph.bond_keys(C8H13O_SGR),
        atm_imp_hyd_vlc_dct=(
            graph.atom_implicit_hydrogen_valences(C8H13O_SGR)),
        atm_ste_par_dct=graph.atom_stereo_parities(C8H13O_SGR),
        bnd_ste_par_dct=graph.bond_stereo_parities(C8H13O_SGR))
    assert sgr == C8H13O_SGR
예제 #2
0
def test__set_atom_implicit_hydrogen_valences():
    """ test graph.set_atom_implicit_hydrogen_valences
    """
    atm_keys = graph.atom_keys(C8H13O_CGR)
    cgr = graph.set_atom_implicit_hydrogen_valences(
        C8H13O_CGR, {atm_key: 0
                     for atm_key in atm_keys})

    assert cgr == automol.graph.from_data(graph.atom_symbols(C8H13O_CGR),
                                          graph.bond_keys(C8H13O_CGR))
예제 #3
0
def test__from_dictionaries():
    """ test graph.from_dictionaries
    """
    assert graph.from_dictionaries(
        graph.atom_symbols(CH2FH2H_CGR_EXP),
        graph.bond_keys(CH2FH2H_CGR_EXP)
    ) == CH2FH2H_CGR_EXP

    assert graph.from_dictionaries(
        graph.atom_symbols(C8H13O_RGRS[0]),
        graph.bond_keys(C8H13O_RGRS[0]),
        atm_imp_hyd_vlc_dct=graph.atom_implicit_hydrogen_valences(
            C8H13O_RGRS[0]),
        bnd_ord_dct=graph.bond_orders(C8H13O_RGRS[0])
    ) == C8H13O_RGRS[0]

    assert graph.from_dictionaries(
        graph.atom_symbols(C8H13O_SGRS[0]),
        graph.bond_keys(C8H13O_SGRS[0]),
        atm_imp_hyd_vlc_dct=graph.atom_implicit_hydrogen_valences(
            C8H13O_SGRS[0]),
        atm_ste_par_dct=graph.atom_stereo_parities(C8H13O_SGRS[0]),
        bnd_ste_par_dct=graph.bond_stereo_parities(C8H13O_SGRS[0])
    ) == C8H13O_SGRS[0]

    # a litte ridiculous, but make sure we get the keys right
    sgr_ref = C8H13O_SGRS[0]
    natms = len(graph.atoms(sgr_ref))
    for _ in range(10):
        pmt_dct = dict(enumerate(numpy.random.permutation(natms)))
        sgr = graph.relabel(sgr_ref, pmt_dct)
        assert graph.from_dictionaries(
            graph.atom_symbols(sgr),
            graph.bond_keys(sgr),
            atm_imp_hyd_vlc_dct=graph.atom_implicit_hydrogen_valences(sgr),
            atm_ste_par_dct=graph.atom_stereo_parities(sgr),
            bnd_ste_par_dct=graph.bond_stereo_parities(sgr)
        ) == sgr
예제 #4
0
def eliminations(rct_gras, viable_only=True):
    """ find all possible elimination reactions for these reactants

    :param rct_gras: graphs for the reactants, without stereo and without
        overlapping keys
    :param viable_only: Filter out reactions with non-viable products?
    :type viable_only: bool
    :returns: a list of Reaction objects
    :rtype: tuple[Reaction]

    Eliminations are enumerated by forming a bond between an attacking heavy
    atom and another atom not initially bonded to it, forming a ring. The bond
    adjacent to the attacked atom is then broken, along with a second bond in
    the ring, downstream from the attacking heavy atom, away from the attacked
    atom.
    """
    assert_is_valid_reagent_graph_list(rct_gras)

    rxns = []

    if len(rct_gras) == 1:
        rct_gra, = rct_gras

        ngb_keys_dct = atoms_neighbor_atom_keys(rct_gra)

        # frm1_keys = atom_keys(rct_gra, excl_syms=('H',))
        frm1_keys = unsaturated_atom_keys(rct_gra)
        rct_symbs = atom_symbols(rct_gra)
        frm1_keys_o = frozenset(key for key in frm1_keys
                                if rct_symbs[key] == 'O')
        frm2_keys = atom_keys(rct_gra)
        bnd_keys = bond_keys(rct_gra)

        frm_bnd_keys = [(frm1_key, frm2_key)
                        for frm1_key, frm2_key in itertools.product(
                            frm1_keys_o, frm2_keys) if frm1_key != frm2_key
                        and not frozenset({frm1_key, frm2_key}) in bnd_keys]

        for frm1_key, frm2_key in frm_bnd_keys:
            # Bond the radical atom to the hydrogen atom
            prds_gra = add_bonds(rct_gra, [(frm2_key, frm1_key)])

            # Get keys to the ring formed by this extra bond
            rng_keys = next((ks for ks in rings_atom_keys(prds_gra)
                             if frm2_key in ks and frm1_key in ks), None)
            # Eliminations (as far as I can tell) only happen through TSs with
            # 3- or 4-membered rings
            if rng_keys is not None and len(rng_keys) < 5:
                frm1_ngb_key, = ngb_keys_dct[frm1_key] & set(rng_keys)
                frm2_ngb_key, = ngb_keys_dct[frm2_key] & set(rng_keys)

                # Break the bonds on either side of the newly formed bond
                prds_gra = remove_bonds(prds_gra, [(frm1_key, frm1_ngb_key)])
                prds_gra = remove_bonds(prds_gra, [(frm2_key, frm2_ngb_key)])

                prd_gras = connected_components(prds_gra)

                if len(prd_gras) == 2:
                    forw_tsg = ts.graph(rct_gra,
                                        frm_bnd_keys=[(frm1_key, frm2_key)],
                                        brk_bnd_keys=[(frm1_key, frm1_ngb_key),
                                                      (frm2_key, frm2_ngb_key)
                                                      ])
                    back_tsg = ts.graph(prds_gra,
                                        frm_bnd_keys=[(frm1_key, frm1_ngb_key),
                                                      (frm2_key, frm2_ngb_key)
                                                      ],
                                        brk_bnd_keys=[(frm1_key, frm2_key)])

                    rcts_atm_keys = list(map(atom_keys, rct_gras))
                    prds_atm_keys = list(map(atom_keys, prd_gras))

                    if frm2_key not in prds_atm_keys[1]:
                        prds_atm_keys = list(reversed(prds_atm_keys))

                    # Create the reaction object
                    rxns.append(
                        Reaction(
                            rxn_cls=par.ReactionClass.Typ.ELIMINATION,
                            forw_tsg=forw_tsg,
                            back_tsg=back_tsg,
                            rcts_keys=rcts_atm_keys,
                            prds_keys=prds_atm_keys,
                        ))

    if viable_only:
        rxns = filter_viable_reactions(rxns)

    return ts_unique(rxns)
예제 #5
0
def eliminations(rct_gras, prd_gras):
    """ find eliminations consistent with these reactants and products

    :param rct_gras: reactant graphs (must have non-overlapping keys)
    :param prd_gras: product graphs (must have non-overlapping keys)

    Eliminations are identified by forming a bond between an attacking heavy
    atom and another atom not initially bonded to it, forming a ring. The bond
    adjacent to the attacked atom is then broken, along with a second bond in
    the ring, downstream of the attacking heavy atom, away from the attacked
    atom.
    """
    def _identify(frm1_keys, frm2_keys, bnd_keys):
        """ Try and identify elmination from some set of keys
        """

        _rxns = []

        frm_bnd_keys = [
            (frm1_key, frm2_key)
            for frm1_key, frm2_key in itertools.product(frm1_keys, frm2_keys)
            if frm1_key != frm2_key
            and not frozenset({frm1_key, frm2_key}) in bnd_keys
        ]

        for frm1_key, frm2_key in frm_bnd_keys:

            prds_gra_ = add_bonds(rct_gra, [(frm2_key, frm1_key)])

            # Get keys of all bonds in the ring formed by this extra bond
            rng_bnd_keys = next((ks for ks in rings_bond_keys(prds_gra_)
                                 if frozenset({frm1_key, frm2_key}) in ks),
                                None)

            if rng_bnd_keys is not None:

                # Elims break two bonds of the ring formed by the forming bond
                # Loop over all ring bond-pairs, break bonds, see if prods form
                # Ensure to preclude the forming-bond from this set
                brk_bnds = tuple(
                    bond for bond in itertools.combinations(rng_bnd_keys, 2)
                    if frozenset({frm1_key, frm2_key}) not in bond)

                for brk_bnd_1, brk_bnd_2 in brk_bnds:
                    prds_gra_2_ = prds_gra_
                    prds_gra_2_ = remove_bonds(prds_gra_2_, [brk_bnd_1])
                    prds_gra_2_ = remove_bonds(prds_gra_2_, [brk_bnd_2])

                    inv_dct = isomorphism(prds_gra_2_, prds_gra)
                    if inv_dct:
                        f_frm_bnd_key = (frm1_key, frm2_key)

                        inv_ = inv_dct.__getitem__
                        b_frm_bnd_key1 = tuple(map(inv_, brk_bnd_1))
                        b_frm_bnd_key2 = tuple(map(inv_, brk_bnd_2))
                        b_brk_bnd_key = tuple(map(inv_, f_frm_bnd_key))

                        forw_tsg = ts.graph(
                            rct_gra,
                            frm_bnd_keys=[f_frm_bnd_key],
                            brk_bnd_keys=[brk_bnd_1, brk_bnd_2])
                        back_tsg = ts.graph(
                            prds_gra,
                            frm_bnd_keys=[b_frm_bnd_key1, b_frm_bnd_key2],
                            brk_bnd_keys=[b_brk_bnd_key])

                        rcts_atm_keys = list(map(atom_keys, rct_gras))
                        prds_atm_keys = list(map(atom_keys, prd_gras))

                        if inv_dct[frm1_key] not in prds_atm_keys[1]:
                            prds_atm_keys = list(reversed(prds_atm_keys))

                        assert inv_dct[frm1_key] in prds_atm_keys[1]
                        assert inv_dct[frm2_key] in prds_atm_keys[1]

                        # Create the reaction object
                        _rxns.append(
                            Reaction(
                                rxn_cls=ReactionClass.Typ.ELIMINATION,
                                forw_tsg=forw_tsg,
                                back_tsg=back_tsg,
                                rcts_keys=rcts_atm_keys,
                                prds_keys=prds_atm_keys,
                            ))

        return _rxns

    assert_is_valid_reagent_graph_list(rct_gras)
    assert_is_valid_reagent_graph_list(prd_gras)

    rxns = []

    if len(rct_gras) == 1 and len(prd_gras) == 2:
        rct_gra, = rct_gras
        prds_gra = union_from_sequence(prd_gras)

        # ngb_keys_dct = atoms_neighbor_atom_keys(rct_gra)

        # Generate keys all bonds and 1/2 the forming bond
        frm1_keys = atom_keys(rct_gra)
        bnd_keys = bond_keys(rct_gra)

        frm2_keys = unsaturated_atom_keys(rct_gra)
        rct_symbs = atom_symbols(rct_gra)
        frm2_keys_o = frozenset(key for key in frm2_keys
                                if rct_symbs[key] == 'O')
        rxns.extend(_identify(frm1_keys, frm2_keys_o, bnd_keys))

        # OLD WAY. More IDs but more mistakes
        # To make the function general, try to ID reaction
        # with different types of keys for the attacking atom
        # (1) unsaturated atom sites
        # frm2_keys = unsaturated_atom_keys(rct_gra)
        # rxns.extend(_identify(frm1_keys, frm2_keys, bnd_keys))
        # if not rxns:
        #     # (2) remaining saturated atom sites
        #     frm2_keys = atom_keys(rct_gra, excl_syms=('H',)) - frm2_keys
        #     rxns.extend(_identify(frm1_keys, frm2_keys, bnd_keys))
        #     # if not rxns:  # Ignoring H2 formation for now for speed
        #     #     # (3) H atoms
        #     #     frm1_keys = atom_keys(rct_gra, sym='H')
        #     #     rxns.extend(_identify(frm1_keys, frm2_keys, bnd_keys))

    return ts_unique(rxns)