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