/*
* This file is part of the GROMACS molecular simulation package.
*
- * 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.
+ * Copyright (c) 2010,2011,2012,2013,2014,2015, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
*
* GROMACS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
*/
#include "distance.h"
+#include <string>
+
#include "gromacs/legacyheaders/pbc.h"
#include "gromacs/legacyheaders/vec.h"
#include "gromacs/analysisdata/analysisdata.h"
+#include "gromacs/analysisdata/modules/average.h"
+#include "gromacs/analysisdata/modules/histogram.h"
#include "gromacs/analysisdata/modules/plot.h"
#include "gromacs/options/basicoptions.h"
#include "gromacs/options/filenameoption.h"
#include "gromacs/selection/selection.h"
#include "gromacs/selection/selectionoption.h"
#include "gromacs/trajectoryanalysis/analysissettings.h"
+#include "gromacs/utility/arrayref.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/stringutil.h"
namespace analysismodules
{
-const char Distance::name[] = "distance";
-const char Distance::shortDescription[] =
- "Calculate distances between pairs of positions";
+namespace
+{
+
+class Distance : public TrajectoryAnalysisModule
+{
+ public:
+ Distance();
+
+ virtual void initOptions(Options *options,
+ TrajectoryAnalysisSettings *settings);
+ virtual void initAnalysis(const TrajectoryAnalysisSettings &settings,
+ const TopologyInformation &top);
+
+ virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
+ TrajectoryAnalysisModuleData *pdata);
+
+ virtual void finishAnalysis(int nframes);
+ virtual void writeOutput();
+
+ private:
+ SelectionList sel_;
+ std::string fnAverage_;
+ std::string fnAll_;
+ std::string fnXYZ_;
+ std::string fnHistogram_;
+ std::string fnAllStats_;
+ double meanLength_;
+ double lengthDev_;
+ double binWidth_;
+
+ AnalysisData distances_;
+ AnalysisData xyz_;
+ AnalysisDataAverageModulePointer summaryStatsModule_;
+ AnalysisDataAverageModulePointer allStatsModule_;
+ AnalysisDataFrameAverageModulePointer averageModule_;
+ AnalysisDataSimpleHistogramModulePointer histogramModule_;
+
+ // Copy and assign disallowed by base.
+};
Distance::Distance()
- : TrajectoryAnalysisModule(name, shortDescription),
+ : TrajectoryAnalysisModule(DistanceInfo::name, DistanceInfo::shortDescription),
meanLength_(0.1), lengthDev_(1.0), binWidth_(0.001)
{
+ summaryStatsModule_.reset(new AnalysisDataAverageModule());
+ summaryStatsModule_->setAverageDataSets(true);
+ distances_.addModule(summaryStatsModule_);
+ allStatsModule_.reset(new AnalysisDataAverageModule());
+ distances_.addModule(allStatsModule_);
averageModule_.reset(new AnalysisDataFrameAverageModule());
distances_.addModule(averageModule_);
histogramModule_.reset(new AnalysisDataSimpleHistogramModule());
registerAnalysisDataset(&distances_, "dist");
registerAnalysisDataset(&xyz_, "xyz");
+ registerBasicDataset(summaryStatsModule_.get(), "stats");
+ registerBasicDataset(allStatsModule_.get(), "allstats");
registerBasicDataset(averageModule_.get(), "average");
registerBasicDataset(&histogramModule_->averager(), "histogram");
}
-Distance::~Distance()
-{
-}
-
-
void
Distance::initOptions(Options *options, TrajectoryAnalysisSettings * /*settings*/)
{
static const char *const desc[] = {
- "[TT]gmx distance[tt] calculates distances between pairs of positions",
+ "[THISMODULE] calculates distances between pairs of positions",
"as a function of time. Each selection specifies an independent set",
"of distances to calculate. Each selection should consist of pairs",
"of positions, and the distances are computed between positions 1-2,",
"[TT]-oh[tt] writes a histogram of the distances for each selection.",
"The location of the histogram is set with [TT]-len[tt] and",
"[TT]-tol[tt]. Bin width is set with [TT]-binw[tt].",
+ "[TT]-oallstat[tt] writes out the average and standard deviation for",
+ "each individual distance, calculated over the frames."
};
- options->setDescription(concatenateStrings(desc));
+ options->setDescription(desc);
options->addOption(FileNameOption("oav").filetype(eftPlot).outputFile()
.store(&fnAverage_).defaultBasename("distave")
options->addOption(FileNameOption("oh").filetype(eftPlot).outputFile()
.store(&fnHistogram_).defaultBasename("disthist")
.description("Histogram of the distances"));
- // 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.
+ options->addOption(FileNameOption("oallstat").filetype(eftPlot).outputFile()
+ .store(&fnAllStats_).defaultBasename("diststat")
+ .description("Statistics for individual distances"));
options->addOption(SelectionOption("select").storeVector(&sel_)
- .required().onlyStatic().multiValue()
+ .required().dynamicMask().multiValue()
.description("Position pairs to calculate distances for"));
// TODO: Extend the histogramming implementation to allow automatic
// extension of the histograms to cover the data, removing the need for
}
-namespace
-{
-
/*! \brief
* Checks that selections conform to the expectations of the tool.
*/
sel[g].name(), sel[g].posCount());
GMX_THROW(InconsistentInputError(message));
}
+ if (sel[g].isDynamic())
+ {
+ for (int i = 0; i < sel[g].posCount(); i += 2)
+ {
+ if (sel[g].position(i).selected() != sel[g].position(i+1).selected())
+ {
+ std::string message =
+ formatString("Dynamic selection %d does not select "
+ "a consistent set of pairs over the frames",
+ static_cast<int>(g + 1));
+ GMX_THROW(InconsistentInputError(message));
+ }
+ }
+ }
}
}
-} // namespace
-
void
Distance::initAnalysis(const TrajectoryAnalysisSettings &settings,
plotm->setTitle("Average distance");
plotm->setXAxisIsTime();
plotm->setYLabel("Distance (nm)");
- // TODO: Add legends
+ for (size_t g = 0; g < sel_.size(); ++g)
+ {
+ plotm->appendLegend(sel_[g].name());
+ }
averageModule_->addModule(plotm);
}
{
AnalysisDataPlotModulePointer plotm(
new AnalysisDataPlotModule(settings.plotSettings()));
- plotm->setFileName(fnAll_);
+ plotm->setFileName(fnXYZ_);
plotm->setTitle("Distance");
plotm->setXAxisIsTime();
plotm->setYLabel("Distance (nm)");
plotm->setTitle("Distance histogram");
plotm->setXLabel("Distance (nm)");
plotm->setYLabel("Probability");
- // TODO: Add legends
+ for (size_t g = 0; g < sel_.size(); ++g)
+ {
+ plotm->appendLegend(sel_[g].name());
+ }
histogramModule_->averager().addModule(plotm);
}
+
+ if (!fnAllStats_.empty())
+ {
+ AnalysisDataPlotModulePointer plotm(
+ new AnalysisDataPlotModule(settings.plotSettings()));
+ plotm->setFileName(fnAllStats_);
+ plotm->setErrorsAsSeparateColumn(true);
+ plotm->setTitle("Statistics for individual distances");
+ plotm->setXLabel("Distance index");
+ plotm->setYLabel("Average/standard deviation (nm)");
+ for (size_t g = 0; g < sel_.size(); ++g)
+ {
+ plotm->appendLegend(std::string(sel_[g].name()) + " avg");
+ plotm->appendLegend(std::string(sel_[g].name()) + " std.dev.");
+ }
+ // TODO: Consider whether this output format is the best possible.
+ allStatsModule_->addModule(plotm);
+ }
}
{
rvec_sub(p2.x(), p1.x(), dx);
}
- real dist = norm(dx);
- distHandle.setPoint(n, dist);
+ real dist = norm(dx);
+ bool bPresent = p1.selected() && p2.selected();
+ distHandle.setPoint(n, dist, bPresent);
xyzHandle.setPoints(n*3, 3, dx);
}
}
void
Distance::writeOutput()
{
- // TODO: Print bond length statistics
- //fprintf(stderr, "Average distance: %f\n", avem_->average(0));
- //fprintf(stderr, "Std. deviation: %f\n", avem_->stddev(0));
+ SelectionList::const_iterator sel;
+ int index;
+ for (sel = sel_.begin(), index = 0; sel != sel_.end(); ++sel, ++index)
+ {
+ printf("%s:\n", sel->name());
+ printf(" Number of samples: %d\n",
+ summaryStatsModule_->sampleCount(index, 0));
+ printf(" Average distance: %-6.3f nm\n",
+ summaryStatsModule_->average(index, 0));
+ printf(" Standard deviation: %-6.3f nm\n",
+ summaryStatsModule_->standardDeviation(index, 0));
+ }
+}
+
+} // namespace
+
+const char DistanceInfo::name[] = "distance";
+const char DistanceInfo::shortDescription[] =
+ "Calculate distances between pairs of positions";
+
+TrajectoryAnalysisModulePointer DistanceInfo::create()
+{
+ return TrajectoryAnalysisModulePointer(new Distance);
}
} // namespace analysismodules