2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2009,2010,2011,2012,2013,2014, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Declares gmx::Selection and supporting classes.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
41 * \ingroup module_selection
43 #ifndef GMX_SELECTION_SELECTION_H
44 #define GMX_SELECTION_SELECTION_H
49 #include "../legacyheaders/typedefs.h"
51 #include "../utility/arrayref.h"
52 #include "../utility/common.h"
53 #include "../utility/gmxassert.h"
56 #include "indexutil.h"
57 #include "selectionenums.h"
62 class SelectionOptionStorage;
63 class SelectionTreeElement;
65 class AnalysisNeighborhoodPositions;
67 class SelectionPosition;
69 //! Container of selections used in public selection interfaces.
70 typedef std::vector<Selection> SelectionList;
77 * Internal data for a single selection.
79 * This class is internal to the selection module, but resides in a public
80 * header because of efficiency reasons: it allows frequently used access
81 * methods in \ref Selection to be inlined.
83 * Methods in this class do not throw unless otherwise specified.
85 * \ingroup module_selection
91 * Creates a new selection object.
93 * \param[in] elem Root of the evaluation tree for this selection.
94 * \param[in] selstr String that was parsed to produce this selection.
95 * \throws std::bad_alloc if out of memory.
97 SelectionData(SelectionTreeElement *elem, const char *selstr);
100 //! Returns the name for this selection.
101 const char *name() const { return name_.c_str(); }
102 //! Returns the string that was parsed to produce this selection.
103 const char *selectionText() const { return selectionText_.c_str(); }
104 //! Returns true if the size of the selection (posCount()) is dynamic.
105 bool isDynamic() const { return bDynamic_; }
106 //! Returns the type of positions in the selection.
107 e_index_t type() const { return rawPositions_.m.type; }
109 //! Number of positions in the selection.
110 int posCount() const { return rawPositions_.count(); }
111 //! Returns the root of the evaluation tree for this selection.
112 SelectionTreeElement &rootElement() { return rootElement_; }
114 //! Returns whether the covered fraction can change between frames.
115 bool isCoveredFractionDynamic() const { return bDynamicCoveredFraction_; }
117 //! Returns true if the given flag is set.
118 bool hasFlag(SelectionFlag flag) const { return flags_.test(flag); }
119 //! Sets the flags for this selection.
120 void setFlags(SelectionFlags flags) { flags_ = flags; }
122 //! \copydoc Selection::initCoveredFraction()
123 bool initCoveredFraction(e_coverfrac_t type);
126 * Updates the name of the selection if missing.
128 * \throws std::bad_alloc if out of memory.
130 * If selections get their value from a group reference that cannot be
131 * resolved during parsing, the name is final only after group
132 * references have been resolved.
134 * This function is called by SelectionCollection::setIndexGroups().
138 * Computes total masses and charges for all selection positions.
140 * \param[in] top Topology information.
141 * \throws std::bad_alloc if out of memory.
143 * For dynamic selections, the values need to be updated after each
144 * evaluation with refreshMassesAndCharges().
145 * This is done by SelectionEvaluator.
147 * This function is called by SelectionCompiler.
149 * Strong exception safety guarantee.
151 void initializeMassesAndCharges(const t_topology *top);
153 * Updates masses and charges after dynamic selection has been
156 * \param[in] top Topology information.
158 * Called by SelectionEvaluator.
160 void refreshMassesAndCharges(const t_topology *top);
162 * Updates the covered fraction after a selection has been evaluated.
164 * Called by SelectionEvaluator.
166 void updateCoveredFractionForFrame();
168 * Computes average covered fraction after all frames have been evaluated.
170 * \param[in] nframes Number of frames that have been evaluated.
172 * \p nframes should be equal to the number of calls to
173 * updateCoveredFractionForFrame().
174 * Called by SelectionEvaluator::evaluateFinal().
176 void computeAverageCoveredFraction(int nframes);
178 * Restores position information to state it was in after compilation.
180 * \param[in] top Topology information.
182 * Depends on SelectionCompiler storing the original atoms in the
183 * \a rootElement_ object.
184 * Called by SelectionEvaluator::evaluateFinal().
186 void restoreOriginalPositions(const t_topology *top);
189 //! Name of the selection.
191 //! The actual selection string.
192 std::string selectionText_;
193 //! Low-level representation of selected positions.
194 gmx_ana_pos_t rawPositions_;
195 //! Total masses for the current positions.
196 std::vector<real> posMass_;
197 //! Total charges for the current positions.
198 std::vector<real> posCharge_;
199 SelectionFlags flags_;
200 //! Root of the selection evaluation tree.
201 SelectionTreeElement &rootElement_;
202 //! Type of the covered fraction.
203 e_coverfrac_t coveredFractionType_;
204 //! Covered fraction of the selection for the current frame.
205 real coveredFraction_;
206 //! The average covered fraction (over the trajectory).
207 real averageCoveredFraction_;
208 //! true if the value can change as a function of time.
210 //! true if the covered fraction depends on the frame.
211 bool bDynamicCoveredFraction_;
214 * Needed to wrap access to information.
216 friend class gmx::Selection;
218 * Needed for proper access to position information.
220 friend class gmx::SelectionPosition;
222 GMX_DISALLOW_COPY_AND_ASSIGN(SelectionData);
225 } // namespace internal
228 * Provides access to a single selection.
230 * This class provides a public interface for accessing selection information.
231 * General information about the selection can be accessed with methods name(),
232 * selectionText(), isDynamic(), and type(). The first three can be accessed
233 * any time after the selection has been parsed, and type() can be accessed
234 * after the selection has been compiled.
236 * There are a few methods that can be used to change the behavior of the
237 * selection. setEvaluateVelocities() and setEvaluateForces() can be called
238 * before the selection is compiled to request evaluation of velocities and/or
239 * forces in addition to coordinates.
241 * Each selection is made of a set of positions. Each position has associated
242 * coordinates, and possibly velocities and forces if they have been requested
243 * and are available. It also has a set of atoms associated with it; typically
244 * the coordinates are the center-of-mass or center-of-geometry coordinates for
245 * that set of atoms. To access the number of positions in the selection, use
246 * posCount(). To access individual positions, use position().
247 * See SelectionPosition for details of how to use individual positions.
248 * setOriginalId() can be used to adjust the return value of
249 * SelectionPosition::mappedId(); see that method for details.
251 * It is also possible to access the list of atoms that make up all the
252 * positions directly: atomCount() returns the total number of atoms in the
253 * selection and atomIndices() an array of their indices.
254 * Similarly, it is possible to access the coordinates and other properties
255 * of the positions as continuous arrays through coordinates(), velocities(),
256 * forces(), masses(), charges(), refIds(), and mappedIds().
258 * Both positions and atoms can be accessed after the selection has been
259 * compiled. For dynamic selections, the return values of these methods change
260 * after each evaluation to reflect the situation for the current frame.
261 * Before any frame has been evaluated, these methods return the maximal set
262 * to which the selection can evaluate.
264 * There are two possible modes for how positions for dynamic selections are
265 * handled. In the default mode, posCount() can change, and for each frame,
266 * only the positions that are selected in that frame can be accessed. In a
267 * masked mode, posCount() remains constant, i.e., the positions are always
268 * evaluated for the maximal set, and SelectionPosition::selected() is used to
269 * determine whether a position is selected for a frame. The masked mode can
270 * be requested with SelectionOption::dynamicMask().
272 * The class also provides methods for printing out information: printInfo()
273 * and printDebugInfo(). These are mainly for internal use by Gromacs.
275 * This class works like a pointer type: copying and assignment is lightweight,
276 * and all copies work interchangeably, accessing the same internal data.
278 * Methods in this class do not throw.
280 * \see SelectionPosition
283 * \ingroup module_selection
289 * Creates a selection wrapper that has no associated selection.
291 * Any attempt to call methods in the object before a selection is
292 * assigned results in undefined behavior.
293 * isValid() returns `false` for the selection until it is initialized.
295 Selection() : sel_(NULL) {}
297 * Creates a new selection object.
299 * \param sel Selection data to wrap.
301 * Only for internal use by the selection module.
303 explicit Selection(internal::SelectionData *sel) : sel_(sel) {}
305 //! Returns whether the selection object is initialized.
306 bool isValid() const { return sel_ != NULL; }
308 //! Returns whether two selection objects wrap the same selection.
309 bool operator==(const Selection &other) const
311 return sel_ == other.sel_;
313 //! Returns whether two selection objects wrap different selections.
314 bool operator!=(const Selection &other) const
316 return !operator==(other);
319 //! Returns the name of the selection.
320 const char *name() const { return data().name(); }
321 //! Returns the string that was parsed to produce this selection.
322 const char *selectionText() const { return data().selectionText(); }
323 //! Returns true if the size of the selection (posCount()) is dynamic.
324 bool isDynamic() const { return data().isDynamic(); }
325 //! Returns the type of positions in the selection.
326 e_index_t type() const { return data().type(); }
328 //! Total number of atoms in the selection.
329 int atomCount() const
331 return data().rawPositions_.m.mapb.nra;
333 //! Returns atom indices of all atoms in the selection.
334 ConstArrayRef<int> atomIndices() const
336 return constArrayRefFromArray(sel_->rawPositions_.m.mapb.a,
337 sel_->rawPositions_.m.mapb.nra);
339 //! Number of positions in the selection.
340 int posCount() const { return data().posCount(); }
341 //! Access a single position.
342 SelectionPosition position(int i) const;
343 //! Returns coordinates for this selection as a continuous array.
344 ConstArrayRef<rvec> coordinates() const
346 return constArrayRefFromArray(data().rawPositions_.x, posCount());
348 //! Returns whether velocities are available for this selection.
349 bool hasVelocities() const { return data().rawPositions_.v != NULL; }
351 * Returns velocities for this selection as a continuous array.
353 * Must not be called if hasVelocities() returns false.
355 ConstArrayRef<rvec> velocities() const
357 GMX_ASSERT(hasVelocities(), "Velocities accessed, but unavailable");
358 return constArrayRefFromArray(data().rawPositions_.v, posCount());
360 //! Returns whether forces are available for this selection.
361 bool hasForces() const { return sel_->rawPositions_.f != NULL; }
363 * Returns forces for this selection as a continuous array.
365 * Must not be called if hasForces() returns false.
367 ConstArrayRef<rvec> forces() const
369 GMX_ASSERT(hasForces(), "Forces accessed, but unavailable");
370 return constArrayRefFromArray(data().rawPositions_.f, posCount());
372 //! Returns masses for this selection as a continuous array.
373 ConstArrayRef<real> masses() const
375 // posMass_ may have more entries than posCount() in the case of
376 // dynamic selections that don't have a topology
377 // (and thus the masses and charges are fixed).
378 GMX_ASSERT(data().posMass_.size() >= static_cast<size_t>(posCount()),
379 "Internal inconsistency");
380 return constArrayRefFromVector<real>(data().posMass_.begin(),
381 data().posMass_.begin() + posCount());
383 //! Returns charges for this selection as a continuous array.
384 ConstArrayRef<real> charges() const
386 // posCharge_ may have more entries than posCount() in the case of
387 // dynamic selections that don't have a topology
388 // (and thus the masses and charges are fixed).
389 GMX_ASSERT(data().posCharge_.size() >= static_cast<size_t>(posCount()),
390 "Internal inconsistency");
391 return constArrayRefFromVector<real>(data().posCharge_.begin(),
392 data().posCharge_.begin() + posCount());
395 * Returns reference IDs for this selection as a continuous array.
397 * \see SelectionPosition::refId()
399 ConstArrayRef<int> refIds() const
401 return constArrayRefFromArray(data().rawPositions_.m.refid, posCount());
404 * Returns mapped IDs for this selection as a continuous array.
406 * \see SelectionPosition::mappedId()
408 ConstArrayRef<int> mappedIds() const
410 return constArrayRefFromArray(data().rawPositions_.m.mapid, posCount());
413 //! Returns whether the covered fraction can change between frames.
414 bool isCoveredFractionDynamic() const { return data().isCoveredFractionDynamic(); }
415 //! Returns the covered fraction for the current frame.
416 real coveredFraction() const { return data().coveredFraction_; }
419 * Allows passing a selection directly to neighborhood searching.
421 * When initialized this way, AnalysisNeighborhoodPair objects return
422 * indices that can be used to index the selection positions with
425 * Works exactly like if AnalysisNeighborhoodPositions had a
426 * constructor taking a Selection object as a parameter.
427 * See AnalysisNeighborhoodPositions for rationale and additional
430 operator AnalysisNeighborhoodPositions() const;
433 * Initializes information about covered fractions.
435 * \param[in] type Type of covered fraction required.
436 * \returns true if the covered fraction can be calculated for the
439 bool initCoveredFraction(e_coverfrac_t type)
441 return data().initCoveredFraction(type);
444 * Sets whether this selection evaluates velocities for positions.
446 * \param[in] bEnabled If true, velocities are evaluated.
448 * If you request the evaluation, but then evaluate the selection for
449 * a frame that does not contain velocity information, results are
453 * Implement it such that in the above case, hasVelocities() will
454 * return false for such frames.
458 void setEvaluateVelocities(bool bEnabled)
460 data().flags_.set(efSelection_EvaluateVelocities, bEnabled);
463 * Sets whether this selection evaluates forces for positions.
465 * \param[in] bEnabled If true, forces are evaluated.
467 * If you request the evaluation, but then evaluate the selection for
468 * a frame that does not contain force information, results are
473 void setEvaluateForces(bool bEnabled)
475 data().flags_.set(efSelection_EvaluateForces, bEnabled);
479 * Sets the ID for the \p i'th position for use with
480 * SelectionPosition::mappedId().
482 * \param[in] i Zero-based index
483 * \param[in] id Identifier to set.
485 * This method is not part of SelectionPosition because that interface
486 * only provides access to const data by design.
488 * This method can only be called after compilation, before the
489 * selection has been evaluated for any frame.
491 * \see SelectionPosition::mappedId()
493 void setOriginalId(int i, int id) { data().rawPositions_.m.orgid[i] = id; }
496 * Prints out one-line description of the selection.
498 * \param[in] fp Where to print the information.
500 * The output contains the name of the selection, the number of atoms
501 * and the number of positions, and indication of whether the selection
504 void printInfo(FILE *fp) const;
506 * Prints out extended information about the selection for debugging.
508 * \param[in] fp Where to print the information.
509 * \param[in] nmaxind Maximum number of values to print in lists
512 void printDebugInfo(FILE *fp, int nmaxind) const;
515 internal::SelectionData &data()
517 GMX_ASSERT(sel_ != NULL,
518 "Attempted to access uninitialized selection");
521 const internal::SelectionData &data() const
523 GMX_ASSERT(sel_ != NULL,
524 "Attempted to access uninitialized selection");
529 * Pointer to internal data for the selection.
531 * The memory for this object is managed by a SelectionCollection
532 * object, and the \ref Selection class simply provides a public
533 * interface for accessing the data.
535 internal::SelectionData *sel_;
538 * Needed to access the data to adjust flags.
540 friend class SelectionOptionStorage;
544 * Provides access to information about a single selected position.
546 * Each position has associated coordinates, and possibly velocities and forces
547 * if they have been requested and are available. It also has a set of atoms
548 * associated with it; typically the coordinates are the center-of-mass or
549 * center-of-geometry coordinates for that set of atoms. It is possible that
550 * there are not atoms associated if the selection has been provided as a fixed
553 * After the selection has been compiled, but not yet evaluated, the contents
554 * of the coordinate, velocity and force vectors are undefined.
556 * Default copy constructor and assignment operators are used, and work as
557 * intended: the copy references the same position and works identically.
559 * Methods in this class do not throw.
564 * \ingroup module_selection
566 class SelectionPosition
570 * Constructs a wrapper object for given selection position.
572 * \param[in] sel Selection from which the position is wrapped.
573 * \param[in] index Zero-based index of the position to wrap.
575 * Asserts if \p index is out of range.
577 * Only for internal use of the library. To obtain a SelectionPosition
578 * object in other code, use Selection::position().
580 SelectionPosition(const internal::SelectionData &sel, int index)
581 : sel_(&sel), i_(index)
583 GMX_ASSERT(index >= 0 && index < sel.posCount(),
584 "Invalid selection position index");
588 * Returns type of this position.
590 * Currently always returns the same as Selection::type().
592 e_index_t type() const { return sel_->type(); }
593 //! Returns coordinates for this position.
594 const rvec &x() const
596 return sel_->rawPositions_.x[i_];
599 * Returns velocity for this position.
601 * Must not be called if Selection::hasVelocities() returns false.
603 const rvec &v() const
605 GMX_ASSERT(sel_->rawPositions_.v != NULL,
606 "Velocities accessed, but unavailable");
607 return sel_->rawPositions_.v[i_];
610 * Returns force for this position.
612 * Must not be called if Selection::hasForces() returns false.
614 const rvec &f() const
616 GMX_ASSERT(sel_->rawPositions_.f != NULL,
617 "Velocities accessed, but unavailable");
618 return sel_->rawPositions_.f[i_];
621 * Returns total mass for this position.
623 * Returns the total mass of atoms that make up this position.
624 * If there are no atoms associated or masses are not available,
629 return sel_->posMass_[i_];
632 * Returns total charge for this position.
634 * Returns the sum of charges of atoms that make up this position.
635 * If there are no atoms associated or charges are not available,
640 return sel_->posCharge_[i_];
642 //! Returns the number of atoms that make up this position.
643 int atomCount() const
645 return sel_->rawPositions_.m.mapb.index[i_ + 1]
646 - sel_->rawPositions_.m.mapb.index[i_];
648 //! Return atom indices that make up this position.
649 ConstArrayRef<int> atomIndices() const
651 const int *atoms = sel_->rawPositions_.m.mapb.a;
654 return ConstArrayRef<int>();
656 const int first = sel_->rawPositions_.m.mapb.index[i_];
657 return constArrayRefFromArray(&atoms[first], atomCount());
660 * Returns whether this position is selected in the current frame.
662 * The return value is equivalent to \c refid() == -1. Returns always
663 * true if SelectionOption::dynamicMask() has not been set.
667 bool selected() const
672 * Returns reference ID for this position.
674 * For dynamic selections, this provides means to associate positions
675 * across frames. After compilation, these IDs are consequently
676 * numbered starting from zero. For each frame, the ID then reflects
677 * the location of the position in the original array of positions.
678 * If SelectionOption::dynamicMask() has been set for the parent
679 * selection, the IDs for positions not present in the current
680 * selection are set to -1, otherwise they are removed completely.
683 * If a dynamic selection consists of at most three positions, after
684 * compilation refId() will return 0, 1, 2 for them, respectively.
685 * If for a particular frame, only the first and the third are present,
686 * refId() will return 0, 2.
687 * If SelectionOption::dynamicMask() has been set, all three positions
688 * can be accessed also for that frame and refId() will return 0, -1,
693 return sel_->rawPositions_.m.refid[i_];
696 * Returns mapped ID for this position.
698 * Returns ID of the position that corresponds to that set with
699 * Selection::setOriginalId().
701 * If for an array \c id, \c setOriginalId(i, id[i]) has been called
702 * for each \c i, then it always holds that
703 * \c mappedId()==id[refId()].
705 * Selection::setOriginalId() has not been called, the default values
706 * are dependent on type():
707 * - ::INDEX_ATOM: atom indices
708 * - ::INDEX_RES: residue numbers
709 * - ::INDEX_MOL: molecule numbers
711 * All the default values are zero-based
715 return sel_->rawPositions_.m.mapid[i_];
719 * Allows passing a selection position directly to neighborhood searching.
721 * When initialized this way, AnalysisNeighborhoodPair objects return
722 * the index that can be used to access this position using
723 * Selection::position().
725 * Works exactly like if AnalysisNeighborhoodPositions had a
726 * constructor taking a SelectionPosition object as a parameter.
727 * See AnalysisNeighborhoodPositions for rationale and additional
730 operator AnalysisNeighborhoodPositions() const;
733 const internal::SelectionData *sel_;
738 inline SelectionPosition
739 Selection::position(int i) const
741 return SelectionPosition(data(), i);