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