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/utility/basedefinitions.h"
55 #include "gromacs/utility/exceptions.h"
56 #include "gromacs/utility/gmxassert.h"
58 #include "frameaverager.h"
63 //! Value used to signify that a real-valued histogram setting is not set.
64 const real UNDEFINED = std::numeric_limits<real>::max();
65 //! Checks whether \p value is defined.
66 bool isDefined(real value)
68 return value != UNDEFINED;
76 /********************************************************************
77 * AnalysisHistogramSettingsInitializer
80 AnalysisHistogramSettingsInitializer::AnalysisHistogramSettingsInitializer()
81 : min_(UNDEFINED), max_(UNDEFINED), binWidth_(UNDEFINED),
82 binCount_(0), bIntegerBins_(false), bRoundRange_(false),
88 /********************************************************************
89 * AnalysisHistogramSettings
92 AnalysisHistogramSettings::AnalysisHistogramSettings()
93 : firstEdge_(0.0), lastEdge_(0.0), binWidth_(0.0), inverseBinWidth_(0.0),
94 binCount_(0), bAll_(false)
99 AnalysisHistogramSettings::AnalysisHistogramSettings(
100 const AnalysisHistogramSettingsInitializer &settings)
102 GMX_RELEASE_ASSERT(isDefined(settings.min_),
103 "Histogram start value must be defined");
104 GMX_RELEASE_ASSERT(!isDefined(settings.max_) || settings.max_ > settings.min_,
105 "Histogram end value must be larger than start value");
106 GMX_RELEASE_ASSERT(!isDefined(settings.binWidth_) || settings.binWidth_ > 0.0,
107 "Histogram bin width must be positive");
108 GMX_RELEASE_ASSERT(settings.binCount_ >= 0,
109 "Histogram bin count must be positive");
111 if (!isDefined(settings.max_))
113 GMX_RELEASE_ASSERT(isDefined(settings.binWidth_) && settings.binCount_ > 0,
114 "Not all required values provided");
115 GMX_RELEASE_ASSERT(!settings.bRoundRange_,
116 "Rounding only supported for min/max ranges");
118 firstEdge_ = settings.min_;
119 binCount_ = settings.binCount_;
120 binWidth_ = settings.binWidth_;
121 if (settings.bIntegerBins_)
123 firstEdge_ -= 0.5 * binWidth_;
125 lastEdge_ = firstEdge_ + binCount_ * binWidth_;
129 GMX_RELEASE_ASSERT(!(isDefined(settings.binWidth_) && settings.binCount_ > 0),
130 "Conflicting histogram bin specifications");
131 GMX_RELEASE_ASSERT(isDefined(settings.binWidth_) || settings.binCount_ > 0,
132 "Not all required values provided");
134 if (settings.bRoundRange_)
136 GMX_RELEASE_ASSERT(!settings.bIntegerBins_,
137 "Rounding and integer bins cannot be combined");
138 GMX_RELEASE_ASSERT(isDefined(settings.binWidth_),
139 "Rounding only makes sense with defined binwidth");
140 binWidth_ = settings.binWidth_;
141 firstEdge_ = binWidth_ * std::floor(settings.min_ / binWidth_);
142 lastEdge_ = binWidth_ * std::ceil(settings.max_ / binWidth_);
143 binCount_ = static_cast<int>((lastEdge_ - firstEdge_) / binWidth_ + 0.5);
147 firstEdge_ = settings.min_;
148 lastEdge_ = settings.max_;
149 if (settings.binCount_ > 0)
151 binCount_ = settings.binCount_;
152 if (settings.bIntegerBins_)
154 GMX_RELEASE_ASSERT(settings.binCount_ > 1,
155 "Bin count must be at least two with integer bins");
156 binWidth_ = (lastEdge_ - firstEdge_) / (binCount_ - 1);
157 firstEdge_ -= 0.5 * binWidth_;
158 lastEdge_ += 0.5 * binWidth_;
162 binWidth_ = (lastEdge_ - firstEdge_) / binCount_;
167 binWidth_ = settings.binWidth_;
168 binCount_ = static_cast<int>((lastEdge_ - firstEdge_) / binWidth_ + 0.5);
169 if (settings.bIntegerBins_)
171 firstEdge_ -= 0.5 * binWidth_;
174 lastEdge_ = firstEdge_ + binCount_ * binWidth_;
179 inverseBinWidth_ = 1.0 / binWidth_;
180 bAll_ = settings.bIncludeAll_;
185 AnalysisHistogramSettings::findBin(real y) const
189 return bAll_ ? 0 : -1;
191 int bin = static_cast<int>((y - firstEdge_) * inverseBinWidth_);
192 if (bin >= binCount_)
194 return bAll_ ? binCount_ - 1 : -1;
200 /********************************************************************
201 * StaticAverageHistogram
208 * Represents copies of average histograms.
210 * Methods in AbstractAverageHistogram that return new histogram instances
211 * return objects of this class.
212 * Initialization of values is handled in those methods.
214 * \ingroup module_analysisdata
216 class StaticAverageHistogram : public AbstractAverageHistogram
219 StaticAverageHistogram();
220 //! Creates an average histogram module with defined bin parameters.
221 explicit StaticAverageHistogram(const AnalysisHistogramSettings &settings);
223 // Copy and assign disallowed by base.
226 StaticAverageHistogram::StaticAverageHistogram()
231 StaticAverageHistogram::StaticAverageHistogram(
232 const AnalysisHistogramSettings &settings)
233 : AbstractAverageHistogram(settings)
240 /********************************************************************
241 * AbstractAverageHistogram
244 AbstractAverageHistogram::AbstractAverageHistogram()
249 AbstractAverageHistogram::AbstractAverageHistogram(
250 const AnalysisHistogramSettings &settings)
251 : settings_(settings)
253 setRowCount(settings.binCount());
254 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(),
255 settings.binWidth());
259 AbstractAverageHistogram::~AbstractAverageHistogram()
265 AbstractAverageHistogram::init(const AnalysisHistogramSettings &settings)
267 settings_ = settings;
268 setRowCount(settings.binCount());
269 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(),
270 settings.binWidth());
274 AverageHistogramPointer
275 AbstractAverageHistogram::resampleDoubleBinWidth(bool bIntegerBins) const
280 nbins = (rowCount() + 1) / 2;
284 nbins = rowCount() / 2;
287 AverageHistogramPointer dest(
288 new StaticAverageHistogram(
289 histogramFromBins(settings().firstEdge(), nbins, 2*xstep())
290 .integerBins(bIntegerBins)));
291 dest->setColumnCount(columnCount());
292 dest->allocateValues();
295 for (i = j = 0; i < nbins; ++i)
297 const bool bFirstHalfBin = (bIntegerBins && i == 0);
298 for (int c = 0; c < columnCount(); ++c)
304 v1 = value(0, c).value();
305 e1 = value(0, c).error();
311 v1 = value(j, c).value();
312 e1 = value(j, c).error();
313 v2 = value(j + 1, c).value();
314 e2 = value(j + 1, c).error();
316 dest->value(i, c).setValue(v1 + v2, std::sqrt(e1 * e1 + e2 * e2));
331 AverageHistogramPointer
332 AbstractAverageHistogram::clone() const
334 AverageHistogramPointer dest(new StaticAverageHistogram());
335 copyContents(this, dest.get());
336 dest->settings_ = settings_;
342 AbstractAverageHistogram::normalizeProbability()
344 for (int c = 0; c < columnCount(); ++c)
347 for (int i = 0; i < rowCount(); ++i)
349 sum += value(i, c).value();
353 scaleSingle(c, 1.0 / (sum * xstep()));
359 AbstractAverageHistogram::makeCumulative()
361 for (int c = 0; c < columnCount(); ++c)
364 for (int i = 0; i < rowCount(); ++i)
366 sum += value(i, c).value();
367 // Clear the error, as we don't cumulate that.
369 value(i, c).setValue(sum);
372 setXAxis(settings().firstEdge() + settings().binWidth(),
373 settings().binWidth());
378 AbstractAverageHistogram::scaleSingle(int index, real factor)
380 for (int i = 0; i < rowCount(); ++i)
382 value(i, index).value() *= factor;
383 value(i, index).error() *= factor;
389 AbstractAverageHistogram::scaleAll(real factor)
391 for (int i = 0; i < columnCount(); ++i)
393 scaleSingle(i, factor);
399 AbstractAverageHistogram::scaleAllByVector(const real factor[])
401 for (int c = 0; c < columnCount(); ++c)
403 for (int i = 0; i < rowCount(); ++i)
405 value(i, c).value() *= factor[i];
406 value(i, c).error() *= factor[i];
412 /********************************************************************
413 * BasicAverageHistogramModule
421 * Implements average histogram module that averages per-frame histograms.
423 * This class is used for accumulating average histograms in per-frame
424 * histogram modules (those that use BasicHistogramImpl as their implementation
426 * There are two columns, first for the average and second for standard
429 * \ingroup module_analysisdata
431 class BasicAverageHistogramModule : public AbstractAverageHistogram,
432 public AnalysisDataModuleSerial
435 BasicAverageHistogramModule();
436 //! Creates an average histogram module with defined bin parameters.
437 explicit BasicAverageHistogramModule(const AnalysisHistogramSettings &settings);
439 using AbstractAverageHistogram::init;
441 int flags() const override;
443 void dataStarted(AbstractAnalysisData *data) override;
444 void frameStarted(const AnalysisDataFrameHeader &header) override;
445 void pointsAdded(const AnalysisDataPointSetRef &points) override;
446 void frameFinished(const AnalysisDataFrameHeader &header) override;
447 void dataFinished() override;
450 //! Averaging helper objects for each input data set.
451 std::vector<AnalysisDataFrameAverager> averagers_;
453 // Copy and assign disallowed by base.
456 BasicAverageHistogramModule::BasicAverageHistogramModule()
461 BasicAverageHistogramModule::BasicAverageHistogramModule(
462 const AnalysisHistogramSettings &settings)
463 : AbstractAverageHistogram(settings)
469 BasicAverageHistogramModule::flags() const
471 return efAllowMulticolumn | efAllowMultipleDataSets;
476 BasicAverageHistogramModule::dataStarted(AbstractAnalysisData *data)
478 setColumnCount(data->dataSetCount());
479 averagers_.resize(data->dataSetCount());
480 for (int i = 0; i < data->dataSetCount(); ++i)
482 GMX_RELEASE_ASSERT(rowCount() == data->columnCount(i),
483 "Inconsistent data sizes, something is wrong in the initialization");
484 averagers_[i].setColumnCount(data->columnCount(i));
490 BasicAverageHistogramModule::frameStarted(const AnalysisDataFrameHeader & /*header*/)
496 BasicAverageHistogramModule::pointsAdded(const AnalysisDataPointSetRef &points)
498 averagers_[points.dataSetIndex()].addPoints(points);
503 BasicAverageHistogramModule::frameFinished(const AnalysisDataFrameHeader & /*header*/)
509 BasicAverageHistogramModule::dataFinished()
512 for (int i = 0; i < columnCount(); ++i)
514 averagers_[i].finish();
515 for (int j = 0; j < rowCount(); ++j)
517 value(j, i).setValue(averagers_[i].average(j),
518 std::sqrt(averagers_[i].variance(j)));
524 /********************************************************************
530 * Base class for private implementation classes for histogram modules.
532 * Actual implementation classes are derived from this and add an accumulation
533 * data member that is specific to the histogram type in question.
534 * This is done like this to keep implementation details out of the header, and
535 * to not unnecessarily duplicate code.
537 * \ingroup module_analysisdata
539 class BasicHistogramImpl
542 //! Smart pointer to manage an BasicAverageHistogramModule object.
543 typedef std::shared_ptr<BasicAverageHistogramModule>
544 BasicAverageHistogramModulePointer;
546 BasicHistogramImpl();
547 //! Creates an histogram impl with defined bin parameters.
548 explicit BasicHistogramImpl(const AnalysisHistogramSettings &settings);
549 // Virtual only for simplicity.
550 virtual ~BasicHistogramImpl();
553 * (Re)initializes the histogram from settings.
555 void init(const AnalysisHistogramSettings &settings);
557 //! Storage implementation object.
558 AnalysisDataStorage storage_;
559 //! Settings for the histogram object.
560 AnalysisHistogramSettings settings_;
562 BasicAverageHistogramModulePointer averager_;
565 BasicHistogramImpl::BasicHistogramImpl()
566 : averager_(new BasicAverageHistogramModule())
571 BasicHistogramImpl::BasicHistogramImpl(const AnalysisHistogramSettings &settings)
572 : settings_(settings), averager_(new BasicAverageHistogramModule(settings))
577 BasicHistogramImpl::~BasicHistogramImpl()
582 void BasicHistogramImpl::init(const AnalysisHistogramSettings &settings)
584 settings_ = settings;
585 averager_->init(settings);
588 } // namespace internal
591 /********************************************************************
592 * AnalysisDataSimpleHistogramModule
596 * Private implementation class for AnalysisDataSimpleHistogramModule.
598 * \ingroup module_analysisdata
600 class AnalysisDataSimpleHistogramModule::Impl : public internal::BasicHistogramImpl
603 //! Shorthand for the per-frame accumulation data structure type.
604 typedef AnalysisDataFrameLocalData<int64_t> FrameLocalData;
607 //! Creates an histogram impl with defined bin parameters.
608 explicit Impl(const AnalysisHistogramSettings &settings)
609 : BasicHistogramImpl(settings)
613 //! Accumulates the histogram within a frame.
614 FrameLocalData accumulator_;
617 AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule()
623 AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule(
624 const AnalysisHistogramSettings &settings)
625 : impl_(new Impl(settings))
630 AnalysisDataSimpleHistogramModule::~AnalysisDataSimpleHistogramModule()
635 void AnalysisDataSimpleHistogramModule::init(const AnalysisHistogramSettings &settings)
637 impl_->init(settings);
641 AbstractAverageHistogram &
642 AnalysisDataSimpleHistogramModule::averager()
644 return *impl_->averager_;
648 const AnalysisHistogramSettings &
649 AnalysisDataSimpleHistogramModule::settings() const
651 return impl_->settings_;
656 AnalysisDataSimpleHistogramModule::frameCount() const
658 return impl_->storage_.frameCount();
663 AnalysisDataSimpleHistogramModule::flags() const
665 return efAllowMulticolumn | efAllowMultipoint | efAllowMissing
666 | efAllowMultipleDataSets;
671 AnalysisDataSimpleHistogramModule::parallelDataStarted(
672 AbstractAnalysisData *data,
673 const AnalysisDataParallelOptions &options)
675 addModule(impl_->averager_);
676 const int dataSetCount = data->dataSetCount();
677 const int columnCount = settings().binCount();
678 setDataSetCount(dataSetCount);
679 impl_->accumulator_.setDataSetCount(dataSetCount);
680 for (int i = 0; i < dataSetCount; ++i)
682 setColumnCount(i, columnCount);
683 impl_->accumulator_.setColumnCount(i, columnCount);
685 impl_->accumulator_.init(options);
686 impl_->storage_.startParallelDataStorage(this, &moduleManager(), options);
692 AnalysisDataSimpleHistogramModule::frameStarted(const AnalysisDataFrameHeader &header)
694 impl_->accumulator_.frameData(header.index()).clear();
699 AnalysisDataSimpleHistogramModule::pointsAdded(const AnalysisDataPointSetRef &points)
701 Impl::FrameLocalData::DataSetHandle handle
702 = impl_->accumulator_.frameDataSet(points.frameIndex(), points.dataSetIndex());
703 for (int i = 0; i < points.columnCount(); ++i)
705 if (points.present(i))
707 const int bin = settings().findBin(points.y(i));
710 handle.value(bin) += 1;
718 AnalysisDataSimpleHistogramModule::frameFinished(const AnalysisDataFrameHeader &header)
720 Impl::FrameLocalData::FrameHandle handle
721 = impl_->accumulator_.frameData(header.index());
722 AnalysisDataStorageFrame &frame = impl_->storage_.startFrame(header);
723 const int columnCount = settings().binCount();
724 for (int s = 0; s < dataSetCount(); ++s)
726 Impl::FrameLocalData::DataSetHandle dataSet = handle.dataSet(s);
727 frame.selectDataSet(s);
728 for (int i = 0; i < columnCount; ++i)
730 frame.setValue(i, dataSet.value(i));
738 AnalysisDataSimpleHistogramModule::frameFinishedSerial(int frameIndex)
740 impl_->storage_.finishFrameSerial(frameIndex);
745 AnalysisDataSimpleHistogramModule::dataFinished()
747 impl_->storage_.finishDataStorage();
752 AnalysisDataSimpleHistogramModule::tryGetDataFrameInternal(int index) const
754 return impl_->storage_.tryGetDataFrame(index);
759 AnalysisDataSimpleHistogramModule::requestStorageInternal(int nframes)
761 return impl_->storage_.requestStorage(nframes);
765 /********************************************************************
766 * AnalysisDataWeightedHistogramModule
770 * Private implementation class for AnalysisDataWeightedHistogramModule.
772 * \ingroup module_analysisdata
774 class AnalysisDataWeightedHistogramModule::Impl : public internal::BasicHistogramImpl
777 //! Shorthand for the per-frame accumulation data structure type.
778 typedef AnalysisDataFrameLocalData<double> FrameLocalData;
781 //! Creates an histogram impl with defined bin parameters.
782 explicit Impl(const AnalysisHistogramSettings &settings)
783 : BasicHistogramImpl(settings)
787 //! Accumulates the histogram within a frame.
788 FrameLocalData accumulator_;
791 AnalysisDataWeightedHistogramModule::AnalysisDataWeightedHistogramModule()
797 AnalysisDataWeightedHistogramModule::AnalysisDataWeightedHistogramModule(
798 const AnalysisHistogramSettings &settings)
799 : impl_(new Impl(settings))
804 AnalysisDataWeightedHistogramModule::~AnalysisDataWeightedHistogramModule()
809 void AnalysisDataWeightedHistogramModule::init(const AnalysisHistogramSettings &settings)
811 impl_->init(settings);
815 AbstractAverageHistogram &
816 AnalysisDataWeightedHistogramModule::averager()
818 return *impl_->averager_;
822 const AnalysisHistogramSettings &
823 AnalysisDataWeightedHistogramModule::settings() const
825 return impl_->settings_;
830 AnalysisDataWeightedHistogramModule::frameCount() const
832 return impl_->storage_.frameCount();
837 AnalysisDataWeightedHistogramModule::flags() const
839 return efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
844 AnalysisDataWeightedHistogramModule::parallelDataStarted(
845 AbstractAnalysisData *data,
846 const AnalysisDataParallelOptions &options)
848 addModule(impl_->averager_);
849 const int dataSetCount = data->dataSetCount();
850 const int columnCount = settings().binCount();
851 setDataSetCount(dataSetCount);
852 impl_->accumulator_.setDataSetCount(dataSetCount);
853 for (int i = 0; i < dataSetCount; ++i)
855 setColumnCount(i, columnCount);
856 impl_->accumulator_.setColumnCount(i, columnCount);
858 impl_->accumulator_.init(options);
859 impl_->storage_.startParallelDataStorage(this, &moduleManager(), options);
865 AnalysisDataWeightedHistogramModule::frameStarted(const AnalysisDataFrameHeader &header)
867 impl_->accumulator_.frameData(header.index()).clear();
872 AnalysisDataWeightedHistogramModule::pointsAdded(const AnalysisDataPointSetRef &points)
874 if (points.firstColumn() != 0 || points.columnCount() < 2)
876 GMX_THROW(APIError("Invalid data layout"));
878 int bin = settings().findBin(points.y(0));
881 Impl::FrameLocalData::DataSetHandle handle
882 = impl_->accumulator_.frameDataSet(points.frameIndex(), points.dataSetIndex());
883 for (int i = 1; i < points.columnCount(); ++i)
885 handle.value(bin) += points.y(i);
892 AnalysisDataWeightedHistogramModule::frameFinished(const AnalysisDataFrameHeader &header)
894 Impl::FrameLocalData::FrameHandle handle
895 = impl_->accumulator_.frameData(header.index());
896 AnalysisDataStorageFrame &frame = impl_->storage_.startFrame(header);
897 const int columnCount = settings().binCount();
898 for (int s = 0; s < dataSetCount(); ++s)
900 Impl::FrameLocalData::DataSetHandle dataSet = handle.dataSet(s);
901 frame.selectDataSet(s);
902 for (int i = 0; i < columnCount; ++i)
904 frame.setValue(i, dataSet.value(i));
912 AnalysisDataWeightedHistogramModule::frameFinishedSerial(int frameIndex)
914 impl_->storage_.finishFrameSerial(frameIndex);
919 AnalysisDataWeightedHistogramModule::dataFinished()
921 impl_->storage_.finishDataStorage();
926 AnalysisDataWeightedHistogramModule::tryGetDataFrameInternal(int index) const
928 return impl_->storage_.tryGetDataFrame(index);
933 AnalysisDataWeightedHistogramModule::requestStorageInternal(int nframes)
935 return impl_->storage_.requestStorage(nframes);
939 /********************************************************************
940 * AnalysisDataBinAverageModule
943 class AnalysisDataBinAverageModule::Impl
947 explicit Impl(const AnalysisHistogramSettings &settings)
948 : settings_(settings)
952 //! Histogram settings.
953 AnalysisHistogramSettings settings_;
954 //! Averaging helper objects for each input data set.
955 std::vector<AnalysisDataFrameAverager> averagers_;
958 AnalysisDataBinAverageModule::AnalysisDataBinAverageModule()
965 AnalysisDataBinAverageModule::AnalysisDataBinAverageModule(
966 const AnalysisHistogramSettings &settings)
967 : impl_(new Impl(settings))
969 setRowCount(settings.binCount());
970 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(),
971 settings.binWidth());
975 AnalysisDataBinAverageModule::~AnalysisDataBinAverageModule()
981 AnalysisDataBinAverageModule::init(const AnalysisHistogramSettings &settings)
983 impl_->settings_ = settings;
984 setRowCount(settings.binCount());
985 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(),
986 settings.binWidth());
990 const AnalysisHistogramSettings &
991 AnalysisDataBinAverageModule::settings() const
993 return impl_->settings_;
998 AnalysisDataBinAverageModule::flags() const
1000 return efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
1005 AnalysisDataBinAverageModule::dataStarted(AbstractAnalysisData *data)
1007 setColumnCount(data->dataSetCount());
1008 impl_->averagers_.resize(data->dataSetCount());
1009 for (int i = 0; i < data->dataSetCount(); ++i)
1011 impl_->averagers_[i].setColumnCount(rowCount());
1017 AnalysisDataBinAverageModule::frameStarted(const AnalysisDataFrameHeader & /*header*/)
1023 AnalysisDataBinAverageModule::pointsAdded(const AnalysisDataPointSetRef &points)
1025 if (points.firstColumn() != 0 || points.columnCount() < 2)
1027 GMX_THROW(APIError("Invalid data layout"));
1029 int bin = settings().findBin(points.y(0));
1032 AnalysisDataFrameAverager &averager = impl_->averagers_[points.dataSetIndex()];
1033 for (int i = 1; i < points.columnCount(); ++i)
1035 averager.addValue(bin, points.y(i));
1042 AnalysisDataBinAverageModule::frameFinished(const AnalysisDataFrameHeader & /*header*/)
1048 AnalysisDataBinAverageModule::dataFinished()
1051 for (int i = 0; i < columnCount(); ++i)
1053 AnalysisDataFrameAverager &averager = impl_->averagers_[i];
1055 for (int j = 0; j < rowCount(); ++j)
1057 value(j, i).setValue(averager.average(j),
1058 std::sqrt(averager.variance(j)));