//*--------------------------------------------------------------------------*// //* 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); }
Options parseCommandLine(int argc, char* argv[]) { static struct option Arguments[] = { { "version", no_argument, NULL, 'v' }, { "reference", required_argument, NULL, 'r' }, { "dbase", required_argument, NULL, 'd' }, { "scores", required_argument, NULL, 's' }, { "out", required_argument, NULL, 'o' }, { "format", required_argument, NULL, 'f' }, { "scoreOnly", no_argument, NULL, 1 }, { "rankBy", required_argument, NULL, 2 }, { "best", required_argument, NULL, 4 }, { "addIterations", required_argument, NULL, 5 }, { "cutoff", required_argument, NULL, 6 }, { "noRef", no_argument, NULL, 11 }, { "help", no_argument, NULL, 'h' } }; Options o; int choice; opterr = 0; int optionIndex = 0; std::string s; std::string format; format.clear(); while((choice = getopt_long(argc, argv,"vhpr:d:s:o:f:", Arguments, &optionIndex )) != -1) { switch (choice) { case 'v': //....................................................version o.version = true; break; case 'r': //..................................................reference o.refInpFile = optarg; o.refInpStream = new std::ifstream(optarg); if (!o.refInpStream->good()) { mainErr("Error opening input file for reference (-r)"); } o.refInpReader = new RDKit::SDMolSupplier(o.refInpStream); break; case 'd': //......................................................dbase o.dbInpFile = optarg; o.dbInpStream = new std::ifstream(optarg); if (!o.dbInpStream->good()) { mainErr("Error opening input file for database (-d)"); } o.dbInpReader = new RDKit::SDMolSupplier(o.dbInpStream); break; case 's': //.....................................................scores o.scoreOutFile = optarg; o.scoreOutStream = new std::ofstream(optarg); if (!o.scoreOutStream->good()) { mainErr("Error opening output file for scores (-s)"); } break; case 'o': //........................................................out o.molOutFile = optarg; o.molOutStream = new std::ofstream(optarg); if (!o.molOutStream->good()) { mainErr("Error opening output file for molecules (-o)"); } o.molOutWriter = new RDKit::SDWriter(o.molOutStream); break; case 'f': //.....................................................format format = optarg; break; case 1: //....................................................scoreOnly o.scoreOnly = true; break; case 2: //.......................................................rankBy s = optarg; transform(s.begin(), s.end(), s.begin(), toupper); if (s == "TANIMOTO") { o.whichScore = tanimoto; } else if (s == "TVERSKY_DB") { o.whichScore = tversky_db; } else if (s == "TVERSKY_REF") { o.whichScore = tversky_ref; } break; case 4: //.........................................................best o.bestHits = strtol(optarg, NULL, 10); break; case 5: //................................................addIterations o.maxIter = strtol(optarg, NULL, 10); break; case 6: //.......................................................cutoff o.cutOff = strtod(optarg, NULL); if (o.cutOff > 1) { o.cutOff = 1.0; } else if (o.cutOff < 0) { o.cutOff = 0.0; } break; case 11: //.......................................................noRef o.showRef = false; break; case 'h': //.......................................................help o.help = true; break; default: mainErr("Unknown command line option"); } } // If no options are given print the help if (optind == 1) { o.help = true; } argc -= optind; argv += optind; return o; }