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