Support for multiple analysis data sets in modules.
[alexxy/gromacs.git] / src / gromacs / analysisdata / modules / plot.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
5  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6  * others, as listed in the AUTHORS file in the top-level source
7  * directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \file
36  * \brief
37  * Declares gmx::AnalysisDataPlotModule for plotting data (into a file).
38  *
39  * \inpublicapi
40  * \ingroup module_analysisdata
41  * \author Teemu Murtola <teemu.murtola@gmail.com>
42  */
43 #ifndef GMX_ANALYSISDATA_MODULES_PLOT_H
44 #define GMX_ANALYSISDATA_MODULES_PLOT_H
45
46 #include <string>
47
48 #include <boost/shared_ptr.hpp>
49
50 #include "../datamodule.h"
51 #include "../../options/timeunitmanager.h"
52 #include "../../utility/common.h"
53
54 namespace gmx
55 {
56
57 class Options;
58 class SelectionCollection;
59
60 /*! \brief
61  * Common settings for data plots.
62  *
63  * \inpublicapi
64  * \ingroup module_analysisdata
65  */
66 class AnalysisDataPlotSettings
67 {
68     public:
69         //! Constructs default analysis plot settings.
70         AnalysisDataPlotSettings();
71
72         //! Returns the selection collection set with setSelectionCollection().
73         const SelectionCollection *selectionCollection() const
74         {
75             return selections_;
76         }
77         //! Returns the time unit set with setTimeUnit().
78         TimeUnit timeUnit() const { return timeUnit_; }
79         /*! \brief
80          * Returns the plot format.
81          *
82          * \todo Use a proper enum.
83          */
84         int plotFormat() const { return plotFormat_; }
85
86         /*! \brief
87          * Set selection collection to print as comments into the output.
88          *
89          * Formatted selection text from all selections in \p selections is
90          * printed as comments in the output file.
91          * If this method is not called, no selection information is written
92          * to the output.
93          */
94         void setSelectionCollection(const SelectionCollection *selections);
95         /*! \brief
96          * Sets the time unit for the plot.
97          *
98          * The value is used only if AbstractPlotModule::setXAxisIsTime() is
99          * called, in which case it is used to print the appropriate axis label
100          * and to scale the values.
101          * If not called, the default time unit is ps.
102          */
103         void setTimeUnit(TimeUnit timeUnit) { timeUnit_ = timeUnit; }
104
105
106         /*! \brief
107          * Adds common options for setting plot options.
108          *
109          * \param[in,out] options Options object to which options are added.
110          */
111         void addOptions(Options *options);
112
113     private:
114         const SelectionCollection *selections_;
115         TimeUnit                   timeUnit_;
116         int                        plotFormat_;
117 };
118
119 /*! \brief
120  * Abstract data module for writing data into a file.
121  *
122  * Implements features common to all plotting modules.  Subclasses implement
123  * features specific to certain applications (AnalysisDataPlotModule implements
124  * straightforward plotting).
125  *
126  * By default, the data is written into an xvgr file, according to the
127  * options read from the AnalysisDataPlotSettings object given to the
128  * constructor.
129  * For non-xvgr data, it's possible to skip all headers by calling
130  * setPlainOutput().
131  *
132  * A single output line corresponds to a single frame.  In most cases with
133  * multipoint data, setPlainOutput() should be called since the output does not
134  * make sense as an xvgr file, but this is not enforced.
135  *
136  * Multipoint data and multiple data sets are both supported, in which case all
137  * the points are written to the output, in the order in which they are added
138  * to the data.
139  *
140  * \ingroup module_analysisdata
141  */
142 class AbstractPlotModule : public AnalysisDataModuleInterface
143 {
144     public:
145         virtual ~AbstractPlotModule();
146
147         /*! \brief
148          * Set common settings for the plotting.
149          */
150         void setSettings(const AnalysisDataPlotSettings &settings);
151         /*! \brief
152          * Set the output file name.
153          *
154          * If no file name is set (or if \p filename is empty), no output occurs.
155          */
156         void setFileName(const std::string &filename);
157         /*! \brief
158          * Set plain output.
159          *
160          * If \p bPlain is true, no xvgr headers are written to the file.
161          * In this case, only setOmitX(), setXFormat(), and setYFormat()
162          * methods have any effect on the output.
163          */
164         void setPlainOutput(bool bPlain);
165         /*! \brief
166          * Omit the X coordinates from the output.
167          *
168          * This method only makes sense when combined with setPlainOutput().
169          */
170         void setOmitX(bool bOmitX);
171         /*! \brief
172          * Set plot title.
173          */
174         void setTitle(const char *title);
175         /*! \brief
176          * Set plot subtitle.
177          */
178         void setSubtitle(const char *subtitle);
179         /*! \brief
180          * Set X axis label.
181          */
182         void setXLabel(const char *label);
183         /*! \brief
184          * Treat X axis as time.
185          *
186          * Sets the label for the axis accordingly and also scales output to
187          * take into account the correct time unit.
188          */
189         void setXAxisIsTime();
190         /*! \brief
191          * Set Y axis label.
192          */
193         void setYLabel(const char *label);
194         /*! \brief
195          * Add legend from an array of strings.
196          *
197          * Multiple calls to setLegend() and/or appendLegend() are added
198          * together.
199          */
200         void setLegend(int nsets, const char * const *setname);
201         /*! \brief
202          * Add a legend string for the next data set.
203          *
204          * Multiple calls to setLegend() and/or appendLegend() are added
205          * together.
206          */
207         void appendLegend(const char *setname);
208         /*! \brief
209          * Set field width and precision for X value output.
210          */
211         void setXFormat(int width, int precision, char format = 'f');
212         /*! \brief
213          * Set field width and precision for Y value output.
214          */
215         void setYFormat(int width, int precision, char format = 'f');
216
217         virtual int flags() const;
218
219         virtual void dataStarted(AbstractAnalysisData *data);
220         virtual void frameStarted(const AnalysisDataFrameHeader &header);
221         virtual void pointsAdded(const AnalysisDataPointSetRef &points) = 0;
222         virtual void frameFinished(const AnalysisDataFrameHeader &header);
223         virtual void dataFinished();
224
225     protected:
226         /*! \cond libapi */
227         AbstractPlotModule();
228         //! Creates AbstractPlotModule and assign common settings.
229         explicit AbstractPlotModule(const AnalysisDataPlotSettings &settings);
230
231         //! Whether an output file has been opened.
232         bool isFileOpen() const;
233         /*! \brief
234          * Appends a single value to the current output line.
235          *
236          * \param[in] value  Value to append.
237          *
238          * Should be used from pointsAdded() implementations in derived classes
239          * to write out individual y values to the output.
240          *
241          * Must not be called if isFileOpen() returns false.
242          */
243         void writeValue(real value) const;
244         //! \endcond
245
246     private:
247         class Impl;
248
249         PrivateImplPointer<Impl> impl_;
250 };
251
252
253 /*! \brief
254  * Plotting module for straightforward plotting of data.
255  *
256  * See AbstractPlotModule for common plotting options.
257  *
258  * \inpublicapi
259  * \ingroup module_analysisdata
260  */
261 class AnalysisDataPlotModule : public AbstractPlotModule
262 {
263     public:
264         AnalysisDataPlotModule();
265         //! Creates AnalysisDataPlotModule and assign common settings.
266         explicit AnalysisDataPlotModule(const AnalysisDataPlotSettings &settings);
267
268         virtual void pointsAdded(const AnalysisDataPointSetRef &points);
269
270         // Copy and assign disallowed by base.
271 };
272
273
274 /*! \brief
275  * Plotting module specifically for data consisting of vectors.
276  *
277  * See AbstractPlotModule for common plotting options.
278  *
279  * \inpublicapi
280  * \ingroup module_analysisdata
281  */
282 class AnalysisDataVectorPlotModule : public AbstractPlotModule
283 {
284     public:
285         AnalysisDataVectorPlotModule();
286         //! Creates AnalysisDataVectorPlotModule and assign common settings.
287         explicit AnalysisDataVectorPlotModule(const AnalysisDataPlotSettings &settings);
288
289         /*! \brief
290          * Set whether to write X component.
291          */
292         void setWriteX(bool bWrite);
293         /*! \brief
294          * Set whether to write Y component.
295          */
296         void setWriteY(bool bWrite);
297         /*! \brief
298          * Set whether to write Z component.
299          */
300         void setWriteZ(bool bWrite);
301         /*! \brief
302          * Set whether to write norm of the vector.
303          */
304         void setWriteNorm(bool bWrite);
305         /*! \brief
306          * Set mask for what to write.
307          */
308         void setWriteMask(bool bWrite[4]);
309
310         virtual void pointsAdded(const AnalysisDataPointSetRef &points);
311
312     private:
313         bool                    bWrite_[4];
314
315         // Copy and assign disallowed by base.
316 };
317
318 //! Smart pointer to manage an AnalysisDataPlotModule object.
319 typedef boost::shared_ptr<AnalysisDataPlotModule>
320     AnalysisDataPlotModulePointer;
321 //! Smart pointer to manage an AnalysisDataVectorPlotModule object.
322 typedef boost::shared_ptr<AnalysisDataVectorPlotModule>
323     AnalysisDataVectorPlotModulePointer;
324
325 } // namespace gmx
326
327 #endif