void ReactionEnumeratorState::_buildMolProduct()

in core/indigo-core/reaction/src/reaction_enumerator_state.cpp [968:1207]


void ReactionEnumeratorState::_buildMolProduct(QueryMolecule& product, Molecule& mol_product, Molecule& uncleaned_fragments, Array<int>& all_forbidden_atoms,
                                               Array<int>& mapping_out)
{
    mol_product.clear();
    mapping_out.clear_resize(product.vertexEnd());
    mapping_out.fffill();

    for (int i = product.vertexBegin(); i != product.vertexEnd(); i = product.vertexNext(i))
    {
        bool has_aam = true, is_default = false;

        int pr_aam = _product_aam_array[i];
        int frags_idx = -1;
        if (pr_aam == 0)
            has_aam = false;
        else
        {
            frags_idx = _fragments_aam_array.find(pr_aam);
            if (frags_idx == -1)
                throw Error("Incorrect AAM");
        }

        int mol_atom_idx = -1;

        if (has_aam && (uncleaned_fragments.getAtomNumber(frags_idx) != product.getAtomNumber(i)) && (product.getAtomNumber(i) != -1))
            is_default = true;

        QueryMolecule::Atom* reactant_atom = _getReactantAtom(pr_aam);

        if ((product.getAtomNumber(i) == -1 && !product.isPseudoAtom(i)) && !is_default && !product.isRSite(i))
        {
            if (!has_aam)
                throw Error("Incorrect AAM");

            if (!product.getAtom(i).possibleValue(QueryMolecule::ATOM_NUMBER, uncleaned_fragments.getAtomNumber(frags_idx)))
                throw Error("product atom's impossible number");
            else
                mol_atom_idx = mol_product.addAtom(uncleaned_fragments.getAtomNumber(frags_idx));
        }
        else
        {
            mol_atom_idx = mol_product.addAtom(product.getAtomNumber(i));

            if (product.isPseudoAtom(i))
                mol_product.setPseudoAtom(i, product.getPseudoAtom(i));
        }

        /* "charge", "radical" or "isotope" parameters have no sense for pseudoatoms */
        if (!product.isPseudoAtom(i) && !(has_aam && uncleaned_fragments.isPseudoAtom(frags_idx)))
        {
            /* Charge copying */
            int reactant_atom_charge = CHARGE_UNKNOWN;
            if (reactant_atom != 0)
                reactant_atom->sureValue(QueryMolecule::ATOM_CHARGE, reactant_atom_charge);

            if ((product.getAtomCharge(i) == CHARGE_UNKNOWN) && (!is_default) && (reactant_atom_charge == product.getAtomCharge(i)))
            {
                if (has_aam)
                {
                    try
                    {
                        mol_product.setAtomCharge(mol_atom_idx, uncleaned_fragments.getAtomCharge(frags_idx));
                    }
                    catch (Element::Error&)
                    {
                    }
                    catch (Molecule::Error&)
                    {
                    }
                }
            }
            else
            {
                int pr_charge = product.getAtomCharge(i);
                mol_product.setAtomCharge(mol_atom_idx, (pr_charge != CHARGE_UNKNOWN ? pr_charge : 0));
            }

            /* Isotope copying*/
            int reactant_atom_isotope = -1;
            if (reactant_atom != 0)
                reactant_atom->sureValue(QueryMolecule::ATOM_ISOTOPE, reactant_atom_isotope);

            if ((product.getAtomIsotope(i) == -1) && (!is_default) && (reactant_atom_isotope == product.getAtomIsotope(i)))
            {
                if (has_aam)
                {
                    try
                    {
                        mol_product.setAtomIsotope(mol_atom_idx, uncleaned_fragments.getAtomIsotope(frags_idx));
                    }
                    catch (Element::Error&)
                    {
                    }
                    catch (Molecule::Error&)
                    {
                    }
                }
            }
            else
            {
                int pr_isotope = product.getAtomIsotope(i);
                mol_product.setAtomIsotope(mol_atom_idx, (pr_isotope != -1 ? pr_isotope : 0));
            }

            /* Radical copying */
            int reactant_atom_radical = -1;
            if (reactant_atom != 0)
                reactant_atom->sureValue(QueryMolecule::ATOM_RADICAL, reactant_atom_radical);

            if ((product.getAtomRadical(i) == -1) && (!is_default) && (reactant_atom_radical == product.getAtomRadical(i)))
            {
                if (has_aam)
                {
                    try
                    {
                        int frag_radical = uncleaned_fragments.getAtomRadical(frags_idx);
                        mol_product.setAtomRadical(mol_atom_idx, frag_radical);
                    }
                    catch (Element::Error&)
                    {
                    }
                    catch (Molecule::Error&)
                    {
                    }
                }
            }
            else
            {
                int pr_radical = product.getAtomRadical(i);
                mol_product.setAtomRadical(mol_atom_idx, (pr_radical != -1 ? pr_radical : 0));
            }
        }

        if (_is_simple_transform && frags_idx == -1)
            throw Error("Incorrect AAM");

        if (_is_simple_transform)
            mol_product.setAtomXyz(mol_atom_idx, uncleaned_fragments.getAtomXyz(frags_idx));
        else
            mol_product.setAtomXyz(mol_atom_idx, product.getAtomXyz(i).x, product.getAtomXyz(i).y, product.getAtomXyz(i).z);

        mapping_out[i] = mol_atom_idx;

        if (frags_idx != -1 && frags_idx < _monomer_forbidden_atoms.size())
            all_forbidden_atoms[mapping_out[i]] += _monomer_forbidden_atoms[frags_idx];
        else
            all_forbidden_atoms[mapping_out[i]] = max_reuse_count;
    }

    for (int i = product.edgeBegin(); i != product.edgeEnd(); i = product.edgeNext(i))
    {
        const Edge& pr_edge = product.getEdge(i);

        if (product.getBondOrder(i) == -1)
        {
            bool has_aam = true;

            int pr_beg_aam = _product_aam_array[pr_edge.beg];
            int pr_end_aam = _product_aam_array[pr_edge.end];
            int frags_beg = -1, frags_end = -1;

            if (pr_beg_aam != 0)
            {
                frags_beg = _fragments_aam_array.find(pr_beg_aam);
                if (frags_beg == -1)
                    throw Error("Incorrect AAM");
            }

            if (pr_end_aam != 0)
            {
                frags_end = _fragments_aam_array.find(pr_end_aam);
                if (frags_end == -1)
                    throw Error("Incorrect AAM");
            }

            if (frags_beg != -1 && frags_end == -1)
            {
                if (product.isRSite(pr_edge.end))
                {
                    frags_end = _att_points[pr_edge.end][0];
                    if (uncleaned_fragments.findEdgeIndex(frags_beg, frags_end) == -1)
                        frags_end = _att_points[pr_edge.end][1];
                }
            }
            else if (frags_beg == -1 && frags_end != -1)
            {
                if (product.isRSite(pr_edge.beg))
                {
                    frags_beg = _att_points[pr_edge.beg][0];
                    if (uncleaned_fragments.findEdgeIndex(frags_beg, frags_end) == -1)
                        frags_beg = _att_points[pr_edge.beg][1];
                }
            }

            int frags_bond_idx = -1;
            if ((frags_beg != -1) && (frags_end != -1))
                frags_bond_idx = uncleaned_fragments.findEdgeIndex(frags_beg, frags_end);

            if (frags_bond_idx == -1)
                has_aam = false;

            if (has_aam)
            {
                mol_product.addBond(mapping_out[pr_edge.beg], mapping_out[pr_edge.end], uncleaned_fragments.getBondOrder(frags_bond_idx));
            }
            else
            {
                // If there is no information about this bond in smarts
                // QueryMolecule::Atom& q_pr_beg = product.getAtom(pr_edge.beg);
                // QueryMolecule::Atom& q_pr_end = product.getAtom(pr_edge.end);

                // int beg_value, end_value;
                bool can_be_aromatic = product.getBond(i).possibleValue(QueryMolecule::BOND_ORDER, BOND_AROMATIC);
                bool can_be_single = product.getBond(i).possibleValue(QueryMolecule::BOND_ORDER, BOND_SINGLE);
                bool can_be_double = product.getBond(i).possibleValue(QueryMolecule::BOND_ORDER, BOND_DOUBLE);
                bool can_be_triple = product.getBond(i).possibleValue(QueryMolecule::BOND_ORDER, BOND_TRIPLE);
                if ((can_be_aromatic && can_be_single && !can_be_double && !can_be_triple)/* &&
                   (q_pr_beg.sureValue(QueryMolecule::ATOM_AROMATICITY, beg_value) &&
                    q_pr_end.sureValue(QueryMolecule::ATOM_AROMATICITY, end_value))
                    && (beg_value == ATOM_AROMATIC) && (end_value == ATOM_AROMATIC)*/)
                {
                    mol_product.addBond(mapping_out[pr_edge.beg], mapping_out[pr_edge.end], BOND_AROMATIC);
                }
                else if ((!can_be_aromatic && can_be_single && !can_be_double && !can_be_triple))
                {
                    mol_product.addBond(mapping_out[pr_edge.beg], mapping_out[pr_edge.end], BOND_SINGLE);
                }
                else
                    throw Error("There is no information about products bond #%d", i);
            }
        }
        else
            mol_product.addBond(mapping_out[pr_edge.beg], mapping_out[pr_edge.end], product.getBondOrder(i));
    }

    mol_product.buildOnSubmoleculeStereocenters(product, mapping_out.ptr());
    mol_product.buildOnSubmoleculeCisTrans(product, mapping_out.ptr());

    mol_product.mergeSGroupsWithSubmolecule(product, mapping_out);
}