Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / trajectoryanalysis / cmdlinerunner.cpp
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11  * Copyright (c) 2001-2009, The GROMACS development team,
12  * check out http://www.gromacs.org for more information.
13
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * If you want to redistribute modifications, please consider that
20  * scientific software is very special. Version control is crucial -
21  * bugs must be traceable. We will be happy to consider code for
22  * inclusion in the official distribution, but derived work must not
23  * be called official GROMACS. Details are found in the README & COPYING
24  * files - if they are missing, get the official version at www.gromacs.org.
25  *
26  * To help us fund GROMACS development, we humbly ask that you cite
27  * the papers on the package - you can find them in the top README file.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \internal \file
32  * \brief
33  * Implements gmx::TrajectoryAnalysisCommandLineRunner.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \ingroup module_trajectoryanalysis
37  */
38 #include "cmdlinerunner.h"
39
40 #ifdef HAVE_CONFIG_H
41 #include "config.h"
42 #endif
43
44 #include "gromacs/legacyheaders/copyrite.h"
45 #include "gromacs/legacyheaders/pbc.h"
46 #include "gromacs/legacyheaders/rmpbc.h"
47 #include "gromacs/legacyheaders/statutil.h"
48
49 #include "gromacs/analysisdata/paralleloptions.h"
50 #include "gromacs/commandline/cmdlinehelpwriter.h"
51 #include "gromacs/commandline/cmdlineparser.h"
52 #include "gromacs/onlinehelp/helpwritercontext.h"
53 #include "gromacs/options/options.h"
54 #include "gromacs/selection/selectioncollection.h"
55 #include "gromacs/selection/selectionoptionmanager.h"
56 #include "gromacs/trajectoryanalysis/analysismodule.h"
57 #include "gromacs/trajectoryanalysis/analysissettings.h"
58 #include "gromacs/trajectoryanalysis/runnercommon.h"
59 #include "gromacs/utility/exceptions.h"
60 #include "gromacs/utility/file.h"
61 #include "gromacs/utility/gmxassert.h"
62
63 namespace gmx
64 {
65
66 /********************************************************************
67  * TrajectoryAnalysisCommandLineRunner::Impl
68  */
69
70 class TrajectoryAnalysisCommandLineRunner::Impl
71 {
72     public:
73         Impl(TrajectoryAnalysisModule *module);
74         ~Impl();
75
76         void printHelp(const Options &options,
77                        const TrajectoryAnalysisSettings &settings,
78                        const TrajectoryAnalysisRunnerCommon &common);
79         bool parseOptions(TrajectoryAnalysisSettings *settings,
80                           TrajectoryAnalysisRunnerCommon *common,
81                           SelectionCollection *selections,
82                           int *argc, char *argv[]);
83
84         TrajectoryAnalysisModule *module_;
85         int                     debugLevel_;
86         bool                    bPrintCopyright_;
87 };
88
89
90 TrajectoryAnalysisCommandLineRunner::Impl::Impl(
91         TrajectoryAnalysisModule *module)
92     : module_(module), debugLevel_(0), bPrintCopyright_(true)
93 {
94 }
95
96
97 TrajectoryAnalysisCommandLineRunner::Impl::~Impl()
98 {
99 }
100
101
102 void
103 TrajectoryAnalysisCommandLineRunner::Impl::printHelp(
104         const Options &options,
105         const TrajectoryAnalysisSettings &settings,
106         const TrajectoryAnalysisRunnerCommon &common)
107 {
108     TrajectoryAnalysisRunnerCommon::HelpFlags flags = common.helpFlags();
109     if (flags != 0)
110     {
111         HelpWriterContext context(&File::standardError(),
112                                   eHelpOutputFormat_Console);
113         CommandLineHelpWriter(options)
114             .setShowDescriptions(flags & TrajectoryAnalysisRunnerCommon::efHelpShowDescriptions)
115             .setShowHidden(flags & TrajectoryAnalysisRunnerCommon::efHelpShowHidden)
116             .setTimeUnitString(settings.timeUnitManager().timeUnitAsString())
117             .writeHelp(context);
118     }
119 }
120
121
122 bool
123 TrajectoryAnalysisCommandLineRunner::Impl::parseOptions(
124         TrajectoryAnalysisSettings *settings,
125         TrajectoryAnalysisRunnerCommon *common,
126         SelectionCollection *selections,
127         int *argc, char *argv[])
128 {
129     Options options(NULL, NULL);
130     Options moduleOptions(module_->name(), module_->description());
131     Options commonOptions("common", "Common analysis control");
132     Options selectionOptions("selection", "Common selection control");
133     module_->initOptions(&moduleOptions, settings);
134     common->initOptions(&commonOptions);
135     selections->initOptions(&selectionOptions);
136
137     options.addSubSection(&commonOptions);
138     options.addSubSection(&selectionOptions);
139     options.addSubSection(&moduleOptions);
140
141     SelectionOptionManager seloptManager(selections);
142     setManagerForSelectionOptions(&options, &seloptManager);
143
144     {
145         CommandLineParser  parser(&options);
146         try
147         {
148             parser.parse(argc, argv);
149         }
150         catch (const UserInputError &ex)
151         {
152             printHelp(options, *settings, *common);
153             throw;
154         }
155         printHelp(options, *settings, *common);
156         common->scaleTimeOptions(&options);
157         options.finish();
158     }
159
160     if (!common->optionsFinished(&commonOptions))
161     {
162         return false;
163     }
164     module_->optionsFinished(&moduleOptions, settings);
165
166     common->initIndexGroups(selections);
167
168     // TODO: Check whether the input is a pipe.
169     bool bInteractive = true;
170     seloptManager.parseRequestedFromStdin(bInteractive);
171     common->doneIndexGroups(selections);
172
173     return true;
174 }
175
176
177 /********************************************************************
178  * TrajectoryAnalysisCommandLineRunner
179  */
180
181 TrajectoryAnalysisCommandLineRunner::TrajectoryAnalysisCommandLineRunner(
182         TrajectoryAnalysisModule *module)
183     : impl_(new Impl(module))
184 {
185 }
186
187
188 TrajectoryAnalysisCommandLineRunner::~TrajectoryAnalysisCommandLineRunner()
189 {
190 }
191
192
193 void
194 TrajectoryAnalysisCommandLineRunner::setPrintCopyright(bool bPrint)
195 {
196     impl_->bPrintCopyright_ = bPrint;
197 }
198
199
200 void
201 TrajectoryAnalysisCommandLineRunner::setSelectionDebugLevel(int debuglevel)
202 {
203     impl_->debugLevel_ = 1;
204 }
205
206
207 int
208 TrajectoryAnalysisCommandLineRunner::run(int argc, char *argv[])
209 {
210     TrajectoryAnalysisModule *module = impl_->module_;
211
212     if (impl_->bPrintCopyright_)
213     {
214         CopyRight(stderr, argv[0]);
215     }
216
217     SelectionCollection  selections;
218     selections.setDebugLevel(impl_->debugLevel_);
219
220     TrajectoryAnalysisSettings  settings;
221     TrajectoryAnalysisRunnerCommon  common(&settings);
222
223     if (!impl_->parseOptions(&settings, &common, &selections, &argc, argv))
224     {
225         return 0;
226     }
227
228     common.initTopology(&selections);
229     selections.compile();
230
231     const TopologyInformation &topology = common.topologyInformation();
232     module->initAnalysis(settings, topology);
233
234     // Load first frame.
235     common.initFirstFrame();
236     module->initAfterFirstFrame(common.frame());
237
238     t_pbc  pbc;
239     t_pbc *ppbc = settings.hasPBC() ? &pbc : NULL;
240
241     int nframes = 0;
242     AnalysisDataParallelOptions dataOptions;
243     TrajectoryAnalysisModuleDataPointer pdata(
244             module->startFrames(dataOptions, selections));
245     do
246     {
247         common.initFrame();
248         t_trxframe &frame = common.frame();
249         if (ppbc != NULL)
250         {
251             set_pbc(ppbc, topology.ePBC(), frame.box);
252         }
253
254         selections.evaluate(&frame, ppbc);
255         module->analyzeFrame(nframes, frame, ppbc, pdata.get());
256
257         nframes++;
258     }
259     while (common.readNextFrame());
260     module->finishFrames(pdata.get());
261     if (pdata.get() != NULL)
262     {
263         pdata->finish();
264     }
265     pdata.reset();
266
267     if (common.hasTrajectory())
268     {
269         fprintf(stderr, "Analyzed %d frames, last time %.3f\n",
270                 nframes, common.frame().time);
271     }
272     else
273     {
274         fprintf(stderr, "Analyzed topology coordinates\n");
275     }
276
277     // Restore the maximal groups for dynamic selections.
278     selections.evaluateFinal(nframes);
279
280     module->finishAnalysis(nframes);
281     module->writeOutput();
282
283     return 0;
284 }
285
286
287 void
288 TrajectoryAnalysisCommandLineRunner::writeHelp(const HelpWriterContext &context)
289 {
290     // TODO: This method duplicates some code from run() and Impl::printHelp().
291     // See how to best refactor it to share the common code.
292     SelectionCollection             selections;
293     TrajectoryAnalysisSettings      settings;
294     TrajectoryAnalysisRunnerCommon  common(&settings);
295
296     Options options(NULL, NULL);
297     Options moduleOptions(impl_->module_->name(), impl_->module_->description());
298     Options commonOptions("common", "Common analysis control");
299     Options selectionOptions("selection", "Common selection control");
300
301     impl_->module_->initOptions(&moduleOptions, &settings);
302     common.initOptions(&commonOptions);
303     selections.initOptions(&selectionOptions);
304
305     options.addSubSection(&commonOptions);
306     options.addSubSection(&selectionOptions);
307     options.addSubSection(&moduleOptions);
308
309     SelectionOptionManager seloptManager(&selections);
310     setManagerForSelectionOptions(&options, &seloptManager);
311
312     CommandLineHelpWriter(options)
313         .setShowDescriptions(true)
314         .setTimeUnitString(settings.timeUnitManager().timeUnitAsString())
315         .writeHelp(context);
316 }
317
318 } // namespace gmx