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.
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 "gromacs/selection/position.h"
50 #include "gromacs/selection/selectionenums.h"
51 #include "gromacs/utility/arrayref.h"
52 #include "gromacs/utility/classhelpers.h"
53 #include "gromacs/utility/gmxassert.h"
61 class SelectionOptionStorage
;
62 class SelectionTreeElement
;
64 class AnalysisNeighborhoodPositions
;
66 class SelectionPosition
;
68 //! Container of selections used in public selection interfaces.
69 typedef std::vector
<Selection
> SelectionList
;
76 * Internal data for a single selection.
78 * This class is internal to the selection module, but resides in a public
79 * header because of efficiency reasons: it allows frequently used access
80 * methods in \ref Selection to be inlined.
82 * Methods in this class do not throw unless otherwise specified.
84 * \ingroup module_selection
90 * Creates a new selection object.
92 * \param[in] elem Root of the evaluation tree for this selection.
93 * \param[in] selstr String that was parsed to produce this selection.
94 * \throws std::bad_alloc if out of memory.
96 SelectionData(SelectionTreeElement
*elem
, const char *selstr
);
99 //! Returns the name for this selection.
100 const char *name() const { return name_
.c_str(); }
101 //! Returns the string that was parsed to produce this selection.
102 const char *selectionText() const { return selectionText_
.c_str(); }
103 //! Returns true if the size of the selection (posCount()) is dynamic.
104 bool isDynamic() const { return bDynamic_
; }
105 //! Returns the type of positions in the selection.
106 e_index_t
type() const { return rawPositions_
.m
.type
; }
107 //! Returns true if the selection only contains positions with a single atom each.
108 bool hasOnlyAtoms() const { return type() == INDEX_ATOM
; }
109 //! Returns `true` if the atom indices in the selection are in ascending order.
110 bool hasSortedAtomIndices() const;
112 //! Number of positions in the selection.
113 int posCount() const { return rawPositions_
.count(); }
114 //! Returns the root of the evaluation tree for this selection.
115 SelectionTreeElement
&rootElement() { return rootElement_
; }
117 //! Returns whether the covered fraction can change between frames.
118 bool isCoveredFractionDynamic() const { return bDynamicCoveredFraction_
; }
120 //! Returns true if the given flag is set.
121 bool hasFlag(SelectionFlag flag
) const { return flags_
.test(flag
); }
122 //! Sets the flags for this selection.
123 void setFlags(SelectionFlags flags
) { flags_
= flags
; }
125 //! \copydoc Selection::initCoveredFraction()
126 bool initCoveredFraction(e_coverfrac_t type
);
129 * Updates the name of the selection if missing.
131 * \throws std::bad_alloc if out of memory.
133 * If selections get their value from a group reference that cannot be
134 * resolved during parsing, the name is final only after group
135 * references have been resolved.
137 * This function is called by SelectionCollection::setIndexGroups().
141 * Computes total masses and charges for all selection positions.
143 * \param[in] top Topology information.
144 * \throws std::bad_alloc if out of memory.
146 * For dynamic selections, the values need to be updated after each
147 * evaluation with refreshMassesAndCharges().
148 * This is done by SelectionEvaluator.
150 * This function is called by SelectionCompiler.
152 * Strong exception safety guarantee.
154 void initializeMassesAndCharges(const t_topology
*top
);
156 * Updates masses and charges after dynamic selection has been
159 * \param[in] top Topology information.
161 * Called by SelectionEvaluator.
163 void refreshMassesAndCharges(const t_topology
*top
);
165 * Updates the covered fraction after a selection has been evaluated.
167 * Called by SelectionEvaluator.
169 void updateCoveredFractionForFrame();
171 * Computes average covered fraction after all frames have been evaluated.
173 * \param[in] nframes Number of frames that have been evaluated.
175 * \p nframes should be equal to the number of calls to
176 * updateCoveredFractionForFrame().
177 * Called by SelectionEvaluator::evaluateFinal().
179 void computeAverageCoveredFraction(int nframes
);
181 * Restores position information to state it was in after compilation.
183 * \param[in] top Topology information.
185 * Depends on SelectionCompiler storing the original atoms in the
186 * \a rootElement_ object.
187 * Called by SelectionEvaluator::evaluateFinal().
189 void restoreOriginalPositions(const t_topology
*top
);
192 //! Name of the selection.
194 //! The actual selection string.
195 std::string selectionText_
;
196 //! Low-level representation of selected positions.
197 gmx_ana_pos_t rawPositions_
;
198 //! Total masses for the current positions.
199 std::vector
<real
> posMass_
;
200 //! Total charges for the current positions.
201 std::vector
<real
> posCharge_
;
202 SelectionFlags flags_
;
203 //! Root of the selection evaluation tree.
204 SelectionTreeElement
&rootElement_
;
205 //! Type of the covered fraction.
206 e_coverfrac_t coveredFractionType_
;
207 //! Covered fraction of the selection for the current frame.
208 real coveredFraction_
;
209 //! The average covered fraction (over the trajectory).
210 real averageCoveredFraction_
;
211 //! true if the value can change as a function of time.
213 //! true if the covered fraction depends on the frame.
214 bool bDynamicCoveredFraction_
;
217 * Needed to wrap access to information.
219 friend class gmx::Selection
;
221 * Needed for proper access to position information.
223 friend class gmx::SelectionPosition
;
225 GMX_DISALLOW_COPY_AND_ASSIGN(SelectionData
);
228 } // namespace internal
231 * Provides access to a single selection.
233 * This class provides a public interface for accessing selection information.
234 * General information about the selection can be accessed with methods name(),
235 * selectionText(), isDynamic(), and type(). The first three can be accessed
236 * any time after the selection has been parsed, and type() can be accessed
237 * after the selection has been compiled.
239 * There are a few methods that can be used to change the behavior of the
240 * selection. setEvaluateVelocities() and setEvaluateForces() can be called
241 * before the selection is compiled to request evaluation of velocities and/or
242 * forces in addition to coordinates.
244 * Each selection is made of a set of positions. Each position has associated
245 * coordinates, and possibly velocities and forces if they have been requested
246 * and are available. It also has a set of atoms associated with it; typically
247 * the coordinates are the center-of-mass or center-of-geometry coordinates for
248 * that set of atoms. To access the number of positions in the selection, use
249 * posCount(). To access individual positions, use position().
250 * See SelectionPosition for details of how to use individual positions.
251 * setOriginalId() can be used to adjust the return value of
252 * SelectionPosition::mappedId(); see that method for details.
254 * It is also possible to access the list of atoms that make up all the
255 * positions directly: atomCount() returns the total number of atoms in the
256 * selection and atomIndices() an array of their indices.
257 * Similarly, it is possible to access the coordinates and other properties
258 * of the positions as continuous arrays through coordinates(), velocities(),
259 * forces(), masses(), charges(), refIds(), and mappedIds().
261 * Both positions and atoms can be accessed after the selection has been
262 * compiled. For dynamic selections, the return values of these methods change
263 * after each evaluation to reflect the situation for the current frame.
264 * Before any frame has been evaluated, these methods return the maximal set
265 * to which the selection can evaluate.
267 * There are two possible modes for how positions for dynamic selections are
268 * handled. In the default mode, posCount() can change, and for each frame,
269 * only the positions that are selected in that frame can be accessed. In a
270 * masked mode, posCount() remains constant, i.e., the positions are always
271 * evaluated for the maximal set, and SelectionPosition::selected() is used to
272 * determine whether a position is selected for a frame. The masked mode can
273 * be requested with SelectionOption::dynamicMask().
275 * The class also provides methods for printing out information: printInfo()
276 * and printDebugInfo(). These are mainly for internal use by Gromacs.
278 * This class works like a pointer type: copying and assignment is lightweight,
279 * and all copies work interchangeably, accessing the same internal data.
281 * Methods in this class do not throw.
283 * \see SelectionPosition
286 * \ingroup module_selection
292 * Creates a selection wrapper that has no associated selection.
294 * Any attempt to call methods in the object before a selection is
295 * assigned results in undefined behavior.
296 * isValid() returns `false` for the selection until it is initialized.
298 Selection() : sel_(NULL
) {}
300 * Creates a new selection object.
302 * \param sel Selection data to wrap.
304 * Only for internal use by the selection module.
306 explicit Selection(internal::SelectionData
*sel
) : sel_(sel
) {}
308 //! Returns whether the selection object is initialized.
309 bool isValid() const { return sel_
!= NULL
; }
311 //! Returns whether two selection objects wrap the same selection.
312 bool operator==(const Selection
&other
) const
314 return sel_
== other
.sel_
;
316 //! Returns whether two selection objects wrap different selections.
317 bool operator!=(const Selection
&other
) const
319 return !operator==(other
);
322 //! Returns the name of the selection.
323 const char *name() const { return data().name(); }
324 //! Returns the string that was parsed to produce this selection.
325 const char *selectionText() const { return data().selectionText(); }
326 //! Returns true if the size of the selection (posCount()) is dynamic.
327 bool isDynamic() const { return data().isDynamic(); }
328 //! Returns the type of positions in the selection.
329 e_index_t
type() const { return data().type(); }
330 //! Returns true if the selection only contains positions with a single atom each.
331 bool hasOnlyAtoms() const { return data().hasOnlyAtoms(); }
332 //! Returns `true` if the atom indices in the selection are in ascending order.
333 bool hasSortedAtomIndices() const { return data().hasSortedAtomIndices(); }
335 //! Total number of atoms in the selection.
336 int atomCount() const
338 return data().rawPositions_
.m
.mapb
.nra
;
340 //! Returns atom indices of all atoms in the selection.
341 ConstArrayRef
<int> atomIndices() const
343 return constArrayRefFromArray(sel_
->rawPositions_
.m
.mapb
.a
,
344 sel_
->rawPositions_
.m
.mapb
.nra
);
346 //! Number of positions in the selection.
347 int posCount() const { return data().posCount(); }
348 //! Access a single position.
349 SelectionPosition
position(int i
) const;
350 //! Returns coordinates for this selection as a continuous array.
351 ConstArrayRef
<rvec
> coordinates() const
353 return constArrayRefFromArray(data().rawPositions_
.x
, posCount());
355 //! Returns whether velocities are available for this selection.
356 bool hasVelocities() const { return data().rawPositions_
.v
!= NULL
; }
358 * Returns velocities for this selection as a continuous array.
360 * Must not be called if hasVelocities() returns false.
362 ConstArrayRef
<rvec
> velocities() const
364 GMX_ASSERT(hasVelocities(), "Velocities accessed, but unavailable");
365 return constArrayRefFromArray(data().rawPositions_
.v
, posCount());
367 //! Returns whether forces are available for this selection.
368 bool hasForces() const { return sel_
->rawPositions_
.f
!= NULL
; }
370 * Returns forces for this selection as a continuous array.
372 * Must not be called if hasForces() returns false.
374 ConstArrayRef
<rvec
> forces() const
376 GMX_ASSERT(hasForces(), "Forces accessed, but unavailable");
377 return constArrayRefFromArray(data().rawPositions_
.f
, posCount());
379 //! Returns masses for this selection as a continuous array.
380 ConstArrayRef
<real
> masses() const
382 // posMass_ may have more entries than posCount() in the case of
383 // dynamic selections that don't have a topology
384 // (and thus the masses and charges are fixed).
385 GMX_ASSERT(data().posMass_
.size() >= static_cast<size_t>(posCount()),
386 "Internal inconsistency");
387 return constArrayRefFromVector
<real
>(data().posMass_
.begin(),
388 data().posMass_
.begin() + posCount());
390 //! Returns charges for this selection as a continuous array.
391 ConstArrayRef
<real
> charges() const
393 // posCharge_ may have more entries than posCount() in the case of
394 // dynamic selections that don't have a topology
395 // (and thus the masses and charges are fixed).
396 GMX_ASSERT(data().posCharge_
.size() >= static_cast<size_t>(posCount()),
397 "Internal inconsistency");
398 return constArrayRefFromVector
<real
>(data().posCharge_
.begin(),
399 data().posCharge_
.begin() + posCount());
402 * Returns reference IDs for this selection as a continuous array.
404 * \see SelectionPosition::refId()
406 ConstArrayRef
<int> refIds() const
408 return constArrayRefFromArray(data().rawPositions_
.m
.refid
, posCount());
411 * Returns mapped IDs for this selection as a continuous array.
413 * \see SelectionPosition::mappedId()
415 ConstArrayRef
<int> mappedIds() const
417 return constArrayRefFromArray(data().rawPositions_
.m
.mapid
, posCount());
420 //! Returns whether the covered fraction can change between frames.
421 bool isCoveredFractionDynamic() const { return data().isCoveredFractionDynamic(); }
422 //! Returns the covered fraction for the current frame.
423 real
coveredFraction() const { return data().coveredFraction_
; }
426 * Allows passing a selection directly to neighborhood searching.
428 * When initialized this way, AnalysisNeighborhoodPair objects return
429 * indices that can be used to index the selection positions with
432 * Works exactly like if AnalysisNeighborhoodPositions had a
433 * constructor taking a Selection object as a parameter.
434 * See AnalysisNeighborhoodPositions for rationale and additional
437 operator AnalysisNeighborhoodPositions() const;
440 * Initializes information about covered fractions.
442 * \param[in] type Type of covered fraction required.
443 * \returns true if the covered fraction can be calculated for the
446 bool initCoveredFraction(e_coverfrac_t type
)
448 return data().initCoveredFraction(type
);
451 * Sets whether this selection evaluates velocities for positions.
453 * \param[in] bEnabled If true, velocities are evaluated.
455 * If you request the evaluation, but then evaluate the selection for
456 * a frame that does not contain velocity information, results are
460 * Implement it such that in the above case, hasVelocities() will
461 * return false for such frames.
465 void setEvaluateVelocities(bool bEnabled
)
467 data().flags_
.set(efSelection_EvaluateVelocities
, bEnabled
);
470 * Sets whether this selection evaluates forces for positions.
472 * \param[in] bEnabled If true, forces are evaluated.
474 * If you request the evaluation, but then evaluate the selection for
475 * a frame that does not contain force information, results are
480 void setEvaluateForces(bool bEnabled
)
482 data().flags_
.set(efSelection_EvaluateForces
, bEnabled
);
486 * Sets the ID for the \p i'th position for use with
487 * SelectionPosition::mappedId().
489 * \param[in] i Zero-based index
490 * \param[in] id Identifier to set.
492 * This method is not part of SelectionPosition because that interface
493 * only provides access to const data by design.
495 * This method can only be called after compilation, before the
496 * selection has been evaluated for any frame.
498 * \see SelectionPosition::mappedId()
500 void setOriginalId(int i
, int id
);
502 * Inits the IDs for use with SelectionPosition::mappedId() for
505 * \param[in] top Topology information
506 * (can be NULL if not required for \p type).
507 * \param[in] type Type of groups to generate.
508 * \returns Number of groups that were present in the selection.
509 * \throws InconsistentInputError if the selection positions cannot
510 * be assigned to groups of the given type.
512 * If `type == INDEX_ATOM`, the IDs are initialized to 0, 1, 2, ...,
513 * and the return value is the number of positions.
514 * If `type == INDEX_ALL`, all the IDs are initialized to 0, and the
515 * return value is one.
516 * If `type == INDEX_RES` or `type == INDEX_MOL`, the first position
517 * will get ID 0, and all following positions that belong to the same
518 * residue/molecule will get the same ID. The first position that
519 * belongs to a different residue/molecule will get ID 1, and so on.
520 * If some position contains atoms from multiple residues/molecules,
521 * i.e., the mapping is ambiguous, an exception is thrown.
522 * The return value is the number of residues/molecules that are
523 * present in the selection positions.
525 * This method is useful if the calling code needs to group the
526 * selection, e.g., for computing aggregate properties for each residue
527 * or molecule. It can then use this method to initialize the
528 * appropriate grouping, use the return value to allocate a
529 * sufficiently sized buffer to store the aggregated values, and then
530 * use SelectionPosition::mappedId() to identify the location where to
533 * \see setOriginalId()
534 * \see SelectionPosition::mappedId()
536 int initOriginalIdsToGroup(const gmx_mtop_t
*top
, e_index_t type
);
539 * Prints out one-line description of the selection.
541 * \param[in] fp Where to print the information.
543 * The output contains the name of the selection, the number of atoms
544 * and the number of positions, and indication of whether the selection
547 void printInfo(FILE *fp
) const;
549 * Prints out extended information about the selection for debugging.
551 * \param[in] fp Where to print the information.
552 * \param[in] nmaxind Maximum number of values to print in lists
555 void printDebugInfo(FILE *fp
, int nmaxind
) const;
558 internal::SelectionData
&data()
560 GMX_ASSERT(sel_
!= NULL
,
561 "Attempted to access uninitialized selection");
564 const internal::SelectionData
&data() const
566 GMX_ASSERT(sel_
!= NULL
,
567 "Attempted to access uninitialized selection");
572 * Pointer to internal data for the selection.
574 * The memory for this object is managed by a SelectionCollection
575 * object, and the \ref Selection class simply provides a public
576 * interface for accessing the data.
578 internal::SelectionData
*sel_
;
581 * Needed to access the data to adjust flags.
583 friend class SelectionOptionStorage
;
587 * Provides access to information about a single selected position.
589 * Each position has associated coordinates, and possibly velocities and forces
590 * if they have been requested and are available. It also has a set of atoms
591 * associated with it; typically the coordinates are the center-of-mass or
592 * center-of-geometry coordinates for that set of atoms. It is possible that
593 * there are not atoms associated if the selection has been provided as a fixed
596 * After the selection has been compiled, but not yet evaluated, the contents
597 * of the coordinate, velocity and force vectors are undefined.
599 * Default copy constructor and assignment operators are used, and work as
600 * intended: the copy references the same position and works identically.
602 * Methods in this class do not throw.
607 * \ingroup module_selection
609 class SelectionPosition
613 * Constructs a wrapper object for given selection position.
615 * \param[in] sel Selection from which the position is wrapped.
616 * \param[in] index Zero-based index of the position to wrap.
618 * Asserts if \p index is out of range.
620 * Only for internal use of the library. To obtain a SelectionPosition
621 * object in other code, use Selection::position().
623 SelectionPosition(const internal::SelectionData
&sel
, int index
)
624 : sel_(&sel
), i_(index
)
626 GMX_ASSERT(index
>= 0 && index
< sel
.posCount(),
627 "Invalid selection position index");
631 * Returns type of this position.
633 * Currently always returns the same as Selection::type().
635 e_index_t
type() const { return sel_
->type(); }
636 //! Returns coordinates for this position.
637 const rvec
&x() const
639 return sel_
->rawPositions_
.x
[i_
];
642 * Returns velocity for this position.
644 * Must not be called if Selection::hasVelocities() returns false.
646 const rvec
&v() const
648 GMX_ASSERT(sel_
->rawPositions_
.v
!= NULL
,
649 "Velocities accessed, but unavailable");
650 return sel_
->rawPositions_
.v
[i_
];
653 * Returns force for this position.
655 * Must not be called if Selection::hasForces() returns false.
657 const rvec
&f() const
659 GMX_ASSERT(sel_
->rawPositions_
.f
!= NULL
,
660 "Velocities accessed, but unavailable");
661 return sel_
->rawPositions_
.f
[i_
];
664 * Returns total mass for this position.
666 * Returns the total mass of atoms that make up this position.
667 * If there are no atoms associated or masses are not available,
672 return sel_
->posMass_
[i_
];
675 * Returns total charge for this position.
677 * Returns the sum of charges of atoms that make up this position.
678 * If there are no atoms associated or charges are not available,
683 return sel_
->posCharge_
[i_
];
685 //! Returns the number of atoms that make up this position.
686 int atomCount() const
688 return sel_
->rawPositions_
.m
.mapb
.index
[i_
+ 1]
689 - sel_
->rawPositions_
.m
.mapb
.index
[i_
];
691 //! Return atom indices that make up this position.
692 ConstArrayRef
<int> atomIndices() const
694 const int *atoms
= sel_
->rawPositions_
.m
.mapb
.a
;
697 return ConstArrayRef
<int>();
699 const int first
= sel_
->rawPositions_
.m
.mapb
.index
[i_
];
700 return constArrayRefFromArray(&atoms
[first
], atomCount());
703 * Returns whether this position is selected in the current frame.
705 * The return value is equivalent to \c refid() == -1. Returns always
706 * true if SelectionOption::dynamicMask() has not been set.
710 bool selected() const
715 * Returns reference ID for this position.
717 * For dynamic selections, this provides means to associate positions
718 * across frames. After compilation, these IDs are consequently
719 * numbered starting from zero. For each frame, the ID then reflects
720 * the location of the position in the original array of positions.
721 * If SelectionOption::dynamicMask() has been set for the parent
722 * selection, the IDs for positions not present in the current
723 * selection are set to -1, otherwise they are removed completely.
726 * If a dynamic selection consists of at most three positions, after
727 * compilation refId() will return 0, 1, 2 for them, respectively.
728 * If for a particular frame, only the first and the third are present,
729 * refId() will return 0, 2.
730 * If SelectionOption::dynamicMask() has been set, all three positions
731 * can be accessed also for that frame and refId() will return 0, -1,
736 return sel_
->rawPositions_
.m
.refid
[i_
];
739 * Returns mapped ID for this position.
741 * Returns ID of the position that corresponds to that set with
742 * Selection::setOriginalId().
744 * If for an array \c id, \c setOriginalId(i, id[i]) has been called
745 * for each \c i, then it always holds that
746 * \c mappedId()==id[refId()].
748 * Selection::setOriginalId() has not been called, the default values
749 * are dependent on type():
750 * - ::INDEX_ATOM: atom indices
751 * - ::INDEX_RES: residue indices
752 * - ::INDEX_MOL: molecule indices
754 * All the default values are zero-based.
758 return sel_
->rawPositions_
.m
.mapid
[i_
];
762 * Allows passing a selection position directly to neighborhood searching.
764 * When initialized this way, AnalysisNeighborhoodPair objects return
765 * the index that can be used to access this position using
766 * Selection::position().
768 * Works exactly like if AnalysisNeighborhoodPositions had a
769 * constructor taking a SelectionPosition object as a parameter.
770 * See AnalysisNeighborhoodPositions for rationale and additional
773 operator AnalysisNeighborhoodPositions() const;
776 const internal::SelectionData
*sel_
;
781 inline SelectionPosition
782 Selection::position(int i
) const
784 return SelectionPosition(data(), i
);