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();
}
Example #5
0
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);

   }
}