ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/trunk/src/applications/mdinConverter/mdinConverter.cpp
Revision: 747
Committed: Wed Nov 16 21:24:34 2005 UTC (19 years, 8 months ago) by tim
File size: 19029 byte(s)
Log Message:
adding mdinConverter

File Contents

# User Rev Content
1 tim 747 /**********************************************************************
2     main.cpp - Main conversion program, command-line handling.
3    
4     Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5     Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison
6     Some portions Copyright (C) 2004-2005 by Chris Morley
7    
8     This file is part of the Open Babel project.
9     For more information, see <http://openbabel.sourceforge.net/>
10    
11     This program is free software; you can redistribute it and/or modify
12     it under the terms of the GNU General Public License as published by
13     the Free Software Foundation version 2 of the License.
14    
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18     GNU General Public License for more details.
19     ***********************************************************************/
20    
21     #include "openbabel/babelconfig.hpp"
22     #if HAVE_IOSTREAM
23     #include <iostream>
24     #elif HAVE_IOSTREAM_H
25     #include <iostream.h>
26     #endif
27     #if HAVE_FSTREAM
28     #include <fstream>
29     #elif HAVE_FSTREAM_H
30     #include <fstream.h>
31     #endif
32     #if HAVE_SSTREAM
33     #include <sstream>
34     #elif
35     #include <sstream.h>
36     #endif
37    
38     #include <string>
39     #include <map>
40     #if HAVE_CONIO_H
41     #include <conio.h>
42     #endif
43    
44     #if !HAVE_STRNCASECMP
45     extern "C" int strncasecmp(const char *s1, const char *s2, size_t n);
46     #endif
47    
48     #include "openbabel/obconversion.hpp"
49     #include "brains/Register.hpp"
50    
51     using namespace std;
52     using namespace OpenBabel;
53     using namespace oopse;
54     void DoOption(const char* p, OBConversion& Conv, OBConversion::Option_type typ,
55     int& arg, int argc, char *argv[]);
56     void usage();
57     void help();
58    
59     // There isn't a great way to do this -- we need to save argv[0] for usage()
60     static char *program_name;
61    
62     int main(int argc,char *argv[])
63     {
64     registerOBFormats();
65     OBConversion Conv(&cin, &cout); //default input and output are console
66    
67     // string GenOptions;
68     OBFormat* pInFormat = NULL;
69     OBFormat* pOutFormat = NULL;
70     vector<string> FileList, OutputFileList;
71     string OutputFileName;
72     // obMessageLevel filterLevel = obWarning; // 2 out of 5
73    
74     // Parse commandline
75     bool gotInType = false, gotOutType = false;
76     bool UseSavedOptions = false;
77     bool SplitOrBatch=false;
78    
79     char *oext;
80     char *iext;
81    
82     //Save name of program without its path (and .exe)
83     string pn(argv[0]);
84     unsigned int pos;
85     #ifdef _WIN32
86     pos = pn.find(".exe");
87     if(pos!=string::npos)
88     argv[0][pos]='\0';
89     #endif
90     pos = pn.find_last_of("/\\");
91     if(pos==string::npos)
92     program_name=argv[0];
93     else
94     program_name=argv[0]+pos+1;
95    
96     const char* p;
97     int arg;
98     for (arg = 1; arg < argc; arg++)
99     {
100     if (argv[arg])
101     {
102     if (argv[arg][0] == '-')
103     {
104     switch (argv[arg][1])
105     {
106    
107     case 'V':
108     {
109     cout << "Open Babel " << BABEL_VERSION << " -- "
110     << __DATE__ << " -- " << __TIME__ << endl;
111     exit(0);
112     }
113    
114     case 'i':
115     gotInType = true;
116     iext = argv[arg] + 2;
117     if(!*iext)
118     iext = argv[++arg]; //space left after -i: use next argument
119    
120     if (strncasecmp(iext, "MIME", 4) == 0)
121     {
122     // get the MIME type from the next argument
123     iext = argv[++arg];
124     pInFormat = Conv.FormatFromMIME(iext);
125     }
126     else
127     {
128     //The ID provided by the OBFormat class is used as the identifying file extension
129     pInFormat = Conv.FindFormat(iext);
130     }
131     if(pInFormat==NULL)
132     {
133     cerr << program_name << ": cannot read input format!" << endl;
134     usage();
135     }
136     break;
137    
138     case 'o':
139     gotOutType = true;
140     oext = argv[arg] + 2;
141     if(!*oext)
142     oext = argv[++arg]; //space left after -i: use next argument
143    
144     if (strncasecmp(oext, "MIME", 4) == 0)
145     {
146     // get the MIME type from the next argument
147     oext = argv[++arg];
148     pOutFormat = Conv.FormatFromMIME(oext);
149     }
150     else
151     pOutFormat = Conv.FindFormat(oext);
152    
153     if(pOutFormat==NULL)
154     {
155     cerr << program_name << ": cannot write output format!" << endl;
156     usage();
157     }
158     break;
159    
160     case 'F':
161     if(!Conv.SetOutFormat("fpt"))
162     cout << "FingerprintFormat needs to be loaded" << endl;
163     else
164     {
165     Conv.AddOption("F",OBConversion::OUTOPTIONS);
166     Conv.Write(NULL);
167     }
168     return 0;
169    
170     case '?':
171     case 'H':
172     if(isalnum(argv[arg][2]))
173     {
174     if(strncasecmp(argv[arg]+2,"all",3))
175     {
176     OBFormat* pFormat = Conv.FindFormat(argv[arg]+2);
177     if(pFormat)
178     {
179     cout << argv[arg]+2 << " " << pFormat->Description() << endl;
180     if(strlen(pFormat->SpecificationURL()))
181     cout << "Specification at: " << pFormat->SpecificationURL() << endl;
182     }
183     else
184     cout << "Format type: " << argv[arg]+2 << " was not recognized" <<endl;
185     }
186     else
187     {
188     Formatpos pos;
189     OBFormat* pFormat;
190     const char* str=NULL;
191     while(OBConversion::GetNextFormat(pos,str,pFormat))
192     {
193     if((pFormat->Flags() & NOTWRITABLE) && (pFormat->Flags() & NOTREADABLE))
194     continue;
195     cout << str << endl;
196     const char* p = strchr(pFormat->Description(),'\n');
197     cout << p+1; //second line of description
198     if(strlen(pFormat->SpecificationURL()))
199     cout << "Specification at: " << pFormat->SpecificationURL();
200     cout << endl << endl;
201     }
202     }
203     }
204     else
205     help();
206     exit(0);
207    
208     case '-': //long option --name text
209     {
210     //Do nothing if name is empty
211     //Option's text is the next arg provided it doesn't start with -
212     char* nam = argv[arg]+2;
213     if(*nam != '\0')
214     {
215     const char* txt=NULL;
216     if(Conv.GetOptionParams(nam, OBConversion::OUTOPTIONS)
217     && arg<argc-1 && argv[arg+1] && *argv[arg+1]!='-')
218     txt = argv[++arg];
219     if(*nam=='-')
220     {
221     // Is a API directive, e.g.---errorlevel
222     //Send to the pseudoformat "obapi" (without any leading -)
223     OBConversion apiConv;
224     OBFormat* pAPI= OBConversion::FindFormat("obapi");
225     if(pAPI)
226     {
227     apiConv.SetOutFormat(pAPI);
228     apiConv.AddOption(nam+1, OBConversion::OUTOPTIONS, txt);
229     apiConv.Write(NULL);
230     }
231     }
232     else
233     // Is a long option name, e.g --addtotitle
234     Conv.AddOption(nam,OBConversion::GENOPTIONS,txt);
235     }
236     }
237     break;
238    
239     case 'm': //multiple output files
240     SplitOrBatch=true;
241     break;
242    
243     case 'a': //single character input option
244     p = argv[arg]+2;
245     DoOption(p,Conv,OBConversion::INOPTIONS,arg,argc,argv);
246     break;
247    
248     case 'x': //single character output option
249     p = argv[arg]+2;
250     DoOption(p,Conv,OBConversion::OUTOPTIONS,arg,argc,argv);
251     break;
252    
253     default: //single character general option
254     p = argv[arg]+1;
255     DoOption(p,Conv,OBConversion::GENOPTIONS,arg,argc,argv);
256     break;
257     }
258     }
259     else
260     {
261     //filenames
262     if(!gotOutType)
263     FileList.push_back(argv[arg]);
264     else
265     OutputFileName = argv[arg];
266     }
267     }
268     }
269    
270     if(!gotOutType) //the last file is the output
271     {
272     if(FileList.empty())
273     {
274     cerr << "No output file or format spec!" << endl;
275     usage();
276     }
277     OutputFileName = FileList.back();
278     FileList.pop_back();
279     }
280    
281     #ifdef _WIN32
282     //Expand wildcards in input filenames and add to FileList
283     vector<string> tempFileList(FileList);
284     FileList.clear();
285     vector<string>::iterator itr;
286     for(itr=tempFileList.begin();itr!=tempFileList.end();itr++)
287     DLHandler::findFiles (FileList, *itr);
288     #endif
289    
290     // Conv.SetGeneralOptions(GenOptions.c_str());
291    
292     if (!gotInType)
293     {
294     if(FileList.empty())
295     {
296     cerr << "No input file or format spec!" <<endl;
297     usage();
298     }
299     }
300    
301     if (!gotOutType)
302     {
303     pOutFormat = Conv.FormatFromExt(OutputFileName.c_str());
304     if(pOutFormat==NULL)
305     {
306     cerr << program_name << ": cannot write output format!" << endl;
307     usage();
308     }
309     }
310    
311     Conv.SetInAndOutFormats(pInFormat,pOutFormat);
312    
313     if(SplitOrBatch)
314     {
315     //Put * into output file name before extension (or ext.gz)
316     if(OutputFileName.empty())
317     {
318     OutputFileName = "*.";
319     OutputFileName += oext;
320     }
321     else
322     {
323     unsigned int pos = OutputFileName.rfind(".gz");
324     if(pos==string::npos)
325     pos = OutputFileName.rfind('.');
326     else
327     pos = OutputFileName.rfind('.',pos-1);
328     if(pos==string::npos)
329     OutputFileName += '*';
330     else
331     OutputFileName.insert(pos,"*");
332     }
333     }
334    
335     // send info message to clog -- don't mess up cerr or cout for user programs
336     int count = Conv.FullConvert(FileList, OutputFileName, OutputFileList);
337     if ( count == 1 )
338     clog << count << " molecule converted" << endl;
339     else
340     clog << count << " molecules converted" << endl;
341    
342     if(OutputFileList.size()>1)
343     {
344     clog << OutputFileList.size() << " files output. The first is " << OutputFileList[0] <<endl;
345     }
346    
347     #ifdef _DEBUG
348     //CM keep window open
349     cout << "Press any key to finish" <<endl;
350     getch();
351     #endif
352    
353     return 0;
354     };
355    
356     void DoOption(const char* p, OBConversion& Conv, OBConversion::Option_type typ, int& arg, int argc, char *argv[])
357     {
358     while(p && *p) //can have multiple single char options
359     {
360     char ch[2]="?";
361     *ch = *p++;
362     const char* txt=NULL;
363     //Get the option text if needed
364     int nParams = Conv.GetOptionParams(ch, typ);
365     if(nParams)
366     {
367     if(*p)
368     {
369     txt = p; //use text immediately following the option letter
370     p=NULL; //no more single char options
371     }
372     else if(arg<argc-1)
373     {
374     txt = argv[++arg]; //use text from next arg
375     if(*txt=='-')
376     {
377     //...unless it is another option
378     cerr << "Option -" << ch << " takes a parameter" << endl;
379     exit(0);
380     }
381     }
382     }
383     Conv.AddOption(ch, typ, txt);
384     }
385     }
386    
387     void usage()
388     {
389     cout << "Open Babel " << BABEL_VERSION << " -- " << __DATE__ << " -- "
390     << __TIME__ << endl;
391     cout << "Usage: " << program_name
392     << " [-i<input-type>] <name> [-o<output-type>] <name>" << endl;
393     cout << "Try -H option for more information." << endl;
394     /*
395     #ifdef _DEBUG
396     //CM keep window open
397     cout << "Press any key to finish" <<endl;
398     getch();
399     #endif
400     */
401     exit (0);
402     }
403    
404     void help()
405     {
406     cout << "Open Babel converts chemical structures from one file format to another"<< endl << endl;
407     cout << "Usage: " << program_name << " <input spec> <output spec> [Options]" << endl << endl;
408     cout << "Each spec can be a file whose extension decides the format." << endl;
409     cout << "Optionally the format can be specified by preceding the file by" << endl;
410     cout << "-i<format-type> e.g. -icml, for input and -o<format-type> for output" << endl << endl;
411     cout << "See below for available format-types, which are the same as the " << endl;
412     cout << "file extensions and are case independent." << endl;
413     cout << "If no input or output file is given stdin or stdout are used instead." << endl << endl;
414     cout << "More than one input file can be specified and their names can contain" <<endl;
415     cout << "wildcard chars (* and ?).The molecules are aggregated in the output file.\n" << endl;
416     cout << OBConversion::Description(); // Conversion options
417     cout << " -H Outputs this help text" << endl;
418     cout << " -Hxxx (xxx is file format ID e.g. -Hcml) gives format info" <<endl;
419     cout << " -Hall Outputs details of all formats" <<endl;
420     cout << " -V Outputs version number" <<endl;
421     cout << " -F Outputs the available fingerprint types" <<endl;
422     cout << " -m Produces multiple output files, to allow:" <<endl;
423     cout << " Splitting: e.g. " << program_name << " infile.mol new.smi -m" <<endl;
424     cout << " puts each molecule into new1.smi new2.smi etc" <<endl;
425     cout << " Batch conversion: e.g. " << program_name << " *.mol -osmi -m" <<endl;
426     cout << " converts each input file to a .smi file" << endl;
427     #ifdef _WIN32
428     cout << " In Windows these can also be done using the forms" <<endl;
429     cout << " " << program_name << " infile.mol new*.smi and " << program_name << " *.mol *.smi respectively.\n" <<endl;
430     #endif
431    
432     OBFormat* pDefault = OBConversion::GetDefaultFormat();
433     if(pDefault)
434     cout << pDefault->TargetClassDescription();// some more options probably for OBMol
435    
436     OBFormat* pAPI= OBConversion::FindFormat("obapi");
437     if(pAPI)
438     cout << pAPI->Description();
439    
440     cout << "The following file formats are recognized:" << endl;
441     Formatpos pos;
442     OBFormat* pFormat;
443     const char* str=NULL;
444     while(OBConversion::GetNextFormat(pos,str,pFormat))
445     {
446     if((pFormat->Flags() & NOTWRITABLE) && (pFormat->Flags() & NOTREADABLE))
447     continue;
448     cout << " " << str << endl;
449     }
450     cout << "\nSee further specific info and options using -H<format-type>, e.g. -Hcml" << endl;
451     }
452    
453     /* OpenBabel man page*/
454     /** \page babel a converter for chemistry and molecular modeling data files
455     *
456     * \n
457     * \par SYNOPSIS
458     *
459     * \b babel [-H<help-options>] [-V] [-m] [-d] [-h] [-p] [-s<SMARTS-pattern>] [-v<SMARTS-pattern>] [-f<#> -l<#>] [-c] [-x<format-options>] [-i<input-type>] \<infile\> [-o<output-type>] \<outfile\>
460     *
461     * \par DESCRIPTION
462     *
463     * Open Babel is a program designed to interconvert a number of
464     * file formats currently used in molecular modeling software. \n\n
465     *
466     * Note that Open Babel can also be used as a library to interconvert
467     * many file formats and to provide standard chemistry software routines.
468     * See the Open Babel web pages (http://openbabel.sourceforge.net) for more
469     * information.
470     *
471     * \par OPTIONS
472     *
473     * If only input and ouput files are given, Open Babel will guess
474     * the file type from the filename extension. \n\n
475     *
476     * \b -V :
477     * Output version number and exit \n\n
478     * \b -H :
479     * Output usage information \n\n
480     * \b -H\<format-ID\> :
481     * Output formatting information and options for format specified\n\n
482     * \b -Hall :
483     * Output formatting information and options for all formats\n\n
484     * \b -i :
485     * Specifies input format, see below for the available formats \n\n
486     * \b -o :
487     * Specifies output format, see below for the available formats \n\n
488     * \b -m :
489     * Produce multiple output files, to allow:\n
490     * * Splitting one input file - put each molecule into consecutively numbered output files \n
491     * * Batch conversion - convert each of multiple input files into a specified output format \n
492     * See examples below \n\n
493     * \b -d :
494     * Delete Hydrogens \n\n
495     * \b -h :
496     * Add Hydrogens \n\n
497     * \b -p :
498     * Add Hydrogens appropriate for pH (use transforms in phmodel.txt) \n\n
499     * \b -t :
500     * All input files describe a single molecule \n\n
501     * \b -f\<#\> :
502     * For multiple entries input, start import at molecule # \n\n
503     * \b -l\<#\> :
504     * For multiple entries input, stop import at molecule # \n\n
505     * \b -c :
506     * Center atomic coordinates at (0,0,0) \n\n
507     * \b -s\<SMARTS\> :
508     * Convert only molecules matching the SMARTS pattern specified \n\n
509     * \b -v\<SMARTS\> :
510     * Convert only molecules \b NOT matching SMARTS pattern specified \n\n
511     *
512     * \par FILE FORMATS
513     *
514     * The following formats are currently supported by Open Babel:
515     * \n alc -- Alchemy format
516     * \n bgf -- BGF format
517     * \n box -- Dock 3.5 Box format
518     * \n bs -- Ball and Stick format
519     * \n c3d1 -- Chem3D Cartesian 1 format
520     * \n c3d2 -- Chem3D Cartesian2 format
521     * \n caccrt -- Cacao format
522     * \n cache -- CAChe format [Writeonly]
523     * \n cacint -- CacaoInternal format [Writeonly]
524     * \n car -- MSI Biosym/Insight II CAR format [Readonly]
525     * \n ccc -- CCC format [Readonly]
526     * \n cht -- ChemTool format [Writeonly]
527     * \n cml -- Chemical Markup Language
528     * \n crk2d -- Chemical Resource Kit diagram format (2D)
529     * \n crk3d -- Chemical Resource Kit 3D format
530     * \n csr -- CSR format [Writeonly]
531     * \n cssr -- CSD CSSR format [Writeonly]
532     * \n ct -- ChemDraw Connection Table format
533     * \n dmol -- DMol3 coordinates format
534     * \n ent -- Protein Data Bank format
535     * \n feat -- Feature format
536     * \n fh -- Fenske-Hall Z-Matrix format [Writeonly]
537     * \n fix -- FIX format [Writeonly]
538     * \n g03 -- Gaussian98/03 Cartesian [Writeonly]
539     * \n g98 -- Gaussian98/03 Cartesian [Writeonly]
540     * \n gam -- GAMESS Output
541     * \n gamout -- GAMESS Output
542     * \n gau -- Gaussian98/03 Cartesian [Writeonly]
543     * \n gpr -- Ghemical format
544     * \n gr96 -- GROMOS96 format [Writeonly]
545     * \n hin -- HyperChem Input format
546     * \n ins -- ShelX format [Readonly]
547     * \n jout -- Jaguar output format
548     * \n mdl -- MDL MOL format
549     * \n mm1gp -- Ghemical format
550     * \n mm3 -- MM3 format [Writeonly]
551     * \n mmd -- MacroMod format
552     * \n mmod -- MacroMod format
553     * \n mol -- MDL MOL format
554     * \n mol2 -- Sybyl Mol2 format
555     * \n mopcrt -- MOPAC Cartesian format
556     * \n mopout -- MOPAC Output format [Readonly]
557     * \n mpqc -- MPQC format [Readonly]
558     * \n nwo -- NWChem format
559     * \n pdb -- Protein Data Bank format
560     * \n pov -- POV-Ray input format [Writeonly]
561     * \n pqs -- Parallel Quantum Solutions format
562     * \n prep -- Amber Prep format [Readonly]
563     * \n qcout -- QChem output format
564     * \n qm1gp -- Ghemical format
565     * \n report -- Report format [Writeonly]
566     * \n res -- ShelX format [Readonly]
567     * \n rxn -- MDL RXN format
568     * \n sd -- MDL MOL format
569     * \n sdf -- MDL MOL format
570     * \n smi -- SMILES format
571     * \n tmol -- TurboMole Coordinate format
572     * \n txyz -- Tinker format [Writeonly]
573     * \n unixyz -- UniChem XYZ format
574     * \n vmol -- ViewMol format
575     * \n xed -- XED format [Writeonly]
576     * \n xyz -- XYZ cartesian coordinates format
577     * \n zin -- ZINDO input format [Writeonly]
578     *
579     * \par FORMAT OPTIONS
580     * Individual file formats may have additional formatting options. \n
581     * Input format options are preceded by 'a', e.g. -as \n
582     * Output format options are preceded by 'x', e.g. -xn \n
583     * For further specific information and options, use -H<format-type> \n
584     * e.g., -Hcml
585     *
586     * \par EXAMPLES
587     * - Standard conversion \n
588     * babel -ixyz ethanol.xyz -opdb ethanol.pdb \n
589     * - Conversion from a SMI file in STDIN to a Mol2 file written to STDOUT \n
590     * babel -ismi -omol2 \n
591     * - Split a multi-molecule file into new1.smi, new2.smi, etc. \n
592     * babel infile.mol new.smi -m \n
593     *
594     * \par AUTHORS
595     *
596     * Open Babel is currently maintained by \b Geoff \b Hutchison, \b Chris \b Morley and \b Michael \b Banck.
597     *
598     * For more contributors to Open Babel, see http://openbabel.sourceforge.net/THANKS.shtml
599     *
600     * \par COPYRIGHT
601     * Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
602     * Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison \n \n
603     * This program is free software; you can redistribute it and/or modify
604     * it under the terms of the GNU General Public License as published by
605     * the Free Software Foundation version 2 of the License.\n \n
606     * This program is distributed in the hope that it will be useful,
607     * but WITHOUT ANY WARRANTY; without even the implied warranty of
608     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
609     * GNU General Public License for more details.
610     *
611     * \par SEE ALSO
612     * The web pages for Open Babel can be found at http://openbabel.sourceforge.net/
613     **/