2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, 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() :
93 /********************************************************************
94 * AnalysisHistogramSettings
97 AnalysisHistogramSettings::AnalysisHistogramSettings() :
101 inverseBinWidth_(0.0),
108 AnalysisHistogramSettings::AnalysisHistogramSettings(const AnalysisHistogramSettingsInitializer& settings)
110 GMX_RELEASE_ASSERT(isDefined(settings.min_), "Histogram start value must be defined");
111 GMX_RELEASE_ASSERT(!isDefined(settings.max_) || settings.max_ > settings.min_,
112 "Histogram end value must be larger than start value");
113 GMX_RELEASE_ASSERT(!isDefined(settings.binWidth_) || settings.binWidth_ > 0.0,
114 "Histogram bin width must be positive");
115 GMX_RELEASE_ASSERT(settings.binCount_ >= 0, "Histogram bin count must be positive");
117 if (!isDefined(settings.max_))
119 GMX_RELEASE_ASSERT(isDefined(settings.binWidth_) && settings.binCount_ > 0,
120 "Not all required values provided");
121 GMX_RELEASE_ASSERT(!settings.bRoundRange_, "Rounding only supported for min/max ranges");
123 firstEdge_ = settings.min_;
124 binCount_ = settings.binCount_;
125 binWidth_ = settings.binWidth_;
126 if (settings.bIntegerBins_)
128 firstEdge_ -= 0.5 * binWidth_;
130 lastEdge_ = firstEdge_ + binCount_ * binWidth_;
134 GMX_RELEASE_ASSERT(!(isDefined(settings.binWidth_) && settings.binCount_ > 0),
135 "Conflicting histogram bin specifications");
136 GMX_RELEASE_ASSERT(isDefined(settings.binWidth_) || settings.binCount_ > 0,
137 "Not all required values provided");
139 if (settings.bRoundRange_)
141 GMX_RELEASE_ASSERT(!settings.bIntegerBins_,
142 "Rounding and integer bins cannot be combined");
143 GMX_RELEASE_ASSERT(isDefined(settings.binWidth_),
144 "Rounding only makes sense with defined binwidth");
145 binWidth_ = settings.binWidth_;
146 firstEdge_ = binWidth_ * std::floor(settings.min_ / binWidth_);
147 lastEdge_ = binWidth_ * std::ceil(settings.max_ / binWidth_);
148 binCount_ = gmx::roundToInt((lastEdge_ - firstEdge_) / binWidth_);
152 firstEdge_ = settings.min_;
153 lastEdge_ = settings.max_;
154 if (settings.binCount_ > 0)
156 binCount_ = settings.binCount_;
157 if (settings.bIntegerBins_)
159 GMX_RELEASE_ASSERT(settings.binCount_ > 1,
160 "Bin count must be at least two with integer bins");
161 binWidth_ = (lastEdge_ - firstEdge_) / (binCount_ - 1);
162 firstEdge_ -= 0.5 * binWidth_;
163 lastEdge_ += 0.5 * binWidth_;
167 binWidth_ = (lastEdge_ - firstEdge_) / binCount_;
172 binWidth_ = settings.binWidth_;
173 binCount_ = gmx::roundToInt((lastEdge_ - firstEdge_) / binWidth_);
174 if (settings.bIntegerBins_)
176 firstEdge_ -= 0.5 * binWidth_;
179 lastEdge_ = firstEdge_ + binCount_ * binWidth_;
184 inverseBinWidth_ = 1.0 / binWidth_;
185 bAll_ = settings.bIncludeAll_;
189 int AnalysisHistogramSettings::findBin(real y) const
193 return bAll_ ? 0 : -1;
195 int bin = static_cast<int>((y - firstEdge_) * inverseBinWidth_);
196 if (bin >= binCount_)
198 return bAll_ ? binCount_ - 1 : -1;
204 /********************************************************************
205 * StaticAverageHistogram
212 * Represents copies of average histograms.
214 * Methods in AbstractAverageHistogram that return new histogram instances
215 * return objects of this class.
216 * Initialization of values is handled in those methods.
218 * \ingroup module_analysisdata
220 class StaticAverageHistogram : public AbstractAverageHistogram
223 StaticAverageHistogram();
224 //! Creates an average histogram module with defined bin parameters.
225 explicit StaticAverageHistogram(const AnalysisHistogramSettings& settings);
227 // Copy and assign disallowed by base.
230 StaticAverageHistogram::StaticAverageHistogram() {}
233 StaticAverageHistogram::StaticAverageHistogram(const AnalysisHistogramSettings& settings) :
234 AbstractAverageHistogram(settings)
241 /********************************************************************
242 * AbstractAverageHistogram
245 AbstractAverageHistogram::AbstractAverageHistogram() {}
248 AbstractAverageHistogram::AbstractAverageHistogram(const AnalysisHistogramSettings& settings) :
251 setRowCount(settings.binCount());
252 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(), settings.binWidth());
256 AbstractAverageHistogram::~AbstractAverageHistogram() {}
259 void AbstractAverageHistogram::init(const AnalysisHistogramSettings& settings)
261 settings_ = settings;
262 setRowCount(settings.binCount());
263 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(), settings.binWidth());
267 AverageHistogramPointer AbstractAverageHistogram::resampleDoubleBinWidth(bool bIntegerBins) const
272 nbins = (rowCount() + 1) / 2;
276 nbins = rowCount() / 2;
279 AverageHistogramPointer dest(new StaticAverageHistogram(
280 histogramFromBins(settings().firstEdge(), nbins, 2 * xstep()).integerBins(bIntegerBins)));
281 dest->setColumnCount(columnCount());
282 dest->allocateValues();
285 for (i = j = 0; i < nbins; ++i)
287 const bool bFirstHalfBin = (bIntegerBins && i == 0);
288 for (int c = 0; c < columnCount(); ++c)
294 v1 = value(0, c).value();
295 e1 = value(0, c).error();
301 v1 = value(j, c).value();
302 e1 = value(j, c).error();
303 v2 = value(j + 1, c).value();
304 e2 = value(j + 1, c).error();
306 dest->value(i, c).setValue(v1 + v2, std::sqrt(e1 * e1 + e2 * e2));
321 AverageHistogramPointer AbstractAverageHistogram::clone() const
323 AverageHistogramPointer dest(new StaticAverageHistogram());
324 copyContents(this, dest.get());
325 dest->settings_ = settings_;
330 void AbstractAverageHistogram::normalizeProbability()
332 for (int c = 0; c < columnCount(); ++c)
335 for (int i = 0; i < rowCount(); ++i)
337 sum += value(i, c).value();
341 scaleSingle(c, 1.0 / (sum * xstep()));
346 void AbstractAverageHistogram::makeCumulative()
348 for (int c = 0; c < columnCount(); ++c)
351 for (int i = 0; i < rowCount(); ++i)
353 sum += value(i, c).value();
354 // Clear the error, as we don't cumulate that.
356 value(i, c).setValue(sum);
359 setXAxis(settings().firstEdge() + settings().binWidth(), settings().binWidth());
363 void AbstractAverageHistogram::scaleSingle(int index, real factor)
365 for (int i = 0; i < rowCount(); ++i)
367 value(i, index).value() *= factor;
368 value(i, index).error() *= factor;
373 void AbstractAverageHistogram::scaleAll(real factor)
375 for (int i = 0; i < columnCount(); ++i)
377 scaleSingle(i, factor);
382 void AbstractAverageHistogram::scaleAllByVector(const real factor[])
384 for (int c = 0; c < columnCount(); ++c)
386 for (int i = 0; i < rowCount(); ++i)
388 value(i, c).value() *= factor[i];
389 value(i, c).error() *= factor[i];
395 /********************************************************************
396 * BasicAverageHistogramModule
404 * Implements average histogram module that averages per-frame histograms.
406 * This class is used for accumulating average histograms in per-frame
407 * histogram modules (those that use BasicHistogramImpl as their implementation
409 * There are two columns, first for the average and second for standard
412 * \ingroup module_analysisdata
414 class BasicAverageHistogramModule : public AbstractAverageHistogram, public AnalysisDataModuleSerial
417 BasicAverageHistogramModule();
418 //! Creates an average histogram module with defined bin parameters.
419 explicit BasicAverageHistogramModule(const AnalysisHistogramSettings& settings);
421 using AbstractAverageHistogram::init;
423 int flags() const override;
425 void dataStarted(AbstractAnalysisData* data) override;
426 void frameStarted(const AnalysisDataFrameHeader& header) override;
427 void pointsAdded(const AnalysisDataPointSetRef& points) override;
428 void frameFinished(const AnalysisDataFrameHeader& header) override;
429 void dataFinished() override;
432 //! Averaging helper objects for each input data set.
433 std::vector<AnalysisDataFrameAverager> averagers_;
435 // Copy and assign disallowed by base.
438 BasicAverageHistogramModule::BasicAverageHistogramModule() {}
441 BasicAverageHistogramModule::BasicAverageHistogramModule(const AnalysisHistogramSettings& settings) :
442 AbstractAverageHistogram(settings)
447 int BasicAverageHistogramModule::flags() const
449 return efAllowMulticolumn | efAllowMultipleDataSets;
453 void BasicAverageHistogramModule::dataStarted(AbstractAnalysisData* data)
455 setColumnCount(data->dataSetCount());
456 averagers_.resize(data->dataSetCount());
457 for (int i = 0; i < data->dataSetCount(); ++i)
459 GMX_RELEASE_ASSERT(rowCount() == data->columnCount(i),
460 "Inconsistent data sizes, something is wrong in the initialization");
461 averagers_[i].setColumnCount(data->columnCount(i));
466 void BasicAverageHistogramModule::frameStarted(const AnalysisDataFrameHeader& /*header*/) {}
469 void BasicAverageHistogramModule::pointsAdded(const AnalysisDataPointSetRef& points)
471 averagers_[points.dataSetIndex()].addPoints(points);
475 void BasicAverageHistogramModule::frameFinished(const AnalysisDataFrameHeader& /*header*/) {}
478 void BasicAverageHistogramModule::dataFinished()
481 for (int i = 0; i < columnCount(); ++i)
483 averagers_[i].finish();
484 for (int j = 0; j < rowCount(); ++j)
486 value(j, i).setValue(averagers_[i].average(j), std::sqrt(averagers_[i].variance(j)));
492 /********************************************************************
498 * Base class for private implementation classes for histogram modules.
500 * Actual implementation classes are derived from this and add an accumulation
501 * data member that is specific to the histogram type in question.
502 * This is done like this to keep implementation details out of the header, and
503 * to not unnecessarily duplicate code.
505 * \ingroup module_analysisdata
507 class BasicHistogramImpl
510 //! Smart pointer to manage an BasicAverageHistogramModule object.
511 typedef std::shared_ptr<BasicAverageHistogramModule> BasicAverageHistogramModulePointer;
513 BasicHistogramImpl();
514 //! Creates an histogram impl with defined bin parameters.
515 explicit BasicHistogramImpl(const AnalysisHistogramSettings& settings);
516 // Virtual only for simplicity.
517 virtual ~BasicHistogramImpl();
520 * (Re)initializes the histogram from settings.
522 void init(const AnalysisHistogramSettings& settings);
524 //! Storage implementation object.
525 AnalysisDataStorage storage_;
526 //! Settings for the histogram object.
527 AnalysisHistogramSettings settings_;
529 BasicAverageHistogramModulePointer averager_;
532 BasicHistogramImpl::BasicHistogramImpl() : averager_(new BasicAverageHistogramModule()) {}
535 BasicHistogramImpl::BasicHistogramImpl(const AnalysisHistogramSettings& settings) :
537 averager_(new BasicAverageHistogramModule(settings))
542 BasicHistogramImpl::~BasicHistogramImpl() {}
545 void BasicHistogramImpl::init(const AnalysisHistogramSettings& settings)
547 settings_ = settings;
548 averager_->init(settings);
551 } // namespace internal
554 /********************************************************************
555 * AnalysisDataSimpleHistogramModule
559 * Private implementation class for AnalysisDataSimpleHistogramModule.
561 * \ingroup module_analysisdata
563 class AnalysisDataSimpleHistogramModule::Impl : public internal::BasicHistogramImpl
566 //! Shorthand for the per-frame accumulation data structure type.
567 typedef AnalysisDataFrameLocalData<int64_t> FrameLocalData;
570 //! Creates an histogram impl with defined bin parameters.
571 explicit Impl(const AnalysisHistogramSettings& settings) : BasicHistogramImpl(settings) {}
573 //! Accumulates the histogram within a frame.
574 FrameLocalData accumulator_;
577 AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule() : impl_(new Impl()) {}
580 AnalysisDataSimpleHistogramModule::AnalysisDataSimpleHistogramModule(const AnalysisHistogramSettings& settings) :
581 impl_(new Impl(settings))
586 AnalysisDataSimpleHistogramModule::~AnalysisDataSimpleHistogramModule() {}
589 void AnalysisDataSimpleHistogramModule::init(const AnalysisHistogramSettings& settings)
591 impl_->init(settings);
595 AbstractAverageHistogram& AnalysisDataSimpleHistogramModule::averager()
597 return *impl_->averager_;
601 const AnalysisHistogramSettings& AnalysisDataSimpleHistogramModule::settings() const
603 return impl_->settings_;
607 int AnalysisDataSimpleHistogramModule::frameCount() const
609 return impl_->storage_.frameCount();
613 int AnalysisDataSimpleHistogramModule::flags() const
615 return efAllowMulticolumn | efAllowMultipoint | efAllowMissing | efAllowMultipleDataSets;
619 bool AnalysisDataSimpleHistogramModule::parallelDataStarted(AbstractAnalysisData* data,
620 const AnalysisDataParallelOptions& options)
622 addModule(impl_->averager_);
623 const int dataSetCount = data->dataSetCount();
624 const int columnCount = settings().binCount();
625 setDataSetCount(dataSetCount);
626 impl_->accumulator_.setDataSetCount(dataSetCount);
627 for (int i = 0; i < dataSetCount; ++i)
629 setColumnCount(i, columnCount);
630 impl_->accumulator_.setColumnCount(i, columnCount);
632 impl_->accumulator_.init(options);
633 impl_->storage_.startParallelDataStorage(this, &moduleManager(), options);
638 void AnalysisDataSimpleHistogramModule::frameStarted(const AnalysisDataFrameHeader& header)
640 impl_->accumulator_.frameData(header.index()).clear();
644 void AnalysisDataSimpleHistogramModule::pointsAdded(const AnalysisDataPointSetRef& points)
646 Impl::FrameLocalData::DataSetHandle handle =
647 impl_->accumulator_.frameDataSet(points.frameIndex(), points.dataSetIndex());
648 for (int i = 0; i < points.columnCount(); ++i)
650 if (points.present(i))
652 const int bin = settings().findBin(points.y(i));
655 handle.value(bin) += 1;
662 void AnalysisDataSimpleHistogramModule::frameFinished(const AnalysisDataFrameHeader& header)
664 Impl::FrameLocalData::FrameHandle handle = impl_->accumulator_.frameData(header.index());
665 AnalysisDataStorageFrame& frame = impl_->storage_.startFrame(header);
666 const int columnCount = settings().binCount();
667 for (int s = 0; s < dataSetCount(); ++s)
669 Impl::FrameLocalData::DataSetHandle dataSet = handle.dataSet(s);
670 frame.selectDataSet(s);
671 for (int i = 0; i < columnCount; ++i)
673 frame.setValue(i, dataSet.value(i));
680 void AnalysisDataSimpleHistogramModule::frameFinishedSerial(int frameIndex)
682 impl_->storage_.finishFrameSerial(frameIndex);
686 void AnalysisDataSimpleHistogramModule::dataFinished()
688 impl_->storage_.finishDataStorage();
692 AnalysisDataFrameRef AnalysisDataSimpleHistogramModule::tryGetDataFrameInternal(int index) const
694 return impl_->storage_.tryGetDataFrame(index);
698 bool AnalysisDataSimpleHistogramModule::requestStorageInternal(int nframes)
700 return impl_->storage_.requestStorage(nframes);
704 /********************************************************************
705 * AnalysisDataWeightedHistogramModule
709 * Private implementation class for AnalysisDataWeightedHistogramModule.
711 * \ingroup module_analysisdata
713 class AnalysisDataWeightedHistogramModule::Impl : public internal::BasicHistogramImpl
716 //! Shorthand for the per-frame accumulation data structure type.
717 typedef AnalysisDataFrameLocalData<double> FrameLocalData;
720 //! Creates an histogram impl with defined bin parameters.
721 explicit Impl(const AnalysisHistogramSettings& settings) : BasicHistogramImpl(settings) {}
723 //! Accumulates the histogram within a frame.
724 FrameLocalData accumulator_;
727 AnalysisDataWeightedHistogramModule::AnalysisDataWeightedHistogramModule() : impl_(new Impl()) {}
730 AnalysisDataWeightedHistogramModule::AnalysisDataWeightedHistogramModule(const AnalysisHistogramSettings& settings) :
731 impl_(new Impl(settings))
736 AnalysisDataWeightedHistogramModule::~AnalysisDataWeightedHistogramModule() {}
739 void AnalysisDataWeightedHistogramModule::init(const AnalysisHistogramSettings& settings)
741 impl_->init(settings);
745 AbstractAverageHistogram& AnalysisDataWeightedHistogramModule::averager()
747 return *impl_->averager_;
751 const AnalysisHistogramSettings& AnalysisDataWeightedHistogramModule::settings() const
753 return impl_->settings_;
757 int AnalysisDataWeightedHistogramModule::frameCount() const
759 return impl_->storage_.frameCount();
763 int AnalysisDataWeightedHistogramModule::flags() const
765 return efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
769 bool AnalysisDataWeightedHistogramModule::parallelDataStarted(AbstractAnalysisData* data,
770 const AnalysisDataParallelOptions& options)
772 addModule(impl_->averager_);
773 const int dataSetCount = data->dataSetCount();
774 const int columnCount = settings().binCount();
775 setDataSetCount(dataSetCount);
776 impl_->accumulator_.setDataSetCount(dataSetCount);
777 for (int i = 0; i < dataSetCount; ++i)
779 setColumnCount(i, columnCount);
780 impl_->accumulator_.setColumnCount(i, columnCount);
782 impl_->accumulator_.init(options);
783 impl_->storage_.startParallelDataStorage(this, &moduleManager(), options);
788 void AnalysisDataWeightedHistogramModule::frameStarted(const AnalysisDataFrameHeader& header)
790 impl_->accumulator_.frameData(header.index()).clear();
794 void AnalysisDataWeightedHistogramModule::pointsAdded(const AnalysisDataPointSetRef& points)
796 if (points.firstColumn() != 0 || points.columnCount() < 2)
798 GMX_THROW(APIError("Invalid data layout"));
800 int bin = settings().findBin(points.y(0));
803 Impl::FrameLocalData::DataSetHandle handle =
804 impl_->accumulator_.frameDataSet(points.frameIndex(), points.dataSetIndex());
805 for (int i = 1; i < points.columnCount(); ++i)
807 handle.value(bin) += points.y(i);
813 void AnalysisDataWeightedHistogramModule::frameFinished(const AnalysisDataFrameHeader& header)
815 Impl::FrameLocalData::FrameHandle handle = impl_->accumulator_.frameData(header.index());
816 AnalysisDataStorageFrame& frame = impl_->storage_.startFrame(header);
817 const int columnCount = settings().binCount();
818 for (int s = 0; s < dataSetCount(); ++s)
820 Impl::FrameLocalData::DataSetHandle dataSet = handle.dataSet(s);
821 frame.selectDataSet(s);
822 for (int i = 0; i < columnCount; ++i)
824 frame.setValue(i, dataSet.value(i));
831 void AnalysisDataWeightedHistogramModule::frameFinishedSerial(int frameIndex)
833 impl_->storage_.finishFrameSerial(frameIndex);
837 void AnalysisDataWeightedHistogramModule::dataFinished()
839 impl_->storage_.finishDataStorage();
843 AnalysisDataFrameRef AnalysisDataWeightedHistogramModule::tryGetDataFrameInternal(int index) const
845 return impl_->storage_.tryGetDataFrame(index);
849 bool AnalysisDataWeightedHistogramModule::requestStorageInternal(int nframes)
851 return impl_->storage_.requestStorage(nframes);
855 /********************************************************************
856 * AnalysisDataBinAverageModule
859 class AnalysisDataBinAverageModule::Impl
863 explicit Impl(const AnalysisHistogramSettings& settings) : settings_(settings) {}
865 //! Histogram settings.
866 AnalysisHistogramSettings settings_;
867 //! Averaging helper objects for each input data set.
868 std::vector<AnalysisDataFrameAverager> averagers_;
871 AnalysisDataBinAverageModule::AnalysisDataBinAverageModule() : impl_(new Impl())
877 AnalysisDataBinAverageModule::AnalysisDataBinAverageModule(const AnalysisHistogramSettings& settings) :
878 impl_(new Impl(settings))
880 setRowCount(settings.binCount());
881 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(), settings.binWidth());
885 AnalysisDataBinAverageModule::~AnalysisDataBinAverageModule() {}
888 void AnalysisDataBinAverageModule::init(const AnalysisHistogramSettings& settings)
890 impl_->settings_ = settings;
891 setRowCount(settings.binCount());
892 setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(), settings.binWidth());
896 const AnalysisHistogramSettings& AnalysisDataBinAverageModule::settings() const
898 return impl_->settings_;
902 int AnalysisDataBinAverageModule::flags() const
904 return efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
908 void AnalysisDataBinAverageModule::dataStarted(AbstractAnalysisData* data)
910 setColumnCount(data->dataSetCount());
911 impl_->averagers_.resize(data->dataSetCount());
912 for (int i = 0; i < data->dataSetCount(); ++i)
914 impl_->averagers_[i].setColumnCount(rowCount());
919 void AnalysisDataBinAverageModule::frameStarted(const AnalysisDataFrameHeader& /*header*/) {}
922 void AnalysisDataBinAverageModule::pointsAdded(const AnalysisDataPointSetRef& points)
924 if (points.firstColumn() != 0 || points.columnCount() < 2)
926 GMX_THROW(APIError("Invalid data layout"));
928 int bin = settings().findBin(points.y(0));
931 AnalysisDataFrameAverager& averager = impl_->averagers_[points.dataSetIndex()];
932 for (int i = 1; i < points.columnCount(); ++i)
934 averager.addValue(bin, points.y(i));
940 void AnalysisDataBinAverageModule::frameFinished(const AnalysisDataFrameHeader& /*header*/) {}
943 void AnalysisDataBinAverageModule::dataFinished()
946 for (int i = 0; i < columnCount(); ++i)
948 AnalysisDataFrameAverager& averager = impl_->averagers_[i];
950 for (int j = 0; j < rowCount(); ++j)
952 value(j, i).setValue(averager.average(j), std::sqrt(averager.variance(j)));