Split lines with many copyright years
[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 by the GROMACS development team.
5  * Copyright (c) 2015,2018,2019,2020, by the GROMACS development team, led by
6  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7  * and including many others, as listed in the AUTHORS file in the
8  * top-level source directory and at http://www.gromacs.org.
9  *
10  * GROMACS is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * GROMACS is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GROMACS; if not, see
22  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24  *
25  * If you want to redistribute modifications to GROMACS, please
26  * consider that scientific software is very special. Version
27  * control is crucial - bugs must be traceable. We will be happy to
28  * consider code for inclusion in the official distribution, but
29  * derived work must not be called official GROMACS. Details are found
30  * in the README & COPYING files - if they are missing, get the
31  * official version at http://www.gromacs.org.
32  *
33  * To help us fund GROMACS development, we humbly ask that you cite
34  * the research papers on the package. Check out http://www.gromacs.org.
35  */
36 /*! \file
37  * \brief
38  * Declares gmx::SelectionOption and gmx::SelectionOptionInfo.
39  *
40  * \author Teemu Murtola <teemu.murtola@gmail.com>
41  * \inpublicapi
42  * \ingroup module_selection
43  */
44 #ifndef GMX_SELECTION_SELECTIONOPTION_H
45 #define GMX_SELECTION_SELECTIONOPTION_H
46
47 #include "gromacs/options/abstractoption.h"
48 #include "gromacs/selection/selection.h"
49
50 #include "selectionenums.h"
51
52 namespace gmx
53 {
54
55 class SelectionOptionInfo;
56 class SelectionOptionManager;
57 class SelectionOptionStorage;
58
59 /*! \brief
60  * Specifies an option that provides selection(s).
61  *
62  * Public methods in this class do not throw.
63  *
64  * To use options of this type, SelectionOptionManager must first be added to
65  * the Options collection.  For trajectory analysis tools, the framework takes
66  * care of this.
67  *
68  * \todo
69  * Support for specifying that an option accepts, e.g., two to four selections.
70  * Currently, only a fixed count or any number of selections is possible.
71  * \if internal
72  * In addition to allowing this in OptionTemplate, also SelectionOptionManager
73  * needs to be updated.
74  * \endif
75  *
76  * \inpublicapi
77  * \ingroup module_selection
78  */
79 class SelectionOption : public OptionTemplate<Selection, SelectionOption>
80 {
81 public:
82     //! OptionInfo subclass corresponding to this option type.
83     typedef SelectionOptionInfo InfoType;
84
85     //! Initializes an option with the given name.
86     explicit SelectionOption(const char* name) :
87         MyBase(name),
88         defaultText_(""),
89         selectionFlags_(efSelection_DisallowEmpty)
90     {
91     }
92
93     /*! \brief
94      * Request velocity evaluation for output positions.
95      *
96      * \see Selection::setEvaluateVelocities()
97      */
98     MyClass& evaluateVelocities()
99     {
100         selectionFlags_.set(efSelection_EvaluateVelocities);
101         return me();
102     }
103     /*! \brief
104      * Request force evaluation for output positions.
105      *
106      * \see Selection::setEvaluateForces()
107      */
108     MyClass& evaluateForces()
109     {
110         selectionFlags_.set(efSelection_EvaluateForces);
111         return me();
112     }
113     /*! \brief
114      * Only accept selections that evaluate to atom positions.
115      */
116     MyClass& onlyAtoms()
117     {
118         selectionFlags_.set(efSelection_OnlyAtoms);
119         return me();
120     }
121     /*! \brief
122      * Only accept selections that evaluate to atom positions in sorted order.
123      */
124     MyClass& onlySortedAtoms()
125     {
126         selectionFlags_.set(efSelection_OnlyAtoms);
127         selectionFlags_.set(efSelection_OnlySorted);
128         return me();
129     }
130     /*! \brief
131      * Only accept static selections for this option.
132      */
133     MyClass& onlyStatic()
134     {
135         selectionFlags_.set(efSelection_OnlyStatic);
136         return me();
137     }
138     /*! \brief
139      * Handle dynamic selections for this option with position masks.
140      *
141      * \see Selection
142      * \see SelectionPosition::selected()
143      */
144     MyClass& dynamicMask()
145     {
146         selectionFlags_.set(efSelection_DynamicMask);
147         return me();
148     }
149     /*! \brief
150      * Allow specifying an unconditionally empty selection for this option.
151      *
152      * If this option is not set, selections that are unconditionally empty
153      * (i.e., can never match any atoms) result in errors.
154      * Note that even without this option, it is still possible that a
155      * dynamic selection evaluates to zero atoms for some frames.
156      */
157     MyClass& allowEmpty()
158     {
159         selectionFlags_.clear(efSelection_DisallowEmpty);
160         return me();
161     }
162
163     /*! \brief
164      * Sets default selection text for the option.
165      *
166      * If the option is not set by the user, the provided text is parsed as
167      * the value of the selection.
168      */
169     MyClass& defaultSelectionText(const char* text)
170     {
171         defaultText_ = text;
172         return me();
173     }
174
175 private:
176     // Disable possibility to allow multiple occurrences, since it isn't
177     // implemented.
178     using MyBase::allowMultiple;
179     // Disable default value because it is impossible to provide a
180     // Selection object.
181     using MyBase::defaultValue;
182     using MyBase::defaultValueIfSet;
183
184     AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
185
186     const char*    defaultText_;
187     SelectionFlags selectionFlags_;
188
189     /*! \brief
190      * Needed to initialize SelectionOptionStorage from this class without
191      * otherwise unnecessary accessors.
192      */
193     friend class SelectionOptionStorage;
194 };
195
196 /*! \brief
197  * Wrapper class for accessing and modifying selection option information.
198  *
199  * Allows changes to a selection option after creation.
200  *
201  * This class provides the necessary interface for changing, e.g., the number
202  * of allowed selections for a selection option after the option has been
203  * created with Options::addOption().  This is needed if the number or other
204  * flags are only known after other options have been parsed.  The main
205  * advantage of this class over custom checks is that if used before
206  * interactive selection prompt, the interactive prompt is updated accordingly.
207  *
208  * When using this class, the option should be initially created with the most
209  * permissive flags, and this class should be used to place restrictions where
210  * appropriate.  Otherwise, values that are provided before adjustments will
211  * need to follow the more strict checks.  In most cases in trajectory analysis
212  * (which is the main use case for selection options), the adjustments should
213  * be done in TrajectoryAnalysisModule::optionsFinished() for them to take
214  * place before interactive selection prompts.
215  *
216  * An instance of this class for a selection option can be obtained with
217  * SelectionOption::getAdjuster() when the option is created.
218  *
219  * Example use:
220  * \code
221    SelectionList sel;
222    Options options("example", "Example options");
223    SelectionOptionInfo *info;
224    info = options.addOption(SelectionOption("sel").storeVector(&sel)
225                                 .multiValue());
226    // < ... assign values to options ...>
227    if ( condition )
228    {
229        // Put limitations on the selections based on the condition,
230        // which can depend on other option values.
231        // Throws if input given so far violates the limitations.
232        info->setValueCount(2);
233        info->setOnlyStatic(true);
234    }
235  * \endcode
236  *
237  * \inpublicapi
238  * \ingroup module_selection
239  */
240 class SelectionOptionInfo : public OptionInfo
241 {
242 public:
243     /*! \brief
244      * Creates option info object for given storage object.
245      *
246      * Does not throw.
247      */
248     explicit SelectionOptionInfo(SelectionOptionStorage* option);
249
250     /*! \brief
251      * Sets the number of selections allowed for the option.
252      *
253      * \param[in] count  Number of allowed selections.
254      * \throws    std::bad_alloc if out of memory.
255      * \throws    InvalidInputError if values have already been provided
256      *      and their count does not match.
257      */
258     void setValueCount(int count);
259
260     /*! \brief
261      * Sets whether this option evaluates velocities for positions.
262      *
263      * \param[in] bEnabled  If true, velocities are evaluated.
264      *
265      * Does not throw.
266      *
267      * \see Selection::setEvaluateVelocities()
268      */
269     void setEvaluateVelocities(bool bEnabled);
270     /*! \brief
271      * Sets whether this option evaluates forces for positions.
272      *
273      * \param[in] bEnabled  If true, forces are evaluated.
274      *
275      * Does not throw.
276      *
277      * \see Selection::setEvaluateForces()
278      */
279     void setEvaluateForces(bool bEnabled);
280     /*! \brief
281      * Sets whether this option accepts positions that come from multiple
282      * atoms.
283      *
284      * \param[in] bEnabled  If true, the option accepts only positions that
285      *      evaluate to atom positions.
286      *
287      * \see SelectionOption::onlyAtoms()
288      */
289     void setOnlyAtoms(bool bEnabled);
290     /*! \brief
291      * Sets whether this option accepts dynamic selections.
292      *
293      * \param[in] bEnabled  If true, the option accepts only static
294      *      selections.
295      * \throws    std::bad_alloc if out of memory.
296      * \throws    InvalidInputError if dynamic selections have already been
297      *      provided.
298      *
299      * Strong exception safety guarantee.
300      *
301      * \see SelectionOption::onlyStatic()
302      */
303     void setOnlyStatic(bool bEnabled);
304     /*! \brief
305      * Sets whether this option uses position masks for dynamic selections.
306      *
307      * \param[in] bEnabled  If true, the position masks are used.
308      *
309      * Does not throw.
310      *
311      * \see SelectionOption::dynamicMask()
312      */
313     void setDynamicMask(bool bEnabled);
314
315 private:
316     SelectionOptionStorage&       option();
317     const SelectionOptionStorage& option() const;
318 };
319
320 } // namespace gmx
321
322 #endif