2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2010,2011,2012,2013,2014 by the GROMACS development team.
5 * Copyright (c) 2015,2018,2019,2020,2021, by the GROMACS development team, led by
6 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7 * and including many others, as listed in the AUTHORS file in the
8 * top-level source directory and at http://www.gromacs.org.
10 * GROMACS is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1
13 * of the License, or (at your option) any later version.
15 * GROMACS is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with GROMACS; if not, see
22 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * If you want to redistribute modifications to GROMACS, please
26 * consider that scientific software is very special. Version
27 * control is crucial - bugs must be traceable. We will be happy to
28 * consider code for inclusion in the official distribution, but
29 * derived work must not be called official GROMACS. Details are found
30 * in the README & COPYING files - if they are missing, get the
31 * official version at http://www.gromacs.org.
33 * To help us fund GROMACS development, we humbly ask that you cite
34 * the research papers on the package. Check out http://www.gromacs.org.
38 * Implements classes in histogram.h.
40 * \author Teemu Murtola <teemu.murtola@gmail.com>
41 * \ingroup module_analysisdata
45 #include "histogram.h"
52 #include "gromacs/analysisdata/dataframe.h"
53 #include "gromacs/analysisdata/datastorage.h"
54 #include "gromacs/analysisdata/framelocaldata.h"
55 #include "gromacs/math/functions.h"
56 #include "gromacs/utility/basedefinitions.h"
57 #include "gromacs/utility/exceptions.h"
58 #include "gromacs/utility/gmxassert.h"
60 #include "frameaverager.h"
65 //! Value used to signify that a real-valued histogram setting is not set.
66 const real UNDEFINED = std::numeric_limits<real>::max();
67 //! Checks whether \p value is defined.
68 bool isDefined(real value)
70 return value != UNDEFINED;
78 /********************************************************************
79 * AnalysisHistogramSettingsInitializer
82 AnalysisHistogramSettingsInitializer::AnalysisHistogramSettingsInitializer() :
94 /********************************************************************
95 * AnalysisHistogramSettings
98 AnalysisHistogramSettings::AnalysisHistogramSettings() :
99 firstEdge_(0.0), lastEdge_(0.0), binWidth_(0.0), inverseBinWidth_(0.0), binCount_(0), bAll_(false)
104 AnalysisHistogramSettings::AnalysisHistogramSettings(const AnalysisHistogramSettingsInitializer& settings)
106 GMX_RELEASE_ASSERT(isDefined(settings.min_), "Histogram start value must be defined");
107 GMX_RELEASE_ASSERT(!isDefined(settings.max_) || settings.max_ > settings.min_,
108 "Histogram end value must be larger than start value");
109 GMX_RELEASE_ASSERT(!isDefined(settings.binWidth_) || settings.binWidth_ > 0.0,
110 "Histogram bin width must be positive");
111 GMX_RELEASE_ASSERT(settings.binCount_ >= 0, "Histogram bin count must be positive");
113 if (!isDefined(settings.max_))
115 GMX_RELEASE_ASSERT(isDefined(settings.binWidth_) && settings.binCount_ > 0,
116 "Not all required values provided");
117 GMX_RELEASE_ASSERT(!settings.bRoundRange_, "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_;
185 int 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() {}
229 StaticAverageHistogram::StaticAverageHistogram(const AnalysisHistogramSettings& settings) :
230 AbstractAverageHistogram(settings)
237 /********************************************************************
238 * AbstractAverageHistogram
241 AbstractAverageHistogram::AbstractAverageHistogram() {}
244 AbstractAverageHistogram::AbstractAverageHistogram(const AnalysisHistogramSettings& settings) :
247 setRowCount(settings.binCount());
248 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(), settings.binWidth());
252 AbstractAverageHistogram::~AbstractAverageHistogram() {}
255 void AbstractAverageHistogram::init(const AnalysisHistogramSettings& settings)
257 settings_ = settings;
258 setRowCount(settings.binCount());
259 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(), settings.binWidth());
263 AverageHistogramPointer AbstractAverageHistogram::resampleDoubleBinWidth(bool bIntegerBins) const
265 const int nbins = bIntegerBins ? (rowCount() + 1) / 2 : rowCount() / 2;
267 AverageHistogramPointer dest(new StaticAverageHistogram(
268 histogramFromBins(settings().firstEdge(), nbins, 2 * xstep()).integerBins(bIntegerBins)));
269 dest->setColumnCount(columnCount());
270 dest->allocateValues();
272 for (int i = 0, j = 0; i < nbins; ++i)
274 const bool bFirstHalfBin = (bIntegerBins && i == 0);
275 for (int c = 0; c < columnCount(); ++c)
277 const real v1 = bFirstHalfBin ? value(0, c).value() : value(j, c).value();
278 const real v2 = bFirstHalfBin ? 0 : value(j + 1, c).value();
279 const real e1 = bFirstHalfBin ? value(0, c).error() : value(j, c).error();
280 const real e2 = bFirstHalfBin ? 0 : value(j + 1, c).error();
281 dest->value(i, c).setValue(v1 + v2, std::sqrt(e1 * e1 + e2 * e2));
296 AverageHistogramPointer AbstractAverageHistogram::clone() const
298 AverageHistogramPointer dest(new StaticAverageHistogram());
299 copyContents(this, dest.get());
300 dest->settings_ = settings_;
305 void AbstractAverageHistogram::normalizeProbability()
307 for (int c = 0; c < columnCount(); ++c)
310 for (int i = 0; i < rowCount(); ++i)
312 sum += value(i, c).value();
316 scaleSingle(c, 1.0 / (sum * xstep()));
321 void AbstractAverageHistogram::makeCumulative()
323 for (int c = 0; c < columnCount(); ++c)
326 for (int i = 0; i < rowCount(); ++i)
328 sum += value(i, c).value();
329 // Clear the error, as we don't cumulate that.
331 value(i, c).setValue(sum);
334 setXAxis(settings().firstEdge() + settings().binWidth(), settings().binWidth());
338 void AbstractAverageHistogram::scaleSingle(int index, real factor)
340 for (int i = 0; i < rowCount(); ++i)
342 value(i, index).value() *= factor;
343 value(i, index).error() *= factor;
348 void AbstractAverageHistogram::scaleAll(real factor)
350 for (int i = 0; i < columnCount(); ++i)
352 scaleSingle(i, factor);
357 void AbstractAverageHistogram::scaleAllByVector(const real factor[])
359 for (int c = 0; c < columnCount(); ++c)
361 for (int i = 0; i < rowCount(); ++i)
363 value(i, c).value() *= factor[i];
364 value(i, c).error() *= factor[i];
370 /********************************************************************
371 * BasicAverageHistogramModule
379 * Implements average histogram module that averages per-frame histograms.
381 * This class is used for accumulating average histograms in per-frame
382 * histogram modules (those that use BasicHistogramImpl as their implementation
384 * There are two columns, first for the average and second for standard
387 * \ingroup module_analysisdata
389 class BasicAverageHistogramModule : public AbstractAverageHistogram, public AnalysisDataModuleSerial
392 BasicAverageHistogramModule();
393 //! Creates an average histogram module with defined bin parameters.
394 explicit BasicAverageHistogramModule(const AnalysisHistogramSettings& settings);
396 using AbstractAverageHistogram::init;
398 int flags() const override;
400 void dataStarted(AbstractAnalysisData* data) override;
401 void frameStarted(const AnalysisDataFrameHeader& header) override;
402 void pointsAdded(const AnalysisDataPointSetRef& points) override;
403 void frameFinished(const AnalysisDataFrameHeader& header) override;
404 void dataFinished() override;
407 //! Averaging helper objects for each input data set.
408 std::vector<AnalysisDataFrameAverager> averagers_;
410 // Copy and assign disallowed by base.
413 BasicAverageHistogramModule::BasicAverageHistogramModule() {}
416 BasicAverageHistogramModule::BasicAverageHistogramModule(const AnalysisHistogramSettings& settings) :
417 AbstractAverageHistogram(settings)
422 int BasicAverageHistogramModule::flags() const
424 return efAllowMulticolumn | efAllowMultipleDataSets;
428 void BasicAverageHistogramModule::dataStarted(AbstractAnalysisData* data)
430 setColumnCount(data->dataSetCount());
431 averagers_.resize(data->dataSetCount());
432 for (int i = 0; i < data->dataSetCount(); ++i)
434 GMX_RELEASE_ASSERT(rowCount() == data->columnCount(i),
435 "Inconsistent data sizes, something is wrong in the initialization");
436 averagers_[i].setColumnCount(data->columnCount(i));
441 void BasicAverageHistogramModule::frameStarted(const AnalysisDataFrameHeader& /*header*/) {}
444 void BasicAverageHistogramModule::pointsAdded(const AnalysisDataPointSetRef& points)
446 averagers_[points.dataSetIndex()].addPoints(points);
450 void BasicAverageHistogramModule::frameFinished(const AnalysisDataFrameHeader& /*header*/) {}
453 void BasicAverageHistogramModule::dataFinished()
456 for (int i = 0; i < columnCount(); ++i)
458 averagers_[i].finish();
459 for (int j = 0; j < rowCount(); ++j)
461 value(j, i).setValue(averagers_[i].average(j), std::sqrt(averagers_[i].variance(j)));
467 /********************************************************************
473 * Base class for private implementation classes for histogram modules.
475 * Actual implementation classes are derived from this and add an accumulation
476 * data member that is specific to the histogram type in question.
477 * This is done like this to keep implementation details out of the header, and
478 * to not unnecessarily duplicate code.
480 * \ingroup module_analysisdata
482 class BasicHistogramImpl
485 //! Smart pointer to manage an BasicAverageHistogramModule object.
486 typedef std::shared_ptr<BasicAverageHistogramModule> BasicAverageHistogramModulePointer;
488 BasicHistogramImpl();
489 //! Creates an histogram impl with defined bin parameters.
490 explicit BasicHistogramImpl(const AnalysisHistogramSettings& settings);
491 // Virtual only for simplicity.
492 virtual ~BasicHistogramImpl();
495 * (Re)initializes the histogram from settings.
497 void init(const AnalysisHistogramSettings& settings);
499 //! Storage implementation object.
500 AnalysisDataStorage storage_;
501 //! Settings for the histogram object.
502 AnalysisHistogramSettings settings_;
504 BasicAverageHistogramModulePointer averager_;
507 BasicHistogramImpl::BasicHistogramImpl() : averager_(new BasicAverageHistogramModule()) {}
510 BasicHistogramImpl::BasicHistogramImpl(const AnalysisHistogramSettings& settings) :
511 settings_(settings), averager_(new BasicAverageHistogramModule(settings))
516 BasicHistogramImpl::~BasicHistogramImpl() {}
519 void BasicHistogramImpl::init(const AnalysisHistogramSettings& settings)
521 settings_ = settings;
522 averager_->init(settings);
525 } // namespace internal
528 /********************************************************************
529 * AnalysisDataSimpleHistogramModule
533 * Private implementation class for AnalysisDataSimpleHistogramModule.
535 * \ingroup module_analysisdata
537 class AnalysisDataSimpleHistogramModule::Impl : public internal::BasicHistogramImpl
540 //! Shorthand for the per-frame accumulation data structure type.
541 typedef AnalysisDataFrameLocalData<int64_t> FrameLocalData;
544 //! Creates an histogram impl with defined bin parameters.
545 explicit Impl(const AnalysisHistogramSettings& settings) : BasicHistogramImpl(settings) {}
547 //! Accumulates the histogram within a frame.
548 FrameLocalData accumulator_;
551 AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule() : impl_(new Impl()) {}
554 AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule(const AnalysisHistogramSettings& settings) :
555 impl_(new Impl(settings))
560 AnalysisDataSimpleHistogramModule::~AnalysisDataSimpleHistogramModule() {}
563 void AnalysisDataSimpleHistogramModule::init(const AnalysisHistogramSettings& settings)
565 impl_->init(settings);
569 AbstractAverageHistogram& AnalysisDataSimpleHistogramModule::averager()
571 return *impl_->averager_;
575 const AnalysisHistogramSettings& AnalysisDataSimpleHistogramModule::settings() const
577 return impl_->settings_;
581 int AnalysisDataSimpleHistogramModule::frameCount() const
583 return impl_->storage_.frameCount();
587 int AnalysisDataSimpleHistogramModule::flags() const
589 return efAllowMulticolumn | efAllowMultipoint | efAllowMissing | efAllowMultipleDataSets;
593 bool AnalysisDataSimpleHistogramModule::parallelDataStarted(AbstractAnalysisData* data,
594 const AnalysisDataParallelOptions& options)
596 addModule(impl_->averager_);
597 const int dataSetCount = data->dataSetCount();
598 const int columnCount = settings().binCount();
599 setDataSetCount(dataSetCount);
600 impl_->accumulator_.setDataSetCount(dataSetCount);
601 for (int i = 0; i < dataSetCount; ++i)
603 setColumnCount(i, columnCount);
604 impl_->accumulator_.setColumnCount(i, columnCount);
606 impl_->accumulator_.init(options);
607 impl_->storage_.startParallelDataStorage(this, &moduleManager(), options);
612 void AnalysisDataSimpleHistogramModule::frameStarted(const AnalysisDataFrameHeader& header)
614 impl_->accumulator_.frameData(header.index()).clear();
618 void AnalysisDataSimpleHistogramModule::pointsAdded(const AnalysisDataPointSetRef& points)
620 Impl::FrameLocalData::DataSetHandle handle =
621 impl_->accumulator_.frameDataSet(points.frameIndex(), points.dataSetIndex());
622 for (int i = 0; i < points.columnCount(); ++i)
624 if (points.present(i))
626 const int bin = settings().findBin(points.y(i));
629 handle.value(bin) += 1;
636 void AnalysisDataSimpleHistogramModule::frameFinished(const AnalysisDataFrameHeader& header)
638 Impl::FrameLocalData::FrameHandle handle = impl_->accumulator_.frameData(header.index());
639 AnalysisDataStorageFrame& frame = impl_->storage_.startFrame(header);
640 const int columnCount = settings().binCount();
641 for (int s = 0; s < dataSetCount(); ++s)
643 Impl::FrameLocalData::DataSetHandle dataSet = handle.dataSet(s);
644 frame.selectDataSet(s);
645 for (int i = 0; i < columnCount; ++i)
647 frame.setValue(i, dataSet.value(i));
654 void AnalysisDataSimpleHistogramModule::frameFinishedSerial(int frameIndex)
656 impl_->storage_.finishFrameSerial(frameIndex);
660 void AnalysisDataSimpleHistogramModule::dataFinished()
662 impl_->storage_.finishDataStorage();
666 AnalysisDataFrameRef AnalysisDataSimpleHistogramModule::tryGetDataFrameInternal(int index) const
668 return impl_->storage_.tryGetDataFrame(index);
672 bool AnalysisDataSimpleHistogramModule::requestStorageInternal(int nframes)
674 return impl_->storage_.requestStorage(nframes);
678 /********************************************************************
679 * AnalysisDataWeightedHistogramModule
683 * Private implementation class for AnalysisDataWeightedHistogramModule.
685 * \ingroup module_analysisdata
687 class AnalysisDataWeightedHistogramModule::Impl : public internal::BasicHistogramImpl
690 //! Shorthand for the per-frame accumulation data structure type.
691 typedef AnalysisDataFrameLocalData<double> FrameLocalData;
694 //! Creates an histogram impl with defined bin parameters.
695 explicit Impl(const AnalysisHistogramSettings& settings) : BasicHistogramImpl(settings) {}
697 //! Accumulates the histogram within a frame.
698 FrameLocalData accumulator_;
701 AnalysisDataWeightedHistogramModule::AnalysisDataWeightedHistogramModule() : impl_(new Impl()) {}
704 AnalysisDataWeightedHistogramModule::AnalysisDataWeightedHistogramModule(const AnalysisHistogramSettings& settings) :
705 impl_(new Impl(settings))
710 AnalysisDataWeightedHistogramModule::~AnalysisDataWeightedHistogramModule() {}
713 void AnalysisDataWeightedHistogramModule::init(const AnalysisHistogramSettings& settings)
715 impl_->init(settings);
719 AbstractAverageHistogram& AnalysisDataWeightedHistogramModule::averager()
721 return *impl_->averager_;
725 const AnalysisHistogramSettings& AnalysisDataWeightedHistogramModule::settings() const
727 return impl_->settings_;
731 int AnalysisDataWeightedHistogramModule::frameCount() const
733 return impl_->storage_.frameCount();
737 int AnalysisDataWeightedHistogramModule::flags() const
739 return efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
743 bool AnalysisDataWeightedHistogramModule::parallelDataStarted(AbstractAnalysisData* data,
744 const AnalysisDataParallelOptions& options)
746 addModule(impl_->averager_);
747 const int dataSetCount = data->dataSetCount();
748 const int columnCount = settings().binCount();
749 setDataSetCount(dataSetCount);
750 impl_->accumulator_.setDataSetCount(dataSetCount);
751 for (int i = 0; i < dataSetCount; ++i)
753 setColumnCount(i, columnCount);
754 impl_->accumulator_.setColumnCount(i, columnCount);
756 impl_->accumulator_.init(options);
757 impl_->storage_.startParallelDataStorage(this, &moduleManager(), options);
762 void AnalysisDataWeightedHistogramModule::frameStarted(const AnalysisDataFrameHeader& header)
764 impl_->accumulator_.frameData(header.index()).clear();
768 void AnalysisDataWeightedHistogramModule::pointsAdded(const AnalysisDataPointSetRef& points)
770 if (points.firstColumn() != 0 || points.columnCount() < 2)
772 GMX_THROW(APIError("Invalid data layout"));
774 int bin = settings().findBin(points.y(0));
777 Impl::FrameLocalData::DataSetHandle handle =
778 impl_->accumulator_.frameDataSet(points.frameIndex(), points.dataSetIndex());
779 for (int i = 1; i < points.columnCount(); ++i)
781 handle.value(bin) += points.y(i);
787 void AnalysisDataWeightedHistogramModule::frameFinished(const AnalysisDataFrameHeader& header)
789 Impl::FrameLocalData::FrameHandle handle = impl_->accumulator_.frameData(header.index());
790 AnalysisDataStorageFrame& frame = impl_->storage_.startFrame(header);
791 const int columnCount = settings().binCount();
792 for (int s = 0; s < dataSetCount(); ++s)
794 Impl::FrameLocalData::DataSetHandle dataSet = handle.dataSet(s);
795 frame.selectDataSet(s);
796 for (int i = 0; i < columnCount; ++i)
798 frame.setValue(i, dataSet.value(i));
805 void AnalysisDataWeightedHistogramModule::frameFinishedSerial(int frameIndex)
807 impl_->storage_.finishFrameSerial(frameIndex);
811 void AnalysisDataWeightedHistogramModule::dataFinished()
813 impl_->storage_.finishDataStorage();
817 AnalysisDataFrameRef AnalysisDataWeightedHistogramModule::tryGetDataFrameInternal(int index) const
819 return impl_->storage_.tryGetDataFrame(index);
823 bool AnalysisDataWeightedHistogramModule::requestStorageInternal(int nframes)
825 return impl_->storage_.requestStorage(nframes);
829 /********************************************************************
830 * AnalysisDataBinAverageModule
833 class AnalysisDataBinAverageModule::Impl
837 explicit Impl(const AnalysisHistogramSettings& settings) : settings_(settings) {}
839 //! Histogram settings.
840 AnalysisHistogramSettings settings_;
841 //! Averaging helper objects for each input data set.
842 std::vector<AnalysisDataFrameAverager> averagers_;
845 AnalysisDataBinAverageModule::AnalysisDataBinAverageModule() : impl_(new Impl())
851 AnalysisDataBinAverageModule::AnalysisDataBinAverageModule(const AnalysisHistogramSettings& settings) :
852 impl_(new Impl(settings))
854 setRowCount(settings.binCount());
855 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(), settings.binWidth());
859 AnalysisDataBinAverageModule::~AnalysisDataBinAverageModule() {}
862 void AnalysisDataBinAverageModule::init(const AnalysisHistogramSettings& settings)
864 impl_->settings_ = settings;
865 setRowCount(settings.binCount());
866 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(), settings.binWidth());
870 const AnalysisHistogramSettings& AnalysisDataBinAverageModule::settings() const
872 return impl_->settings_;
876 int AnalysisDataBinAverageModule::flags() const
878 return efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
882 void AnalysisDataBinAverageModule::dataStarted(AbstractAnalysisData* data)
884 setColumnCount(data->dataSetCount());
885 impl_->averagers_.resize(data->dataSetCount());
886 for (int i = 0; i < data->dataSetCount(); ++i)
888 impl_->averagers_[i].setColumnCount(rowCount());
893 void AnalysisDataBinAverageModule::frameStarted(const AnalysisDataFrameHeader& /*header*/) {}
896 void AnalysisDataBinAverageModule::pointsAdded(const AnalysisDataPointSetRef& points)
898 if (points.firstColumn() != 0 || points.columnCount() < 2)
900 GMX_THROW(APIError("Invalid data layout"));
902 int bin = settings().findBin(points.y(0));
905 AnalysisDataFrameAverager& averager = impl_->averagers_[points.dataSetIndex()];
906 for (int i = 1; i < points.columnCount(); ++i)
908 averager.addValue(bin, points.y(i));
914 void AnalysisDataBinAverageModule::frameFinished(const AnalysisDataFrameHeader& /*header*/) {}
917 void AnalysisDataBinAverageModule::dataFinished()
920 for (int i = 0; i < columnCount(); ++i)
922 AnalysisDataFrameAverager& averager = impl_->averagers_[i];
924 for (int j = 0; j < rowCount(); ++j)
926 value(j, i).setValue(averager.average(j), std::sqrt(averager.variance(j)));