Exemple #1
0
//*--------------------------------------------------------------------------*//
//* 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;
}