Support for multiple analysis data sets in modules.
authorTeemu Murtola <teemu.murtola@gmail.com>
Wed, 12 Jun 2013 17:49:20 +0000 (20:49 +0300)
committerGerrit Code Review <gerrit@gerrit.gromacs.org>
Sun, 11 Aug 2013 11:56:26 +0000 (13:56 +0200)
Main changes:
- Support for multiple data sets in the input data for most analysisdata
  modules.  For the clearest output, standard deviation values were
  moved from a separate column into the error value instead, which
  required updating a lot of unit test reference data.
- Support for computing multiple sets of angles using 'gmx gangle'.
- Extend the analysis data test utilities to handle multiple data sets
  when comparing against reference data.
- Add some unit tests for the new functionality.

Supporting changes:
- Add support for providing error values through AnalysisDataTestInput.
- AbstractArrayData now provides the means to use the full functionality
  of AnalysisDataValue for constructing the data.  AnalysisDataValue
  objects were already used internally for storage, so this amounts to
  exposing accessors for those objects instead of wrapping them in
  simple setters/getters for the value only.

Part of #1010.

Change-Id: I63abc05ab7e24362169e7d9ba0fa6ffc561be9d6

40 files changed:
src/gromacs/analysisdata/arraydata.h
src/gromacs/analysisdata/modules/average.cpp
src/gromacs/analysisdata/modules/average.h
src/gromacs/analysisdata/modules/histogram.cpp
src/gromacs/analysisdata/modules/histogram.h
src/gromacs/analysisdata/modules/plot.cpp
src/gromacs/analysisdata/modules/plot.h
src/gromacs/analysisdata/tests/average.cpp
src/gromacs/analysisdata/tests/histogram.cpp
src/gromacs/analysisdata/tests/refdata/AbstractAverageHistogramTest_ResamplesAtDoubleBinWidth.xml
src/gromacs/analysisdata/tests/refdata/AbstractAverageHistogramTest_ResamplesAtDoubleBinWidthWithIntegerBins.xml
src/gromacs/analysisdata/tests/refdata/AverageModuleTest_BasicTest.xml
src/gromacs/analysisdata/tests/refdata/AverageModuleTest_CanCustomizeXAxis.xml
src/gromacs/analysisdata/tests/refdata/AverageModuleTest_HandlesMultipointData.xml
src/gromacs/analysisdata/tests/refdata/BinAverageModuleTest_ComputesCorrectly.xml
src/gromacs/analysisdata/tests/refdata/BinAverageModuleTest_ComputesCorrectlyWithAll.xml
src/gromacs/analysisdata/tests/refdata/BinAverageModuleTest_HandlesMultipleDataSets.xml [new file with mode: 0644]
src/gromacs/analysisdata/tests/refdata/FrameAverageModuleTest_BasicTest.xml
src/gromacs/analysisdata/tests/refdata/FrameAverageModuleTest_HandlesMultipleDataSets.xml [new file with mode: 0644]
src/gromacs/analysisdata/tests/refdata/SimpleHistogramModuleTest_ComputesCorrectly.xml
src/gromacs/analysisdata/tests/refdata/SimpleHistogramModuleTest_ComputesCorrectlyWithAll.xml
src/gromacs/analysisdata/tests/refdata/WeightedHistogramModuleTest_ComputesCorrectly.xml
src/gromacs/analysisdata/tests/refdata/WeightedHistogramModuleTest_ComputesCorrectlyWithAll.xml
src/gromacs/analysisdata/tests/refdata/WeightedHistogramModuleTest_HandlesMultipleDataSets.xml [new file with mode: 0644]
src/gromacs/analysisdata/tests/refdata/analysisdata-referencedata.xsl
src/gromacs/trajectoryanalysis/modules/angle.cpp
src/gromacs/trajectoryanalysis/tests/angle.cpp
src/gromacs/trajectoryanalysis/tests/refdata/AngleModuleTest_ComputesDihedrals.xml
src/gromacs/trajectoryanalysis/tests/refdata/AngleModuleTest_ComputesMultipleAngles.xml [new file with mode: 0644]
src/gromacs/trajectoryanalysis/tests/refdata/AngleModuleTest_ComputesPlaneZAxisAngles.xml
src/gromacs/trajectoryanalysis/tests/refdata/AngleModuleTest_ComputesSimpleAngles.xml
src/gromacs/trajectoryanalysis/tests/refdata/AngleModuleTest_ComputesVectorPairAngles.xml
src/gromacs/trajectoryanalysis/tests/refdata/AngleModuleTest_ComputesVectorPlanePairAngles.xml
src/gromacs/trajectoryanalysis/tests/refdata/AngleModuleTest_ComputesVectorSphereNormalZAxisAngles.xml
src/gromacs/trajectoryanalysis/tests/refdata/AngleModuleTest_ComputesVectorTimeZeroAngles.xml
src/gromacs/trajectoryanalysis/tests/refdata/analysisdata-referencedata.xsl
src/testutils/analysisdata-referencedata.xsl
src/testutils/datatest.cpp
src/testutils/datatest.h
src/testutils/mock_datamodule.cpp

index 8febbc7ee78829486c9954236cb9792aca71ba1f..f4f66096f4ccbdfbd7a22c45370986f831958660 100644 (file)
@@ -66,9 +66,6 @@ namespace gmx
  * accessed before it is available.
  *
  * \todo
- * Add methods to take full advantage of AnalysisDataValue features.
- *
- * \todo
  * Add support for multiple data sets.
  *
  * \inlibraryapi
@@ -99,12 +96,12 @@ class AbstractAnalysisArrayData : public AbstractAnalysisData
             return xstart() + row * xstep();
         }
         //! Returns a given array element.
-        real value(int row, int col) const
+        const AnalysisDataValue &value(int row, int col) const
         {
             GMX_ASSERT(row >= 0 && row < rowCount(), "Row index out of range");
             GMX_ASSERT(col >= 0 && col < columnCount(), "Column index out of range");
             GMX_ASSERT(isAllocated(), "Data array not allocated");
-            return value_[row * columnCount() + col].value();
+            return value_[row * columnCount() + col];
         }
 
     protected:
@@ -157,25 +154,12 @@ class AbstractAnalysisArrayData : public AbstractAnalysisData
          */
         void setXAxis(real start, real step);
         //! Returns a reference to a given array element.
-        real &value(int row, int col)
+        AnalysisDataValue &value(int row, int col)
         {
             GMX_ASSERT(row >= 0 && row < rowCount(), "Row index out of range");
             GMX_ASSERT(col >= 0 && col < columnCount(), "Column index out of range");
             GMX_ASSERT(isAllocated(), "Data array not allocated");
-            return value_[row * columnCount() + col].value();
-        }
-        /*! \brief
-         * Sets the value of an element in the array.
-         *
-         * \param[in] row  Zero-based row index for the value.
-         * \param[in] col  Zero-based column index for the value.
-         * \param[in] val  Value to set in the given location.
-         *
-         * Does not throw.
-         */
-        void setValue(int row, int col, real val)
-        {
-            value(row, col) = val;
+            return value_[row * columnCount() + col];
         }
         /*! \brief
          * Notifies modules of the data.
@@ -249,7 +233,6 @@ class AnalysisArrayData : public AbstractAnalysisArrayData
         using AbstractAnalysisArrayData::allocateValues;
         using AbstractAnalysisArrayData::setXAxis;
         using AbstractAnalysisArrayData::value;
-        using AbstractAnalysisArrayData::setValue;
         using AbstractAnalysisArrayData::valuesReady;
 
         // Copy and assign disallowed by base.
index 61cf7454c85f979037abddf6395a3a2024cba307..43f65f5d922dbc73fd8f1f506c1e2a0b4c83cee3 100644 (file)
@@ -43,6 +43,8 @@
 
 #include <cmath>
 
+#include <vector>
+
 #include "gromacs/analysisdata/dataframe.h"
 #include "gromacs/analysisdata/datastorage.h"
 
@@ -109,8 +111,8 @@ AnalysisDataAverageModule::dataFinished()
     allocateValues();
     for (int i = 0; i < rowCount(); ++i)
     {
-        setValue(i, 0, impl_->averager_.average(i));
-        setValue(i, 1, sqrt(impl_->averager_.variance(i)));
+        value(i, 0).setValue(impl_->averager_.average(i));
+        value(i, 1).setValue(std::sqrt(impl_->averager_.variance(i)));
     }
     valuesReady();
 }
@@ -118,13 +120,13 @@ AnalysisDataAverageModule::dataFinished()
 real
 AnalysisDataAverageModule::average(int index) const
 {
-    return value(index, 0);
+    return value(index, 0).value();
 }
 
 real
 AnalysisDataAverageModule::stddev(int index) const
 {
-    return value(index, 1);
+    return value(index, 1).value();
 }
 
 
@@ -137,14 +139,13 @@ class AnalysisDataFrameAverageModule::Impl
     public:
         //! Storage implementation object.
         AnalysisDataStorage     storage_;
-        //! Number of samples in a frame.
-        int                     sampleCount_;
+        //! Number of samples in a frame for each data set.
+        std::vector<int>        sampleCount_;
 };
 
 AnalysisDataFrameAverageModule::AnalysisDataFrameAverageModule()
     : impl_(new Impl())
 {
-    setColumnCount(0, 1);
 }
 
 AnalysisDataFrameAverageModule::~AnalysisDataFrameAverageModule()
@@ -154,12 +155,15 @@ AnalysisDataFrameAverageModule::~AnalysisDataFrameAverageModule()
 int
 AnalysisDataFrameAverageModule::flags() const
 {
-    return efAllowMultipoint | efAllowMulticolumn | efAllowMissing;
+    return efAllowMultipoint | efAllowMulticolumn | efAllowMissing
+           | efAllowMultipleDataSets;
 }
 
 void
 AnalysisDataFrameAverageModule::dataStarted(AbstractAnalysisData *data)
 {
+    setColumnCount(0, data->dataSetCount());
+    impl_->sampleCount_.resize(data->dataSetCount());
     notifyDataStart();
     impl_->storage_.startDataStorage(this);
 }
@@ -167,23 +171,29 @@ AnalysisDataFrameAverageModule::dataStarted(AbstractAnalysisData *data)
 void
 AnalysisDataFrameAverageModule::frameStarted(const AnalysisDataFrameHeader &header)
 {
-    impl_->sampleCount_ = 0;
     AnalysisDataStorageFrame &frame = impl_->storage_.startFrame(header);
-    frame.setValue(0, 0.0);
+    for (int i = 0; i < columnCount(); ++i)
+    {
+        impl_->sampleCount_[i] = 0;
+        frame.setValue(i, 0.0);
+    }
 }
 
 void
 AnalysisDataFrameAverageModule::pointsAdded(const AnalysisDataPointSetRef &points)
 {
-    AnalysisDataStorageFrame &frame =
+    const int                 dataSet = points.dataSetIndex();
+    AnalysisDataStorageFrame &frame   =
         impl_->storage_.currentFrame(points.frameIndex());
     for (int i = 0; i < points.columnCount(); ++i)
     {
         if (points.present(i))
         {
-            const real y = points.y(i);
-            frame.value(0)      += y;
-            impl_->sampleCount_ += 1;
+            // TODO: Consider using AnalysisDataFrameAverager
+            const real y     = points.y(i);
+            const real delta = y - frame.value(dataSet);
+            impl_->sampleCount_[dataSet] += 1;
+            frame.value(dataSet)         += delta / impl_->sampleCount_[dataSet];
         }
     }
 }
@@ -191,13 +201,6 @@ AnalysisDataFrameAverageModule::pointsAdded(const AnalysisDataPointSetRef &point
 void
 AnalysisDataFrameAverageModule::frameFinished(const AnalysisDataFrameHeader &header)
 {
-    AnalysisDataStorageFrame &frame =
-        impl_->storage_.currentFrame(header.index());
-    const int                 samples = impl_->sampleCount_;
-    if (samples > 0)
-    {
-        frame.value(0) /= samples;
-    }
     impl_->storage_.finishFrame(header.index());
 }
 
index 999fb01f99a6699e2ce0a2a7714ef17522b6bc82..6ef3464b4f82083c38af4c53bd99dee9fb4c0b87 100644 (file)
@@ -60,6 +60,7 @@ namespace gmx
  * the input data.  Multipoint data and missing data points are both supported.
  * The average is always calculated over all frames and data points for a
  * column.
+ * Multiple input data sets are currently not supported.
  *
  * Output data contains a frame for each column in the input data.
  * The first column of each output frame is the average of the corresponding
@@ -109,13 +110,15 @@ typedef boost::shared_ptr<AnalysisDataAverageModule>
 /*! \brief
  * Data module for averaging of columns for each frame.
  *
- * Output data has the same number of frames as the input data, but only one
- * column.
- * Each frame in the output contains the average of the column values in the
- * corresponding frame of the input data.
+ * Output data has the same number of frames as the input data.
+ * The number of columns in the output data is the same as the number of data
+ * sets in the input data.
+ * Each frame in the output contains the average of the column values for each
+ * data set in the corresponding frame of the input data.
  *
- * Multipoint data and missing data points are both supported. The average
- * is always calculated over all data points present in a column.
+ * Multipoint data and missing data points are both supported.  The average
+ * is always calculated over all data points present in a column for a data
+ * set.
  *
  * \inpublicapi
  * \ingroup module_analysisdata
index bdac5127c42a561c309e62a150aec27f2d7fc5c1..2afc2368b69ed9427b0558c6e6b5c8b4a6410cee 100644 (file)
@@ -44,6 +44,7 @@
 #include <cmath>
 
 #include <limits>
+#include <vector>
 
 #include "gromacs/analysisdata/dataframe.h"
 #include "gromacs/analysisdata/datastorage.h"
@@ -293,24 +294,22 @@ AbstractAverageHistogram::resampleDoubleBinWidth(bool bIntegerBins) const
         for (int c = 0; c < columnCount(); ++c)
         {
             real  v1, v2;
+            real  e1, e2;
             if (bFirstHalfBin)
             {
-                v1 = value(0, c);
+                v1 = value(0, c).value();
+                e1 = value(0, c).error();
                 v2 = 0;
+                e2 = 0;
             }
             else
             {
-                v1 = value(j, c);
-                v2 = value(j + 1, c);
-            }
-            if (c == 1)
-            {
-                dest->setValue(i, c, sqrt(v1 * v1 + v2 * v2));
-            }
-            else
-            {
-                dest->setValue(i, c, v1 + v2);
+                v1 = value(j, c).value();
+                e1 = value(j, c).error();
+                v2 = value(j + 1, c).value();
+                e2 = value(j + 1, c).error();
             }
+            dest->value(i, c).setValue(v1 + v2, std::sqrt(e1 * e1 + e2 * e2));
         }
         if (bFirstHalfBin)
         {
@@ -337,33 +336,49 @@ AbstractAverageHistogram::clone() const
 void
 AbstractAverageHistogram::normalizeProbability()
 {
-    real sum = 0;
-    for (int i = 0; i < rowCount(); ++i)
+    for (int c = 0; c < columnCount(); ++c)
     {
-        sum += value(i, 0);
+        real sum = 0;
+        for (int i = 0; i < rowCount(); ++i)
+        {
+            sum += value(i, c).value();
+        }
+        scaleSingle(c, 1.0 / (sum * xstep()));
     }
-    scale(1.0 / (sum * xstep()));
 }
 
 
 void
-AbstractAverageHistogram::scale(real norm)
+AbstractAverageHistogram::scaleSingle(int index, real factor)
 {
     for (int i = 0; i < rowCount(); ++i)
     {
-        value(i, 0) *= norm;
-        value(i, 1) *= norm;
+        value(i, index).value() *= factor;
+        value(i, index).error() *= factor;
     }
 }
 
 
 void
-AbstractAverageHistogram::scaleVector(real norm[])
+AbstractAverageHistogram::scaleAll(real factor)
 {
-    for (int i = 0; i < rowCount(); ++i)
+    for (int i = 0; i < columnCount(); ++i)
     {
-        value(i, 0) *= norm[i];
-        value(i, 1) *= norm[i];
+        scaleSingle(i, factor);
+    }
+}
+
+
+void
+AbstractAverageHistogram::scaleAllByVector(real factor[])
+{
+    for (int c = 0; c < columnCount(); ++c)
+    {
+        for (int i = 0; i < rowCount(); ++i)
+        {
+            value(i, c).value() *= factor[i];
+            value(i, c).error() *= factor[i];
+        }
     }
 }
 
@@ -405,15 +420,14 @@ class BasicAverageHistogramModule : public AbstractAverageHistogram,
         virtual void dataFinished();
 
     private:
-        //! Averaging helper object.
-        AnalysisDataFrameAverager averager_;
+        //! Averaging helper objects for each input data set.
+        std::vector<AnalysisDataFrameAverager> averagers_;
 
         // Copy and assign disallowed by base.
 };
 
 BasicAverageHistogramModule::BasicAverageHistogramModule()
 {
-    setColumnCount(2);
 }
 
 
@@ -421,23 +435,27 @@ BasicAverageHistogramModule::BasicAverageHistogramModule(
         const AnalysisHistogramSettings &settings)
     : AbstractAverageHistogram(settings)
 {
-    setColumnCount(2);
 }
 
 
 int
 BasicAverageHistogramModule::flags() const
 {
-    return efAllowMulticolumn;
+    return efAllowMulticolumn | efAllowMultipleDataSets;
 }
 
 
 void
 BasicAverageHistogramModule::dataStarted(AbstractAnalysisData *data)
 {
-    GMX_RELEASE_ASSERT(rowCount() == data->columnCount(),
-                       "Inconsistent data sizes, something is wrong in the initialization");
-    averager_.setColumnCount(rowCount());
+    setColumnCount(data->dataSetCount());
+    averagers_.resize(data->dataSetCount());
+    for (int i = 0; i < data->dataSetCount(); ++i)
+    {
+        GMX_RELEASE_ASSERT(rowCount() == data->columnCount(i),
+                           "Inconsistent data sizes, something is wrong in the initialization");
+        averagers_[i].setColumnCount(data->columnCount(i));
+    }
 }
 
 
@@ -450,7 +468,7 @@ BasicAverageHistogramModule::frameStarted(const AnalysisDataFrameHeader & /*head
 void
 BasicAverageHistogramModule::pointsAdded(const AnalysisDataPointSetRef &points)
 {
-    averager_.addPoints(points);
+    averagers_[points.dataSetIndex()].addPoints(points);
 }
 
 
@@ -463,12 +481,15 @@ BasicAverageHistogramModule::frameFinished(const AnalysisDataFrameHeader & /*hea
 void
 BasicAverageHistogramModule::dataFinished()
 {
-    averager_.finish();
     allocateValues();
-    for (int i = 0; i < rowCount(); ++i)
+    for (int i = 0; i < columnCount(); ++i)
     {
-        setValue(i, 0, averager_.average(i));
-        setValue(i, 1, sqrt(averager_.variance(i)));
+        averagers_[i].finish();
+        for (int j = 0; j < rowCount(); ++j)
+        {
+            value(j, i).setValue(averagers_[i].average(j),
+                                 std::sqrt(averagers_[i].variance(j)));
+        }
     }
 }
 
@@ -502,7 +523,7 @@ class BasicHistogramImpl
         /*! \brief
          * Initializes data storage frame when a new frame starts.
          */
-        void initFrame(AnalysisDataStorageFrame *frame);
+        void initFrame(int dataSetCount, AnalysisDataStorageFrame *frame);
 
         //! Storage implementation object.
         AnalysisDataStorage                  storage_;
@@ -537,12 +558,17 @@ void BasicHistogramImpl::init(const AnalysisHistogramSettings &settings)
 
 
 void
-BasicHistogramImpl::initFrame(AnalysisDataStorageFrame *frame)
+BasicHistogramImpl::initFrame(int dataSetCount, AnalysisDataStorageFrame *frame)
 {
-    for (int i = 0; i < frame->columnCount(); ++i)
+    for (int s = 0; s < dataSetCount; ++s)
     {
-        frame->setValue(i, 0.0);
+        frame->selectDataSet(s);
+        for (int i = 0; i < frame->columnCount(); ++i)
+        {
+            frame->setValue(i, 0.0);
+        }
     }
+    frame->selectDataSet(0);
 }
 
 }   // namespace internal
@@ -593,7 +619,7 @@ AnalysisDataSimpleHistogramModule::settings() const
 int
 AnalysisDataSimpleHistogramModule::flags() const
 {
-    return efAllowMulticolumn | efAllowMultipoint;
+    return efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
 }
 
 
@@ -601,7 +627,11 @@ void
 AnalysisDataSimpleHistogramModule::dataStarted(AbstractAnalysisData *data)
 {
     addModule(impl_->averager_);
-    setColumnCount(0, settings().binCount());
+    setDataSetCount(data->dataSetCount());
+    for (int i = 0; i < data->dataSetCount(); ++i)
+    {
+        setColumnCount(i, settings().binCount());
+    }
     notifyDataStart();
     impl_->storage_.startDataStorage(this);
 }
@@ -611,7 +641,7 @@ void
 AnalysisDataSimpleHistogramModule::frameStarted(const AnalysisDataFrameHeader &header)
 {
     AnalysisDataStorageFrame &frame = impl_->storage_.startFrame(header);
-    impl_->initFrame(&frame);
+    impl_->initFrame(dataSetCount(), &frame);
 }
 
 
@@ -620,6 +650,7 @@ AnalysisDataSimpleHistogramModule::pointsAdded(const AnalysisDataPointSetRef &po
 {
     AnalysisDataStorageFrame &frame =
         impl_->storage_.currentFrame(points.frameIndex());
+    frame.selectDataSet(points.dataSetIndex());
     for (int i = 0; i < points.columnCount(); ++i)
     {
         int bin = settings().findBin(points.y(i));
@@ -704,7 +735,7 @@ AnalysisDataWeightedHistogramModule::settings() const
 int
 AnalysisDataWeightedHistogramModule::flags() const
 {
-    return efAllowMulticolumn | efAllowMultipoint;
+    return efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
 }
 
 
@@ -712,7 +743,11 @@ void
 AnalysisDataWeightedHistogramModule::dataStarted(AbstractAnalysisData *data)
 {
     addModule(impl_->averager_);
-    setColumnCount(0, settings().binCount());
+    setDataSetCount(data->dataSetCount());
+    for (int i = 0; i < data->dataSetCount(); ++i)
+    {
+        setColumnCount(i, settings().binCount());
+    }
     notifyDataStart();
     impl_->storage_.startDataStorage(this);
 }
@@ -722,7 +757,7 @@ void
 AnalysisDataWeightedHistogramModule::frameStarted(const AnalysisDataFrameHeader &header)
 {
     AnalysisDataStorageFrame &frame = impl_->storage_.startFrame(header);
-    impl_->initFrame(&frame);
+    impl_->initFrame(dataSetCount(), &frame);
 }
 
 
@@ -738,6 +773,7 @@ AnalysisDataWeightedHistogramModule::pointsAdded(const AnalysisDataPointSetRef &
     {
         AnalysisDataStorageFrame &frame =
             impl_->storage_.currentFrame(points.frameIndex());
+        frame.selectDataSet(points.dataSetIndex());
         for (int i = 1; i < points.columnCount(); ++i)
         {
             frame.value(bin) += points.y(i);
@@ -788,9 +824,9 @@ class AnalysisDataBinAverageModule::Impl
         }
 
         //! Histogram settings.
-        AnalysisHistogramSettings  settings_;
-        //! Averaging helper object.
-        AnalysisDataFrameAverager  averager_;
+        AnalysisHistogramSettings               settings_;
+        //! Averaging helper objects for each input data set.
+        std::vector<AnalysisDataFrameAverager>  averagers_;
 };
 
 AnalysisDataBinAverageModule::AnalysisDataBinAverageModule()
@@ -804,7 +840,6 @@ AnalysisDataBinAverageModule::AnalysisDataBinAverageModule(
         const AnalysisHistogramSettings &settings)
     : impl_(new Impl(settings))
 {
-    setColumnCount(3);
     setRowCount(settings.binCount());
     setXAxis(settings.firstEdge() + 0.5 * settings.binWidth(),
              settings.binWidth());
@@ -836,14 +871,19 @@ AnalysisDataBinAverageModule::settings() const
 int
 AnalysisDataBinAverageModule::flags() const
 {
-    return efAllowMulticolumn | efAllowMultipoint;
+    return efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
 }
 
 
 void
-AnalysisDataBinAverageModule::dataStarted(AbstractAnalysisData * /*data*/)
+AnalysisDataBinAverageModule::dataStarted(AbstractAnalysisData *data)
 {
-    impl_->averager_.setColumnCount(rowCount());
+    setColumnCount(data->dataSetCount());
+    impl_->averagers_.resize(data->dataSetCount());
+    for (int i = 0; i < data->dataSetCount(); ++i)
+    {
+        impl_->averagers_[i].setColumnCount(rowCount());
+    }
 }
 
 
@@ -863,9 +903,10 @@ AnalysisDataBinAverageModule::pointsAdded(const AnalysisDataPointSetRef &points)
     int bin = settings().findBin(points.y(0));
     if (bin != -1)
     {
+        AnalysisDataFrameAverager &averager = impl_->averagers_[points.dataSetIndex()];
         for (int i = 1; i < points.columnCount(); ++i)
         {
-            impl_->averager_.addValue(bin, points.y(i));
+            averager.addValue(bin, points.y(i));
         }
     }
 }
@@ -880,13 +921,16 @@ AnalysisDataBinAverageModule::frameFinished(const AnalysisDataFrameHeader & /*he
 void
 AnalysisDataBinAverageModule::dataFinished()
 {
-    impl_->averager_.finish();
     allocateValues();
-    for (int i = 0; i < settings().binCount(); ++i)
+    for (int i = 0; i < columnCount(); ++i)
     {
-        setValue(i, 0, impl_->averager_.average(i));
-        setValue(i, 1, std::sqrt(impl_->averager_.variance(i)));
-        setValue(i, 2, impl_->averager_.sampleCount(i));
+        AnalysisDataFrameAverager &averager = impl_->averagers_[i];
+        averager.finish();
+        for (int j = 0; j < rowCount(); ++j)
+        {
+            value(j, i).setValue(averager.average(j),
+                                 std::sqrt(averager.variance(j)));
+        }
     }
     valuesReady();
 }
index aa002e45c5f2319a55743db5ff6531f574d25b1a..bbed9f8142dd44c033d9b50ea07ea674cc6f5fd4 100644 (file)
@@ -259,6 +259,9 @@ typedef gmx_unique_ptr<AbstractAverageHistogram>::type
  * the main use of the object is to postprocess the histogram once the
  * calculation is finished.
  *
+ * This class can represent multiple histograms in one object: each column in
+ * the data is an independent histogram.
+ *
  * \inpublicapi
  * \ingroup module_analysisdata
  */
@@ -292,10 +295,12 @@ class AbstractAverageHistogram : public AbstractAnalysisArrayData
         AverageHistogramPointer clone() const;
         //! Normalizes the histogram such that the integral over it is one.
         void normalizeProbability();
-        //! Scales the value of each bin by an uniform scaling factor.
-        void scale(real norm);
+        //! Scales a single histogram by a uniform scaling factor.
+        void scaleSingle(int index, real factor);
+        //! Scales all histograms by a uniform scaling factor.
+        void scaleAll(real factor);
         //! Scales the value of each bin by a different scaling factor.
-        void scaleVector(real norm[]);
+        void scaleAllByVector(real factor[]);
         /*! \brief
          * Notifies attached modules of the histogram data.
          *
@@ -330,10 +335,13 @@ class AbstractAverageHistogram : public AbstractAnalysisArrayData
 /*! \brief
  * Data module for per-frame histograms.
  *
- * Output data contains the same number of frames as the input data.
- * Each frame contains the histogram for the points in that frame.
- * All input columns are averaged into the same histogram.
- * The number of columns equals the number of bins in the histogram.
+ * Output data contains the same number of frames and data sets as the input
+ * data.  Each frame contains the histogram(s) for the points in that frame.
+ * Each input data set is processed independently into the corresponding output
+ * data set.
+ * All input columns for a data set are averaged into the same histogram.
+ * The number of columns for all data sets equals the number of bins in the
+ * histogram.
  *
  * \inpublicapi
  * \ingroup module_analysisdata
@@ -392,13 +400,17 @@ class AnalysisDataSimpleHistogramModule : public AbstractAnalysisData,
 /*! \brief
  * Data module for per-frame weighted histograms.
  *
- * Output data contains the same number of frames as the input data.
- * Each frame contains the histogram for the points in that frame, interpreted
- * such that the first column passed to pointsAdded() determines the bin and
- * the rest give weights to be added to that bin (input data should have at
- * least two colums, and at least two columns should be added at the same time).
- * All input columns are averaged into the same histogram.
- * The number of columns equals the number of bins in the histogram.
+ * Output data contains the same number of frames and data sets as the input
+ * data.  Each frame contains the histogram(s) for the points in that frame,
+ * interpreted such that the first column passed to pointsAdded() determines
+ * the bin and the rest give weights to be added to that bin (input data should
+ * have at least two colums, and at least two columns should be added at the
+ * same time).
+ * Each input data set is processed independently into the corresponding output
+ * data set.
+ * All input columns for a data set are averaged into the same histogram.
+ * The number of columns for all data sets equals the number of bins in the
+ * histogram.
  *
  * \inpublicapi
  * \ingroup module_analysisdata
@@ -444,14 +456,14 @@ class AnalysisDataWeightedHistogramModule : public AbstractAnalysisData,
  * Data module for bin averages.
  *
  * Output data contains one row for each bin; see AbstractAverageHistogram.
- * Output data contains three columns: the first is the average over all frames
- * for that bin, the second is the standard deviation of the values, and the
- * third is the number of samples in that bin.
+ * Output data contains one column for each input data set.
+ * The value in a column is the average over all frames of that data set for
+ * that bin.
  * The input data is interpreted such that the first column passed to
  * pointsAdded() determines the bin and the rest give values to be added to
  * that bin (input data should have at least two colums, and at least two
  * columns should be added at the same time).
- * All input columns are averaged into the same histogram.
+ * All input columns for a data set are averaged into the same histogram.
  *
  * \inpublicapi
  * \ingroup module_analysisdata
index b3db5ea4faa2964fa26dc32808e93d159030e11e..e69db362bc702ef47f1f10fb831174b8dc7a5e6c 100644 (file)
@@ -54,8 +54,8 @@
 #include "gromacs/legacyheaders/vec.h"
 #include "gromacs/legacyheaders/xvgr.h"
 
-#include "gromacs/options/basicoptions.h"
 #include "gromacs/analysisdata/dataframe.h"
+#include "gromacs/options/basicoptions.h"
 #include "gromacs/options/options.h"
 #include "gromacs/options/timeunitmanager.h"
 #include "gromacs/selection/selectioncollection.h"
@@ -292,12 +292,12 @@ AbstractPlotModule::setYFormat(int width, int precision, char format)
 int
 AbstractPlotModule::flags() const
 {
-    return efAllowMulticolumn | efAllowMultipoint;
+    return efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
 }
 
 
 void
-AbstractPlotModule::dataStarted(AbstractAnalysisData *data)
+AbstractPlotModule::dataStarted(AbstractAnalysisData * /*data*/)
 {
     if (!impl_->filename_.empty())
     {
@@ -488,7 +488,7 @@ AnalysisDataVectorPlotModule::setWriteMask(bool bWrite[DIM + 1])
 void
 AnalysisDataVectorPlotModule::pointsAdded(const AnalysisDataPointSetRef &points)
 {
-    if (points.firstColumn() % DIM != 0)
+    if (points.firstColumn() % DIM != 0 || points.columnCount() % DIM != 0)
     {
         GMX_THROW(APIError("Partial data points"));
     }
index f0fd168d6e676571712919cad5bf0850d5d53338..bd020d5f95d13a95412fe23857483a5bbbeedf99 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file is part of the GROMACS molecular simulation package.
  *
- * Copyright (c) 2010,2011,2012, by the GROMACS development team, led by
+ * Copyright (c) 2010,2011,2012,2013, by the GROMACS development team, led by
  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
  * others, as listed in the AUTHORS file in the top-level source
  * directory and at http://www.gromacs.org.
@@ -124,15 +124,18 @@ class AnalysisDataPlotSettings
  * straightforward plotting).
  *
  * By default, the data is written into an xvgr file, according to the
- * options read from the Options object given to the constructor.
+ * options read from the AnalysisDataPlotSettings object given to the
+ * constructor.
  * For non-xvgr data, it's possible to skip all headers by calling
  * setPlainOutput().
  *
- * Multipoint data is supported, in which case all the points are written to
- * the output, in the order in which they are added to the data.  A single
- * output line corresponds to a single frame.  In most cases with multipoint
- * data, setPlainOutput() should be called since the output does not make sense
- * as an xvgr file, but this is not enforced.
+ * A single output line corresponds to a single frame.  In most cases with
+ * multipoint data, setPlainOutput() should be called since the output does not
+ * make sense as an xvgr file, but this is not enforced.
+ *
+ * Multipoint data and multiple data sets are both supported, in which case all
+ * the points are written to the output, in the order in which they are added
+ * to the data.
  *
  * \ingroup module_analysisdata
  */
index f5c2a52e176003083305d3ba5b95a1a2aa845b8a..5c48ce3f72dfbd5aec82073b7dab13d93264a85c 100644 (file)
@@ -110,6 +110,39 @@ class MultipointInputData
         AnalysisDataTestInput  data_;
 };
 
+// Input data with multiple data sets for gmx::AnalysisDataAverageModule tests.
+class MultiDataSetInputData
+{
+    public:
+        static const AnalysisDataTestInput &get()
+        {
+            static MultiDataSetInputData singleton;
+            return singleton.data_;
+        }
+
+        MultiDataSetInputData() : data_(2, true)
+        {
+            using gmx::test::AnalysisDataTestInputFrame;
+            data_.setColumnCount(0, 3);
+            data_.setColumnCount(1, 2);
+            AnalysisDataTestInputFrame &frame1 = data_.addFrame(1.0);
+            frame1.addPointSetWithValues(0, 0, 0.0, 1.0, 2.0);
+            frame1.addPointSetWithValues(0, 0, 1.0, 0.0);
+            frame1.addPointSetWithValues(1, 0, 2.0, 1.0);
+            frame1.addPointSetWithValues(1, 1, 2.0);
+            AnalysisDataTestInputFrame &frame2 = data_.addFrame(2.0);
+            frame2.addPointSetWithValues(0, 0, 1.0, 1.0);
+            frame2.addPointSetWithValues(0, 2, 2.0);
+            frame2.addPointSetWithValues(1, 0, 1.0, 0.0);
+            AnalysisDataTestInputFrame &frame3 = data_.addFrame(3.0);
+            frame3.addPointSetWithValues(0, 0, 2.0, 0.0, 0.0);
+            frame3.addPointSetWithValues(1, 0, 0.0, 2.0);
+        }
+
+    private:
+        AnalysisDataTestInput  data_;
+};
+
 
 /********************************************************************
  * Tests for gmx::AnalysisDataAverageModule.
@@ -189,4 +222,20 @@ TEST_F(FrameAverageModuleTest, BasicTest)
     ASSERT_NO_THROW_GMX(presentAllData(input, &data));
 }
 
+TEST_F(FrameAverageModuleTest, HandlesMultipleDataSets)
+{
+    const AnalysisDataTestInput &input = MultiDataSetInputData::get();
+    gmx::AnalysisData            data;
+    ASSERT_NO_THROW_GMX(setupDataObject(input, &data));
+
+    gmx::AnalysisDataFrameAverageModulePointer module(
+            new gmx::AnalysisDataFrameAverageModule);
+    data.addModule(module);
+
+    ASSERT_NO_THROW_GMX(addStaticCheckerModule(input, &data));
+    ASSERT_NO_THROW_GMX(addReferenceCheckerModule("InputData", &data));
+    ASSERT_NO_THROW_GMX(addReferenceCheckerModule("FrameAverage", module.get()));
+    ASSERT_NO_THROW_GMX(presentAllData(input, &data));
+}
+
 } // namespace
index b2e3481bca0e2f3fe0bab2b8203c1fa22e17305e..5182e74c6e128f11f2ef98b9e88676fcb599252a 100644 (file)
@@ -233,16 +233,16 @@ TEST_F(SimpleHistogramModuleTest, ComputesCorrectlyWithAll)
 typedef gmx::test::AnalysisDataTestFixture WeightedHistogramModuleTest;
 
 // Input data for both weighted histogram and bin average module tests.
-class WeightedInputData
+class WeightedSimpleInputData
 {
     public:
         static const AnalysisDataTestInput &get()
         {
-            static WeightedInputData singleton;
+            static WeightedSimpleInputData singleton;
             return singleton.data_;
         }
 
-        WeightedInputData() : data_(1, true)
+        WeightedSimpleInputData() : data_(1, true)
         {
             using gmx::test::AnalysisDataTestInputFrame;
             data_.setColumnCount(0, 2);
@@ -264,9 +264,42 @@ class WeightedInputData
         AnalysisDataTestInput  data_;
 };
 
+// Input data for both weighted histogram and bin average module tests.
+class WeightedDataSetInputData
+{
+    public:
+        static const AnalysisDataTestInput &get()
+        {
+            static WeightedDataSetInputData singleton;
+            return singleton.data_;
+        }
+
+        WeightedDataSetInputData() : data_(2, true)
+        {
+            using gmx::test::AnalysisDataTestInputFrame;
+            data_.setColumnCount(0, 2);
+            data_.setColumnCount(1, 2);
+            AnalysisDataTestInputFrame &frame1 = data_.addFrame(1.0);
+            frame1.addPointSetWithValues(0, 0, 0.7, 0.5);
+            frame1.addPointSetWithValues(0, 0, 1.1, 1.0);
+            frame1.addPointSetWithValues(1, 0, 2.3, 1.0);
+            frame1.addPointSetWithValues(1, 0, 2.9, 2.0);
+            AnalysisDataTestInputFrame &frame2 = data_.addFrame(2.0);
+            frame2.addPointSetWithValues(0, 0, 1.3, 1.0);
+            frame2.addPointSetWithValues(1, 0, 2.2, 3.0);
+            AnalysisDataTestInputFrame &frame3 = data_.addFrame(3.0);
+            frame3.addPointSetWithValues(0, 0, 3.3, 0.5);
+            frame3.addPointSetWithValues(0, 0, 1.2, 2.0);
+            frame3.addPointSetWithValues(1, 0, 1.3, 1.0);
+        }
+
+    private:
+        AnalysisDataTestInput  data_;
+};
+
 TEST_F(WeightedHistogramModuleTest, ComputesCorrectly)
 {
-    const AnalysisDataTestInput &input = WeightedInputData::get();
+    const AnalysisDataTestInput &input = WeightedSimpleInputData::get();
     gmx::AnalysisData            data;
     ASSERT_NO_THROW_GMX(setupDataObject(input, &data));
 
@@ -287,7 +320,7 @@ TEST_F(WeightedHistogramModuleTest, ComputesCorrectly)
 
 TEST_F(WeightedHistogramModuleTest, ComputesCorrectlyWithAll)
 {
-    const AnalysisDataTestInput &input = WeightedInputData::get();
+    const AnalysisDataTestInput &input = WeightedSimpleInputData::get();
     gmx::AnalysisData            data;
     ASSERT_NO_THROW_GMX(setupDataObject(input, &data));
 
@@ -306,6 +339,27 @@ TEST_F(WeightedHistogramModuleTest, ComputesCorrectlyWithAll)
 }
 
 
+TEST_F(WeightedHistogramModuleTest, HandlesMultipleDataSets)
+{
+    const AnalysisDataTestInput &input = WeightedDataSetInputData::get();
+    gmx::AnalysisData            data;
+    ASSERT_NO_THROW_GMX(setupDataObject(input, &data));
+
+    gmx::AnalysisDataWeightedHistogramModulePointer module(
+            new gmx::AnalysisDataWeightedHistogramModule(
+                    gmx::histogramFromRange(1.0, 3.0).binCount(4)));
+    data.addModule(module);
+
+    ASSERT_NO_THROW_GMX(addStaticCheckerModule(input, &data));
+    ASSERT_NO_THROW_GMX(addReferenceCheckerModule("InputData", &data));
+    ASSERT_NO_THROW_GMX(addReferenceCheckerModule("Histogram", module.get()));
+    ASSERT_NO_THROW_GMX(addReferenceCheckerModule("HistogramAverage",
+                                                  &module->averager()));
+    ASSERT_NO_THROW_GMX(presentAllData(input, &data));
+    ASSERT_NO_THROW_GMX(module->averager().done());
+}
+
+
 /********************************************************************
  * Tests for gmx::AnalysisDataBinAverageModule.
  */
@@ -315,7 +369,7 @@ typedef gmx::test::AnalysisDataTestFixture BinAverageModuleTest;
 
 TEST_F(BinAverageModuleTest, ComputesCorrectly)
 {
-    const AnalysisDataTestInput &input = WeightedInputData::get();
+    const AnalysisDataTestInput &input = WeightedSimpleInputData::get();
     gmx::AnalysisData            data;
     ASSERT_NO_THROW_GMX(setupDataObject(input, &data));
 
@@ -333,7 +387,7 @@ TEST_F(BinAverageModuleTest, ComputesCorrectly)
 
 TEST_F(BinAverageModuleTest, ComputesCorrectlyWithAll)
 {
-    const AnalysisDataTestInput &input = WeightedInputData::get();
+    const AnalysisDataTestInput &input = WeightedSimpleInputData::get();
     gmx::AnalysisData            data;
     ASSERT_NO_THROW_GMX(setupDataObject(input, &data));
 
@@ -349,6 +403,24 @@ TEST_F(BinAverageModuleTest, ComputesCorrectlyWithAll)
 }
 
 
+TEST_F(BinAverageModuleTest, HandlesMultipleDataSets)
+{
+    const AnalysisDataTestInput &input = WeightedDataSetInputData::get();
+    gmx::AnalysisData            data;
+    ASSERT_NO_THROW_GMX(setupDataObject(input, &data));
+
+    gmx::AnalysisDataBinAverageModulePointer module(
+            new gmx::AnalysisDataBinAverageModule(
+                    gmx::histogramFromRange(1.0, 3.0).binCount(4)));
+    data.addModule(module);
+
+    ASSERT_NO_THROW_GMX(addStaticCheckerModule(input, &data));
+    ASSERT_NO_THROW_GMX(addReferenceCheckerModule("InputData", &data));
+    ASSERT_NO_THROW_GMX(addReferenceCheckerModule("HistogramAverage", module.get()));
+    ASSERT_NO_THROW_GMX(presentAllData(input, &data));
+}
+
+
 /********************************************************************
  * Tests for gmx::AbstractAverageHistogram.
  *
@@ -371,14 +443,14 @@ class AverageInputData
 
         AverageInputData() : data_(1, false)
         {
-            data_.setColumnCount(0, 2);
-            data_.addFrameWithValues(1.0,  2.0, 1.0);
-            data_.addFrameWithValues(1.5,  1.0, 1.0);
-            data_.addFrameWithValues(2.0,  3.0, 2.0);
-            data_.addFrameWithValues(2.5,  4.0, 2.0);
-            data_.addFrameWithValues(3.0,  2.0, 1.0);
-            data_.addFrameWithValues(3.5,  0.0, 3.0);
-            data_.addFrameWithValues(4.0,  1.0, 3.0);
+            data_.setColumnCount(0, 1);
+            data_.addFrameWithValueAndError(1.0,  2.0, 1.0);
+            data_.addFrameWithValueAndError(1.5,  1.0, 1.0);
+            data_.addFrameWithValueAndError(2.0,  3.0, 2.0);
+            data_.addFrameWithValueAndError(2.5,  4.0, 2.0);
+            data_.addFrameWithValueAndError(3.0,  2.0, 1.0);
+            data_.addFrameWithValueAndError(3.5,  0.0, 3.0);
+            data_.addFrameWithValueAndError(4.0,  1.0, 3.0);
         }
 
     private:
@@ -405,7 +477,7 @@ class MockAverageHistogram : public gmx::AbstractAverageHistogram
         using AbstractAverageHistogram::setColumnCount;
         using AbstractAverageHistogram::setRowCount;
         using AbstractAverageHistogram::allocateValues;
-        using AbstractAverageHistogram::setValue;
+        using AbstractAverageHistogram::value;
 };
 
 
index 1d30d5fce83e6da968fdd38e067ac8d6c2e0f37e..ad573c417e06a357acb91b6a7d840e9d22aa091a 100644 (file)
@@ -5,84 +5,70 @@
     <DataFrame Name="Frame0">
       <Real Name="X">1.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.000000</Real>
+          <Real Name="Error">1.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame1">
       <Real Name="X">1.500000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
-        <DataValue>
-          <Real Name="Value">1.000000</Real>
-        </DataValue>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.000000</Real>
+          <Real Name="Error">1.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame2">
       <Real Name="X">2.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">3.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">2.000000</Real>
+          <Real Name="Error">2.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame3">
       <Real Name="X">2.500000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">4.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">2.000000</Real>
+          <Real Name="Error">2.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame4">
       <Real Name="X">3.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.000000</Real>
+          <Real Name="Error">1.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame5">
       <Real Name="X">3.500000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">3.000000</Real>
+          <Real Name="Error">3.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame6">
       <Real Name="X">4.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">3.000000</Real>
+          <Real Name="Error">3.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame0">
       <Real Name="X">1.500000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">3.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.414214</Real>
+          <Real Name="Error">1.414214</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame1">
       <Real Name="X">2.500000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">7.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">2.828427</Real>
+          <Real Name="Error">2.828427</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame2">
       <Real Name="X">3.500000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">3.162278</Real>
+          <Real Name="Error">3.162278</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
index 999553a915cacf8545acfe829403016aa42c4fb7..c0c325330dd867c005bb48235a9f01deefb4dd3f 100644 (file)
@@ -5,84 +5,70 @@
     <DataFrame Name="Frame0">
       <Real Name="X">1.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.000000</Real>
+          <Real Name="Error">1.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame1">
       <Real Name="X">1.500000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
-        <DataValue>
-          <Real Name="Value">1.000000</Real>
-        </DataValue>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.000000</Real>
+          <Real Name="Error">1.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame2">
       <Real Name="X">2.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">3.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">2.000000</Real>
+          <Real Name="Error">2.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame3">
       <Real Name="X">2.500000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">4.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">2.000000</Real>
+          <Real Name="Error">2.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame4">
       <Real Name="X">3.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.000000</Real>
+          <Real Name="Error">1.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame5">
       <Real Name="X">3.500000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">3.000000</Real>
+          <Real Name="Error">3.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame6">
       <Real Name="X">4.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">3.000000</Real>
+          <Real Name="Error">3.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame0">
       <Real Name="X">1.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.000000</Real>
+          <Real Name="Error">1.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame1">
       <Real Name="X">2.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">4.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">2.236068</Real>
+          <Real Name="Error">2.236068</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame2">
       <Real Name="X">3.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">6.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">2.236068</Real>
+          <Real Name="Error">2.236068</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame3">
       <Real Name="X">4.000000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">4.242640</Real>
+          <Real Name="Error">4.242640</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
index 2b50ff2d6477a5b221208c1e7dec1fdc5f494a4f..be4664895814a9f28c24345c4b44afa8bb845d32 100644 (file)
@@ -8,15 +8,12 @@
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
index b04f97188d6721eac300c2790a0ef40338c3c4f1..88acc657263fc1fcc439d7ea784d77f4db067d29 100644 (file)
@@ -8,15 +8,12 @@
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
index f245bd98eb22a61471561e856ad725681f339aeb..faa59f3f9f494f1210e7f668451c3a5b6297b48d 100644 (file)
@@ -8,15 +8,12 @@
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="LastColumn">1</Int>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
@@ -38,7 +33,6 @@
         <Int Name="LastColumn">0</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="LastColumn">1</Int>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
@@ -63,7 +55,6 @@
         <Int Name="LastColumn">0</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
index 0847792a44ffb751dbbbd908c9d30c3b54fca7be..adb6dff3d8b6aca99bf3e679b83cdd6cf57cca72 100644 (file)
@@ -8,44 +8,36 @@
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">0.700000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.500000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.100000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.900000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">3.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">3.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.500000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame0">
       <Real Name="X">1.250000</Real>
       <DataValues>
-        <Int Name="Count">3</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.250000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.500000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">4.000000</Real>
+          <Real Name="Error">0.500000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame1">
       <Real Name="X">1.750000</Real>
       <DataValues>
-        <Int Name="Count">3</Int>
-        <DataValue>
-          <Real Name="Value">0.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.000000</Real>
-        </DataValue>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame2">
       <Real Name="X">2.250000</Real>
       <DataValues>
-        <Int Name="Count">3</Int>
-        <DataValue>
-          <Real Name="Value">2.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.414214</Real>
-        </DataValue>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
+          <Real Name="Error">1.414214</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame3">
       <Real Name="X">2.750000</Real>
       <DataValues>
-        <Int Name="Count">3</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.000000</Real>
+          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
index dd97dc7bcb23c411e5dcd8f40fcfe4e002db8f37..6a9eede4243ed59e966843d8eeb626e532412688 100644 (file)
@@ -8,44 +8,36 @@
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">0.700000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.500000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.100000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.900000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">3.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">3.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.500000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame0">
       <Real Name="X">1.250000</Real>
       <DataValues>
-        <Int Name="Count">3</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.100000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.547723</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">5.000000</Real>
+          <Real Name="Error">0.547723</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame1">
       <Real Name="X">1.750000</Real>
       <DataValues>
-        <Int Name="Count">3</Int>
-        <DataValue>
-          <Real Name="Value">0.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.000000</Real>
-        </DataValue>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame2">
       <Real Name="X">2.250000</Real>
       <DataValues>
-        <Int Name="Count">3</Int>
-        <DataValue>
-          <Real Name="Value">2.000000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.414214</Real>
-        </DataValue>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
+          <Real Name="Error">1.414214</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame3">
       <Real Name="X">2.750000</Real>
       <DataValues>
-        <Int Name="Count">3</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.250000</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.060660</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">2.000000</Real>
+          <Real Name="Error">1.060660</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
diff --git a/src/gromacs/analysisdata/tests/refdata/BinAverageModuleTest_HandlesMultipleDataSets.xml b/src/gromacs/analysisdata/tests/refdata/BinAverageModuleTest_HandlesMultipleDataSets.xml
new file mode 100644 (file)
index 0000000..3171fea
--- /dev/null
@@ -0,0 +1,163 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <AnalysisData Name="InputData">
+    <DataFrame Name="Frame0">
+      <Real Name="X">1.000000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">0.700000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.500000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">1.100000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">2.300000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">2.900000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame1">
+      <Real Name="X">2.000000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">1.300000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">2.200000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">3.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame2">
+      <Real Name="X">3.000000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">3.300000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.500000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">1.200000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">1.300000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+  </AnalysisData>
+  <AnalysisData Name="HistogramAverage">
+    <DataFrame Name="Frame0">
+      <Real Name="X">1.250000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">1.333333</Real>
+          <Real Name="Error">0.577350</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+          <Real Name="Error">0.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame1">
+      <Real Name="X">1.750000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame2">
+      <Real Name="X">2.250000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+          <Real Name="Error">1.414214</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame3">
+      <Real Name="X">2.750000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+          <Real Name="Error">0.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+  </AnalysisData>
+</ReferenceData>
index dea4a9f8e591371d3d82c2fc4ea5e0f80a8004cd..6ce464f4b1ac343c4c0a21a1b0a12fd4b9d6d1c0 100644 (file)
@@ -8,15 +8,12 @@
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">3</Int>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
diff --git a/src/gromacs/analysisdata/tests/refdata/FrameAverageModuleTest_HandlesMultipleDataSets.xml b/src/gromacs/analysisdata/tests/refdata/FrameAverageModuleTest_HandlesMultipleDataSets.xml
new file mode 100644 (file)
index 0000000..63865e9
--- /dev/null
@@ -0,0 +1,151 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <AnalysisData Name="InputData">
+    <DataFrame Name="Frame0">
+      <Real Name="X">1.000000</Real>
+      <DataValues>
+        <Int Name="Count">3</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <Int Name="FirstColumn">0</Int>
+        <Int Name="LastColumn">1</Int>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">1</Int>
+        <Int Name="DataSet">1</Int>
+        <Int Name="FirstColumn">1</Int>
+        <Int Name="LastColumn">1</Int>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame1">
+      <Real Name="X">2.000000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <Int Name="FirstColumn">0</Int>
+        <Int Name="LastColumn">1</Int>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">1</Int>
+        <Int Name="DataSet">0</Int>
+        <Int Name="FirstColumn">2</Int>
+        <Int Name="LastColumn">2</Int>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame2">
+      <Real Name="X">3.000000</Real>
+      <DataValues>
+        <Int Name="Count">3</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+  </AnalysisData>
+  <AnalysisData Name="FrameAverage">
+    <DataFrame Name="Frame0">
+      <Real Name="X">1.000000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">0.800000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.666667</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame1">
+      <Real Name="X">2.000000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">1.333333</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.500000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame2">
+      <Real Name="X">3.000000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">0.666667</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+  </AnalysisData>
+</ReferenceData>
index 15c02759741d105aff654d5e842e871c62e07664..c4bcf44b66d2c08e52ccd3e9e773bcb8a276c93c 100644 (file)
@@ -8,28 +8,24 @@
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.700000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.100000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.900000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">3.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame0">
       <Real Name="X">1.250000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.333333</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.577350</Real>
+          <Real Name="Error">0.577350</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame1">
       <Real Name="X">1.750000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
-        <DataValue>
-          <Real Name="Value">0.000000</Real>
-        </DataValue>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame2">
       <Real Name="X">2.250000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.666667</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.577350</Real>
+          <Real Name="Error">0.577350</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame3">
       <Real Name="X">2.750000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.333333</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.577350</Real>
+          <Real Name="Error">0.577350</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
index 5c8f6038167e5fdeda76c993a0c644541be1ee75..226eadba194512a29e31f5f72fbb5004097f984e 100644 (file)
@@ -8,28 +8,24 @@
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.700000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.100000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.900000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">2.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">3.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame0">
       <Real Name="X">1.250000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.666667</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.577350</Real>
+          <Real Name="Error">0.577350</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame1">
       <Real Name="X">1.750000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
-        <DataValue>
-          <Real Name="Value">0.000000</Real>
-        </DataValue>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame2">
       <Real Name="X">2.250000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.666667</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.577350</Real>
+          <Real Name="Error">0.577350</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame3">
       <Real Name="X">2.750000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.666667</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">0.577350</Real>
+          <Real Name="Error">0.577350</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
index 95af2f52ebc0a3f18e9611fc1cfa03f3b8a6415e..ee7d8f389c73636984a70acb73f6cbcd41a8b9ec 100644 (file)
@@ -8,44 +8,36 @@
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">0.700000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.500000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.100000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.900000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">3.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">3.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.500000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame0">
       <Real Name="X">1.250000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.666667</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.154701</Real>
+          <Real Name="Error">1.154701</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame1">
       <Real Name="X">1.750000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
-        <DataValue>
-          <Real Name="Value">0.000000</Real>
-        </DataValue>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame2">
       <Real Name="X">2.250000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.333333</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.527525</Real>
+          <Real Name="Error">1.527525</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame3">
       <Real Name="X">2.750000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.666667</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.154701</Real>
+          <Real Name="Error">1.154701</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
index 48d48130c915292683a901d24975700833e599ba..667e24c83feb362299f7a0d43bd4dcc6aef2d069 100644 (file)
@@ -8,44 +8,36 @@
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">0.700000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.500000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.100000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.900000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">2.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">3.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">3.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">0.500000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.200000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">2.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
       <DataValues>
         <Int Name="Count">2</Int>
         <DataValue>
           <Real Name="Value">1.300000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
         <DataValue>
           <Real Name="Value">1.000000</Real>
-          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame0">
       <Real Name="X">1.250000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.833333</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.040833</Real>
+          <Real Name="Error">1.040833</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame1">
       <Real Name="X">1.750000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
-        <DataValue>
-          <Real Name="Value">0.000000</Real>
-        </DataValue>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame2">
       <Real Name="X">2.250000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">1.333333</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.527525</Real>
+          <Real Name="Error">1.527525</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
     <DataFrame Name="Frame3">
       <Real Name="X">2.750000</Real>
       <DataValues>
-        <Int Name="Count">2</Int>
+        <Int Name="Count">1</Int>
         <DataValue>
           <Real Name="Value">0.833333</Real>
-        </DataValue>
-        <DataValue>
-          <Real Name="Value">1.040833</Real>
+          <Real Name="Error">1.040833</Real>
         </DataValue>
       </DataValues>
     </DataFrame>
diff --git a/src/gromacs/analysisdata/tests/refdata/WeightedHistogramModuleTest_HandlesMultipleDataSets.xml b/src/gromacs/analysisdata/tests/refdata/WeightedHistogramModuleTest_HandlesMultipleDataSets.xml
new file mode 100644 (file)
index 0000000..4c02d37
--- /dev/null
@@ -0,0 +1,270 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <AnalysisData Name="InputData">
+    <DataFrame Name="Frame0">
+      <Real Name="X">1.000000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">0.700000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.500000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">1.100000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">2.300000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">2.900000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame1">
+      <Real Name="X">2.000000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">1.300000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">2.200000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">3.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame2">
+      <Real Name="X">3.000000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">3.300000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.500000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">1.200000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">1.300000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+  </AnalysisData>
+  <AnalysisData Name="Histogram">
+    <DataFrame Name="Frame0">
+      <Real Name="X">1.000000</Real>
+      <DataValues>
+        <Int Name="Count">4</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">4</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame1">
+      <Real Name="X">2.000000</Real>
+      <DataValues>
+        <Int Name="Count">4</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">4</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">3.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame2">
+      <Real Name="X">3.000000</Real>
+      <DataValues>
+        <Int Name="Count">4</Int>
+        <Int Name="DataSet">0</Int>
+        <DataValue>
+          <Real Name="Value">2.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+      </DataValues>
+      <DataValues>
+        <Int Name="Count">4</Int>
+        <Int Name="DataSet">1</Int>
+        <DataValue>
+          <Real Name="Value">1.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+  </AnalysisData>
+  <AnalysisData Name="HistogramAverage">
+    <DataFrame Name="Frame0">
+      <Real Name="X">1.250000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">1.333333</Real>
+          <Real Name="Error">0.577350</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.333333</Real>
+          <Real Name="Error">0.577350</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame1">
+      <Real Name="X">1.750000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame2">
+      <Real Name="X">2.250000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">1.333333</Real>
+          <Real Name="Error">1.527525</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+    <DataFrame Name="Frame3">
+      <Real Name="X">2.750000</Real>
+      <DataValues>
+        <Int Name="Count">2</Int>
+        <DataValue>
+          <Real Name="Value">0.000000</Real>
+          <Real Name="Error">0.000000</Real>
+        </DataValue>
+        <DataValue>
+          <Real Name="Value">0.666667</Real>
+          <Real Name="Error">1.154701</Real>
+        </DataValue>
+      </DataValues>
+    </DataFrame>
+  </AnalysisData>
+</ReferenceData>
index abad36c26ad0cb0afb66fb9e89ea03b97c6a1cc7..99060e985b9a4c5cfd7c47479aec0ef3bf6a147e 100644 (file)
@@ -13,12 +13,17 @@ and use the copy_xsl.sh script to copy it to relevant locations.
 <xsl:import href="common-referencedata.xsl"/>
 
 <xsl:template match="AnalysisData">
+    <xsl:variable name="has-datasetspec"
+                  select="DataFrame/DataValues/Int[@Name='DataSet']"/>
     <xsl:variable name="has-columnspec"
                   select="DataFrame/DataValues/Int[@Name='FirstColumn']"/>
     <table border="1">
         <tr>
             <th>Frame</th>
             <th>X</th>
+            <xsl:if test="$has-datasetspec">
+                <th>Set</th>
+            </xsl:if>
             <xsl:if test="$has-columnspec">
                 <th>Columns</th>
             </xsl:if>
@@ -28,6 +33,9 @@ and use the copy_xsl.sh script to copy it to relevant locations.
         <tr>
             <td><xsl:value-of select="../@Name"/></td>
             <td><xsl:value-of select="../Real[@Name='X']"/></td>
+            <xsl:if test="$has-datasetspec">
+                <td><xsl:value-of select="Int[@Name='DataSet']"/></td>
+            </xsl:if>
             <xsl:if test="$has-columnspec">
                 <td>
                     <xsl:choose>
@@ -48,6 +56,9 @@ and use the copy_xsl.sh script to copy it to relevant locations.
 
 <xsl:template match="DataValue">
     <xsl:value-of select="Real[@Name='Value']"/>
+    <xsl:if test="Real[@Name='Error']">
+        &#177; <xsl:value-of select="Real[@Name='Error']"/>
+    </xsl:if>
 </xsl:template>
 
 </xsl:stylesheet>
index 4c7e9377a982f6e88f4184e8ab7092e9c9c3d019..edbaec81829b99da8b8725260e078850322fb8c9 100644 (file)
@@ -105,22 +105,24 @@ Angle::initOptions(Options *options, TrajectoryAnalysisSettings * /*settings*/)
         "The type of the angle is specified with [TT]-g1[tt] and [TT]-g2[tt].",
         "If [TT]-g1[tt] is [TT]angle[tt] or [TT]dihedral[tt], [TT]-g2[tt]",
         "should not be specified.",
-        "In this case, [TT]-group1[tt] should specify one selection,",
-        "and it should contain triplets or quartets of positions that define",
+        "In this case, [TT]-group1[tt] should specify one or more selections,",
+        "and each should contain triplets or quartets of positions that define",
         "the angles to be calculated.[PAR]",
         "If [TT]-g1[tt] is [TT]vector[tt] or [TT]plane[tt], [TT]-group1[tt]",
-        "should specify a selection that has either pairs ([TT]vector[tt])",
+        "should specify selections that contain either pairs ([TT]vector[tt])",
         "or triplets ([TT]plane[tt]) of positions. For vectors, the positions",
         "set the endpoints of the vector, and for planes, the three positions",
         "are used to calculate the normal of the plane. In both cases,",
         "[TT]-g2[tt] specifies the other vector to use (see below).[PAR]",
         "With [TT]-g2 vector[tt] or [TT]-g2 plane[tt], [TT]-group2[tt] should",
-        "specify another set of vectors. Both selections should specify the",
-        "same number of vectors.[PAR]",
-        "With [TT]-g2 sphnorm[tt], [TT]-group2[tt] should specify a single",
-        "position that is the center of the sphere. The second vector is then",
-        "calculated as the vector from the center to the midpoint of the",
-        "positions specified by [TT]-group1[tt].[PAR]",
+        "specify another set of vectors. [TT]-group1[tt] and [TT]-group2[tt]",
+        "should specify the same number of selections, and for each selection",
+        "in [TT]-group1[tt], the corresponding selection in [TT]-group2[tt]",
+        "should specify the same number of vectors.[PAR]",
+        "With [TT]-g2 sphnorm[tt], each selection in [TT]-group2[tt] should",
+        "specify a single position that is the center of the sphere.",
+        "The second vector is calculated as the vector from the center to the",
+        "midpoint of the positions specified by [TT]-group1[tt].[PAR]",
         "With [TT]-g2 z[tt], [TT]-group2[tt] is not necessary, and angles",
         "between the first vectors and the positive Z axis are calculated.[PAR]",
         "With [TT]-g2 t0[tt], [TT]-group2[tt] is not necessary, and angles",
@@ -130,7 +132,9 @@ Angle::initOptions(Options *options, TrajectoryAnalysisSettings * /*settings*/)
         "for each frame.",
         "[TT]-oall[tt] writes all the individual angles.",
         "[TT]-oh[tt] writes a histogram of the angles. The bin width can be",
-        "set with [TT]-binw[tt]."
+        "set with [TT]-binw[tt].",
+        "For [TT]-oav[tt] and [TT]-oh[tt], separate average/histogram is",
+        "computed for each selection in [TT]-group1[tt]."
         /* TODO: Consider if the dump option is necessary and how to best
          * implement it.
            "[TT]-od[tt] can be used to dump all the individual angles,",
@@ -164,17 +168,16 @@ Angle::initOptions(Options *options, TrajectoryAnalysisSettings * /*settings*/)
     options->addOption(DoubleOption("binw").store(&binWidth_)
                            .description("Binwidth for -oh in degrees"));
 
-    // TODO: Allow multiple angles to be computed in one invocation.
-    // Most of the code already supports it, but requires a solution for
-    // Redmine issue #1010.
     // TODO: Consider what is the best way to support dynamic selections.
     // Again, most of the code already supports it, but it needs to be
     // considered how should -oall work, and additional checks should be added.
     sel1info_ = options->addOption(SelectionOption("group1")
                                        .required().onlyStatic().storeVector(&sel1_)
+                                       .multiValue()
                                        .description("First analysis/vector selection"));
     sel2info_ = options->addOption(SelectionOption("group2")
                                        .onlyStatic().storeVector(&sel2_)
+                                       .multiValue()
                                        .description("Second analysis/vector selection"));
 }
 
@@ -274,7 +277,12 @@ Angle::initAnalysis(const TrajectoryAnalysisSettings &settings,
 {
     checkSelections(sel1_, sel2_);
 
-    angles_.setColumnCount(0, sel1_[0].posCount() / natoms1_);
+    // checkSelections() ensures that both selection lists have the same size.
+    angles_.setDataSetCount(sel1_.size());
+    for (size_t i = 0; i < sel1_.size(); ++i)
+    {
+        angles_.setColumnCount(i, sel1_[i].posCount() / natoms1_);
+    }
     double histogramMin = (g1type_ == "dihedral" ? -180.0 : 0);
     histogramModule_->init(histogramFromRange(histogramMin, 180.0)
                                .binWidth(binWidth_).includeAll());
@@ -407,6 +415,7 @@ Angle::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
                 copy_rvec(sel2_[g].position(0).x(), c2);
                 break;
         }
+        dh.selectDataSet(g);
         for (int i = 0, j = 0, n = 0;
              i < sel1[g].posCount();
              i += natoms1_, j += natoms2_, ++n)
index a1c13501e5e240e2f25d57d49a2f863044991d93..b6b7783e4e10a8d3d5968003f5fcb0b3211d3a5e 100644 (file)
@@ -143,4 +143,22 @@ TEST_F(AngleModuleTest, ComputesVectorTimeZeroAngles)
     runTest(CommandLine::create(cmdline));
 }
 
+TEST_F(AngleModuleTest, ComputesMultipleAngles)
+{
+    const char *const cmdline[] = {
+        "angle",
+        "-g1", "vector",
+        "-group1",
+        "resname RV1 RV2 and name A1 A2",
+        "resname RV3 RV4 and name A1 A2",
+        "-g2", "plane",
+        "-group2",
+        "resname RP1 RP2 and name A1 A2 A3",
+        "resname RP1 RP2 and name A1 A2 A3",
+        "-binw", "60"
+    };
+    setTopology("angle.gro");
+    runTest(CommandLine::create(cmdline));
+}
+
 } // namespace
index cead6c4759fe4da52a9b17980ea0ff165c82ddc9..1f24e40462959273e1dd2b950c7e6921421e17ef 100644 (file)
       <DataFrame Name="Frame0">
         <Real Name="X">-120.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.002778</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame1">
         <Real Name="X">0.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.002778</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame2">
         <Real Name="X">120.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.002778</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
diff --git a/src/gromacs/trajectoryanalysis/tests/refdata/AngleModuleTest_ComputesMultipleAngles.xml b/src/gromacs/trajectoryanalysis/tests/refdata/AngleModuleTest_ComputesMultipleAngles.xml
new file mode 100644 (file)
index 0000000..fccc0f7
--- /dev/null
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="referencedata.xsl"?>
+<ReferenceData>
+  <String Name="CommandLine">angle -g1 vector -group1 'resname RV1 RV2 and name A1 A2' 'resname RV3 RV4 and name A1 A2' -g2 plane -group2 'resname RP1 RP2 and name A1 A2 A3' 'resname RP1 RP2 and name A1 A2 A3' -binw 60</String>
+  <OutputData Name="Data">
+    <AnalysisData Name="angle">
+      <DataFrame Name="Frame0">
+        <Real Name="X">0.000000</Real>
+        <DataValues>
+          <Int Name="Count">2</Int>
+          <Int Name="DataSet">0</Int>
+          <DataValue>
+            <Real Name="Value">90.000000</Real>
+          </DataValue>
+          <DataValue>
+            <Real Name="Value">45.000000</Real>
+          </DataValue>
+        </DataValues>
+        <DataValues>
+          <Int Name="Count">2</Int>
+          <Int Name="DataSet">1</Int>
+          <DataValue>
+            <Real Name="Value">90.000000</Real>
+          </DataValue>
+          <DataValue>
+            <Real Name="Value">135.000000</Real>
+          </DataValue>
+        </DataValues>
+      </DataFrame>
+    </AnalysisData>
+    <AnalysisData Name="average">
+      <DataFrame Name="Frame0">
+        <Real Name="X">0.000000</Real>
+        <DataValues>
+          <Int Name="Count">2</Int>
+          <DataValue>
+            <Real Name="Value">67.500000</Real>
+          </DataValue>
+          <DataValue>
+            <Real Name="Value">112.500000</Real>
+          </DataValue>
+        </DataValues>
+      </DataFrame>
+    </AnalysisData>
+    <AnalysisData Name="histogram">
+      <DataFrame Name="Frame0">
+        <Real Name="X">30.000000</Real>
+        <DataValues>
+          <Int Name="Count">2</Int>
+          <DataValue>
+            <Real Name="Value">0.008333</Real>
+            <Real Name="Error">0.000000</Real>
+          </DataValue>
+          <DataValue>
+            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
+          </DataValue>
+        </DataValues>
+      </DataFrame>
+      <DataFrame Name="Frame1">
+        <Real Name="X">90.000000</Real>
+        <DataValues>
+          <Int Name="Count">2</Int>
+          <DataValue>
+            <Real Name="Value">0.008333</Real>
+            <Real Name="Error">0.000000</Real>
+          </DataValue>
+          <DataValue>
+            <Real Name="Value">0.008333</Real>
+            <Real Name="Error">0.000000</Real>
+          </DataValue>
+        </DataValues>
+      </DataFrame>
+      <DataFrame Name="Frame2">
+        <Real Name="X">150.000000</Real>
+        <DataValues>
+          <Int Name="Count">2</Int>
+          <DataValue>
+            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
+          </DataValue>
+          <DataValue>
+            <Real Name="Value">0.008333</Real>
+            <Real Name="Error">0.000000</Real>
+          </DataValue>
+        </DataValues>
+      </DataFrame>
+    </AnalysisData>
+  </OutputData>
+</ReferenceData>
index cdf24955d9daa491b3cef1ff762f34c0d7ad3532..9e58ae81a8b21c952297e4c645887faf6e99b84a 100644 (file)
       <DataFrame Name="Frame0">
         <Real Name="X">30.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.008333</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame1">
         <Real Name="X">90.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
-          </DataValue>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame2">
         <Real Name="X">150.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.008333</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
index b995df6b81f9769db5e9e843cb90cccd3eb5be99..9f4e0e8f06d575efe25bd6e47d3c753fe17f6ac1 100644 (file)
       <DataFrame Name="Frame0">
         <Real Name="X">30.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.008333</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame1">
         <Real Name="X">90.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
-          </DataValue>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame2">
         <Real Name="X">150.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.008333</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
index 1600814cb0affb0e790b2840c4e39668de8e13ba..fe2bd05879cd5e3d51912d5587787ffbce3f62f4 100644 (file)
       <DataFrame Name="Frame0">
         <Real Name="X">30.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.008333</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame1">
         <Real Name="X">90.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.008333</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame2">
         <Real Name="X">150.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
-          </DataValue>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
index 255d191b9243c1d266c31c6e2613876b5314af40..aef2ce6d062a9f6b15c6c67f56f44b3745d2da4b 100644 (file)
       <DataFrame Name="Frame0">
         <Real Name="X">30.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.008333</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame1">
         <Real Name="X">90.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.008333</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame2">
         <Real Name="X">150.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
-          </DataValue>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
index 5392df1bb2482ce288f817299cf977c94a1c9210..20c170c84356d7e22dbd9c78c0173d54d5629f09 100644 (file)
       <DataFrame Name="Frame0">
         <Real Name="X">30.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.008333</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame1">
         <Real Name="X">90.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.008333</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame2">
         <Real Name="X">150.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
-          <DataValue>
-            <Real Name="Value">0.000000</Real>
-          </DataValue>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.000000</Real>
+            <Real Name="Error">0.000000</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
index 50ca1d66c794f61204617c205049f4b511bddc8f..dd0fb8e9347a5b10f0ab059695ad5d5536197da7 100644 (file)
       <DataFrame Name="Frame0">
         <Real Name="X">30.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.012500</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.005893</Real>
+            <Real Name="Error">0.005893</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame1">
         <Real Name="X">90.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.002083</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.002946</Real>
+            <Real Name="Error">0.002946</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
       <DataFrame Name="Frame2">
         <Real Name="X">150.000000</Real>
         <DataValues>
-          <Int Name="Count">2</Int>
+          <Int Name="Count">1</Int>
           <DataValue>
             <Real Name="Value">0.002083</Real>
-          </DataValue>
-          <DataValue>
-            <Real Name="Value">0.002946</Real>
+            <Real Name="Error">0.002946</Real>
           </DataValue>
         </DataValues>
       </DataFrame>
index abad36c26ad0cb0afb66fb9e89ea03b97c6a1cc7..99060e985b9a4c5cfd7c47479aec0ef3bf6a147e 100644 (file)
@@ -13,12 +13,17 @@ and use the copy_xsl.sh script to copy it to relevant locations.
 <xsl:import href="common-referencedata.xsl"/>
 
 <xsl:template match="AnalysisData">
+    <xsl:variable name="has-datasetspec"
+                  select="DataFrame/DataValues/Int[@Name='DataSet']"/>
     <xsl:variable name="has-columnspec"
                   select="DataFrame/DataValues/Int[@Name='FirstColumn']"/>
     <table border="1">
         <tr>
             <th>Frame</th>
             <th>X</th>
+            <xsl:if test="$has-datasetspec">
+                <th>Set</th>
+            </xsl:if>
             <xsl:if test="$has-columnspec">
                 <th>Columns</th>
             </xsl:if>
@@ -28,6 +33,9 @@ and use the copy_xsl.sh script to copy it to relevant locations.
         <tr>
             <td><xsl:value-of select="../@Name"/></td>
             <td><xsl:value-of select="../Real[@Name='X']"/></td>
+            <xsl:if test="$has-datasetspec">
+                <td><xsl:value-of select="Int[@Name='DataSet']"/></td>
+            </xsl:if>
             <xsl:if test="$has-columnspec">
                 <td>
                     <xsl:choose>
@@ -48,6 +56,9 @@ and use the copy_xsl.sh script to copy it to relevant locations.
 
 <xsl:template match="DataValue">
     <xsl:value-of select="Real[@Name='Value']"/>
+    <xsl:if test="Real[@Name='Error']">
+        &#177; <xsl:value-of select="Real[@Name='Error']"/>
+    </xsl:if>
 </xsl:template>
 
 </xsl:stylesheet>
index abad36c26ad0cb0afb66fb9e89ea03b97c6a1cc7..99060e985b9a4c5cfd7c47479aec0ef3bf6a147e 100644 (file)
@@ -13,12 +13,17 @@ and use the copy_xsl.sh script to copy it to relevant locations.
 <xsl:import href="common-referencedata.xsl"/>
 
 <xsl:template match="AnalysisData">
+    <xsl:variable name="has-datasetspec"
+                  select="DataFrame/DataValues/Int[@Name='DataSet']"/>
     <xsl:variable name="has-columnspec"
                   select="DataFrame/DataValues/Int[@Name='FirstColumn']"/>
     <table border="1">
         <tr>
             <th>Frame</th>
             <th>X</th>
+            <xsl:if test="$has-datasetspec">
+                <th>Set</th>
+            </xsl:if>
             <xsl:if test="$has-columnspec">
                 <th>Columns</th>
             </xsl:if>
@@ -28,6 +33,9 @@ and use the copy_xsl.sh script to copy it to relevant locations.
         <tr>
             <td><xsl:value-of select="../@Name"/></td>
             <td><xsl:value-of select="../Real[@Name='X']"/></td>
+            <xsl:if test="$has-datasetspec">
+                <td><xsl:value-of select="Int[@Name='DataSet']"/></td>
+            </xsl:if>
             <xsl:if test="$has-columnspec">
                 <td>
                     <xsl:choose>
@@ -48,6 +56,9 @@ and use the copy_xsl.sh script to copy it to relevant locations.
 
 <xsl:template match="DataValue">
     <xsl:value-of select="Real[@Name='Value']"/>
+    <xsl:if test="Real[@Name='Error']">
+        &#177; <xsl:value-of select="Real[@Name='Error']"/>
+    </xsl:if>
 </xsl:template>
 
 </xsl:stylesheet>
index 50ebe42247d24b8bc66203365192c8f7aea167a7..723e0ad2948be83f2e4da30f3f450743ff55fc5f 100644 (file)
@@ -111,6 +111,13 @@ void AnalysisDataTestInputFrame::addPointSetWithValues(
     pointSet.addValue(y3);
 }
 
+void AnalysisDataTestInputFrame::addPointSetWithValueAndError(
+        int dataSet, int firstColumn, real y1, real e1)
+{
+    AnalysisDataTestInputPointSet &pointSet = addPointSet(dataSet, firstColumn);
+    pointSet.addValueWithError(y1, e1);
+}
+
 
 /********************************************************************
  * AnalysisDataTestInput
@@ -167,6 +174,12 @@ void AnalysisDataTestInput::addFrameWithValues(real x, real y1, real y2, real y3
     frame.addPointSetWithValues(0, 0, y1, y2, y3);
 }
 
+void AnalysisDataTestInput::addFrameWithValueAndError(real x, real y1, real e1)
+{
+    AnalysisDataTestInputFrame &frame = addFrame(x);
+    frame.addPointSetWithValueAndError(0, 0, y1, e1);
+}
+
 
 /********************************************************************
  * AnalysisDataTest
@@ -214,8 +227,16 @@ void AnalysisDataTestFixture::presentDataFrame(const AnalysisDataTestInput &inpu
         handle.selectDataSet(points.dataSetIndex());
         for (int j = 0; j < points.size(); ++j)
         {
-            handle.setPoint(j + points.firstColumn(),
-                            points.y(j), points.dy(j), points.present(j));
+            if (points.hasError(j))
+            {
+                handle.setPoint(j + points.firstColumn(),
+                                points.y(j), points.error(j), points.present(j));
+            }
+            else
+            {
+                handle.setPoint(j + points.firstColumn(),
+                                points.y(j), points.present(j));
+            }
         }
         if (input.isMultipoint())
         {
index f7bf76fde3053a81b3397942665014974f8a4a7a..ef2290120fdb2dcc19a55b9285702d16678e8a51 100644 (file)
@@ -49,6 +49,7 @@
 
 #include "gromacs/legacyheaders/types/simple.h"
 
+#include "gromacs/analysisdata/dataframe.h"
 #include "gromacs/utility/gmxassert.h"
 
 #include "testutils/refdata.h"
@@ -86,28 +87,55 @@ class AnalysisDataTestInputPointSet
         //! Returns zero-based index of the last column in this point set.
         int lastColumn() const { return firstColumn_ + size() - 1; }
         //! Returns the number of columns in the point set.
-        int size() const { return y_.size(); }
+        int size() const { return values_.size(); }
         //! Returns the value in column \p i.
-        real y(int i) const { return y_[i]; }
+        real y(int i) const { return values_[i].y; }
+        //! Returns whether the error is present for column \p i.
+        bool hasError(int i) const { return values_[i].bError; }
         //! Returns the error in column \p i.
-        real dy(int i) const { return 0.0; }
+        real error(int i) const { return values_[i].error; }
         //! Returns whether the value in column \p i is present.
-        real present(int i) const { return true; }
-        //! Returns a vector of values for all columns.
-        const std::vector<real> &yvector() const { return y_; }
+        bool present(int i) const { return true; }
+        //! Returns an AnalysisDataValue for column \p i.
+        AnalysisDataValue value(int i) const
+        {
+            AnalysisDataValue result;
+            result.setValue(values_[i].y);
+            if (values_[i].bError)
+            {
+                result.setError(values_[i].error);
+            }
+            return result;
+        }
 
         //! Appends a value to this point set.
-        void addValue(real y) { y_.push_back(y); }
+        void addValue(real y) { values_.push_back(Value(y)); }
+        //! Appends a value with an error estimate to this point set.
+        void addValueWithError(real y, real error)
+        {
+            values_.push_back(Value(y, error));
+        }
 
     private:
         //! Creates an empty point set.
         AnalysisDataTestInputPointSet(int index, int dataSetIndex,
                                       int firstColumn);
 
+        struct Value
+        {
+            Value() : y(0.0), error(0.0), bError(false) {}
+            explicit Value(real y) : y(y), error(0.0), bError(false) {}
+            Value(real y, real error) : y(y), error(error), bError(true) {}
+
+            real                y;
+            real                error;
+            bool                bError;
+        };
+
         int                     index_;
         int                     dataSetIndex_;
         int                     firstColumn_;
-        std::vector<real>       y_;
+        std::vector<Value>      values_;
 
         //! For constructing new point sets.
         friend class AnalysisDataTestInputFrame;
@@ -149,6 +177,9 @@ class AnalysisDataTestInputFrame
         //! Adds a point set with given values to this frame.
         void addPointSetWithValues(int dataSet, int firstColumn,
                                    real y1, real y2, real y3);
+        //! Adds a point set with given values to this frame.
+        void addPointSetWithValueAndError(int dataSet, int firstColumn,
+                                          real y1, real e1);
 
     private:
         //! Constructs a new frame object with the given values.
@@ -209,6 +240,8 @@ class AnalysisDataTestInput
         void addFrameWithValues(real x, real y1, real y2);
         //! Adds a frame with a single point set and the given values.
         void addFrameWithValues(real x, real y1, real y2, real y3);
+        //! Adds a frame with a single point set and the given values.
+        void addFrameWithValueAndError(real x, real y1, real e1);
 
     private:
         std::vector<int>                        columnCounts_;
@@ -424,7 +457,7 @@ void AnalysisDataTestFixture::setupArrayData(const AnalysisDataTestInput &input,
         const AnalysisDataTestInputPointSet &points = frame.pointSet(0);
         for (int column = 0; column < points.size(); ++column)
         {
-            data->setValue(row, column + points.firstColumn(), points.y(column));
+            data->value(row, column + points.firstColumn()) = points.value(column);
         }
     }
 }
index da6e4ca24131872e4784282a3fc32b3479e9db7e..4a4cbccef16defaa1e7b70f15981f52d018196b2 100644 (file)
@@ -77,7 +77,7 @@ class MockAnalysisDataModule::Impl
          * Callback used to initialize reference data checks
          *
          * Called in response to dataStarted().
-         * Records information about the source data for later use.
+         * Records the source data for later use (for access to data properties).
          */
         void startReferenceData(AbstractAnalysisData *data);
         /*! \brief
@@ -115,12 +115,12 @@ class MockAnalysisDataModule::Impl
          * calls.
          */
         boost::scoped_ptr<TestReferenceChecker>  frameChecker_;
+        //! Source data.
+        const AbstractAnalysisData              *source_;
         //! Flags that will be returned by the mock module.
         int                                      flags_;
         //! Index of the current/next frame.
         int                                      frameIndex_;
-        //! Number of columns in the source data (for reference checking only).
-        int                                      columnCount_;
 };
 
 namespace
@@ -149,7 +149,7 @@ void checkReferenceDataPoint(TestReferenceChecker    *checker,
 }       // namespace
 
 MockAnalysisDataModule::Impl::Impl(int flags)
-    : flags_(flags), frameIndex_(0), columnCount_(-1)
+    : source_(NULL), flags_(flags), frameIndex_(0)
 {
 }
 
@@ -157,7 +157,7 @@ MockAnalysisDataModule::Impl::Impl(int flags)
 void
 MockAnalysisDataModule::Impl::startReferenceData(AbstractAnalysisData *data)
 {
-    columnCount_ = data->columnCount();
+    source_ = data;
 }
 
 
@@ -186,13 +186,19 @@ MockAnalysisDataModule::Impl::checkReferencePoints(
         TestReferenceChecker checker(
                 frameChecker_->checkCompound("DataValues", NULL));
         checker.checkInteger(points.columnCount(), "Count");
-        bool bAllColumns = (points.firstColumn() == 0
-                            && points.columnCount() == columnCount_);
+        if (checker.checkPresent(source_->dataSetCount() > 1, "DataSet"))
+        {
+            checker.checkInteger(points.dataSetIndex(), "DataSet");
+        }
+        const int  sourceColumnCount = source_->columnCount(points.dataSetIndex());
+        const bool bAllColumns       = (points.firstColumn() == 0
+                                        && points.columnCount() == sourceColumnCount);
         if (checker.checkPresent(!bAllColumns, "FirstColumn"))
         {
             checker.checkInteger(points.firstColumn(), "FirstColumn");
             checker.checkInteger(points.lastColumn(),  "LastColumn");
         }
+
         AnalysisDataValuesRef::const_iterator value;
         for (value = points.values().begin(); value != points.values().end(); ++value)
         {
@@ -580,7 +586,7 @@ void
 MockAnalysisDataModule::setupReferenceCheck(const TestReferenceChecker &checker,
                                             AbstractAnalysisData       *source)
 {
-    impl_->flags_ |= efAllowMulticolumn | efAllowMultipoint;
+    impl_->flags_ |= efAllowMulticolumn | efAllowMultipoint | efAllowMultipleDataSets;
 
     impl_->rootChecker_.reset(new TestReferenceChecker(checker));
     // Google Mock does not support checking the order fully, because