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