Hello,

some time ago I've developed code to un-/serialize OBMol objects to binary, 
which is used in pgchem and mychem. The speed increase of using this vs. SMILES 
input are substantial (about 5x) and for molecules without stereochemistry it 
is working as expected.

But with stereochemistry there are differences when matching molecules, 
compared to SMILES input: 
http://theplateisbad.blogspot.com/2011/12/first-light.html

So, my code is obviously missing something. It would be great if somebody could 
tell me, which information is missing from my code that has to be included in 
the serialization regarding stereochemistry?

Best regards,

Ernst-Georg
bool unserializeOBMol(OBBase* pOb, const char *serializedInput)
  {
    OBMol* pmol = pOb->CastAndClear<OBMol>();
    map<OBAtom*,OBChiralData*> _mapcd;

    //Define some references so we can use the old parameter names
    OBMol &mol = *pmol;
    _mapcd.clear();
    bool chiralWatch=false;

    //stringstream errorMsg;
    //string clearError;

    // Allows addition of further disconnected atoms to an existing molecule
    //int offset = mol.NumAtoms();

    int i,natoms,nbonds;
    //string r1,r2;

    unsigned int *intptr = (unsigned int*) serializedInput;

    //cout << *intptr << endl;

    //mol.SetDimension(*intptr);

    //intptr++;

    natoms = *intptr;

    intptr++;

    nbonds = *intptr;

    intptr++;

    //cout << mol.GetDimension() << natoms << nbonds << endl;

    _ATOM *atomptr = (_ATOM*) intptr;

    //mol.BeginModify();

        mol.ReserveAtoms(natoms);

        OBAtom atom;
        int stereo;

        for (i = 1;i <= natoms;i++) {

        //cout << atomptr->atomicnum << " " << atomptr->isotope << " " << 
atomptr->idx << " " << atomptr->radical << " " << atomptr->stereo << " " << 
atomptr->formalcharge << endl;

         atom.SetIdx(atomptr->idx);

         atom.SetHyb(atomptr->hybridization);

          //int iso=0;
          atom.SetAtomicNum((int) atomptr->atomicnum);
          //iso=atomptr->isotope;

          //if(iso)
            atom.SetIsotope((unsigned int) atomptr->isotope);

          atom.SetFormalCharge((int) atomptr->formalcharge);

         stereo = atomptr->stereo;

              if (stereo == 2)
                {
                  chiralWatch=true;
                  atom.SetAntiClockwiseStereo();
                }
              else if (stereo == 1)
                {
                  chiralWatch=true;
                  atom.SetClockwiseStereo();
                }
              else if(stereo == 3)
                {
                  chiralWatch=true;
                  atom.SetChiral();
                }

          atom.SetSpinMultiplicity((short) atomptr->spinmultiplicity);

          if(atomptr->aromatic != 0) atom.SetAromatic();

          if (!mol.AddAtom(atom)) return (false);

          if(chiralWatch)  // fill the map with data for each chiral atom
            _mapcd[mol.GetAtom(i)] = new OBChiralData;
          atom.Clear();
          atomptr++;
        }

        _BOND *bondptr = (_BOND*) atomptr;

        unsigned int start,end,order,flags;

        for (i = 0;i < nbonds;i++) {
          flags = 0;

          start = bondptr->beginidx;
          end = bondptr->endidx;
          order = (int) bondptr->order;

          if (start == 0 || end == 0 || order == 0 ||
              start > natoms || end > natoms)
            return false;

          order = (unsigned int) (order == 4) ? 5 : order;

          stereo = bondptr->stereo;

          //cout << atomptr->atomicnum << " " << atomptr->isotope << " " << 
atomptr->idx << " " << atomptr->radical << " " << atomptr->stereo << " " << 
atomptr->formalcharge << endl;

            if (stereo) {
              if (stereo == 1) flags |= OB_WEDGE_BOND;
              if (stereo == 6) flags |= OB_HASH_BOND;
            }

          if(bondptr->aromatic != 0) flags |= OB_AROMATIC_BOND;

          //flags |= bondptr->flags;

          if (!mol.AddBond(start,end,order,flags)) return (false);

          // after adding a bond to atom # "start+offset"
          // search to see if atom is bonded to a chiral atom
          // HERE
          map<OBAtom*,OBChiralData*>::iterator ChiralSearch;
          ChiralSearch = _mapcd.find(mol.GetAtom(start));
          if (ChiralSearch!=_mapcd.end())
            {
              (ChiralSearch->second)->AddAtomRef(end, input);
            }
          // after adding a bond to atom # "end + offset"
          // search to see if atom is bonded to a chiral atom
          ChiralSearch = _mapcd.find(mol.GetAtom(end));
          if (ChiralSearch!=_mapcd.end())
            {
              (ChiralSearch->second)->AddAtomRef(start, input);
            }
         bondptr++;
        }

    //mol.AssignSpinMultiplicity();

    //mol.EndModify();

    intptr = (unsigned int*) bondptr;

    //NE add the OBChiralData stored inside the _mapcd to the atoms now after 
end
    // modify so they don't get lost.
    if(_mapcd.size()>0)
      {
        OBAtom* atomptr;
        OBChiralData* cd;
        map<OBAtom*,OBChiralData*>::iterator ChiralSearch;
        
for(ChiralSearch=_mapcd.begin();ChiralSearch!=_mapcd.end();ChiralSearch++)
          {
            atomptr=ChiralSearch->first;
            cd=ChiralSearch->second;
            atomptr->SetData(cd);
          }
      }

    //mol.SetFlags(*(int*)intptr);

    mol.SetAromaticPerceived();
    mol.SetKekulePerceived();
    //mol.FindChiralCenters();
    mol.SetChiralityPerceived();

    return(true);
  }

char *serializeOBMol(char* smiles) {
      OBMol mol;
      OBConversion conv;
      string tmpStr (smiles);
      istringstream molstream (tmpStr);
      conv.SetInFormat("SMI");
      conv.Read (&mol, &molstream);
      if(mol.Empty()) return NULL;
      unsigned int numatoms = mol.NumAtoms();
      unsigned int numbonds = mol.NumBonds();
      unsigned int 
totalsize=(numatoms*sizeof(_ATOM))+(numbonds*sizeof(_BOND))+(3*sizeof(unsigned 
int));
      char *retval = new char[totalsize];
      int  stereo;
      _ATOM *atomptr;
      _BOND *bondptr;

      //mol.Kekulize();

      memset(retval,0x0,totalsize);

      unsigned int *uintptr = (unsigned int*) retval;

      *uintptr = totalsize-sizeof(unsigned int);

      uintptr++;

      //*uintptr = (unsigned int) mol.GetDimension();

      //uintptr++;

      *uintptr = numatoms;

      uintptr++;

      *uintptr = numbonds;

      uintptr++;

      atomptr = (_ATOM*) uintptr;

      //cout << mol.GetDimension() << numatoms << numbonds << endl;


        FOR_ATOMS_OF_MOL(atom, mol) {
            stereo = 0;
            atomptr->idx = atom->GetIdx();
            atomptr->hybridization = atom->GetHyb();
            atomptr->atomicnum = (unsigned char) atom->GetAtomicNum();
            atomptr->formalcharge = (char) atom->GetFormalCharge();
            atomptr->isotope = (unsigned short) atom->GetIsotope();

            //cout << atom->GetFormalCharge() << " " << atom->GetIsotope() << " 
" << atom->GetSpinMultiplicity() << endl;

            if(atom->IsClockwise()) stereo = 1;
            else if (atom->IsAntiClockwise()) stereo = 2;
            else if (atom->IsChiral()) stereo = 3;
            atomptr->stereo = stereo;
            atomptr->spinmultiplicity = (unsigned char) 
atom->GetSpinMultiplicity();
            atomptr->aromatic = atom->IsAromatic() ? 1 : 0;
            //atomptr->flags = atom->GetFlag();
            atomptr++;
            }


       bondptr = (_BOND*) atomptr;

       if(numbonds>0) {
         FOR_BONDS_OF_MOL(bond, mol) {
             stereo = 0;
             bondptr->beginidx = bond->GetBeginAtomIdx();
             bondptr->endidx = bond->GetEndAtomIdx();
             bondptr->order = (unsigned char) bond->GetBondOrder();
             if(bond->IsWedge()) stereo = 1;
             else if(bond->IsHash()) stereo = 6;
             bondptr->stereo = stereo;
             bondptr->aromatic = bond->IsAromatic() ? 1 : 0;
             //bondptr->flags = bond->GetFlags();
             bondptr++;
             }
         }

      //int *intptr = (int*) bondptr;

      //*intptr = mol.GetFlags();

      return retval;
  }
------------------------------------------------------------------------------
Cloud Services Checklist: Pricing and Packaging Optimization
This white paper is intended to serve as a reference, checklist and point of 
discussion for anyone considering optimizing the pricing and packaging model 
of a cloud services business. Read Now!
http://www.accelacomm.com/jaw/sfnl/114/51491232/
_______________________________________________
OpenBabel-Devel mailing list
OpenBabel-Devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openbabel-devel

Reply via email to