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