30f060c5577ce72d813cd822faa0207d314d6885
[alexxy/gromacs.git] / src / gromacs / selection / selection.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
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.
8  *
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.
13  *
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.
18  *
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.
23  *
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.
31  *
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.
34  */
35 /*! \file
36  * \brief
37  * Declares gmx::Selection and supporting classes.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inpublicapi
41  * \ingroup module_selection
42  */
43 #ifndef GMX_SELECTION_SELECTION_H
44 #define GMX_SELECTION_SELECTION_H
45
46 #include <string>
47 #include <vector>
48
49 #include "../utility/arrayref.h"
50 #include "../utility/common.h"
51 #include "../utility/gmxassert.h"
52
53 #include "position.h"
54 #include "selectionenums.h"
55
56 struct t_topology;
57
58 namespace gmx
59 {
60
61 class SelectionOptionStorage;
62 class SelectionTreeElement;
63
64 class AnalysisNeighborhoodPositions;
65 class Selection;
66 class SelectionPosition;
67
68 //! Container of selections used in public selection interfaces.
69 typedef std::vector<Selection> SelectionList;
70
71 namespace internal
72 {
73
74 /*! \internal
75  * \brief
76  * Internal data for a single selection.
77  *
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.
81  *
82  * Methods in this class do not throw unless otherwise specified.
83  *
84  * \ingroup module_selection
85  */
86 class SelectionData
87 {
88     public:
89         /*! \brief
90          * Creates a new selection object.
91          *
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.
95          */
96         SelectionData(SelectionTreeElement *elem, const char *selstr);
97         ~SelectionData();
98
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
110         //! Number of positions in the selection.
111         int posCount() const { return rawPositions_.count(); }
112         //! Returns the root of the evaluation tree for this selection.
113         SelectionTreeElement &rootElement() { return rootElement_; }
114
115         //! Returns whether the covered fraction can change between frames.
116         bool isCoveredFractionDynamic() const { return bDynamicCoveredFraction_; }
117
118         //! Returns true if the given flag is set.
119         bool hasFlag(SelectionFlag flag) const { return flags_.test(flag); }
120         //! Sets the flags for this selection.
121         void setFlags(SelectionFlags flags) { flags_ = flags; }
122
123         //! \copydoc Selection::initCoveredFraction()
124         bool initCoveredFraction(e_coverfrac_t type);
125
126         /*! \brief
127          * Updates the name of the selection if missing.
128          *
129          * \throws    std::bad_alloc if out of memory.
130          *
131          * If selections get their value from a group reference that cannot be
132          * resolved during parsing, the name is final only after group
133          * references have been resolved.
134          *
135          * This function is called by SelectionCollection::setIndexGroups().
136          */
137         void refreshName();
138         /*! \brief
139          * Computes total masses and charges for all selection positions.
140          *
141          * \param[in] top   Topology information.
142          * \throws    std::bad_alloc if out of memory.
143          *
144          * For dynamic selections, the values need to be updated after each
145          * evaluation with refreshMassesAndCharges().
146          * This is done by SelectionEvaluator.
147          *
148          * This function is called by SelectionCompiler.
149          *
150          * Strong exception safety guarantee.
151          */
152         void initializeMassesAndCharges(const t_topology *top);
153         /*! \brief
154          * Updates masses and charges after dynamic selection has been
155          * evaluated.
156          *
157          * \param[in] top   Topology information.
158          *
159          * Called by SelectionEvaluator.
160          */
161         void refreshMassesAndCharges(const t_topology *top);
162         /*! \brief
163          * Updates the covered fraction after a selection has been evaluated.
164          *
165          * Called by SelectionEvaluator.
166          */
167         void updateCoveredFractionForFrame();
168         /*! \brief
169          * Computes average covered fraction after all frames have been evaluated.
170          *
171          * \param[in] nframes  Number of frames that have been evaluated.
172          *
173          * \p nframes should be equal to the number of calls to
174          * updateCoveredFractionForFrame().
175          * Called by SelectionEvaluator::evaluateFinal().
176          */
177         void computeAverageCoveredFraction(int nframes);
178         /*! \brief
179          * Restores position information to state it was in after compilation.
180          *
181          * \param[in] top   Topology information.
182          *
183          * Depends on SelectionCompiler storing the original atoms in the
184          * \a rootElement_ object.
185          * Called by SelectionEvaluator::evaluateFinal().
186          */
187         void restoreOriginalPositions(const t_topology *top);
188
189     private:
190         //! Name of the selection.
191         std::string               name_;
192         //! The actual selection string.
193         std::string               selectionText_;
194         //! Low-level representation of selected positions.
195         gmx_ana_pos_t             rawPositions_;
196         //! Total masses for the current positions.
197         std::vector<real>         posMass_;
198         //! Total charges for the current positions.
199         std::vector<real>         posCharge_;
200         SelectionFlags            flags_;
201         //! Root of the selection evaluation tree.
202         SelectionTreeElement     &rootElement_;
203         //! Type of the covered fraction.
204         e_coverfrac_t             coveredFractionType_;
205         //! Covered fraction of the selection for the current frame.
206         real                      coveredFraction_;
207         //! The average covered fraction (over the trajectory).
208         real                      averageCoveredFraction_;
209         //! true if the value can change as a function of time.
210         bool                      bDynamic_;
211         //! true if the covered fraction depends on the frame.
212         bool                      bDynamicCoveredFraction_;
213
214         /*! \brief
215          * Needed to wrap access to information.
216          */
217         friend class gmx::Selection;
218         /*! \brief
219          * Needed for proper access to position information.
220          */
221         friend class gmx::SelectionPosition;
222
223         GMX_DISALLOW_COPY_AND_ASSIGN(SelectionData);
224 };
225
226 }   // namespace internal
227
228 /*! \brief
229  * Provides access to a single selection.
230  *
231  * This class provides a public interface for accessing selection information.
232  * General information about the selection can be accessed with methods name(),
233  * selectionText(), isDynamic(), and type().  The first three can be accessed
234  * any time after the selection has been parsed, and type() can be accessed
235  * after the selection has been compiled.
236  *
237  * There are a few methods that can be used to change the behavior of the
238  * selection.  setEvaluateVelocities() and setEvaluateForces() can be called
239  * before the selection is compiled to request evaluation of velocities and/or
240  * forces in addition to coordinates.
241  *
242  * Each selection is made of a set of positions.  Each position has associated
243  * coordinates, and possibly velocities and forces if they have been requested
244  * and are available.  It also has a set of atoms associated with it; typically
245  * the coordinates are the center-of-mass or center-of-geometry coordinates for
246  * that set of atoms.  To access the number of positions in the selection, use
247  * posCount().  To access individual positions, use position().
248  * See SelectionPosition for details of how to use individual positions.
249  * setOriginalId() can be used to adjust the return value of
250  * SelectionPosition::mappedId(); see that method for details.
251  *
252  * It is also possible to access the list of atoms that make up all the
253  * positions directly: atomCount() returns the total number of atoms in the
254  * selection and atomIndices() an array of their indices.
255  * Similarly, it is possible to access the coordinates and other properties
256  * of the positions as continuous arrays through coordinates(), velocities(),
257  * forces(), masses(), charges(), refIds(), and mappedIds().
258  *
259  * Both positions and atoms can be accessed after the selection has been
260  * compiled.  For dynamic selections, the return values of these methods change
261  * after each evaluation to reflect the situation for the current frame.
262  * Before any frame has been evaluated, these methods return the maximal set
263  * to which the selection can evaluate.
264  *
265  * There are two possible modes for how positions for dynamic selections are
266  * handled.  In the default mode, posCount() can change, and for each frame,
267  * only the positions that are selected in that frame can be accessed.  In a
268  * masked mode, posCount() remains constant, i.e., the positions are always
269  * evaluated for the maximal set, and SelectionPosition::selected() is used to
270  * determine whether a position is selected for a frame.  The masked mode can
271  * be requested with SelectionOption::dynamicMask().
272  *
273  * The class also provides methods for printing out information: printInfo()
274  * and printDebugInfo().  These are mainly for internal use by Gromacs.
275  *
276  * This class works like a pointer type: copying and assignment is lightweight,
277  * and all copies work interchangeably, accessing the same internal data.
278  *
279  * Methods in this class do not throw.
280  *
281  * \see SelectionPosition
282  *
283  * \inpublicapi
284  * \ingroup module_selection
285  */
286 class Selection
287 {
288     public:
289         /*! \brief
290          * Creates a selection wrapper that has no associated selection.
291          *
292          * Any attempt to call methods in the object before a selection is
293          * assigned results in undefined behavior.
294          * isValid() returns `false` for the selection until it is initialized.
295          */
296         Selection() : sel_(NULL) {}
297         /*! \brief
298          * Creates a new selection object.
299          *
300          * \param  sel  Selection data to wrap.
301          *
302          * Only for internal use by the selection module.
303          */
304         explicit Selection(internal::SelectionData *sel) : sel_(sel) {}
305
306         //! Returns whether the selection object is initialized.
307         bool isValid() const { return sel_ != NULL; }
308
309         //! Returns whether two selection objects wrap the same selection.
310         bool operator==(const Selection &other) const
311         {
312             return sel_ == other.sel_;
313         }
314         //! Returns whether two selection objects wrap different selections.
315         bool operator!=(const Selection &other) const
316         {
317             return !operator==(other);
318         }
319
320         //! Returns the name of the selection.
321         const char *name() const  { return data().name(); }
322         //! Returns the string that was parsed to produce this selection.
323         const char *selectionText() const { return data().selectionText(); }
324         //! Returns true if the size of the selection (posCount()) is dynamic.
325         bool isDynamic() const { return data().isDynamic(); }
326         //! Returns the type of positions in the selection.
327         e_index_t type() const { return data().type(); }
328         //! Returns true if the selection only contains positions with a single atom each.
329         bool hasOnlyAtoms() const { return data().hasOnlyAtoms(); }
330
331         //! Total number of atoms in the selection.
332         int atomCount() const
333         {
334             return data().rawPositions_.m.mapb.nra;
335         }
336         //! Returns atom indices of all atoms in the selection.
337         ConstArrayRef<int> atomIndices() const
338         {
339             return constArrayRefFromArray(sel_->rawPositions_.m.mapb.a,
340                                           sel_->rawPositions_.m.mapb.nra);
341         }
342         //! Number of positions in the selection.
343         int posCount() const { return data().posCount(); }
344         //! Access a single position.
345         SelectionPosition position(int i) const;
346         //! Returns coordinates for this selection as a continuous array.
347         ConstArrayRef<rvec> coordinates() const
348         {
349             return constArrayRefFromArray(data().rawPositions_.x, posCount());
350         }
351         //! Returns whether velocities are available for this selection.
352         bool hasVelocities() const { return data().rawPositions_.v != NULL; }
353         /*! \brief
354          * Returns velocities for this selection as a continuous array.
355          *
356          * Must not be called if hasVelocities() returns false.
357          */
358         ConstArrayRef<rvec> velocities() const
359         {
360             GMX_ASSERT(hasVelocities(), "Velocities accessed, but unavailable");
361             return constArrayRefFromArray(data().rawPositions_.v, posCount());
362         }
363         //! Returns whether forces are available for this selection.
364         bool hasForces() const { return sel_->rawPositions_.f != NULL; }
365         /*! \brief
366          * Returns forces for this selection as a continuous array.
367          *
368          * Must not be called if hasForces() returns false.
369          */
370         ConstArrayRef<rvec> forces() const
371         {
372             GMX_ASSERT(hasForces(), "Forces accessed, but unavailable");
373             return constArrayRefFromArray(data().rawPositions_.f, posCount());
374         }
375         //! Returns masses for this selection as a continuous array.
376         ConstArrayRef<real> masses() const
377         {
378             // posMass_ may have more entries than posCount() in the case of
379             // dynamic selections that don't have a topology
380             // (and thus the masses and charges are fixed).
381             GMX_ASSERT(data().posMass_.size() >= static_cast<size_t>(posCount()),
382                        "Internal inconsistency");
383             return constArrayRefFromVector<real>(data().posMass_.begin(),
384                                                  data().posMass_.begin() + posCount());
385         }
386         //! Returns charges for this selection as a continuous array.
387         ConstArrayRef<real> charges() const
388         {
389             // posCharge_ may have more entries than posCount() in the case of
390             // dynamic selections that don't have a topology
391             // (and thus the masses and charges are fixed).
392             GMX_ASSERT(data().posCharge_.size() >= static_cast<size_t>(posCount()),
393                        "Internal inconsistency");
394             return constArrayRefFromVector<real>(data().posCharge_.begin(),
395                                                  data().posCharge_.begin() + posCount());
396         }
397         /*! \brief
398          * Returns reference IDs for this selection as a continuous array.
399          *
400          * \see SelectionPosition::refId()
401          */
402         ConstArrayRef<int> refIds() const
403         {
404             return constArrayRefFromArray(data().rawPositions_.m.refid, posCount());
405         }
406         /*! \brief
407          * Returns mapped IDs for this selection as a continuous array.
408          *
409          * \see SelectionPosition::mappedId()
410          */
411         ConstArrayRef<int> mappedIds() const
412         {
413             return constArrayRefFromArray(data().rawPositions_.m.mapid, posCount());
414         }
415
416         //! Returns whether the covered fraction can change between frames.
417         bool isCoveredFractionDynamic() const { return data().isCoveredFractionDynamic(); }
418         //! Returns the covered fraction for the current frame.
419         real coveredFraction() const { return data().coveredFraction_; }
420
421         /*! \brief
422          * Allows passing a selection directly to neighborhood searching.
423          *
424          * When initialized this way, AnalysisNeighborhoodPair objects return
425          * indices that can be used to index the selection positions with
426          * position().
427          *
428          * Works exactly like if AnalysisNeighborhoodPositions had a
429          * constructor taking a Selection object as a parameter.
430          * See AnalysisNeighborhoodPositions for rationale and additional
431          * discussion.
432          */
433         operator AnalysisNeighborhoodPositions() const;
434
435         /*! \brief
436          * Initializes information about covered fractions.
437          *
438          * \param[in] type Type of covered fraction required.
439          * \returns   true if the covered fraction can be calculated for the
440          *      selection.
441          */
442         bool initCoveredFraction(e_coverfrac_t type)
443         {
444             return data().initCoveredFraction(type);
445         }
446         /*! \brief
447          * Sets whether this selection evaluates velocities for positions.
448          *
449          * \param[in] bEnabled  If true, velocities are evaluated.
450          *
451          * If you request the evaluation, but then evaluate the selection for
452          * a frame that does not contain velocity information, results are
453          * undefined.
454          *
455          * \todo
456          * Implement it such that in the above case, hasVelocities() will
457          * return false for such frames.
458          *
459          * Does not throw.
460          */
461         void setEvaluateVelocities(bool bEnabled)
462         {
463             data().flags_.set(efSelection_EvaluateVelocities, bEnabled);
464         }
465         /*! \brief
466          * Sets whether this selection evaluates forces for positions.
467          *
468          * \param[in] bEnabled  If true, forces are evaluated.
469          *
470          * If you request the evaluation, but then evaluate the selection for
471          * a frame that does not contain force information, results are
472          * undefined.
473          *
474          * Does not throw.
475          */
476         void setEvaluateForces(bool bEnabled)
477         {
478             data().flags_.set(efSelection_EvaluateForces, bEnabled);
479         }
480
481         /*! \brief
482          * Sets the ID for the \p i'th position for use with
483          * SelectionPosition::mappedId().
484          *
485          * \param[in] i  Zero-based index
486          * \param[in] id Identifier to set.
487          *
488          * This method is not part of SelectionPosition because that interface
489          * only provides access to const data by design.
490          *
491          * This method can only be called after compilation, before the
492          * selection has been evaluated for any frame.
493          *
494          * \see SelectionPosition::mappedId()
495          */
496         void setOriginalId(int i, int id) { data().rawPositions_.m.orgid[i] = id; }
497
498         /*! \brief
499          * Prints out one-line description of the selection.
500          *
501          * \param[in] fp      Where to print the information.
502          *
503          * The output contains the name of the selection, the number of atoms
504          * and the number of positions, and indication of whether the selection
505          * is dynamic.
506          */
507         void printInfo(FILE *fp) const;
508         /*! \brief
509          * Prints out extended information about the selection for debugging.
510          *
511          * \param[in] fp      Where to print the information.
512          * \param[in] nmaxind Maximum number of values to print in lists
513          *      (-1 = print all).
514          */
515         void printDebugInfo(FILE *fp, int nmaxind) const;
516
517     private:
518         internal::SelectionData &data()
519         {
520             GMX_ASSERT(sel_ != NULL,
521                        "Attempted to access uninitialized selection");
522             return *sel_;
523         }
524         const internal::SelectionData &data() const
525         {
526             GMX_ASSERT(sel_ != NULL,
527                        "Attempted to access uninitialized selection");
528             return *sel_;
529         }
530
531         /*! \brief
532          * Pointer to internal data for the selection.
533          *
534          * The memory for this object is managed by a SelectionCollection
535          * object, and the \ref Selection class simply provides a public
536          * interface for accessing the data.
537          */
538         internal::SelectionData *sel_;
539
540         /*! \brief
541          * Needed to access the data to adjust flags.
542          */
543         friend class SelectionOptionStorage;
544 };
545
546 /*! \brief
547  * Provides access to information about a single selected position.
548  *
549  * Each position has associated coordinates, and possibly velocities and forces
550  * if they have been requested and are available.  It also has a set of atoms
551  * associated with it; typically the coordinates are the center-of-mass or
552  * center-of-geometry coordinates for that set of atoms.  It is possible that
553  * there are not atoms associated if the selection has been provided as a fixed
554  * position.
555  *
556  * After the selection has been compiled, but not yet evaluated, the contents
557  * of the coordinate, velocity and force vectors are undefined.
558  *
559  * Default copy constructor and assignment operators are used, and work as
560  * intended: the copy references the same position and works identically.
561  *
562  * Methods in this class do not throw.
563  *
564  * \see Selection
565  *
566  * \inpublicapi
567  * \ingroup module_selection
568  */
569 class SelectionPosition
570 {
571     public:
572         /*! \brief
573          * Constructs a wrapper object for given selection position.
574          *
575          * \param[in] sel    Selection from which the position is wrapped.
576          * \param[in] index  Zero-based index of the position to wrap.
577          *
578          * Asserts if \p index is out of range.
579          *
580          * Only for internal use of the library.  To obtain a SelectionPosition
581          * object in other code, use Selection::position().
582          */
583         SelectionPosition(const internal::SelectionData &sel, int index)
584             : sel_(&sel), i_(index)
585         {
586             GMX_ASSERT(index >= 0 && index < sel.posCount(),
587                        "Invalid selection position index");
588         }
589
590         /*! \brief
591          * Returns type of this position.
592          *
593          * Currently always returns the same as Selection::type().
594          */
595         e_index_t type() const { return sel_->type(); }
596         //! Returns coordinates for this position.
597         const rvec &x() const
598         {
599             return sel_->rawPositions_.x[i_];
600         }
601         /*! \brief
602          * Returns velocity for this position.
603          *
604          * Must not be called if Selection::hasVelocities() returns false.
605          */
606         const rvec &v() const
607         {
608             GMX_ASSERT(sel_->rawPositions_.v != NULL,
609                        "Velocities accessed, but unavailable");
610             return sel_->rawPositions_.v[i_];
611         }
612         /*! \brief
613          * Returns force for this position.
614          *
615          * Must not be called if Selection::hasForces() returns false.
616          */
617         const rvec &f() const
618         {
619             GMX_ASSERT(sel_->rawPositions_.f != NULL,
620                        "Velocities accessed, but unavailable");
621             return sel_->rawPositions_.f[i_];
622         }
623         /*! \brief
624          * Returns total mass for this position.
625          *
626          * Returns the total mass of atoms that make up this position.
627          * If there are no atoms associated or masses are not available,
628          * returns unity.
629          */
630         real mass() const
631         {
632             return sel_->posMass_[i_];
633         }
634         /*! \brief
635          * Returns total charge for this position.
636          *
637          * Returns the sum of charges of atoms that make up this position.
638          * If there are no atoms associated or charges are not available,
639          * returns zero.
640          */
641         real charge() const
642         {
643             return sel_->posCharge_[i_];
644         }
645         //! Returns the number of atoms that make up this position.
646         int atomCount() const
647         {
648             return sel_->rawPositions_.m.mapb.index[i_ + 1]
649                    - sel_->rawPositions_.m.mapb.index[i_];
650         }
651         //! Return atom indices that make up this position.
652         ConstArrayRef<int> atomIndices() const
653         {
654             const int *atoms = sel_->rawPositions_.m.mapb.a;
655             if (atoms == NULL)
656             {
657                 return ConstArrayRef<int>();
658             }
659             const int first = sel_->rawPositions_.m.mapb.index[i_];
660             return constArrayRefFromArray(&atoms[first], atomCount());
661         }
662         /*! \brief
663          * Returns whether this position is selected in the current frame.
664          *
665          * The return value is equivalent to \c refid() == -1.  Returns always
666          * true if SelectionOption::dynamicMask() has not been set.
667          *
668          * \see refId()
669          */
670         bool selected() const
671         {
672             return refId() >= 0;
673         }
674         /*! \brief
675          * Returns reference ID for this position.
676          *
677          * For dynamic selections, this provides means to associate positions
678          * across frames.  After compilation, these IDs are consequently
679          * numbered starting from zero.  For each frame, the ID then reflects
680          * the location of the position in the original array of positions.
681          * If SelectionOption::dynamicMask() has been set for the parent
682          * selection, the IDs for positions not present in the current
683          * selection are set to -1, otherwise they are removed completely.
684          *
685          * Example:
686          * If a dynamic selection consists of at most three positions, after
687          * compilation refId() will return 0, 1, 2 for them, respectively.
688          * If for a particular frame, only the first and the third are present,
689          * refId() will return 0, 2.
690          * If SelectionOption::dynamicMask() has been set, all three positions
691          * can be accessed also for that frame and refId() will return 0, -1,
692          * 2.
693          */
694         int refId() const
695         {
696             return sel_->rawPositions_.m.refid[i_];
697         }
698         /*! \brief
699          * Returns mapped ID for this position.
700          *
701          * Returns ID of the position that corresponds to that set with
702          * Selection::setOriginalId().
703          *
704          * If for an array \c id, \c setOriginalId(i, id[i]) has been called
705          * for each \c i, then it always holds that
706          * \c mappedId()==id[refId()].
707          *
708          * Selection::setOriginalId() has not been called, the default values
709          * are dependent on type():
710          *  - ::INDEX_ATOM: atom indices
711          *  - ::INDEX_RES:  residue numbers
712          *  - ::INDEX_MOL:  molecule numbers
713          *  .
714          * All the default values are zero-based
715          */
716         int mappedId() const
717         {
718             return sel_->rawPositions_.m.mapid[i_];
719         }
720
721         /*! \brief
722          * Allows passing a selection position directly to neighborhood searching.
723          *
724          * When initialized this way, AnalysisNeighborhoodPair objects return
725          * the index that can be used to access this position using
726          * Selection::position().
727          *
728          * Works exactly like if AnalysisNeighborhoodPositions had a
729          * constructor taking a SelectionPosition object as a parameter.
730          * See AnalysisNeighborhoodPositions for rationale and additional
731          * discussion.
732          */
733         operator AnalysisNeighborhoodPositions() const;
734
735     private:
736         const internal::SelectionData  *sel_;
737         int                             i_;
738 };
739
740
741 inline SelectionPosition
742 Selection::position(int i) const
743 {
744     return SelectionPosition(data(), i);
745 }
746
747 } // namespace gmx
748
749 #endif