3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
33 * Declares gmx::Selection and supporting classes.
35 * \author Teemu Murtola <teemu.murtola@gmail.com>
37 * \ingroup module_selection
39 #ifndef GMX_SELECTION_SELECTION_H
40 #define GMX_SELECTION_SELECTION_H
45 #include "../legacyheaders/typedefs.h"
47 #include "../utility/arrayref.h"
48 #include "../utility/common.h"
49 #include "../utility/gmxassert.h"
52 #include "indexutil.h"
53 #include "selectionenums.h"
58 class SelectionOptionStorage;
59 class SelectionTreeElement;
62 class SelectionPosition;
64 //! Container of selections used in public selection interfaces.
65 typedef std::vector<Selection> SelectionList;
71 * Internal data for a single selection.
73 * This class is internal to the selection module, but resides in a public
74 * header because of efficiency reasons: it allows frequently used access
75 * methods in \ref Selection to be inlined.
77 * Methods in this class do not throw unless otherwise specified.
79 * \ingroup module_selection
85 * Creates a new selection object.
87 * \param[in] elem Root of the evaluation tree for this selection.
88 * \param[in] selstr String that was parsed to produce this selection.
89 * \throws std::bad_alloc if out of memory.
91 SelectionData(SelectionTreeElement *elem, const char *selstr);
94 //! Returns the string that was parsed to produce this selection.
95 const char *selectionText() const { return selectionText_.c_str(); }
96 //! Returns true if the size of the selection (posCount()) is dynamic.
97 bool isDynamic() const { return bDynamic_; }
98 //! Number of positions in the selection.
99 int posCount() const { return rawPositions_.nr; }
100 //! Returns the root of the evaluation tree for this selection.
101 SelectionTreeElement &rootElement() { return rootElement_; }
103 //! Returns whether the covered fraction can change between frames.
104 bool isCoveredFractionDynamic() const { return bDynamicCoveredFraction_; }
106 //! Returns true if the given flag is set.
107 bool hasFlag(SelectionFlag flag) const { return flags_.test(flag); }
108 //! Sets the flags for this selection.
109 void setFlags(SelectionFlags flags) { flags_ = flags; }
111 //! \copydoc Selection::initCoveredFraction()
112 bool initCoveredFraction(e_coverfrac_t type);
115 * Computes total masses and charges for all selection positions.
117 * \param[in] top Topology information.
118 * \throws std::bad_alloc if out of memory.
120 * For dynamic selections, the values need to be updated after each
121 * evaluation with refreshMassesAndCharges().
122 * This is done by SelectionEvaluator.
124 * This function is called by SelectionCompiler.
126 * Strong exception safety guarantee.
128 void initializeMassesAndCharges(const t_topology *top);
130 * Updates masses and charges after dynamic selection has been
133 * \param[in] top Topology information.
135 * Called by SelectionEvaluator.
137 void refreshMassesAndCharges(const t_topology *top);
139 * Updates the covered fraction after a selection has been evaluated.
141 * Called by SelectionEvaluator.
143 void updateCoveredFractionForFrame();
145 * Computes average covered fraction after all frames have been evaluated.
147 * \param[in] nframes Number of frames that have been evaluated.
149 * \p nframes should be equal to the number of calls to
150 * updateCoveredFractionForFrame().
151 * Called by SelectionEvaluator::evaluateFinal().
153 void computeAverageCoveredFraction(int nframes);
155 * Restores position information to state it was in after compilation.
157 * \param[in] top Topology information.
159 * Depends on SelectionCompiler storing the original atoms in the
160 * \a rootElement_ object.
161 * Called by SelectionEvaluator::evaluateFinal().
163 void restoreOriginalPositions(const t_topology *top);
166 //! Name of the selection.
168 //! The actual selection string.
169 std::string selectionText_;
170 //! Low-level representation of selected positions.
171 gmx_ana_pos_t rawPositions_;
172 //! Total masses for the current positions.
173 std::vector<real> posMass_;
174 //! Total charges for the current positions.
175 std::vector<real> posCharge_;
176 SelectionFlags flags_;
177 //! Root of the selection evaluation tree.
178 SelectionTreeElement &rootElement_;
179 //! Type of the covered fraction.
180 e_coverfrac_t coveredFractionType_;
181 //! Covered fraction of the selection for the current frame.
182 real coveredFraction_;
183 //! The average covered fraction (over the trajectory).
184 real averageCoveredFraction_;
185 //! true if the value can change as a function of time.
187 //! true if the covered fraction depends on the frame.
188 bool bDynamicCoveredFraction_;
191 * Needed to wrap access to information.
193 friend class gmx::Selection;
195 * Needed for proper access to position information.
197 friend class gmx::SelectionPosition;
199 GMX_DISALLOW_COPY_AND_ASSIGN(SelectionData);
202 } // namespace internal
205 * Provides access to a single selection.
207 * This class provides a public interface for accessing selection information.
208 * General information about the selection can be accessed with methods name(),
209 * selectionText(), isDynamic(), and type(). The first three can be accessed
210 * any time after the selection has been parsed, and type() can be accessed
211 * after the selection has been compiled.
213 * There are a few methods that can be used to change the behavior of the
214 * selection. setEvaluateVelocities() and setEvaluateForces() can be called
215 * before the selection is compiled to request evaluation of velocities and/or
216 * forces in addition to coordinates.
218 * Each selection is made of a set of positions. Each position has associated
219 * coordinates, and possibly velocities and forces if they have been requested
220 * and are available. It also has a set of atoms associated with it; typically
221 * the coordinates are the center-of-mass or center-of-geometry coordinates for
222 * that set of atoms. To access the number of positions in the selection, use
223 * posCount(). To access individual positions, use position().
224 * See SelectionPosition for details of how to use individual positions.
225 * setOriginalId() can be used to adjust the return value of
226 * SelectionPosition::mappedId(); see that method for details.
228 * It is also possible to access the list of atoms that make up all the
229 * positions directly: atomCount() returns the total number of atoms in the
230 * selection and atomIndices() an array of their indices.
231 * Similarly, it is possible to access the coordinates and other properties
232 * of the positions as continuous arrays through coordinates(), velocities(),
233 * forces(), masses(), charges(), refIds(), and mappedIds().
235 * Both positions and atoms can be accessed after the selection has been
236 * compiled. For dynamic selections, the return values of these methods change
237 * after each evaluation to reflect the situation for the current frame.
238 * Before any frame has been evaluated, these methods return the maximal set
239 * to which the selection can evaluate.
241 * There are two possible modes for how positions for dynamic selections are
242 * handled. In the default mode, posCount() can change, and for each frame,
243 * only the positions that are selected in that frame can be accessed. In a
244 * masked mode, posCount() remains constant, i.e., the positions are always
245 * evaluated for the maximal set, and SelectionPosition::selected() is used to
246 * determine whether a position is selected for a frame. The masked mode can
247 * be requested with SelectionOption::dynamicMask().
249 * The class also provides methods for printing out information: printInfo()
250 * and printDebugInfo(). These are mainly for internal use by Gromacs.
252 * This class works like a pointer type: copying and assignment is lightweight,
253 * and all copies work interchangeably, accessing the same internal data.
255 * Methods in this class do not throw.
257 * \see SelectionPosition
260 * \ingroup module_selection
266 * Creates a selection wrapper that has no associated selection.
268 * Any attempt to call methods in the object before a selection is
269 * assigned results in undefined behavior.
271 Selection() : sel_(NULL) {}
273 * Creates a new selection object.
275 * \param sel Selection data to wrap.
277 * Only for internal use by the selection module.
279 explicit Selection(internal::SelectionData *sel) : sel_(sel) {}
281 //! Returns the name of the selection.
282 const char *name() const { return data().name_.c_str(); }
283 //! Returns the string that was parsed to produce this selection.
284 const char *selectionText() const { return data().selectionText(); }
285 //! Returns true if the size of the selection (posCount()) is dynamic.
286 bool isDynamic() const { return data().isDynamic(); }
287 //! Returns the type of positions in the selection.
288 e_index_t type() const { return data().rawPositions_.m.type; }
290 //! Total number of atoms in the selection.
291 int atomCount() const
293 return data().rawPositions_.g != NULL ? data().rawPositions_.g->isize : 0;
295 //! Returns atom indices of all atoms in the selection.
296 ConstArrayRef<int> atomIndices() const
298 if (data().rawPositions_.g == NULL)
300 return ConstArrayRef<int>();
302 return ConstArrayRef<int>(data().rawPositions_.g->index,
303 data().rawPositions_.g->isize);
305 //! Number of positions in the selection.
306 int posCount() const { return data().posCount(); }
307 //! Access a single position.
308 SelectionPosition position(int i) const;
309 //! Returns coordinates for this selection as a continuous array.
310 ConstArrayRef<rvec> coordinates() const
312 return ConstArrayRef<rvec>(data().rawPositions_.x, posCount());
314 //! Returns whether velocities are available for this selection.
315 bool hasVelocities() const { return data().rawPositions_.v != NULL; }
317 * Returns velocities for this selection as a continuous array.
319 * Must not be called if hasVelocities() returns false.
321 ConstArrayRef<rvec> velocities() const
323 GMX_ASSERT(hasVelocities(), "Velocities accessed, but unavailable");
324 return ConstArrayRef<rvec>(data().rawPositions_.v, posCount());
326 //! Returns whether forces are available for this selection.
327 bool hasForces() const { return sel_->rawPositions_.f != NULL; }
329 * Returns forces for this selection as a continuous array.
331 * Must not be called if hasForces() returns false.
333 ConstArrayRef<rvec> forces() const
335 GMX_ASSERT(hasForces(), "Forces accessed, but unavailable");
336 return ConstArrayRef<rvec>(data().rawPositions_.f, posCount());
338 //! Returns masses for this selection as a continuous array.
339 ConstArrayRef<real> masses() const
341 // posMass_ may have more entries than posCount() in the case of
342 // dynamic selections that don't have a topology
343 // (and thus the masses and charges are fixed).
344 GMX_ASSERT(data().posMass_.size() >= static_cast<size_t>(posCount()),
345 "Internal inconsistency");
346 return ConstArrayRef<real>(data().posMass_.begin(),
347 data().posMass_.begin() + posCount());
349 //! Returns charges for this selection as a continuous array.
350 ConstArrayRef<real> charges() const
352 // posCharge_ may have more entries than posCount() in the case of
353 // dynamic selections that don't have a topology
354 // (and thus the masses and charges are fixed).
355 GMX_ASSERT(data().posCharge_.size() >= static_cast<size_t>(posCount()),
356 "Internal inconsistency");
357 return ConstArrayRef<real>(data().posCharge_.begin(),
358 data().posCharge_.begin() + posCount());
361 * Returns reference IDs for this selection as a continuous array.
363 * \see SelectionPosition::refId()
365 ConstArrayRef<int> refIds() const
367 return ConstArrayRef<int>(data().rawPositions_.m.refid, posCount());
370 * Returns mapped IDs for this selection as a continuous array.
372 * \see SelectionPosition::mappedId()
374 ConstArrayRef<int> mappedIds() const
376 return ConstArrayRef<int>(data().rawPositions_.m.mapid, posCount());
379 //! Deprecated method for direct access to position data.
380 const gmx_ana_pos_t *positions() const { return &data().rawPositions_; }
382 //! Returns whether the covered fraction can change between frames.
383 bool isCoveredFractionDynamic() const { return data().isCoveredFractionDynamic(); }
384 //! Returns the covered fraction for the current frame.
385 real coveredFraction() const { return data().coveredFraction_; }
388 * Initializes information about covered fractions.
390 * \param[in] type Type of covered fraction required.
391 * \returns true if the covered fraction can be calculated for the
394 bool initCoveredFraction(e_coverfrac_t type)
396 return data().initCoveredFraction(type);
399 * Sets whether this selection evaluates velocities for positions.
401 * \param[in] bEnabled If true, velocities are evaluated.
403 * If you request the evaluation, but then evaluate the selection for
404 * a frame that does not contain velocity information, results are
408 * Implement it such that in the above case, hasVelocities() will
409 * return false for such frames.
413 void setEvaluateVelocities(bool bEnabled)
415 data().flags_.set(efSelection_EvaluateVelocities, bEnabled);
418 * Sets whether this selection evaluates forces for positions.
420 * \param[in] bEnabled If true, forces are evaluated.
422 * If you request the evaluation, but then evaluate the selection for
423 * a frame that does not contain force information, results are
428 void setEvaluateForces(bool bEnabled)
430 data().flags_.set(efSelection_EvaluateForces, bEnabled);
434 * Sets the ID for the \p i'th position for use with
435 * SelectionPosition::mappedId().
437 * \param[in] i Zero-based index
438 * \param[in] id Identifier to set.
440 * This method is not part of SelectionPosition because that interface
441 * only provides access to const data by design.
443 * This method can only be called after compilation, before the
444 * selection has been evaluated for any frame.
446 * \see SelectionPosition::mappedId()
448 void setOriginalId(int i, int id) { data().rawPositions_.m.orgid[i] = id; }
451 * Prints out one-line description of the selection.
453 * \param[in] fp Where to print the information.
455 * The output contains the name of the selection, the number of atoms
456 * and the number of positions, and indication of whether the selection
459 void printInfo(FILE *fp) const;
461 * Prints out extended information about the selection for debugging.
463 * \param[in] fp Where to print the information.
464 * \param[in] nmaxind Maximum number of values to print in lists
467 void printDebugInfo(FILE *fp, int nmaxind) const;
470 internal::SelectionData &data()
472 GMX_ASSERT(sel_ != NULL,
473 "Attempted to access uninitialized selection");
476 const internal::SelectionData &data() const
478 GMX_ASSERT(sel_ != NULL,
479 "Attempted to access uninitialized selection");
484 * Pointer to internal data for the selection.
486 * The memory for this object is managed by a SelectionCollection
487 * object, and the \ref Selection class simply provides a public
488 * interface for accessing the data.
490 internal::SelectionData *sel_;
493 * Needed to access the data to adjust flags.
495 friend class SelectionOptionStorage;
499 * Provides access to information about a single selected position.
501 * Each position has associated coordinates, and possibly velocities and forces
502 * if they have been requested and are available. It also has a set of atoms
503 * associated with it; typically the coordinates are the center-of-mass or
504 * center-of-geometry coordinates for that set of atoms. It is possible that
505 * there are not atoms associated if the selection has been provided as a fixed
508 * After the selection has been compiled, but not yet evaluated, the contents
509 * of the coordinate, velocity and force vectors are undefined.
511 * Default copy constructor and assignment operators are used, and work as
512 * intended: the copy references the same position and works identically.
514 * Methods in this class do not throw.
519 * \ingroup module_selection
521 class SelectionPosition
525 * Constructs a wrapper object for given selection position.
527 * \param[in] sel Selection from which the position is wrapped.
528 * \param[in] index Zero-based index of the position to wrap.
530 * Asserts if \p index is out of range.
532 * Only for internal use of the library. To obtain a SelectionPosition
533 * object in other code, use Selection::position().
535 SelectionPosition(const internal::SelectionData &sel, int index)
536 : sel_(&sel), i_(index)
538 GMX_ASSERT(index >= 0 && index < sel.posCount(),
539 "Invalid selection position index");
543 * Returns type of this position.
545 * Currently always returns the same as Selection::type().
547 e_index_t type() const { return sel_->rawPositions_.m.type; }
548 //! Returns coordinates for this position.
549 const rvec &x() const
551 return sel_->rawPositions_.x[i_];
554 * Returns velocity for this position.
556 * Must not be called if Selection::hasVelocities() returns false.
558 const rvec &v() const
560 GMX_ASSERT(sel_->rawPositions_.v != NULL,
561 "Velocities accessed, but unavailable");
562 return sel_->rawPositions_.v[i_];
565 * Returns force for this position.
567 * Must not be called if Selection::hasForces() returns false.
569 const rvec &f() const
571 GMX_ASSERT(sel_->rawPositions_.f != NULL,
572 "Velocities accessed, but unavailable");
573 return sel_->rawPositions_.f[i_];
576 * Returns total mass for this position.
578 * Returns the total mass of atoms that make up this position.
579 * If there are no atoms associated or masses are not available,
584 return sel_->posMass_[i_];
587 * Returns total charge for this position.
589 * Returns the sum of charges of atoms that make up this position.
590 * If there are no atoms associated or charges are not available,
595 return sel_->posCharge_[i_];
597 //! Returns the number of atoms that make up this position.
598 int atomCount() const
600 return sel_->rawPositions_.m.mapb.index[i_ + 1]
601 - sel_->rawPositions_.m.mapb.index[i_];
603 //! Return atom indices that make up this position.
604 ConstArrayRef<int> atomIndices() const
606 if (sel_->rawPositions_.g == NULL)
608 return ConstArrayRef<int>();
610 int first = sel_->rawPositions_.m.mapb.index[i_];
611 return ConstArrayRef<int>(&sel_->rawPositions_.g->index[first],
615 * Returns whether this position is selected in the current frame.
617 * The return value is equivalent to \c refid() == -1. Returns always
618 * true if SelectionOption::dynamicMask() has not been set.
622 bool selected() const
627 * Returns reference ID for this position.
629 * For dynamic selections, this provides means to associate positions
630 * across frames. After compilation, these IDs are consequently
631 * numbered starting from zero. For each frame, the ID then reflects
632 * the location of the position in the original array of positions.
633 * If SelectionOption::dynamicMask() has been set for the parent
634 * selection, the IDs for positions not present in the current
635 * selection are set to -1, otherwise they are removed completely.
638 * If a dynamic selection consists of at most three positions, after
639 * compilation refId() will return 0, 1, 2 for them, respectively.
640 * If for a particular frame, only the first and the third are present,
641 * refId() will return 0, 2.
642 * If SelectionOption::dynamicMask() has been set, all three positions
643 * can be accessed also for that frame and refId() will return 0, -1,
648 return sel_->rawPositions_.m.refid[i_];
651 * Returns mapped ID for this position.
653 * Returns ID of the position that corresponds to that set with
654 * Selection::setOriginalId().
656 * If for an array \c id, \c setOriginalId(i, id[i]) has been called
657 * for each \c i, then it always holds that
658 * \c mappedId()==id[refId()].
660 * Selection::setOriginalId() has not been called, the default values
661 * are dependent on type():
662 * - ::INDEX_ATOM: atom indices
663 * - ::INDEX_RES: residue numbers
664 * - ::INDEX_MOL: molecule numbers
666 * All the default values are zero-based
670 return sel_->rawPositions_.m.mapid[i_];
674 const internal::SelectionData *sel_;
679 inline SelectionPosition
680 Selection::position(int i) const
682 return SelectionPosition(data(), i);