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->GetBondOrder(); // 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<OBBond*>::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->GetBondOrder(); 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); } }
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 OBChemTsfm::Apply(OBMol &mol) { if (!_bgn.Match(mol)) return(false); mol.BeginModify(); vector<vector<int> > mlist = _bgn.GetUMapList(); obErrorLog.ThrowError(__FUNCTION__, "Ran OpenBabel::OBChemTransform", obAuditMsg); if (!_vchrg.empty()) //modify charges { vector<vector<int> >::iterator i; vector<pair<int,int> >::iterator j; for (i = mlist.begin();i != mlist.end();++i) for (j = _vchrg.begin();j != _vchrg.end();++j) if (j->first < (signed)i->size()) { //goof proofing OBAtom *atom = mol.GetAtom((*i)[j->first]); int old_charge = atom->GetFormalCharge(); atom->SetFormalCharge(j->second); int new_hcount = atom->GetImplicitHCount() + (j->second - old_charge); if (new_hcount < 0) new_hcount = 0; atom->SetImplicitHCount(new_hcount); } } if (!_vbond.empty()) //modify bond orders { OBBond *bond; vector<vector<int> >::iterator i; vector<pair<pair<int,int>,int> >::iterator j; for (i = mlist.begin();i != mlist.end();++i) for (j = _vbond.begin();j != _vbond.end();++j) { bond = mol.GetBond((*i)[j->first.first],(*i)[j->first.second]); if (!bond) { obErrorLog.ThrowError(__FUNCTION__, "unable to find bond", obDebug); continue; } unsigned int old_bond_order = bond->GetBondOrder(); bond->SetBondOrder(j->second); for (int k = 0; k < 2; ++k) { OBAtom* atom = k == 0 ? bond->GetBeginAtom() : bond->GetEndAtom(); int new_hcount = atom->GetImplicitHCount() - (j->second - old_bond_order); if (new_hcount < 0) new_hcount = 0; atom->SetImplicitHCount(new_hcount); } } } if (!_vadel.empty() || !_vele.empty()) //delete atoms and change elements { vector<int>::iterator j; vector<vector<int> >::iterator i; if (!_vele.empty()) { vector<pair<int,int> >::iterator k; for (i = mlist.begin();i != mlist.end();++i) for (k = _vele.begin();k != _vele.end();++k) mol.GetAtom((*i)[k->first])->SetAtomicNum(k->second); } //make sure same atom isn't deleted twice vector<bool> vda; vector<OBAtom*> vdel; vda.resize(mol.NumAtoms()+1,false); for (i = mlist.begin();i != mlist.end();++i) for (j = _vadel.begin();j != _vadel.end();++j) if (!vda[(*i)[*j]]) { vda[(*i)[*j]] = true; vdel.push_back(mol.GetAtom((*i)[*j])); } vector<OBAtom*>::iterator k; for (k = vdel.begin();k != vdel.end();++k) mol.DeleteAtom((OBAtom*)*k); } mol.EndModify(); return(true); }
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(); mol.SetPartialChargesPerceived(); // Annotate origin of partial charges OBPairData *dp = new OBPairData; dp->SetAttribute("PartialCharges"); dp->SetValue("MACROMODEL"); dp->SetOrigin(fileformatInput); mol.SetData(dp); OBBond *bond; vector<OBBond*>::iterator bi; for (bond = mol.BeginBond(bi);bond;bond = mol.NextBond(bi)) if (bond->GetBondOrder() == 5 && !bond->IsInRing()) bond->SetBondOrder(1); if ( natoms != (signed)mol.NumAtoms() ) return(false); // clean out remaining blank lines std::streampos ipos; do { ipos = ifs.tellg(); ifs.getline(buffer,BUFF_SIZE); } while(strlen(buffer) == 0 && !ifs.eof() ); ifs.seekg(ipos); return(true); }