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