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