Add readConfAndTopology
[gromacs.git] / src / gromacs / trajectoryanalysis / modules / select.cpp
blob893bc7a2c0c5ece9b378deb0e42ac3b33e6795aa
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
35 /*! \internal \file
36 * \brief
37 * Implements gmx::analysismodules::Select.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_trajectoryanalysis
42 #include "gmxpre.h"
44 #include "select.h"
46 #include <cstdio>
47 #include <cstring>
49 #include <algorithm>
50 #include <set>
51 #include <string>
52 #include <vector>
54 #include "gromacs/analysisdata/analysisdata.h"
55 #include "gromacs/analysisdata/dataframe.h"
56 #include "gromacs/analysisdata/datamodule.h"
57 #include "gromacs/analysisdata/modules/average.h"
58 #include "gromacs/analysisdata/modules/lifetime.h"
59 #include "gromacs/analysisdata/modules/plot.h"
60 #include "gromacs/fileio/gmxfio.h"
61 #include "gromacs/fileio/trxio.h"
62 #include "gromacs/options/basicoptions.h"
63 #include "gromacs/options/filenameoption.h"
64 #include "gromacs/options/ioptionscontainer.h"
65 #include "gromacs/selection/selection.h"
66 #include "gromacs/selection/selectionoption.h"
67 #include "gromacs/topology/topology.h"
68 #include "gromacs/trajectory/trajectoryframe.h"
69 #include "gromacs/trajectoryanalysis/analysissettings.h"
70 #include "gromacs/utility/arrayref.h"
71 #include "gromacs/utility/exceptions.h"
72 #include "gromacs/utility/gmxassert.h"
73 #include "gromacs/utility/scoped_cptr.h"
74 #include "gromacs/utility/smalloc.h"
75 #include "gromacs/utility/stringutil.h"
77 namespace gmx
80 namespace analysismodules
83 namespace
86 /*! \internal \brief
87 * Data module for writing index files.
89 * \ingroup module_analysisdata
91 class IndexFileWriterModule : public AnalysisDataModuleSerial
93 public:
94 IndexFileWriterModule();
95 virtual ~IndexFileWriterModule();
97 //! Sets the file name to write the index file to.
98 void setFileName(const std::string &fnm);
99 /*! \brief
100 * Adds information about a group to be printed.
102 * Must be called for each group present in the input data.
104 void addGroup(const std::string &name, bool bDynamic);
106 virtual int flags() const;
108 virtual void dataStarted(AbstractAnalysisData *data);
109 virtual void frameStarted(const AnalysisDataFrameHeader &header);
110 virtual void pointsAdded(const AnalysisDataPointSetRef &points);
111 virtual void frameFinished(const AnalysisDataFrameHeader &header);
112 virtual void dataFinished();
114 private:
115 void closeFile();
117 struct GroupInfo
119 GroupInfo(const std::string &name, bool bDynamic)
120 : name(name), bDynamic(bDynamic)
123 std::string name;
124 bool bDynamic;
127 std::string fnm_;
128 std::vector<GroupInfo> groups_;
129 FILE *fp_;
130 int currentGroup_;
131 int currentSize_;
132 bool bAnyWritten_;
135 /********************************************************************
136 * IndexFileWriterModule
139 IndexFileWriterModule::IndexFileWriterModule()
140 : fp_(NULL), currentGroup_(-1), currentSize_(0), bAnyWritten_(false)
145 IndexFileWriterModule::~IndexFileWriterModule()
147 closeFile();
151 void IndexFileWriterModule::closeFile()
153 if (fp_ != NULL)
155 gmx_fio_fclose(fp_);
156 fp_ = NULL;
161 void IndexFileWriterModule::setFileName(const std::string &fnm)
163 fnm_ = fnm;
167 void IndexFileWriterModule::addGroup(const std::string &name, bool bDynamic)
169 std::string newName(name);
170 std::replace(newName.begin(), newName.end(), ' ', '_');
171 groups_.emplace_back(newName, bDynamic);
175 int IndexFileWriterModule::flags() const
177 return efAllowMulticolumn | efAllowMultipoint;
181 void IndexFileWriterModule::dataStarted(AbstractAnalysisData * /*data*/)
183 if (!fnm_.empty())
185 fp_ = gmx_fio_fopen(fnm_.c_str(), "w");
190 void IndexFileWriterModule::frameStarted(const AnalysisDataFrameHeader & /*header*/)
192 bAnyWritten_ = false;
193 currentGroup_ = -1;
197 void
198 IndexFileWriterModule::pointsAdded(const AnalysisDataPointSetRef &points)
200 if (fp_ == NULL)
202 return;
204 bool bFirstFrame = (points.frameIndex() == 0);
205 if (points.firstColumn() == 0)
207 ++currentGroup_;
208 GMX_RELEASE_ASSERT(currentGroup_ < static_cast<int>(groups_.size()),
209 "Too few groups initialized");
210 if (bFirstFrame || groups_[currentGroup_].bDynamic)
212 if (!bFirstFrame || currentGroup_ > 0)
214 std::fprintf(fp_, "\n\n");
216 std::string name = groups_[currentGroup_].name;
217 if (groups_[currentGroup_].bDynamic)
219 name += formatString("_f%d_t%.3f", points.frameIndex(), points.x());
221 std::fprintf(fp_, "[ %s ]", name.c_str());
222 bAnyWritten_ = true;
223 currentSize_ = 0;
226 else
228 if (bFirstFrame || groups_[currentGroup_].bDynamic)
230 if (currentSize_ % 15 == 0)
232 std::fprintf(fp_, "\n");
234 std::fprintf(fp_, "%4d ", static_cast<int>(points.y(0)));
235 ++currentSize_;
241 void IndexFileWriterModule::frameFinished(const AnalysisDataFrameHeader & /*header*/)
246 void IndexFileWriterModule::dataFinished()
248 if (fp_ != NULL)
250 std::fprintf(fp_, "\n");
252 closeFile();
255 /********************************************************************
256 * Select
259 //! How to identify residues in output files.
260 enum ResidueNumbering
262 ResidueNumbering_ByNumber,
263 ResidueNumbering_ByIndex
265 //! Which atoms to write out to PDB files.
266 enum PdbAtomsSelection
268 PdbAtomsSelection_All,
269 PdbAtomsSelection_MaxSelection,
270 PdbAtomsSelection_Selected
272 //! String values corresponding to ResidueNumbering.
273 const char *const cResNumberEnum[] = { "number", "index" };
274 //! String values corresponding to PdbAtomsSelection.
275 const char *const cPDBAtomsEnum[] = { "all", "maxsel", "selected" };
277 class Select : public TrajectoryAnalysisModule
279 public:
280 Select();
282 virtual void initOptions(IOptionsContainer *options,
283 TrajectoryAnalysisSettings *settings);
284 virtual void optionsFinished(TrajectoryAnalysisSettings *settings);
285 virtual void initAnalysis(const TrajectoryAnalysisSettings &settings,
286 const TopologyInformation &top);
288 virtual void analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
289 TrajectoryAnalysisModuleData *pdata);
291 virtual void finishAnalysis(int nframes);
292 virtual void writeOutput();
294 private:
295 SelectionList sel_;
296 SelectionOptionInfo *selOpt_;
298 std::string fnSize_;
299 std::string fnFrac_;
300 std::string fnIndex_;
301 std::string fnNdx_;
302 std::string fnMask_;
303 std::string fnOccupancy_;
304 std::string fnPDB_;
305 std::string fnLifetime_;
306 bool bTotNorm_;
307 bool bFracNorm_;
308 bool bResInd_;
309 bool bCumulativeLifetimes_;
310 ResidueNumbering resNumberType_;
311 PdbAtomsSelection pdbAtoms_;
313 const TopologyInformation *top_;
314 std::vector<int> totsize_;
315 AnalysisData sdata_;
316 AnalysisData cdata_;
317 AnalysisData idata_;
318 AnalysisData mdata_;
319 AnalysisDataAverageModulePointer occupancyModule_;
320 AnalysisDataLifetimeModulePointer lifetimeModule_;
323 Select::Select()
324 : selOpt_(NULL), bTotNorm_(false), bFracNorm_(false), bResInd_(false),
325 bCumulativeLifetimes_(true), resNumberType_(ResidueNumbering_ByNumber),
326 pdbAtoms_(PdbAtomsSelection_All), top_(NULL),
327 occupancyModule_(new AnalysisDataAverageModule()),
328 lifetimeModule_(new AnalysisDataLifetimeModule())
330 mdata_.addModule(occupancyModule_);
331 mdata_.addModule(lifetimeModule_);
333 registerAnalysisDataset(&sdata_, "size");
334 registerAnalysisDataset(&cdata_, "cfrac");
335 idata_.setColumnCount(0, 2);
336 idata_.setMultipoint(true);
337 registerAnalysisDataset(&idata_, "index");
338 registerAnalysisDataset(&mdata_, "mask");
339 occupancyModule_->setXAxis(1.0, 1.0);
340 registerBasicDataset(occupancyModule_.get(), "occupancy");
341 registerBasicDataset(lifetimeModule_.get(), "lifetime");
345 void
346 Select::initOptions(IOptionsContainer *options, TrajectoryAnalysisSettings *settings)
348 static const char *const desc[] = {
349 "[THISMODULE] writes out basic data about dynamic selections.",
350 "It can be used for some simple analyses, or the output can",
351 "be combined with output from other programs and/or external",
352 "analysis programs to calculate more complex things.",
353 "For detailed help on the selection syntax, please use",
354 "[TT]gmx help selections[tt].[PAR]",
355 "Any combination of the output options is possible, but note",
356 "that [TT]-om[tt] only operates on the first selection.",
357 "Also note that if you provide no output options, no output is",
358 "produced.[PAR]",
359 "With [TT]-os[tt], calculates the number of positions in each",
360 "selection for each frame. With [TT]-norm[tt], the output is",
361 "between 0 and 1 and describes the fraction from the maximum",
362 "number of positions (e.g., for selection 'resname RA and x < 5'",
363 "the maximum number of positions is the number of atoms in",
364 "RA residues). With [TT]-cfnorm[tt], the output is divided",
365 "by the fraction covered by the selection.",
366 "[TT]-norm[tt] and [TT]-cfnorm[tt] can be specified independently",
367 "of one another.[PAR]",
368 "With [TT]-oc[tt], the fraction covered by each selection is",
369 "written out as a function of time.[PAR]",
370 "With [TT]-oi[tt], the selected atoms/residues/molecules are",
371 "written out as a function of time. In the output, the first",
372 "column contains the frame time, the second contains the number",
373 "of positions, followed by the atom/residue/molecule numbers.",
374 "If more than one selection is specified, the size of the second",
375 "group immediately follows the last number of the first group",
376 "and so on.[PAR]",
377 "With [TT]-on[tt], the selected atoms are written as a index file",
378 "compatible with [TT]make_ndx[tt] and the analyzing tools. Each selection",
379 "is written as a selection group and for dynamic selections a",
380 "group is written for each frame.[PAR]",
381 "For residue numbers, the output of [TT]-oi[tt] can be controlled",
382 "with [TT]-resnr[tt]: [TT]number[tt] (default) prints the residue",
383 "numbers as they appear in the input file, while [TT]index[tt] prints",
384 "unique numbers assigned to the residues in the order they appear",
385 "in the input file, starting with 1. The former is more intuitive,",
386 "but if the input contains multiple residues with the same number,",
387 "the output can be less useful.[PAR]",
388 "With [TT]-om[tt], a mask is printed for the first selection",
389 "as a function of time. Each line in the output corresponds to",
390 "one frame, and contains either 0/1 for each atom/residue/molecule",
391 "possibly selected. 1 stands for the atom/residue/molecule being",
392 "selected for the current frame, 0 for not selected.[PAR]",
393 "With [TT]-of[tt], the occupancy fraction of each position (i.e.,",
394 "the fraction of frames where the position is selected) is",
395 "printed.[PAR]",
396 "With [TT]-ofpdb[tt], a PDB file is written out where the occupancy",
397 "column is filled with the occupancy fraction of each atom in the",
398 "selection. The coordinates in the PDB file will be those from the",
399 "input topology. [TT]-pdbatoms[tt] can be used to control which atoms",
400 "appear in the output PDB file: with [TT]all[tt] all atoms are",
401 "present, with [TT]maxsel[tt] all atoms possibly selected by the",
402 "selection are present, and with [TT]selected[tt] only atoms that are",
403 "selected at least in one frame are present.[PAR]",
404 "With [TT]-olt[tt], a histogram is produced that shows the number of",
405 "selected positions as a function of the time the position was",
406 "continuously selected. [TT]-cumlt[tt] can be used to control whether",
407 "subintervals of longer intervals are included in the histogram.[PAR]",
408 "[TT]-om[tt], [TT]-of[tt], and [TT]-olt[tt] only make sense with",
409 "dynamic selections."
412 settings->setHelpText(desc);
414 options->addOption(FileNameOption("os").filetype(eftPlot).outputFile()
415 .store(&fnSize_).defaultBasename("size")
416 .description("Number of positions in each selection"));
417 options->addOption(FileNameOption("oc").filetype(eftPlot).outputFile()
418 .store(&fnFrac_).defaultBasename("cfrac")
419 .description("Covered fraction for each selection"));
420 options->addOption(FileNameOption("oi").filetype(eftGenericData).outputFile()
421 .store(&fnIndex_).defaultBasename("index")
422 .description("Indices selected by each selection"));
423 options->addOption(FileNameOption("on").filetype(eftIndex).outputFile()
424 .store(&fnNdx_).defaultBasename("index")
425 .description("Index file from the selection"));
426 options->addOption(FileNameOption("om").filetype(eftPlot).outputFile()
427 .store(&fnMask_).defaultBasename("mask")
428 .description("Mask for selected positions"));
429 options->addOption(FileNameOption("of").filetype(eftPlot).outputFile()
430 .store(&fnOccupancy_).defaultBasename("occupancy")
431 .description("Occupied fraction for selected positions"));
432 options->addOption(FileNameOption("ofpdb").filetype(eftPDB).outputFile()
433 .store(&fnPDB_).defaultBasename("occupancy")
434 .description("PDB file with occupied fraction for selected positions"));
435 options->addOption(FileNameOption("olt").filetype(eftPlot).outputFile()
436 .store(&fnLifetime_).defaultBasename("lifetime")
437 .description("Lifetime histogram"));
439 selOpt_ = options->addOption(SelectionOption("select").storeVector(&sel_)
440 .required().multiValue()
441 .description("Selections to analyze"));
443 options->addOption(BooleanOption("norm").store(&bTotNorm_)
444 .description("Normalize by total number of positions with -os"));
445 options->addOption(BooleanOption("cfnorm").store(&bFracNorm_)
446 .description("Normalize by covered fraction with -os"));
447 options->addOption(EnumOption<ResidueNumbering>("resnr").store(&resNumberType_)
448 .enumValue(cResNumberEnum)
449 .description("Residue number output type with -oi and -on"));
450 options->addOption(EnumOption<PdbAtomsSelection>("pdbatoms").store(&pdbAtoms_)
451 .enumValue(cPDBAtomsEnum)
452 .description("Atoms to write with -ofpdb"));
453 options->addOption(BooleanOption("cumlt").store(&bCumulativeLifetimes_)
454 .description("Cumulate subintervals of longer intervals in -olt"));
457 void
458 Select::optionsFinished(TrajectoryAnalysisSettings *settings)
460 if (!fnPDB_.empty())
462 settings->setFlag(TrajectoryAnalysisSettings::efRequireTop);
463 settings->setFlag(TrajectoryAnalysisSettings::efUseTopX);
467 void
468 Select::initAnalysis(const TrajectoryAnalysisSettings &settings,
469 const TopologyInformation &top)
471 bResInd_ = (resNumberType_ == ResidueNumbering_ByIndex);
473 for (SelectionList::iterator i = sel_.begin(); i != sel_.end(); ++i)
475 i->initCoveredFraction(CFRAC_SOLIDANGLE);
478 // TODO: For large systems, a float may not have enough precision
479 sdata_.setColumnCount(0, sel_.size());
480 totsize_.reserve(sel_.size());
481 for (size_t g = 0; g < sel_.size(); ++g)
483 totsize_.push_back(sel_[g].posCount());
485 if (!fnSize_.empty())
487 AnalysisDataPlotModulePointer plot(
488 new AnalysisDataPlotModule(settings.plotSettings()));
489 plot->setFileName(fnSize_);
490 plot->setTitle("Selection size");
491 plot->setXAxisIsTime();
492 plot->setYLabel("Number");
493 for (size_t g = 0; g < sel_.size(); ++g)
495 plot->appendLegend(sel_[g].name());
497 sdata_.addModule(plot);
500 cdata_.setColumnCount(0, sel_.size());
501 if (!fnFrac_.empty())
503 AnalysisDataPlotModulePointer plot(
504 new AnalysisDataPlotModule(settings.plotSettings()));
505 plot->setFileName(fnFrac_);
506 plot->setTitle("Covered fraction");
507 plot->setXAxisIsTime();
508 plot->setYLabel("Fraction");
509 plot->setYFormat(6, 4);
510 for (size_t g = 0; g < sel_.size(); ++g)
512 plot->appendLegend(sel_[g].name());
514 cdata_.addModule(plot);
517 // TODO: For large systems, a float may not have enough precision
518 if (!fnIndex_.empty())
520 AnalysisDataPlotModulePointer plot(
521 new AnalysisDataPlotModule(settings.plotSettings()));
522 plot->setFileName(fnIndex_);
523 plot->setPlainOutput(true);
524 plot->setYFormat(4, 0);
525 idata_.addModule(plot);
527 if (!fnNdx_.empty())
529 std::shared_ptr<IndexFileWriterModule> writer(new IndexFileWriterModule());
530 writer->setFileName(fnNdx_);
531 for (size_t g = 0; g < sel_.size(); ++g)
533 writer->addGroup(sel_[g].name(), sel_[g].isDynamic());
535 idata_.addModule(writer);
538 mdata_.setDataSetCount(sel_.size());
539 for (size_t g = 0; g < sel_.size(); ++g)
541 mdata_.setColumnCount(g, sel_[g].posCount());
543 lifetimeModule_->setCumulative(bCumulativeLifetimes_);
544 if (!fnMask_.empty())
546 AnalysisDataPlotModulePointer plot(
547 new AnalysisDataPlotModule(settings.plotSettings()));
548 plot->setFileName(fnMask_);
549 plot->setTitle("Selection mask");
550 plot->setXAxisIsTime();
551 plot->setYLabel("Occupancy");
552 plot->setYFormat(1, 0);
553 // TODO: Add legend? (there can be massive amount of columns)
554 mdata_.addModule(plot);
556 if (!fnOccupancy_.empty())
558 AnalysisDataPlotModulePointer plot(
559 new AnalysisDataPlotModule(settings.plotSettings()));
560 plot->setFileName(fnOccupancy_);
561 plot->setTitle("Fraction of time selection matches");
562 plot->setXLabel("Selected position");
563 plot->setYLabel("Occupied fraction");
564 for (size_t g = 0; g < sel_.size(); ++g)
566 plot->appendLegend(sel_[g].name());
568 occupancyModule_->addModule(plot);
570 if (!fnLifetime_.empty())
572 AnalysisDataPlotModulePointer plot(
573 new AnalysisDataPlotModule(settings.plotSettings()));
574 plot->setFileName(fnLifetime_);
575 plot->setTitle("Lifetime histogram");
576 plot->setXAxisIsTime();
577 plot->setYLabel("Number of occurrences");
578 for (size_t g = 0; g < sel_.size(); ++g)
580 plot->appendLegend(sel_[g].name());
582 lifetimeModule_->addModule(plot);
585 top_ = &top;
589 void
590 Select::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc * /* pbc */,
591 TrajectoryAnalysisModuleData *pdata)
593 AnalysisDataHandle sdh = pdata->dataHandle(sdata_);
594 AnalysisDataHandle cdh = pdata->dataHandle(cdata_);
595 AnalysisDataHandle idh = pdata->dataHandle(idata_);
596 AnalysisDataHandle mdh = pdata->dataHandle(mdata_);
597 const SelectionList &sel = pdata->parallelSelections(sel_);
598 t_topology *top = top_->topology();
600 sdh.startFrame(frnr, fr.time);
601 for (size_t g = 0; g < sel.size(); ++g)
603 real normfac = bFracNorm_ ? 1.0 / sel[g].coveredFraction() : 1.0;
604 if (bTotNorm_)
606 normfac /= totsize_[g];
608 sdh.setPoint(g, sel[g].posCount() * normfac);
610 sdh.finishFrame();
612 cdh.startFrame(frnr, fr.time);
613 for (size_t g = 0; g < sel.size(); ++g)
615 cdh.setPoint(g, sel[g].coveredFraction());
617 cdh.finishFrame();
619 idh.startFrame(frnr, fr.time);
620 for (size_t g = 0; g < sel.size(); ++g)
622 idh.setPoint(0, sel[g].posCount());
623 idh.finishPointSet();
624 for (int i = 0; i < sel[g].posCount(); ++i)
626 const SelectionPosition &p = sel[g].position(i);
627 if (sel[g].type() == INDEX_RES && !bResInd_)
629 idh.setPoint(1, top->atoms.resinfo[p.mappedId()].nr);
631 else
633 idh.setPoint(1, p.mappedId() + 1);
635 idh.finishPointSet();
638 idh.finishFrame();
640 mdh.startFrame(frnr, fr.time);
641 for (size_t g = 0; g < sel.size(); ++g)
643 mdh.selectDataSet(g);
644 for (int i = 0; i < totsize_[g]; ++i)
646 mdh.setPoint(i, 0);
648 for (int i = 0; i < sel[g].posCount(); ++i)
650 mdh.setPoint(sel[g].position(i).refId(), 1);
653 mdh.finishFrame();
657 void
658 Select::finishAnalysis(int /*nframes*/)
663 void
664 Select::writeOutput()
666 if (!fnPDB_.empty())
668 GMX_RELEASE_ASSERT(top_->hasTopology(),
669 "Topology should have been loaded or an error given earlier");
670 t_atoms atoms;
671 atoms = top_->topology()->atoms;
672 t_pdbinfo *pdbinfo;
673 snew(pdbinfo, atoms.nr);
674 scoped_guard_sfree pdbinfoGuard(pdbinfo);
675 if (atoms.havePdbInfo)
677 std::memcpy(pdbinfo, atoms.pdbinfo, atoms.nr*sizeof(*pdbinfo));
679 else
681 atoms.havePdbInfo = TRUE;
683 atoms.pdbinfo = pdbinfo;
684 for (int i = 0; i < atoms.nr; ++i)
686 pdbinfo[i].occup = 0.0;
688 for (size_t g = 0; g < sel_.size(); ++g)
690 for (int i = 0; i < sel_[g].posCount(); ++i)
692 ConstArrayRef<int> atomIndices
693 = sel_[g].position(i).atomIndices();
694 ConstArrayRef<int>::const_iterator ai;
695 for (ai = atomIndices.begin(); ai != atomIndices.end(); ++ai)
697 pdbinfo[*ai].occup += occupancyModule_->average(g, i);
702 t_trxframe fr;
703 clear_trxframe(&fr, TRUE);
704 fr.bAtoms = TRUE;
705 fr.atoms = &atoms;
706 fr.bX = TRUE;
707 fr.bBox = TRUE;
708 top_->getTopologyConf(&fr.x, fr.box);
710 switch (pdbAtoms_)
712 case PdbAtomsSelection_All:
714 t_trxstatus *status = open_trx(fnPDB_.c_str(), "w");
715 write_trxframe(status, &fr, NULL);
716 close_trx(status);
717 break;
719 case PdbAtomsSelection_MaxSelection:
721 std::set<int> atomIndicesSet;
722 for (size_t g = 0; g < sel_.size(); ++g)
724 ConstArrayRef<int> atomIndices = sel_[g].atomIndices();
725 atomIndicesSet.insert(atomIndices.begin(), atomIndices.end());
727 std::vector<int> allAtomIndices(atomIndicesSet.begin(),
728 atomIndicesSet.end());
729 t_trxstatus *status = open_trx(fnPDB_.c_str(), "w");
730 write_trxframe_indexed(status, &fr, allAtomIndices.size(),
731 allAtomIndices.data(), NULL);
732 close_trx(status);
733 break;
735 case PdbAtomsSelection_Selected:
737 std::vector<int> indices;
738 for (int i = 0; i < atoms.nr; ++i)
740 if (pdbinfo[i].occup > 0.0)
742 indices.push_back(i);
745 t_trxstatus *status = open_trx(fnPDB_.c_str(), "w");
746 write_trxframe_indexed(status, &fr, indices.size(), indices.data(), NULL);
747 close_trx(status);
748 break;
750 default:
751 GMX_RELEASE_ASSERT(false,
752 "Mismatch between -pdbatoms enum values and implementation");
757 } // namespace
759 const char SelectInfo::name[] = "select";
760 const char SelectInfo::shortDescription[] =
761 "Print general information about selections";
763 TrajectoryAnalysisModulePointer SelectInfo::create()
765 return TrajectoryAnalysisModulePointer(new Select);
768 } // namespace analysismodules
770 } // namespace gmx