Updated Doxygen comments for selections.
authorTeemu Murtola <teemu.murtola@gmail.com>
Sun, 15 Apr 2012 17:05:45 +0000 (20:05 +0300)
committerTeemu Murtola <teemu.murtola@gmail.com>
Sun, 15 Apr 2012 17:55:40 +0000 (20:55 +0300)
- Updated the list of installed selection headers to a more consistent
  set.
- Added/updated/made more uniform Doxygen comments for public classes in
  the selection library.
- Small source code adjustments, mainly for improved exception behavior.

Part of issue #867.

Change-Id: I289660ffc7326f810d2df5dbf6060416fdd38e45

13 files changed:
src/gromacs/options/optioninfo.h
src/gromacs/options/optionstoragetemplate.h
src/gromacs/selection.h
src/gromacs/selection/CMakeLists.txt
src/gromacs/selection/selection.cpp
src/gromacs/selection/selection.h
src/gromacs/selection/selectioncollection-impl.h
src/gromacs/selection/selectioncollection.cpp
src/gromacs/selection/selectioncollection.h
src/gromacs/selection/selectionoption.cpp
src/gromacs/selection/selectionoption.h
src/gromacs/selection/selectionoptioninfo.h
src/gromacs/selection/selectionoptionstorage.h

index a913b9280c6e9e5fe95c6a08376304844dc686a8..8958ba0531840b9ba39d49190b0783fd6ca2825b 100644 (file)
@@ -121,6 +121,8 @@ class OptionInfo
         /*! \cond libapi */
         /*! \brief
          * Wraps a given option object.
+         *
+         * Does not throw.
          */
         explicit OptionInfo(AbstractOptionStorage *option);
 
index 4b2a41825cce67449fd1e84d68cc47b6e453345e..3544f3724105afb110b48f15f278b5ff3ed8782c 100644 (file)
@@ -164,11 +164,12 @@ class OptionStorageTemplate : public AbstractOptionStorage
          * Adds a value to a temporary storage.
          *
          * \param[in] value  Value to add. A copy is made.
+         * \throws std::bad_alloc if out of memory.
          * \throws InvalidInputError if the maximum value count has been reached.
          *
          * Derived classes should call this function from the convertValue()
          * implementation to add converted values to the storage.
-         * If the maximum value cont has been reached, the value is discarded
+         * If the maximum value count has been reached, the value is discarded
          * and an exception is thrown.
          *
          * If adding values outside convertValue() (e.g., to set a custom
@@ -180,6 +181,8 @@ class OptionStorageTemplate : public AbstractOptionStorage
         /*! \brief
          * Commits values added with addValue().
          *
+         * \throws std::bad_alloc if out of memory.
+         *
          * If this function succeeds, values added with addValue() since the
          * previous clearSet() are added to the storage for the option.
          * Only throws in out-of-memory conditions, and provides the strong
index 53d38bda7f847b9392d96ec30d8b9d10974eef13..039158b6038398bc9048d23e3d20f688ff1c26b1 100644 (file)
  * \brief
  * Provides functionality for initializing and evaluating selections.
  *
- * \internal
+ * The core of the selection engine is accessed through
+ * gmx::SelectionCollection, which manages a set of selections.
+ * Documentation for that class explains the general selection mechanisms.
+ *
+ * For each selection that is parsed using a gmx::SelectionCollection, a
+ * gmx::Selection handle is returned and can be used to access information
+ * about that selection.  gmx::SelectionPosition is a helper class used to
+ * access information about individual positions in a selection.  These classes
+ * refer to internal state within the gmx::SelectionCollection, and their
+ * contents update automatically when the gmx::SelectionCollection is compiled
+ * or evaluated.
+ *
+ * This module also provides gmx::SelectionOption and gmx::SelectionOptionInfo
+ * classes for declaring options that evaluate to selections (see \ref
+ * module_options for general explanation of the options mechanism).  These
+ * classes provide the main interface to obtain gmx::Selection objects in
+ * trajectory analysis using gmx::TrajectoryAnalysisModule.
+ *
+ * \if libapi
+ * The selection module contains some lower-level functionality that is
+ * currently internal to it (centerofmass.h, indexutil.h, poscalc.h,
+ * position.h), but could possibly be useful also outside the module.
+ * It should be considered whether they should be moved somewhere else.
+ * \endif
+ *
+ * \if internal
  * Implementation details of different parts of the module are discussed on
  * separate pages:
  *   - \ref page_module_selection_custom
  *   - \ref page_module_selection_parser
  *   - \ref page_module_selection_compiler
  *   - \ref page_module_selection_insolidangle
+ * \endif
  *
  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
  */
@@ -55,6 +81,8 @@
 #define GMX_SELECTION_H
 
 #include "selection/selection.h"
+#include "selection/selectioncollection.h"
 #include "selection/selectionoption.h"
+#include "selection/selectionoptioninfo.h"
 
 #endif
index e834cf89781a51b62fd05772b5030f61185252db..6381fe505b52ede9cf440de18a93c3b5d89eb093 100644 (file)
@@ -2,18 +2,14 @@ file(GLOB SELECTION_SOURCES *.cpp)
 set(LIBGROMACS_SOURCES ${LIBGROMACS_SOURCES} ${SELECTION_SOURCES} PARENT_SCOPE)
 
 set(SELECTION_PUBLIC_HEADERS
-    centerofmass.h
     nbsearch.h
-    poscalc.h
     indexutil.h
     position.h
     selection.h
+    selectioncollection.h
     selectionenums.h
     selectionoption.h
-    selectionoptioninfo.h
-    selparam.h
-    selmethod.h
-    selvalue.h)
+    selectionoptioninfo.h)
 install(FILES ${SELECTION_PUBLIC_HEADERS}
         DESTINATION ${INCL_INSTALL_DIR}/gromacs/selection
         COMPONENT development)
index 2f17cc7e9c46afa01a0669ee95d1e4c1fb527949..54427cb5c2a842dd299ef21251a97d00976ae3bd 100644 (file)
  */
 /*! \internal \file
  * \brief
- * Implements gmx::Selection.
+ * Implements classes in selection.h.
  *
  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
  * \ingroup module_selection
  */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <statutil.h>
-#include <string2.h>
-#include <xvgr.h>
-
-#include "gromacs/selection/position.h"
-#include "gromacs/selection/selection.h"
-#include "gromacs/selection/selvalue.h"
+#include "selection.h"
 
+#include "position.h"
 #include "selelem.h"
+#include "selvalue.h"
 
 namespace gmx
 {
@@ -231,7 +223,7 @@ Selection::printInfo(FILE *fp) const
 void
 Selection::printDebugInfo(FILE *fp, int nmaxind) const
 {
-    const gmx_ana_pos_t &p = sel_->rawPositions_;
+    const gmx_ana_pos_t &p = data().rawPositions_;
 
     fprintf(fp, "  ");
     printInfo(fp);
index 8ba6682518e3ee94aa642ca00c91ed3b44e27263..a7c8541873402b6849aeab49bc1e3508cf978300 100644 (file)
@@ -30,7 +30,7 @@
  */
 /*! \file
  * \brief
- * Declares gmx::Selection.
+ * Declares gmx::Selection and supporting classes.
  *
  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
  * \inpublicapi
@@ -73,7 +73,9 @@ namespace internal
  *
  * This class is internal to the selection module, but resides in a public
  * header because of efficiency reasons: it allows frequently used access
- * methods to be inlined.
+ * methods in \ref Selection to be inlined.
+ *
+ * Methods in this class do not throw unless otherwise specified.
  *
  * \ingroup module_selection
  */
@@ -85,6 +87,7 @@ class SelectionData
          *
          * \param[in] elem   Root of the evaluation tree for this selection.
          * \param[in] selstr String that was parsed to produce this selection.
+         * \throws    std::bad_alloc if out of memory.
          */
         SelectionData(t_selelem *elem, const char *selstr);
         ~SelectionData();
@@ -112,13 +115,16 @@ class SelectionData
         /*! \brief
          * Computes total masses and charges for all selection positions.
          *
-         * \param[in]  top   Topology information.
+         * \param[in] top   Topology information.
+         * \throws    std::bad_alloc if out of memory.
          *
          * Computed values are cached, and need to be updated for dynamic
          * selections with refreshMassesAndCharges() after the selection has
          * been evaluated.  This is done by SelectionEvaluator.
          *
          * This function is called by SelectionCompiler.
+         *
+         * Strong exception safety guarantee.
          */
         void initializeMassesAndCharges(const t_topology *top);
         /*! \brief
@@ -159,6 +165,8 @@ class SelectionData
          *
          * This structure contains information about positions in the
          * selection that is not stored in ::gmx_ana_pos_t.
+         *
+         * Methods in this class do not throw.
          */
         struct PositionInfo
         {
@@ -198,7 +206,7 @@ class SelectionData
         bool                    bDynamicCoveredFraction_;
 
         /*! \brief
-         * Needed for to wrap access to information.
+         * Needed to wrap access to information.
          */
         friend class gmx::Selection;
         /*! \brief
@@ -214,6 +222,50 @@ class SelectionData
 /*! \brief
  * Provides access to a single selection.
  *
+ * This class provides a public interface for accessing selection information.
+ * General information about the selection can be accessed with methods name(),
+ * selectionText(), isDynamic(), and type().  The first three can be accessed
+ * any time after the selection has been parsed, and type() can be accessed
+ * after the selection has been compiled.
+ *
+ * Each selection is made of a set of positions.  Each position has associated
+ * coordinates, and possibly velocities and forces if they have been requested
+ * and are available.  It also has a set of atoms associated with it; typically
+ * the coordinates are the center-of-mass or center-of-geometry coordinates for
+ * that set of atoms.  To access the number of positions in the selection, use
+ * posCount().  To access individual positions, use position().
+ * See SelectionPosition for details of how to use individual positions.
+ * setOriginalId() can be used to adjust the return value of
+ * SelectionPosition::mappedId(); see that method for details.
+ *
+ * It is also possible to access the list of atoms that make up all the
+ * positions directly: atomCount() returns the total number of atoms in the
+ * selection and atomIndices() an array of their indices.
+ *
+ * Both positions and atoms can be accessed after the selection has been
+ * compiled.  For dynamic selections, the return values of these methods change
+ * after each evaluation to reflect the situation for the current frame.
+ * Before any frame has been evaluated, these methods return the maximal set
+ * to which the selection can evaluate.
+ *
+ * There are two possible modes for how positions for dynamic selections are
+ * handled.  In the default mode, posCount() can change, and for each frame,
+ * only the positions that are selected in that frame can be accessed.  In a
+ * masked mode, posCount() remains constant, i.e., the positions are always
+ * evaluated for the maximal set, and SelectionPosition::selected() is used to
+ * determine whether a position is selected for a frame.  The masked mode can
+ * be requested with SelectionOption::dynamicMask().
+ *
+ * The class also provides methods for printing out information: printInfo()
+ * and printDebugInfo().  These are mainly for internal use by Gromacs.
+ *
+ * This class works like a pointer type: copying and assignment is lightweight,
+ * and all copies work interchangeably, accessing the same internal data.
+ *
+ * Methods in this class do not throw.
+ *
+ * \see SelectionPosition
+ *
  * \inpublicapi
  * \ingroup module_selection
  */
@@ -231,6 +283,8 @@ class Selection
          * Creates a new selection object.
          *
          * \param  sel  Selection data to wrap.
+         *
+         * Only for internal use by the selection module.
          */
         explicit Selection(internal::SelectionData *sel) : sel_(sel) {}
 
@@ -243,8 +297,6 @@ class Selection
         //! Returns the type of positions in the selection.
         e_index_t type() const { return data().rawPositions_.m.type; }
 
-        //! Number of positions in the selection.
-        int posCount() const { return data().posCount(); }
         //! Total number of atoms in the selection.
         int atomCount() const
         {
@@ -260,30 +312,39 @@ class Selection
             return ConstArrayRef<int>(data().rawPositions_.g->isize,
                                       data().rawPositions_.g->index);
         }
+        //! Number of positions in the selection.
+        int posCount() const { return data().posCount(); }
         //! Access a single position.
         SelectionPosition position(int i) const;
         /*! \brief
          * Sets the ID for the \p i'th position for use with
          * SelectionPosition::mappedId().
          *
+         * \param[in] i  Zero-based index
+         * \param[in] id Identifier to set.
+         *
          * This method is not part of SelectionPosition because that interface
          * only provides access to const data by design.
+         *
+         * This method can only be called after compilation, before the
+         * selection has been evaluated for any frame.
+         *
+         * \see SelectionPosition::mappedId()
          */
         void setOriginalId(int i, int id) { data().rawPositions_.m.orgid[i] = id; }
 
+        //! Deprecated method for direct access to position data.
+        const gmx_ana_pos_t *positions() const { return &data().rawPositions_; }
+
         //! Returns whether the covered fraction can change between frames.
         bool isCoveredFractionDynamic() const { return data().isCoveredFractionDynamic(); }
         //! Returns the covered fraction for the current frame.
         real coveredFraction() const { return data().coveredFraction_; }
-
-        //! Deprecated method for direct access to position data.
-        const gmx_ana_pos_t *positions() const { return &data().rawPositions_; }
-
         /*! \brief
          * Initializes information about covered fractions.
          *
          * \param[in] type Type of covered fraction required.
-         * \returns   True if the covered fraction can be calculated for the
+         * \returns   true if the covered fraction can be calculated for the
          *      selection.
          */
         bool initCoveredFraction(e_coverfrac_t type)
@@ -295,6 +356,10 @@ class Selection
          * Prints out one-line description of the selection.
          *
          * \param[in] fp      Where to print the information.
+         *
+         * The output contains the name of the selection, the number of atoms
+         * and the number of positions, and indication of whether the selection
+         * is dynamic.
          */
         void printInfo(FILE *fp) const;
         /*! \brief
@@ -320,6 +385,13 @@ class Selection
             return *sel_;
         }
 
+        /*! \brief
+         * Pointer to internal data for the selection.
+         *
+         * The memory for this object is managed by a SelectionCollection
+         * object, and the \ref Selection class simply provides a public
+         * interface for accessing the data.
+         */
         internal::SelectionData *sel_;
 
         /*! \brief
@@ -329,13 +401,25 @@ class Selection
 };
 
 /*! \brief
- * Wrapper object to access information about a single selected position.
+ * Provides access to information about a single selected position.
+ *
+ * Each position has associated coordinates, and possibly velocities and forces
+ * if they have been requested and are available.  It also has a set of atoms
+ * associated with it; typically the coordinates are the center-of-mass or
+ * center-of-geometry coordinates for that set of atoms.  It is possible that
+ * there are not atoms associated if the selection has been provided as a fixed
+ * position.
+ *
+ * After the selection has been compiled, but not yet evaluated, the contents
+ * of the coordinate, velocity and force vectors are undefined.
  *
  * Default copy constructor and assignment operators are used, and work as
  * intended: the copy references the same position and works identically.
  *
  * Methods in this class do not throw.
  *
+ * \see Selection
+ *
  * \inpublicapi
  * \ingroup module_selection
  */
@@ -348,7 +432,10 @@ class SelectionPosition
          * \param[in] sel    Selection from which the position is wrapped.
          * \param[in] index  Zero-based index of the position to wrap.
          *
-         * Does not throw.  Asserts if \p index is out of range.
+         * Asserts if \p index is out of range.
+         *
+         * Only for internal use of the library.  To obtain a SelectionPosition
+         * object in other code, use Selection::position().
          */
         SelectionPosition(const internal::SelectionData &sel, int index)
             : sel_(&sel), i_(index)
@@ -360,7 +447,7 @@ class SelectionPosition
         /*! \brief
          * Returns type of this position.
          *
-         * Currently returns the same as Selection::type().
+         * Currently always returns the same as Selection::type().
          */
         e_index_t type() const { return sel_->rawPositions_.m.type; }
         //! Returns coordinates for this position.
@@ -383,7 +470,7 @@ class SelectionPosition
         //! Returns whether force is available for this position.
         bool hasForce() const { return sel_->rawPositions_.f != NULL; }
         /*! \brief
-         * Returns velocity for this position.
+         * Returns force for this position.
          *
          * Must not be called if hasForce() returns false.
          */
@@ -396,7 +483,7 @@ class SelectionPosition
          * Returns total mass for this position.
          *
          * Returns the total mass of atoms that make up this position.
-         * If there are not atoms associated or masses are not available,
+         * If there are no atoms associated or masses are not available,
          * returns unity.
          */
         real mass() const
@@ -407,7 +494,7 @@ class SelectionPosition
          * Returns total charge for this position.
          *
          * Returns the sum of charges of atoms that make up this position.
-         * If there are not atoms associated or masses are not available,
+         * If there are no atoms associated or charges are not available,
          * returns zero.
          */
         real charge() const
@@ -431,6 +518,18 @@ class SelectionPosition
             return ConstArrayRef<int>(atomCount(),
                                       &sel_->rawPositions_.g->index[first]);
         }
+        /*! \brief
+         * Returns whether this position is selected in the current frame.
+         *
+         * The return value is equivalent to \c refid() == -1.  Returns always
+         * true if SelectionOption::dynamicMask() has not been set.
+         *
+         * \see refId()
+         */
+        bool selected() const
+        {
+            return refId() >= 0;
+        }
         /*! \brief
          * Returns reference ID for this position.
          *
@@ -443,12 +542,13 @@ class SelectionPosition
          * selection are set to -1, otherwise they are removed completely.
          *
          * Example:
-         * If a dynamic selection consists of three positions, after
+         * If a dynamic selection consists of at most three positions, after
          * compilation refId() will return 0, 1, 2 for them, respectively.
          * If for a particular frame, only the first and the third are present,
          * refId() will return 0, 2.
          * If SelectionOption::dynamicMask() has been set, all three positions
-         * can be accessed also in this case and refId() will return 0, -1, 2.
+         * can be accessed also for that frame and refId() will return 0, -1,
+         * 2.
          */
         int refId() const
         {
@@ -460,9 +560,17 @@ class SelectionPosition
          * Returns ID of the position that corresponds to that set with
          * Selection::setOriginalId().
          *
-         * If for an array \c id, \c setOriginalId(i, c[i]) has been called
+         * If for an array \c id, \c setOriginalId(i, id[i]) has been called
          * for each \c i, then it always holds that
-         * \c mappedId()==c[refId()].
+         * \c mappedId()==id[refId()].
+         *
+         * Selection::setOriginalId() has not been called, the default values
+         * are dependent on type():
+         *  - ::INDEX_ATOM: atom indices
+         *  - ::INDEX_RES:  residue numbers
+         *  - ::INDEX_MOL:  molecule numbers
+         *  .
+         * All the default values are zero-based
          */
         int mappedId() const
         {
index 2f21c515aa5c530ae591e6af0391a93c533a9fd9..76207dd2ba8978002daacbdb053743bb41adbfda 100644 (file)
@@ -57,7 +57,7 @@ namespace gmx
 {
 //! Smart pointer for managing an internal selection data object.
 typedef gmx_unique_ptr<internal::SelectionData>::type SelectionDataPointer;
-//! Shorthand for storing a list of selections internally.
+//! Container for storing a list of selections internally.
 typedef std::vector<SelectionDataPointer> SelectionDataList;
 }
 
@@ -109,8 +109,15 @@ class SelectionOptionStorage;
 class SelectionCollection::Impl
 {
     public:
+        /*! \brief
+         * Request for postponed parsing of selections.
+         *
+         * Used to communicate what needs to be parsed with
+         * parseRequestedFromStdin() or parseRequstedFromString().
+         */
         struct SelectionRequest
         {
+            //! Initializes a request for the given option.
             SelectionRequest(const std::string &name, const std::string &descr,
                              SelectionOptionStorage *storage)
                 : name(name), descr(descr), storage(storage)
@@ -124,20 +131,31 @@ class SelectionCollection::Impl
              */
             int count() const;
 
+            //! Name of the option to which this request relates to.
             std::string                 name;
+            //! Description of the option to which this request relates to.
             std::string                 descr;
+            //! Storage object to which the selections will be added.
             SelectionOptionStorage     *storage;
         };
 
-        //! Shorthand for a list of selection requests.
+        //! Collection for a list of selection requests.
         typedef std::vector<SelectionRequest> RequestList;
 
+        /*! \brief
+         * Helper class that clears a request list on scope exit.
+         *
+         * Methods in this class do not throw.
+         */
         class RequestsClearer
         {
             public:
-                RequestsClearer(RequestList *requests) : requests_(requests)
+                //! Constructs an object that clears given list on scope exit.
+                explicit RequestsClearer(RequestList *requests)
+                    : requests_(requests)
                 {
                 }
+                //! Clears the request list given to the constructor.
                 ~RequestsClearer()
                 {
                     requests_->clear();
@@ -155,7 +173,11 @@ class SelectionCollection::Impl
         Impl();
         ~Impl();
 
-        //! Clears the symbol table of the selection collection.
+        /*! \brief
+         * Clears the symbol table of the selection collection.
+         *
+         * Does not throw.
+         */
         void clearSymbolTable();
         /*! \brief
          * Helper function that runs the parser once the tokenizer has been
@@ -166,8 +188,14 @@ class SelectionCollection::Impl
          *      (if -1, parse as many as provided by the user).
          * \param[out]    output  Vector to which parsed selections are
          *      appended.
+         * \throws        std::bad_alloc if out of memory.
+         * \throws        InvalidInputError if there is a parsing error.
          *
-         * Does not clear \p output.
+         * Parsed selections are appended to \p output without clearing it
+         * first.  If parsing fails, \p output is not modified.
+         *
+         * Used internally to implement parseFromStdin(), parseFromFile() and
+         * parseFromString().
          */
         void runParser(void *scanner, int maxnr,
                        SelectionList *output);
@@ -177,6 +205,9 @@ class SelectionCollection::Impl
          * \param[in] name    Name for the requested selections.
          * \param[in] descr   Description of the requested selections.
          * \param     storage Storage object to receive the selections.
+         * \throws    std::bad_alloc if out of memory.
+         *
+         * Strong exception safety.
          *
          * \see parseRequestedFromStdin()
          */
@@ -194,6 +225,9 @@ class SelectionCollection::Impl
          * \a _grps and replaces the reference with a constant element that
          * contains the atoms from the referenced group.  Any failures to
          * resolve references are reported to \p errors.
+         *
+         * Does not throw currently, but this is subject to change when more
+         * underlying code is converted to C++.
          */
         void resolveExternalGroups(struct t_selelem *root,
                                    MessageStringCollector *errors);
@@ -217,7 +251,7 @@ class SelectionCollection::Impl
          *  - 4: combine 2 and 3
          */
         int                     _debugLevel;
-        //! Whether external groups have been set for the collection.
+        //! Whether setIndexGroups() has been called.
         bool                    _bExternalGroupsSet;
         //! External index groups (can be NULL).
         gmx_ana_indexgrps_t    *_grps;
index 22a30826cbdf1b2adb69b5616617871f62d59e7f..e5f9d94e3769c90a1dfea8be462dc74f24d8295b 100644 (file)
 
 #include <cstdio>
 
-#include <smalloc.h>
-#include <statutil.h>
-#include <string2.h>
-#include <xvgr.h>
+#include "futil.h"
+#include "oenv.h"
+#include "smalloc.h"
+#include "xvgr.h"
 
 #include "gromacs/fatalerror/exceptions.h"
 #include "gromacs/fatalerror/gmxassert.h"
@@ -153,11 +153,13 @@ SelectionCollection::Impl::runParser(yyscan_t scanner, int maxnr,
     if (bOk)
     {
         SelectionDataList::const_iterator i;
+        output->reserve(output->size() + nr);
         for (i = _sc.sel.begin() + oldCount; i != _sc.sel.end(); ++i)
         {
             output->push_back(Selection(i->get()));
         }
     }
+    // TODO: Remove added selections from the collection if parsing failed?
 
     if (!bOk || !errors.isEmpty())
     {
@@ -303,30 +305,27 @@ SelectionCollection::setOutputPosType(const char *type)
 
 
 void
-SelectionCollection::setDebugLevel(int debuglevel)
+SelectionCollection::setDebugLevel(int debugLevel)
 {
-    _impl->_debugLevel = debuglevel;
+    _impl->_debugLevel = debugLevel;
 }
 
 
 void
 SelectionCollection::setTopology(t_topology *top, int natoms)
 {
-    gmx_ana_selcollection_t *sc = &_impl->_sc;
-    sc->pcc.setTopology(top);
-    sc->top = top;
-
-    /* Get the number of atoms from the topology if it is not given */
+    GMX_RELEASE_ASSERT(natoms > 0 || top != NULL,
+        "The number of atoms must be given if there is no topology");
+    // Get the number of atoms from the topology if it is not given.
     if (natoms <= 0)
     {
-        if (sc->top == NULL)
-        {
-            GMX_THROW(APIError("Selections need either the topology or the number of atoms"));
-        }
-        natoms = sc->top->atoms.nr;
+        natoms = top->atoms.nr;
     }
-
+    gmx_ana_selcollection_t *sc = &_impl->_sc;
+    // Do this first, as it allocates memory, while the others don't throw.
     gmx_ana_index_init_simple(&sc->gall, natoms, NULL);
+    sc->pcc.setTopology(top);
+    sc->top = top;
 }
 
 
index decc46e1873986033171b4bffdbdabf6d28207b4..7a689388e4671cfe8043f2b2c708b0dfade91171 100644 (file)
  *
  * For more info, check our website at http://www.gromacs.org
  */
-/*! \libinternal \file
+/*! \file
  * \brief
  * Declares gmx::SelectionCollection.
  *
  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
- * \inlibraryapi
+ * \inpublicapi
  * \ingroup module_selection
  */
 #ifndef GMX_SELECTION_SELECTIONCOLLECTION_H
@@ -57,31 +57,48 @@ class SelectionCompiler;
 class SelectionEvaluator;
 class SelectionOptionStorage;
 
-/*! \libinternal \brief
+/*! \brief
  * Collection of selections.
  *
- * Some default values must then be set with
- * gmx_ana_selcollection_set_refpostype() and
- * gmx_ana_selcollection_set_outpostype().
+ * This class is the main interface to the core of the selection engine.
+ * It is used to initialize and manage a collection of selections that share
+ * the same topology.  Selections within one collection can share variables and
+ * can be optimized together.  Selections from two different collections do not
+ * interact.
+ *
+ * The constructor creates an empty selection collection object.  To initialize
+ * the object, either call initOptions(), or both setReferencePosType() and
+ * setOutputPosType().  See these methods for more details on the
+ * initialization options.
+ *
+ * After setting the default values, one or more selections can be parsed with
+ * one or more calls to parseFromStdin(), parseFromFile(), and/or
+ * parseFromString().  parseRequestedFromStdin() and parseRequestedFromString()
+ * are provided for integration with SelectionOption.  After all selections are
+ * parsed, the topology must be set with setTopology() unless
+ * requiresTopology() returns false (the topology can also be set earlier).
+ * setIndexGroups() must also be called if external index group references are
+ * used in the selections; it can be called at any point before compile().
+ * Once all selections are parsed, they must be compiled all at once using
+ * compile().
  *
- * After setting the default values, one or more selections can be parsed
- * with one or more calls to parseFromStdin(), parseFromFile(), and/or
- * parseFromString().  After all selections are parsed, the topology must be
- * set with setTopology() unless requiresTopology() returns false (the topology
- * can also be set earlier).  Once all selections are parsed, they must be
- * compiled all at once using compile().
  * After compilation, dynamic selections have the maximum number of atoms they
- * can evaluate to, but positions have undefined values.  evaluate() can be
- * used to update the selections for a new frame.
- * evaluateFinal() can be called after all the frames have been processed to
- * restore the selection values back to the ones they were after compile().
+ * can evaluate to, but positions have undefined values (see \ref Selection and
+ * SelectionPosition).  evaluate() can be used to update the selections for a
+ * new frame.  evaluateFinal() can be called after all the frames have been
+ * processed to restore the selection values back to the ones they were after
+ * compile().
  *
  * At any point, requiresTopology() can be called to see whether the
  * information provided so far requires loading the topology.
  * printTree() can be used to print the internal representation of the
  * selections (mostly useful for debugging).
  *
- * \inlibraryapi
+ * Note that for trajectory analysis using TrajectoryAnalysisModule, the
+ * SelectionCollection object is managed by Gromacs, and \ref Selection objects
+ * are obtained from SelectionOption.
+ *
+ * \inpublicapi
  * \ingroup module_selection
  */
 class SelectionCollection
@@ -97,6 +114,13 @@ class SelectionCollection
 
         /*! \brief
          * Initializes options for setting global properties on the collection.
+         *
+         * \returns Initialized options object.
+         * \throws  std::bad_alloc if out of memory.
+         *
+         * The returned options can be used to set the default position types
+         * (see setReferencePosType() and setOutputPosType()) and debugging
+         * options.
          */
         Options &initOptions();
 
@@ -107,11 +131,14 @@ class SelectionCollection
          * \param[in]     type      Default selection reference position type
          *     (one of the strings acceptable for
          *     PositionCalculationCollection::typeFromEnum()).
+         * \throws  InternalError if \p type is invalid.
          *
          * Should be called before calling the parser functions, unless
          * initOptions() has been called.  In the latter case, can still be
-         * used to override the default value and/or the value provided through
-         * the Options object.
+         * used to override the default value (before initOptions() is called)
+         * and/or the value provided through the Options object.
+         *
+         * Strong exception safety.
          */
         void setReferencePosType(const char *type);
         /*! \brief
@@ -121,17 +148,32 @@ class SelectionCollection
          * \param[in]     type      Default selection output position type
          *     (one of the strings acceptable for
          *     PositionCalculationCollection::typeFromEnum()).
+         * \throws  InternalError if \p type is invalid.
          *
          * Should be called before calling the parser functions, unless
          * initOptions() has been called.  In the latter case, can still be
-         * used to override the default value and/or the value provided through
-         * the Options object.
+         * used to override the default value (before initOptions() is called)
+         * and/or the value provided through the Options object.
+         *
+         * Strong exception safety.
          */
         void setOutputPosType(const char *type);
         /*! \brief
          * Sets the debugging level for the selection collection.
+         *
+         * \param[in]   debugLevel  Debug level to set (0 = no debug
+         *      information).
+         *
+         * initOptions() creates debugging options that can also be used to set
+         * the debug level.  These are normally hidden, but if this method is
+         * called before initOptions() with a non-zero \p debugLevel, they are
+         * made visible.
+         *
+         * Mostly useful for debugging tools.
+         *
+         * Does not throw.
          */
-        void setDebugLevel(int debuglevel);
+        void setDebugLevel(int debugLevel);
 
         /*! \brief
          * Returns true if the collection requires topology information for
@@ -144,6 +186,8 @@ class SelectionCollection
          * based just on the position types set.
          * After parser functions have been called, the return value also takes
          * into account the selection keywords used.
+         *
+         * Does not throw.
          */
         bool requiresTopology() const;
         /*! \brief
@@ -152,21 +196,35 @@ class SelectionCollection
          * \param[in]     top       Topology data.
          * \param[in]     natoms    Number of atoms. If <=0, the number of
          *      atoms in the topology is used.
-         * \retval  0 on success.
-         * \retval  ::eeInvalidValue if \p top is NULL and \p natoms <= 0.
          *
-         * The topology is also set for the position calculation collection
-         * associated with the collection.
+         * Either the topology must be provided, or \p natoms must be > 0.
          *
          * \p natoms determines the largest atom index that can be selected by
          * the selection: even if the topology contains more atoms, they will
          * not be selected.
+         *
+         * Does not throw currently, but this is subject to change when more
+         * underlying code is converted to C++.
          */
         void setTopology(t_topology *top, int natoms);
         /*! \brief
          * Sets the external index groups to use for the selections.
          *
-         * Can be called only once with non-NULL \p grps.
+         * \param[in]  grps  Index groups to use for the selections.
+         * \throws  std::bad_alloc if out of memory.
+         * \throws  InvalidInputError if a group reference cannot be resolved.
+         *
+         * Only the first call to this method can have a non-NULL \p grps.
+         * At this point, any selections that have already been provided are
+         * searched for references to external groups, and the references are
+         * replaced by the contents of the groups.  If any referenced group
+         * cannot be found in \p grps (or if \p grps is NULL and there are any
+         * references), InvalidInputError is thrown.
+         *
+         * The selection collection keeps a reference to \p grps until this
+         * method is called with a NULL \p grps.
+         * If this method is not called before compile(), it is automatically
+         * called as setIndexGroups(NULL).
          */
         void setIndexGroups(gmx_ana_indexgrps_t *grps);
         /*! \brief
@@ -175,17 +233,39 @@ class SelectionCollection
          *
          * \param[in]  bInteractive Whether the parser should behave
          *      interactively.
+         * \throws     unspecified  Can throw any exception thrown by
+         *      parseFromStdin().
+         * \throws     std::bad_alloc if out of memory.
          *
          * This method cooperates with SelectionOption to allow interactive
          * input of missing selections after all options have been processed.
          * It should be called after the Options::finish() method has been
          * called on all options that add selections to this collection.
+         * For each required selection option that has not been given, as well
+         * as for optional selection options that have been specified without
+         * values, it will prompt the user to input the necessary selections.
          */
         void parseRequestedFromStdin(bool bInteractive);
         /*! \brief
          * Parses selection(s) from a string for options not yet provided.
          *
          * \param[in]  str     String to parse.
+         * \throws     unspecified  Can throw any exception thrown by
+         *      parseFromString().
+         * \throws     std::bad_alloc if out of memory.
+         * \throws     InvalidInputError if
+         *      - the number of selections in \p str doesn't match the number
+         *        requested.
+         *      - any selection uses a feature that is not allowed for the
+         *        corresponding option.
+         * \throws     APIError if there is a request for any number of
+         *      selections that is not the last (in which case it is not
+         *      possible to determine which selections belong to which
+         *      request).
+         *
+         * This method behaves as parseRequestedFromStdin(), but reads the
+         * selections from a string instead of standard input.
+         * This method is mainly used for testing.
          *
          * \see parseRequestedFromStdin()
          */
@@ -198,18 +278,18 @@ class SelectionCollection
          * \param[in]  bInteractive Whether the parser should behave
          *      interactively.
          * \param[out] output   Vector to which parsed selections are appended.
-         * \retval     0 on success.
-         * \retval     ::eeInvalidInput on syntax error (an interactive parser
-         *      only returns this if an incorrect number of selections is
-         *      provided).
+         * \throws     std::bad_alloc if out of memory.
+         * \throws     InvalidInputError if there is a parsing error
+         *      (an interactive parser only throws this if too few selections
+         *      are provided and the user forced the end of input).
          *
          * Parsed selections are appended to \p output without clearing it
          * first.  If parsing fails, \p output is not modified.
          *
          * The objects returned in \p output remain valid for the lifetime of
-         * the selection collection, and should not be freed by the user.
+         * the selection collection.
          * Some information about the selections only becomes available once
-         * compile() has been called.
+         * compile() has been called; see \ref Selection.
          */
         void parseFromStdin(int count, bool bInteractive,
                             SelectionList *output);
@@ -218,16 +298,16 @@ class SelectionCollection
          *
          * \param[in]  filename Name of the file to parse selections from.
          * \param[out] output   Vector to which parsed selections are appended.
-         * \retval     0 on success.
-         * \retval     ::eeInvalidInput on syntax error.
+         * \throws     std::bad_alloc if out of memory.
+         * \throws     InvalidInputError if there is a parsing error.
          *
          * Parsed selections are appended to \p output without clearing it
          * first.  If parsing fails, \p output is not modified.
          *
          * The objects returned in \p output remain valid for the lifetime of
-         * the selection collection, and should not be freed by the user.
+         * the selection collection.
          * Some information about the selections only becomes available once
-         * compile() has been called.
+         * compile() has been called; see \ref Selection.
          */
         void parseFromFile(const std::string &filename,
                            SelectionList *output);
@@ -236,28 +316,35 @@ class SelectionCollection
          *
          * \param[in]  str      String to parse selections from.
          * \param[out] output   Vector to which parsed selections are appended.
-         * \retval     0 on success.
-         * \retval     ::eeInvalidInput on syntax error.
+         * \throws     std::bad_alloc if out of memory.
+         * \throws     InvalidInputError if there is a parsing error.
          *
          * Parsed selections are appended to \p output without clearing it
          * first.  If parsing fails, \p output is not modified.
          *
          * The objects returned in \p output remain valid for the lifetime of
-         * the selection collection, and should not be freed by the user.
+         * the selection collection.
          * Some information about the selections only becomes available once
-         * compile() has been called.
+         * compile() has been called; see \ref Selection.
          */
         void parseFromString(const std::string &str,
                              SelectionList *output);
         /*! \brief
          * Prepares the selections for evaluation and performs optimizations.
          *
-         * \retval  0 on successful compilation, a non-zero error code on error.
+         * \throws  InconsistentInputError if topology is required but not set.
+         * \throws  InvalidInputError if setIndexGroups() has not been called
+         *      and there are index group references.
+         * \throws  unspecified if compilation fails (TODO: list/reduce these).
          *
          * Before compilation, selections should have been added to the
          * collection using the parseFrom*() functions.
          * The compiled selection collection can be passed to evaluate() to
          * evaluate the selection for a frame.
+         * Before the compiled selection is evaluated, the selections indicate
+         * the maximal set of atoms/positions to which they can be evaluated;
+         * see \ref Selection.
+         *
          * If an error occurs, the collection is cleared.
          *
          * The covered fraction information is initialized to ::CFRAC_NONE for
@@ -269,7 +356,8 @@ class SelectionCollection
          *
          * \param[in] fr  Frame for which the evaluation should be carried out.
          * \param[in] pbc PBC data, or NULL if no PBC should be used.
-         * \returns   0 on successful evaluation, a non-zero error code on error.
+         * \throws    unspeficied  Multiple possible exceptions to indicate
+         *      evaluation failure (TODO: enumerate).
          */
         void evaluate(t_trxframe *fr, t_pbc *pbc);
         /*! \brief
@@ -277,7 +365,13 @@ class SelectionCollection
          *
          * \param[in] nframes Total number of frames.
          *
-         * This function does not throw.
+         * This method restores the selections to the state they were after
+         * compile().
+         *
+         * \p nframes should equal the number of times evaluate() has been
+         * called.
+         *
+         * Does not throw.
          */
         void evaluateFinal(int nframes);
 
@@ -288,6 +382,10 @@ class SelectionCollection
          * \param[in] fp      File handle to receive the output.
          * \param[in] bValues If true, the evaluated values of selection
          *      elements are printed as well.
+         *
+         * The output is very techical, and intended for debugging purposes.
+         *
+         * Does not throw.
          */
         void printTree(FILE *fp, bool bValues) const;
         /*! \brief
@@ -295,6 +393,8 @@ class SelectionCollection
          *
          * \param[in] fp   Output file.
          * \param[in] oenv Output options structure.
+         *
+         * Does not throw.
          */
         void printXvgrInfo(FILE *fp, output_env_t oenv) const;
 
index 0521cb6a48eb1cc59ff34594d041e443adada028..d5a87b0a3bfe036af4b76ebce0affc167d871788 100644 (file)
@@ -142,6 +142,7 @@ void SelectionOptionStorage::processAll()
 
 void SelectionOptionStorage::setAllowedValueCount(int count)
 {
+    // TODO: It should be possible to have strong exception safety here.
     MessageStringCollector errors;
     errors.startContext("In option '" + name() + "'");
     if (count >= 0)
@@ -170,11 +171,10 @@ void SelectionOptionStorage::setAllowedValueCount(int count)
 
 void SelectionOptionStorage::setSelectionFlag(SelectionFlag flag, bool bSet)
 {
-    _selectionFlags.set(flag, bSet);
     ValueList::iterator i;
     for (i = values().begin(); i != values().end(); ++i)
     {
-        if (_selectionFlags.test(efOnlyStatic) && i->isDynamic())
+        if (flag == efOnlyStatic && bSet && i->isDynamic())
         {
             MessageStringCollector errors;
             errors.startContext("In option '" + name() + "'");
@@ -182,6 +182,10 @@ void SelectionOptionStorage::setSelectionFlag(SelectionFlag flag, bool bSet)
             errors.finishContext();
             GMX_THROW(InvalidInputError(errors.toString()));
         }
+    }
+    _selectionFlags.set(flag, bSet);
+    for (i = values().begin(); i != values().end(); ++i)
+    {
         i->data().setFlags(_selectionFlags);
     }
 }
@@ -296,12 +300,10 @@ class SelectionCollectionSetter : public OptionsModifyingTypeVisitor<SelectionOp
 
 } // namespace
 
-/*! \cond libapi */
 void setSelectionCollectionForOptions(Options *options,
                                       SelectionCollection *selections)
 {
     SelectionCollectionSetter(selections).visitSubSection(options);
 }
-//! \endcond
 
 } // namespace gmx
index a47b3517fe6f57dde9d5b40b75f27062b9434f04..169eab1b040f4e3295c7f41da23226b1bf61bb4f 100644 (file)
@@ -52,6 +52,8 @@ class SelectionOptionStorage;
 /*! \brief
  * Specifies an option that provides selection(s).
  *
+ * Public methods in this class do not throw.
+ *
  * \inpublicapi
  * \ingroup module_selection
  */
@@ -65,11 +67,17 @@ class SelectionOption : public OptionTemplate<Selection, SelectionOption>
 
         /*! \brief
          * Request velocity evaluation for output positions.
+         *
+         * Note that even with this flag set, velocities may not be available,
+         * in which case SelectionPosition::hasVelocity() returns false.
          */
         MyClass &evaluateVelocities()
         { _selectionFlags.set(efEvaluateVelocities); return me(); }
         /*! \brief
          * Request force evaluation for output positions.
+         *
+         * Note that even with this flag set, forces may not be available,
+         * in which case SelectionPosition::hasForce() returns false.
          */
         MyClass &evaluateForces()
         { _selectionFlags.set(efEvaluateForces); return me(); }
@@ -88,9 +96,8 @@ class SelectionOption : public OptionTemplate<Selection, SelectionOption>
         /*! \brief
          * Handle dynamic selections for this option with position masks.
          *
-         * \if internal
-         * Sets ::POS_MASKONLY on the positions for this selection.
-         * \endif
+         * \see Selection
+         * \see SelectionPosition::selected()
          */
         MyClass &dynamicMask()
         { _selectionFlags.set(efDynamicMask); return me(); }
index b3a461cdff2cfae85e4f5a38ec4b71580fa371f8..9a56ea738d1b4d8c37fc0a088ebcda69fe2e8f46 100644 (file)
@@ -95,17 +95,25 @@ if ( condition )
 class SelectionOptionInfo : public OptionInfo
 {
     public:
-        //! Creates option info object for given storage object.
+        /*! \brief
+         * Creates option info object for given storage object.
+         *
+         * Does not throw.
+         */
         explicit SelectionOptionInfo(SelectionOptionStorage *option);
 
         /*! \brief
          * Set selection collection into which this option adds selections.
          *
+         * \param   selections  Selection collection to set.
+         *
          * This must be called before the values are added.
          *
          * Typically it is called through setSelectionCollectionForOptions(),
          * which recursively sets the collection for all selection options in
          * an Options object.
+         *
+         * Does not throw.
          */
         void setSelectionCollection(SelectionCollection *selections);
 
@@ -113,20 +121,78 @@ class SelectionOptionInfo : public OptionInfo
          * Sets the number of selections allowed for the option.
          *
          * \param[in] count  Number of allowed selections.
+         * \throws    std::bad_alloc if out of memory.
+         * \throws    InvalidInputError if values have already been provided
+         *      and their count does not match.
          */
         void setValueCount(int count);
 
-        //! \copydoc SelectionOption::evaluateVelocities()
+        /*! \brief
+         * Sets whether this option evaluates velocities for positions.
+         *
+         * \param[in] bEnabled  If true, velocities are evaluated.
+         *
+         * Does not throw.
+         *
+         * \see SelectionOption::evaluateVelocities()
+         */
         void setEvaluateVelocities(bool bEnabled);
-        //! \copydoc SelectionOption::evaluateForces()
+        /*! \brief
+         * Sets whether this option evaluates forces for positions.
+         *
+         * \param[in] bEnabled  If true, forces are evaluated.
+         *
+         * Does not throw.
+         *
+         * \see SelectionOption::evaluateForces()
+         */
         void setEvaluateForces(bool bEnabled);
-        //! \copydoc SelectionOption::onlyAtoms()
+        /*! \brief
+         * Sets whether this option accepts positions that come from multiple
+         * atoms.
+         *
+         * \param[in] bEnabled  If true, the option accepts only positions that
+         *      evaluate to atom positions.
+         *
+         * TODO: This is not yet implemented.
+         *
+         * \see SelectionOption::onlyAtoms()
+         */
         void setOnlyAtoms(bool bEnabled);
-        //! \copydoc SelectionOption::onlyStatic()
+        /*! \brief
+         * Sets whether this option accepts dynamic selections.
+         *
+         * \param[in] bEnabled  If true, the option accepts only static
+         *      selections.
+         * \throws    std::bad_alloc if out of memory.
+         * \throws    InvalidInputError if dynamic selections have already been
+         *      provided.
+         *
+         * Strong exception safety guarantee.
+         *
+         * \see SelectionOption::onlyStatic()
+         */
         void setOnlyStatic(bool bEnabled);
-        //! \copydoc SelectionOption::dynamicMask()
+        /*! \brief
+         * Sets whether this option uses position masks for dynamic selections.
+         *
+         * \param[in] bEnabled  If true, the position masks are used.
+         *
+         * Does not throw.
+         *
+         * \see SelectionOption::dynamicMask()
+         */
         void setDynamicMask(bool bEnabled);
-        //! \copydoc SelectionOption::dynamicOnlyWhole()
+        /*! \brief
+         * Sets whether atom coordinates are allowed as reference positions.
+         *
+         * \param[in] bEnabled  If true, the option does not accept atom
+         *      coordinates as reference positions.
+         *
+         * TODO: This is not yet implemented.
+         *
+         * \see SelectionOption::dynamicOnlyWhole()
+         */
         void setDynamicOnlyWhole(bool bEnabled);
 
     private:
@@ -134,8 +200,7 @@ class SelectionOptionInfo : public OptionInfo
         const SelectionOptionStorage &option() const;
 };
 
-/*! \cond libapi */
-/*! \libinternal \brief
+/*! \brief
  * Set selection collection for all selection options.
  *
  * Recursively sets the selection collection to \p selections for all selection
@@ -144,7 +209,7 @@ class SelectionOptionInfo : public OptionInfo
  *
  * Does not throw.
  *
- * \inlibraryapi
+ * \inpublicapi
  */
 void setSelectionCollectionForOptions(Options *options,
                                       SelectionCollection *selections);
index 582ed51d058203e13ff1aab7fd101871e75cc1e7..f0d13e756157b9ce549abb472b3cfd24d4045dcc 100644 (file)
@@ -80,6 +80,11 @@ class SelectionOptionStorage : public OptionStorageTemplate<Selection>
          * \param[in] selections  List of selections to add.
          * \param[in] bFullValue  If true, the provided selections are the full
          *      value of the option, and additional checks are performed.
+         * \throws  std::bad_alloc if out of memory.
+         * \throws  InvalidInputError if
+         *      - There is an incorrect number of selections in \p selections.
+         *      - Any selection in \p selections is not allowed for this
+         *        option.
          *
          * This function is used to implement the methods
          * SelectionCollection::parseRequestedFromStdin() and
@@ -93,25 +98,22 @@ class SelectionOptionStorage : public OptionStorageTemplate<Selection>
         // Required to access the number of values in selection requests.
         // See SelectionCollection::Impl.
         using MyBase::maxValueCount;
-        /*! \brief
-         * Sets the number of selections allowed for this selection.
-         *
-         * \param[in] count       Required number of selections for this option.
-         *
-         * If values have already been provided, it is checked that a correct
-         * number has been provided.  If requests have already been made, but
-         * have not yet been processed, they are also affected.
-         */
+        //! \copydoc SelectionOptionInfo::setValueCount()
         void setAllowedValueCount(int count);
         /*! \brief
          * Alters flags for the selections created by this option.
          *
          * \param[in] flag        Flag to change.
          * \param[in] bSet        Whether to set or clear the flag.
+         * \throws    std::bad_alloc if out of memory.
+         * \throws    InvalidInputError if selections have already been
+         *      provided and conflict with the given flags.
+         *
+         * If selections have already been provided, it is checked that they
+         * match the limitations enforced by the flags.  Pending requests are
+         * also affected.
          *
-         * If values have already been provided, it is checked that they match
-         * the limitations enforced by the flags.  If requests have already
-         * been made, but have not yet been processed, they are also affected.
+         * Strong exception safety guarantee.
          */
         void setSelectionFlag(SelectionFlag flag, bool bSet);