unsigned int OBRing::GetRootAtom() { vector<int>::iterator i; OBMol *mol = (OBMol*)GetParent(); //if (!IsAromatic()) // return 0; if (Size() == 6) for (i = _path.begin();i != _path.end();++i) if (mol->GetAtom(*i)->GetAtomicNum() != OBElements::Carbon) return (*i); if (Size() == 5) for (i = _path.begin();i != _path.end();++i) { OBAtom *atom = mol->GetAtom(*i); switch (atom->GetAtomicNum()) { case OBElements::Sulfur: if (atom->GetValence() == 2) return (*i); break; case OBElements::Oxygen: if (atom->GetValence() == 2) return (*i); break; case OBElements::Nitrogen: if (atom->BOSum() == atom->GetValence()) return (*i); break; } } return 0; }
unsigned int OBRing::GetRootAtom() { vector<int>::iterator i; OBMol *mol = (OBMol*)GetParent(); //if (!IsAromatic()) // return 0; if (Size() == 6) for (i = _path.begin();i != _path.end();++i) if (!(mol->GetAtom(*i))->IsCarbon()) return (*i); if (Size() == 5) for (i = _path.begin();i != _path.end();++i) { OBAtom *atom = mol->GetAtom(*i); if (atom->IsSulfur() && (atom->GetValence() == 2)) return (*i); if (atom->IsOxygen() && (atom->GetValence() == 2)) return (*i); if (atom->IsNitrogen() && (atom->BOSum() == atom->GetValence())) return (*i); } return 0; }
void OBAtomTyper::AssignImplicitValence(OBMol &mol) { // FF Make sure that valence has not been perceived if(mol.HasImplicitValencePerceived()) return; if (!_init) Init(); mol.SetImplicitValencePerceived(); obErrorLog.ThrowError(__FUNCTION__, "Ran OpenBabel::AssignImplicitValence", obAuditMsg); // FF Ensure that the aromatic typer will not be called int oldflags = mol.GetFlags(); // save the current state flags mol.SetAromaticPerceived(); // and set the aromatic perceived flag on OBAtom *atom; vector<OBAtom*>::iterator k; for (atom = mol.BeginAtom(k);atom;atom = mol.NextAtom(k)) atom->SetImplicitValence(atom->GetValence()); vector<vector<int> >::iterator j; vector<pair<OBSmartsPattern*,int> >::iterator i; for (i = _vimpval.begin();i != _vimpval.end();++i) if (i->first->Match(mol)) { _mlist = i->first->GetMapList(); for (j = _mlist.begin();j != _mlist.end();++j) mol.GetAtom((*j)[0])->SetImplicitValence(i->second); } if (!mol.HasAromaticCorrected()) CorrectAromaticNitrogens(mol); for (atom = mol.BeginAtom(k);atom;atom = mol.NextAtom(k)) { if (atom->GetImplicitValence() < atom->GetValence()) atom->SetImplicitValence(atom->GetValence()); } // FF Come back to the initial flags mol.SetFlags(oldflags); return; }
bool WriteHIN(ostream &ofs,OBMol &mol) { unsigned int i, file_num = 1; string str,str1; char buffer[BUFF_SIZE]; OBAtom *atom; OBBond *bond; vector<OBEdgeBase*>::iterator j; char bond_char; ofs << "mol " << file_num << " " << mol.GetTitle() << endl;; for(i = 1;i <= mol.NumAtoms(); i++) { atom = mol.GetAtom(i); sprintf(buffer,"atom %d - %-3s ** - %8.5f %8.5f %8.5f %8.5f %d ", i, etab.GetSymbol(atom->GetAtomicNum()), atom->GetPartialCharge(), atom->GetX(), atom->GetY(), atom->GetZ(), atom->GetValence()); ofs << buffer; for (bond = atom->BeginBond(j); bond; bond = atom->NextBond(j)) { switch(bond->GetBO()) { case 1 : bond_char = 's'; break; case 2 : bond_char = 'd'; break; case 3 : bond_char = 't'; break; case 5 : bond_char = 'a'; break; default: bond_char = 's'; break; } sprintf(buffer,"%d %c ", (bond->GetNbrAtom(atom))->GetIdx(), bond_char); ofs << buffer; } ofs << endl; } ofs << "endmol " << file_num << endl; return(true); }
bool PDBFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv) { OBMol* pmol = dynamic_cast<OBMol*>(pOb); if(pmol==NULL) return false; //Define some references so we can use the old parameter names ostream &ofs = *pConv->GetOutStream(); OBMol &mol = *pmol; unsigned int i; char buffer[BUFF_SIZE]; char type_name[10], padded_name[10]; char the_res[10]; char the_chain = ' '; const char *element_name; int res_num; bool het=true; int model_num = 0; if (!pConv->IsLast() || pConv->GetOutputIndex() > 1) { // More than one molecule record model_num = pConv->GetOutputIndex(); // MODEL 1-based index snprintf(buffer, BUFF_SIZE, "MODEL %8d", model_num); ofs << buffer << endl; } // write back all fields (REMARKS, HELIX, SHEET, SITE, ...) bool compndWritten = false; bool authorWritten = false; std::vector<OBGenericData*> pairData = mol.GetAllData(OBGenericDataType::PairData); for (std::vector<OBGenericData*>::iterator data = pairData.begin(); data != pairData.end(); ++data) { OBPairData *pd = static_cast<OBPairData*>(*data); string attr = pd->GetAttribute(); // filter to make sure we are writing pdb fields only if (attr != "HEADER" && attr != "OBSLTE" && attr != "TITLE" && attr != "SPLIT" && attr != "CAVEAT" && attr != "COMPND" && attr != "SOURCE" && attr != "KEYWDS" && attr != "EXPDTA" && attr != "NUMMDL" && attr != "MDLTYP" && attr != "AUTHOR" && attr != "REVDAT" && attr != "SPRSDE" && attr != "JRNL" && attr != "REMARK" && attr != "DBREF" && attr != "DBREF1" && attr != "DBREF2" && attr != "SEQADV" && attr != "SEQRES" && attr != "MODRES" && attr != "HET" && attr != "HETNAM" && attr != "HETSYN" && attr != "FORMUL" && attr != "HELIX" && attr != "SHEET" && attr != "SSBOND" && attr != "LINK" && attr != "CISPEP" && attr != "SITE" && attr != "ORIGX1" && attr != "ORIGX2" && attr != "ORIGX3" && attr != "SCALE1" && attr != "SCALE2" && attr != "SCALE3" && attr != "MATRIX1" && attr != "MATRIX2" && attr != "MATRIX3" && attr != "MODEL") continue; if (attr == "COMPND") compndWritten = true; if (attr == "AUTHOR") authorWritten = true; // compute spacing needed. HELIX, SITE, HET, ... are trimmed when reading int nSpacing = 6 - attr.size(); for (int i = 0; i < nSpacing; ++i) attr += " "; std::string lines = pd->GetValue(); string::size_type last = 0; string::size_type pos = lines.find('\n'); while (last != string::npos) { string line = lines.substr(last, pos - last); if (pos == string::npos) last = string::npos; else last = pos + 1; pos = lines.find('\n', last); ofs << attr << line << endl; } } if (!compndWritten) { if (strlen(mol.GetTitle()) > 0) snprintf(buffer, BUFF_SIZE, "COMPND %s ",mol.GetTitle()); else snprintf(buffer, BUFF_SIZE, "COMPND UNNAMED"); ofs << buffer << endl; } if (!authorWritten) { snprintf(buffer, BUFF_SIZE, "AUTHOR GENERATED BY OPEN BABEL %s",BABEL_VERSION); ofs << buffer << endl; } // Write CRYST1 record, containing unit cell parameters, space group // and Z value (supposed to be 1) if (pmol->HasData(OBGenericDataType::UnitCell)) { OBUnitCell *pUC = (OBUnitCell*)pmol->GetData(OBGenericDataType::UnitCell); if(pUC->GetSpaceGroup()){ string tmpHM=pUC->GetSpaceGroup()->GetHMName(); // Do we have an extended HM symbol, with origin choice as ":1" or ":2" ? If so, remove it. size_t n=tmpHM.find(":"); if(n!=string::npos) tmpHM=tmpHM.substr(0,n); snprintf(buffer, BUFF_SIZE, "CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11s 1", pUC->GetA(), pUC->GetB(), pUC->GetC(), pUC->GetAlpha(), pUC->GetBeta(), pUC->GetGamma(), tmpHM.c_str()); } else snprintf(buffer, BUFF_SIZE, "CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11s 1", pUC->GetA(), pUC->GetB(), pUC->GetC(), pUC->GetAlpha(), pUC->GetBeta(), pUC->GetGamma(), "P1"); ofs << buffer << endl; } // before we write any records, we should check to see if any coord < -1000 // which will cause errors in the formatting double minX, minY, minZ; minX = minY = minZ = -999.0f; FOR_ATOMS_OF_MOL(a, mol) { if (a->GetX() < minX) minX = a->GetX(); if (a->GetY() < minY) minY = a->GetY(); if (a->GetZ() < minZ) minZ = a->GetZ(); } vector3 transV = VZero; if (minX < -999.0) transV.SetX(-1.0*minX - 900.0); if (minY < -999.0) transV.SetY(-1.0*minY - 900.0); if (minZ < -999.0) transV.SetZ(-1.0*minZ - 900.0); // if minX, minY, or minZ was never changed, shift will be 0.0f // otherwise, move enough so that smallest coord is > -999.0f mol.Translate(transV); OBAtom *atom; OBResidue *res; for (i = 1; i <= mol.NumAtoms(); i++) { atom = mol.GetAtom(i); strncpy(type_name, etab.GetSymbol(atom->GetAtomicNum()), sizeof(type_name)); type_name[sizeof(type_name) - 1] = '\0'; //two char. elements are on position 13 and 14 one char. start at 14 if (strlen(type_name) > 1) type_name[1] = toupper(type_name[1]); else { char tmp[10]; strncpy(tmp, type_name, 9); // make sure to null-terminate tmp snprintf(type_name, sizeof(type_name), " %-3s", tmp); } if ( (res = atom->GetResidue()) != 0 ) { het = res->IsHetAtom(atom); snprintf(the_res,4,"%s",(char*)res->GetName().c_str()); the_res[4] = '\0'; snprintf(type_name,5,"%s",(char*)res->GetAtomID(atom).c_str()); the_chain = res->GetChain(); //two char. elements are on position 13 and 14 one char. start at 14 if (strlen(etab.GetSymbol(atom->GetAtomicNum())) == 1) { if (strlen(type_name) < 4) { char tmp[10]; strncpy(tmp, type_name, 9); // make sure to null-terminate tmp snprintf(padded_name, sizeof(padded_name), " %-3s", tmp); strncpy(type_name,padded_name,4); type_name[4] = '\0'; } else { /* type_name[4] = type_name[3]; type_name[3] = type_name[2]; type_name[2] = type_name[1]; type_name[1] = type_name[0]; type_name[0] = type_name[4]; */ type_name[4] = '\0'; } } res_num = res->GetNum(); } else { strcpy(the_res,"UNK"); the_res[3] = '\0'; snprintf(padded_name,sizeof(padded_name), "%s",type_name); strncpy(type_name,padded_name,4); type_name[4] = '\0'; res_num = 1; } element_name = etab.GetSymbol(atom->GetAtomicNum()); int charge = atom->GetFormalCharge(); char scharge[3] = { ' ', ' ', '\0' }; if(0 != charge) { snprintf(scharge, 3, "%+d", charge); char tmp = scharge[1]; scharge[1] = scharge[0]; scharge[0] = tmp; } snprintf(buffer, BUFF_SIZE, "%s%5d %-4s %-3s %c%4d %8.3f%8.3f%8.3f 1.00 0.00 %2s%2s\n", het?"HETATM":"ATOM ", i, type_name, the_res, the_chain, res_num, atom->GetX(), atom->GetY(), atom->GetZ(), element_name, scharge); ofs << buffer; } OBAtom *nbr; vector<OBBond*>::iterator k; for (i = 1; i <= mol.NumAtoms(); i ++) { atom = mol.GetAtom(i); if (atom->GetValence() == 0) continue; // no need to write a CONECT record -- no bonds snprintf(buffer, BUFF_SIZE, "CONECT%5d", i); ofs << buffer; // Write out up to 4 real bonds per line PR#1711154 int currentValence = 0; for (nbr = atom->BeginNbrAtom(k);nbr;nbr = atom->NextNbrAtom(k)) { snprintf(buffer, BUFF_SIZE, "%5d", nbr->GetIdx()); ofs << buffer; if (++currentValence % 4 == 0) { // Add the trailing space to finish this record ofs << " \n"; // write the start of a new CONECT record snprintf(buffer, BUFF_SIZE, "CONECT%5d", i); ofs << buffer; } } // Add trailing spaces int remainingValence = atom->GetValence() % 4; for (int count = 0; count < (4 - remainingValence); count++) { snprintf(buffer, BUFF_SIZE, " "); ofs << buffer; } ofs << " \n"; } snprintf(buffer, BUFF_SIZE, "MASTER 0 0 0 0 0 0 0 0 "); ofs << buffer; snprintf(buffer, BUFF_SIZE, "%4d 0 %4d 0\n",mol.NumAtoms(),mol.NumAtoms()); ofs << buffer; ofs << "END\n"; if (model_num) { ofs << "ENDMDL" << endl; } return(true); }
bool BGFFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv) { OBMol* pmol = dynamic_cast<OBMol*>(pOb); if(pmol==NULL) return false; //Define some references so we can use the old parameter names ostream &ofs = *pConv->GetOutStream(); OBMol &mol = *pmol; vector<OBAtom*>::iterator i; int max_val; OBAtom *atom; char buffer[BUFF_SIZE]; char elmnt_typ[8], dreid_typ[8], atm_sym[16], max_val_str[8]; mol.Kekulize(); ofs << "BIOGRF 200\n"; snprintf(buffer, BUFF_SIZE, "DESCRP %s\n",mol.GetTitle()); ofs << buffer; snprintf(buffer, BUFF_SIZE, "REMARK BGF file created by Open Babel %s\n",BABEL_VERSION); ofs << "FORCEFIELD DREIDING \n"; // write unit cell if available if (mol.HasData(OBGenericDataType::UnitCell)) { OBUnitCell *uc = (OBUnitCell*)mol.GetData(OBGenericDataType::UnitCell); // e.g. CRYSTX 49.30287 49.23010 25.45631 90.00008 89.99995 57.10041 snprintf(buffer, BUFF_SIZE, "CRYSTX%12.5f%12.5f%12.5f%12.5f%12.5f%12.5f", uc->GetA(), uc->GetB(), uc->GetC(), uc->GetAlpha() , uc->GetBeta(), uc->GetGamma()); ofs << buffer << "\n"; } ofs << "FORMAT ATOM (a6,1x,i5,1x,a5,1x,a3,1x,a1,1x,a5,3f10.5,1x,a5,i3,i2,1x,f8.5)\n"; ttab.SetFromType("INT"); for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) { strncpy(elmnt_typ,etab.GetSymbol(atom->GetAtomicNum()), 7); // make sure to null-terminate elmnt_typ[sizeof(elmnt_typ) - 1] = '0'; ToUpper(elmnt_typ); ttab.SetToType("DRE"); ttab.Translate(dreid_typ,atom->GetType()); ttab.SetToType("HAD"); ttab.Translate(max_val_str,atom->GetType()); max_val = atoi(max_val_str); if (max_val == 0) max_val = 1; snprintf(atm_sym,16,"%s%d",elmnt_typ,atom->GetIdx()); snprintf(buffer,BUFF_SIZE,"%6s %5d %-5s %3s %1s %5s%10.5f%10.5f%10.5f %-5s%3d%2d %8.5f\n", "HETATM", atom->GetIdx(), atm_sym, "RES", "A", "444", atom->GetX(), atom->GetY(), atom->GetZ(), dreid_typ, max_val, 0, atom->GetPartialCharge()); ofs << buffer; } ofs<< "FORMAT CONECT (a6,12i6)\n\n"; OBAtom *nbr; vector<OBBond*>::iterator j; for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) if (atom->GetValence()) { snprintf(buffer,BUFF_SIZE,"CONECT%6d",atom->GetIdx()); ofs << buffer; for (nbr = atom->BeginNbrAtom(j);nbr;nbr = atom->NextNbrAtom(j)) { snprintf(buffer,BUFF_SIZE,"%6d",nbr->GetIdx()); ofs << buffer; } ofs << endl; snprintf(buffer,BUFF_SIZE,"ORDER %6d",atom->GetIdx()); ofs << buffer; for (nbr = atom->BeginNbrAtom(j);nbr;nbr = atom->NextNbrAtom(j)) { snprintf(buffer,BUFF_SIZE,"%6d",(*j)->GetBO()); ofs << buffer; } ofs << endl; } ofs << "END" << endl; return(true); }
bool OBDepict::DrawMolecule(OBMol *mol) { if (!d->painter) return false; d->mol = mol; double width=0.0, height=0.0; OBAtom *atom; OBBondIterator j; OBAtomIterator i; if(mol->NumAtoms()>0) { // scale bond lengths double bondLengthSum = 0.0; for (OBBond *bond = mol->BeginBond(j); bond; bond = mol->NextBond(j)) bondLengthSum += bond->GetLength(); const double averageBondLength = bondLengthSum / mol->NumBonds(); const double f = mol->NumBonds() ? d->bondLength / averageBondLength : 1.0; for (atom = mol->BeginAtom(i); atom; atom = mol->NextAtom(i)) atom->SetVector(atom->GetX() * f, atom->GetY() * f, 0.0); // find min/max values double min_x, max_x; double min_y, max_y; atom = mol->BeginAtom(i); min_x = max_x = atom->GetX(); min_y = max_y = atom->GetY(); for (atom = mol->NextAtom(i); atom; atom = mol->NextAtom(i)) { min_x = std::min(min_x, atom->GetX()); max_x = std::max(max_x, atom->GetX()); min_y = std::min(min_y, atom->GetY()); max_y = std::max(max_y, atom->GetY()); } const double margin = 40.0; // translate all atoms so the bottom-left atom is at margin,margin for (atom = mol->BeginAtom(i); atom; atom = mol->NextAtom(i)) atom->SetVector(atom->GetX() - min_x + margin, atom->GetY() - min_y + margin, 0.0); width = max_x - min_x + 2*margin; height = max_y - min_y + 2*margin; //d->painter->SetPenWidth(d->penWidth); //d->painter->SetPenColor(d->pen)); //d->painter->SetFillColor(OBColor("black")); } d->painter->NewCanvas(width, height); // draw bonds if(d->options & genWedgeHash) d->SetWedgeAndHash(mol); for (OBBond *bond = mol->BeginBond(j); bond; bond = mol->NextBond(j)) { OBAtom *begin = bond->GetBeginAtom(); OBAtom *end = bond->GetEndAtom(); if((d->options & internalColor) && bond->HasData("color")) d->painter->SetPenColor(OBColor(bond->GetData("color")->GetValue())); else d->painter->SetPenColor(d->bondColor); if (bond->IsWedge()) { d->DrawWedge(begin, end); } else if (bond->IsHash()) { d->DrawHash(begin, end); } else if (!bond->IsInRing()) { d->DrawSimpleBond(begin, end, bond->GetBO()); } } // draw ring bonds std::vector<OBRing*> rings(mol->GetSSSR()); OBBitVec drawnBonds; for (std::vector<OBRing*>::iterator k = rings.begin(); k != rings.end(); ++k) { OBRing *ring = *k; std::vector<int> indexes = ring->_path; vector3 center(VZero); for (std::vector<int>::iterator l = indexes.begin(); l != indexes.end(); ++l) { center += mol->GetAtom(*l)->GetVector(); } center /= indexes.size(); for (unsigned int l = 0; l < indexes.size(); ++l) { OBAtom *begin = mol->GetAtom(indexes[l]); OBAtom *end; if (l+1 < indexes.size()) end = mol->GetAtom(indexes[l+1]); else end = mol->GetAtom(indexes[0]); OBBond *ringBond = mol->GetBond(begin, end); if (drawnBonds.BitIsSet(ringBond->GetId())) continue; if((d->options & internalColor) && ringBond->HasData("color")) d->painter->SetPenColor(OBColor(ringBond->GetData("color")->GetValue())); else d->painter->SetPenColor(d->bondColor); d->DrawRingBond(begin, end, center, ringBond->GetBO()); drawnBonds.SetBitOn(ringBond->GetId()); } } // draw atom labels for (atom = mol->BeginAtom(i); atom; atom = mol->NextAtom(i)) { double x = atom->GetX(); double y = atom->GetY(); int alignment = GetLabelAlignment(atom); bool rightAligned = false; switch (alignment) { case TopRight: case CenterRight: case BottomRight: rightAligned = true; default: break; } if((d->options & internalColor) && atom->HasData("color")) d->painter->SetPenColor(OBColor(atom->GetData("color")->GetValue())); else if(d->options & bwAtoms) d->painter->SetPenColor(d->bondColor); else d->painter->SetPenColor(OBColor(etab.GetRGB(atom->GetAtomicNum()))); //charge and radical int charge = atom->GetFormalCharge(); int spin = atom->GetSpinMultiplicity(); if(charge || spin) { OBFontMetrics metrics = d->painter->GetFontMetrics("N"); double yoffset = d->HasLabel(atom) ? 0.4 * metrics.height : 0.0; switch (GetLabelAlignment(atom)) { case TopCenter: case TopRight: case TopLeft: case CenterLeft: case CenterRight: yoffset = - 1.2 * metrics.height; } stringstream ss; if(charge) { if(abs(charge)!=1) ss << abs(charge); ss << (charge>0 ? "+" : "-") ; } if(spin) { ss << (spin==2 ? "." : ".."); yoffset += 0.5 * metrics.height; } if(spin || charge<0) d->painter->SetFontSize(2 * metrics.fontSize); d->painter->DrawText(x-0.4*metrics.width, y-yoffset, ss.str()); d->painter->SetFontSize(metrics.fontSize);//restore } if (atom->IsCarbon()) { if(!(d->options & drawAllC)) { if (atom->GetValence() > 1) continue; if ((atom->GetValence() == 1) && !(d->options & drawTermC))//!d->drawTerminalC) continue; } } stringstream ss; AliasData* ad = NULL; if(d->aliasMode && atom->HasData(AliasDataType)) ad = static_cast<AliasData*>(atom->GetData(AliasDataType)); //For unexpanded aliases use appropriate form of alias instead of element symbol, Hs, etc if(ad && !ad->IsExpanded()) { ss <<ad->GetAlias(rightAligned); OBColor aliasColor = !ad->GetColor().empty() ? ad->GetColor() : d->bondColor; d->painter->SetPenColor(aliasColor); } else { const char* atomSymbol; if(atom->IsHydrogen() && atom->GetIsotope()>1) atomSymbol = atom->GetIsotope()==2 ? "D" : "T"; else atomSymbol = etab.GetSymbol(atom->GetAtomicNum()); unsigned int hCount = atom->ImplicitHydrogenCount(); // rightAligned: // false CH3 // true H3C if (hCount && rightAligned) ss << "H"; if ((hCount > 1) && rightAligned) ss << hCount; ss << atomSymbol; if (hCount && !rightAligned) ss << "H"; if ((hCount > 1) && !rightAligned) ss << hCount; } d->DrawAtomLabel(ss.str(), alignment, vector3(x, y, 0.0)); } return true; }
bool HINFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv) { OBMol* pmol = dynamic_cast<OBMol*>(pOb); if(pmol==NULL) return false; //Define some references so we can use the old parameter names ostream &ofs = *pConv->GetOutStream(); OBMol &mol = *pmol; unsigned int i, file_num = 1; string str,str1; char buffer[BUFF_SIZE]; OBAtom *atom; OBBond *bond; vector<OBBond*>::iterator j; char bond_char; // make sure to escape titles in double quotes // PR#1501694 ofs << "mol " << file_num << " \"" << mol.GetTitle() << "\"\n"; for(i = 1;i <= mol.NumAtoms(); i++) { atom = mol.GetAtom(i); snprintf(buffer, BUFF_SIZE, "atom %d - %-3s ** - %8.5f %8.5f %8.5f %8.5f %d ", i, etab.GetSymbol(atom->GetAtomicNum()), atom->GetPartialCharge(), atom->GetX(), atom->GetY(), atom->GetZ(), atom->GetValence()); ofs << buffer; for (bond = atom->BeginBond(j); bond; bond = atom->NextBond(j)) { switch(bond->GetBO()) { case 1 : bond_char = 's'; break; case 2 : bond_char = 'd'; break; case 3 : bond_char = 't'; break; case 5 : bond_char = 'a'; break; default: bond_char = 's'; break; } if (bond->IsAromatic()) bond_char = 'a'; snprintf(buffer,BUFF_SIZE, "%d %c ", (bond->GetNbrAtom(atom))->GetIdx(), bond_char); ofs << buffer; } ofs << endl; } ofs << "endmol " << file_num << endl; return(true); }
bool OBCisTransStereo::IsOnSameAtom(unsigned long id1, unsigned long id2) const { const OBMol *mol = GetMolecule(); if (!mol) { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : No valid molecule set", obError); return false; } OBAtom *begin = mol->GetAtomById(m_cfg.begin); if (!begin) { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : Begin reference id is not valid.", obError); return false; } OBAtom *end = mol->GetAtomById(m_cfg.end); if (!end) { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : End reference id is not valid.", obError); return false; } OBAtom *a = mol->GetAtomById(id1); OBAtom *b = mol->GetAtomById(id2); if (a && b) { // both on begin atom? if (a->IsConnected(begin) && b->IsConnected(begin)) return true; // both on end atom? if (a->IsConnected(end) && b->IsConnected(end)) return true; return false; } else { if (a) { // b atom not found, could be a deleted hydrogen... if (a->IsConnected(begin)) { // a is connected to begin. if this is the atom missing a hydrogen, return false if (begin->GetValence() == 2) return true; // check if the end atom really is missing an atom if (end->GetValence() != 2) { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : id2 is not valid and is not a missing hydrogen.", obError); return false; } // inform user we are treating id2 as deleted hydrogen obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : Atom with id2 doesn't exist anymore, must be a (deleted) hydrogen.", obInfo); } else if (a->IsConnected(end)) { // a is connected to end. again, if this is the atom missing a hydrogen, return false if (end->GetValence() == 2) return true; // check if the begin atom really is missing an atom if (begin->GetValence() != 2) { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : id2 is not valid and is not a missing hydrogen.", obError); return true; } // inform user we are treating id2 as deleted hydrogen obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : Atom with id2 doesn't exist, must be a (deleted) hydrogen.", obInfo); } else { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : Atom with id1 isn't connected to the begin or end atom.", obError); return true; } } else if (b) { // a atom not found, could be a deleted hydrogen... if (b->IsConnected(begin)) { // b is connected to begin. if this is the atom missing a hydrogen, return false if (begin->GetValence() == 2) return true; // check if the end atom really is missing an atom if (end->GetValence() != 2) { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : id1 is not valid and is not a missing hydrogen.", obError); return true; } // inform user we are treating id1 as deleted hydrogen obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : Atom with id1 doesn't exist, must be a (deleted) hydrogen.", obInfo); } else if (b->IsConnected(end)) { // a is connected to end. again, if this is the atom missing a hydrogen, return false if (end->GetValence() == 2) return true; // check if the begin atom really is missing an atom if (begin->GetValence() != 2) { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : id1 is not valid and is not a missing hydrogen.", obError); return true; } // inform user we are treating id2 as deleted hydrogen obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : Atom with id1 doesn't exist, must be a (deleted) hydrogen.", obInfo); } else { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : Atom with id1 isn't connected to the begin or end atom.", obError); return true; } } else { OBAtom *c = 0, *d = 0; // no a & b, check the remaining ids which will reveal same info for (int i = 0; i < 4; ++i) { if ((m_cfg.refs.at(i) == id1) || (m_cfg.refs.at(i) == id2)) continue; if (!c) { c = mol->GetAtomById(m_cfg.refs.at(i)); } else { d = mol->GetAtomById(m_cfg.refs.at(i)); } } if (!c || !d) { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : invalid stereochemistry!", obError); return true; } if ((begin->GetValence() != 2) || (end->GetValence() != 2)) { obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : invalid stereochemistry!", obError); return true; } obErrorLog.ThrowError(__FUNCTION__, "OBCisTransStereo::IsOnSameAtom : Atoms with id1 & id2 don't exist, must be a (deleted) hydrogens.", obInfo); return IsOnSameAtom(c->GetId(), d->GetId()); } } return false; }
int SetMM3Type(OBAtom *atom) { OBAtom *b; // neighbor OBBondIterator i, j; int countNeighborO, countNeighborS, countNeighborN, countNeighborC; countNeighborO = countNeighborS = countNeighborN = countNeighborC = 0; // The MM2 typing isn't very good, so we do this ourselves for the most common atom types switch (atom->GetAtomicNum()) { case 1: // Hydrogen b = atom->BeginNbrAtom(j); if (b->IsCarboxylOxygen()) return 24; if (b->GetAtomicNum() == OBElements::Sulfur) return 44; if (b->GetAtomicNum() == OBElements::Nitrogen) { if (b->IsAmideNitrogen()) return 28; if (b->GetValence() > 3) return 48;// ammonium return 23; // default amine/imine } if (b->GetAtomicNum() == OBElements::Carbon && b->GetHyb() == 1) return 124; // acetylene if (b->GetAtomicNum() == OBElements::Oxygen) { if (b->HasAlphaBetaUnsat()) return 73; // includes non-enol/phenol, but has the right spirit return 21; // default alcohol } return 5; // default H break; case 2: // Helium return 51; break; case 3: // Li return 163; break; case 5: // B if (atom->GetValence() >= 4) return 27; // tetrahedral return 26; break; case 6: // C if (atom->IsInRingSize(3)) { // cyclopropane / cyclopropene if (atom->GetHyb() == 3) return 22; if (atom->GetHyb() == 2) { if (atom->CountFreeOxygens() == 1) // propanone return 67; return 38; // propane } } if (atom->IsInRingSize(4)) { // cyclobutane or cyclobutene if (atom->GetHyb() == 3) return 56; if (atom->GetHyb() == 2) { if (atom->CountFreeOxygens() == 1) // butanone return 58; return 57; // regular cyclobutane } } if (atom->CountBondsOfOrder(2) == 2) { // allene if (atom->CountFreeOxygens() == 1) // ketene return 106; return 68; } if (atom->GetFormalCharge() == +1) return 30; if (atom->GetSpinMultiplicity() == 2) return 29; if (atom->GetHyb() == 3) return 1; else if (atom->GetHyb() == 2) { if (atom->CountFreeOxygens() >= 1) return 3; return 2; } else if (atom->GetHyb() == 1) return 4; break; case 7: // N // TODO if (atom->IsAmideNitrogen()) return 151; if (atom->IsAromatic()) { if (atom->GetFormalCharge() == 1) return 111; if (atom->IsInRingSize(5)) // pyrrole return 40; if (atom->IsInRingSize(6)) // pyridine return 37; } if (atom->CountFreeOxygens() == 2) // nitro return 46; if (atom->GetHyb() == 3) { if (atom->GetValence() > 3) return 39; // ammonium return 8; } else if (atom->GetHyb() == 2) return 9; else if (atom->GetHyb() == 1) return 10; break; case 8: // O //TODO if (atom->IsPhosphateOxygen()) return 159; if (atom->IsCarboxylOxygen()) return 75; if (atom->IsInRingSize(3)) return 49; // epoxy b = atom->BeginNbrAtom(j); if (atom->HasBondOfOrder(2) && b->GetAtomicNum() == OBElements::Carbon) { // O=C return 7; } if (atom->IsAromatic()) return 41; // furan return 6; break; case 9: // F return 11; break; case 10: // Ne return 52; break; case 12: // Mg return 59; break; case 14: // Si return 19; break; case 15: // P if (atom->CountFreeOxygens() > 0) return 153; // phosphate if (atom->BOSum() > 3) return 60; // phosphorus V return 25; break; case 16: // S if (atom->IsAromatic()) return 42; // thiophene if (atom->GetFormalCharge() == 1) return 16; // sulfonium // look at the neighbors for (b = atom->BeginNbrAtom(j); b; b = atom->NextNbrAtom(j)) { switch (b->GetAtomicNum()) { case 6: if (b->GetHyb() == 2) // S=C countNeighborC++; break; case 7: countNeighborN++; break; case 8: if (b->GetHvyValence() == 1) countNeighborO++; break; case 16: countNeighborS++; break; default: continue; } } if (countNeighborO == 1) return 17; // sulfoxide if (countNeighborO >= 2) { if (countNeighborN) return 154; // sulfonamide return 18; // sulfone or sulfate } if (countNeighborC) return 74; // S=C if (countNeighborS == 1) return 104; // S-S disulfide else if (countNeighborS > 1) return 105; return 15; break; case 17: // Cl return 12; break; case 18: // Ar return 153; break; case 20: // Ca return 125; break; case 26: // Fe if (atom->GetFormalCharge() == 2) return 61; return 62; break; case 27: // Co if (atom->GetFormalCharge() == 2) return 65; return 66; break; case 28: // Ni if (atom->GetFormalCharge() == 2) return 63; return 64; break; case 32: // Ge return 31; break; case 34: // Se return 34; break; case 35: // Br return 13; break; case 36: // Kr return 54; break; case 38: // Sr return 126; break; case 50: // Sn return 32; break; case 52: // Te return 35; break; case 53: // I return 14; break; case 54: // Xe return 55; break; case 56: // Ba return 127; break; case 57: return 128; break; case 58: return 129; break; case 59: return 130; break; case 60: return 131; break; case 61: return 132; break; case 62: return 133; break; case 63: return 134; break; case 64: return 135; break; case 65: return 136; break; case 66: return 137; break; case 67: return 138; break; case 68: return 139; break; case 69: return 140; break; case 70: return 141; break; case 71: return 142; break; case 82: // Pb return 33; break; default: break; } return 0; }
bool PDBFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv) { OBMol* pmol = dynamic_cast<OBMol*>(pOb); if(pmol==NULL) return false; //Define some references so we can use the old parameter names ostream &ofs = *pConv->GetOutStream(); OBMol &mol = *pmol; unsigned int i; char buffer[BUFF_SIZE]; char type_name[10], padded_name[10]; char the_res[10]; char the_chain = ' '; const char *element_name; int res_num; bool het=true; int model_num = 0; if (!pConv->IsLast() || pConv->GetOutputIndex() > 1) { // More than one molecule record model_num = pConv->GetOutputIndex(); // MODEL 1-based index snprintf(buffer, BUFF_SIZE, "MODEL %8d", model_num); ofs << buffer << endl; } if (strlen(mol.GetTitle()) > 0) snprintf(buffer, BUFF_SIZE, "COMPND %s ",mol.GetTitle()); else snprintf(buffer, BUFF_SIZE, "COMPND UNNAMED"); ofs << buffer << endl; snprintf(buffer, BUFF_SIZE, "AUTHOR GENERATED BY OPEN BABEL %s",BABEL_VERSION); ofs << buffer << endl; // Write CRYST1 record, containing unit cell parameters, space group // and Z value (supposed to be 1) if (pmol->HasData(OBGenericDataType::UnitCell)) { OBUnitCell *pUC = (OBUnitCell*)pmol->GetData(OBGenericDataType::UnitCell); snprintf(buffer, BUFF_SIZE, "CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f %-11s 1", pUC->GetA(), pUC->GetB(), pUC->GetC(), pUC->GetAlpha(), pUC->GetBeta(), pUC->GetGamma(), pUC->GetSpaceGroup() ? pUC->GetSpaceGroup()->GetHMName().c_str() : "P1"); ofs << buffer << endl; } // before we write any records, we should check to see if any coord < -1000 // which will cause errors in the formatting double minX, minY, minZ; minX = minY = minZ = -999.0f; FOR_ATOMS_OF_MOL(a, mol) { if (a->GetX() < minX) minX = a->GetX(); if (a->GetY() < minY) minY = a->GetY(); if (a->GetZ() < minZ) minZ = a->GetZ(); } vector3 transV = VZero; if (minX < -999.0) transV.SetX(-1.0*minX - 900.0); if (minY < -999.0) transV.SetY(-1.0*minY - 900.0); if (minZ < -999.0) transV.SetZ(-1.0*minZ - 900.0); // if minX, minY, or minZ was never changed, shift will be 0.0f // otherwise, move enough so that smallest coord is > -999.0f mol.Translate(transV); OBAtom *atom; OBResidue *res; for (i = 1; i <= mol.NumAtoms(); i++) { atom = mol.GetAtom(i); strncpy(type_name, etab.GetSymbol(atom->GetAtomicNum()), sizeof(type_name)); type_name[sizeof(type_name) - 1] = '\0'; //two char. elements are on position 13 and 14 one char. start at 14 if (strlen(type_name) > 1) type_name[1] = toupper(type_name[1]); else { char tmp[10]; strncpy(tmp, type_name, 10); snprintf(type_name, sizeof(type_name), " %-3s", tmp); } if ( (res = atom->GetResidue()) != 0 ) { het = res->IsHetAtom(atom); snprintf(the_res,4,"%s",(char*)res->GetName().c_str()); snprintf(type_name,5,"%s",(char*)res->GetAtomID(atom).c_str()); the_chain = res->GetChain(); //two char. elements are on position 13 and 14 one char. start at 14 if (strlen(etab.GetSymbol(atom->GetAtomicNum())) == 1) { if (strlen(type_name) < 4) { char tmp[16]; strncpy(tmp, type_name, 16); snprintf(padded_name, sizeof(padded_name), " %-3s", tmp); strncpy(type_name,padded_name,4); type_name[4] = '\0'; } else { /* type_name[4] = type_name[3]; type_name[3] = type_name[2]; type_name[2] = type_name[1]; type_name[1] = type_name[0]; type_name[0] = type_name[4]; */ type_name[4] = '\0'; } } res_num = res->GetNum(); } else { strcpy(the_res,"UNK"); snprintf(padded_name,sizeof(padded_name), "%s",type_name); strncpy(type_name,padded_name,4); type_name[4] = '\0'; res_num = 1; } element_name = etab.GetSymbol(atom->GetAtomicNum()); int charge = atom->GetFormalCharge(); char scharge[3] = { ' ', ' ', '\0' }; if(0 != charge) { snprintf(scharge, 3, "%+d", charge); char tmp = scharge[1]; scharge[1] = scharge[0]; scharge[0] = tmp; } snprintf(buffer, BUFF_SIZE, "%s%5d %-4s %-3s %c%4d %8.3f%8.3f%8.3f 1.00 0.00 %2s%2s\n", het?"HETATM":"ATOM ", i, type_name, the_res, the_chain, res_num, atom->GetX(), atom->GetY(), atom->GetZ(), element_name, scharge); ofs << buffer; } OBAtom *nbr; vector<OBBond*>::iterator k; for (i = 1; i <= mol.NumAtoms(); i ++) { atom = mol.GetAtom(i); if (atom->GetValence() == 0) continue; // no need to write a CONECT record -- no bonds snprintf(buffer, BUFF_SIZE, "CONECT%5d", i); ofs << buffer; // Write out up to 4 real bonds per line PR#1711154 unsigned int currentValence = 0; for (nbr = atom->BeginNbrAtom(k);nbr;nbr = atom->NextNbrAtom(k)) { unsigned int order = mol.GetBond(atom, nbr)->GetBondOrder(); unsigned int it_order = 0; for( it_order = 0; it_order < order; it_order++ ) { if (0 != currentValence && 0 == currentValence % 4) { // Add the trailing space to finish this record ofs << " \n"; // write the start of a new CONECT record snprintf(buffer, BUFF_SIZE, "CONECT%5d", i); ofs << buffer; } currentValence++; snprintf(buffer, BUFF_SIZE, "%5d", nbr->GetIdx()); ofs << buffer; } } // Add trailing spaces unsigned int remainingValence = currentValence % 4; if( 0 < remainingValence ) { for (int count = 0; count < (4 - remainingValence); count++) { snprintf(buffer, BUFF_SIZE, " "); ofs << buffer; } } ofs << " \n"; } snprintf(buffer, BUFF_SIZE, "MASTER 0 0 0 0 0 0 0 0 "); ofs << buffer; snprintf(buffer, BUFF_SIZE, "%4d 0 %4d 0\n",mol.NumAtoms(),mol.NumAtoms()); ofs << buffer; ofs << "END\n"; if (model_num) { ofs << "ENDMDL" << endl; } return(true); }