Beispiel #1
0
int DynOptionswx::SetOptions(OpenBabel::OBConversion& Conv, OpenBabel::OBConversion::Option_type opttyp)
{
  //Now sets options directly in OBConversion
  int count=0;
  OMapType::iterator itr;
  for (itr = OptionMap.begin(); itr != OptionMap.end(); ++itr)
  {
    if(itr->first.empty()) continue; //just a caption or a line

    wxString oname = itr->first;
    wxString txt;

    wxCheckBox* pChk = dynamic_cast<wxCheckBox*> (itr->second);
    if(pChk)
    {
      if(!pChk->IsChecked())
      {
        // if a checkbox is not checked, ignore the subsidiary editboxes also
        while(!(++itr)->first.empty()&& itr->first[0]==_T(' '));
        --itr;
        continue;
      }
    }
    else
    {
      wxRadioButton* pRadio = dynamic_cast<wxRadioButton*> (itr->second);
      if(pRadio)
      {
        if(pRadio->GetValue())
          continue;
      }
      else
      {
        wxTextCtrl* pText = dynamic_cast<wxTextCtrl*> (itr->second);
        if(pText)
        {
          txt = pText->GetValue();
          if(txt.IsEmpty()) continue;
          oname = itr->first;
        }
      }
    }

    //Get the contents of subsequent editboxes
    OMapType::iterator itr2 = itr;
    while(++itr2!= OptionMap.end())
    {
      if((itr2->first).empty() || itr2->first[0]!=_T(' ')) //subsequent editboxes have the name preceded by a space
        break;
      txt = txt + _T(' ') + static_cast<wxTextCtrl*>(itr2->second)->GetValue();
      ++itr;
    }
    txt.Trim(true); txt.Trim(false);
    Conv.AddOption(oname.mb_str(), opttyp, txt.mb_str());
    ++count;

  }
  return count;
}
Beispiel #2
0
//
// Read the input data files
//
void readInputFiles(int argc, char** argv,
                    std::vector<Linker>& linkers, std::vector<Rigid>& rigids)
{
    // Input parser functionality for Open babel
    OpenBabel::OBConversion obConversion;
    obConversion.SetInFormat("sdf");

    //
    // For each file
    //
    for (int f = 1; f < argc; f++)
    {
        //
        // For each molecule in this file.
        //
        OpenBabel::OBMol* mol = new OpenBabel::OBMol();
        bool notatend = obConversion.ReadFile(mol, argv[f]);
        while (notatend)
        {
            //
            // Create this particular molecule type.
            //
            // Is there a better way to handle distinguising linkers vs. rigids
            // other than the name of the file (prefix)?
            switch(argv[f][0])
            {
              case 'l':
                linkers.push_back(*(new Linker(*mol)));
                break;

              case 'r':
                rigids.push_back(*(new Rigid(*mol)));
                break;

              default: 
                cerr << "Unexpected file prefix: " << argv[f][0] << " with file " << argv[f][0] << endl; 
            }

            //
            // Read the next molecule in from the file.
            //
            mol = new OpenBabel::OBMol();
            notatend = obConversion.Read(mol);
        }        
    }
}
void ReadFileThread::run()
{
  // Check that the file can be read from disk
  if (!MoleculeFile::canOpen(m_moleculeFile->m_fileName, QFile::ReadOnly | QFile::Text)) {
    // Cannot read the file
    m_moleculeFile->m_error.append(QObject::tr("File %1 cannot be opened for reading.")
                                   .arg(m_moleculeFile->m_fileName));
    return;
  }

  // Construct the OpenBabel objects, set the file type
  OpenBabel::OBConversion conv;
  OpenBabel::OBFormat *inFormat;
  if (!m_moleculeFile->m_fileType.isEmpty() &&
      !conv.SetInFormat(m_moleculeFile->m_fileType.toAscii().data())) {
    // Input format not supported
    m_moleculeFile->m_error.append(
          QObject::tr("File type '%1' is not supported for reading.")
          .arg(m_moleculeFile->m_fileType));
    return;
  }
  else {
    inFormat = conv.FormatFromExt(m_moleculeFile->m_fileName.toAscii().data());
    if (!inFormat || !conv.SetInFormat(inFormat)) {
      // Input format not supported
      m_moleculeFile->m_error
          .append(QObject::tr("File type for file '%1' is not supported for reading.")
                  .arg(m_moleculeFile->m_fileName));
      return;
    }
  }

  // set any options
  if (!m_moleculeFile->m_fileOptions.isEmpty()) {
    foreach(const QString &option, m_moleculeFile
            ->m_fileOptions.split('\n', QString::SkipEmptyParts)) {
      conv.AddOption(option.toAscii().data(), OBConversion::INOPTIONS);
    }
  }
Data::Geometry* ZMatrixCoordinates::parse(QString const& str)
{
    OpenBabel::OBConversion conv;
    conv.SetInFormat("gzmat");
    // create dummy z-matrix input
    std::string s("#\n\nzmat\n\n0  1\n");
    s += str.toStdString();

    OpenBabel::OBMol mol;
    std::istringstream iss(s);
    conv.Read(&mol, &iss);

    Data::Geometry* geometry(new Data::Geometry);

    for (::OpenBabel::OBMolAtomIter obAtom(&mol); obAtom; ++obAtom) {
        qglviewer::Vec position(obAtom->x(), obAtom->y(), obAtom->z());
        unsigned Z(obAtom->GetAtomicNum());
        geometry->append(Z, position);
    }

    geometry->computeGasteigerCharges();
    return geometry;
}
Beispiel #5
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);

}
Beispiel #6
0
void readMoleculeFile(const char* fileName)
{
    //
    // Input parser conversion functionality for Open babel
    //
    OpenBabel::OBConversion obConversion;
    obConversion.SetInFormat("SDF");

    //
    // Open the file, split the current molecule into Molecule Data (prefix)
    // and Our Data (Suffix)
    //
    std::ifstream infile;
    infile.open(fileName);

    std::string name = "UNKNOWN";
    std::string prefix = "";
    std::string suffix = "";
    
    while(splitMolecule(infile, name, prefix, suffix))
    {
        //
        // If the name of molecule is not given, overwrite it with the name of the file.
        //
        if (name == "UNKNOWN")
        {
           name = "####   ";
           name += fileName;
           name += "    ####";
        }

        if (g_debug_output) std::cerr << "Name: " << std::endl << name << std::endl;
        if (g_debug_output) std::cerr << "Prefix: " << std::endl << prefix << std::endl;
        if (g_debug_output) std::cerr << "Suffix: " << std::endl << suffix << std::endl;

        // Create and parse using Open Babel
        OpenBabel::OBMol* mol = new OpenBabel::OBMol();
        bool notAtEnd = obConversion.ReadString(mol, prefix);

        // Assign all needed data to the molecule (comment data)
        Molecule* local = createLocalMolecule(mol, fileName[0] == 'l' ? LINKER : RIGID,
                                              name, suffix);

        // calculate the molecular weight, H donors and acceptors and the plogp
        local->openBabelPredictLipinski();

        // add to logfile
        if (local->islipinskiPredicted())
        {
            std::ofstream logfile("synth_log_initial_fragments_logfile.txt",
                                  std::ofstream::out | std::ofstream::app); // append
            logfile << fileName << "\nMolWt = " << local->getMolWt() << "\n";
            logfile << "HBD = " << local->getHBD() << "\n";
            logfile << "HBA1 = " << local->getHBA1() << "\n";
            logfile << "logP = " << local->getlogP() << "\n";
            logfile << std::endl;
            logfile.close();
        }
        else std::cerr << "Main: predictLipinski failed somehow!" << endl;

        if (g_debug_output) std::cout << "Local: " << *local << "|" << std::endl;
    
        // Add to the linker or rigid list as needed.
        addMolecule(fileName[0], local); 
    }
}
int main(int argc,char **argv)
{
	std::string ifile = "";
	OpenBabel::OBSpectrophore::AccuracyOption accuracy = OpenBabel::OBSpectrophore::AngStepSize20;
	OpenBabel::OBSpectrophore::StereoOption stereo = OpenBabel::OBSpectrophore::NoStereoSpecificProbes;
	OpenBabel::OBSpectrophore::NormalizationOption normalization = OpenBabel::OBSpectrophore::NoNormalization;
	double resolution = 3.0;
	int c;
	
	opterr = 0;
	std::string msg;
	
	while ((c = getopt(argc, argv, "ui:n:a:s:r:h")) != -1)
	{
		switch (c)
		{
			case 'u':
            showImplementationDetails(argv[0]);
            exit(1);
				break;
				
			case 'i':
				if (!isValidValue('i', optarg))
				{
					msg = "Option -i is followed by an invalid argument: ";
					msg += optarg;
					showError(msg);
					exit(1);
				}
				else
				{
					ifile = optarg;
				}
				break;
				
			case 'n':
				if (!isValidValue('n', optarg))
				{
					msg = "Option -n is followed by an invalid argument: ";
					msg += optarg;
					showError(msg);
					exit(1);
				}
				else normalization = stringToNormalizationOption(optarg);
				break;
				
			case 'a':
				if (!isValidValue('a', optarg))
				{
					msg = "Option -a is followed by an invalid argument: ";
					msg += optarg;
					showError(msg);
					exit(1);
				}
				else accuracy = stringToAccuracyOption(optarg);
				break;
				
			case 's':
				if (!isValidValue('s', optarg))
				{
					msg = "Option -s is followed by an invalid argument: ";
					msg += optarg;
					showError(msg);
					exit(1);
				}
				else stereo = stringToStereoOption(optarg);
				break;
				
			case 'r':
				if (!isValidValue('r', optarg))
				{
					msg = "Option -r is followed by an invalid argument: ";
					msg += optarg;
					showError(msg);
					exit(1);
				}
				else
				{
					resolution = atof(optarg);
					if (resolution <= 0)
					{
						msg = "Resolution -r should be larger than 0.0: ";
						msg += optarg;
						showError(msg);
						exit(1);
					}
				}
				break;
				
			case 'h':
				showHelp(argv[0]);
				exit(0);
				break;
				
			case '?':
				if ((optopt == 'i') || 
						(optopt == 'n') || 
						(optopt == 'a') || 
						(optopt == 's') || 
						(optopt == 'r'))
				{
					msg = "Option -";
					msg += optopt;
					msg += " requires an argument.";
					showError(msg);
					exit(1);
				}
				else
				{
					msg = "Unknown option -";
					msg += optopt;
					msg += ".";
					showError(msg);
					exit(1);
				}
				break;
				
			default:
				showError("Unknown option");
				exit(1);
				break;
		}
	}
	
	// The input file (-i) is the only required option
	if (ifile.empty())
	{
		msg = "Input file specification is required (option -i).";
		showError(msg);
		exit(1);
	}
	OpenBabel::OBConversion obconversion;
	OpenBabel::OBFormat *format = obconversion.FormatFromExt(ifile.c_str());
	if (!format)
	{
		msg = "Could not find file format for ";
		msg += ifile;
		showError(msg);
		exit(1);
	}
	obconversion.SetInFormat(format);
	std::ifstream ifs;
	ifs.open(ifile.c_str());
	obconversion.SetInStream(&ifs);
	
	// Start calculations
	OpenBabel::OBMol mol;
	OpenBabel::OBSpectrophore spec;
	spec.SetAccuracy(accuracy);
	spec.SetNormalization(normalization);
	spec.SetStereo(stereo);
	spec.SetResolution(resolution);
	showParameters(spec, ifile);
	unsigned int count(0);
	while (obconversion.Read(&mol))
	{
		std::vector<double> result = spec.GetSpectrophore(&mol);
		if (result.empty()) {
			std::cerr << "Error calculating Spectrophore from molecule number ";
			std::cerr << count;
			std::cerr << " (counting starts at 0)!";
			std::cerr << std::endl;
		}
		else
		{
			std::cout << mol.GetTitle() << "\t";
			for (unsigned int i(0); i < result.size(); ++i)
			{
				std::cout << result[i] << "\t";
			}
			std::cout << std::endl;
		}
		mol.Clear();
		++count;
	}
	return 0;
}