Use smart pointer to pass ownership across functions.
[alexxy/gromacs.git] / src / gromacs / analysisdata / modules / histogram.h
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 /*! \file
32  * \brief
33  * Declares analysis data modules for calculating histograms.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \inpublicapi
37  * \ingroup module_analysisdata
38  */
39 #ifndef GMX_ANALYSISDATA_MODULES_HISTOGRAM_H
40 #define GMX_ANALYSISDATA_MODULES_HISTOGRAM_H
41
42 #include "../abstractdata.h"
43 #include "../arraydata.h"
44 #include "../datamodule.h"
45 #include "../../utility/uniqueptr.h"
46
47 namespace gmx
48 {
49
50 class AnalysisHistogramSettings;
51
52 /*! \brief
53  * Provides "named parameter" idiom for constructing histograms.
54  *
55  * \see histogramFromBins()
56  * \see histogramFromRange()
57  *
58  * \inpublicapi
59  * \ingroup module_analysisdata
60  */
61 class AnalysisHistogramSettingsInitializer
62 {
63     public:
64         /*! \brief
65          * Creates an empty initializer.
66          *
67          * Should not be called directly, but histogramFromRange() or
68          * histogramFromBins() should be used instead.
69          */
70         AnalysisHistogramSettingsInitializer();
71
72         /*! \brief
73          * Sets the first bin location.
74          *
75          * Typically should not be called directly, but through
76          * histogramFromBins().
77          */
78         AnalysisHistogramSettingsInitializer &start(real min)
79         { min_ = min; return *this; }
80         /*! \brief
81          * Sets the number of bins in the histogram.
82          *
83          * If only the first bin location is specified, this value is required
84          * (and automatically provided if histogramFromBins() is used).
85          * If both the first and last bins are specified, either this value or
86          * binWidth() is required.
87          */
88         AnalysisHistogramSettingsInitializer &binCount(int binCount)
89         { binCount_ = binCount; return *this; }
90         /*! \brief
91          * Sets the first and last bin locations.
92          *
93          * Typically should not be called directly, but through
94          * histogramFromRange().
95          */
96         AnalysisHistogramSettingsInitializer &range(real min, real max)
97         { min_ = min; max_ = max; return *this; }
98         /*! \brief
99          * Sets the bin width of the histogram.
100          *
101          * If only the first bin location is specified, this value is required
102          * (and automatically provided if histogramFromBins() is used).
103          * If both the first and last bins are specified, either this value or
104          * binCount() is required.
105          * If a bin width is provided with both first and last bin locations,
106          * and the given bin width does not divide the range exactly, the last
107          * bin location is adjusted to match.
108          */
109         AnalysisHistogramSettingsInitializer &binWidth(real binWidth)
110         { binWidth_ = binWidth; return *this; }
111         /*! \brief
112          * Indicate that first and last bin locations to specify bin centers.
113          *
114          * If set, the first and last bin locations are interpreted as bin
115          * centers.
116          * If not set (the default), the first and last bin locations are
117          * interpreted as the edges of the whole histogram.
118          *
119          * Cannot be specified together with roundRange().
120          */
121         AnalysisHistogramSettingsInitializer &integerBins(bool enabled = true)
122         { bIntegerBins_ = enabled; return *this; }
123         /*! \brief
124          * Round first and last bin locations.
125          *
126          * If set, the resulting histogram will cover the range specified, but
127          * the actual bin locations will be rounded such that the edges fall
128          * on multiples of the bin width.
129          * Only implemented when both first and last bin location and bin width
130          * are defined.
131          * Cannot be specified together with integerBins() or with binCount().
132          */
133         AnalysisHistogramSettingsInitializer &roundRange(bool enabled = true)
134         { bRoundRange_ = enabled; return *this; }
135         /*! \brief
136          * Sets the histogram to match all values.
137          *
138          * If set, the histogram behaves as if the bins at the ends extended to
139          * +-infinity.
140          */
141         AnalysisHistogramSettingsInitializer &includeAll(bool enabled = true)
142         { bIncludeAll_ = enabled; return *this; }
143
144     private:
145         real                    min_;
146         real                    max_;
147         real                    binWidth_;
148         int                     binCount_;
149         bool                    bIntegerBins_;
150         bool                    bRoundRange_;
151         bool                    bIncludeAll_;
152
153         friend class AnalysisHistogramSettings;
154 };
155
156 /*! \brief
157  * Initializes a histogram using a range and a bin width.
158  *
159  * \inpublicapi
160  */
161 inline AnalysisHistogramSettingsInitializer
162 histogramFromRange(real min, real max)
163 {
164     return AnalysisHistogramSettingsInitializer().range(min, max);
165 }
166
167 /*! \brief
168  * Initializes a histogram using bin width and the number of bins.
169  *
170  * \inpublicapi
171  */
172 inline AnalysisHistogramSettingsInitializer
173 histogramFromBins(real start, int nbins, real binwidth)
174 {
175     return AnalysisHistogramSettingsInitializer()
176         .start(start).binCount(nbins).binWidth(binwidth);
177 }
178
179
180 /*! \brief
181  * Contains parameters that specify histogram bin locations.
182  *
183  * \inpublicapi
184  * \ingroup module_analysisdata
185  */
186 class AnalysisHistogramSettings
187 {
188     public:
189         //! Initializes undefined parameters.
190         AnalysisHistogramSettings();
191         /*! \brief
192          * Initializes parameters based on a named parameter object.
193          *
194          * This constructor is not explicit to allow initialization of
195          * histograms directly from AnalysisHistogramSettingsInitializer:
196          * \code
197          gmx::AnalysisDataSimpleHistogramModule *hist =
198             new gmx::AnalysisDataSimpleHistogramModule(
199                 histogramFromRange(0.0, 5.0).binWidth(0.5));
200          * \endcode
201          */
202         AnalysisHistogramSettings(const AnalysisHistogramSettingsInitializer &settings);
203
204         //! Returns the left edge of the first bin.
205         real firstEdge() const { return firstEdge_; }
206         //! Returns the right edge of the first bin.
207         real lastEdge() const { return lastEdge_; }
208         //! Returns the number of bins in the histogram.
209         int binCount() const { return binCount_; }
210         //! Returns the width of a bin in the histogram.
211         real binWidth() const { return binWidth_; }
212         //! Whether values beyond the edges are mapped to the edge bins.
213         bool includeAll() const { return bAll_; }
214         //! Returns a zero-based bin index for a value, or -1 if not in range.
215         int findBin(real y) const;
216
217     private:
218         real                    firstEdge_;
219         real                    lastEdge_;
220         real                    binWidth_;
221         real                    inverseBinWidth_;
222         int                     binCount_;
223         bool                    bAll_;
224 };
225
226
227 namespace internal
228 {
229
230 class BasicHistogramImpl;
231
232 } // namespace internal
233
234 class AbstractAverageHistogram;
235
236 //! Smart pointer to manage an AbstractAverageHistogram object.
237 typedef gmx_unique_ptr<AbstractAverageHistogram>::type
238         AverageHistogramPointer;
239
240 /*! \brief
241  * Base class for representing histograms averaged over frames.
242  *
243  * The averaging module for a per-frame histogram is always created by the
244  * AbstractHistogramModule class, and can be accessed using
245  * AbstractHistogramModule::averager().
246  * The user can alter some properties of the average histogram directly, but
247  * the main use of the object is to postprocess the histogram once the
248  * calculation is finished.
249  *
250  * \inpublicapi
251  * \ingroup module_analysisdata
252  */
253 class AbstractAverageHistogram : public AbstractAnalysisArrayData
254 {
255     public:
256         virtual ~AbstractAverageHistogram();
257
258         //! Returns bin properties for the histogram.
259         const AnalysisHistogramSettings &settings() const { return settings_; }
260
261         /*! \brief
262          * Creates a copy of the histogram with double the bin width.
263          *
264          * The caller is responsible of deleting the returned object.
265          */
266         AverageHistogramPointer resampleDoubleBinWidth(bool bIntegerBins) const;
267         /*! \brief
268          * Creates a deep copy of the histogram.
269          *
270          * The returned histogram is not necessarily of the same dynamic type
271          * as the original object, but contains the same data from the point of
272          * view of the AbstractAverageHistogram interface.
273          *
274          * The caller is responsible of deleting the returned object.
275          */
276         AverageHistogramPointer clone() const;
277         //! Normalizes the histogram such that the integral over it is one.
278         void normalizeProbability();
279         //! Scales the value of each bin by an uniform scaling factor.
280         void scale(real norm);
281         //! Scales the value of each bin by a different scaling factor.
282         void scaleVector(real norm[]);
283         /*! \brief
284          * Notifies attached modules of the histogram data.
285          *
286          * After this function has been called, it is no longer possible to
287          * alter the histogram.
288          */
289         void done() { AbstractAnalysisArrayData::valuesReady(); }
290
291     protected:
292         /*! \brief
293          * Creates a histogram module with undefined bins.
294          *
295          * Bin parameters must be defined with init() before data input is
296          * started.
297          */
298         AbstractAverageHistogram();
299         //! Creates a histogram module with defined bin parameters.
300         explicit AbstractAverageHistogram(const AnalysisHistogramSettings &settings);
301
302         /*! \brief
303          * (Re)initializes the histogram from settings.
304          */
305         void init(const AnalysisHistogramSettings &settings);
306
307     private:
308         AnalysisHistogramSettings  settings_;
309
310         // Copy and assign disallowed by base.
311 };
312
313
314 /*! \brief
315  * Data module for per-frame histograms.
316  *
317  * Output data contains the same number of frames as the input data.
318  * Each frame contains the histogram for the points in that frame.
319  * All input columns are averaged into the same histogram.
320  * The number of columns equals the number of bins in the histogram.
321  *
322  * \inpublicapi
323  * \ingroup module_analysisdata
324  */
325 class AnalysisDataSimpleHistogramModule : public AbstractAnalysisData,
326                                           public AnalysisDataModuleInterface
327 {
328     public:
329         /*! \brief
330          * Creates a histogram module with undefined bins.
331          *
332          * Bin parameters must be defined with init() before data input is
333          * started.
334          */
335         AnalysisDataSimpleHistogramModule();
336         //! Creates a histogram module with defined bin parameters.
337         explicit AnalysisDataSimpleHistogramModule(const AnalysisHistogramSettings &settings);
338         virtual ~AnalysisDataSimpleHistogramModule();
339
340         /*! \brief
341          * (Re)initializes the histogram from settings.
342          */
343         void init(const AnalysisHistogramSettings &settings);
344
345         /*! \brief
346          * Returns the average histogram over all frames.
347          *
348          * Can be called already before the histogram is calculated to
349          * customize the way the average histogram is calculated.
350          *
351          * \see AbstractAverageHistogram
352          */
353         AbstractAverageHistogram &averager();
354
355         //! Returns bin properties for the histogram.
356         const AnalysisHistogramSettings &settings() const;
357
358         virtual int flags() const;
359
360         virtual void dataStarted(AbstractAnalysisData *data);
361         virtual void frameStarted(const AnalysisDataFrameHeader &header);
362         virtual void pointsAdded(const AnalysisDataPointSetRef &points);
363         virtual void frameFinished(const AnalysisDataFrameHeader &header);
364         virtual void dataFinished();
365
366     private:
367         virtual AnalysisDataFrameRef tryGetDataFrameInternal(int index) const;
368         virtual bool requestStorageInternal(int nframes);
369
370         PrivateImplPointer<internal::BasicHistogramImpl> impl_;
371
372         // Copy and assign disallowed by base.
373 };
374
375
376 /*! \brief
377  * Data module for per-frame weighted histograms.
378  *
379  * Output data contains the same number of frames as the input data.
380  * Each frame contains the histogram for the points in that frame, interpreted
381  * such that the first column passed to pointsAdded() determines the bin and
382  * the rest give weights to be added to that bin (input data should have at
383  * least two colums, and at least two columns should be added at the same time).
384  * All input columns are averaged into the same histogram.
385  * The number of columns equals the number of bins in the histogram.
386  *
387  * \inpublicapi
388  * \ingroup module_analysisdata
389  */
390 class AnalysisDataWeightedHistogramModule : public AbstractAnalysisData,
391                                             public AnalysisDataModuleInterface
392 {
393     public:
394         //! \copydoc AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule()
395         AnalysisDataWeightedHistogramModule();
396         //! \copydoc AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule(const AnalysisHistogramSettings &)
397         explicit AnalysisDataWeightedHistogramModule(const AnalysisHistogramSettings &settings);
398         virtual ~AnalysisDataWeightedHistogramModule();
399
400         //! \copydoc AnalysisDataSimpleHistogramModule::init()
401         void init(const AnalysisHistogramSettings &settings);
402
403         //! \copydoc AnalysisDataSimpleHistogramModule::averager()
404         AbstractAverageHistogram &averager();
405
406         //! \copydoc AnalysisDataSimpleHistogramModule::settings()
407         const AnalysisHistogramSettings &settings() const;
408
409         virtual int flags() const;
410
411         virtual void dataStarted(AbstractAnalysisData *data);
412         virtual void frameStarted(const AnalysisDataFrameHeader &header);
413         virtual void pointsAdded(const AnalysisDataPointSetRef &points);
414         virtual void frameFinished(const AnalysisDataFrameHeader &header);
415         virtual void dataFinished();
416
417     private:
418         virtual AnalysisDataFrameRef tryGetDataFrameInternal(int index) const;
419         virtual bool requestStorageInternal(int nframes);
420
421         PrivateImplPointer<internal::BasicHistogramImpl> impl_;
422
423         // Copy and assign disallowed by base.
424 };
425
426
427 /*! \brief
428  * Data module for bin averages.
429  *
430  * Output data contains one row for each bin; see AbstractAverageHistogram.
431  * Output data contains three columns: the first is the average over all frames
432  * for that bin, the second is the standard deviation of the values, and the
433  * third is the number of samples in that bin.
434  * The input data is interpreted such that the first column passed to
435  * pointsAdded() determines the bin and the rest give values to be added to
436  * that bin (input data should have at least two colums, and at least two
437  * columns should be added at the same time).
438  * All input columns are averaged into the same histogram.
439  *
440  * \inpublicapi
441  * \ingroup module_analysisdata
442  */
443 class AnalysisDataBinAverageModule : public AbstractAnalysisArrayData,
444                                      public AnalysisDataModuleInterface
445 {
446     public:
447         //! \copydoc AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule()
448         AnalysisDataBinAverageModule();
449         //! \copydoc AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule(const AnalysisHistogramSettings &)
450         explicit AnalysisDataBinAverageModule(const AnalysisHistogramSettings &settings);
451         virtual ~AnalysisDataBinAverageModule();
452
453         //! \copydoc AnalysisDataSimpleHistogramModule::init()
454         void init(const AnalysisHistogramSettings &settings);
455
456         //! \copydoc AnalysisDataSimpleHistogramModule::settings()
457         const AnalysisHistogramSettings &settings() const { return settings_; }
458
459         virtual int flags() const;
460
461         virtual void dataStarted(AbstractAnalysisData *data);
462         virtual void frameStarted(const AnalysisDataFrameHeader &header);
463         virtual void pointsAdded(const AnalysisDataPointSetRef &points);
464         virtual void frameFinished(const AnalysisDataFrameHeader &header);
465         virtual void dataFinished();
466
467     private:
468         AnalysisHistogramSettings  settings_;
469
470         // Copy and assign disallowed by base.
471 };
472
473 //! Smart pointer to manage an AnalysisDataSimpleHistogramModule object.
474 typedef boost::shared_ptr<AnalysisDataSimpleHistogramModule>
475         AnalysisDataSimpleHistogramModulePointer;
476 //! Smart pointer to manage an AnalysisDataWeightedHistogramModule object.
477 typedef boost::shared_ptr<AnalysisDataWeightedHistogramModule>
478         AnalysisDataWeightedHistogramModulePointer;
479 //! Smart pointer to manage an AnalysisDataBinAverageModule object.
480 typedef boost::shared_ptr<AnalysisDataBinAverageModule>
481         AnalysisDataBinAverageModulePointer;
482
483 } // namespace gmx
484
485 #endif