b9435f45805026eebaab07937e28b4be1f5b0a25
[alexxy/gromacs.git] / src / gromacs / selection / selectionoption.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010,2011,2012,2013,2014,2015,2018,2019, 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::SelectionOption and gmx::SelectionOptionInfo.
38  *
39  * \author Teemu Murtola <teemu.murtola@gmail.com>
40  * \inpublicapi
41  * \ingroup module_selection
42  */
43 #ifndef GMX_SELECTION_SELECTIONOPTION_H
44 #define GMX_SELECTION_SELECTIONOPTION_H
45
46 #include "gromacs/options/abstractoption.h"
47 #include "gromacs/selection/selection.h"
48
49 #include "selectionenums.h"
50
51 namespace gmx
52 {
53
54 class SelectionOptionInfo;
55 class SelectionOptionManager;
56 class SelectionOptionStorage;
57
58 /*! \brief
59  * Specifies an option that provides selection(s).
60  *
61  * Public methods in this class do not throw.
62  *
63  * To use options of this type, SelectionOptionManager must first be added to
64  * the Options collection.  For trajectory analysis tools, the framework takes
65  * care of this.
66  *
67  * \todo
68  * Support for specifying that an option accepts, e.g., two to four selections.
69  * Currently, only a fixed count or any number of selections is possible.
70  * \if internal
71  * In addition to allowing this in OptionTemplate, also SelectionOptionManager
72  * needs to be updated.
73  * \endif
74  *
75  * \inpublicapi
76  * \ingroup module_selection
77  */
78 class SelectionOption : public OptionTemplate<Selection, SelectionOption>
79 {
80 public:
81     //! OptionInfo subclass corresponding to this option type.
82     typedef SelectionOptionInfo InfoType;
83
84     //! Initializes an option with the given name.
85     explicit SelectionOption(const char* name) :
86         MyBase(name),
87         defaultText_(""),
88         selectionFlags_(efSelection_DisallowEmpty)
89     {
90     }
91
92     /*! \brief
93      * Request velocity evaluation for output positions.
94      *
95      * \see Selection::setEvaluateVelocities()
96      */
97     MyClass& evaluateVelocities()
98     {
99         selectionFlags_.set(efSelection_EvaluateVelocities);
100         return me();
101     }
102     /*! \brief
103      * Request force evaluation for output positions.
104      *
105      * \see Selection::setEvaluateForces()
106      */
107     MyClass& evaluateForces()
108     {
109         selectionFlags_.set(efSelection_EvaluateForces);
110         return me();
111     }
112     /*! \brief
113      * Only accept selections that evaluate to atom positions.
114      */
115     MyClass& onlyAtoms()
116     {
117         selectionFlags_.set(efSelection_OnlyAtoms);
118         return me();
119     }
120     /*! \brief
121      * Only accept selections that evaluate to atom positions in sorted order.
122      */
123     MyClass& onlySortedAtoms()
124     {
125         selectionFlags_.set(efSelection_OnlyAtoms);
126         selectionFlags_.set(efSelection_OnlySorted);
127         return me();
128     }
129     /*! \brief
130      * Only accept static selections for this option.
131      */
132     MyClass& onlyStatic()
133     {
134         selectionFlags_.set(efSelection_OnlyStatic);
135         return me();
136     }
137     /*! \brief
138      * Handle dynamic selections for this option with position masks.
139      *
140      * \see Selection
141      * \see SelectionPosition::selected()
142      */
143     MyClass& dynamicMask()
144     {
145         selectionFlags_.set(efSelection_DynamicMask);
146         return me();
147     }
148     /*! \brief
149      * Allow specifying an unconditionally empty selection for this option.
150      *
151      * If this option is not set, selections that are unconditionally empty
152      * (i.e., can never match any atoms) result in errors.
153      * Note that even without this option, it is still possible that a
154      * dynamic selection evaluates to zero atoms for some frames.
155      */
156     MyClass& allowEmpty()
157     {
158         selectionFlags_.clear(efSelection_DisallowEmpty);
159         return me();
160     }
161
162     /*! \brief
163      * Sets default selection text for the option.
164      *
165      * If the option is not set by the user, the provided text is parsed as
166      * the value of the selection.
167      */
168     MyClass& defaultSelectionText(const char* text)
169     {
170         defaultText_ = text;
171         return me();
172     }
173
174 private:
175     // Disable possibility to allow multiple occurrences, since it isn't
176     // implemented.
177     using MyBase::allowMultiple;
178     // Disable default value because it is impossible to provide a
179     // Selection object.
180     using MyBase::defaultValue;
181     using MyBase::defaultValueIfSet;
182
183     AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
184
185     const char*    defaultText_;
186     SelectionFlags selectionFlags_;
187
188     /*! \brief
189      * Needed to initialize SelectionOptionStorage from this class without
190      * otherwise unnecessary accessors.
191      */
192     friend class SelectionOptionStorage;
193 };
194
195 /*! \brief
196  * Wrapper class for accessing and modifying selection option information.
197  *
198  * Allows changes to a selection option after creation.
199  *
200  * This class provides the necessary interface for changing, e.g., the number
201  * of allowed selections for a selection option after the option has been
202  * created with Options::addOption().  This is needed if the number or other
203  * flags are only known after other options have been parsed.  The main
204  * advantage of this class over custom checks is that if used before
205  * interactive selection prompt, the interactive prompt is updated accordingly.
206  *
207  * When using this class, the option should be initially created with the most
208  * permissive flags, and this class should be used to place restrictions where
209  * appropriate.  Otherwise, values that are provided before adjustments will
210  * need to follow the more strict checks.  In most cases in trajectory analysis
211  * (which is the main use case for selection options), the adjustments should
212  * be done in TrajectoryAnalysisModule::optionsFinished() for them to take
213  * place before interactive selection prompts.
214  *
215  * An instance of this class for a selection option can be obtained with
216  * SelectionOption::getAdjuster() when the option is created.
217  *
218  * Example use:
219  * \code
220    SelectionList sel;
221    Options options("example", "Example options");
222    SelectionOptionInfo *info;
223    info = options.addOption(SelectionOption("sel").storeVector(&sel)
224                                 .multiValue());
225    // < ... assign values to options ...>
226    if ( condition )
227    {
228        // Put limitations on the selections based on the condition,
229        // which can depend on other option values.
230        // Throws if input given so far violates the limitations.
231        info->setValueCount(2);
232        info->setOnlyStatic(true);
233    }
234  * \endcode
235  *
236  * \inpublicapi
237  * \ingroup module_selection
238  */
239 class SelectionOptionInfo : public OptionInfo
240 {
241 public:
242     /*! \brief
243      * Creates option info object for given storage object.
244      *
245      * Does not throw.
246      */
247     explicit SelectionOptionInfo(SelectionOptionStorage* option);
248
249     /*! \brief
250      * Sets the number of selections allowed for the option.
251      *
252      * \param[in] count  Number of allowed selections.
253      * \throws    std::bad_alloc if out of memory.
254      * \throws    InvalidInputError if values have already been provided
255      *      and their count does not match.
256      */
257     void setValueCount(int count);
258
259     /*! \brief
260      * Sets whether this option evaluates velocities for positions.
261      *
262      * \param[in] bEnabled  If true, velocities are evaluated.
263      *
264      * Does not throw.
265      *
266      * \see Selection::setEvaluateVelocities()
267      */
268     void setEvaluateVelocities(bool bEnabled);
269     /*! \brief
270      * Sets whether this option evaluates forces for positions.
271      *
272      * \param[in] bEnabled  If true, forces are evaluated.
273      *
274      * Does not throw.
275      *
276      * \see Selection::setEvaluateForces()
277      */
278     void setEvaluateForces(bool bEnabled);
279     /*! \brief
280      * Sets whether this option accepts positions that come from multiple
281      * atoms.
282      *
283      * \param[in] bEnabled  If true, the option accepts only positions that
284      *      evaluate to atom positions.
285      *
286      * \see SelectionOption::onlyAtoms()
287      */
288     void setOnlyAtoms(bool bEnabled);
289     /*! \brief
290      * Sets whether this option accepts dynamic selections.
291      *
292      * \param[in] bEnabled  If true, the option accepts only static
293      *      selections.
294      * \throws    std::bad_alloc if out of memory.
295      * \throws    InvalidInputError if dynamic selections have already been
296      *      provided.
297      *
298      * Strong exception safety guarantee.
299      *
300      * \see SelectionOption::onlyStatic()
301      */
302     void setOnlyStatic(bool bEnabled);
303     /*! \brief
304      * Sets whether this option uses position masks for dynamic selections.
305      *
306      * \param[in] bEnabled  If true, the position masks are used.
307      *
308      * Does not throw.
309      *
310      * \see SelectionOption::dynamicMask()
311      */
312     void setDynamicMask(bool bEnabled);
313
314 private:
315     SelectionOptionStorage&       option();
316     const SelectionOptionStorage& option() const;
317 };
318
319 } // namespace gmx
320
321 #endif