in core/indigo-core/molecule/src/cmf_loader.cpp [406:715]
void CmfLoader::loadMolecule(Molecule& mol)
{
int code;
mol.clear();
QS_DEF(Array<int>, cycle_numbers);
QS_DEF(Array<int>, atom_stack);
_atoms.clear();
_bonds.clear();
_pseudo_labels.clear();
_attachments.clear();
cycle_numbers.clear();
atom_stack.clear();
bool first_atom = true;
if (!_getNextCode(code))
return;
bool has_ext_part = false;
/* Main loop */
do
{
_BondDesc* bond = 0;
if (code > CMF_ALPHABET_SIZE)
throw Error("unexpected code");
if (code == CMF_TERMINATOR)
break;
if (code == CMF_EXT)
{
has_ext_part = true;
// Ext part has to be read till CMF_TERMINATOR
break;
}
if (!first_atom)
{
int number;
while (_readCycleNumber(code, number))
{
while (cycle_numbers.size() <= number)
cycle_numbers.push(-1);
if (cycle_numbers[number] >= 0)
throw Error("cycle #%d already in use", number);
cycle_numbers[number] = atom_stack.top();
if (!_getNextCode(code))
break;
}
}
if (code == CMF_SEPARATOR)
{
atom_stack.pop();
first_atom = true;
if (!_getNextCode(code))
break;
continue;
}
if (code == CMF_OPEN_BRACKET)
{
atom_stack.push(atom_stack.top());
if (!_getNextCode(code))
break;
continue;
}
if (code == CMF_CLOSE_BRACKET)
{
atom_stack.pop();
if (!_getNextCode(code))
break;
continue;
}
if (!first_atom)
{
bond = &_bonds.push();
bond->beg = atom_stack.top();
}
if (bond != 0)
{
_readBond(code, *bond);
int number;
if (_readCycleNumber(code, number))
{
if (cycle_numbers[number] < 0)
throw Error("bad cycle number after bond symbol");
bond->end = cycle_numbers[number];
cycle_numbers[number] = -1;
if (!_getNextCode(code))
break;
continue;
}
}
_AtomDesc& atom = _atoms.push();
if (!first_atom)
atom_stack.pop();
atom_stack.push(_atoms.size() - 1);
first_atom = false;
if (bond != 0)
bond->end = _atoms.size() - 1;
memset(&atom, 0, sizeof(_AtomDesc));
atom.hydrogens = -1;
atom.valence = -1;
atom.pseudo_atom_idx = -1;
atom.rsite = false;
if (code > 0 && (code < ELEM_MAX || code == CMF_PSEUDOATOM || code == CMF_RSITE || code == CMF_RSITE_EXT))
{
if (!_readAtom(code, atom, _atoms.size() - 1))
break;
continue;
}
if (!_getNextCode(code))
break;
} while (true);
// if have internal decoder, finish it
/* if (_decoder_obj.get() != 0)
_decoder_obj->finish(); */
/* Reading finished, filling molecule */
int i;
for (i = 0; i < _atoms.size(); i++)
{
mol.addAtom(_atoms[i].label);
if (_atoms[i].pseudo_atom_idx >= 0)
mol.setPseudoAtom(i, _pseudo_labels.at(_atoms[i].pseudo_atom_idx));
if (_atoms[i].rsite_bits > 0)
mol.setRSiteBits(i, _atoms[i].rsite_bits);
mol.setAtomCharge(i, _atoms[i].charge);
mol.setAtomIsotope(i, _atoms[i].isotope);
if (_atoms[i].hydrogens >= 0)
mol.setImplicitH(i, _atoms[i].hydrogens);
mol.setAtomRadical(i, _atoms[i].radical);
if (_atoms[i].highlighted)
mol.highlightAtom(i);
}
for (i = 0; i < _bonds.size(); i++)
{
int type = _bonds[i].type;
int beg = _bonds[i].beg;
int end = _bonds[i].end;
if (_bonds[i].swap)
std::swap(beg, end);
int idx = mol.addBond_Silent(beg, end, type);
if (_bonds[i].in_ring)
mol.setEdgeTopology(idx, TOPOLOGY_RING);
else
mol.setEdgeTopology(idx, TOPOLOGY_CHAIN);
if (_bonds[i].direction != 0)
mol.setBondDirection(idx, _bonds[i].direction);
if (_bonds[i].highlighted)
mol.highlightBond(idx);
}
for (i = 0; i < _attachments.size(); i++)
mol.addAttachmentPoint(_attachments[i].index, _attachments[i].atom);
mol.validateEdgeTopologies();
if (has_ext_part)
_readExtSection(mol);
if (atom_flags != 0)
{
atom_flags->clear();
for (i = 0; i < _atoms.size(); i++)
atom_flags->push(_atoms[i].flags);
}
if (bond_flags != 0)
{
bond_flags->clear();
for (i = 0; i < _bonds.size(); i++)
bond_flags->push(_bonds[i].flags);
}
if (!skip_cistrans)
{
for (i = 0; i < _bonds.size(); i++)
{
if (_bonds[i].cis_trans != 0)
{
int parity = _bonds[i].cis_trans;
if (parity > 0)
mol.cis_trans.setParity(i, _bonds[i].cis_trans);
else
mol.cis_trans.ignore(i);
mol.restoreSubstituents(i);
}
}
}
if (!skip_valence)
{
for (i = 0; i < _atoms.size(); i++)
{
if (_atoms[i].valence >= 0)
mol.setValence(i, _atoms[i].valence);
}
}
if (!skip_stereocenters)
{
for (i = 0; i < _atoms.size(); i++)
{
if (_atoms[i].stereo_type != 0)
mol.addStereocenters(i, _atoms[i].stereo_type, _atoms[i].stereo_group, _atoms[i].stereo_invert_pyramid);
}
}
for (i = 0; i < _atoms.size(); i++)
{
if (_atoms[i].allene_stereo_parity != 0)
{
int left, right, subst[4];
bool pure_h[4];
int parity = _atoms[i].allene_stereo_parity;
if (!MoleculeAlleneStereo::possibleCenter(mol, i, left, right, subst, pure_h))
throw Error("invalid molecule allene stereo marker");
if (subst[1] != -1 && subst[1] < subst[0])
std::swap(subst[1], subst[0]);
if (subst[3] != -1 && subst[3] < subst[2])
std::swap(subst[3], subst[2]);
if (pure_h[0])
{
std::swap(subst[1], subst[0]);
parity = 3 - parity;
}
if (pure_h[2])
{
std::swap(subst[2], subst[3]);
parity = 3 - parity;
}
mol.allene_stereo.add(i, left, right, subst, parity);
}
}
// for loadXyz()
_mol = &mol;
// Check if atom mapping was used
if (has_mapping)
{
// Compute inv_atom_mapping_to_restore
inv_atom_mapping_to_restore.clear_resize(atom_mapping_to_restore.size());
for (i = 0; i < atom_mapping_to_restore.size(); i++)
inv_atom_mapping_to_restore[atom_mapping_to_restore[i]] = i;
// Compute inv_bond_mapping_to_restore
inv_bond_mapping_to_restore.clear_resize(bond_mapping_to_restore.size());
for (i = 0; i < bond_mapping_to_restore.size(); i++)
inv_bond_mapping_to_restore[bond_mapping_to_restore[i]] = i;
QS_DEF(Molecule, tmp);
tmp.makeEdgeSubmolecule(mol, atom_mapping_to_restore, bond_mapping_to_restore, NULL);
mol.clone(tmp, NULL, NULL);
}
}