int main() { OBAtom a, b, c; a.SetAtomicNum(8); b.SetAtomicNum(6); c.SetAtomicNum(8); OBMol mol; mol.AddAtom(a); mol.AddAtom(b); mol.AddAtom(c); mol.AddBond(1,2,2); mol.AddBond(2,3,2); OBConversion conv; conv.SetOutFormat("SMI"); cout << conv.WriteString(&mol,1) << endl; OBSmartsPattern sp; sp.Init ("C~*"); sp.Match (mol,false); cout << sp.NumMatches() << endl; cout << sp.GetUMapList().size() << endl; return EXIT_SUCCESS; }
bool OpExtraOut::Do(OBBase* pOb, const char* OptionText, OpMap* pmap, OBConversion* pConv) { /* OptionText contains an output filename with a format extension. Make an OBConversion object with this as output destination. Make a copy the current OBConversion and replace the output format by an instance of ExtraFormat. This then does all the subsequent work. */ if(!pConv || !OptionText || *OptionText=='\0') return true; //silent no-op. false would prevent the main output if(pConv->IsFirstInput()) { OBConversion* pExtraConv = new OBConversion(*pConv); //copy ensures OBConversion::Index>-1 std::ofstream* ofs; if( (ofs = new std::ofstream(OptionText)) ) // extra parens to indicate truth value pExtraConv->SetOutStream(ofs); if(!ofs || !pExtraConv->SetOutFormat(OBConversion::FormatFromExt(OptionText))) { obErrorLog.ThrowError(__FUNCTION__, "Error setting up extra output file", obError); return true; } OBConversion* pOrigConv = new OBConversion(*pConv); //Make an instance of ExtraFormat and divert the output to it. It will delete itself. pConv->SetOutFormat(new ExtraFormat(pOrigConv, pExtraConv)); } return true; }
void testPdbOccupancies() { // See https://github.com/openbabel/openbabel/pull/1558 OBConversion conv; OBMol mol; conv.SetInFormat("cif"); conv.SetOutFormat("pdb"); conv.ReadFile(&mol, GetFilename("test08.cif")); string pdb = conv.WriteString(&mol); conv.AddOption("o", OBConversion::OUTOPTIONS); pdb = conv.WriteString(&mol); OB_ASSERT(pdb.find("HETATM 1 NA UNL 1 0.325 0.000 4.425 0.36") != string::npos); OB_ASSERT(pdb.find("HETATM 17 O UNL 8 1.954 8.956 3.035 1.00") != string::npos); OBMol mol_pdb; conv.SetInFormat("pdb"); conv.ReadFile(&mol_pdb, GetFilename("test09.pdb")); pdb = conv.WriteString(&mol_pdb); OB_ASSERT(pdb.find("HETATM 1 NA UNL 1 0.325 0.000 4.425 0.36") != string::npos); OB_ASSERT(pdb.find("HETATM 2 NA UNL 1 0.002 8.956 1.393 0.10") != string::npos); OB_ASSERT(pdb.find("HETATM 17 O UNL 8 1.954 8.956 3.035 1.00") != string::npos); }
void testSpaceGroupClean() { // See https://github.com/openbabel/openbabel/pull/254 OBConversion conv; OBMol mol; conv.SetInFormat("cif"); conv.SetOutFormat("pdb"); conv.ReadFile(&mol, GetFilename("test02.cif")); OBUnitCell* pUC = (OBUnitCell*)mol.GetData(OBGenericDataType::UnitCell); const SpaceGroup* pSG = pUC->GetSpaceGroup(); SpaceGroup* sg = new SpaceGroup(*pSG); pSG = SpaceGroup::Find(sg); OB_ASSERT( pSG != NULL ); // Check also for errors and warnings string summary = obErrorLog.GetMessageSummary(); OB_ASSERT( summary.find("error") == string::npos); OB_ASSERT( summary.find("warning") == string::npos); OB_ASSERT( pSG->GetId() == 166 ); string pdb = conv.WriteString(&mol); pdb = conv.WriteString(&mol); OB_ASSERT(pdb.find("H -3 m") != string::npos); }
// Reading an InChI and then adding hydrogens messed up the structure void test_Issue134_InChI_addH() { OBConversion conv; conv.SetInFormat("inchi"); OBMol mol; conv.ReadString(&mol, "InChI=1S/C2H7NO/c1-2(3)4/h2,4H,3H2,1H3/t2-/m0/s1"); OB_ASSERT(!mol.HasData(OBGenericDataType::VirtualBondData)); mol.AddHydrogens(); conv.SetOutFormat("smi"); std::string res = conv.WriteString(&mol, true); OB_COMPARE(res, "C[C@@H](N)O"); }
void testCIFMolecules() { // See https://github.com/openbabel/openbabel/pull/1558 OBConversion conv; OBMol mol; conv.SetInFormat("cif"); conv.SetOutFormat("smi"); // check for disconnected fragments conv.ReadFile(&mol, GetFilename("1519159.cif")); string smi = conv.WriteString(&mol); // never, never disconnected fragments from a molecule OB_ASSERT(smi.find(".") == string::npos); }
void testPdbRemSpacesHMName() { // See https://github.com/openbabel/openbabel/pull/1558 OBConversion conv; OBMol mol; conv.SetInFormat("cif"); conv.SetOutFormat("pdb"); conv.ReadFile(&mol, GetFilename("test07.cif")); string pdb = conv.WriteString(&mol); conv.AddOption("o", OBConversion::OUTOPTIONS); pdb = conv.WriteString(&mol); OB_ASSERT(pdb.find("I41/amd:2") != string::npos); }
void testPdbOutHexagonalAlternativeOrigin2() { // See https://github.com/openbabel/openbabel/pull/1558 OBConversion conv; OBMol mol; conv.SetInFormat("cif"); conv.SetOutFormat("pdb"); conv.ReadFile(&mol, GetFilename("test06.cif")); string pdb = conv.WriteString(&mol); conv.AddOption("o", OBConversion::OUTOPTIONS); pdb = conv.WriteString(&mol); OB_ASSERT(pdb.find("H -3 m") != string::npos); }
// A segfault was occuring when a Universal SMILES was output after an InChIfied SMILES. // This was due to short-circuit caching of InChIs on reading. The fix was to limit // the situations when the cached value was used, but also to delete the cached value // in this particular instance. void test_Issue135_UniversalSmiles() { // Test writing U smiles after I smiles OBConversion conv; conv.SetInFormat("smi"); OBMol mol; conv.ReadString(&mol, "C(=O)([O-])C(=O)O"); conv.SetOutFormat("smi"); conv.SetOptions("I", OBConversion::OUTOPTIONS); std::string res = conv.WriteString(&mol, true); OB_COMPARE(res, "C(=O)(C(=O)O)[O-]"); conv.SetOptions("U", OBConversion::OUTOPTIONS); res = conv.WriteString(&mol, true); OB_COMPARE(res, "C(=O)(C(=O)[O-])O"); }
int main(int argc, char **argv) { if (argc < 2) { std::cout << "Usage: " << argv[0] << " <filename>" << std::endl; return 1; } // Read the file shared_ptr<OBMol> mol = GetMol(argv[1]); // Create the OBConformerSearch object OBConformerSearch cs; // Setup std::cout << "Setting up conformer searching..." << std::endl << " conformers: 30" << std::endl << " children: 5" << std::endl << " mutability: 5" << std::endl << " convergence: 25" << std::endl; cs.Setup(*mol.get(), 30, // numConformers 5, // numChildren 5, // mutability 25); // convergence // Perform searching cs.Search(); // Print the rotor keys RotorKeys keys = cs.GetRotorKeys(); for (RotorKeys::iterator key = keys.begin(); key != keys.end(); ++key) { for (unsigned int i = 1; i < key->size(); ++i) std::cout << key->at(i) << " "; std::cout << std::endl; } // Get the conformers cs.GetConformers(*mol.get()); std::cout << mol->NumConformers() << std::endl; OBConversion conv; conv.SetOutFormat("sdf"); for (unsigned int c = 0; c < mol->NumConformers(); ++c) { mol->SetConformer(c); conv.Write(mol.get(), &std::cerr); } }
int main(int argc, char **argv) { // Define location of file formats for testing #ifdef FORMATDIR char env[BUFF_SIZE]; snprintf(env, BUFF_SIZE, "BABEL_LIBDIR=%s", FORMATDIR); putenv(env); #endif std::ifstream ifs(GetFilename("canonstable.can").c_str()); OB_REQUIRE( ifs ); OBMol mol; OBConversion conv; conv.SetInFormat("smi"); conv.SetOutFormat("can"); std::string line; while (std::getline(ifs, line)) { OB_REQUIRE( conv.ReadString(&mol, line.c_str()) ); std::vector<OBAtom*> atoms; FOR_ATOMS_OF_MOL(atom, mol) atoms.push_back(&*atom); for (int i = 0; i < 5; ++i) { // shuffle the atoms std::random_shuffle(atoms.begin(), atoms.end()); mol.RenumberAtoms(atoms); // get can smiles mol.SetTitle(""); std::string cansmi = conv.WriteString(&mol, true); // comapare with ref if (cansmi != line) { cout << "ref = " << line << endl; cout << "can = " << cansmi << endl; OB_ASSERT( cansmi == line ); } } } return 0; }
void testPdbOutAlternativeOrigin() { // See https://github.com/openbabel/openbabel/pull/1558 OBConversion conv; OBMol mol; conv.SetInFormat("cif"); conv.SetOutFormat("pdb"); conv.ReadFile(&mol, GetFilename("test04.cif")); string pdb = conv.WriteString(&mol); // ending space is needed to check that there is no origin set OB_ASSERT(pdb.find("P 4/n b m ") != string::npos); conv.AddOption("o", OBConversion::OUTOPTIONS); pdb = conv.WriteString(&mol); OB_ASSERT(pdb.find("P 4/n b m:1") != string::npos); }
bool OpReadConformers::ProcessVec(std::vector<OBBase*>& vec) { // DeferredFormat collects all the molecules, they are processed here, and Deferred Format outputs them OBConversion smconv; smconv.AddOption("n"); if(!smconv.SetOutFormat("smi")) { obErrorLog.ThrowError(__FUNCTION__, "SmilesFormat is not loaded" , obError, onceOnly); return false; } std::string smiles, stored_smiles; OBMol* stored_pmol=NULL; std::vector<OBBase*>::iterator iter; for(iter= vec.begin();iter!=vec.end();++iter) { OBMol* pmol = dynamic_cast<OBMol*>(*iter); if(!pmol) continue; smiles = smconv.WriteString(pmol); Trim(smiles); if(stored_smiles==smiles) { //add the coordinates of the current mol to the stored one as a conformer, and delete current mol double *confCoord = new double [pmol->NumAtoms() * 3]; memcpy((char*)confCoord,(char*)pmol->GetCoordinates(),sizeof(double)*3*pmol->NumAtoms()); stored_pmol->AddConformer(confCoord); delete pmol; *iter = NULL; } else { stored_pmol = pmol; stored_smiles = smiles; } } //erase the NULLS vec.erase(std::remove(vec.begin(),vec.end(), (void*)NULL), vec.end()); return true; }
bool FastSearchFormat::ObtainTarget(OBConversion* pConv, vector<OBMol>& patternMols, const string& indexname) { //Obtains an OBMol from: // the filename in the -s option or // the SMARTS string in the -s option or // by converting the file in the -S or -aS options (deprecated). // If there is no -s -S or -aS option, information on the index file is displayed. OBMol patternMol; patternMol.SetIsPatternStructure(); const char* p = pConv->IsOption("s",OBConversion::GENOPTIONS); bool OldSOption=false; //If no -s option, make OBMol from file in -S option or -aS option (both deprecated) if(!p) { p = pConv->IsOption("S",OBConversion::GENOPTIONS); if(!p) p = pConv->IsOption("S",OBConversion::INOPTIONS);//for GUI mainly OldSOption = true; } if(p) { vector<string> vec; tokenize(vec, p); //ignore leading ~ (not relevant to fastsearch) if(vec[0][0]=='~') vec[0].erase(0,1); if(vec.size()>1 && vec[1]=="exact") pConv->AddOption("e", OBConversion::INOPTIONS); OBConversion patternConv; OBFormat* pFormat; //Interpret as a filename if possible string& txt =vec [0]; if( txt.empty() || txt.find('.')==string::npos || !(pFormat = patternConv.FormatFromExt(txt.c_str())) || !patternConv.SetInFormat(pFormat) || !patternConv.ReadFile(&patternMol, txt) || patternMol.NumAtoms()==0) //if false, have a valid patternMol from a file { //is SMARTS/SMILES //Replace e.g. [#6] in SMARTS by C so that it can be converted as SMILES //for the fingerprint phase, but allow more generality in the SMARTS phase. for(;;) { string::size_type pos1, pos2; pos1 = txt.find("[#"); if(pos1==string::npos) break; pos2 = txt.find(']'); int atno; if(pos2!=string::npos && (atno = atoi(txt.substr(pos1+2, pos2-pos1-2).c_str())) && atno>0) txt.replace(pos1, pos2-pos1+1, etab.GetSymbol(atno)); else { obErrorLog.ThrowError(__FUNCTION__,"Ill-formed [#n] atom in SMARTS", obError); return false; } } bool hasTildeBond; if( (hasTildeBond = (txt.find('~')!=string::npos)) ) // extra parens to indicate truth value { //Find ~ bonds and make versions of query molecule with a single and aromatic bonds //To avoid having to parse the SMILES here, replace ~ by $ (quadruple bond) //and then replace this in patternMol. Check first that there are no $ already //Sadly, isocynanides may have $ bonds. if(txt.find('$')!=string::npos) { obErrorLog.ThrowError(__FUNCTION__, "Cannot use ~ bonds in patterns with $ (quadruple) bonds.)", obError); return false; } replace(txt.begin(),txt.end(), '~' , '$'); } //read as standard SMILES patternConv.SetInFormat("smi"); if(!patternConv.ReadString(&patternMol, vec[0])) { obErrorLog.ThrowError(__FUNCTION__,"Cannot read the SMILES string",obError); return false; } if(hasTildeBond) { AddPattern(patternMols, patternMol, 0); //recursively add all combinations of tilde bond values return true; } } else { // target(s) are in a file patternMols.push_back(patternMol); while(patternConv.Read(&patternMol)) patternMols.push_back(patternMol); return true; } } if(OldSOption) //only when using deprecated -S and -aS options { //make -s option for later SMARTS test OBConversion conv; if(conv.SetOutFormat("smi")) { string optiontext = conv.WriteString(&patternMol, true); pConv->AddOption("s", OBConversion::GENOPTIONS, optiontext.c_str()); } } if(!p) { //neither -s or -S options provided. Output info rather than doing search const FptIndexHeader& header = fs.GetIndexHeader(); string id(header.fpid); if(id.empty()) id = "default"; clog << indexname << " is an index of\n " << header.datafilename << ".\n It contains " << header.nEntries << " molecules. The fingerprint type is " << id << " with " << OBFingerprint::Getbitsperint() * header.words << " bits.\n" << "Typical usage for a substructure search:\n" << "obabel indexfile.fs -osmi -sSMILES\n" << "(-s option in GUI is 'Convert only if match SMARTS or mols in file')" << endl; return false; } patternMols.push_back(patternMol); return true; }
/////////////////////////////////////////////////////////////////////////////// //! \brief compute rms between chemically identical molecules int main(int argc, char **argv) { bool firstOnly = false; if (argc != 3 && argc != 4) { cerr << "Usage: " << argv[0] << " [-firstonly] <reference structure(s)> <comparison structure(s)>\n"; cerr << "Computes the heavy-atom RMSD of identical compound structures.\n"; cerr << "Structures in multi-structure files are compared one-by-one unless -firstonly\n" << "is passed, in which case only the first structure in the reference file is used.\n"; exit(-1); } char *fileRef = argv[1]; char *fileTest = argv[2]; if (argc == 4) { //if iterate is passed as first command, try to match structures in first file to strucutres in second if (strcmp("-firstonly", argv[1]) != 0) { cerr << "Usage: " << argv[0] << " [-firstonly] <reference structure(s)> <comparison structure(s)>\n"; exit(-1); } fileRef = argv[2]; fileTest = argv[3]; firstOnly = true; } //open mols OBConversion refconv; OBFormat *refFormat = refconv.FormatFromExt(fileRef); if (!refFormat || !refconv.SetInFormat(refFormat) || !refconv.SetOutFormat("SMI")) { cerr << "Cannot read reference molecule format!" << endl; exit(-1); } OBConversion testconv; OBFormat *testFormat = testconv.FormatFromExt(fileTest); if (!testFormat || !testconv.SetInAndOutFormats(testFormat, testFormat)) { cerr << "Cannot read reference molecule format!" << endl; exit(-1); } //read reference ifstream ifsref; OBMol molref; ifsref.open(fileRef); if (!ifsref) { cerr << "Cannot read fixed molecule file: " << fileRef << endl; exit(-1); } //check comparison file ifstream ifstest; ifstest.open(fileTest); if (!ifstest) { cerr << "Cannot read file: " << fileTest << endl; exit(-1); } while (refconv.Read(&molref, &ifsref)) { processMol(molref); Matcher matcher(molref);// create the matcher OBMol moltest; while (testconv.Read(&moltest, &ifstest)) { if (moltest.Empty()) break; processMol(moltest); double rmsd = matcher.computeRMSD(moltest); cout << "RMSD " << moltest.GetTitle() << " " << rmsd << "\n"; if (!firstOnly) { break; } } } return (0); }
int main(int argc,char *argv[]) { OBConversion Conv(&cin, &cout); //default input and output are console OBFormat* pInFormat = NULL; OBFormat* pOutFormat = NULL; bool inGzip = false; bool outGzip = false; vector<string> FileList, OutputFileList; string OutputFileName; // Parse commandline bool gotInType = false, gotOutType = false; bool SplitOrBatch=false; char *oext = NULL; char *iext = NULL; //load plugs to fully initialize option parameters OBPlugin::LoadAllPlugins(); //Save name of program without its path (and .exe) string pn(argv[0]); string::size_type pos; #ifdef _WIN32 pos = pn.find(".exe"); if(pos!=string::npos) argv[0][pos]='\0'; #endif pos = pn.find_last_of("/\\"); if(pos==string::npos) program_name=argv[0]; else program_name=argv[0]+pos+1; const char* p; int arg; for (arg = 1; arg < argc; ++arg) { if (argv[arg]) { if (argv[arg][0] == '-') { switch (argv[arg][1]) { case 'V': { cout << "Open Babel " << BABEL_VERSION << " -- " << __DATE__ << " -- " << __TIME__ << endl; exit(0); } case 'i': gotInType = true; iext = argv[arg] + 2; if(!*iext) iext = argv[++arg]; //space left after -i: use next argument if (strncasecmp(iext, "MIME", 4) == 0) { // get the MIME type from the next argument iext = argv[++arg]; pInFormat = Conv.FormatFromMIME(iext); } else { //The ID provided by the OBFormat class is used as the identifying file extension pInFormat = Conv.FindFormat(iext); } if(pInFormat==NULL) { cerr << program_name << ": cannot read input format!" << endl; usage(); } break; case 'o': gotOutType = true; oext = argv[arg] + 2; if(!*oext) oext = argv[++arg]; //space left after -i: use next argument if (arg >= argc) usage(); // error in parsing command-line if (strncasecmp(oext, "MIME", 4) == 0) { // get the MIME type from the next argument oext = argv[++arg]; pOutFormat = Conv.FormatFromMIME(oext); } else pOutFormat = Conv.FindFormat(oext); if(pOutFormat==NULL) { cerr << program_name << ": cannot write output format!" << endl; usage(); } break; case 'L': //display a list of plugin type or classes { const char* param=NULL; if(argc>arg+1) param = argv[arg+2]; // First assume first arg is a plugin type and // param is a subtype, like babel -L ops gen3D // or first arg is a plugin ID, like babel -L cml OBPlugin* plugin; if ((OBPlugin::GetPlugin("plugins", argv[arg+1]) && (plugin = OBPlugin::GetPlugin(argv[arg+1], param))) || (plugin = OBPlugin::GetPlugin(NULL, argv[arg+1]))) { //Output details of subtype string txt; plugin->Display(txt, "verbose", argv[arg+1]); cout << "One of the " << plugin->TypeID() << '\n' << txt << endl; return 0; } //...otherwise assume it is a plugin type, like babel -L forcefields //Output list of subtypes OBPlugin::List(argv[arg+1], param); return 0; } case '?': case 'H': if(isalnum(argv[arg][2]) || arg==argc-2) { if(strncasecmp(argv[arg]+2,"all",3)) { const char* pID= (arg==argc-2) ? argv[arg+1] : argv[arg]+2; OBFormat* pFormat = Conv.FindFormat(pID); if(pFormat) { cout << pID << " " << pFormat->Description() << endl; if(pFormat->Flags() & NOTWRITABLE) cout << " This format is Read-only" << endl; if(pFormat->Flags() & NOTREADABLE) cout << " This format is Write-only" << endl; if(strlen(pFormat->SpecificationURL())) cout << "Specification at: " << pFormat->SpecificationURL() << endl; } else cout << "Format type: " << pID << " was not recognized" <<endl; } else { OBPlugin::List("formats","verbose"); } } else help(); return 0; case '-': //long option --name text { //Do nothing if name is empty //Option's text is the next arg provided it doesn't start with - char* nam = argv[arg]+2; if(*nam != '\0') { string txt; int i; for(i=0; i<Conv.GetOptionParams(nam, OBConversion::GENOPTIONS) && arg<argc-1 && argv[arg+1];++i) //removed && *argv[arg+1]!='-' { if(!txt.empty()) txt+=' '; txt += argv[++arg]; } if(*nam=='-') { // Is a API directive, e.g.---errorlevel //Send to the pseudoformat "obapi" (without any leading -) OBConversion apiConv; OBFormat* pAPI= OBConversion::FindFormat("obapi"); if(pAPI) { apiConv.SetOutFormat(pAPI); apiConv.AddOption(nam+1, OBConversion::GENOPTIONS, txt.c_str()); apiConv.Write(NULL, &std::cout); } } else // Is a long option name, e.g --addtotitle Conv.AddOption(nam,OBConversion::GENOPTIONS,txt.c_str()); } } break; case 'm': //multiple output files SplitOrBatch=true; break; case 'a': //single character input option p = argv[arg]+2; DoOption(p,Conv,OBConversion::INOPTIONS,arg,argc,argv); break; case 'x': //single character output option p = argv[arg]+2; DoOption(p,Conv,OBConversion::OUTOPTIONS,arg,argc,argv); break; default: //single character general option p = argv[arg]+1; DoOption(p,Conv,OBConversion::GENOPTIONS,arg,argc,argv); break; } } else { //filenames if(!gotOutType) FileList.push_back(argv[arg]); else OutputFileName = argv[arg]; } } } if(!gotOutType) //the last file is the output { if(FileList.empty()) { cerr << "No output file or format spec!" << endl; usage(); } OutputFileName = FileList.back(); FileList.pop_back(); } #if defined(_WIN32) && defined(USING_DYNAMIC_LIBS) //Expand wildcards in input filenames and add to FileList vector<string> tempFileList(FileList); FileList.clear(); vector<string>::iterator itr; for(itr=tempFileList.begin();itr!=tempFileList.end();++itr) DLHandler::findFiles (FileList, *itr); #endif if (!gotInType) { if(FileList.empty()) { cerr << "No input file or format spec!" <<endl; usage(); } } if (!gotOutType) { pOutFormat = Conv.FormatFromExt(OutputFileName.c_str(), outGzip); if(pOutFormat==NULL) { cerr << program_name << ": cannot write output format!" << endl; usage(); } } if(!Conv.SetInFormat(pInFormat)) { cerr << "Invalid input format" << endl; usage(); } if(!Conv.SetOutFormat(pOutFormat, outGzip)) { cerr << "Invalid output format" << endl; usage(); } if(SplitOrBatch) { //Put * into output file name before extension (or ext.gz) if(OutputFileName.empty()) { OutputFileName = "*."; if (oext != NULL) OutputFileName += oext; } else { string::size_type pos = OutputFileName.rfind(".gz"); if(pos==string::npos) pos = OutputFileName.rfind('.'); else pos = OutputFileName.rfind('.',pos-1); if(pos==string::npos) OutputFileName += '*'; else OutputFileName.insert(pos,"*"); } } int count = Conv.FullConvert(FileList, OutputFileName, OutputFileList); Conv.ReportNumberConverted(count); if(OutputFileList.size()>1) { clog << OutputFileList.size() << " files output. The first is " << OutputFileList[0] <<endl; } std::string messageSummary = obErrorLog.GetMessageSummary(); if (messageSummary.size()) { clog << messageSummary << endl; } #ifdef _DEBUG //CM keep window open cout << "Press any key to finish" <<endl; getch(); #endif return 0; }
bool ReactionInChIFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv) { OBMol* pmol = dynamic_cast<OBMol*>(pOb); if (pmol == NULL || !pmol->IsReaction()) return false; ostream &ofs = *pConv->GetOutStream(); OBFormat* pInChIFormat = OBConversion::FindFormat("inchi"); if (!pInChIFormat) return false; bool isEquilibrium = pConv->IsOption("e"); OBConversion inchiconv; inchiconv.SetOutFormat(pInChIFormat); stringstream ss; inchiconv.SetOutStream(&ss); #define M_REACTANTS 0 #define M_PRODUCTS 1 #define M_AGENTS 2 OBReactionFacade facade(pmol); std::vector<std::vector<std::string> > inchis(3); unsigned int nonInchi[3] = { 0, 0, 0 }; bool hasNonInchi = false; OBMol mol; for (int part = 0; part <= 2; ++part) { unsigned int N; switch (part) { case M_REACTANTS: N = facade.NumComponents(REACTANT); break; case M_PRODUCTS: N = facade.NumComponents(PRODUCT); break; case M_AGENTS: N = facade.NumComponents(AGENT); break; } for (unsigned int i = 0; i < N; ++i) { mol.Clear(); switch (part) { case M_REACTANTS: facade.GetComponent(&mol, REACTANT, i); break; case M_PRODUCTS: facade.GetComponent(&mol, PRODUCT, i); break; case M_AGENTS: facade.GetComponent(&mol, AGENT, i); break; } if (mol.NumAtoms() == 1 && mol.GetFirstAtom()->GetAtomicNum() == 0) { // This represents an unknown component nonInchi[part]++; hasNonInchi = true; } else { bool ok = inchiconv.Write(&mol); if (!ok) { nonInchi[part]++; hasNonInchi = true; } else { string inchi = ss.str(); if (strncmp(inchi.c_str(), "InChI=1S/", 9) != 0) return false; inchis[part].push_back(TrimInChI(inchi.c_str())); } ss.str(""); } } } std::sort(inchis[M_REACTANTS].begin(), inchis[M_REACTANTS].end()); std::sort(inchis[M_PRODUCTS].begin(), inchis[M_PRODUCTS].end()); std::sort(inchis[M_AGENTS].begin(), inchis[M_AGENTS].end()); std::string reactants_string = ""; const int rsize = inchis[M_REACTANTS].size(); for (int i = 0; i < rsize; ++i) { if (i > 0) reactants_string += '!'; reactants_string += inchis[M_REACTANTS][i]; } std::string products_string = ""; const int psize = inchis[M_PRODUCTS].size(); for (int i = 0; i < psize; ++i) { if (i > 0) products_string += '!'; products_string += inchis[M_PRODUCTS][i]; } bool reactants_first = reactants_string <= products_string; ofs << RINCHI_VERSION_STRING; if (rsize > 0 || psize > 0 || !inchis[M_AGENTS].empty()) { ofs << (reactants_first ? reactants_string : products_string); ofs << "<>"; ofs << (reactants_first ? products_string : reactants_string); if (!inchis[M_AGENTS].empty()) { ofs << "<>"; for (std::vector<std::string>::const_iterator vit = inchis[M_AGENTS].begin(); vit != inchis[M_AGENTS].end(); ++vit) { if (vit != inchis[M_AGENTS].begin()) ofs << '!'; ofs << *vit; } } } ofs << "/d"; if (isEquilibrium) ofs << '='; else ofs << (reactants_first ? '+' : '-'); if (hasNonInchi) { ofs << "/u" << (reactants_first ? nonInchi[M_REACTANTS] : nonInchi[M_PRODUCTS]) << '-' << (reactants_first ? nonInchi[M_PRODUCTS] : nonInchi[M_REACTANTS]) << '-' << nonInchi[M_AGENTS]; } ofs << '\n'; return true; }
// This function will call the Babel library to add // hydrogens to the residues void PDB::addHydrogensToPair(AminoAcid& a, AminoAcid& b, int cd1, int cd2) { OBMol mol; string addedH; istringstream tempss; bool ligand; if(b.atom[0]->line.find("HETATM") != string::npos) { ligand = true; } else { ligand = false; } // This section is just to suppress all of the // warning message that aren't important to us { OBConversion apiConv; OBFormat* pAPI = OBConversion::FindFormat("obapi"); if(pAPI) { apiConv.SetOutFormat(pAPI); apiConv.AddOption("errorlevel", OBConversion::GENOPTIONS, "0"); apiConv.Write(NULL, &std::cout); } } // Now, let's pack up the information into a string string packedFile=""; for(unsigned int i=0; i < a.altlocs[cd1].size(); i++) { if( !a.altlocs[cd1][i]->skip ) { packedFile += a.altlocs[cd1][i]->line + "\n"; } } int cd2_al = cd2; if(b.residue == "ASP" || b.residue == "GLU") { cd2_al = cd2%(b.altlocs.size()); } for(unsigned int i=0; i < b.altlocs[cd2_al].size(); i++) { if( !b.altlocs[cd2_al][i]->skip ) { packedFile += b.altlocs[cd2_al][i]->line + "\n"; } } packedFile += a.makeConect(cd1); packedFile += b.makeConect(cd2_al); // Now, let's set up some Babel information // First, we get the PDB format to tell // Babel how to read the information and // how to output it OBFormat* pdbformat = this->conv.FindFormat("pdb"); this->conv.SetInFormat(pdbformat); this->conv.SetOutFormat(pdbformat); // Here is where Babel reads everything // and adds hydrogens to the pair // TO ADD: option to set pH this->conv.ReadString(&mol,packedFile); mol.AddHydrogens(false,true,PH_LEVEL); // Let's write the newly written hydrogens to // a string and parse it addedH = this->conv.WriteString(&mol); tempss.str(addedH); // This ensures that the ligand hydrogens are labeled as // HETATM instead of ATOM just for the sake of STAAR. // This may be wrong, but it should be fine since we are // stripping out that information later when we write // the GAMESS inp files if( ligand ) { string line; string f = ""; while( getline(tempss,line) ) { if( line.find(b.residue) != string::npos ) { line.replace(0,6,"HETATM"); } f += line + "\n"; } tempss.seekg(ios_base::beg); tempss.clear(); tempss.str(f); } this->failure = false; this->parsePDB(tempss,99999.99); // This is just to ensure that all of the atoms // are grouped together because Babel just // appends the H to the end of the file if( !ligand ) this->sortAtoms(); // Split the atoms up into amino acids and chains this->populateChains(true); }
int main(int argc,char *argv[]) { // turn off slow sync with C-style output (we don't use it anyway). std::ios::sync_with_stdio(false); OBConversion conv; OBFormat *inFormat, *canFormat; OBMol mol; ifstream ifs; vector<OBMol> fragments; unsigned int fragmentCount = 0; // track how many in library -- give a running count map<string, int> index; // index of cansmi string currentCAN; unsigned int size; OBAtom *atom; OBBond *bond; bool nonRingAtoms, nonRingBonds; char buffer[BUFF_SIZE]; canFormat = conv.FindFormat("can"); conv.SetOutFormat(canFormat); if (argc < 2) { cout << "Usage: obfragment <file>" << endl; return(-1); } for (int i = 1; i < argc; i++) { cerr << " Reading file " << argv[i] << endl; inFormat = conv.FormatFromExt(argv[i]); if(inFormat==NULL || !conv.SetInFormat(inFormat)) { cerr << " Cannot read file format for " << argv[i] << endl; continue; // try next file } ifs.open(argv[i]); if (!ifs) { cerr << "Cannot read input file: " << argv[i] << endl; continue; } while(ifs.peek() != EOF && ifs.good()) { conv.Read(&mol, &ifs); if (!mol.Has3D()) continue; // invalid coordinates! mol.DeleteHydrogens(); // remove these before we do anything else do { nonRingAtoms = false; size = mol.NumAtoms(); for (unsigned int i = 1; i <= size; ++i) { atom = mol.GetAtom(i); if (!atom->IsInRing()) { mol.DeleteAtom(atom); nonRingAtoms = true; break; // don't know how many atoms there are } // Previously, we changed atoms to carbon here. // Now we perform this alchemy in terms of string-rewriting // once the canonical SMILES is generated } } while (nonRingAtoms); if (mol.NumAtoms() < 3) continue; if (mol.NumBonds() == 0) continue; do { nonRingBonds = false; size = mol.NumBonds(); for (unsigned int i = 0; i < size; ++i) { bond = mol.GetBond(i); if (!bond->IsInRing()) { mol.DeleteBond(bond); nonRingBonds = true; break; // don't know how many bonds there are } } } while (nonRingBonds); fragments = mol.Separate(); for (unsigned int i = 0; i < fragments.size(); ++i) { if (fragments[i].NumAtoms() < 3) // too small to care continue; currentCAN = conv.WriteString(&fragments[i], true); currentCAN = RewriteSMILES(currentCAN); // change elements to "a/A" for compression if (index.find(currentCAN) != index.end()) { // already got this index[currentCAN] += 1; // add to the count for bookkeeping continue; } index[currentCAN] = 1; // don't ever write this ring fragment again // OK, now retrieve the canonical ordering for the fragment vector<string> canonical_order; if (fragments[i].HasData("Canonical Atom Order")) { OBPairData *data = (OBPairData*)fragments[i].GetData("Canonical Atom Order"); tokenize(canonical_order, data->GetValue().c_str()); } // Write out an XYZ-style file with the CANSMI as the title cout << fragments[i].NumAtoms() << '\n'; cout << currentCAN << '\n'; // endl causes a flush vector<string>::iterator can_iter; unsigned int order; OBAtom *atom; fragments[i].Center(); fragments[i].ToInertialFrame(); for (unsigned int index = 0; index < canonical_order.size(); ++index) { order = atoi(canonical_order[index].c_str()); atom = fragments[i].GetAtom(order); snprintf(buffer, BUFF_SIZE, "C%8.3f%8.3f%8.3f\n", atom->x(), atom->y(), atom->z()); cout << buffer; } } fragments.clear(); if (index.size() > fragmentCount) { fragmentCount = index.size(); cerr << " Fragments: " << fragmentCount << endl; } } // while reading molecules (in this file) ifs.close(); ifs.clear(); } // while reading files // loop through the map and output frequencies map<string, int>::const_iterator indexItr; for (indexItr = index.begin(); indexItr != index.end(); ++indexItr) { cerr << (*indexItr).second << " INDEX " << (*indexItr).first << "\n"; } return(0); }
bool OpNewS::Do(OBBase* pOb, const char* OptionText, OpMap* pmap, OBConversion* pConv) { OBMol* pmol = dynamic_cast<OBMol*>(pOb); if(!pmol) return false; // The SMARTS and any other parameters are extracted on the first molecule // and stored in the member variables. The parameter is cleared so that // the original -s option in transform.cpp is inactive //string txt(pmap->find(GetID())->second); // ID can be "s" or "v" vector<OBQuery*>::iterator qiter; if(OptionText && *OptionText)//(!pConv || pConv->IsFirstInput()) { //Set up on first call queries.clear(); query=NULL; nPatternAtoms=0; inv=false; tokenize(vec, OptionText); inv = GetID()[0]=='v'; if(vec[0][0]=='~') { inv = true; vec[0].erase(0,1); } //Do not filter out any molecules if there is a parameter "showall"; //allows -s option to be used for highlighting substructures (--highlight also does this) vector<string>::iterator it = std::remove(vec.begin(), vec.end(),"showall"); showAll = it != vec.end(); if(showAll) vec.erase(it); //Store the number of matches required, if as a number in the second parameter, else 0. nmatches = 0; comparechar = '\0'; if(vec.size()>1) { comparechar = vec[1][0]; if(comparechar=='>' || comparechar=='<') vec[1].erase(0,1); else comparechar = '\0'; nmatches = atoi(vec[1].c_str()); if(nmatches) //remove this parameter to still allow coloring vec.erase(vec.begin()+1); } //Interpret as a filename if possible MakeQueriesFromMolInFile(queries, vec[0], &nPatternAtoms, strstr(OptionText,"noH")); vec.erase(remove(vec.begin(),vec.end(),"noH"),vec.end());//to prevent "noH2" being seen as a color if(queries.empty()) { //SMARTS supplied // Explicit H in SMARTS requires explicit H in the molecule. // Calling AddHydrogens() on a copy of the molecule is done in parsmart.cpp // only when SMARTS contains [H]. Doing more has complications with atom typing, // so AddHydrogens here on the molecule (not a copy) when #1 detected. addHydrogens = (vec[0].find("#1]")!=string::npos); // If extra target mols have been supplied, make a composite SMARTS // to test for any of the targets. if(ExtraMols.size()>0) { for(unsigned i=0;i<ExtraMols.size();++i) { OBConversion extraConv; extraConv.AddOption("h"); if(!extraConv.SetOutFormat("smi")) return false; // Add option which avoids implicit H being added to the SMARTS. // The parameter must be present but can be anything. extraConv.AddOption("h",OBConversion::OUTOPTIONS, "X"); xsmarts += ",$(" + extraConv.WriteString(ExtraMols[i], true) + ")"; } } string ysmarts = xsmarts.empty() ? vec[0] : "[$(" + vec[0] + ")" + xsmarts +"]"; xsmarts.clear(); if(!sp.Init(ysmarts)) { string msg = ysmarts + " cannot be interpreted as either valid SMARTS " "or the name of a file with an extension known to OpenBabel " "that contains one or more pattern molecules."; obErrorLog.ThrowError(__FUNCTION__, msg, obError, onceOnly); delete pmol; pmol = NULL; pConv->SetOneObjectOnly(); //stop conversion return false; } } else { // Target is in a file. Add extra targets if any supplied for(unsigned i=0;i<ExtraMols.size();++i) queries.push_back(CompileMoleculeQuery(static_cast<OBMol*>(ExtraMols[i]))); ExtraMols.clear(); } if(vec.size()>1 && vec[1]=="exact") { if(queries.empty()) { //Convert SMARTS to SMILES to count number of atoms OBConversion conv; OBMol patmol; if(!conv.SetInFormat("smi") || !conv.ReadString(&patmol, vec[0])) { obErrorLog.ThrowError(__FUNCTION__, "Cannot read the parameter of -s option, " "which has to be valid SMILES when the exact option is used.", obError, onceOnly); delete pmol; if(pConv) pConv->SetOneObjectOnly(); //stop conversion return false; } nPatternAtoms = patmol.NumHvyAtoms(); } } else nPatternAtoms = 0; //disable old versions if(pConv) pConv->AddOption(GetID(), OBConversion::GENOPTIONS, ""); } bool match = false; //These are a vector of each mapping, each containing atom indxs. vector<vector<int> > vecatomvec; vector<vector<int> >* pMappedAtoms = NULL; if(nPatternAtoms) if(pmol->NumHvyAtoms() != nPatternAtoms) return false; unsigned int imol=0; //index of mol in pattern file if(!queries.empty()) //filename supplied { //match is set true if any of the structures match - OR behaviour for(qiter=queries.begin();qiter!=queries.end();++qiter, ++imol) { OBIsomorphismMapper* mapper = OBIsomorphismMapper::GetInstance(*qiter); OBIsomorphismMapper::Mappings mappings; mapper->MapUnique(pmol, mappings); if( (match = !mappings.empty()) ) // extra parens to indicate truth value { OBIsomorphismMapper::Mappings::iterator ita; OBIsomorphismMapper::Mapping::iterator itb; for(ita=mappings.begin(); ita!=mappings.end();++ita)//each mapping { vector<int> atomvec; for(itb=ita->begin(); itb!=ita->end();++itb)//each atom index atomvec.push_back(itb->second+1); vecatomvec.push_back(atomvec); atomvec.clear(); } pMappedAtoms = &vecatomvec; break; } } } else //SMARTS supplied { if(addHydrogens) pmol->AddHydrogens(false,false); if( (match = sp.Match(*pmol)) ) // extra parens to indicate truth value { pMappedAtoms = &sp.GetMapList(); if(nmatches!=0) { int n = sp.GetUMapList().size(); if(comparechar=='>') match = (n > nmatches); else if(comparechar=='<') match = (n < nmatches); else match = (n == nmatches); } } } if((!showAll && (!match && !inv)) || (match && inv)) { //delete a non-matching mol delete pmol; pmol = NULL; return false; } if(match) //Copy the idxes of the first match to a member variable so that it can be retrieved from outside firstmatch.assign(pMappedAtoms->begin()->begin(), pMappedAtoms->begin()->end()); else firstmatch.clear(); if(match && !inv && vec.size()>=2 && !vec[1].empty() && !nPatternAtoms) { vector<vector<int> >::iterator iter; if (vec[1]=="extract" || (vec.size()>3 && vec[2]=="extract")) { //Delete all unmatched atoms. Use only the first match ExtractSubstruct(pmol, *pMappedAtoms->begin()); return true; } // color the substructure if there is a second parameter which is not "exact" or "extract" or "noH" // with multiple color parameters use the one corresponding to the query molecule, or the last if(imol>vec.size()-2) imol = vec.size()-2; for(iter=pMappedAtoms->begin();iter!=pMappedAtoms->end();++iter)//each match AddDataToSubstruct(pmol, *iter, "color", vec[imol+1]); return true; } if(pConv && pConv->IsLast()) { for(qiter=queries.begin();qiter!=queries.end();++qiter) delete *qiter; queries.clear(); } return true; }
void phmodel_test() { OBMol mol; OBConversion conv; conv.SetInFormat("smi"); conv.SetOutFormat("smi"); unsigned int test = 0; // amine acid COOH pKa = 4.0 (carboxylic acid entry in phmodel.txt) // amino acid NH3+ pKa = 10.0 (amine entry in phmodel.txt) // // Aspartic acid (sidechain COOH pKa = 3.8) // conv.ReadString(&mol, "NC(CC(O)=O)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 1.0); // NH3+ COOH COOH //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 17, "Aspartic acid pH 1.0" ); conv.ReadString(&mol, "NC(CC(O)=O)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 3.9); // NH3+ COOH COO- //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 16, "Aspartic acid pH 3.9" ); conv.ReadString(&mol, "NC(CC(O)=O)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 7.4); // NH3+ COO- COO- //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 15, "Aspartic acid pH 7.4" ); conv.ReadString(&mol, "NC(CC(O)=O)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 13.0); // NH2 COO- COO- //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 14, "Aspartic acid pH 13.0" ); // // Glutamic acid (sidechain COOH pKa = 4.3) // conv.ReadString(&mol, "NC(CCC(O)=O)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 1.0); // NH3+ COOH COOH //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 20, "Glutamic acid pH 1.0" ); conv.ReadString(&mol, "NC(CCC(O)=O)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 4.15); // NH3+ COOH COO- //conv.Write(&mol, &cout); // known bug BOOST_CHECK_MESSAGE( mol.NumAtoms() == 19, "Glutamic acid pH 4.15" ); conv.ReadString(&mol, "NC(CCC(O)=O)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 7.4); // NH3+ COO- COO- //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 18, "Glutamic acid pH 7.4" ); conv.ReadString(&mol, "NC(CCC(O)=O)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 13.0); // NH2 COO- COO- //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 17, "Glutamic acid pH 13.0" ); // // Histidine (sidechain nH+ pKa = 6.08) // conv.ReadString(&mol, "NC(Cc1ncnc1)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 1.0); // NH3+ COOH nH+ //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 22, "Histidine pH 1.0" ); conv.ReadString(&mol, "NC(Cc1ncnc1)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 5.0); // NH3+ COO- nH+ //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 21, "Histidine pH 5.0" ); conv.ReadString(&mol, "NC(Cc1ncnc1)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 7.4); // NH3+ COO- n: //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 20, "Histidine pH 7.4" ); conv.ReadString(&mol, "NC(Cc1ncnc1)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 13.0); // NH2 COO- n: //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 19, "Histidine pH 13.0" ); // // Lysine (sidechain NH3+ pKa = 8.28) // conv.ReadString(&mol, "NC(CCCCN)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 1.0); // NH3+ COOH NH3+ //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 26, "Lysine pH 1.0" ); conv.ReadString(&mol, "NC(CCCCN)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 7.4); // NH3+ COO- NH3+ //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 25, "Lysine pH 7.4" ); conv.ReadString(&mol, "NC(CCCCN)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 9.0); // NH3+ COO- NH2 //conv.Write(&mol, &cout); // known bug BOOST_CHECK_MESSAGE( mol.NumAtoms() == 24, "Lysine pH 9.0" ); conv.ReadString(&mol, "NC(CCCCN)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 13.0); // NH2 COO- NH2 //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 23, "Lysine pH 13.0" ); // // Tyrosine (sidechain OH pKa = 10.1) // conv.ReadString(&mol, "NC(Cc1ccc(O)cc1)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 1.0); // NH3+ COOH NH3+ //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 25, "Tyrosine pH 1.0" ); conv.ReadString(&mol, "NC(Cc1ccc(O)cc1)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 7.4); // NH3+ COO- NH3+ //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 24, "Tyrosine pH 7.4" ); conv.ReadString(&mol, "NC(Cc1ccc(O)cc1)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 10.05); // NH3+ COO- NH2 //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 23, "Tyrosine pH 10.05" ); conv.ReadString(&mol, "NC(Cc1ccc(O)cc1)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 13.0); // NH2 COO- NH2 //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 22, "Tyrosine pH 13.0" ); // // Arginine (sidechain =NH2+ pKa = 12.0) // conv.ReadString(&mol, "NC(CCCNC(N)=N)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 1.0); // NH3+ COOH =NH2+ //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 28, "Arginine pH 1.0" ); conv.ReadString(&mol, "NC(CCCNC(N)=N)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 7.4); // NH3+ COO- NH3+ //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 27, "Arginine pH 7.4" ); conv.ReadString(&mol, "NC(CCCNC(N)=N)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 11.0); // NH3+ COO- NH2 //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 26, "Arginine pH 11.0" ); conv.ReadString(&mol, "NC(CCCNC(N)=N)C(O)=O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 13.0); // NH2 COO- NH2 //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 25, "Arginine pH 13.0" ); // // Gly-Gly (terminal NH3+, COOH and the amide bond) // conv.ReadString(&mol, "NCC(=O)NCC(=O)O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 1.0); // NH3+ COOH =NH2+ //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 18, "Gly-Gly pH 1.0" ); conv.ReadString(&mol, "NCC(=O)NCC(=O)O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 7.4); // NH3+ COO- NH3+ //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 17, "Gly-Gly pH 7.4" ); conv.ReadString(&mol, "NCC(=O)NCC(=O)O"); mol.SetAutomaticFormalCharge(true); mol.AddHydrogens(false, true, 13.0); // NH2 COO- NH2 //conv.Write(&mol, &cout); BOOST_CHECK_MESSAGE( mol.NumAtoms() == 16, "Gly-Gly pH 13.0" ); }
void genericSmilesCanonicalTest(const std::string &smiles) { cout << "Testing generic smiles <-> canonical smiles" << endl; // read a smiles string OBMol mol; OBConversion conv; OB_REQUIRE( conv.SetInFormat("smi") ); OB_REQUIRE( conv.SetOutFormat("can") ); cout << "smiles: " << smiles << endl; // read a smiles string OB_REQUIRE( conv.ReadString(&mol, smiles) ); // store the stereo data for the smiles string using unique symmetry ids std::vector<OBTetrahedralStereo::Config> tetrahedral1; std::vector<OBCisTransStereo::Config> cistrans1; std::vector<OBSquarePlanarStereo::Config> squareplanar1; // get the stereo data OB_ASSERT( mol.HasData(OBGenericDataType::StereoData) ); std::vector<OBGenericData *> stereoData = mol.GetAllData(OBGenericDataType::StereoData); std::vector<unsigned int> canlbls; std::vector<unsigned int> symclasses; OBGraphSym gs1(&mol); gs1.GetSymmetry(symclasses); CanonicalLabels(&mol, symclasses, canlbls); cout << "mol.NumAtoms = " << mol.NumAtoms() << endl; for (std::vector<OBGenericData*>::iterator data = stereoData.begin(); data != stereoData.end(); ++data) { if (((OBStereoBase*)*data)->GetType() == OBStereo::Tetrahedral) { // convert to tetrahedral data OBTetrahedralStereo *ts = dynamic_cast<OBTetrahedralStereo*>(*data); OB_REQUIRE( ts ); OB_ASSERT( ts->IsValid() ); if (!ts->IsValid()) continue; OBTetrahedralStereo::Config config = ts->GetConfig(); // convert atom ids to symmetry ids if (mol.GetAtomById(config.center)) config.center = canlbls.at( mol.GetAtomById(config.center)->GetIdx() - 1 ); if (mol.GetAtomById(config.from)) config.from = canlbls.at( mol.GetAtomById(config.from)->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[0])) config.refs[0] = canlbls.at( mol.GetAtomById(config.refs[0])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[1])) config.refs[1] = canlbls.at( mol.GetAtomById(config.refs[1])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[2])) config.refs[2] = canlbls.at( mol.GetAtomById(config.refs[2])->GetIdx() - 1 ); cout << "Config with symmetry ids: " << config << endl; tetrahedral1.push_back(config); } else if (((OBStereoBase*)*data)->GetType() == OBStereo::CisTrans) { // convert to tetrahedral data OBCisTransStereo *ct = dynamic_cast<OBCisTransStereo*>(*data); OB_REQUIRE( ct ); OB_ASSERT( ct->IsValid() ); OBCisTransStereo::Config config = ct->GetConfig(); // convert atom ids to symmetry ids config.begin = canlbls.at( mol.GetAtomById(config.begin)->GetIdx() - 1 ); config.end = canlbls.at( mol.GetAtomById(config.end)->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[0])) config.refs[0] = canlbls.at( mol.GetAtomById(config.refs[0])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[1])) config.refs[1] = canlbls.at( mol.GetAtomById(config.refs[1])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[2])) config.refs[2] = canlbls.at( mol.GetAtomById(config.refs[2])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[3])) config.refs[3] = canlbls.at( mol.GetAtomById(config.refs[3])->GetIdx() - 1 ); cout << "Config with symmetry ids: " << config << endl; cistrans1.push_back(config); } else if (((OBStereoBase*)*data)->GetType() == OBStereo::SquarePlanar) { // convert to tetrahedral data OBSquarePlanarStereo *sp = dynamic_cast<OBSquarePlanarStereo*>(*data); OB_REQUIRE( sp ); OB_ASSERT( sp->IsValid() ); if (!sp->IsValid()) continue; OBSquarePlanarStereo::Config config = sp->GetConfig(); // convert atom ids to symmetry ids if (mol.GetAtomById(config.center)) config.center = canlbls.at( mol.GetAtomById(config.center)->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[0])) config.refs[0] = canlbls.at( mol.GetAtomById(config.refs[0])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[1])) config.refs[1] = canlbls.at( mol.GetAtomById(config.refs[1])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[2])) config.refs[2] = canlbls.at( mol.GetAtomById(config.refs[2])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[3])) config.refs[3] = canlbls.at( mol.GetAtomById(config.refs[3])->GetIdx() - 1 ); cout << "Config with symmetry ids: " << config << endl; squareplanar1.push_back(config); } } // write to can smiles std::string canSmiles = conv.WriteString(&mol); cout << "canSmiles: " << canSmiles; // read can smiles in again OB_REQUIRE( conv.ReadString(&mol, canSmiles) ); // store the stereo data for the smiles string using unique symmetry ids std::vector<OBTetrahedralStereo::Config> tetrahedral2; std::vector<OBCisTransStereo::Config> cistrans2; std::vector<OBSquarePlanarStereo::Config> squareplanar2; // get the stereo data OB_ASSERT( mol.HasData(OBGenericDataType::StereoData) ); stereoData = mol.GetAllData(OBGenericDataType::StereoData); OBGraphSym gs2(&mol); gs2.GetSymmetry(symclasses); CanonicalLabels(&mol, symclasses, canlbls); cout << "mol.NumAtoms = " << mol.NumAtoms() << endl; for (std::vector<OBGenericData*>::iterator data = stereoData.begin(); data != stereoData.end(); ++data) { if (((OBStereoBase*)*data)->GetType() == OBStereo::Tetrahedral) { // convert to tetrahedral data OBTetrahedralStereo *ts = dynamic_cast<OBTetrahedralStereo*>(*data); OB_REQUIRE( ts ); OB_ASSERT( ts->IsValid() ); OBTetrahedralStereo::Config config = ts->GetConfig(); // convert atom ids to symmetry ids if (mol.GetAtomById(config.center)) config.center = canlbls.at( mol.GetAtomById(config.center)->GetIdx() - 1 ); if (mol.GetAtomById(config.from)) config.from = canlbls.at( mol.GetAtomById(config.from)->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[0])) config.refs[0] = canlbls.at( mol.GetAtomById(config.refs[0])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[1])) config.refs[1] = canlbls.at( mol.GetAtomById(config.refs[1])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[2])) config.refs[2] = canlbls.at( mol.GetAtomById(config.refs[2])->GetIdx() - 1 ); cout << "Config with symmetry ids: " << config << endl; tetrahedral2.push_back(config); } if (((OBStereoBase*)*data)->GetType() == OBStereo::CisTrans) { // convert to tetrahedral data OBCisTransStereo *ct = dynamic_cast<OBCisTransStereo*>(*data); OB_REQUIRE( ct ); OB_ASSERT( ct->IsValid() ); OBCisTransStereo::Config config = ct->GetConfig(); // convert atom ids to symmetry ids config.begin = canlbls.at( mol.GetAtomById(config.begin)->GetIdx() - 1 ); config.end = canlbls.at( mol.GetAtomById(config.end)->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[0])) config.refs[0] = canlbls.at( mol.GetAtomById(config.refs[0])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[1])) config.refs[1] = canlbls.at( mol.GetAtomById(config.refs[1])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[2])) config.refs[2] = canlbls.at( mol.GetAtomById(config.refs[2])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[3])) config.refs[3] = canlbls.at( mol.GetAtomById(config.refs[3])->GetIdx() - 1 ); cout << "Config with symmetry ids: " << config << endl; cistrans2.push_back(config); } else if (((OBStereoBase*)*data)->GetType() == OBStereo::SquarePlanar) { // convert to tetrahedral data OBSquarePlanarStereo *sp = dynamic_cast<OBSquarePlanarStereo*>(*data); OB_REQUIRE( sp ); OB_ASSERT( sp->IsValid() ); OBSquarePlanarStereo::Config config = sp->GetConfig(); // convert atom ids to symmetry ids if (mol.GetAtomById(config.center)) config.center = canlbls.at( mol.GetAtomById(config.center)->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[0])) config.refs[0] = canlbls.at( mol.GetAtomById(config.refs[0])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[1])) config.refs[1] = canlbls.at( mol.GetAtomById(config.refs[1])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[2])) config.refs[2] = canlbls.at( mol.GetAtomById(config.refs[2])->GetIdx() - 1 ); if (mol.GetAtomById(config.refs[3])) config.refs[3] = canlbls.at( mol.GetAtomById(config.refs[3])->GetIdx() - 1 ); cout << "Config with symmetry ids: " << config << endl; squareplanar2.push_back(config); } } // compare the tetrahedral structs OB_ASSERT( tetrahedral1.size() == tetrahedral2.size() ); for (unsigned int i = 0; i < tetrahedral1.size(); ++i) { for (unsigned int j = 0; j < tetrahedral2.size(); ++j) { if (tetrahedral1[i].center == tetrahedral2[j].center) OB_ASSERT( tetrahedral1[i] == tetrahedral2[j] ); if ( tetrahedral1[i] != tetrahedral2[j] ) { cout << "1 = " << tetrahedral1[i] << endl; cout << "2 = " << tetrahedral2[j] << endl; } } } // compare the cistrans structs OB_ASSERT( cistrans1.size() == cistrans2.size() ); for (unsigned int i = 0; i < cistrans1.size(); ++i) { for (unsigned int j = 0; j < cistrans2.size(); ++j) { if ((cistrans1[i].begin == cistrans2[j].begin) && (cistrans1[i].end == cistrans2[j].end)) OB_ASSERT( cistrans1[i] == cistrans2[j] ); if ((cistrans1[i].begin == cistrans2[j].end) && (cistrans1[i].end == cistrans2[j].begin)) OB_ASSERT( cistrans1[i] == cistrans2[j] ); } } // compare the square-planar structs OB_ASSERT( squareplanar1.size() == squareplanar2.size() ); for (unsigned int i = 0; i < squareplanar1.size(); ++i) { for (unsigned int j = 0; j < squareplanar2.size(); ++j) { if (squareplanar1[i].center == squareplanar2[j].center) OB_ASSERT( squareplanar1[i] == squareplanar2[j] ); if ( squareplanar1[i] != squareplanar2[j] ) { cout << "1 = " << squareplanar1[i] << endl; cout << "2 = " << squareplanar2[j] << endl; } } } cout << "." << endl << endl; }
int main(int argc,char **argv) { OBForceField* pFF = OBForceField::FindForceField("Ghemical"); pFF->SetLogFile(&cout); pFF->SetLogLevel(OBFF_LOGLVL_LOW); OBMol mol; mol.Clear(); char commandline[100]; vector<string> vs; cout << endl; cout << "openbabel " << endl; cout << "M O L E C U L A R M E C H A N I C S" << endl; cout << " program" << endl; cout << " v 0.1 " << endl << endl; while (1) { cout << "command > "; cin.getline(commandline, 100); // // commands with no parameters // if (EQn(commandline, "quit", 4) || cin.eof()) { cout << "bye." << endl; exit(0); } if (EQn(commandline, "help", 4) || cin.eof()) { cout << endl; cout << "commands: description:" << endl; cout << "load <filename> load a molecule from filename" << endl; cout << "save <filename> save currently loaded molecule to filename" << endl; cout << "ff <forcefield> select the force field" << endl; cout << "forcefields print the available forcefields" << endl; cout << endl; cout << "energy calculate the energy" << endl; cout << "ebond calculate the bond stretching energy" << endl; cout << "eangle calculate the angle bending energy" << endl; cout << "estrbnd calculate the stretch-bending enregy" << endl; cout << "eoop calculate the out-of-plane bending energy" << endl; cout << "etorsion calculate the torsional energy" << endl; cout << "evdw calculate the Van der Waals energy" << endl; cout << "eeq calculate the electrostatic energy" << endl; cout << endl; cout << "sd <n> steepest descent energy minimization for n steps" << endl; cout << "cg <n> conjugate gradients energy minimization for n steps" << endl; cout << "" << endl; cout << "addH add hydrogens" << endl; cout << "delH delete hydrogens" << endl; cout << endl; cout << "gen generate/minimize a (random) structure" << endl; cout << "rs rotate around all rotatable bonds" << endl; cout << "nconf print the number of conformers" << endl; cout << "conf <n> select conformer n" << endl; cout << endl; cout << "quit quit" << endl; cout << endl; continue; } // calculate the energy if (EQn(commandline, "energy", 6)) { if (mol.Empty()) { cout << "no molecule loaded." << endl; continue; } cout << endl << " total energy = " << pFF->Energy() << " " << pFF->GetUnit() << endl << endl; continue; } if (EQn(commandline, "ebond", 5)) { if (mol.Empty()) { cout << "no molecule loaded." << endl; continue; } cout << endl << " bond stretching energy = " << pFF->E_Bond() << " " << pFF->GetUnit() << endl << endl; continue; } if (EQn(commandline, "eangle", 6)) { if (mol.Empty()) { cout << "no molecule loaded." << endl; continue; } cout << endl << " angle bending energy = " << pFF->E_Angle() << " " << pFF->GetUnit() << endl << endl; continue; } if (EQn(commandline, "estrbnd", 7)) { if (mol.Empty()) { cout << "no molecule loaded." << endl; continue; } cout << endl << " stretch-bending energy = " << pFF->E_StrBnd() << " " << pFF->GetUnit() << endl << endl; continue; } if (EQn(commandline, "eoop", 4)) { if (mol.Empty()) { cout << "no molecule loaded." << endl; continue; } cout << endl << " out-of-plane bending energy = " << pFF->E_OOP() << " " << pFF->GetUnit() << endl << endl; continue; } if (EQn(commandline, "etorsion", 8)) { if (mol.Empty()) { cout << "no molecule loaded." << endl; continue; } cout << endl << " torsional energy = " << pFF->E_Torsion() << " " << pFF->GetUnit() << endl << endl; continue; } if (EQn(commandline, "evdw", 4)) { if (mol.Empty()) { cout << "no molecule loaded." << endl; continue; } cout << endl << " Van der Waals energy = " << pFF->E_VDW() << " " << pFF->GetUnit() << endl << endl; continue; } if (EQn(commandline, "eeq", 3)) { if (mol.Empty()) { cout << "no molecule loaded." << endl; continue; } cout << endl << " electrostatic energy = " << pFF->E_Electrostatic() << " " << pFF->GetUnit() << endl << endl; continue; } if (EQn(commandline, "addH", 4)) { int num1, num2; num1 = mol.NumAtoms(); mol.AddHydrogens(false, true); num2 = mol.NumAtoms(); cout << (num2 - num1) << " hydrogens added." << endl; if (!pFF->Setup(mol)) { cout << "error while initializing the force field for this molecule." <<endl; continue; } continue; } if (EQn(commandline, "delH", 4)) { int num1, num2; num1 = mol.NumAtoms(); mol.DeleteHydrogens(); num2 = mol.NumAtoms(); cout << (num1 - num2) << " hydrogens deleted." << endl; if (!pFF->Setup(mol)) { cout << "error while initializing the force field for this molecule." <<endl; continue; } continue; } if (EQn(commandline, "gen", 3)) { //pFF->GenerateCoordinates(); pFF->UpdateCoordinates(mol); continue; } if (EQn(commandline, "rs", 2)) { pFF->SystematicRotorSearch(); pFF->UpdateCoordinates(mol); continue; } if (EQn(commandline, "nconf", 5)) { cout << endl << " number of conformers = " << mol.NumConformers() << endl << endl; continue; } // // commands with parameters // tokenize(vs, commandline); // select forcefield if (EQn(commandline, "ff", 2)) { if (vs.size() < 2) { cout << "no <forcefield> specified." << endl; continue; } pFF = OBForceField::FindForceField(vs[1]); if (!mol.Empty()) if (!pFF->Setup(mol)) cout << "error while initializing the force field (" << vs[1] << ") for this molecule." <<endl; continue; } // load <filename> if (EQn(commandline, "load", 4)) { if (vs.size() < 2) { cout << "no <filename> specified." << endl; continue; } ifstream ifs; OBConversion conv; OBFormat *format_in = conv.FormatFromExt(vs[1].c_str()); if (!format_in || !conv.SetInFormat(format_in)) { cout << "could not detect format." << endl; continue; } ifs.open(vs[1].c_str()); if (!ifs) { cout << "could not open '" << vs[1] << "'." <<endl; continue; } mol.Clear(); if (!conv.Read(&mol, &ifs)) { cout << "could not read a molecule from '" << vs[1] << "'." <<endl; continue; } if (mol.Empty()) { cout << "this molecule is empty." <<endl; continue; } if (!pFF->Setup(mol)) { cout << "error while initializing the force field for this molecule." <<endl; continue; } cout << "molecule succesfully loaded." << endl; cout << " " << mol.NumAtoms() << " atoms" << endl; cout << " " << mol.NumBonds() << " bonds" << endl; ifs.close(); continue; } // save <filename> if (EQn(commandline, "save", 4)) { if (vs.size() < 2) { cout << "no <filename> specified." << endl; continue; } ofstream ofs; OBConversion conv; OBFormat *format_out = conv.FormatFromExt(vs[1].c_str()); if (!format_out || !conv.SetOutFormat(format_out)) { cout << "could not detect format." << endl; continue; } ofs.open(vs[1].c_str()); if (!ofs) { cout << "could not open '" << vs[1] << "'." <<endl; continue; } if (!conv.Write(&mol, &ofs)) { cout << "could not read a molecule from '" << vs[1] << "'." <<endl; continue; } cout << "molecule succesfully saved." << endl; cout << " " << mol.NumAtoms() << " atoms" << endl; cout << " " << mol.NumBonds() << " bonds" << endl; ofs.close(); continue; } // steepest descent if (EQn(commandline, "sd", 2)) { if (vs.size() < 2) { cout << "no <n> steps specified." << endl; continue; } pFF->SteepestDescent(atoi(vs[1].c_str()), OBFF_ANALYTICAL_GRADIENT); pFF->UpdateCoordinates(mol); continue; } // conjugate gradients if (EQn(commandline, "cg", 2)) { if (vs.size() < 2) { cout << "no <n> steps specified." << endl; continue; } pFF->ConjugateGradients(atoi(vs[1].c_str()), OBFF_ANALYTICAL_GRADIENT); pFF->UpdateCoordinates(mol); continue; } cout << "invalid command." << endl; } return(1); }
int main(int argc,char *argv[]) { OBConversion Conv(&cin, &cout); //default input and output are console OBFormat* pInFormat = NULL; OBFormat* pOutFormat = NULL; vector<string> FileList, OutputFileList; string OutputFileName; // Parse commandline bool gotInType = false, gotOutType = false; bool SplitOrBatch=false; char *oext = NULL; char *iext = NULL; //Save name of program without its path (and .exe) string pn(argv[0]); string::size_type pos; #ifdef _WIN32 pos = pn.find(".exe"); if(pos!=string::npos) argv[0][pos]='\0'; #endif pos = pn.find_last_of("/\\"); if(pos==string::npos) program_name=argv[0]; else program_name=argv[0]+pos+1; const char* p; int arg; for (arg = 1; arg < argc; ++arg) { if (argv[arg]) { if (argv[arg][0] == '-') { char opchar[2]="?"; opchar[0]=argv[arg][1]; switch (opchar[0]) { case 'V': { cout << "Open Babel " << BABEL_VERSION << " -- " << __DATE__ << " -- " << __TIME__ << endl; exit(0); } case 'i': //Parameter is the input format which overrides any file extensions gotInType = true; iext = argv[arg] + 2; if(!*iext) iext = argv[++arg]; //space left after -i: use next argument if (strncasecmp(iext, "MIME", 4) == 0) { // get the MIME type from the next argument iext = argv[++arg]; pInFormat = Conv.FormatFromMIME(iext); } else pInFormat = Conv.FindFormat(iext); if(pInFormat==NULL) { cerr << program_name << ": cannot read input format!" << endl; usage(); } break; case 'o': //Parameter is the output format which overrides any file extension gotOutType = true; oext = argv[arg] + 2; if(!*oext) oext = argv[++arg]; //space left after -i: use next argument if (strncasecmp(oext, "MIME", 4) == 0) { // get the MIME type from the next argument oext = argv[++arg]; pOutFormat = Conv.FormatFromMIME(oext); } else pOutFormat = Conv.FindFormat(oext); if(pOutFormat==NULL) { cerr << program_name << ": cannot write output format!" << endl; usage(); } break; case 'O': OutputFileName = argv[arg] + 2; if(OutputFileName.size()<3) OutputFileName = argv[++arg]; //space left after -O: use next argument break; case 'L': //display a list of plugin type or classes { const char* param=NULL; if(argc>arg+1) param = argv[arg+2]; // First assume first arg is a plugin type and // param is a subtype, like babel -L ops gen3D // or first arg is a plugin ID, like babel -L cml OBPlugin* plugin; if(OBPlugin::GetPlugin("plugins", argv[arg+1]) && (plugin = OBPlugin::GetPlugin(argv[arg+1], param)) || (plugin = OBPlugin::GetPlugin(NULL, argv[arg+1]))) { //Output details of subtype string txt; plugin->Display(txt, "verbose", argv[arg+1]); cout << "One of the " << plugin->TypeID() << '\n' << txt << endl; return 0; } //...otherwise assume it is a plugin type, like babel -L forcefields //Output list of subtypes OBPlugin::List(argv[arg+1], param); return 0; } case '?': case 'H': if(isalnum(argv[arg][2]) || arg==argc-2) { if(strncasecmp(argv[arg]+2,"all",3)) { OBFormat* pFormat = (arg==argc-2) ? Conv.FindFormat(argv[arg+1]) : Conv.FindFormat(argv[arg]+2); if(pFormat) { cout << argv[arg]+2 << " " << pFormat->Description() << endl; if(pFormat->Flags() & NOTWRITABLE) cout << " This format is Read-only" << endl; if(pFormat->Flags() & NOTREADABLE) cout << " This format is Write-only" << endl; if(strlen(pFormat->SpecificationURL())) cout << "Specification at: " << pFormat->SpecificationURL() << endl; } else cout << "Format type: " << argv[arg]+2 << " was not recognized" <<endl; } else { OBPlugin::List("formats","verbose"); } } else help(); return 0; case '-': //long option --name text { //Option's text is in the next and subsequent args, until one starts with - char* nam = argv[arg]+2; if(!strcasecmp(nam, "help")) //special case handled here { help(); return 0; } if(*nam != '\0') //Do nothing if name is empty { string txt; while(arg<argc-1 && *argv[arg+1]!='-') { //use text from subsequent args if(!txt.empty())txt += ' '; //..space separated if more than one txt += argv[++arg]; } // If a API directive, e.g.---errorlevel // send to the pseudoformat "obapi" (without any leading -) if(*nam=='-') { OBConversion apiConv; OBFormat* pAPI= OBConversion::FindFormat("obapi"); if(pAPI) { apiConv.SetOutFormat(pAPI); apiConv.AddOption(nam+1, OBConversion::GENOPTIONS, txt.c_str()); apiConv.Write(NULL, &std::cout); } } else // Is a normal long option name, e.g --addtotitle Conv.AddOption(nam,OBConversion::GENOPTIONS,txt.c_str()); } } break; case 'm': //multiple output files SplitOrBatch=true; break; case 'a': //single character input option p = argv[arg]+2; DoOption(p,Conv,OBConversion::INOPTIONS,arg,argc,argv); break; case 'x': //single character output option p = argv[arg]+2; DoOption(p,Conv,OBConversion::OUTOPTIONS,arg,argc,argv); break; //Not essential, but allows these options to be before input filenames //since we know they take one parameter, and are the most likely options to be misplaced case 'f': case 'l': p = argv[arg] + 2; if(!*p) p = argv[++arg]; //space left after -f: use next argument Conv.AddOption(opchar, OBConversion::GENOPTIONS, p); break; case ':': //e.g. -:c1ccccc1. SMILES passed as a file name and handled in OBConversion FileList.push_back(argv[arg]); break; default: //single character general option p = argv[arg]+1; DoOption(p,Conv,OBConversion::GENOPTIONS,arg,argc,argv); break; } } else //filenames FileList.push_back(argv[arg]); } } #ifdef _WIN32 //Expand wildcards in input filenames and add to FileList vector<string> tempFileList(FileList); FileList.clear(); vector<string>::iterator itr; for(itr=tempFileList.begin();itr!=tempFileList.end();++itr) { if((*itr)[0]=='-') FileList.push_back(*itr); else DLHandler::findFiles (FileList, *itr); } #endif if (!gotInType) { if(FileList.empty()) { cerr << "No input file or format spec or possibly a misplaced option.\n" "Options, other than -i -o -O -m, must come after the input files.\n" <<endl; usage(); } } if (!gotOutType) { //check there is a valid output format, but the extension will be re-interpreted in OBConversion pOutFormat = Conv.FormatFromExt(OutputFileName.c_str()); if(OutputFileName.empty() || pOutFormat==NULL) { cerr << "Missing or unknown output file or format spec or possibly a misplaced option.\n" "Options, other than -i -o -O -m, must come after the input files.\n" <<endl; usage(); } } if(!Conv.SetInFormat(pInFormat)) { cerr << "Invalid input format" << endl; usage(); } if(!Conv.SetOutFormat(pOutFormat)) { cerr << "Invalid output format" << endl; usage(); } if(SplitOrBatch) { //Put * into output file name before extension (or ext.gz) if(OutputFileName.empty()) { OutputFileName = "*."; OutputFileName += oext; } else { string::size_type pos = OutputFileName.rfind(".gz"); if(pos==string::npos) pos = OutputFileName.rfind('.'); else pos = OutputFileName.rfind('.',pos-1); if(pos==string::npos) OutputFileName += '*'; else OutputFileName.insert(pos,"*"); } } int count = Conv.FullConvert(FileList, OutputFileName, OutputFileList); Conv.ReportNumberConverted(count); if(OutputFileList.size()>1) { clog << OutputFileList.size() << " files output. The first is " << OutputFileList[0] <<endl; } //std::string messageSummary = obErrorLog.GetMessageSummary(); //if (messageSummary.size()) // { // clog << messageSummary << endl; // } #ifdef _DEBUG //CM keep window open cout << "Press any key to finish" <<endl; getch(); #endif return 0; }
int main(int argc,char **argv) { char *program_name= argv[0]; int c; char *FileIn = NULL; if (argc != 2) { string err = "Usage: "; err += program_name; err += " <filename>\n" "Output format:\n" "name NAME\n" "formula FORMULA\n" "mol_weight MOLECULAR_WEIGHT\n" "exact_mass ISOTOPIC MASS\n" "canonical_SMILES STRING\n" "InChI STRING\n" "num_atoms NUM\n" "num_bonds NUM\n" "num_residues NUM\n" "num_rotors NUM\n" "sequence RESIDUE_SEQUENCE\n" "num_rings NUMBER_OF_RING_(SSSR)\n" "logP NUM\n" "PSA POLAR_SURFACE_AREA\n" "MR MOLAR REFRACTIVITY"; err += "$$$$"; // ThrowError(err); wasn't being output because error level too low cerr << err; //Why not do directly exit(-1); } else { FileIn = argv[1]; } // Find Input filetype OBConversion conv; OBFormat *format = conv.FormatFromExt(FileIn); if (!format || !conv.SetInFormat(format)) { cerr << program_name << ": cannot read input format!" << endl; exit (-1); } ifstream ifs; // Read the file ifs.open(FileIn); if (!ifs) { cerr << program_name << ": cannot read input file!" << endl; exit (-1); } OBMol mol; OBFormat *canSMIFormat = conv.FindFormat("can"); OBFormat *inchiFormat = conv.FindFormat("inchi"); //////////////////////////////////////////////////////////////////////////// // List of properties // Name // Molecular weight (Standard molar mass given by IUPAC atomic masses) // Number of rings : the size of the smallest set of smallest rings (SSSR) //.....ADD YOURS HERE..... for (c = 1;; ++c) { mol.Clear(); conv.Read(&mol, &ifs); if (mol.Empty()) break; if (!mol.HasHydrogensAdded()) mol.AddHydrogens(); // Print the properties if (strlen(mol.GetTitle()) != 0) cout << "name " << mol.GetTitle() << endl; else cout << "name " << FileIn << " " << c << endl; cout << "formula " << mol.GetFormula() << endl; cout << "mol_weight " << mol.GetMolWt() << endl; cout << "exact_mass " << mol.GetExactMass() << endl; string smilesString = "-"; if (canSMIFormat) { conv.SetOutFormat(canSMIFormat); smilesString = conv.WriteString(&mol); if ( smilesString.length() == 0 ) { smilesString = "-"; } } cout << "canonical_SMILES " << smilesString << endl; string inchiString = "-"; if (inchiFormat) { conv.SetOutFormat(inchiFormat); inchiString = conv.WriteString(&mol); if ( inchiString.length() == 0 ) { inchiString = "-"; } } cout << "InChI " << inchiString << endl; cout << "num_atoms " << mol.NumAtoms() << endl; cout << "num_bonds " << mol.NumBonds() << endl; cout << "num_residues " << mol.NumResidues() << endl; cout << "num_rotors " << mol.NumRotors() << endl; if (mol.NumResidues() > 0) cout << "sequence " << sequence(mol) << endl; else cout << "sequence " << "-" << endl; cout << "num_rings " << nrings(mol) << endl; OBDescriptor* pDesc; pDesc= OBDescriptor::FindType("logP"); if(pDesc) cout << "logP " << pDesc->Predict(&mol) << endl; pDesc = OBDescriptor::FindType("TPSA"); if(pDesc) cout << "PSA " << pDesc->Predict(&mol) << endl; pDesc = OBDescriptor::FindType("MR"); if(pDesc) cout << "MR " << pDesc->Predict(&mol) << endl; cout << "$$$$" << endl; // SDF like end of compound descriptor list //Other OBDescriptors could be output here, even ones that were rarely // used. Since these are plugin classes, they may not be loaded, but // then with code like the above they are just ignored. } // end for loop return(0); }