2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2010,2011,2012,2013,2014,2015,2018, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
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.
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.
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.
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.
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.
37 * Implements classes in histogram.h.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_analysisdata
44 #include "histogram.h"
51 #include "gromacs/analysisdata/dataframe.h"
52 #include "gromacs/analysisdata/datastorage.h"
53 #include "gromacs/analysisdata/framelocaldata.h"
54 #include "gromacs/math/functions.h"
55 #include "gromacs/utility/basedefinitions.h"
56 #include "gromacs/utility/exceptions.h"
57 #include "gromacs/utility/gmxassert.h"
59 #include "frameaverager.h"
64 //! Value used to signify that a real-valued histogram setting is not set.
65 const real UNDEFINED
= std::numeric_limits
<real
>::max();
66 //! Checks whether \p value is defined.
67 bool isDefined(real value
)
69 return value
!= UNDEFINED
;
77 /********************************************************************
78 * AnalysisHistogramSettingsInitializer
81 AnalysisHistogramSettingsInitializer::AnalysisHistogramSettingsInitializer()
82 : min_(UNDEFINED
), max_(UNDEFINED
), binWidth_(UNDEFINED
),
83 binCount_(0), bIntegerBins_(false), bRoundRange_(false),
89 /********************************************************************
90 * AnalysisHistogramSettings
93 AnalysisHistogramSettings::AnalysisHistogramSettings()
94 : firstEdge_(0.0), lastEdge_(0.0), binWidth_(0.0), inverseBinWidth_(0.0),
95 binCount_(0), bAll_(false)
100 AnalysisHistogramSettings::AnalysisHistogramSettings(
101 const AnalysisHistogramSettingsInitializer
&settings
)
103 GMX_RELEASE_ASSERT(isDefined(settings
.min_
),
104 "Histogram start value must be defined");
105 GMX_RELEASE_ASSERT(!isDefined(settings
.max_
) || settings
.max_
> settings
.min_
,
106 "Histogram end value must be larger than start value");
107 GMX_RELEASE_ASSERT(!isDefined(settings
.binWidth_
) || settings
.binWidth_
> 0.0,
108 "Histogram bin width must be positive");
109 GMX_RELEASE_ASSERT(settings
.binCount_
>= 0,
110 "Histogram bin count must be positive");
112 if (!isDefined(settings
.max_
))
114 GMX_RELEASE_ASSERT(isDefined(settings
.binWidth_
) && settings
.binCount_
> 0,
115 "Not all required values provided");
116 GMX_RELEASE_ASSERT(!settings
.bRoundRange_
,
117 "Rounding only supported for min/max ranges");
119 firstEdge_
= settings
.min_
;
120 binCount_
= settings
.binCount_
;
121 binWidth_
= settings
.binWidth_
;
122 if (settings
.bIntegerBins_
)
124 firstEdge_
-= 0.5 * binWidth_
;
126 lastEdge_
= firstEdge_
+ binCount_
* binWidth_
;
130 GMX_RELEASE_ASSERT(!(isDefined(settings
.binWidth_
) && settings
.binCount_
> 0),
131 "Conflicting histogram bin specifications");
132 GMX_RELEASE_ASSERT(isDefined(settings
.binWidth_
) || settings
.binCount_
> 0,
133 "Not all required values provided");
135 if (settings
.bRoundRange_
)
137 GMX_RELEASE_ASSERT(!settings
.bIntegerBins_
,
138 "Rounding and integer bins cannot be combined");
139 GMX_RELEASE_ASSERT(isDefined(settings
.binWidth_
),
140 "Rounding only makes sense with defined binwidth");
141 binWidth_
= settings
.binWidth_
;
142 firstEdge_
= binWidth_
* std::floor(settings
.min_
/ binWidth_
);
143 lastEdge_
= binWidth_
* std::ceil(settings
.max_
/ binWidth_
);
144 binCount_
= gmx::roundToInt((lastEdge_
- firstEdge_
) / binWidth_
);
148 firstEdge_
= settings
.min_
;
149 lastEdge_
= settings
.max_
;
150 if (settings
.binCount_
> 0)
152 binCount_
= settings
.binCount_
;
153 if (settings
.bIntegerBins_
)
155 GMX_RELEASE_ASSERT(settings
.binCount_
> 1,
156 "Bin count must be at least two with integer bins");
157 binWidth_
= (lastEdge_
- firstEdge_
) / (binCount_
- 1);
158 firstEdge_
-= 0.5 * binWidth_
;
159 lastEdge_
+= 0.5 * binWidth_
;
163 binWidth_
= (lastEdge_
- firstEdge_
) / binCount_
;
168 binWidth_
= settings
.binWidth_
;
169 binCount_
= gmx::roundToInt((lastEdge_
- firstEdge_
) / binWidth_
);
170 if (settings
.bIntegerBins_
)
172 firstEdge_
-= 0.5 * binWidth_
;
175 lastEdge_
= firstEdge_
+ binCount_
* binWidth_
;
180 inverseBinWidth_
= 1.0 / binWidth_
;
181 bAll_
= settings
.bIncludeAll_
;
186 AnalysisHistogramSettings::findBin(real y
) const
190 return bAll_
? 0 : -1;
192 int bin
= static_cast<int>((y
- firstEdge_
) * inverseBinWidth_
);
193 if (bin
>= binCount_
)
195 return bAll_
? binCount_
- 1 : -1;
201 /********************************************************************
202 * StaticAverageHistogram
209 * Represents copies of average histograms.
211 * Methods in AbstractAverageHistogram that return new histogram instances
212 * return objects of this class.
213 * Initialization of values is handled in those methods.
215 * \ingroup module_analysisdata
217 class StaticAverageHistogram
: public AbstractAverageHistogram
220 StaticAverageHistogram();
221 //! Creates an average histogram module with defined bin parameters.
222 explicit StaticAverageHistogram(const AnalysisHistogramSettings
&settings
);
224 // Copy and assign disallowed by base.
227 StaticAverageHistogram::StaticAverageHistogram()
232 StaticAverageHistogram::StaticAverageHistogram(
233 const AnalysisHistogramSettings
&settings
)
234 : AbstractAverageHistogram(settings
)
241 /********************************************************************
242 * AbstractAverageHistogram
245 AbstractAverageHistogram::AbstractAverageHistogram()
250 AbstractAverageHistogram::AbstractAverageHistogram(
251 const AnalysisHistogramSettings
&settings
)
252 : settings_(settings
)
254 setRowCount(settings
.binCount());
255 setXAxis(settings
.firstEdge() + 0.5 * settings
.binWidth(),
256 settings
.binWidth());
260 AbstractAverageHistogram::~AbstractAverageHistogram()
266 AbstractAverageHistogram::init(const AnalysisHistogramSettings
&settings
)
268 settings_
= settings
;
269 setRowCount(settings
.binCount());
270 setXAxis(settings
.firstEdge() + 0.5 * settings
.binWidth(),
271 settings
.binWidth());
275 AverageHistogramPointer
276 AbstractAverageHistogram::resampleDoubleBinWidth(bool bIntegerBins
) const
281 nbins
= (rowCount() + 1) / 2;
285 nbins
= rowCount() / 2;
288 AverageHistogramPointer
dest(
289 new StaticAverageHistogram(
290 histogramFromBins(settings().firstEdge(), nbins
, 2*xstep())
291 .integerBins(bIntegerBins
)));
292 dest
->setColumnCount(columnCount());
293 dest
->allocateValues();
296 for (i
= j
= 0; i
< nbins
; ++i
)
298 const bool bFirstHalfBin
= (bIntegerBins
&& i
== 0);
299 for (int c
= 0; c
< columnCount(); ++c
)
305 v1
= value(0, c
).value();
306 e1
= value(0, c
).error();
312 v1
= value(j
, c
).value();
313 e1
= value(j
, c
).error();
314 v2
= value(j
+ 1, c
).value();
315 e2
= value(j
+ 1, c
).error();
317 dest
->value(i
, c
).setValue(v1
+ v2
, std::sqrt(e1
* e1
+ e2
* e2
));
332 AverageHistogramPointer
333 AbstractAverageHistogram::clone() const
335 AverageHistogramPointer
dest(new StaticAverageHistogram());
336 copyContents(this, dest
.get());
337 dest
->settings_
= settings_
;
343 AbstractAverageHistogram::normalizeProbability()
345 for (int c
= 0; c
< columnCount(); ++c
)
348 for (int i
= 0; i
< rowCount(); ++i
)
350 sum
+= value(i
, c
).value();
354 scaleSingle(c
, 1.0 / (sum
* xstep()));
360 AbstractAverageHistogram::makeCumulative()
362 for (int c
= 0; c
< columnCount(); ++c
)
365 for (int i
= 0; i
< rowCount(); ++i
)
367 sum
+= value(i
, c
).value();
368 // Clear the error, as we don't cumulate that.
370 value(i
, c
).setValue(sum
);
373 setXAxis(settings().firstEdge() + settings().binWidth(),
374 settings().binWidth());
379 AbstractAverageHistogram::scaleSingle(int index
, real factor
)
381 for (int i
= 0; i
< rowCount(); ++i
)
383 value(i
, index
).value() *= factor
;
384 value(i
, index
).error() *= factor
;
390 AbstractAverageHistogram::scaleAll(real factor
)
392 for (int i
= 0; i
< columnCount(); ++i
)
394 scaleSingle(i
, factor
);
400 AbstractAverageHistogram::scaleAllByVector(const real factor
[])
402 for (int c
= 0; c
< columnCount(); ++c
)
404 for (int i
= 0; i
< rowCount(); ++i
)
406 value(i
, c
).value() *= factor
[i
];
407 value(i
, c
).error() *= factor
[i
];
413 /********************************************************************
414 * BasicAverageHistogramModule
422 * Implements average histogram module that averages per-frame histograms.
424 * This class is used for accumulating average histograms in per-frame
425 * histogram modules (those that use BasicHistogramImpl as their implementation
427 * There are two columns, first for the average and second for standard
430 * \ingroup module_analysisdata
432 class BasicAverageHistogramModule
: public AbstractAverageHistogram
,
433 public AnalysisDataModuleSerial
436 BasicAverageHistogramModule();
437 //! Creates an average histogram module with defined bin parameters.
438 explicit BasicAverageHistogramModule(const AnalysisHistogramSettings
&settings
);
440 using AbstractAverageHistogram::init
;
442 int flags() const override
;
444 void dataStarted(AbstractAnalysisData
*data
) override
;
445 void frameStarted(const AnalysisDataFrameHeader
&header
) override
;
446 void pointsAdded(const AnalysisDataPointSetRef
&points
) override
;
447 void frameFinished(const AnalysisDataFrameHeader
&header
) override
;
448 void dataFinished() override
;
451 //! Averaging helper objects for each input data set.
452 std::vector
<AnalysisDataFrameAverager
> averagers_
;
454 // Copy and assign disallowed by base.
457 BasicAverageHistogramModule::BasicAverageHistogramModule()
462 BasicAverageHistogramModule::BasicAverageHistogramModule(
463 const AnalysisHistogramSettings
&settings
)
464 : AbstractAverageHistogram(settings
)
470 BasicAverageHistogramModule::flags() const
472 return efAllowMulticolumn
| efAllowMultipleDataSets
;
477 BasicAverageHistogramModule::dataStarted(AbstractAnalysisData
*data
)
479 setColumnCount(data
->dataSetCount());
480 averagers_
.resize(data
->dataSetCount());
481 for (int i
= 0; i
< data
->dataSetCount(); ++i
)
483 GMX_RELEASE_ASSERT(rowCount() == data
->columnCount(i
),
484 "Inconsistent data sizes, something is wrong in the initialization");
485 averagers_
[i
].setColumnCount(data
->columnCount(i
));
491 BasicAverageHistogramModule::frameStarted(const AnalysisDataFrameHeader
& /*header*/)
497 BasicAverageHistogramModule::pointsAdded(const AnalysisDataPointSetRef
&points
)
499 averagers_
[points
.dataSetIndex()].addPoints(points
);
504 BasicAverageHistogramModule::frameFinished(const AnalysisDataFrameHeader
& /*header*/)
510 BasicAverageHistogramModule::dataFinished()
513 for (int i
= 0; i
< columnCount(); ++i
)
515 averagers_
[i
].finish();
516 for (int j
= 0; j
< rowCount(); ++j
)
518 value(j
, i
).setValue(averagers_
[i
].average(j
),
519 std::sqrt(averagers_
[i
].variance(j
)));
525 /********************************************************************
531 * Base class for private implementation classes for histogram modules.
533 * Actual implementation classes are derived from this and add an accumulation
534 * data member that is specific to the histogram type in question.
535 * This is done like this to keep implementation details out of the header, and
536 * to not unnecessarily duplicate code.
538 * \ingroup module_analysisdata
540 class BasicHistogramImpl
543 //! Smart pointer to manage an BasicAverageHistogramModule object.
544 typedef std::shared_ptr
<BasicAverageHistogramModule
>
545 BasicAverageHistogramModulePointer
;
547 BasicHistogramImpl();
548 //! Creates an histogram impl with defined bin parameters.
549 explicit BasicHistogramImpl(const AnalysisHistogramSettings
&settings
);
550 // Virtual only for simplicity.
551 virtual ~BasicHistogramImpl();
554 * (Re)initializes the histogram from settings.
556 void init(const AnalysisHistogramSettings
&settings
);
558 //! Storage implementation object.
559 AnalysisDataStorage storage_
;
560 //! Settings for the histogram object.
561 AnalysisHistogramSettings settings_
;
563 BasicAverageHistogramModulePointer averager_
;
566 BasicHistogramImpl::BasicHistogramImpl()
567 : averager_(new BasicAverageHistogramModule())
572 BasicHistogramImpl::BasicHistogramImpl(const AnalysisHistogramSettings
&settings
)
573 : settings_(settings
), averager_(new BasicAverageHistogramModule(settings
))
578 BasicHistogramImpl::~BasicHistogramImpl()
583 void BasicHistogramImpl::init(const AnalysisHistogramSettings
&settings
)
585 settings_
= settings
;
586 averager_
->init(settings
);
589 } // namespace internal
592 /********************************************************************
593 * AnalysisDataSimpleHistogramModule
597 * Private implementation class for AnalysisDataSimpleHistogramModule.
599 * \ingroup module_analysisdata
601 class AnalysisDataSimpleHistogramModule::Impl
: public internal::BasicHistogramImpl
604 //! Shorthand for the per-frame accumulation data structure type.
605 typedef AnalysisDataFrameLocalData
<int64_t> FrameLocalData
;
608 //! Creates an histogram impl with defined bin parameters.
609 explicit Impl(const AnalysisHistogramSettings
&settings
)
610 : BasicHistogramImpl(settings
)
614 //! Accumulates the histogram within a frame.
615 FrameLocalData accumulator_
;
618 AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule()
624 AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule(
625 const AnalysisHistogramSettings
&settings
)
626 : impl_(new Impl(settings
))
631 AnalysisDataSimpleHistogramModule::~AnalysisDataSimpleHistogramModule()
636 void AnalysisDataSimpleHistogramModule::init(const AnalysisHistogramSettings
&settings
)
638 impl_
->init(settings
);
642 AbstractAverageHistogram
&
643 AnalysisDataSimpleHistogramModule::averager()
645 return *impl_
->averager_
;
649 const AnalysisHistogramSettings
&
650 AnalysisDataSimpleHistogramModule::settings() const
652 return impl_
->settings_
;
657 AnalysisDataSimpleHistogramModule::frameCount() const
659 return impl_
->storage_
.frameCount();
664 AnalysisDataSimpleHistogramModule::flags() const
666 return efAllowMulticolumn
| efAllowMultipoint
| efAllowMissing
667 | efAllowMultipleDataSets
;
672 AnalysisDataSimpleHistogramModule::parallelDataStarted(
673 AbstractAnalysisData
*data
,
674 const AnalysisDataParallelOptions
&options
)
676 addModule(impl_
->averager_
);
677 const int dataSetCount
= data
->dataSetCount();
678 const int columnCount
= settings().binCount();
679 setDataSetCount(dataSetCount
);
680 impl_
->accumulator_
.setDataSetCount(dataSetCount
);
681 for (int i
= 0; i
< dataSetCount
; ++i
)
683 setColumnCount(i
, columnCount
);
684 impl_
->accumulator_
.setColumnCount(i
, columnCount
);
686 impl_
->accumulator_
.init(options
);
687 impl_
->storage_
.startParallelDataStorage(this, &moduleManager(), options
);
693 AnalysisDataSimpleHistogramModule::frameStarted(const AnalysisDataFrameHeader
&header
)
695 impl_
->accumulator_
.frameData(header
.index()).clear();
700 AnalysisDataSimpleHistogramModule::pointsAdded(const AnalysisDataPointSetRef
&points
)
702 Impl::FrameLocalData::DataSetHandle handle
703 = impl_
->accumulator_
.frameDataSet(points
.frameIndex(), points
.dataSetIndex());
704 for (int i
= 0; i
< points
.columnCount(); ++i
)
706 if (points
.present(i
))
708 const int bin
= settings().findBin(points
.y(i
));
711 handle
.value(bin
) += 1;
719 AnalysisDataSimpleHistogramModule::frameFinished(const AnalysisDataFrameHeader
&header
)
721 Impl::FrameLocalData::FrameHandle handle
722 = impl_
->accumulator_
.frameData(header
.index());
723 AnalysisDataStorageFrame
&frame
= impl_
->storage_
.startFrame(header
);
724 const int columnCount
= settings().binCount();
725 for (int s
= 0; s
< dataSetCount(); ++s
)
727 Impl::FrameLocalData::DataSetHandle dataSet
= handle
.dataSet(s
);
728 frame
.selectDataSet(s
);
729 for (int i
= 0; i
< columnCount
; ++i
)
731 frame
.setValue(i
, dataSet
.value(i
));
739 AnalysisDataSimpleHistogramModule::frameFinishedSerial(int frameIndex
)
741 impl_
->storage_
.finishFrameSerial(frameIndex
);
746 AnalysisDataSimpleHistogramModule::dataFinished()
748 impl_
->storage_
.finishDataStorage();
753 AnalysisDataSimpleHistogramModule::tryGetDataFrameInternal(int index
) const
755 return impl_
->storage_
.tryGetDataFrame(index
);
760 AnalysisDataSimpleHistogramModule::requestStorageInternal(int nframes
)
762 return impl_
->storage_
.requestStorage(nframes
);
766 /********************************************************************
767 * AnalysisDataWeightedHistogramModule
771 * Private implementation class for AnalysisDataWeightedHistogramModule.
773 * \ingroup module_analysisdata
775 class AnalysisDataWeightedHistogramModule::Impl
: public internal::BasicHistogramImpl
778 //! Shorthand for the per-frame accumulation data structure type.
779 typedef AnalysisDataFrameLocalData
<double> FrameLocalData
;
782 //! Creates an histogram impl with defined bin parameters.
783 explicit Impl(const AnalysisHistogramSettings
&settings
)
784 : BasicHistogramImpl(settings
)
788 //! Accumulates the histogram within a frame.
789 FrameLocalData accumulator_
;
792 AnalysisDataWeightedHistogramModule::AnalysisDataWeightedHistogramModule()
798 AnalysisDataWeightedHistogramModule::AnalysisDataWeightedHistogramModule(
799 const AnalysisHistogramSettings
&settings
)
800 : impl_(new Impl(settings
))
805 AnalysisDataWeightedHistogramModule::~AnalysisDataWeightedHistogramModule()
810 void AnalysisDataWeightedHistogramModule::init(const AnalysisHistogramSettings
&settings
)
812 impl_
->init(settings
);
816 AbstractAverageHistogram
&
817 AnalysisDataWeightedHistogramModule::averager()
819 return *impl_
->averager_
;
823 const AnalysisHistogramSettings
&
824 AnalysisDataWeightedHistogramModule::settings() const
826 return impl_
->settings_
;
831 AnalysisDataWeightedHistogramModule::frameCount() const
833 return impl_
->storage_
.frameCount();
838 AnalysisDataWeightedHistogramModule::flags() const
840 return efAllowMulticolumn
| efAllowMultipoint
| efAllowMultipleDataSets
;
845 AnalysisDataWeightedHistogramModule::parallelDataStarted(
846 AbstractAnalysisData
*data
,
847 const AnalysisDataParallelOptions
&options
)
849 addModule(impl_
->averager_
);
850 const int dataSetCount
= data
->dataSetCount();
851 const int columnCount
= settings().binCount();
852 setDataSetCount(dataSetCount
);
853 impl_
->accumulator_
.setDataSetCount(dataSetCount
);
854 for (int i
= 0; i
< dataSetCount
; ++i
)
856 setColumnCount(i
, columnCount
);
857 impl_
->accumulator_
.setColumnCount(i
, columnCount
);
859 impl_
->accumulator_
.init(options
);
860 impl_
->storage_
.startParallelDataStorage(this, &moduleManager(), options
);
866 AnalysisDataWeightedHistogramModule::frameStarted(const AnalysisDataFrameHeader
&header
)
868 impl_
->accumulator_
.frameData(header
.index()).clear();
873 AnalysisDataWeightedHistogramModule::pointsAdded(const AnalysisDataPointSetRef
&points
)
875 if (points
.firstColumn() != 0 || points
.columnCount() < 2)
877 GMX_THROW(APIError("Invalid data layout"));
879 int bin
= settings().findBin(points
.y(0));
882 Impl::FrameLocalData::DataSetHandle handle
883 = impl_
->accumulator_
.frameDataSet(points
.frameIndex(), points
.dataSetIndex());
884 for (int i
= 1; i
< points
.columnCount(); ++i
)
886 handle
.value(bin
) += points
.y(i
);
893 AnalysisDataWeightedHistogramModule::frameFinished(const AnalysisDataFrameHeader
&header
)
895 Impl::FrameLocalData::FrameHandle handle
896 = impl_
->accumulator_
.frameData(header
.index());
897 AnalysisDataStorageFrame
&frame
= impl_
->storage_
.startFrame(header
);
898 const int columnCount
= settings().binCount();
899 for (int s
= 0; s
< dataSetCount(); ++s
)
901 Impl::FrameLocalData::DataSetHandle dataSet
= handle
.dataSet(s
);
902 frame
.selectDataSet(s
);
903 for (int i
= 0; i
< columnCount
; ++i
)
905 frame
.setValue(i
, dataSet
.value(i
));
913 AnalysisDataWeightedHistogramModule::frameFinishedSerial(int frameIndex
)
915 impl_
->storage_
.finishFrameSerial(frameIndex
);
920 AnalysisDataWeightedHistogramModule::dataFinished()
922 impl_
->storage_
.finishDataStorage();
927 AnalysisDataWeightedHistogramModule::tryGetDataFrameInternal(int index
) const
929 return impl_
->storage_
.tryGetDataFrame(index
);
934 AnalysisDataWeightedHistogramModule::requestStorageInternal(int nframes
)
936 return impl_
->storage_
.requestStorage(nframes
);
940 /********************************************************************
941 * AnalysisDataBinAverageModule
944 class AnalysisDataBinAverageModule::Impl
948 explicit Impl(const AnalysisHistogramSettings
&settings
)
949 : settings_(settings
)
953 //! Histogram settings.
954 AnalysisHistogramSettings settings_
;
955 //! Averaging helper objects for each input data set.
956 std::vector
<AnalysisDataFrameAverager
> averagers_
;
959 AnalysisDataBinAverageModule::AnalysisDataBinAverageModule()
966 AnalysisDataBinAverageModule::AnalysisDataBinAverageModule(
967 const AnalysisHistogramSettings
&settings
)
968 : impl_(new Impl(settings
))
970 setRowCount(settings
.binCount());
971 setXAxis(settings
.firstEdge() + 0.5 * settings
.binWidth(),
972 settings
.binWidth());
976 AnalysisDataBinAverageModule::~AnalysisDataBinAverageModule()
982 AnalysisDataBinAverageModule::init(const AnalysisHistogramSettings
&settings
)
984 impl_
->settings_
= settings
;
985 setRowCount(settings
.binCount());
986 setXAxis(settings
.firstEdge() + 0.5 * settings
.binWidth(),
987 settings
.binWidth());
991 const AnalysisHistogramSettings
&
992 AnalysisDataBinAverageModule::settings() const
994 return impl_
->settings_
;
999 AnalysisDataBinAverageModule::flags() const
1001 return efAllowMulticolumn
| efAllowMultipoint
| efAllowMultipleDataSets
;
1006 AnalysisDataBinAverageModule::dataStarted(AbstractAnalysisData
*data
)
1008 setColumnCount(data
->dataSetCount());
1009 impl_
->averagers_
.resize(data
->dataSetCount());
1010 for (int i
= 0; i
< data
->dataSetCount(); ++i
)
1012 impl_
->averagers_
[i
].setColumnCount(rowCount());
1018 AnalysisDataBinAverageModule::frameStarted(const AnalysisDataFrameHeader
& /*header*/)
1024 AnalysisDataBinAverageModule::pointsAdded(const AnalysisDataPointSetRef
&points
)
1026 if (points
.firstColumn() != 0 || points
.columnCount() < 2)
1028 GMX_THROW(APIError("Invalid data layout"));
1030 int bin
= settings().findBin(points
.y(0));
1033 AnalysisDataFrameAverager
&averager
= impl_
->averagers_
[points
.dataSetIndex()];
1034 for (int i
= 1; i
< points
.columnCount(); ++i
)
1036 averager
.addValue(bin
, points
.y(i
));
1043 AnalysisDataBinAverageModule::frameFinished(const AnalysisDataFrameHeader
& /*header*/)
1049 AnalysisDataBinAverageModule::dataFinished()
1052 for (int i
= 0; i
< columnCount(); ++i
)
1054 AnalysisDataFrameAverager
&averager
= impl_
->averagers_
[i
];
1056 for (int j
= 0; j
< rowCount(); ++j
)
1058 value(j
, i
).setValue(averager
.average(j
),
1059 std::sqrt(averager
.variance(j
)));