Fix copyright notices for new C++ code.
[alexxy/gromacs.git] / src / gromacs / analysisdata / tests / histogram.cpp
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012, 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 /*! \internal \file
36  * \brief
37  * Tests for functionality of analysis data histogram modules.
38  *
39  * These tests check that classes in histogram.h compute histograms correctly
40  * with simple input data.  Also different ways of initializing the histograms
41  * are tested.
42  * Checking is done using gmx::test::AnalysisDataTestFixture and reference
43  * data.  Also the input data is written to the reference data to catch
44  * out-of-date reference.
45  *
46  * \author Teemu Murtola <teemu.murtola@gmail.com>
47  * \ingroup module_analysisdata
48  */
49 #include <gtest/gtest.h>
50
51 #include "gromacs/analysisdata/analysisdata.h"
52 #include "gromacs/analysisdata/modules/histogram.h"
53
54 #include "testutils/datatest.h"
55
56 namespace
57 {
58
59 /********************************************************************
60  * Tests for gmx::AnalysisHistogramSettings.
61  *
62  * These tests check that gmx::AnalysisHistogramSettings objects can be
63  * initialized from various types of values, and that the bin positions are
64  * computed correctly based on the input values.
65  */
66
67 TEST(AnalysisHistogramSettingsTest, InitializesFromBins)
68 {
69     gmx::AnalysisHistogramSettings settings(
70             gmx::histogramFromBins(1.0, 5, 0.5));
71     EXPECT_FLOAT_EQ(1.0, settings.firstEdge());
72     EXPECT_EQ(5, settings.binCount());
73     EXPECT_FLOAT_EQ(0.5, settings.binWidth());
74     EXPECT_FLOAT_EQ(3.5, settings.lastEdge());
75 }
76
77
78 TEST(AnalysisHistogramSettingsTest, InitializesFromBinsWithIntegerBins)
79 {
80     gmx::AnalysisHistogramSettings settings(
81             gmx::histogramFromBins(1.0, 5, 0.5).integerBins());
82     EXPECT_FLOAT_EQ(0.75, settings.firstEdge());
83     EXPECT_EQ(5, settings.binCount());
84     EXPECT_FLOAT_EQ(0.5, settings.binWidth());
85     EXPECT_FLOAT_EQ(3.25, settings.lastEdge());
86 }
87
88
89 TEST(AnalysisHistogramSettingsTest, InitializesFromRangeWithBinCount)
90 {
91     gmx::AnalysisHistogramSettings settings(
92             gmx::histogramFromRange(1.0, 4.0).binCount(6));
93     EXPECT_FLOAT_EQ(1.0, settings.firstEdge());
94     EXPECT_FLOAT_EQ(4.0, settings.lastEdge());
95     EXPECT_EQ(6, settings.binCount());
96     EXPECT_FLOAT_EQ(0.5, settings.binWidth());
97 }
98
99
100 TEST(AnalysisHistogramSettingsTest, InitializesFromRangeWithBinWidth)
101 {
102     gmx::AnalysisHistogramSettings settings(
103             gmx::histogramFromRange(1.0, 4.0).binWidth(0.5));
104     EXPECT_FLOAT_EQ(1.0, settings.firstEdge());
105     EXPECT_FLOAT_EQ(4.0, settings.lastEdge());
106     EXPECT_FLOAT_EQ(0.5, settings.binWidth());
107     EXPECT_EQ(6, settings.binCount());
108 }
109
110
111 TEST(AnalysisHistogramSettingsTest, InitializesFromRangeWithBinCountAndIntegerBins)
112 {
113     gmx::AnalysisHistogramSettings settings(
114             gmx::histogramFromRange(1.0, 4.0).binCount(7).integerBins());
115     EXPECT_FLOAT_EQ(0.75, settings.firstEdge());
116     EXPECT_FLOAT_EQ(4.25, settings.lastEdge());
117     EXPECT_EQ(7, settings.binCount());
118     EXPECT_FLOAT_EQ(0.5, settings.binWidth());
119 }
120
121
122 TEST(AnalysisHistogramSettingsTest, InitializesFromRangeWithBinWidthAndIntegerBins)
123 {
124     gmx::AnalysisHistogramSettings settings(
125             gmx::histogramFromRange(1.0, 4.0).binWidth(0.5).integerBins());
126     EXPECT_FLOAT_EQ(0.75, settings.firstEdge());
127     EXPECT_FLOAT_EQ(4.25, settings.lastEdge());
128     EXPECT_FLOAT_EQ(0.5, settings.binWidth());
129     EXPECT_EQ(7, settings.binCount());
130 }
131
132
133 TEST(AnalysisHistogramSettingsTest, InitializesFromRangeWithRoundedRange)
134 {
135     gmx::AnalysisHistogramSettings settings(
136             gmx::histogramFromRange(1.2, 3.8).binWidth(0.5).roundRange());
137     EXPECT_FLOAT_EQ(1.0, settings.firstEdge());
138     EXPECT_FLOAT_EQ(4.0, settings.lastEdge());
139     EXPECT_FLOAT_EQ(0.5, settings.binWidth());
140     EXPECT_EQ(6, settings.binCount());
141 }
142
143
144 /********************************************************************
145  * Tests for gmx::AnalysisDataSimpleHistogramModule.
146  */
147
148 //! Test fixture for gmx::AnalysisDataSimpleHistogramModule.
149 typedef gmx::test::AnalysisDataTestFixture SimpleHistogramModuleTest;
150
151 using gmx::test::END_OF_FRAME;
152 using gmx::test::MPSTOP;
153 //! Input data for gmx::AnalysisDataSimpleHistogramModule tests.
154 const real simpleinputdata[] = {
155     1.0,  0.7, MPSTOP, 1.1, MPSTOP, 2.3, MPSTOP, 2.9, END_OF_FRAME,
156     2.0,  1.3, MPSTOP, 2.2, END_OF_FRAME,
157     3.0,  3.3, MPSTOP, 1.2, MPSTOP, 1.3, END_OF_FRAME
158 };
159
160 TEST_F(SimpleHistogramModuleTest, ComputesCorrectly)
161 {
162     gmx::test::AnalysisDataTestInput input(simpleinputdata);
163     gmx::AnalysisData                data;
164     data.setColumnCount(input.columnCount());
165     data.setMultipoint(true);
166     gmx::AnalysisDataSimpleHistogramModulePointer module(
167             new gmx::AnalysisDataSimpleHistogramModule(
168                     gmx::histogramFromRange(1.0, 3.0).binCount(4)));
169     data.addModule(module);
170
171     ASSERT_NO_THROW(addStaticCheckerModule(input, &data));
172     ASSERT_NO_THROW(addReferenceCheckerModule("InputData", &data));
173     ASSERT_NO_THROW(addReferenceCheckerModule("Histogram", module.get()));
174     ASSERT_NO_THROW(addReferenceCheckerModule("HistogramAverage",
175                                               &module->averager()));
176     ASSERT_NO_THROW(presentAllData(input, &data));
177     ASSERT_NO_THROW(module->averager().done());
178 }
179
180
181 TEST_F(SimpleHistogramModuleTest, ComputesCorrectlyWithAll)
182 {
183     gmx::test::AnalysisDataTestInput input(simpleinputdata);
184     gmx::AnalysisData                data;
185     data.setColumnCount(input.columnCount());
186     data.setMultipoint(true);
187     gmx::AnalysisDataSimpleHistogramModulePointer module(
188             new gmx::AnalysisDataSimpleHistogramModule(
189                     gmx::histogramFromRange(1.0, 3.0).binCount(4).includeAll()));
190     data.addModule(module);
191
192     ASSERT_NO_THROW(addStaticCheckerModule(input, &data));
193     ASSERT_NO_THROW(addReferenceCheckerModule("InputData", &data));
194     ASSERT_NO_THROW(addReferenceCheckerModule("Histogram", module.get()));
195     ASSERT_NO_THROW(addReferenceCheckerModule("HistogramAverage",
196                                               &module->averager()));
197     ASSERT_NO_THROW(presentAllData(input, &data));
198     ASSERT_NO_THROW(module->averager().done());
199 }
200
201
202 /********************************************************************
203  * Tests for gmx::AnalysisDataWeightedHistogramModule.
204  */
205
206 //! Test fixture for gmx::AnalysisDataWeightedHistogramModule.
207 typedef gmx::test::AnalysisDataTestFixture WeightedHistogramModuleTest;
208
209 //! Input data for both weighted histogram and bin average module tests.
210 const real weightedinputdata[] = {
211     1.0,  0.7, 0.5, MPSTOP, 1.1, 1.0, MPSTOP, 2.3, 1.0, MPSTOP, 2.9, 2.0, END_OF_FRAME,
212     2.0,  1.3, 1.0, MPSTOP, 2.2, 3.0, END_OF_FRAME,
213     3.0,  3.3, 0.5, MPSTOP, 1.2, 2.0, MPSTOP, 1.3, 1.0, END_OF_FRAME
214 };
215
216 TEST_F(WeightedHistogramModuleTest, ComputesCorrectly)
217 {
218     gmx::test::AnalysisDataTestInput input(weightedinputdata);
219     gmx::AnalysisData                data;
220     data.setColumnCount(input.columnCount());
221     data.setMultipoint(true);
222     gmx::AnalysisDataWeightedHistogramModulePointer module(
223             new gmx::AnalysisDataWeightedHistogramModule(
224                     gmx::histogramFromRange(1.0, 3.0).binCount(4)));
225     data.addModule(module);
226
227     ASSERT_NO_THROW(addStaticCheckerModule(input, &data));
228     ASSERT_NO_THROW(addReferenceCheckerModule("InputData", &data));
229     ASSERT_NO_THROW(addReferenceCheckerModule("Histogram", module.get()));
230     ASSERT_NO_THROW(addReferenceCheckerModule("HistogramAverage",
231                                               &module->averager()));
232     ASSERT_NO_THROW(presentAllData(input, &data));
233     ASSERT_NO_THROW(module->averager().done());
234 }
235
236
237 TEST_F(WeightedHistogramModuleTest, ComputesCorrectlyWithAll)
238 {
239     gmx::test::AnalysisDataTestInput input(weightedinputdata);
240     gmx::AnalysisData                data;
241     data.setColumnCount(input.columnCount());
242     data.setMultipoint(true);
243     gmx::AnalysisDataWeightedHistogramModulePointer module(
244             new gmx::AnalysisDataWeightedHistogramModule(
245                     gmx::histogramFromRange(1.0, 3.0).binCount(4).includeAll()));
246     data.addModule(module);
247
248     ASSERT_NO_THROW(addStaticCheckerModule(input, &data));
249     ASSERT_NO_THROW(addReferenceCheckerModule("InputData", &data));
250     ASSERT_NO_THROW(addReferenceCheckerModule("Histogram", module.get()));
251     ASSERT_NO_THROW(addReferenceCheckerModule("HistogramAverage",
252                                               &module->averager()));
253     ASSERT_NO_THROW(presentAllData(input, &data));
254     ASSERT_NO_THROW(module->averager().done());
255 }
256
257
258 /********************************************************************
259  * Tests for gmx::AnalysisDataBinAverageModule.
260  */
261
262 //! Test fixture for gmx::AnalysisDataBinAverageModule.
263 typedef gmx::test::AnalysisDataTestFixture BinAverageModuleTest;
264
265 TEST_F(BinAverageModuleTest, ComputesCorrectly)
266 {
267     gmx::test::AnalysisDataTestInput input(weightedinputdata);
268     gmx::AnalysisData                data;
269     data.setColumnCount(input.columnCount());
270     data.setMultipoint(true);
271     gmx::AnalysisDataBinAverageModulePointer module(
272             new gmx::AnalysisDataBinAverageModule(
273                     gmx::histogramFromRange(1.0, 3.0).binCount(4)));
274     data.addModule(module);
275
276     ASSERT_NO_THROW(addStaticCheckerModule(input, &data));
277     ASSERT_NO_THROW(addReferenceCheckerModule("InputData", &data));
278     ASSERT_NO_THROW(addReferenceCheckerModule("HistogramAverage", module.get()));
279     ASSERT_NO_THROW(presentAllData(input, &data));
280 }
281
282
283 TEST_F(BinAverageModuleTest, ComputesCorrectlyWithAll)
284 {
285     gmx::test::AnalysisDataTestInput input(weightedinputdata);
286     gmx::AnalysisData                data;
287     data.setColumnCount(input.columnCount());
288     data.setMultipoint(true);
289     gmx::AnalysisDataBinAverageModulePointer module(
290             new gmx::AnalysisDataBinAverageModule(
291                     gmx::histogramFromRange(1.0, 3.0).binCount(4).includeAll()));
292     data.addModule(module);
293
294     ASSERT_NO_THROW(addStaticCheckerModule(input, &data));
295     ASSERT_NO_THROW(addReferenceCheckerModule("InputData", &data));
296     ASSERT_NO_THROW(addReferenceCheckerModule("HistogramAverage", module.get()));
297     ASSERT_NO_THROW(presentAllData(input, &data));
298 }
299
300
301 /********************************************************************
302  * Tests for gmx::AbstractAverageHistogram.
303  *
304  * This class derives from gmx::AbstractAnalysisArrayData, and is tested using
305  * corresponding facilities in gmx::test::AnalysisDataTestFixture.
306  */
307
308 //! Test fixture for gmx::AbstractAverageHistogram.
309 typedef gmx::test::AnalysisDataTestFixture AbstractAverageHistogramTest;
310
311 //! Input data for gmx::AbstractAverageHistogram tests.
312 const real averageinputdata[] = {
313     1.0, 2.0, 1.0, END_OF_FRAME,
314     1.5, 1.0, 1.0, END_OF_FRAME,
315     2.0, 3.0, 2.0, END_OF_FRAME,
316     2.5, 4.0, 2.0, END_OF_FRAME,
317     3.0, 2.0, 1.0, END_OF_FRAME,
318     3.5, 0.0, 3.0, END_OF_FRAME,
319     4.0, 1.0, 3.0, END_OF_FRAME
320 };
321
322 /*! \internal \brief
323  * Mock object for testing gmx::AbstractAverageHistogram.
324  *
325  * Exposes necessary methods from gmx::AbstractAverageHistogram to use with
326  * gmx::test::AnalysisDataTestFixture::setupArrayData().
327  */
328 class MockAverageHistogram : public gmx::AbstractAverageHistogram
329 {
330     public:
331         MockAverageHistogram() {}
332         //! Creates a histogram module with defined bin parameters.
333         explicit MockAverageHistogram(const gmx::AnalysisHistogramSettings &settings)
334             : AbstractAverageHistogram(settings)
335         {
336         }
337
338         using AbstractAverageHistogram::init;
339         using AbstractAverageHistogram::setColumnCount;
340         using AbstractAverageHistogram::setRowCount;
341         using AbstractAverageHistogram::allocateValues;
342         using AbstractAverageHistogram::setValue;
343 };
344
345
346 TEST_F(AbstractAverageHistogramTest, ClonesCorrectly)
347 {
348     gmx::test::AnalysisDataTestInput input(averageinputdata);
349     MockAverageHistogram             data(
350             gmx::histogramFromBins(1.0, input.frameCount(), 0.5).integerBins());
351     setupArrayData(input, &data);
352
353     ASSERT_NO_THROW(addStaticCheckerModule(input, &data));
354     gmx::AverageHistogramPointer copy(data.clone());
355     ASSERT_NO_THROW(addStaticCheckerModule(input, copy.get()));
356     ASSERT_NO_THROW(copy->done());
357     ASSERT_NO_THROW(data.done());
358     gmx::AverageHistogramPointer copy2(data.clone());
359     ASSERT_NO_THROW(addStaticCheckerModule(input, copy2.get()));
360     ASSERT_NO_THROW(copy2->done());
361 }
362
363
364 TEST_F(AbstractAverageHistogramTest, ResamplesAtDoubleBinWidth)
365 {
366     gmx::test::AnalysisDataTestInput input(averageinputdata);
367     MockAverageHistogram             data(
368             gmx::histogramFromBins(1.0, input.frameCount(), 0.5).integerBins());
369     setupArrayData(input, &data);
370
371     ASSERT_NO_THROW(addStaticCheckerModule(input, &data));
372     ASSERT_NO_THROW(addReferenceCheckerModule("InputData", &data));
373     gmx::AverageHistogramPointer resampled(data.resampleDoubleBinWidth(false));
374     ASSERT_NO_THROW(addReferenceCheckerModule("ResampledHistogram", resampled.get()));
375     ASSERT_NO_THROW(data.done());
376     ASSERT_NO_THROW(resampled->done());
377 }
378
379
380 TEST_F(AbstractAverageHistogramTest, ResamplesAtDoubleBinWidthWithIntegerBins)
381 {
382     gmx::test::AnalysisDataTestInput input(averageinputdata);
383     MockAverageHistogram             data(
384             gmx::histogramFromBins(1.0, input.frameCount(), 0.5).integerBins());
385     setupArrayData(input, &data);
386
387     ASSERT_NO_THROW(addStaticCheckerModule(input, &data));
388     ASSERT_NO_THROW(addReferenceCheckerModule("InputData", &data));
389     gmx::AverageHistogramPointer resampled(data.resampleDoubleBinWidth(true));
390     ASSERT_NO_THROW(addReferenceCheckerModule("ResampledHistogram", resampled.get()));
391     ASSERT_NO_THROW(data.done());
392     ASSERT_NO_THROW(resampled->done());
393 }
394
395 } // namespace