MolAtomPtr MolCoord::getAtom(const LString &chain, ResidIndex resid, const LString &aname, char cConfID /*='\0'*/) const { MolResiduePtr pResid = getResidue(chain, resid); if (pResid.isnull()) return MolAtomPtr(); int id = pResid->getAtomID(aname, cConfID); if (id<0) return MolAtomPtr(); return getAtom(id); /* if (cConfID=='\0') { int id = pResid->getAtomID(aname); if (id<0) return MolAtomPtr(); return getAtom(id); } else { LString key = aname + ":" + cConfID; int id = pResid->getAtomID(key); if (id<0) return MolAtomPtr(); return getAtom(id); } */ }
int MolCoord::appendAtomScrHelper(MolAtomPtr pAtom, const LString &ch, ResidIndex resid, const LString &resn) { qlib::uid_t nuid = pAtom->getParentUID(); if (nuid!=qlib::invalid_uid) { // pAtom has been already belonged to other mol // --> ERROR!! MB_DPRINTLN("MolCoord.appendAtom> ERROR, pAtom already belongs to mol %d ().", nuid); return -1; } pAtom->setParentUID(getUID()); pAtom->setChainName(ch); pAtom->setResIndex(resid); if (resn.isEmpty()) { // res name is determined by chain name and resindex MolResiduePtr pRes = getResidue(ch, resid); if (pRes.isnull()) { // ERROR!! cannot determine the residue to append to return -1; } pAtom->setResName(pRes->getName()); } else { pAtom->setResName(resn); } return appendAtom(pAtom); }
bool MolCoord::removeAtom(int atomid) { MolAtomPtr pAtom = getAtom(atomid); if (pAtom.isnull() || pAtom->getParentUID()!=getUID()) return false; m_atomPool.remove(atomid); // invalidate ID pAtom->setID(-1); const LString &aname = pAtom->getName(); char cConfID = pAtom->getConfID(); ResidIndex nresid = pAtom->getResIndex(); const LString &cname = pAtom->getChainName(); MolChainPtr pCh = getChain(cname); if (pCh.isnull()) return false; MolResiduePtr pRes = getResidue(cname, nresid); if (pRes.isnull()) return false; // remove atom if (!pRes->removeAtom(aname, cConfID)) return false; if (pRes->getAtomSize()>0) return true; // purge the empty residue if (!pCh->removeResidue(nresid)) return false; // delete pRes; if (pCh->getSize()>0) return true; // purge the empty chain if (!removeChain(cname)) return false; // delete pCh; return true; }
int SelCommand::isSelectedChain(MolChainPtr pCh) { if (m_pSelRoot==NULL) return true; MolChain::ResidCursor riter = pCh->begin(); int nsel=0, nresid=0; for ( ; riter!=pCh->end(); riter++) { MolResiduePtr pRes = *riter; if (pRes.isnull()) continue; if (isSelectedResid(pRes)) nsel++; nresid++; } if (nsel==nresid) return SEL_ALL; else if (nsel==0) return SEL_NONE; else return SEL_PART; }
// write PDB file to stream bool PDBFileWriter::write(qlib::OutStream &outs) { m_pMol = getTarget<MolCoord>(); if (m_pMol==NULL) { LOG_DPRINTLN("PDBWriter> MolCoord is not attached !!"); return false; } // check extension record handlers PDBFileReader::HndlrTab &htab = PDBFileReader::m_htab; bool bUseHndlr = htab.size()>0; MolCoord *pMol = m_pMol; qlib::PrintStream prs(outs); // // write header // //LString sbuf = pqsys->getVersion(); //prs.formatln("REMARK PDB File Generated by CueMol (ver %s)", sbuf.c_str()); prs.formatln("REMARK PDB File Generated by CueMol2"); // // write SSBOND record // writeSSBonds(prs); // // write LINK record // writeLinks(prs); writeSecstr(prs); // // write extension records (CRYST1) // if (bUseHndlr) { LString sbuf; PDBFileReader::HndlrTab::const_iterator iter = htab.begin(); for (; iter!=htab.end(); ++iter) { PDBFileReader::RecordHandler *ph = iter->second; if (ph!=NULL && ph->write(sbuf, pMol)) { prs.println(sbuf); } } } // // write body (ATOM/ANISOU records) // int nserial = 1; // Sort chain names by ASCII order // take care of '_' (empty) chain std::list<LString> chnames; { MolCoord::ChainIter iter = pMol->begin(); bool bHasEmptyChain = false; for (; iter!=pMol->end(); ++iter) { MolChainPtr pChn = iter->second; LString chnam = (pChn->getName().c_str()); if (chnam.equals("_")) { bHasEmptyChain = true; continue; } chnames.push_back(chnam); } chnames.sort(); if (bHasEmptyChain) chnames.push_back("_"); } std::list<LString>::const_iterator cniter = chnames.begin(); for (; cniter!=chnames.end(); ++cniter) { LString chnam = *cniter; MolChainPtr pChn = pMol->getChain(chnam); // format chain name char cch = convChainName(chnam); LString resnam; MolChain::ResidCursor2 riter = pChn->begin2(); // int nlastres = 0; for (; riter!=pChn->end2(); ++riter) { //MolResiduePtr pRes = *riter; MolResiduePtr pRes = riter->second; if (pRes.isnull()) continue; ResidIndex rindex = pRes->getIndex(); resnam = pRes->getName(); // format residue name // resnam = resnam.toUpperCase(); resnam = resnam.substr(0,3); // sort atom by AID std::list<int> atmlist; { MolResidue::AtomCursor aiter = pRes->atomBegin(); for (; aiter!=pRes->atomEnd(); ++aiter) { atmlist.push_back(aiter->second); } atmlist.sort(); } std::list<int>::const_iterator iter = atmlist.begin(); for (; iter!=atmlist.end(); ++iter) { int aid = *iter; MolAtomPtr pAtm = pMol->getAtom(aid); if (pAtm.isnull()) continue; if (!m_pSel.isnull()) { if (!m_pSel->isSelected(pAtm)) continue; // skip nonselected atom } writeAtomLine(nserial, rindex, resnam, cch, pAtm, prs); nserial++; } // nlastres = rindex.first; } // print TER record /*prs.formatln("TER " "%5d" " " "%3s " "%1s" "%4d" " ", nserial, resnam.c_str(), chnam.c_str(), nlastres);*/ prs.println("TER"); nserial ++; } //prs.println("END "); prs.println("END"); return true; }
/// read one MOL entry from stream bool MOL2MolReader::readMol(qlib::LineStream &lin, bool bskip) { LString sline; std::vector<LString> slist; for (;;) { sline = lin.readLine().chomp(); if (sline.isEmpty() && !lin.ready()) return false; // EOF if (sline.equals("@<TRIPOS>MOLECULE")) { break; } } // mol_name LString cmpd_name = lin.readLine().trim(" \t\r\n"); if (cmpd_name.isEmpty()) cmpd_name = "_"; // XXX // molecule info sline = lin.readLine().chomp(); split(sline, ' ', std::back_inserter(slist)); if (slist.size()<1) { MB_THROW(MOL2FormatException, "Invalid atom info record"); } int natoms; if (!slist[0].toInt(&natoms)) { MB_THROW(MOL2FormatException, "Invalid atom info record"); } int nbonds=0; if (slist.size()>1) { if (!slist[1].toInt(&nbonds)) { MB_THROW(MOL2FormatException, "Invalid atom info record"); } } // mol_type LString mol_type = lin.readLine().chomp(); bool bApplyTopo = false; if (mol_type.equals("PROTEIN") || mol_type.equals("NUCLEIC_ACID")) bApplyTopo = true; // Ignore charge_type // Ignore mol_comment // Search ATOM record for (;;) { sline = lin.readLine().chomp(); if (sline.isEmpty() && !lin.ready()) return false; // EOF if (sline.equals("@<TRIPOS>ATOM")) { break; } } int i, idot, iresid, naid, ind, prev_resid; ElemID eleid; double xx, yy, zz; LString aname, atype, satom, res_name; std::map<int,int> atommap; std::map<LString, int> aname_counts; std::map<LString, int>::iterator an_iter; // XXXX prev_resid = -999999; for (i=0; i<natoms; ++i) { //LOG_DPRINTLN("i=%d, natoms=%d", i, natoms); sline = lin.readLine().chomp(); slist.clear(); split(sline, ' ', std::back_inserter(slist)); if (slist.size()<8) { MB_THROW(MOL2FormatException, "Invalid atom record"); } if (!slist[0].toInt(&ind)) { MB_THROW(MOL2FormatException, "Invalid atom ID record"); } aname = slist[1]; an_iter = aname_counts.find(aname); if (an_iter==aname_counts.end()) { aname_counts.insert(std::pair<LString, int>(aname, 1)); } else { an_iter->second = an_iter->second + 1; aname = LString::format("%d%s", an_iter->second, aname.c_str()); } if (!slist[2].toRealNum(&xx)) { MB_THROW(MOL2FormatException, "Invalid atom coord record"); } if (!slist[3].toRealNum(&yy)) { MB_THROW(MOL2FormatException, "Invalid atom coord record"); } if (!slist[4].toRealNum(&zz)) { MB_THROW(MOL2FormatException, "Invalid atom coord record"); } atype = slist[5]; satom = ""; idot = atype.indexOf('.'); if (idot<0) { satom = atype; } else if (idot>0) { satom = atype.substr(0, idot); } else { MB_THROW(MOL2FormatException, "Invalid SYBYL atom type"); } iresid = 0; if (!slist[6].toInt(&iresid)) { MB_THROW(MOL2FormatException, "Invalid atom resid record"); } res_name = slist[7]; if (res_name.equals("<0>")) res_name = cmpd_name; if (bApplyTopo) { // protein or nucleic acid // strip residue number from res_name int ntmp; if (res_name.substr(3).toInt(&ntmp)) { res_name = res_name.substr(0, 3); iresid = ntmp; } if (iresid!=prev_resid) // residue is changed --> clear atom name count aname_counts.clear(); } eleid = ElemSym::str2SymID(satom); // LOG_DPRINTLN("Atom: %f, %f, %f, <%s> %d", xx, yy, zz, aname.c_str(), eleid); if (!bskip) { MolAtomPtr pAtom = MolAtomPtr(MB_NEW MolAtom()); pAtom->setParentUID(m_pMol->getUID()); pAtom->setName(aname); pAtom->setElement(eleid); pAtom->setChainName(m_sCurrChName); pAtom->setResIndex(iresid); pAtom->setResName(res_name); pAtom->setPos(Vector4D(xx,yy,zz)); pAtom->setBfac(0.0); pAtom->setOcc(1.0); naid = m_pMol->appendAtom(pAtom); if (naid<0) MB_THROW(MOL2FormatException, "appendAtom() failed"); atommap.insert(std::pair<int,int>(ind, naid)); m_nReadAtoms++; } prev_resid = iresid; } // Search BOND record for (;;) { sline = lin.readLine().chomp(); if (sline.isEmpty() && !lin.ready()) return false; // EOF if (sline.equals("@<TRIPOS>BOND")) { break; } } int natm1, natm2; int natm_id1, natm_id2; std::map<int,int>::const_iterator iter; for (i=0; i<nbonds; ++i) { sline = lin.readLine().chomp(); slist.clear(); split(sline, ' ', std::back_inserter(slist)); if (slist.size()<4) { MB_THROW(MOL2FormatException, "Invalid bond record"); } if (!slist[1].toInt(&natm1)) { MB_THROW(MOL2FormatException, "Invalid bond line (atom1)"); } if (!slist[2].toInt(&natm2)) { MB_THROW(MOL2FormatException, "Invalid bond line (atom2)"); } LString sbont = slist[3]; if (!bskip) { iter = atommap.find(natm1); if (iter==atommap.end()) MB_THROW(MOL2FormatException, "Invalid bond line (bond atom1 not found)"); natm_id1 = iter->second; iter = atommap.find(natm2); if (iter==atommap.end()) MB_THROW(MOL2FormatException, "Invalid bond line (bond atom2 not found)"); natm_id2 = iter->second; MolBond *pB = m_pMol->makeBond(natm_id1, natm_id2, true); if (pB==NULL) MB_THROW(MOL2FormatException, "makeBond failed"); if (sbont.equals("1")) pB->setType(MolBond::SINGLE); else if (sbont.equals("2")) pB->setType(MolBond::DOUBLE); else if (sbont.equals("3")) pB->setType(MolBond::TRIPLE); else if (sbont.equals("ar")||sbont.equals("am")) pB->setType(MolBond::DELOC); m_nReadBonds++; } //LOG_DPRINTLN("bond %d<-->%d: %d", natm_id1, natm_id2, nbont); } if (bApplyTopo) { m_pMol->applyTopology(); if (mol_type.equals("PROTEIN")) m_pMol->calcProt2ndry(-500.0); if (mol_type.equals("NUCLEIC_ACID")) m_pMol->calcBasePair(3.7, 30); } else { // Set noautogen prop to this residue, // to avoid topology autogen, when saved to and loaded from the qdf stream. if (!bskip) { iter = atommap.begin(); if (iter!=atommap.end()) { int aid0 = iter->second; MolAtomPtr pA = m_pMol->getAtom(aid0); if (!pA.isnull()) { MolResiduePtr pRes = pA->getParentResidue(); if (!pRes.isnull()) { pRes->setPropStr("noautogen", "true"); } } } } } /* */ return true; }
int MolCoord::appendAtom(MolAtomPtr pAtom) { pAtom->setParentUID(getUID()); const LString &cname = pAtom->getChainName(); const LString &rname = pAtom->getResName(); const LString &aname = pAtom->getName(); ResidIndex nresid = pAtom->getResIndex(); if (cname.length()<=0 || aname.length()<=0) { LString msg = LString::format("MolCoord> ERROR: appending atom with invalid properties" " (c:'%s' rn:'%s' ri:'%s' an:'%s')", cname.c_str(), rname.c_str(), nresid.toString().c_str(), aname.c_str()); MB_DPRINTLN(msg); MB_THROW(qlib::IllegalArgumentException, msg); return -1; } MolChainPtr pCh = getChain(cname); if (pCh.isnull()) { pCh = MolChainPtr(MB_NEW MolChain()); pCh->setParentUID(getUID()); pCh->setName(cname); appendChain(pCh); } MolResiduePtr pRes = pCh->getResidue(nresid); if (pRes.isnull()) { pRes = MolResiduePtr(MB_NEW MolResidue()); pRes->setParentUID(getUID()); pRes->setIndex(nresid); pRes->setName(rname); // pRes->setChainName(cname); pCh->appendResidue(pRes); } else { const LString &pre_rname = pRes->getName(); if (!pre_rname.equals(rname)) { MB_DPRINTLN("MolCoord> ERROR: appending an atom (%s %s%s %s) with inconsistent residue (%s)", cname.c_str(), rname.c_str(), nresid.toString().c_str(), aname.c_str(), pre_rname.c_str()); // TO DO: throw exception (???) // This is often the case, so is not an exception. // return -1; } } // // Append to the atompool --> assign the atom ID // int atomid = m_atomPool.put(pAtom); if (atomid<0) { // This isn't fail in normal situation. MB_THROW(qlib::RuntimeException, "append to the atompool failed"); return -1; } pAtom->setID(atomid); // MolResidue::appendAtom() must be called after setID(), // because MolResidue makes map from name to AID, which requires "AID". if (!pRes->appendAtom(pAtom)) { // This is often the case with malformed PDB files, so is not an exception. MB_DPRINTLN("MolCoord> ERROR: appending duplicated atom (%s %s%s %s)", cname.c_str(), rname.c_str(), nresid.toString().c_str(), aname.c_str()); // Remove the mis-appended atom from the pool. m_atomPool.remove(atomid); return -1; } // Update the cached xform matrix if required pAtom->resetXformMatrix(); if (!getXformMatrix().isIdent()) pAtom->setXformMatrix(getXformMatrix()); return atomid; }