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@cbr.su.se>
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 * Each selection is made of a set of positions. Each position has associated
214 * coordinates, and possibly velocities and forces if they have been requested
215 * and are available. It also has a set of atoms associated with it; typically
216 * the coordinates are the center-of-mass or center-of-geometry coordinates for
217 * that set of atoms. To access the number of positions in the selection, use
218 * posCount(). To access individual positions, use position().
219 * See SelectionPosition for details of how to use individual positions.
220 * setOriginalId() can be used to adjust the return value of
221 * SelectionPosition::mappedId(); see that method for details.
223 * It is also possible to access the list of atoms that make up all the
224 * positions directly: atomCount() returns the total number of atoms in the
225 * selection and atomIndices() an array of their indices.
226 * Similarly, it is possible to access the coordinates and other properties
227 * of the positions as continuous arrays through coordinates(), velocities(),
228 * forces(), masses(), charges(), refIds(), and mappedIds().
230 * Both positions and atoms can be accessed after the selection has been
231 * compiled. For dynamic selections, the return values of these methods change
232 * after each evaluation to reflect the situation for the current frame.
233 * Before any frame has been evaluated, these methods return the maximal set
234 * to which the selection can evaluate.
236 * There are two possible modes for how positions for dynamic selections are
237 * handled. In the default mode, posCount() can change, and for each frame,
238 * only the positions that are selected in that frame can be accessed. In a
239 * masked mode, posCount() remains constant, i.e., the positions are always
240 * evaluated for the maximal set, and SelectionPosition::selected() is used to
241 * determine whether a position is selected for a frame. The masked mode can
242 * be requested with SelectionOption::dynamicMask().
244 * The class also provides methods for printing out information: printInfo()
245 * and printDebugInfo(). These are mainly for internal use by Gromacs.
247 * This class works like a pointer type: copying and assignment is lightweight,
248 * and all copies work interchangeably, accessing the same internal data.
250 * Methods in this class do not throw.
252 * \see SelectionPosition
255 * \ingroup module_selection
261 * Creates a selection wrapper that has no associated selection.
263 * Any attempt to call methods in the object before a selection is
264 * assigned results in undefined behavior.
266 Selection() : sel_(NULL) {}
268 * Creates a new selection object.
270 * \param sel Selection data to wrap.
272 * Only for internal use by the selection module.
274 explicit Selection(internal::SelectionData *sel) : sel_(sel) {}
276 //! Returns the name of the selection.
277 const char *name() const { return data().name_.c_str(); }
278 //! Returns the string that was parsed to produce this selection.
279 const char *selectionText() const { return data().selectionText(); }
280 //! Returns true if the size of the selection (posCount()) is dynamic.
281 bool isDynamic() const { return data().isDynamic(); }
282 //! Returns the type of positions in the selection.
283 e_index_t type() const { return data().rawPositions_.m.type; }
285 //! Total number of atoms in the selection.
286 int atomCount() const
288 return data().rawPositions_.g != NULL ? data().rawPositions_.g->isize : 0;
290 //! Returns atom indices of all atoms in the selection.
291 ConstArrayRef<int> atomIndices() const
293 if (data().rawPositions_.g == NULL)
295 return ConstArrayRef<int>();
297 return ConstArrayRef<int>(data().rawPositions_.g->index,
298 data().rawPositions_.g->isize);
300 //! Number of positions in the selection.
301 int posCount() const { return data().posCount(); }
302 //! Access a single position.
303 SelectionPosition position(int i) const;
304 //! Returns coordinates for this selection as a continuous array.
305 ConstArrayRef<rvec> coordinates() const
307 return ConstArrayRef<rvec>(data().rawPositions_.x, posCount());
309 //! Returns whether velocities are available for this selection.
310 bool hasVelocities() const { return data().rawPositions_.v != NULL; }
312 * Returns velocities for this selection as a continuous array.
314 * Must not be called if hasVelocities() returns false.
316 ConstArrayRef<rvec> velocities() const
318 GMX_ASSERT(hasVelocities(), "Velocities accessed, but unavailable");
319 return ConstArrayRef<rvec>(data().rawPositions_.v, posCount());
321 //! Returns whether forces are available for this selection.
322 bool hasForces() const { return sel_->rawPositions_.f != NULL; }
324 * Returns forces for this selection as a continuous array.
326 * Must not be called if hasForces() returns false.
328 ConstArrayRef<rvec> forces() const
330 GMX_ASSERT(hasForces(), "Forces accessed, but unavailable");
331 return ConstArrayRef<rvec>(data().rawPositions_.f, posCount());
333 //! Returns masses for this selection as a continuous array.
334 ConstArrayRef<real> masses() const
336 // posMass_ may have more entries than posCount() in the case of
337 // dynamic selections that don't have a topology
338 // (and thus the masses and charges are fixed).
339 GMX_ASSERT(data().posMass_.size() >= static_cast<size_t>(posCount()),
340 "Internal inconsistency");
341 return ConstArrayRef<real>(data().posMass_.begin(),
342 data().posMass_.begin() + posCount());
344 //! Returns charges for this selection as a continuous array.
345 ConstArrayRef<real> charges() const
347 // posCharge_ may have more entries than posCount() in the case of
348 // dynamic selections that don't have a topology
349 // (and thus the masses and charges are fixed).
350 GMX_ASSERT(data().posCharge_.size() >= static_cast<size_t>(posCount()),
351 "Internal inconsistency");
352 return ConstArrayRef<real>(data().posCharge_.begin(),
353 data().posCharge_.begin() + posCount());
356 * Returns reference IDs for this selection as a continuous array.
358 * \see SelectionPosition::refId()
360 ConstArrayRef<int> refIds() const
362 return ConstArrayRef<int>(data().rawPositions_.m.refid, posCount());
365 * Returns mapped IDs for this selection as a continuous array.
367 * \see SelectionPosition::mappedId()
369 ConstArrayRef<int> mappedIds() const
371 return ConstArrayRef<int>(data().rawPositions_.m.mapid, posCount());
374 * Sets the ID for the \p i'th position for use with
375 * SelectionPosition::mappedId().
377 * \param[in] i Zero-based index
378 * \param[in] id Identifier to set.
380 * This method is not part of SelectionPosition because that interface
381 * only provides access to const data by design.
383 * This method can only be called after compilation, before the
384 * selection has been evaluated for any frame.
386 * \see SelectionPosition::mappedId()
388 void setOriginalId(int i, int id) { data().rawPositions_.m.orgid[i] = id; }
390 //! Deprecated method for direct access to position data.
391 const gmx_ana_pos_t *positions() const { return &data().rawPositions_; }
393 //! Returns whether the covered fraction can change between frames.
394 bool isCoveredFractionDynamic() const { return data().isCoveredFractionDynamic(); }
395 //! Returns the covered fraction for the current frame.
396 real coveredFraction() const { return data().coveredFraction_; }
398 * Initializes information about covered fractions.
400 * \param[in] type Type of covered fraction required.
401 * \returns true if the covered fraction can be calculated for the
404 bool initCoveredFraction(e_coverfrac_t type)
406 return data().initCoveredFraction(type);
410 * Prints out one-line description of the selection.
412 * \param[in] fp Where to print the information.
414 * The output contains the name of the selection, the number of atoms
415 * and the number of positions, and indication of whether the selection
418 void printInfo(FILE *fp) const;
420 * Prints out extended information about the selection for debugging.
422 * \param[in] fp Where to print the information.
423 * \param[in] nmaxind Maximum number of values to print in lists
426 void printDebugInfo(FILE *fp, int nmaxind) const;
429 internal::SelectionData &data()
431 GMX_ASSERT(sel_ != NULL,
432 "Attempted to access uninitialized selection");
435 const internal::SelectionData &data() const
437 GMX_ASSERT(sel_ != NULL,
438 "Attempted to access uninitialized selection");
443 * Pointer to internal data for the selection.
445 * The memory for this object is managed by a SelectionCollection
446 * object, and the \ref Selection class simply provides a public
447 * interface for accessing the data.
449 internal::SelectionData *sel_;
452 * Needed to access the data to adjust flags.
454 friend class SelectionOptionStorage;
458 * Provides access to information about a single selected position.
460 * Each position has associated coordinates, and possibly velocities and forces
461 * if they have been requested and are available. It also has a set of atoms
462 * associated with it; typically the coordinates are the center-of-mass or
463 * center-of-geometry coordinates for that set of atoms. It is possible that
464 * there are not atoms associated if the selection has been provided as a fixed
467 * After the selection has been compiled, but not yet evaluated, the contents
468 * of the coordinate, velocity and force vectors are undefined.
470 * Default copy constructor and assignment operators are used, and work as
471 * intended: the copy references the same position and works identically.
473 * Methods in this class do not throw.
478 * \ingroup module_selection
480 class SelectionPosition
484 * Constructs a wrapper object for given selection position.
486 * \param[in] sel Selection from which the position is wrapped.
487 * \param[in] index Zero-based index of the position to wrap.
489 * Asserts if \p index is out of range.
491 * Only for internal use of the library. To obtain a SelectionPosition
492 * object in other code, use Selection::position().
494 SelectionPosition(const internal::SelectionData &sel, int index)
495 : sel_(&sel), i_(index)
497 GMX_ASSERT(index >= 0 && index < sel.posCount(),
498 "Invalid selection position index");
502 * Returns type of this position.
504 * Currently always returns the same as Selection::type().
506 e_index_t type() const { return sel_->rawPositions_.m.type; }
507 //! Returns coordinates for this position.
508 const rvec &x() const
510 return sel_->rawPositions_.x[i_];
513 * Returns velocity for this position.
515 * Must not be called if Selection::hasVelocities() returns false.
517 const rvec &v() const
519 GMX_ASSERT(sel_->rawPositions_.v != NULL,
520 "Velocities accessed, but unavailable");
521 return sel_->rawPositions_.v[i_];
524 * Returns force for this position.
526 * Must not be called if Selection::hasForces() returns false.
528 const rvec &f() const
530 GMX_ASSERT(sel_->rawPositions_.f != NULL,
531 "Velocities accessed, but unavailable");
532 return sel_->rawPositions_.f[i_];
535 * Returns total mass for this position.
537 * Returns the total mass of atoms that make up this position.
538 * If there are no atoms associated or masses are not available,
543 return sel_->posMass_[i_];
546 * Returns total charge for this position.
548 * Returns the sum of charges of atoms that make up this position.
549 * If there are no atoms associated or charges are not available,
554 return sel_->posCharge_[i_];
556 //! Returns the number of atoms that make up this position.
557 int atomCount() const
559 return sel_->rawPositions_.m.mapb.index[i_ + 1]
560 - sel_->rawPositions_.m.mapb.index[i_];
562 //! Return atom indices that make up this position.
563 ConstArrayRef<int> atomIndices() const
565 if (sel_->rawPositions_.g == NULL)
567 return ConstArrayRef<int>();
569 int first = sel_->rawPositions_.m.mapb.index[i_];
570 return ConstArrayRef<int>(&sel_->rawPositions_.g->index[first],
574 * Returns whether this position is selected in the current frame.
576 * The return value is equivalent to \c refid() == -1. Returns always
577 * true if SelectionOption::dynamicMask() has not been set.
581 bool selected() const
586 * Returns reference ID for this position.
588 * For dynamic selections, this provides means to associate positions
589 * across frames. After compilation, these IDs are consequently
590 * numbered starting from zero. For each frame, the ID then reflects
591 * the location of the position in the original array of positions.
592 * If SelectionOption::dynamicMask() has been set for the parent
593 * selection, the IDs for positions not present in the current
594 * selection are set to -1, otherwise they are removed completely.
597 * If a dynamic selection consists of at most three positions, after
598 * compilation refId() will return 0, 1, 2 for them, respectively.
599 * If for a particular frame, only the first and the third are present,
600 * refId() will return 0, 2.
601 * If SelectionOption::dynamicMask() has been set, all three positions
602 * can be accessed also for that frame and refId() will return 0, -1,
607 return sel_->rawPositions_.m.refid[i_];
610 * Returns mapped ID for this position.
612 * Returns ID of the position that corresponds to that set with
613 * Selection::setOriginalId().
615 * If for an array \c id, \c setOriginalId(i, id[i]) has been called
616 * for each \c i, then it always holds that
617 * \c mappedId()==id[refId()].
619 * Selection::setOriginalId() has not been called, the default values
620 * are dependent on type():
621 * - ::INDEX_ATOM: atom indices
622 * - ::INDEX_RES: residue numbers
623 * - ::INDEX_MOL: molecule numbers
625 * All the default values are zero-based
629 return sel_->rawPositions_.m.mapid[i_];
633 const internal::SelectionData *sel_;
638 inline SelectionPosition
639 Selection::position(int i) const
641 return SelectionPosition(data(), i);