示例#1
0
    def _group_ions(self, reaction: ReactionContainer):
        """
        Ungroup molecules recorded as ions, regroup ions. Returns a tuple with the corresponding ReactionContainer and
        return code as int (0 - nothing was changed, 1 - ions were regrouped, 2 - ions are unbalanced).
        :param reaction: current reaction
        :return: tuple[ReactionContainer, int]
        """
        meta = reaction.meta
        reaction_parts = []
        return_codes = []
        for molecules in (reaction.reactants, reaction.reagents, reaction.products):
            divided_molecules = [x for m in molecules for x in m.split('.')]

            if len(divided_molecules) == 0:
                reaction_parts.append(())
                continue
            elif len(divided_molecules) == 1 and self._calc_charge(divided_molecules[0]) == 0:
                return_codes.append(0)
                reaction_parts.append(molecules)
                continue
            elif len(divided_molecules) == 1:
                return_codes.append(2)
                reaction_parts.append(molecules)
                continue

            new_molecules = []
            cations, anions, ions = [], [], []
            total_charge = 0
            for molecule in divided_molecules:
                mol_charge = self._calc_charge(molecule)
                total_charge += mol_charge
                if mol_charge == 0:
                    new_molecules.append(molecule)
                elif mol_charge > 0:
                    cations.append((mol_charge, molecule))
                    ions.append((mol_charge, molecule))
                else:
                    anions.append((mol_charge, molecule))
                    ions.append((mol_charge, molecule))

            if len(cations) == 0 and len(anions) == 0:
                return_codes.append(0)
                reaction_parts.append(tuple(new_molecules))
                continue
            elif total_charge != 0:
                return_codes.append(2)
                reaction_parts.append(tuple(divided_molecules))
                continue
            else:
                salt = MoleculeContainer()
                for ion_charge, ion in ions:
                    salt = salt.union(ion)
                    total_charge += ion_charge
                    if total_charge == 0:
                        new_molecules.append(salt)
                        salt = MoleculeContainer()
                if total_charge != 0:
                    new_molecules.append(salt)
                    return_codes.append(2)
                    reaction_parts.append(tuple(new_molecules))
                else:
                    return_codes.append(1)
                    reaction_parts.append(tuple(new_molecules))
        return ReactionContainer(reactants=reaction_parts[0], reagents=reaction_parts[1], products=reaction_parts[2],
                                 meta=meta), max(return_codes)
def enumeration_cgr(reaction):

    cgrs = ~reaction

    all_prot = diff_atoms(reaction.reactants, reaction.products)
    all_coming = diff_atoms(reaction.products, reaction.reactants)

    prot_gr = cgrs.substructure(all_prot).split()
    coming_gr = cgrs.substructure(all_coming).split()

    united_prot = defaultdict(list)
    united_come = defaultdict(list)
    united = []
    other_list = []

    for x in cgrs.centers_list:
        flafg = 1
        for y, z in zip(prot_gr, coming_gr):
            if set(x).intersection(y):
                flafg = 0
                [united_prot[y].append(x) for x in x]
            if set(x).intersection(z):
                flafg = 0
                [united_come[z].append(x) for x in x]
        if flafg:
            other_list.append(x)

    for y in united_prot.values():
        flafg = 1
        for x in united_come.values():
            if set(x).intersection(y):
                flafg = 0
                x.extend(y)
                united.append(set(x))
        if flafg:
            other_list.append(y)
    other_list.extend(united)

    if 1 < len(other_list):

        variants_reaction = []
        reactants_to_work = big_mol(reaction.reactants)
        product_to_work = big_mol(reaction.products)

        list_rc = []

        const_at = atom_re_pr(
            set(reactants_to_work).difference(all_prot).difference(
                cgrs.center_atoms), reactants_to_work, product_to_work)
        const_bond = bonds_re_pr(cgrs.bonds(), const_at.keys())

        for big_rc in other_list:

            atom_t = atom_re_pr(
                set(big_rc).difference(all_prot).difference(all_coming),
                reactants_to_work, product_to_work)
            prot_atoms = atom_re_pr(prot_come(big_rc, all_prot, prot_gr),
                                    reactants_to_work, product_to_work)
            comming_atoms = atom_re_pr(
                prot_come(big_rc, all_coming, coming_gr), reactants_to_work,
                product_to_work)

            prot_bonds = bonds_re_pr(cgrs.bonds(), prot_atoms.keys())
            comming_bonds = bonds_re_pr(cgrs.bonds(), comming_atoms.keys())
            t_bond = bonds_re_pr(cgrs.bonds(), atom_t.keys())

            list_rc.append([
                atom_t, prot_atoms, comming_atoms, t_bond, prot_bonds,
                comming_bonds
            ])

        for e, t_rc in enumerate(list_rc):
            for state in list(product([1, 0], repeat=len(list_rc) - 1)):

                new_reactant = MoleculeContainer()
                new_product = MoleculeContainer()
                new_all_bonds_reactants = []
                new_all_bonds_products = []

                new_reactant = add_at(const_at, reactants_to_work,
                                      new_reactant)
                new_product = add_at(const_at, product_to_work, new_product)

                for x, y in t_rc[0].items():
                    new_reactant.add_atom(y['re'], x)
                    new_product.add_atom(y['pr'], x)

                for x, y in t_rc[1].items():
                    new_reactant.add_atom(y['re'], x)  # атомы уходящей группы

                for x, y in t_rc[2].items():
                    new_product.add_atom(y['pr'], x)  # приходящие атомы

                for x in const_bond.values():
                    new_all_bonds_reactants.append(x['re'])
                    new_all_bonds_products.append(x['pr'])

                for x in t_rc[5].values():
                    new_all_bonds_products.append(x['pr'])

                for x in t_rc[3].values():
                    if x['re'][2]:
                        new_all_bonds_reactants.append(x['re'])
                    if x['pr'][2]:
                        new_all_bonds_products.append(x['pr'])

                for x in t_rc[4].values():
                    new_all_bonds_reactants.append(x['re'])

                for s, big_rc in zip(state, list_rc[:e] + list_rc[e + 1:]):
                    if s == 0:
                        for x, y in big_rc[0].items():
                            new_reactant.add_atom(y['re'], x)
                            new_product.add_atom(y['re'], x)

                        for x, y in big_rc[1].items():
                            new_reactant.add_atom(y['re'], x)
                            new_product.add_atom(y['re'], x)

                        for x in big_rc[3].values():
                            if x['re'][2]:
                                new_all_bonds_reactants.append(x['re'])
                                new_all_bonds_products.append(x['re'])

                        for x in big_rc[4].values():
                            new_all_bonds_reactants.append(x['re'])
                            new_all_bonds_products.append(x['re'])

                    if s == 1:

                        for x, y in big_rc[0].items():
                            new_reactant.add_atom(y['pr'], x)
                            new_product.add_atom(y['pr'], x)

                        for x, y in big_rc[2].items():
                            new_reactant.add_atom(y['pr'], x)
                            new_product.add_atom(y['pr'], x)

                        for x in big_rc[3].values():
                            if x['pr'][2]:
                                new_all_bonds_reactants.append(x['pr'])
                                new_all_bonds_products.append(x['pr'])

                        for x in big_rc[5].values():
                            new_all_bonds_reactants.append(x['pr'])
                            new_all_bonds_products.append(x['pr'])

                [
                    new_reactant.add_bond(*x) for x in new_all_bonds_reactants
                    if not new_reactant.has_edge(x[0], x[1])
                ]
                [
                    new_product.add_bond(*x) for x in new_all_bonds_products
                    if not new_product.has_edge(x[0], x[1])
                ]
                variants_reaction.append(
                    ReactionContainer(reactants=(new_reactant, ),
                                      products=(new_product, )))
        return variants_reaction
    return [reaction]
def enumeration_cgr(reaction):

    cgrs = ~reaction

    all_prot = diff_atoms(reaction.reactants, reaction.products)
    all_coming = diff_atoms(reaction.products, reaction.reactants)

    prot_list = []
    coming_list = []

    if all_prot:
        prot_gr = cgrs.substructure(all_prot).split()
        prot_list = [set(x) for x in prot_gr]
    if all_coming:
        coming_gr = cgrs.substructure(all_coming).split()
        coming_list = [set(x) for x in coming_gr]

    all_prot_come = prot_list + coming_list
    other_list = list(cgrs.centers_list)

    for x in all_prot_come:
        unio = []

        for i, y in enumerate(other_list):
            if set(x).intersection(y):
                unio.append(i)

        if len(unio) > 1:
            qq = set()
            for i in reversed(unio):
                qq.update(other_list[i])
                other_list.pop(i)
            other_list.append(list(qq))
        del (unio)

    del (prot_list, coming_list)

    cycles = []
    for x in reaction.reactants:
        cycles.extend(x.sssr)
    for x in reaction.products:
        for y in x.sssr:
            if y not in cycles:
                cycles.append(y)
# объединение реакционных центров при циклизации в общий для этих рц цикл
    for y in cycles:
        kk = cgrs.substructure(y)
        ept = []
        new_ind = []
        unite = []
        if all(z[2].order == 4 for z in list(kk.bonds())) and any(z[2].p_order != 4 for z in list(kk.bonds()))\
                or all(z[2].p_order == 4 for z in list(kk.bonds())) and any(z[2].order != 4 for z in list(kk.bonds())):
            unite.extend(y)
        else:
            for x in other_list:
                #if set(x).intersection(kk)  and len(set(x).intersection(kk))>1:
                if len(set(x).intersection(kk)) > 1:
                    ept.append(set(x).intersection(kk))

            if len(ept) >= 2:
                for x in ept:
                    for i, p in enumerate(x):
                        for i2, m in enumerate(x):
                            if i != i2:
                                if any((m == mp[0] and p == mp[1]) or
                                       (p == mp[0] and m == mp[1])
                                       for mp in kk.bonds()) and (
                                           kk.bond(m, p).order == None
                                           or kk.bond(m, p).p_order == None):
                                    unite.extend([m, p])

        if unite:
            for i3, zop in enumerate(other_list):
                if set(zop).intersection(unite):
                    new_ind.append(i3)
        if len(new_ind) > 1:
            y = []
            new_ind.reverse()
            for x in new_ind:
                y.extend(other_list[x])
                other_list.pop(x)
            other_list.append(y)
        del (ept, new_ind, unite, kk)
#конец объединения
    del (cycles, all_prot_come)  #  хреновая оптимизация

    if 1 < len(other_list):

        #variants_reaction = []
        reactants_to_work = reduce(or_, reaction.reactants)
        product_to_work = reduce(or_, reaction.products)
        list_rc = []

        const_at = atom_re_pr(
            set(reactants_to_work).difference(all_prot).difference(
                cgrs.center_atoms), reactants_to_work, product_to_work)
        const_bond = bonds_re_pr(cgrs.bonds(), const_at.keys())

        prot_atoms = {}
        prot_bonds = {}
        comming_atoms = {}
        comming_bonds = {}
        for big_rc in other_list:

            if all_prot:
                prot_atoms = atom_re_pr(prot_come(big_rc, all_prot, prot_gr),
                                        reactants_to_work, product_to_work)
                prot_bonds = bonds_re_pr(cgrs.bonds(), prot_atoms.keys())

            if all_coming:
                comming_atoms = atom_re_pr(
                    prot_come(big_rc, all_coming, coming_gr),
                    reactants_to_work, product_to_work)
                comming_bonds = bonds_re_pr(cgrs.bonds(), comming_atoms.keys())

            atom_t = atom_re_pr(set(big_rc), reactants_to_work,
                                product_to_work)
            t_bond = bonds_re_pr_t(cgrs.bonds(), atom_t.keys(), all_prot,
                                   all_coming)

            list_rc.append([
                atom_t, prot_atoms, comming_atoms, t_bond, prot_bonds,
                comming_bonds
            ])

        for e, t_rc in enumerate(list_rc):
            for state in list(product([1, 0], repeat=len(list_rc) - 1)):

                new_reactant = MoleculeContainer()
                new_product = MoleculeContainer()
                new_all_bonds_reactants = []
                new_all_bonds_products = []

                add_at(const_at, reactants_to_work, new_reactant)
                add_at(const_at, product_to_work, new_product)

                for x in const_bond.values():
                    new_all_bonds_reactants.append(x['re'])
                    new_all_bonds_products.append(x['pr'])

                for x, y in t_rc[0].items():
                    if y['re']:
                        new_reactant.add_atom(
                            y['re'].copy(),
                            x,
                            charge=reactants_to_work.atom(x).charge)
                    if y['pr']:
                        new_product.add_atom(
                            y['pr'].copy(),
                            x,
                            charge=product_to_work.atom(x).charge)

                for x, y in t_rc[1].items():
                    new_reactant.add_atom(
                        y['re'].copy(),
                        x,
                        charge=reactants_to_work.atom(
                            x).charge)  # атомы уходящей группы

                for x, y in t_rc[2].items():
                    new_product.add_atom(y['pr'].copy(),
                                         x,
                                         charge=product_to_work.atom(
                                             x).charge)  # приходящие атомы

                for x in t_rc[5].values():
                    new_all_bonds_products.append(x['pr'])

                for x in t_rc[3].values():
                    if x['re'][2]:
                        new_all_bonds_reactants.append(x['re'])
                    if x['pr'][2]:
                        new_all_bonds_products.append(x['pr'])

                for x in t_rc[4].values():
                    new_all_bonds_reactants.append(x['re'])

                for s, big_rc in zip(state, list_rc[:e] + list_rc[e + 1:]):
                    if s == 0:

                        for x, y in big_rc[0].items():
                            if y['re']:
                                new_reactant.add_atom(
                                    y['re'].copy(),
                                    x,
                                    charge=reactants_to_work.atom(x).charge)
                                new_product.add_atom(
                                    y['re'].copy(),
                                    x,
                                    charge=reactants_to_work.atom(x).charge)

                        for x, y in big_rc[1].items():
                            new_reactant.add_atom(
                                y['re'].copy(),
                                x,
                                charge=reactants_to_work.atom(x).charge)
                            new_product.add_atom(
                                y['re'].copy(),
                                x,
                                charge=reactants_to_work.atom(x).charge)

                        for x in big_rc[3].values():
                            if x['re'][2]:
                                new_all_bonds_reactants.append(x['re'])
                                new_all_bonds_products.append(x['re'])

                        for x in big_rc[4].values():
                            new_all_bonds_reactants.append(x['re'])
                            new_all_bonds_products.append(x['re'])

                    if s == 1:

                        for x, y in big_rc[0].items():
                            if y['pr']:
                                new_reactant.add_atom(
                                    y['pr'].copy(),
                                    x,
                                    charge=product_to_work.atom(x).charge)
                                new_product.add_atom(
                                    y['pr'].copy(),
                                    x,
                                    charge=product_to_work.atom(x).charge)

                        for x, y in big_rc[2].items():
                            new_reactant.add_atom(
                                y['pr'].copy(),
                                x,
                                charge=product_to_work.atom(x).charge)
                            new_product.add_atom(
                                y['pr'].copy(),
                                x,
                                charge=product_to_work.atom(x).charge)

                        for x in big_rc[3].values():
                            if x['pr'][2]:
                                new_all_bonds_reactants.append(x['pr'])
                                new_all_bonds_products.append(x['pr'])

                        for x in big_rc[5].values():
                            new_all_bonds_reactants.append(x['pr'])
                            new_all_bonds_products.append(x['pr'])

                [new_reactant.add_bond(*x) for x in new_all_bonds_reactants]
                [new_product.add_bond(*x) for x in new_all_bonds_products]
                #   [new_product.add_bond(*x) for x in new_all_bonds_products if not new_product.has_edge(x[0], x[1])]

                new_reaction = ReactionContainer(reactants=(new_reactant, ),
                                                 products=(new_product, ))
                new_reaction.meta.update(reaction.meta)
                # variants_reaction.append(new_reaction)
                yield new_reaction
    else:
        yield reaction
def big_mol(mols):
    to_work = MoleculeContainer()
    for x in mols:
        to_work._node.update(x._node)
        to_work._adj.update(x._adj)
    return to_work