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);
}