vector<OBBond*> OBResidue::GetBonds(bool exterior) const { OBAtom *atom; vector<OBBond*> bonds; OBBitVec idxs; unsigned int sz; sz = (unsigned int) _atoms.size(); for ( unsigned int i = 0 ; i < sz ; ++i ) { atom = _atoms[i]; OBBond *bond; vector<OBBond*>::iterator b; for (bond = atom->BeginBond(b) ; bond ; bond = atom->NextBond(b)) { if (!idxs.BitIsOn(bond->GetIdx())) { if (!exterior) { if (bond->GetNbrAtom(atom)->GetResidue() == this) bonds.push_back(&(*bond)); } else bonds.push_back(&(*bond)); idxs.SetBitOn(bond->GetIdx()); } } } return bonds; }
bool OBBond::IsTertiaryAmide() { OBAtom *c,*n; c = n = NULL; // Look for C-N bond if (_bgn->GetAtomicNum() == 6 && _end->GetAtomicNum() == 7) { c = (OBAtom*)_bgn; n = (OBAtom*)_end; } if (_bgn->GetAtomicNum() == 7 && _end->GetAtomicNum() == 6) { c = (OBAtom*)_end; n = (OBAtom*)_bgn; } if (!c || !n) return(false); if (GetBondOrder() != 1) return(false); if (n->GetImplicitValence() != 3) return(false); // Make sure that N is connected to three non-H atoms if (n->GetHvyValence() != 3) return(false); // Make sure C is attached to =O OBBond *bond; vector<OBBond*>::iterator i; for (bond = c->BeginBond(i); bond; bond = c->NextBond(i)) { if (bond->IsCarbonyl()) return(true); } return(false); }
static int DetermineFRJ(OBMol &mol) { vector<vector<int> >::iterator i; vector<vector<int> > cfl; //find all continuous graphs in the mol area mol.ContigFragList(cfl); if (cfl.empty()) return(0); if (cfl.size() == 1) return(mol.NumBonds() - mol.NumAtoms() + 1); //count up the atoms and bonds belonging to each graph OBBond *bond; vector<OBBond*>::iterator j; int numatoms,numbonds,frj=0; OBBitVec frag; for (i = cfl.begin();i != cfl.end();++i) { frag.Clear(); frag.FromVecInt(*i); numatoms = (*i).size(); numbonds=0; for (bond = mol.BeginBond(j);bond;bond = mol.NextBond(j)) if (frag.BitIsOn(bond->GetBeginAtomIdx()) && frag.BitIsOn(bond->GetEndAtomIdx())) numbonds++; frj += numbonds - numatoms + 1; } return(frj); }
//preprocess molecule into a standardized state for heavy atom rmsd computation static void processMol(OBMol& mol) { //isomorphismmapper wants isomorphic atoms to have the same aromatic and ring state, //but these proporties aren't reliable enough to be trusted in evaluating molecules //should be considered the same based solely on connectivity mol.DeleteHydrogens(); //heavy atom rmsd for(OBAtomIterator aitr = mol.BeginAtoms(); aitr != mol.EndAtoms(); aitr++) { OBAtom *a = *aitr; a->UnsetAromatic(); a->SetInRing(); } for(OBBondIterator bitr = mol.BeginBonds(); bitr != mol.EndBonds(); bitr++) { OBBond *b = *bitr; b->UnsetAromatic(); b->SetBondOrder(1); b->SetInRing(); } //avoid recomputations mol.SetHybridizationPerceived(); mol.SetRingAtomsAndBondsPerceived(); mol.SetAromaticPerceived(); }
void fingerprint2::getFragments(vector<int> levels, vector<int> curfrag, int level, OBAtom* patom, OBBond* pbond) { //Recursive routine to analyse schemical structure and populate fragset and ringset //Hydrogens,charges(except dative bonds), spinMultiplicity ignored const int Max_Fragment_Size = 7; int bo=0; if(pbond) { bo = pbond->IsAromatic() ? 5 : pbond->GetBO(); // OBAtom* pprevat = pbond->GetNbrAtom(patom); // if(patom->GetFormalCharge() && (patom->GetFormalCharge() == -pprevat->GetFormalCharge())) // ++bo; //coordinate (dative) bond eg C[N+]([O-])=O is seen as CN(=O)=O } curfrag.push_back(bo); curfrag.push_back(patom->GetAtomicNum()); levels[patom->GetIdx()-1] = level; vector<OBEdgeBase*>::iterator itr; OBBond *pnewbond; // PrintFpt(curfrag,(int)patom); for (pnewbond = patom->BeginBond(itr);pnewbond;pnewbond = patom->NextBond(itr)) { if(pnewbond==pbond) continue; //don't retrace steps OBAtom* pnxtat = pnewbond->GetNbrAtom(patom); if(pnxtat->GetAtomicNum() == OBElements::Hydrogen) continue; int atlevel = levels[pnxtat->GetIdx()-1]; if(atlevel) //ring { if(atlevel==1) { //If complete ring (last bond is back to starting atom) add bond at front //and save in ringset curfrag[0] = pnewbond->IsAromatic() ? 5 : pnewbond->GetBO(); ringset.insert(curfrag); curfrag[0] = 0; } } else //no ring { if(level<Max_Fragment_Size) { // TRACE("level=%d size=%d %p frag[0]=%p\n",level, curfrag.size(),&curfrag, &(curfrag[0])); //Do the next atom; levels, curfrag are passed by value and hence copied getFragments(levels, curfrag, level+1, pnxtat, pnewbond); } } } //do not save C,N,O single atom fragments if(curfrag[0]==0 && (level>1 || patom->GetAtomicNum()>8 || patom->GetAtomicNum()<6)) { fragset.insert(curfrag); //curfrag ignored if an identical fragment already present // PrintFpt(curfrag,level); } }
//! Sets atom->IsChiral() to true for chiral atoms void OBMol::FindChiralCenters() { if (HasChiralityPerceived()) return; SetChiralityPerceived(); obErrorLog.ThrowError(__FUNCTION__, "Ran OpenBabel::FindChiralCenters", obAuditMsg); //do quick test to see if there are any possible chiral centers bool mayHaveChiralCenter=false; OBAtom *atom,*nbr; vector<OBAtom*>::iterator i; for (atom = BeginAtom(i);atom;atom = NextAtom(i)) if (atom->GetHyb() == 3 && atom->GetHvyValence() >= 3) { mayHaveChiralCenter=true; break; } if (!mayHaveChiralCenter) return; OBBond *bond; vector<OBBond*>::iterator j; for (bond = BeginBond(j);bond;bond = NextBond(j)) if (bond->IsWedge() || bond->IsHash()) (bond->GetBeginAtom())->SetChiral(); vector<unsigned int> vgid; GetGIDVector(vgid); vector<unsigned int> tlist; vector<unsigned int>::iterator k; bool ischiral; for (atom = BeginAtom(i);atom;atom = NextAtom(i)) if (atom->GetHyb() == 3 && atom->GetHvyValence() >= 3 && !atom->IsChiral()) { tlist.clear(); ischiral = true; for (nbr = atom->BeginNbrAtom(j);nbr;nbr = atom->NextNbrAtom(j)) { for (k = tlist.begin();k != tlist.end();++k) if (vgid[nbr->GetIdx()-1] == *k) ischiral = false; if (ischiral) tlist.push_back(vgid[nbr->GetIdx()-1]); else break; } if (ischiral) atom->SetChiral(); } }
bool OBBond::IsClosure() { OBMol *mol = (OBMol*)GetParent(); if (!mol) return(false); if (mol->HasClosureBondsPerceived()) return(HasFlag(OB_CLOSURE_BOND)); mol->SetClosureBondsPerceived(); obErrorLog.ThrowError(__FUNCTION__, "Ran OpenBabel::PerceiveClosureBonds", obAuditMsg); OBBond *bond; OBAtom *atom,*nbr; OBBitVec uatoms,ubonds; vector<OBAtom*> curr,next; vector<OBAtom*>::iterator i; vector<OBBond*>::iterator j; uatoms.Resize(mol->NumAtoms()+1); ubonds.Resize(mol->NumAtoms()+1); for (;static_cast<unsigned int>(uatoms.CountBits()) < mol->NumAtoms();) { if (curr.empty()) for (atom = mol->BeginAtom(i);atom;atom = mol->NextAtom(i)) if (!uatoms[atom->GetIdx()]) { uatoms |= atom->GetIdx(); curr.push_back(atom); break; } for (;!curr.empty();) { for (i = curr.begin();i != curr.end();++i) for (nbr = ((OBAtom*)*i)->BeginNbrAtom(j);nbr;nbr = ((OBAtom*)*i)->NextNbrAtom(j)) if (!uatoms[nbr->GetIdx()]) { uatoms |= nbr->GetIdx(); ubonds |= (*j)->GetIdx(); next.push_back(nbr); } curr = next; next.clear(); } } for (bond = mol->BeginBond(j);bond;bond = mol->NextBond(j)) if (!ubonds[bond->GetIdx()]) bond->SetClosure(); return(HasFlag(OB_CLOSURE_BOND)); }
bool OBRotorList::FindRotors(OBMol &mol, bool sampleRingBonds) { // Find ring atoms & bonds // This function will set OBBond::IsRotor(). mol.FindRingAtomsAndBonds(); obErrorLog.ThrowError(__FUNCTION__, "Ran OpenBabel::FindRotors", obAuditMsg); // // Score the bonds using the graph theoretical distance (GTD). // The GTD is the distance from atom i to every other atom j. // Atoms on the "inside" of the molecule will have a lower GTD // value than atoms on the "outside" // // The scoring will rank "inside" bonds first. // vector<int> gtd; mol.GetGTDVector(gtd); // compute the scores vector<OBBond*>::iterator i; vector<pair<OBBond*,int> > vtmp; for (OBBond *bond = mol.BeginBond(i);bond;bond = mol.NextBond(i)) { // check if the bond is "rotatable" if (bond->IsRotor(sampleRingBonds)) { // check if the bond is fixed (using deprecated fixed atoms or new fixed bonds) if ((HasFixedAtoms() || HasFixedBonds()) && IsFixedBond(bond)) continue; if (bond->IsInRing()) { //otherwise mark that we have them and add it to the pile _ringRotors = true; } int score = gtd[bond->GetBeginAtomIdx()-1] + gtd[bond->GetEndAtomIdx()-1]; // compute the GTD bond score as sum of atom GTD scores vtmp.push_back(pair<OBBond*,int> (bond,score)); } } // sort the rotatable bonds by GTD score sort(vtmp.begin(),vtmp.end(),CompareRotor); // create rotors for the bonds int count = 0; vector<pair<OBBond*,int> >::iterator j; for (j = vtmp.begin(); j != vtmp.end(); ++j, ++count) { OBRotor *rotor = new OBRotor; rotor->SetBond((*j).first); rotor->SetIdx(count); rotor->SetNumCoords(mol.NumAtoms()*3); _rotor.push_back(rotor); } return true; }
void GenerateRingReference() { std::ifstream ifs; if (!SafeOpen(ifs,"attype.00.smi")) return; std::ofstream ofs; if (!SafeOpen(ofs,"ringresults.txt")) return; int count; OBAtom *atom; OBBond *bond; char buffer[BUFF_SIZE]; vector<OBRing*> vr; vector<OBEdgeBase*>::iterator i; vector<OBNodeBase*>::iterator j; vector<OBRing*>::iterator k; OBMol mol(SMI,SMI); OBFileFormat ff; for (;ifs;) { mol.Clear(); ff.ReadMolecule(ifs, mol); if (mol.Empty()) continue; //write out ring bonds for (bond = mol.BeginBond(i);bond;bond = mol.NextBond(i)) if (bond->IsInRing()) { sprintf(buffer,"%3d",bond->GetIdx()); ofs << buffer; } ofs << endl; vr = mol.GetSSSR(); //write the total number of rings ofs << vr.size() << endl; //write the number of rings that each atom is a member of for (atom = mol.BeginAtom(j);atom;atom = mol.NextAtom(j)) { count = 0; for (k = vr.begin();k != vr.end();k++) if ((*k)->_pathset[atom->GetIdx()]) count++; sprintf(buffer,"%3d",count); ofs << buffer; } ofs << endl; } ThrowError("Ring perception test results written successfully"); }
static int DetermineFRJ(OBMol &mol) { if (!mol.HasClosureBondsPerceived()) return (int)FindRingAtomsAndBonds2(mol); int frj = 0; OBBond *bond; vector<OBBond*>::iterator j; for (bond = mol.BeginBond(j);bond;bond = mol.NextBond(j)) if (bond->IsClosure()) // bond->HasFlag(OB_CLOSURE_BOND)? frj++; return frj; }
bool GetDFFVector(OBMol &mol,vector<int> &dffv,OBBitVec &bv) { dffv.clear(); dffv.resize(mol.NumAtoms()); int dffcount,natom; OBBitVec used,curr,next; OBAtom *atom,*atom1; OBBond *bond; vector<OBAtom*>::iterator i; vector<OBBond*>::iterator j; next.Clear(); for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) { if (bv[atom->GetIdx()]) { dffv[atom->GetIdx()-1] = 0; continue; } dffcount = 0; used.Clear(); curr.Clear(); used.SetBitOn(atom->GetIdx()); curr.SetBitOn(atom->GetIdx()); while (!curr.IsEmpty() && (bv&curr).Empty()) { next.Clear(); for (natom = curr.NextBit(-1);natom != curr.EndBit();natom = curr.NextBit(natom)) { atom1 = mol.GetAtom(natom); for (bond = atom1->BeginBond(j);bond;bond = atom1->NextBond(j)) if (!used.BitIsOn(bond->GetNbrAtomIdx(atom1)) && !curr.BitIsOn(bond->GetNbrAtomIdx(atom1))) if (!(bond->GetNbrAtom(atom1))->IsHydrogen()) next.SetBitOn(bond->GetNbrAtomIdx(atom1)); } used |= next; curr = next; dffcount++; } dffv[atom->GetIdx()-1] = dffcount; } return(true); }
void OBDepictPrivate::SetWedgeAndHash(OBMol* mol) { std::map<OBBond*, enum OBStereo::BondDirection> updown; std::map<OBBond*, OBStereo::Ref> from; std::map<OBBond*, OBStereo::Ref>::const_iterator from_cit; TetStereoToWedgeHash(*mol, updown, from); for(from_cit=from.begin();from_cit!=from.end();++from_cit) { OBBond* pbond = from_cit->first; if(updown[pbond]==OBStereo::UpBond) pbond->SetHash(); else if(updown[pbond]==OBStereo::DownBond) pbond->SetWedge(); } }
bool WriteAlchemy(ostream &ofs,OBMol &mol) { unsigned int i; char buffer[BUFF_SIZE]; char bond_string[10]; snprintf(buffer, BUFF_SIZE, "%5d ATOMS, %5d BONDS, 0 CHARGES", mol.NumAtoms(), mol.NumBonds()); ofs << buffer << endl; ttab.SetFromType("INT"); ttab.SetToType("ALC"); OBAtom *atom; string str,str1; for(i = 1;i <= mol.NumAtoms(); i++) { atom = mol.GetAtom(i); str = atom->GetType(); ttab.Translate(str1,str); snprintf(buffer, BUFF_SIZE, "%5d %-6s%8.4f %8.4f %8.4f 0.0000", i, (char*)str1.c_str(), atom->GetX(), atom->GetY(), atom->GetZ()); ofs << buffer << endl; } OBBond *bond; vector<OBEdgeBase*>::iterator j; for (bond = mol.BeginBond(j);bond;bond = mol.NextBond(j)) { switch(bond->GetBO()) { case 1 : strcpy(bond_string,"SINGLE"); break; case 2 : strcpy(bond_string,"DOUBLE"); break; case 3 : strcpy(bond_string,"TRIPLE"); break; case 5 : strcpy(bond_string,"AROMATIC"); break; default : strcpy(bond_string,"SINGLE"); } snprintf(buffer, BUFF_SIZE, "%5d %4d %4d %s", bond->GetIdx()+1, bond->GetBeginAtomIdx(), bond->GetEndAtomIdx(), bond_string); ofs << buffer << endl; } return(true); }
void OBRotorList::RemoveSymVals(OBMol &mol) { OBGraphSym gs(&mol); vector<unsigned int> sym_classes; gs.GetSymmetry(sym_classes); OBRotor *rotor; vector<OBRotor*>::iterator i; std::set<unsigned int> syms; for (rotor = BeginRotor(i);rotor;rotor = NextRotor(i)) { OBBond* bond = rotor->GetBond(); OBAtom* end = bond->GetEndAtom(); OBAtom* begin = bond->GetBeginAtom(); int N_fold_symmetry = 1; for (int here=0; here <= 1; ++here) { // Try each side of the bond in turn OBAtom *this_side, *other_side; if (here == 0) { this_side = begin; other_side = end; } else { this_side = end; other_side = begin; } for (int hyb=2; hyb<=3; ++hyb) { // sp2 and sp3 carbons, with explicit Hs if (this_side->GetAtomicNum() == 6 && this_side->GetHyb() == hyb && this_side->GetValence() == (hyb + 1) ) { syms.clear(); FOR_NBORS_OF_ATOM(nbr, this_side) { if ( &(*nbr) == other_side ) continue; syms.insert(sym_classes[nbr->GetIdx() - 1]); } if (syms.size() == 1) // All of the rotated atoms have the same symmetry class N_fold_symmetry *= hyb; } } } if (N_fold_symmetry > 1) { size_t old_size = rotor->Size(); rotor->RemoveSymTorsionValues(N_fold_symmetry); if (!_quiet) { cout << "...." << N_fold_symmetry << "-fold symmetry at rotor between " << begin->GetIdx() << " and " << end->GetIdx(); cout << " - reduced from " << old_size << " to " << rotor->Size() << endl; } } }
// OBMol::NewBond() void testIdsNewBond1() { OBMol mol; for (int i = 0; i < 10; ++i) { OBBond *bond = mol.NewBond(); OB_REQUIRE(bond->GetId() == i); } OB_REQUIRE( mol.GetBondById(0) ); OB_REQUIRE( mol.GetBondById(4) ); OB_REQUIRE( mol.GetBondById(9) ); OB_REQUIRE( !mol.GetBondById(10) ); OB_REQUIRE( mol.GetBondById(0)->GetId() == 0 ); OB_REQUIRE( mol.GetBondById(4)->GetId() == 4 ); OB_REQUIRE( mol.GetBondById(9)->GetId() == 9 ); }
void testIdsAddBond() { OBMol mol; // add 5 bonds for (int i = 0; i < 5; ++i) mol.NewBond(); OBBond bond; OBAtom *a = mol.NewAtom(); OBAtom *b = mol.NewAtom(); bond.SetBegin(a); bond.SetEnd(b); // add a sixth bond mol.AddBond(bond); OB_REQUIRE( mol.NumBonds() == 6 ); OB_REQUIRE( mol.GetBondById(5) ); OB_REQUIRE( mol.GetBondById(5)->GetId() == 5 ); }
// OBMol::NewBond(unsigned long id) void testIdsNewBond2() { OBMol mol; for (int i = 0; i < 10; ++i) { OBBond *bond = mol.NewBond(i*2); OB_REQUIRE(bond->GetId() == i*2); } OB_REQUIRE( mol.GetBondById(0) ); OB_REQUIRE( !mol.GetBondById(7) ); OB_REQUIRE( mol.GetBondById(8) ); OB_REQUIRE( !mol.GetBondById(9) ); OB_REQUIRE( mol.GetBondById(18) ); OB_REQUIRE( !mol.GetBondById(19) ); OB_REQUIRE( mol.GetBondById(0)->GetId() == 0 ); OB_REQUIRE( mol.GetBondById(8)->GetId() == 8 ); OB_REQUIRE( mol.GetBondById(18)->GetId() == 18 ); }
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); }
static void FindRings(OBMol &mol,vector<int> &path,OBBitVec &avisit, OBBitVec &bvisit, int natom,int depth ) { OBAtom *atom; OBBond *bond; vector<OBBond*>::iterator k; // don't return if all atoms are visited // (For example, some atoms are in multiple rings!) -GRH if (avisit[natom]) { int j = depth-1; bond=mol.GetBond(path[j--]); bond->SetInRing(); while( j >= 0 ) { bond=mol.GetBond(path[j--]); bond->SetInRing(); (bond->GetBeginAtom())->SetInRing(); (bond->GetEndAtom())->SetInRing(); if(bond->GetBeginAtomIdx()==static_cast<unsigned int>(natom) || bond-> GetEndAtomIdx()==static_cast<unsigned int>(natom)) break; } } else { avisit.SetBitOn(natom); atom = mol.GetAtom(natom); for(bond = atom->BeginBond(k);bond;bond=atom->NextBond(k)) if( !bvisit[bond->GetIdx()]) { path[depth] = bond->GetIdx(); bvisit.SetBitOn(bond->GetIdx()); FindRings(mol,path,avisit,bvisit,bond->GetNbrAtomIdx(atom), depth+1); } } }
void testOBRotorGetSet() { OBBond bond; OBRotor rotor; // SetBond/GetBond rotor.SetBond(&bond); OB_ASSERT(rotor.GetBond()->GetIdx() == bond.GetIdx()); // SetIdx/GetIdx rotor.SetIdx(45); OB_ASSERT(rotor.GetIdx() == 45); // SetDihedralAtoms/GetDihedralAtoms int ref_ptr[4] = {1, 2, 3, 4}; rotor.SetDihedralAtoms(ref_ptr); rotor.GetDihedralAtoms(ref_ptr); OB_ASSERT(ref_ptr[0] == 1); OB_ASSERT(ref_ptr[1] == 2); OB_ASSERT(ref_ptr[2] == 3); OB_ASSERT(ref_ptr[3] == 4); std::vector<int> ref_vector = rotor.GetDihedralAtoms(); OB_ASSERT(ref_vector[0] == 1); OB_ASSERT(ref_vector[1] == 2); OB_ASSERT(ref_vector[2] == 3); OB_ASSERT(ref_vector[3] == 4); rotor.SetDihedralAtoms(ref_vector); ref_vector = rotor.GetDihedralAtoms(); OB_ASSERT(ref_vector[0] == 1); OB_ASSERT(ref_vector[1] == 2); OB_ASSERT(ref_vector[2] == 3); OB_ASSERT(ref_vector[3] == 4); // SetTorsionValues/GetTorsionValues/Size std::vector<double> angles; angles.push_back(0.0); angles.push_back(3.1415); rotor.SetTorsionValues(angles); OB_ASSERT(rotor.GetTorsionValues().size() == 2); OB_ASSERT(rotor.Size() == 2); }
/* A recursive O(N) traversal of the molecule */ static int FindRings(OBAtom *atom, int *avisit, unsigned char *bvisit, unsigned int &frj, int depth) { OBBond *bond; int result = -1; vector<OBBond*>::iterator k; for(bond = atom->BeginBond(k);bond;bond=atom->NextBond(k)) { unsigned int bidx = bond->GetIdx(); if (bvisit[bidx] == 0) { bvisit[bidx] = 1; OBAtom *nbor = bond->GetNbrAtom(atom); unsigned int nidx = nbor->GetIdx(); int nvisit = avisit[nidx]; if (nvisit == 0) { avisit[nidx] = depth+1; nvisit = FindRings(nbor,avisit,bvisit,frj,depth+1); if (nvisit > 0) { if (nvisit <= depth) { bond->SetInRing(); if (result < 0 || nvisit < result) result = nvisit; } } } else { if (result < 0 || nvisit < result) result = nvisit; bond->SetClosure(); bond->SetInRing(); frj++; } } } if (result > 0 && result <= depth) atom->SetInRing(); return result; }
bool OBResidueData::AssignBonds(OBMol &mol,OBBitVec &bv) { if (!_init) Init(); OBAtom *a1,*a2; OBResidue *r1,*r2; vector<OBAtom*>::iterator i,j; vector3 v; int bo; string skipres = ""; // Residue Number to skip string rname = ""; //assign residue bonds for (a1 = mol.BeginAtom(i);a1;a1 = mol.NextAtom(i)) { r1 = a1->GetResidue(); if (r1 == NULL) // atoms may not have residues continue; if (skipres.length() && r1->GetNumString() == skipres) continue; if (r1->GetName() != rname) { skipres = SetResName(r1->GetName()) ? "" : r1->GetNumString(); rname = r1->GetName(); } //assign bonds for each atom for (j=i,a2 = mol.NextAtom(j);a2;a2 = mol.NextAtom(j)) { r2 = a2->GetResidue(); if (r2 == NULL) // atoms may not have residues continue; if (r1->GetNumString() != r2->GetNumString()) break; if (r1->GetName() != r2->GetName()) break; if (r1->GetChain() != r2->GetChain()) break; // Fixes PR#2889763 - Fabian if ((bo = LookupBO(r1->GetAtomID(a1),r2->GetAtomID(a2)))) { // Suggested by Liu Zhiguo 2007-08-13 // for predefined residues, don't perceive connection // by distance // v = a1->GetVector() - a2->GetVector(); // if (v.length_2() < 3.5) //check by distance mol.AddBond(a1->GetIdx(),a2->GetIdx(),bo); } } } int hyb; string type; //types and hybridization rname = ""; // name of current residue skipres = ""; // don't skip any residues right now for (a1 = mol.BeginAtom(i);a1;a1 = mol.NextAtom(i)) { if (a1->GetAtomicNum() == OBElements::Oxygen && !a1->GetValence()) { a1->SetType("O3"); continue; } if (a1->GetAtomicNum() == OBElements::Hydrogen) { a1->SetType("H"); continue; } //***valence rule for O- if (a1->GetAtomicNum() == OBElements::Oxygen && a1->GetValence() == 1) { OBBond *bond; bond = (OBBond*)*(a1->BeginBonds()); if (bond->GetBO() == 2) { a1->SetType("O2"); a1->SetHyb(2); } else if (bond->GetBO() == 1) { // Leave the protonation/deprotonation to phmodel.txt a1->SetType("O3"); a1->SetHyb(3); // PR#3203039 -- Fix from Magnus Lundborg // a1->SetFormalCharge(0); } continue; } r1 = a1->GetResidue(); if (r1 == NULL) continue; // atoms may not have residues if (skipres.length() && r1->GetNumString() == skipres) continue; if (r1->GetName() != rname) { // if SetResName fails, skip this residue skipres = SetResName(r1->GetName()) ? "" : r1->GetNumString(); rname = r1->GetName(); } if (LookupType(r1->GetAtomID(a1),type,hyb)) { a1->SetType(type); a1->SetHyb(hyb); } else // try to figure it out by bond order ??? {} } return(true); }
bool parseConectRecord(char *buffer,OBMol &mol) { stringstream errorMsg; string clearError; // Setup strings and string buffers vector<string> vs; buffer[70] = '\0'; if (strlen(buffer) < 70) { errorMsg << "WARNING: Problems reading a PDB file\n" << " Problems reading a CONECT record.\n" << " According to the PDB specification,\n" << " the record should have 70 columns, but OpenBabel found " << strlen(buffer) << " columns." << endl; obErrorLog.ThrowError(__FUNCTION__, errorMsg.str() , obInfo); errorMsg.str(clearError); } // Serial number of the first atom, read from column 7-11 of the // connect record, to which the other atoms connect to. long int startAtomSerialNumber; // A pointer to the first atom. OBAtom *firstAtom = NULL; // Serial numbers of the atoms which bind to firstAtom, read from // columns 12-16, 17-21, 22-27 and 27-31 of the connect record. Note // that we reserve space for 5 integers, but read only four of // them. This is to simplify the determination of the bond order; // see below. long int boundedAtomsSerialNumbers[5] = {0,0,0,0,0}; // Bools which tell us which of the serial numbers in // boundedAtomsSerialNumbers are read from the file, and which are // invalid bool boundedAtomsSerialNumbersValid[5] = {false, false, false, false, false}; // Pragmatic approach -- too many non-standard PDB files out there // (including some old ones from us) // So if we have a small number of atoms, then try to break by spaces // Otherwise (i.e., NumAtoms() > 9,999 we need to go by position) // We'll switch back and forth a few times to save duplicating common code if (mol.NumAtoms() <= 9999) { // make sure we don't look at salt bridges or whatever, so cut the buffer short buffer[32] = '\0'; tokenize(vs,buffer); if( vs.empty() || vs.size() < 2) return false; vs.erase(vs.begin()); // remove "CONECT" startAtomSerialNumber = atoi(vs[0].c_str()); } else { if (readIntegerFromRecord(buffer, 7, &startAtomSerialNumber) == false) { errorMsg << "WARNING: Problems reading a PDB file\n" << " Problems reading a CONECT record.\n" << " According to the PDB specification,\n" << " columns 7-11 should contain the serial number of an atom.\n" << " THIS CONECT RECORD WILL BE IGNORED." << endl; obErrorLog.ThrowError(__FUNCTION__, errorMsg.str() , obWarning); return(false); } } vector<OBAtom*>::iterator i; for (OBAtom *a1 = mol.BeginAtom(i);a1;a1 = mol.NextAtom(i)) { // atoms may not have residue information, but if they do, // check serial numbers if (a1->GetResidue() != NULL && static_cast<long int>(a1->GetResidue()-> GetSerialNum(a1)) == startAtomSerialNumber) { firstAtom = a1; break; } } if (firstAtom == NULL) { errorMsg << "WARNING: Problems reading a PDB file:\n" << " Problems reading a CONECT record.\n" << " According to the PDB specification,\n" << " columns 7-11 should contain the serial number of an atom.\n" << " No atom was found with this serial number.\n" << " THIS CONECT RECORD WILL BE IGNORED." << endl; obErrorLog.ThrowError(__FUNCTION__, errorMsg.str() , obWarning); return(false); } if (mol.NumAtoms() < 9999) { if (vs.size() > 1) boundedAtomsSerialNumbers[0] = atoi(vs[1].c_str()); if (vs.size() > 2) boundedAtomsSerialNumbers[1] = atoi(vs[2].c_str()); if (vs.size() > 3) boundedAtomsSerialNumbers[2] = atoi(vs[3].c_str()); if (vs.size() > 4) boundedAtomsSerialNumbers[3] = atoi(vs[4].c_str()); unsigned int limit = 4; if (vs.size() <= 4) limit = vs.size() - 1; for (unsigned int s = 0; s < limit; ++s) boundedAtomsSerialNumbersValid[s] = true; } else { // Now read the serial numbers. If the first serial number is not // present, this connect record probably contains only hydrogen // bonds and salt bridges, which we ignore. In that case, we just // exit gracefully. boundedAtomsSerialNumbersValid[0] = readIntegerFromRecord(buffer, 12, boundedAtomsSerialNumbers+0); if (boundedAtomsSerialNumbersValid[0] == false) return(true); boundedAtomsSerialNumbersValid[1] = readIntegerFromRecord(buffer, 17, boundedAtomsSerialNumbers+1); boundedAtomsSerialNumbersValid[2] = readIntegerFromRecord(buffer, 22, boundedAtomsSerialNumbers+2); boundedAtomsSerialNumbersValid[3] = readIntegerFromRecord(buffer, 27, boundedAtomsSerialNumbers+3); } // Now iterate over the VALID boundedAtomsSerialNumbers and connect // the atoms. for(unsigned int k=0; boundedAtomsSerialNumbersValid[k]; k++) { // Find atom that is connected to, write an error message OBAtom *connectedAtom = 0L; for (OBAtom *a1 = mol.BeginAtom(i);a1;a1 = mol.NextAtom(i)) { // again, atoms may not have residues, but if they do, check serials if (a1->GetResidue() != NULL && static_cast<long int>(a1->GetResidue()-> GetSerialNum(a1)) == boundedAtomsSerialNumbers[k]) { connectedAtom = a1; break; } } if (connectedAtom == 0L) { errorMsg << "WARNING: Problems reading a PDB file:\n" << " Problems reading a CONECT record.\n" << " According to the PDB specification,\n" << " Atoms with serial #" << startAtomSerialNumber << " and #" << boundedAtomsSerialNumbers[k] << " should be connected\n" << " However, an atom with serial #" << boundedAtomsSerialNumbers[k] << " was not found.\n" << " THIS CONECT RECORD WILL BE IGNORED." << endl; obErrorLog.ThrowError(__FUNCTION__, errorMsg.str() , obWarning); return(false); } // Figure the bond order unsigned char order = 0; while(boundedAtomsSerialNumbersValid[k+order+1] && (boundedAtomsSerialNumbers[k+order] == boundedAtomsSerialNumbers[k+order+1])) order++; k += order; // Generate the bond if (firstAtom->GetIdx() < connectedAtom->GetIdx()) { // record the bond 'in one direction' only OBBond *bond = mol.GetBond(firstAtom, connectedAtom); if (!bond) mol.AddBond(firstAtom->GetIdx(), connectedAtom->GetIdx(), order+1); else // An additional CONECT record with the same firstAtom that references // a bond created in the previous CONECT record. // For example, the 1136->1138 double bond in the following: // CONECT 1136 1128 1137 1137 1138 // CONECT 1136 1138 1139 bond->SetBondOrder(bond->GetBondOrder() + order+1); } } return(true); }
bool MOL2Format::ReadMolecule(OBBase* pOb, OBConversion* pConv) { OBMol* pmol = pOb->CastAndClear<OBMol>(); if(pmol==NULL) return false; //Define some references so we can use the old parameter names istream &ifs = *pConv->GetInStream(); OBMol &mol = *pmol; //Old code follows... bool foundAtomLine = false; char buffer[BUFF_SIZE]; char *comment = NULL; string str,str1; vector<string> vstr; int len; mol.BeginModify(); for (;;) { if (!ifs.getline(buffer,BUFF_SIZE)) return(false); if (EQn(buffer,"@<TRIPOS>MOLECULE",17)) break; } int lcount; int natoms,nbonds; for (lcount=0;;lcount++) { if (!ifs.getline(buffer,BUFF_SIZE)) return(false); if (EQn(buffer,"@<TRIPOS>ATOM",13)) { foundAtomLine = true; break; } if (lcount == 0) { tokenize(vstr,buffer); if (!vstr.empty()) mol.SetTitle(buffer); } else if (lcount == 1) sscanf(buffer,"%d%d",&natoms,&nbonds); else if (lcount == 4) //energy { tokenize(vstr,buffer); if (!vstr.empty() && vstr.size() == 3) if (vstr[0] == "Energy") mol.SetEnergy(atof(vstr[2].c_str())); } else if (lcount == 5) //comment { if ( buffer[0] ) { len = (int) strlen(buffer)+1; // TODO allow better multi-line comments // which don't allow ill-formed data to consume memory // Thanks to Andrew Dalke for the pointer if (comment != NULL) delete [] comment; comment = new char [len]; memcpy(comment,buffer,len); } } } if (!foundAtomLine) { mol.EndModify(); mol.Clear(); obErrorLog.ThrowError(__FUNCTION__, "Unable to read Mol2 format file. No atoms found.", obWarning); return(false); } mol.ReserveAtoms(natoms); int i; vector3 v; OBAtom atom; bool hasPartialCharges=false; double x,y,z,pcharge; char temp_type[BUFF_SIZE], resname[BUFF_SIZE], atmid[BUFF_SIZE]; int elemno, resnum = -1; ttab.SetFromType("SYB"); for (i = 0;i < natoms;i++) { if (!ifs.getline(buffer,BUFF_SIZE)) return(false); sscanf(buffer," %*s %1024s %lf %lf %lf %1024s %d %1024s %lf", atmid, &x,&y,&z, temp_type, &resnum, resname, &pcharge); atom.SetVector(x, y, z); // Handle "CL" and "BR" and other mis-typed atoms str = temp_type; if (strncmp(temp_type, "CL", 2) == 0) { str = "Cl"; } else if (strncmp(temp_type,"BR",2) == 0) { str = "Br"; } else if (strncmp(temp_type,"S.o2", 4) == 02) { str = "S.O2"; } else if (strncmp(temp_type,"S.o", 3) == 0) { str = "S.O"; } else if (strncmp(temp_type,"SI", 2) == 0) { str = "Si"; // The following cases are entries which are not in openbabel/data/types.txt // and should probably be added there } else if (strncmp(temp_type,"S.1", 3) == 0) { str = "S.2"; // no idea what the best type might be here } else if (strncmp(temp_type,"P.", 2) == 0) { str = "P.3"; } else if (strncasecmp(temp_type,"Ti.", 3) == 0) { // e.g. Ti.th str = "Ti"; } else if (strncasecmp(temp_type,"Ru.", 3) == 0) { // e.g. Ru.oh str = "Ru"; } ttab.SetToType("ATN"); ttab.Translate(str1,str); elemno = atoi(str1.c_str()); ttab.SetToType("IDX"); // We might have missed some SI or FE type things above, so here's // another check if( !elemno && isupper(temp_type[1]) ) { temp_type[1] = (char)tolower(temp_type[1]); str = temp_type; ttab.Translate(str1,str); elemno = atoi(str1.c_str()); } // One last check if there isn't a period in the type, // it's a malformed atom type, but it may be the element symbol // GaussView does this (PR#1739905) if ( !elemno ) { obErrorLog.ThrowError(__FUNCTION__, "This Mol2 file is non-standard. Cannot interpret atom types correctly, instead attempting to interpret as elements instead.", obWarning); string::size_type dotPos = str.find('.'); if (dotPos == string::npos) { elemno = etab.GetAtomicNum(str.c_str()); } } atom.SetAtomicNum(elemno); ttab.SetToType("INT"); ttab.Translate(str1,str); atom.SetType(str1); atom.SetPartialCharge(pcharge); if (!mol.AddAtom(atom)) return(false); if (!IsNearZero(pcharge)) hasPartialCharges = true; // Add residue information if it exists if (resnum != -1 && resnum != 0 && strlen(resname) != 0 && strncmp(resname,"<1>", 3) != 0) { OBResidue *res = (mol.NumResidues() > 0) ? mol.GetResidue(mol.NumResidues()-1) : NULL; if (res == NULL || res->GetName() != resname || static_cast<int>(res->GetNum()) != resnum) { vector<OBResidue*>::iterator ri; for (res = mol.BeginResidue(ri) ; res ; res = mol.NextResidue(ri)) if (res->GetName() == resname && static_cast<int>(res->GetNum()) == resnum) break; if (res == NULL) { res = mol.NewResidue(); res->SetName(resname); res->SetNum(resnum); } } OBAtom *atomPtr = mol.GetAtom(mol.NumAtoms()); res->AddAtom(atomPtr); res->SetAtomID(atomPtr, atmid); } // end adding residue info } for (;;) { if (!ifs.getline(buffer,BUFF_SIZE)) return(false); str = buffer; if (!strncmp(buffer,"@<TRIPOS>BOND",13)) break; } int start,end,order; for (i = 0; i < nbonds; i++) { if (!ifs.getline(buffer,BUFF_SIZE)) return(false); sscanf(buffer,"%*d %d %d %1024s",&start,&end,temp_type); str = temp_type; order = 1; if (str == "ar" || str == "AR" || str == "Ar") order = 5; else if (str == "AM" || str == "am" || str == "Am") order = 1; else order = atoi(str.c_str()); mol.AddBond(start,end,order); } // update neighbour bonds information for each atom. vector<OBAtom*>::iterator apos; vector<OBBond*>::iterator bpos; OBAtom* patom; OBBond* pbond; for (patom = mol.BeginAtom(apos); patom; patom = mol.NextAtom(apos)) { patom->ClearBond(); for (pbond = mol.BeginBond(bpos); pbond; pbond = mol.NextBond(bpos)) { if (patom == pbond->GetBeginAtom() || patom == pbond->GetEndAtom()) { patom->AddBond(pbond); } } } // Suggestion by Liu Zhiguo 2008-01-26 // Mol2 files define atom types -- there is no need to re-perceive mol.SetAtomTypesPerceived(); mol.EndModify(); //must add generic data after end modify - otherwise it will be blown away if (comment) { OBCommentData *cd = new OBCommentData; cd->SetData(comment); cd->SetOrigin(fileformatInput); mol.SetData(cd); delete [] comment; comment = NULL; } if (hasPartialCharges) mol.SetPartialChargesPerceived(); // continue untill EOF or untill next molecule record streampos pos; for(;;) { pos = ifs.tellg(); if (!ifs.getline(buffer,BUFF_SIZE)) break; if (EQn(buffer,"@<TRIPOS>MOLECULE",17)) break; } ifs.seekg(pos); // go back to the end of the molecule return(true); }
void OBMol::FindLSSR() { if (HasLSSRPerceived()) return; SetLSSRPerceived(); obErrorLog.ThrowError(__FUNCTION__, "Ran OpenBabel::FindLSSR", obAuditMsg); // Delete any old data before we start finding new rings // The following procedure is slow // So if client code is multi-threaded, we don't want to make them wait if (HasData("LSSR")) { DeleteData("LSSR"); } OBRing *ring; vector<OBRing*>::iterator j; //get frerejaque taking int account multiple possible spanning graphs int frj = DetermineFRJ(*this); if (frj) { vector<OBRing*> vr; FindRingAtomsAndBonds(); OBBond *bond; vector<OBBond*> cbonds; vector<OBBond*>::iterator k; //restrict search for rings around closure bonds for (bond = BeginBond(k);bond;bond = NextBond(k)) if (bond->IsClosure()) cbonds.push_back(bond); if (!cbonds.empty()) { OBRingSearch rs; //search for all rings about closures vector<OBBond*>::iterator i; for (i = cbonds.begin();i != cbonds.end();++i) rs.AddRingFromClosure(*this,(OBBond*)*i); rs.SortRings(); rs.RemoveRedundant(-1); // -1 means LSSR //store the LSSR set for (j = rs.BeginRings();j != rs.EndRings();++j) { ring = new OBRing ((*j)->_path,NumAtoms()+1); ring->SetParent(this); vr.push_back(ring); } //rs.WriteRings(); } OBRingData *rd = new OBRingData(); rd->SetOrigin(perceived); // to separate from user or file input rd->SetAttribute("LSSR"); rd->SetData(vr); SetData(rd); } }
bool MOL2Format::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; bool ligandsOnly = pConv->IsOption("l", OBConversion::OUTOPTIONS)!=NULL; //The old code follows.... string str,str1; char buffer[BUFF_SIZE],label[BUFF_SIZE]; char rnum[BUFF_SIZE],rlabel[BUFF_SIZE]; ofs << "@<TRIPOS>MOLECULE" << endl; str = mol.GetTitle(); if (str.empty()) ofs << "*****" << endl; else ofs << str << endl; snprintf(buffer, BUFF_SIZE," %d %d 0 0 0", mol.NumAtoms(),mol.NumBonds()); ofs << buffer << endl; ofs << "SMALL" << endl; OBPairData *dp = (OBPairData*)mol.GetData("PartialCharges"); if (dp != NULL) { // Tripos spec says: // NO_CHARGES, DEL_RE, GASTEIGER, GAST_HUCK, HUCKEL, PULLMAN, // GAUSS80_CHARGES, AMPAC_CHARGES, MULLIKEN_CHARGES, DICT_ CHARGES, // MMFF94_CHARGES, USER_CHARGES if (dp->GetValue() == "Mulliken") ofs << "MULLIKEN_CHARGES" << endl; else // should pick from the Tripos types ofs << "GASTEIGER" << endl; } else { // No idea what these charges are... all our code sets "PartialCharges" ofs << "GASTEIGER" << endl; } ofs << "Energy = " << mol.GetEnergy() << endl; if (mol.HasData(OBGenericDataType::CommentData)) { OBCommentData *cd = (OBCommentData*)mol.GetData(OBGenericDataType::CommentData); ofs << cd->GetData(); } ofs << endl; ofs << "@<TRIPOS>ATOM" << endl; OBAtom *atom; OBResidue *res; vector<OBAtom*>::iterator i; vector<int> labelcount; labelcount.resize( etab.GetNumberOfElements() ); ttab.SetFromType("INT"); ttab.SetToType("SYB"); for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i)) { // // Use sequentially numbered atom names if no residues // snprintf(label,BUFF_SIZE, "%s%d", etab.GetSymbol(atom->GetAtomicNum()), ++labelcount[atom->GetAtomicNum()]); strcpy(rlabel,"<1>"); strcpy(rnum,"1"); str = atom->GetType(); ttab.Translate(str1,str); // // Use original atom names if there are residues // if (!ligandsOnly && (res = atom->GetResidue()) ) { // use original atom names defined by residue snprintf(label,BUFF_SIZE,"%s",(char*)res->GetAtomID(atom).c_str()); // make sure that residue name includes its number snprintf(rlabel,BUFF_SIZE,"%s%d",res->GetName().c_str(), res->GetNum()); snprintf(rnum,BUFF_SIZE,"%d",res->GetNum()); } snprintf(buffer,BUFF_SIZE,"%7d%1s%-6s%12.4f%10.4f%10.4f%1s%-5s%4s%1s %-8s%10.4f", atom->GetIdx(),"",label, atom->GetX(),atom->GetY(),atom->GetZ(), "",str1.c_str(), rnum,"",rlabel, atom->GetPartialCharge()); ofs << buffer << endl; } ofs << "@<TRIPOS>BOND" << endl; OBBond *bond; vector<OBBond*>::iterator j; OBSmartsPattern pat; string s1, s2; for (bond = mol.BeginBond(j);bond;bond = mol.NextBond(j)) { s1 = bond->GetBeginAtom()->GetType(); s2 = bond->GetEndAtom()->GetType(); if (bond->IsAromatic() || s1 == "O.co2" || s2 == "O.co2") strcpy(label,"ar"); else if (bond->IsAmide()) strcpy(label,"am"); else snprintf(label,BUFF_SIZE,"%d",bond->GetBO()); snprintf(buffer, BUFF_SIZE,"%6d%6d%6d%3s%2s", bond->GetIdx()+1,bond->GetBeginAtomIdx(),bond->GetEndAtomIdx(), "",label); ofs << buffer << endl; } // NO trailing blank line (PR#1868929). // ofs << endl; return(true); }
int main(int argc,char *argv[]) { // turn off slow sync with C-style output (we don't use it anyway). std::ios::sync_with_stdio(false); OBConversion conv; OBFormat *inFormat, *canFormat; OBMol mol; ifstream ifs; vector<OBMol> fragments; unsigned int fragmentCount = 0; // track how many in library -- give a running count map<string, int> index; // index of cansmi string currentCAN; unsigned int size; OBAtom *atom; OBBond *bond; bool nonRingAtoms, nonRingBonds; char buffer[BUFF_SIZE]; canFormat = conv.FindFormat("can"); conv.SetOutFormat(canFormat); if (argc < 2) { cout << "Usage: obfragment <file>" << endl; return(-1); } for (int i = 1; i < argc; i++) { cerr << " Reading file " << argv[i] << endl; inFormat = conv.FormatFromExt(argv[i]); if(inFormat==NULL || !conv.SetInFormat(inFormat)) { cerr << " Cannot read file format for " << argv[i] << endl; continue; // try next file } ifs.open(argv[i]); if (!ifs) { cerr << "Cannot read input file: " << argv[i] << endl; continue; } while(ifs.peek() != EOF && ifs.good()) { conv.Read(&mol, &ifs); if (!mol.Has3D()) continue; // invalid coordinates! mol.DeleteHydrogens(); // remove these before we do anything else do { nonRingAtoms = false; size = mol.NumAtoms(); for (unsigned int i = 1; i <= size; ++i) { atom = mol.GetAtom(i); if (!atom->IsInRing()) { mol.DeleteAtom(atom); nonRingAtoms = true; break; // don't know how many atoms there are } // Previously, we changed atoms to carbon here. // Now we perform this alchemy in terms of string-rewriting // once the canonical SMILES is generated } } while (nonRingAtoms); if (mol.NumAtoms() < 3) continue; if (mol.NumBonds() == 0) continue; do { nonRingBonds = false; size = mol.NumBonds(); for (unsigned int i = 0; i < size; ++i) { bond = mol.GetBond(i); if (!bond->IsInRing()) { mol.DeleteBond(bond); nonRingBonds = true; break; // don't know how many bonds there are } } } while (nonRingBonds); fragments = mol.Separate(); for (unsigned int i = 0; i < fragments.size(); ++i) { if (fragments[i].NumAtoms() < 3) // too small to care continue; currentCAN = conv.WriteString(&fragments[i], true); currentCAN = RewriteSMILES(currentCAN); // change elements to "a/A" for compression if (index.find(currentCAN) != index.end()) { // already got this index[currentCAN] += 1; // add to the count for bookkeeping continue; } index[currentCAN] = 1; // don't ever write this ring fragment again // OK, now retrieve the canonical ordering for the fragment vector<string> canonical_order; if (fragments[i].HasData("Canonical Atom Order")) { OBPairData *data = (OBPairData*)fragments[i].GetData("Canonical Atom Order"); tokenize(canonical_order, data->GetValue().c_str()); } // Write out an XYZ-style file with the CANSMI as the title cout << fragments[i].NumAtoms() << '\n'; cout << currentCAN << '\n'; // endl causes a flush vector<string>::iterator can_iter; unsigned int order; OBAtom *atom; fragments[i].Center(); fragments[i].ToInertialFrame(); for (unsigned int index = 0; index < canonical_order.size(); ++index) { order = atoi(canonical_order[index].c_str()); atom = fragments[i].GetAtom(order); snprintf(buffer, BUFF_SIZE, "C%8.3f%8.3f%8.3f\n", atom->x(), atom->y(), atom->z()); cout << buffer; } } fragments.clear(); if (index.size() > fragmentCount) { fragmentCount = index.size(); cerr << " Fragments: " << fragmentCount << endl; } } // while reading molecules (in this file) ifs.close(); ifs.clear(); } // while reading files // loop through the map and output frequencies map<string, int>::const_iterator indexItr; for (indexItr = index.begin(); indexItr != index.end(); ++indexItr) { cerr << (*indexItr).second << " INDEX " << (*indexItr).first << "\n"; } return(0); }
bool TinkerFormat::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; bool mmffTypes = pConv->IsOption("m",OBConversion::OUTOPTIONS) != NULL; unsigned int i; char buffer[BUFF_SIZE]; OBBond *bond; vector<OBBond*>::iterator j; // Before we try output of MMFF94 atom types, check if it works OBForceField *ff = OpenBabel::OBForceField::FindForceField("MMFF94"); if (mmffTypes && ff && ff->Setup(mol)) mmffTypes = ff->GetAtomTypes(mol); else mmffTypes = false; // either the force field isn't available, or it doesn't work if (!mmffTypes) snprintf(buffer, BUFF_SIZE, "%6d %-20s MM2 parameters\n",mol.NumAtoms(),mol.GetTitle()); else snprintf(buffer, BUFF_SIZE, "%6d %-20s MMFF94 parameters\n",mol.NumAtoms(),mol.GetTitle()); ofs << buffer; ttab.SetFromType("INT"); OBAtom *atom; string str,str1; for(i = 1;i <= mol.NumAtoms(); i++) { atom = mol.GetAtom(i); str = atom->GetType(); ttab.SetToType("MM2"); ttab.Translate(str1,str); if (mmffTypes) { // Override the MM2 typing OBPairData *type = (OpenBabel::OBPairData*)atom->GetData("FFAtomType"); if (type) str1 = type->GetValue().c_str(); } snprintf(buffer, BUFF_SIZE, "%6d %2s %12.6f%12.6f%12.6f %5d", i, etab.GetSymbol(atom->GetAtomicNum()), atom->GetX(), atom->GetY(), atom->GetZ(), atoi((char*)str1.c_str())); ofs << buffer; for (bond = atom->BeginBond(j); bond; bond = atom->NextBond(j)) { snprintf(buffer, BUFF_SIZE, "%6d", (bond->GetNbrAtom(atom))->GetIdx()); ofs << buffer; } ofs << endl; } return(true); }
void ring_test() { ostringstream os; #ifdef TESTDATADIR string testdatadir = TESTDATADIR; string results_file = testdatadir + "ringresults.txt"; string smilestypes_file = testdatadir + "attype.00.smi"; #else string results_file = "files/ringresults.txt"; string smilestypes_file = "files/attype.00.smi"; #endif cout << "# Testing ring perception..." << endl; std::ifstream mifs; os << "Bail out! Cannot read test data " << smilestypes_file.c_str(); BOOST_REQUIRE_MESSAGE( SafeOpen(mifs, smilestypes_file.c_str()), os.str().c_str() ); std::ifstream rifs; os.str(""); os << "Bail out! Cannot read test data " << results_file.c_str(); BOOST_REQUIRE_MESSAGE( SafeOpen(rifs, results_file.c_str()), os.str().c_str() ); unsigned int size; OBBond *bond; OBAtom *atom; int count; char buffer[BUFF_SIZE]; vector<string> vs; vector<OBRing*> vr; vector<bool> vb; vector<int> vi; OBMol mol; vector<string>::iterator i; vector<OBBond*>::iterator j; vector<OBAtom*>::iterator k; vector<OBRing*>::iterator m; OBConversion conv(&mifs, &cout); unsigned int currentTest = 0; BOOST_REQUIRE_MESSAGE( conv.SetInAndOutFormats("SMI","SMI"), "Bail out! SMILES format is not loaded" ); for (;mifs;) { mol.Clear(); conv.Read(&mol); if (mol.Empty()) continue; BOOST_REQUIRE_MESSAGE( rifs.getline(buffer,BUFF_SIZE), "Bail out! error reading reference data" ); vb.clear(); vb.resize(mol.NumBonds(),false); //check ring bonds tokenize(vs,buffer); for (i = vs.begin();i != vs.end();i++) vb[atoi(i->c_str())] = true; for (bond = mol.BeginBond(j);bond;bond = mol.NextBond(j)) { os.str(""); os << "ring bond data different than reference # Molecule: " << mol.GetTitle(); BOOST_CHECK_MESSAGE( vb[bond->GetIdx()] == bond->IsInRing(), os.str().c_str() ); } vr = mol.GetSSSR(); BOOST_REQUIRE_MESSAGE( rifs.getline(buffer,BUFF_SIZE), "Bail out! error reading reference data" ); sscanf(buffer,"%d",&size); os.str(""); os << "SSSR size different than reference # Molecule: " << mol.GetTitle(); BOOST_CHECK_MESSAGE( vr.size() == size, os.str().c_str() ); //check SSSR size BOOST_REQUIRE_MESSAGE( rifs.getline(buffer,BUFF_SIZE), "Bail out! error reading reference data" ); tokenize(vs,buffer); i = vs.begin(); for (atom = mol.BeginAtom(k);atom;atom = mol.NextAtom(k)) { os.str(""); os << "error in SSSR count # Molecule: " << mol.GetTitle(); BOOST_CHECK_MESSAGE( i != vs.end(), os.str().c_str() ); //check SSSR size count = 0; for (m = vr.begin();m != vr.end();m++) if ((*m)->_pathset[atom->GetIdx()]) count++; os.str(""); os << "ring membership test failed # Molecule: " << mol.GetTitle(); BOOST_CHECK_MESSAGE( atoi(i->c_str()) == count, os.str().c_str() ); i++; } } }
bool MacroModFormat::ReadMolecule(OBBase* pOb, OBConversion* pConv) { OBMol* pmol = pOb->CastAndClear<OBMol>(); if(pmol==NULL) return false; //Define some references so we can use the old parameter names istream &ifs = *pConv->GetInStream(); OBMol &mol = *pmol; const char* defaultTitle = pConv->GetTitle(); // Get Title char buffer[BUFF_SIZE]; int natoms; vector<vector<pair<int,int> > > connections; if (ifs.getline(buffer,BUFF_SIZE)) { vector<string> vs; tokenize(vs,buffer," \n"); if ( !vs.empty() && vs.size() > 0) sscanf(buffer,"%i%*s",&natoms); if (natoms == 0) return false; if ( !vs.empty() && vs.size() > 1) mol.SetTitle(vs[1]); else { string s = defaultTitle; mol.SetTitle(defaultTitle); } } else return(false); mol.BeginModify(); mol.ReserveAtoms(natoms); connections.resize(natoms+1); /***********************************************************************/ // Get Type Bonds, BondOrder, X, Y, Z double x,y,z; vector3 v; char temp_type[10]; int i,j; double charge; OBAtom atom; ttab.SetFromType("MMD"); for (i = 1; i <= natoms; i++) { if (!ifs.getline(buffer,BUFF_SIZE)) break; int end[6], order[6]; sscanf(buffer,"%9s%d%d%d%d%d%d%d%d%d%d%d%d%lf%lf%lf", temp_type,&end[0],&order[0],&end[1],&order[1],&end[2],&order[2], &end[3], &order[3], &end[4], &order[4], &end[5], &order[5], &x, &y, &z); pair<int,int> tmp; for ( j = 0 ; j <=5 ; j++ ) { if ( end[j] > 0 && end[j] > i) { tmp.first = end[j]; tmp.second = order[j]; connections[i].push_back(tmp); } } v.SetX(x); v.SetY(y); v.SetZ(z); atom.SetVector(v); string str = temp_type,str1; ttab.SetToType("ATN"); ttab.Translate(str1,str); atom.SetAtomicNum(atoi(str1.c_str())); ttab.SetToType("INT"); ttab.Translate(str1,str); atom.SetType(str1); // stuff for optional fields buffer[109]='\0'; sscanf(&buffer[101],"%lf", &charge); atom.SetPartialCharge(charge); mol.AddAtom(atom); } for (i = 1; i <= natoms; i++) for (j = 0; j < (signed)connections[i].size(); j++) mol.AddBond(i, connections[i][j].first, connections[i][j].second); mol.EndModify(); OBBond *bond; vector<OBBond*>::iterator bi; for (bond = mol.BeginBond(bi);bond;bond = mol.NextBond(bi)) if (bond->GetBO() == 5 && !bond->IsInRing()) bond->SetBO(1); if ( natoms != (signed)mol.NumAtoms() ) return(false); // clean out remaining blank lines while(ifs.peek() != EOF && ifs.good() && (ifs.peek() == '\n' || ifs.peek() == '\r')) ifs.getline(buffer,BUFF_SIZE); return(true); }