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 * Computed values are cached, and need to be updated for dynamic
121 * selections with refreshMassesAndCharges() after the selection has
122 * been evaluated. 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 * Called by SelectionEvaluator.
135 void refreshMassesAndCharges();
137 * Updates the covered fraction after a selection has been evaluated.
139 * Called by SelectionEvaluator.
141 void updateCoveredFractionForFrame();
143 * Computes average covered fraction after all frames have been evaluated.
145 * \param[in] nframes Number of frames that have been evaluated.
147 * \p nframes should be equal to the number of calls to
148 * updateCoveredFractionForFrame().
149 * Called by SelectionEvaluator::evaluateFinal().
151 void computeAverageCoveredFraction(int nframes);
153 * Restores position information to state it was in after compilation.
155 * Depends on SelectionCompiler storing the original atoms in the
156 * \a rootElement_ object.
157 * Called by SelectionEvaluator::evaluateFinal().
159 void restoreOriginalPositions();
163 * Additional information about positions.
165 * This structure contains information about positions in the
166 * selection that is not stored in ::gmx_ana_pos_t.
168 * Methods in this class do not throw.
172 //! Construct position information with unit mass and no charge.
173 PositionInfo() : mass(1.0), charge(0.0) {}
174 //! Construct position information with the given information.
175 PositionInfo(real mass, real charge) : mass(mass), charge(charge) {}
177 //! Total mass of atoms that make up the position.
179 //! Total charge of atoms that make up the position.
183 //! Name of the selection.
185 //! The actual selection string.
186 std::string selectionText_;
187 //! Low-level representation of selected positions.
188 gmx_ana_pos_t rawPositions_;
189 //! Information associated with the current positions.
190 std::vector<PositionInfo> posInfo_;
191 //! Information for all possible positions.
192 std::vector<PositionInfo> originalPosInfo_;
193 SelectionFlags flags_;
194 //! Root of the selection evaluation tree.
195 SelectionTreeElement &rootElement_;
196 //! Type of the covered fraction.
197 e_coverfrac_t coveredFractionType_;
198 //! Covered fraction of the selection for the current frame.
199 real coveredFraction_;
200 //! The average covered fraction (over the trajectory).
201 real averageCoveredFraction_;
202 //! true if the value can change as a function of time.
204 //! true if the covered fraction depends on the frame.
205 bool bDynamicCoveredFraction_;
208 * Needed to wrap access to information.
210 friend class gmx::Selection;
212 * Needed for proper access to position information.
214 friend class gmx::SelectionPosition;
216 GMX_DISALLOW_COPY_AND_ASSIGN(SelectionData);
219 } // namespace internal
222 * Provides access to a single selection.
224 * This class provides a public interface for accessing selection information.
225 * General information about the selection can be accessed with methods name(),
226 * selectionText(), isDynamic(), and type(). The first three can be accessed
227 * any time after the selection has been parsed, and type() can be accessed
228 * after the selection has been compiled.
230 * Each selection is made of a set of positions. Each position has associated
231 * coordinates, and possibly velocities and forces if they have been requested
232 * and are available. It also has a set of atoms associated with it; typically
233 * the coordinates are the center-of-mass or center-of-geometry coordinates for
234 * that set of atoms. To access the number of positions in the selection, use
235 * posCount(). To access individual positions, use position().
236 * See SelectionPosition for details of how to use individual positions.
237 * setOriginalId() can be used to adjust the return value of
238 * SelectionPosition::mappedId(); see that method for details.
240 * It is also possible to access the list of atoms that make up all the
241 * positions directly: atomCount() returns the total number of atoms in the
242 * selection and atomIndices() an array of their indices.
244 * Both positions and atoms can be accessed after the selection has been
245 * compiled. For dynamic selections, the return values of these methods change
246 * after each evaluation to reflect the situation for the current frame.
247 * Before any frame has been evaluated, these methods return the maximal set
248 * to which the selection can evaluate.
250 * There are two possible modes for how positions for dynamic selections are
251 * handled. In the default mode, posCount() can change, and for each frame,
252 * only the positions that are selected in that frame can be accessed. In a
253 * masked mode, posCount() remains constant, i.e., the positions are always
254 * evaluated for the maximal set, and SelectionPosition::selected() is used to
255 * determine whether a position is selected for a frame. The masked mode can
256 * be requested with SelectionOption::dynamicMask().
258 * The class also provides methods for printing out information: printInfo()
259 * and printDebugInfo(). These are mainly for internal use by Gromacs.
261 * This class works like a pointer type: copying and assignment is lightweight,
262 * and all copies work interchangeably, accessing the same internal data.
264 * Methods in this class do not throw.
266 * \see SelectionPosition
269 * \ingroup module_selection
275 * Creates a selection wrapper that has no associated selection.
277 * Any attempt to call methods in the object before a selection is
278 * assigned results in undefined behavior.
280 Selection() : sel_(NULL) {}
282 * Creates a new selection object.
284 * \param sel Selection data to wrap.
286 * Only for internal use by the selection module.
288 explicit Selection(internal::SelectionData *sel) : sel_(sel) {}
290 //! Returns the name of the selection.
291 const char *name() const { return data().name_.c_str(); }
292 //! Returns the string that was parsed to produce this selection.
293 const char *selectionText() const { return data().selectionText(); }
294 //! Returns true if the size of the selection (posCount()) is dynamic.
295 bool isDynamic() const { return data().isDynamic(); }
296 //! Returns the type of positions in the selection.
297 e_index_t type() const { return data().rawPositions_.m.type; }
299 //! Total number of atoms in the selection.
300 int atomCount() const
302 return data().rawPositions_.g != NULL ? data().rawPositions_.g->isize : 0;
304 //! Returns atom indices of all atoms in the selection.
305 ConstArrayRef<int> atomIndices() const
307 if (data().rawPositions_.g == NULL)
309 return ConstArrayRef<int>();
311 return ConstArrayRef<int>(data().rawPositions_.g->isize,
312 data().rawPositions_.g->index);
314 //! Number of positions in the selection.
315 int posCount() const { return data().posCount(); }
316 //! Access a single position.
317 SelectionPosition position(int i) const;
319 * Sets the ID for the \p i'th position for use with
320 * SelectionPosition::mappedId().
322 * \param[in] i Zero-based index
323 * \param[in] id Identifier to set.
325 * This method is not part of SelectionPosition because that interface
326 * only provides access to const data by design.
328 * This method can only be called after compilation, before the
329 * selection has been evaluated for any frame.
331 * \see SelectionPosition::mappedId()
333 void setOriginalId(int i, int id) { data().rawPositions_.m.orgid[i] = id; }
335 //! Deprecated method for direct access to position data.
336 const gmx_ana_pos_t *positions() const { return &data().rawPositions_; }
338 //! Returns whether the covered fraction can change between frames.
339 bool isCoveredFractionDynamic() const { return data().isCoveredFractionDynamic(); }
340 //! Returns the covered fraction for the current frame.
341 real coveredFraction() const { return data().coveredFraction_; }
343 * Initializes information about covered fractions.
345 * \param[in] type Type of covered fraction required.
346 * \returns true if the covered fraction can be calculated for the
349 bool initCoveredFraction(e_coverfrac_t type)
351 return data().initCoveredFraction(type);
355 * Prints out one-line description of the selection.
357 * \param[in] fp Where to print the information.
359 * The output contains the name of the selection, the number of atoms
360 * and the number of positions, and indication of whether the selection
363 void printInfo(FILE *fp) const;
365 * Prints out extended information about the selection for debugging.
367 * \param[in] fp Where to print the information.
368 * \param[in] nmaxind Maximum number of values to print in lists
371 void printDebugInfo(FILE *fp, int nmaxind) const;
374 internal::SelectionData &data()
376 GMX_ASSERT(sel_ != NULL,
377 "Attempted to access uninitialized selection");
380 const internal::SelectionData &data() const
382 GMX_ASSERT(sel_ != NULL,
383 "Attempted to access uninitialized selection");
388 * Pointer to internal data for the selection.
390 * The memory for this object is managed by a SelectionCollection
391 * object, and the \ref Selection class simply provides a public
392 * interface for accessing the data.
394 internal::SelectionData *sel_;
397 * Needed to access the data to adjust flags.
399 friend class SelectionOptionStorage;
403 * Provides access to information about a single selected position.
405 * Each position has associated coordinates, and possibly velocities and forces
406 * if they have been requested and are available. It also has a set of atoms
407 * associated with it; typically the coordinates are the center-of-mass or
408 * center-of-geometry coordinates for that set of atoms. It is possible that
409 * there are not atoms associated if the selection has been provided as a fixed
412 * After the selection has been compiled, but not yet evaluated, the contents
413 * of the coordinate, velocity and force vectors are undefined.
415 * Default copy constructor and assignment operators are used, and work as
416 * intended: the copy references the same position and works identically.
418 * Methods in this class do not throw.
423 * \ingroup module_selection
425 class SelectionPosition
429 * Constructs a wrapper object for given selection position.
431 * \param[in] sel Selection from which the position is wrapped.
432 * \param[in] index Zero-based index of the position to wrap.
434 * Asserts if \p index is out of range.
436 * Only for internal use of the library. To obtain a SelectionPosition
437 * object in other code, use Selection::position().
439 SelectionPosition(const internal::SelectionData &sel, int index)
440 : sel_(&sel), i_(index)
442 GMX_ASSERT(index >= 0 && index < sel.posCount(),
443 "Invalid selection position index");
447 * Returns type of this position.
449 * Currently always returns the same as Selection::type().
451 e_index_t type() const { return sel_->rawPositions_.m.type; }
452 //! Returns coordinates for this position.
453 const rvec &x() const
455 return sel_->rawPositions_.x[i_];
457 //! Returns whether velocity is available for this position.
458 bool hasVelocity() const { return sel_->rawPositions_.v != NULL; }
460 * Returns velocity for this position.
462 * Must not be called if hasVelocity() returns false.
464 const rvec &v() const
466 GMX_ASSERT(hasVelocity(), "Velocities accessed, but unavailable");
467 return sel_->rawPositions_.v[i_];
469 //! Returns whether force is available for this position.
470 bool hasForce() const { return sel_->rawPositions_.f != NULL; }
472 * Returns force for this position.
474 * Must not be called if hasForce() returns false.
476 const rvec &f() const
478 GMX_ASSERT(hasForce(), "Forces accessed, but unavailable");
479 return sel_->rawPositions_.f[i_];
482 * Returns total mass for this position.
484 * Returns the total mass of atoms that make up this position.
485 * If there are no atoms associated or masses are not available,
490 return sel_->posInfo_[i_].mass;
493 * Returns total charge for this position.
495 * Returns the sum of charges of atoms that make up this position.
496 * If there are no atoms associated or charges are not available,
501 return sel_->posInfo_[i_].charge;
503 //! Returns the number of atoms that make up this position.
504 int atomCount() const
506 return sel_->rawPositions_.m.mapb.index[i_ + 1]
507 - sel_->rawPositions_.m.mapb.index[i_];
509 //! Return atom indices that make up this position.
510 ConstArrayRef<int> atomIndices() const
512 if (sel_->rawPositions_.g == NULL)
514 return ConstArrayRef<int>();
516 int first = sel_->rawPositions_.m.mapb.index[i_];
517 return ConstArrayRef<int>(atomCount(),
518 &sel_->rawPositions_.g->index[first]);
521 * Returns whether this position is selected in the current frame.
523 * The return value is equivalent to \c refid() == -1. Returns always
524 * true if SelectionOption::dynamicMask() has not been set.
528 bool selected() const
533 * Returns reference ID for this position.
535 * For dynamic selections, this provides means to associate positions
536 * across frames. After compilation, these IDs are consequently
537 * numbered starting from zero. For each frame, the ID then reflects
538 * the location of the position in the original array of positions.
539 * If SelectionOption::dynamicMask() has been set for the parent
540 * selection, the IDs for positions not present in the current
541 * selection are set to -1, otherwise they are removed completely.
544 * If a dynamic selection consists of at most three positions, after
545 * compilation refId() will return 0, 1, 2 for them, respectively.
546 * If for a particular frame, only the first and the third are present,
547 * refId() will return 0, 2.
548 * If SelectionOption::dynamicMask() has been set, all three positions
549 * can be accessed also for that frame and refId() will return 0, -1,
554 return sel_->rawPositions_.m.refid[i_];
557 * Returns mapped ID for this position.
559 * Returns ID of the position that corresponds to that set with
560 * Selection::setOriginalId().
562 * If for an array \c id, \c setOriginalId(i, id[i]) has been called
563 * for each \c i, then it always holds that
564 * \c mappedId()==id[refId()].
566 * Selection::setOriginalId() has not been called, the default values
567 * are dependent on type():
568 * - ::INDEX_ATOM: atom indices
569 * - ::INDEX_RES: residue numbers
570 * - ::INDEX_MOL: molecule numbers
572 * All the default values are zero-based
576 return sel_->rawPositions_.m.mapid[i_];
580 const internal::SelectionData *sel_;
585 inline SelectionPosition
586 Selection::position(int i) const
588 return SelectionPosition(data(), i);