/** * Fill in dependency list for all MathExpns on reactions. * Note that when a MathExpn updates, it alters a further * molecule, that may be a substrate for another reaction. * So we need to also add further dependent reactions. * In principle we might also cascade to deeper MathExpns. Later. */ void Gsolve::fillMathDep() { // create map of funcs that depend on specified molecule. vector< vector< unsigned int > > funcMap( stoichPtr_->getNumAllPools()); unsigned int numFuncs = stoichPtr_->getNumFuncs(); for ( unsigned int i = 0; i < numFuncs; ++i ) { const FuncTerm *f = stoichPtr_->funcs( i ); vector< unsigned int > molIndex; unsigned int numMols = f->getReactants( molIndex ); for ( unsigned int j = 0; j < numMols; ++j ) funcMap[ molIndex[j] ].push_back( i ); } // The output of each func is a mol indexed as // numVarMols + numBufMols + i unsigned int funcOffset = stoichPtr_->getNumVarPools() + stoichPtr_->getNumBufPools(); unsigned int numRates = stoichPtr_->getNumRates(); sys_.dependentMathExpn.resize( numRates ); vector< unsigned int > indices; for ( unsigned int i = 0; i < numRates; ++i ) { vector< unsigned int >& dep = sys_.dependentMathExpn[ i ]; dep.resize( 0 ); // Extract the row of all molecules that depend on the reac. const int* entry; const unsigned int* colIndex; unsigned int numInRow = sys_.transposeN.getRow( i, &entry, &colIndex ); for ( unsigned int j = 0; j < numInRow; ++j ) { unsigned int molIndex = colIndex[j]; vector< unsigned int >& funcs = funcMap[ molIndex ]; dep.insert( dep.end(), funcs.begin(), funcs.end() ); for ( unsigned int k = 0; k < funcs.size(); ++k ) { unsigned int outputMol = funcs[k] + funcOffset; // Insert reac deps here. Columns are reactions. vector< int > e; // Entries: we don't need. vector< unsigned int > c; // Column index: the reactions. stoichPtr_->getStoichiometryMatrix(). getRow( outputMol, e, c ); // Each of the reacs (col entries) depend on this func. vector< unsigned int > rdep = sys_.dependency[i]; rdep.insert( rdep.end(), c.begin(), c.end() ); } } } }
//*--------------------------------------------------------------------------*// //* MAIN MAIN *// //*--------------------------------------------------------------------------*// int main(int argc, char* argv[]) { // Initialise random number generator srandom(time(NULL)); clock_t t0 = clock(); // Print header printHeader(); // Read options Options uo = parseCommandLine(argc,argv); if(!uo.noHybrid) { if(uo.funcGroupVec[AROM] && uo.funcGroupVec[LIPO]) { uo.funcGroupVec[HYBL] = true; } if(uo.funcGroupVec[HDON] && uo.funcGroupVec[HACC]) { uo.funcGroupVec[HYBH] = true; } } std::cerr << uo.print() << std::endl; if (uo.version) { printHeader(); exit(0); } if (uo.help) { printUsage(); exit(0); } // Db file and pharmacophore out are mandatory elements if (uo.dbInpFile.empty()) { mainErr("Missing database file. This is a required option (-d)."); } if (uo.pharmOutFile.empty() && uo.molOutFile.empty() && uo.scoreOutFile.empty()) { mainErr("No output file defined. So there is actually no use to compute anything at all."); } if ((uo.pharmOutFile.empty() && uo.scoreOutFile.empty()) && !uo.molOutFile.empty()) { mainErr("No file defined to write pharmacophore information."); } if (uo.refInpFile.empty() && uo.pharmOutFile.empty() && uo.molOutFile.empty() && !uo.scoreOutFile.empty()) { mainErr("Only score file requested when no reference is given. Unable to generate this output."); } // Reference variables Pharmacophore refPharm; refPharm.clear(); std::string refId; double refVolume(0.0); int refSize(0); int exclSize(0); // Database variables std::vector<Result*> resList; Pharmacophore dbPharm; std::string dbId; double dbVolume(0.0); int dbSize(0); //---------------------------------------------------------------------------- //...(A).. Process the reference //---------------------------------------------------------------------------- if (!uo.refInpFile.empty()) { //------------------------------------------------------- //...(1).. get reference pharmacophore //------------------------------------------------------- if (uo.refInpType == UNKNOWN) { std::string ext(getExt(uo.refInpFile)); if (ext == ".phar") { uo.refInpType = PHAR; } else { uo.refInpType = MOL; } } if (uo.refInpType == MOL) { OpenBabel::OBMol m; OpenBabel::OBConversion* reader = new OpenBabel::OBConversion(); reader->SetInFormat(reader->FormatFromExt(uo.refInpFile.c_str())); if (!reader->Read(&m, uo.refInpStream)) { mainErr("Unable to read reference molecule"); } calcPharm(&m, &refPharm, uo); refId = m.GetTitle(); delete reader; reader = NULL; } else if (uo.refInpType == PHAR) { PharmacophoreReader* reader = new PharmacophoreReader(); refPharm = reader->read(uo.refInpStream, refId); if (refPharm.empty()) { mainErr("Error reading reference pharmacophore"); } delete reader; reader = NULL; } else { mainErr("Unknown format of reference molecule."); } //------------------------------------------------------- //...(2).. process reference pharmacophore //------------------------------------------------------- if (uo.merge) { pharMerger.merge(refPharm); } refSize = refPharm.size(); for (unsigned int i(0); i < refSize; ++i) { if (refPharm[i].func == EXCL) { // extract overlap with exclusion spheres for (unsigned int j(0); j < refPharm.size(); ++j) { if (refPharm[j].func != EXCL) { refVolume -= VolumeOverlap(refPharm[i], refPharm[j], !uo.noNormal); } } exclSize++; } else { // add point self-overlap refVolume += VolumeOverlap(refPharm[i], refPharm[i], !uo.noNormal); } } if(!uo.isQuiet) { std::cerr << "Reference pharmacophore " << refId << std::endl; std::cerr << " number of points: " << refSize - exclSize << std::endl; std::cerr << " number of exclusion spheres: " << exclSize << std::endl; std::cerr << " totalvolume: " << refVolume << std::endl; } } //---------------------------------------------------------------------------- //...(B).. Process the database file //---------------------------------------------------------------------------- // DB files if (uo.dbInpType == UNKNOWN) { std::string ext(getExt(uo.dbInpFile)); if (ext==".phar") { uo.dbInpType = PHAR; } else { uo.dbInpType = MOL; } } // local storage of the rotation matrix SiMath::Matrix rotMat(3,3,0.0); unsigned int molCount(0); OpenBabel::OBConversion* molReader = NULL; PharmacophoreReader* pharmReader = NULL; if (uo.dbInpType == PHAR) { pharmReader = new PharmacophoreReader(); } else if (uo.dbInpType == MOL) { molReader = new OpenBabel::OBConversion(); molReader->SetInFormat(molReader->FormatFromExt(uo.dbInpFile.c_str())); molReader->SetInStream(uo.dbInpStream); } else { mainErr("Unknown format of db file."); } bool done(false); OpenBabel::OBMol m; while (!done) { dbPharm.clear(); m.Clear(); if (uo.dbInpType == MOL) { if (!molReader->Read(&m)) { done = true; break; } else { calcPharm(&m, &dbPharm, uo); dbId = m.GetTitle(); } } else { if (uo.dbInpStream->eof()) { done = true; break; } else { dbPharm = pharmReader->read(uo.dbInpStream, dbId); } } if (dbPharm.empty()) { continue; } ++molCount; if (!uo.isQuiet ) { if ((molCount % 10) == 0) { std::cerr << "." << std::flush; } if ((molCount % 500) == 0) { std::cerr << molCount << std::endl << std::flush; } } if (uo.merge) { pharMerger.merge(dbPharm); } if (uo.refInpFile.empty()) { if (!(uo.isQuiet)) { printProgress(molCount); } if( !uo.pharmOutFile.empty()) { uo.pharmOutWriter->write(dbPharm, uo.pharmOutStream, dbId); } continue; } //------------------------------------------------------- //...(1).. Alignment //------------------------------------------------------- dbSize = dbPharm.size(); dbVolume = 0.0; for (unsigned int i(0); i < dbSize; ++i) { if (dbPharm[i].func == EXCL) { continue; } dbVolume += VolumeOverlap(dbPharm[i], dbPharm[i], !uo.noNormal); } // Create a result structure Result res; res.refId = refId; res.refVolume = refVolume; res.dbId = dbId; res.dbVolume = dbVolume; res.overlapVolume = 0.0; res.exclVolume = 0.0; res.resMol = m; res.resPharSize = 0; if (uo.scoreOnly) { FunctionMapping funcMap(&refPharm, &dbPharm, uo.epsilon); PharmacophoreMap fMap = funcMap.getNextMap(); double volBest(-9999.999); // loop over all reference points while (!fMap.empty()) { double newVol(0.0); double exclVol(0.0); for (PharmacophoreMap::iterator itP = fMap.begin(); itP != fMap.end(); ++itP) { if ((itP->first)->func == EXCL) { exclVol += VolumeOverlap((itP->first), (itP->second), !uo.noNormal); } else if (((itP->first)->func == (itP->second)->func ) || (((itP->first)->func == HYBH || (itP->first)->func == HDON || (itP->first)->func == HACC) && ((itP->second)->func == HDON || (itP->second)->func == HACC || (itP->second)->func == HYBH)) || (((itP->first)->func == HYBL || (itP->first)->func == AROM || (itP->first)->func == LIPO) && ((itP->second)->func == AROM || (itP->second)->func == LIPO || (itP->second)->func == HYBL))) { newVol += VolumeOverlap((itP->first),(itP->second), !uo.noNormal); } } if ((newVol - exclVol) > volBest) { res.resPhar.clear(); res.resPharSize = 0; for (PharmacophoreMap::iterator itP = fMap.begin(); itP != fMap.end(); ++itP) { // add point to resulting pharmacophore PharmacophorePoint p(itP->second); (res.resPhar).push_back(p); ++res.resPharSize; } res.overlapVolume = newVol; res.exclVolume = exclVol; volBest = newVol - exclVol; } // get the next map fMap.clear(); fMap = funcMap.getNextMap(); } } else { FunctionMapping funcMap(&refPharm, &dbPharm, uo.epsilon); PharmacophoreMap fMap = funcMap.getNextMap(); PharmacophoreMap bestMap; // default solution SolutionInfo best; best.volume = -999.9; // rotor is set to no rotation best.rotor.resize(4); best.rotor = 0.0; best.rotor[0] = 1.0; double bestScore = -1000; int mapSize(fMap.size()); int maxSize = mapSize - 3; while (!fMap.empty()) { int msize = fMap.size(); // add the exclusion spheres to the alignment procedure if (uo.withExclusion) { for (unsigned int i(0); i < refSize ; ++i) { if (refPharm[i].func != EXCL) { continue; } for (unsigned int j(0); j < dbSize; ++j) { if (dbPharm[j].func == EXCL) { continue; } fMap.insert(std::make_pair(&(refPharm[i]), &(dbPharm[j]))); } } } // Only align if the expected score has any chance of being larger // than best score so far if ((msize > maxSize) && (((double) msize / (refSize - exclSize + dbSize - msize)) > bestScore)) { Alignment align(fMap); SolutionInfo r = align.align(!uo.noNormal); if (best.volume < r.volume) { best = r; bestScore = best.volume / (refVolume + dbVolume - best.volume); bestMap = fMap; mapSize = msize; } } else { // Level of mapping site to low break; } if (bestScore > 0.98) { break; } // Get the next map fMap.clear(); fMap = funcMap.getNextMap(); } // Transform the complete pharmacophore and the molecule towards the // best alignment rotMat = quat2Rotation(best.rotor); positionPharmacophore(dbPharm, rotMat, best); positionMolecule(&res.resMol, rotMat, best); // Update result res.info = best; // Compute overlap volume between exlusion spheres and pharmacophore // points for (int i(0); i < refSize; ++i) { if (refPharm[i].func != EXCL) { continue; } for (int j(0); j < dbSize; ++j) { res.exclVolume += VolumeOverlap(refPharm[i], dbPharm[j], !uo.noNormal); } } // make copy of the best map and compute the volume overlap for (PharmacophoreMap::iterator itP = bestMap.begin(); itP != bestMap.end(); ++itP) { if(((itP->first)->func == EXCL) || ((itP->second)->func == EXCL)) { continue; } // compute overlap res.overlapVolume += VolumeOverlap(itP->first, itP->second, !uo.noNormal); // add point to resulting pharmacophore PharmacophorePoint p(itP->second); (res.resPhar).push_back(p); ++res.resPharSize; } } // update scores res.info.volume = res.overlapVolume - res.exclVolume; if (res.info.volume > 0.0) { res.tanimoto = res.info.volume / (res.refVolume + res.dbVolume - res.info.volume); res.tversky_ref = res.info.volume / res.refVolume; res.tversky_db = res.info.volume / res.dbVolume; } switch (uo.rankby) { case TANIMOTO: res.rankbyScore = res.tanimoto; break; case TVERSKY_REF: res.rankbyScore = res.tversky_ref; break; case TVERSKY_DB: res.rankbyScore = res.tversky_db; break; } //------------------------------------------------------- //...(5).. Generate output //------------------------------------------------------- if (uo.cutOff != 0.0) { if (res.rankbyScore < uo.cutOff) { continue; } } if (uo.best != 0) { addBest(res, uo, resList); } else { if (!uo.molOutFile.empty()) { logOut(&res, uo); } if (!uo.pharmOutFile.empty()) { logPharmacophores(&res, uo); } if (!uo.scoreOutFile.empty()) { logScores(&res, uo); } } } if (molReader) { delete molReader; molReader = NULL; } if (pharmReader) { delete pharmReader; pharmReader = NULL; } //---------------------------------------------------------------------------- //...(C).. Process best list (if defined) //---------------------------------------------------------------------------- if (uo.best != 0) { std::vector<Result*>::iterator itR; for (itR = resList.begin(); itR != resList.end(); ++itR) { Result* res(*itR); if (!uo.molOutFile.empty()) { logOut(res, uo); } if (!uo.pharmOutFile.empty()) { logPharmacophores(res, uo); } if (!uo.scoreOutFile.empty()) { logScores(res, uo); } delete res; } } // done processing database if (!uo.isQuiet) { if (uo.refInpFile.empty()) { std::cerr << std::endl; std::cerr << "Processed " << molCount << " molecules"; double tt = (double)(clock() - t0 )/CLOCKS_PER_SEC; std::cerr << " in " << tt << " seconds ("; std::cerr << molCount/tt << " molecules per second)." << std::endl; } else { std::cerr << std::endl; std::cerr << "Processed " << molCount << " molecules" << std::endl; double tt = (double)(clock() - t0 )/CLOCKS_PER_SEC; std::cerr << molCount << " alignments in " << tt << " seconds ("; std::cerr << molCount/tt << " alignments per second)." << std::endl; } } exit(0); }