MoleculeIter::SourceRGroups::SourceRGroups(const MoleculeIter &m) { Array<int> fs; m._at.dump(fs); MultiMap<int, int> rgroup2fragment; RedBlackMap<Fragment, int> fragment2count; for (auto i = 0; i < fs.size(); i++) { auto x = m._parent._fragment_coordinates(i, fs[i]); if (rgroup2fragment.find(x.rgroup, x.fragment)) { int count = fragment2count.at(x); fragment2count.remove(x); fragment2count.insert(x, count + 1); } else { rgroup2fragment.insert(x.rgroup, x.fragment); fragment2count.insert(x, 1); } } const RedBlackSet<int> &rgroups = rgroup2fragment.keys(); for (auto i = rgroups.begin(); i != rgroups.end(); i = rgroups.next(i)) { auto r = rgroups.key(i); RGroup &rgroup = _rgroups.push(); RGroup &source = m._parent._rgroups.getRGroup(r); const RedBlackSet<int> &fs_r = rgroup2fragment[r]; for (auto j = fs_r.begin(); j != fs_r.end(); j = fs_r.next(j)) { auto f = fs_r.key(j); for (auto k = 0; k < fragment2count.at({r,f}); k++) { Molecule *fragment = new Molecule(); fragment->clone(*source.fragments[f], nullptr, nullptr); fragment->removeAttachmentPoints(); rgroup.fragments.add(fragment); } } } }
MoleculeIter::OrderedRGroups::OrderedRGroups(const MoleculeIter &m) { Array<int> fs; m._at.dump(fs); for (auto i = 0; i < fs.size(); i++) { RGroup &rgroup = _rgroups.push(); Molecule *fragment = new Molecule(); fragment->clone(m._parent._fragment(i, fs[i]), nullptr, nullptr); fragment->removeAttachmentPoints(); rgroup.fragments.add(fragment); } }
void LayeredMolecules::constructMolecule(Molecule &molecule, int layer, bool aromatized) const { molecule.clone(const_cast<Molecule&>(_proto), NULL, NULL); molecule.clearXyz(); for (auto i : const_cast<Molecule&>(_proto).edges()) { int order = BOND_ZERO; _bond_masks[BOND_SINGLE][i].get(layer)? order = BOND_SINGLE: 0; _bond_masks[BOND_DOUBLE][i].get(layer)? order = BOND_DOUBLE: 0; _bond_masks[BOND_TRIPLE][i].get(layer)? order = BOND_TRIPLE: 0; molecule.setBondOrder(i, order); } for (auto i : const_cast<Molecule&>(_proto).vertices()) { molecule.setAtomCharge(i, const_cast<Molecule&>(_proto).getAtomCharge(i)); } // Actually I would prefer to aromatize the molecule manually (and much more effective) as far as I have the list of aromatic bonds already. // But I don't have any approprite molecule API to do it effectively... :( if(aromatized) molecule.aromatize(AromaticityOptions()); }
void MoleculeRGroupsComposition::decorate(const Array<int> &fs, Molecule &mol) const { mol.clone(_mol, nullptr, nullptr); for (int i = 0; i < fs.size(); i++) { BaseMolecule &fragment = _fragment(i, fs[i]); int rsite = _rsite2vertex.at(i); int apcount = fragment.attachmentPointCount(); int apoint = fragment.getAttachmentPoint(apcount, 0); Array<int> map; mol.mergeWithMolecule(fragment, &map); int atom = mol.getAtomNumber(map[apoint]); if (mol.mergeAtoms(rsite, map[apoint]) == rsite) { mol.resetAtom(rsite, atom); } } mol.removeAttachmentPoints(); mol.rgroups.clear(); }
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; int tmp; if (_bonds[i].swap) __swap(beg, end, tmp); 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.cis_trans.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.stereocenters.add(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; int tmp; 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]) __swap(subst[1], subst[0], tmp); if (subst[3] != -1 && subst[3] < subst[2]) __swap(subst[3], subst[2], tmp); if (pure_h[0]) { __swap(subst[1], subst[0], tmp); parity = 3 - parity; } if (pure_h[2]) { __swap(subst[2], subst[3], tmp); 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 (int 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 (int 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); } }