Improve selection interface (remove some pointers).
authorTeemu Murtola <teemu.murtola@gmail.com>
Sat, 24 Mar 2012 13:47:37 +0000 (15:47 +0200)
committerTeemu Murtola <teemu.murtola@gmail.com>
Sun, 1 Apr 2012 06:04:46 +0000 (09:04 +0300)
Made it possible to handle Selection objects by value; the data that is
unique and non-copyable is now in a separate internal class.

Change-Id: Ibb6a55c180a1cdb0940229ed98258ca6d3d34d88

24 files changed:
share/template/template.cpp
src/gromacs/selection/compiler.cpp
src/gromacs/selection/evaluate.cpp
src/gromacs/selection/parsetree.cpp
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
src/gromacs/selection/tests/selectioncollection.cpp
src/gromacs/selection/tests/selectionoption.cpp
src/gromacs/trajectoryanalysis/analysismodule.cpp
src/gromacs/trajectoryanalysis/analysismodule.h
src/gromacs/trajectoryanalysis/modules/angle.cpp
src/gromacs/trajectoryanalysis/modules/angle.h
src/gromacs/trajectoryanalysis/modules/distance.cpp
src/gromacs/trajectoryanalysis/modules/distance.h
src/gromacs/trajectoryanalysis/modules/select.cpp
src/gromacs/trajectoryanalysis/modules/select.h
src/gromacs/trajectoryanalysis/tests/test_selection.cpp

index 5314988609ccb8c2d58a3c13bb69c233e3437839..4b6c6bdccf7e8f817513c7a2920d2dd8873bda44 100644 (file)
@@ -62,8 +62,8 @@ class AnalysisTemplate : public TrajectoryAnalysisModule
         Options                          _options;
         std::string                      _fnDist;
         double                           _cutoff;
-        Selection                       *_refsel;
-        std::vector<Selection *>         _sel;
+        Selection                        _refsel;
+        SelectionList                    _sel;
         AnalysisData                     _data;
         AnalysisDataAverageModulePointer _avem;
 };
@@ -105,7 +105,7 @@ class AnalysisTemplate::ModuleData : public TrajectoryAnalysisModuleData
 
 AnalysisTemplate::AnalysisTemplate()
     : _options("template", "Template options"), _cutoff(0.0),
-      _refsel(NULL), _avem(new AnalysisDataAverageModule())
+      _avem(new AnalysisDataAverageModule())
 {
 }
 
@@ -180,7 +180,7 @@ AnalysisTemplate::startFrames(const AnalysisDataParallelOptions &opt,
                               const SelectionCollection &selections)
 {
     return TrajectoryAnalysisModuleDataPointer(
-            new ModuleData(this, opt, selections, _cutoff, _refsel->posCount()));
+            new ModuleData(this, opt, selections, _cutoff, _refsel.posCount()));
 }
 
 
@@ -190,18 +190,18 @@ AnalysisTemplate::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
 {
     AnalysisDataHandle  dh = pdata->dataHandle(_data);
     NeighborhoodSearch &nb = static_cast<ModuleData *>(pdata)->_nb;
-    Selection          *refsel = pdata->parallelSelection(_refsel);
+    const Selection    &refsel = pdata->parallelSelection(_refsel);
 
-    nb.init(pbc, refsel->positions());
+    nb.init(pbc, refsel.positions());
     dh.startFrame(frnr, fr.time);
     for (size_t g = 0; g < _sel.size(); ++g)
     {
-        Selection *sel = pdata->parallelSelection(_sel[g]);
-        int   nr = sel->posCount();
+        const Selection &sel = pdata->parallelSelection(_sel[g]);
+        int   nr = sel.posCount();
         real  frave = 0.0;
         for (int i = 0; i < nr; ++i)
         {
-            SelectionPosition p = sel->position(i);
+            SelectionPosition p = sel.position(i);
             frave += nb.minimumDistance(p.x());
         }
         frave /= nr;
@@ -224,7 +224,7 @@ AnalysisTemplate::writeOutput()
     for (size_t g = 0; g < _sel.size(); ++g)
     {
         fprintf(stderr, "Average mean distance for '%s': %.3f nm\n",
-                _sel[g]->name(), _avem->average(g));
+                _sel[g].name(), _avem->average(g));
     }
 }
 
index f61ab1afcf3a2cb37bec6de377b8117855e3016f..1e55df0f4df1fc6e2ac96ef81c6b4ee9637ae998 100644 (file)
@@ -557,8 +557,8 @@ set_evaluation_function(t_selelem *sel, sel_evalfunc eval)
  *      for, or NULL if the element is an internal element.
  */
 static void
-init_pos_keyword_defaults(t_selelem *root, const char *spost,
-                          const char *rpost, const gmx::Selection *sel)
+init_pos_keyword_defaults(t_selelem *root, const char *spost, const char *rpost,
+                          const gmx::internal::SelectionData *sel)
 {
     /* Selections use largest static group by default, while
      * reference positions use the whole residue/molecule. */
@@ -2581,11 +2581,11 @@ SelectionCompiler::compile(SelectionCollection *coll)
      */
     for (i = 0; i < sc->sel.size(); ++i)
     {
-        gmx::Selection *sel = sc->sel[i].get();
-        init_pos_keyword_defaults(sel->rootElement_,
+        gmx::internal::SelectionData &sel = *sc->sel[i];
+        init_pos_keyword_defaults(sel.rootElement(),
                                   coll->_impl->_spost.c_str(),
                                   coll->_impl->_rpost.c_str(),
-                                  sel);
+                                  &sel);
     }
 
     /* Remove any unused variables. */
index 28b365ee28cac18976f01bb51ba6f1c4b4d865d4..822d5218d12c7bd3b426a84fde0808c22480172d 100644 (file)
@@ -393,10 +393,10 @@ SelectionEvaluator::evaluate(SelectionCollection *coll,
         sel = sel->next;
     }
     /* Update selection information */
-    SelectionList::const_iterator isel;
+    SelectionDataList::const_iterator isel;
     for (isel = sc->sel.begin(); isel != sc->sel.end(); ++isel)
     {
-        Selection &sel = **isel;
+        internal::SelectionData &sel = **isel;
         sel.refreshMassesAndCharges();
         sel.updateCoveredFractionForFrame();
     }
@@ -411,10 +411,10 @@ SelectionEvaluator::evaluateFinal(SelectionCollection *coll, int nframes)
 {
     gmx_ana_selcollection_t *sc = &coll->_impl->_sc;
 
-    SelectionList::const_iterator isel;
+    SelectionDataList::const_iterator isel;
     for (isel = sc->sel.begin(); isel != sc->sel.end(); ++isel)
     {
-        Selection &sel = **isel;
+        internal::SelectionData &sel = **isel;
         sel.restoreOriginalPositions();
         sel.computeAverageCoveredFraction(nframes);
     }
index 7a3de60ba8af8dbf76edb493f2582b40aefc35a9..bcfdecc9c61691bcf58de9141af3b24339027bc3 100644 (file)
@@ -1285,9 +1285,10 @@ _gmx_sel_append_selection(t_selelem *sel, t_selelem *last, yyscan_t scanner)
         /* Add the new selection to the collection if it is not a variable. */
         if (sel->child->type != SEL_SUBEXPR)
         {
-            gmx::SelectionPointer selPtr(
-                    new gmx::Selection(sel, _gmx_sel_lexer_pselstr(scanner)));
-            sc->sel.push_back(move(selPtr));
+            gmx::SelectionDataPointer selPtr(
+                    new gmx::internal::SelectionData(
+                        sel, _gmx_sel_lexer_pselstr(scanner)));
+            sc->sel.push_back(gmx::move(selPtr));
         }
     }
     /* Clear the selection string now that we've saved it */
index e21f6053c0961cb25b1388d7df0815b5acf49094..2f17cc7e9c46afa01a0669ee95d1e4c1fb527949 100644 (file)
 namespace gmx
 {
 
-Selection::Selection(t_selelem *elem, const char *selstr)
+namespace internal
+{
+
+SelectionData::SelectionData(t_selelem *elem, const char *selstr)
     : name_(elem->name), selectionText_(selstr),
       rootElement_(elem), coveredFractionType_(CFRAC_NONE),
       coveredFraction_(1.0), averageCoveredFraction_(1.0),
@@ -102,25 +105,14 @@ Selection::Selection(t_selelem *elem, const char *selstr)
 }
 
 
-Selection::~Selection()
+SelectionData::~SelectionData()
 {
     gmx_ana_pos_deinit(&rawPositions_);
 }
 
 
-void
-Selection::printInfo(FILE *fp) const
-{
-    fprintf(fp, "\"%s\" (%d position%s, %d atom%s%s)", name_.c_str(),
-            posCount(),  posCount()  == 1 ? "" : "s",
-            atomCount(), atomCount() == 1 ? "" : "s",
-            isDynamic() ? ", dynamic" : "");
-    fprintf(fp, "\n");
-}
-
-
 bool
-Selection::initCoveredFraction(e_coverfrac_t type)
+SelectionData::initCoveredFraction(e_coverfrac_t type)
 {
     coveredFractionType_ = type;
     if (type == CFRAC_NONE || rootElement_ == NULL)
@@ -143,67 +135,7 @@ Selection::initCoveredFraction(e_coverfrac_t type)
 
 
 void
-Selection::printDebugInfo(FILE *fp, int nmaxind) const
-{
-    const gmx_ana_pos_t &p = rawPositions_;
-
-    fprintf(fp, "  ");
-    printInfo(fp);
-    fprintf(fp, "    ");
-    gmx_ana_index_dump(fp, p.g, -1, nmaxind);
-
-    fprintf(fp, "    Block (size=%d):", p.m.mapb.nr);
-    if (!p.m.mapb.index)
-    {
-        fprintf(fp, " (null)");
-    }
-    else
-    {
-        int n = p.m.mapb.nr;
-        if (nmaxind >= 0 && n > nmaxind)
-            n = nmaxind;
-        for (int i = 0; i <= n; ++i)
-            fprintf(fp, " %d", p.m.mapb.index[i]);
-        if (n < p.m.mapb.nr)
-            fprintf(fp, " ...");
-    }
-    fprintf(fp, "\n");
-
-    int n = posCount();
-    if (nmaxind >= 0 && n > nmaxind)
-        n = nmaxind;
-    fprintf(fp, "    RefId:");
-    if (!p.m.refid)
-    {
-        fprintf(fp, " (null)");
-    }
-    else
-    {
-        for (int i = 0; i < n; ++i)
-            fprintf(fp, " %d", p.m.refid[i]);
-        if (n < posCount())
-            fprintf(fp, " ...");
-    }
-    fprintf(fp, "\n");
-
-    fprintf(fp, "    MapId:");
-    if (!p.m.mapid)
-    {
-        fprintf(fp, " (null)");
-    }
-    else
-    {
-        for (int i = 0; i < n; ++i)
-            fprintf(fp, " %d", p.m.mapid[i]);
-        if (n < posCount())
-            fprintf(fp, " ...");
-    }
-    fprintf(fp, "\n");
-}
-
-
-void
-Selection::initializeMassesAndCharges(const t_topology *top)
+SelectionData::initializeMassesAndCharges(const t_topology *top)
 {
     posInfo_.reserve(posCount());
     for (int b = 0; b < posCount(); ++b)
@@ -232,7 +164,7 @@ Selection::initializeMassesAndCharges(const t_topology *top)
 
 
 void
-Selection::refreshMassesAndCharges()
+SelectionData::refreshMassesAndCharges()
 {
     if (!originalPosInfo_.empty())
     {
@@ -247,11 +179,11 @@ Selection::refreshMassesAndCharges()
 
 
 void
-Selection::updateCoveredFractionForFrame()
+SelectionData::updateCoveredFractionForFrame()
 {
     if (isCoveredFractionDynamic())
     {
-        real cfrac = _gmx_selelem_estimate_coverfrac(rootElement_);
+        real cfrac = _gmx_selelem_estimate_coverfrac(rootElement());
         coveredFraction_ = cfrac;
         averageCoveredFraction_ += cfrac;
     }
@@ -259,7 +191,7 @@ Selection::updateCoveredFractionForFrame()
 
 
 void
-Selection::computeAverageCoveredFraction(int nframes)
+SelectionData::computeAverageCoveredFraction(int nframes)
 {
     if (isCoveredFractionDynamic() && nframes > 0)
     {
@@ -269,7 +201,7 @@ Selection::computeAverageCoveredFraction(int nframes)
 
 
 void
-Selection::restoreOriginalPositions()
+SelectionData::restoreOriginalPositions()
 {
     if (isDynamic())
     {
@@ -282,4 +214,77 @@ Selection::restoreOriginalPositions()
     }
 }
 
+} // namespace internal
+
+
+void
+Selection::printInfo(FILE *fp) const
+{
+    fprintf(fp, "\"%s\" (%d position%s, %d atom%s%s)", name(),
+            posCount(),  posCount()  == 1 ? "" : "s",
+            atomCount(), atomCount() == 1 ? "" : "s",
+            isDynamic() ? ", dynamic" : "");
+    fprintf(fp, "\n");
+}
+
+
+void
+Selection::printDebugInfo(FILE *fp, int nmaxind) const
+{
+    const gmx_ana_pos_t &p = sel_->rawPositions_;
+
+    fprintf(fp, "  ");
+    printInfo(fp);
+    fprintf(fp, "    ");
+    gmx_ana_index_dump(fp, p.g, -1, nmaxind);
+
+    fprintf(fp, "    Block (size=%d):", p.m.mapb.nr);
+    if (!p.m.mapb.index)
+    {
+        fprintf(fp, " (null)");
+    }
+    else
+    {
+        int n = p.m.mapb.nr;
+        if (nmaxind >= 0 && n > nmaxind)
+            n = nmaxind;
+        for (int i = 0; i <= n; ++i)
+            fprintf(fp, " %d", p.m.mapb.index[i]);
+        if (n < p.m.mapb.nr)
+            fprintf(fp, " ...");
+    }
+    fprintf(fp, "\n");
+
+    int n = posCount();
+    if (nmaxind >= 0 && n > nmaxind)
+        n = nmaxind;
+    fprintf(fp, "    RefId:");
+    if (!p.m.refid)
+    {
+        fprintf(fp, " (null)");
+    }
+    else
+    {
+        for (int i = 0; i < n; ++i)
+            fprintf(fp, " %d", p.m.refid[i]);
+        if (n < posCount())
+            fprintf(fp, " ...");
+    }
+    fprintf(fp, "\n");
+
+    fprintf(fp, "    MapId:");
+    if (!p.m.mapid)
+    {
+        fprintf(fp, " (null)");
+    }
+    else
+    {
+        for (int i = 0; i < n; ++i)
+            fprintf(fp, " %d", p.m.mapid[i]);
+        if (n < posCount())
+            fprintf(fp, " ...");
+    }
+    fprintf(fp, "\n");
+}
+
 } // namespace gmx
index 45a5ae86a13867e21b3614336021f9e507376a4c..d87b928b93c6c13167a2434e293a5a733514d699 100644 (file)
@@ -57,19 +57,27 @@ struct t_selelem;
 namespace gmx
 {
 
-class SelectionEvaluator;
-class SelectionCollection;
-class SelectionCompiler;
+class SelectionOptionStorage;
 
+class Selection;
 class SelectionPosition;
 
-/*! \brief
- * Provides access to a single selection.
+//! Container of selections used in public selection interfaces.
+typedef std::vector<Selection> SelectionList;
+
+namespace internal
+{
+
+/*! \internal \brief
+ * Internal data for a single selection.
+ *
+ * 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.
  *
- * \inpublicapi
  * \ingroup module_selection
  */
-class Selection
+class SelectionData
 {
     public:
         /*! \brief
@@ -78,104 +86,28 @@ class Selection
          * \param[in] elem   Root of the evaluation tree for this selection.
          * \param[in] selstr String that was parsed to produce this selection.
          */
-        Selection(t_selelem *elem, const char *selstr);
-        ~Selection();
+        SelectionData(t_selelem *elem, const char *selstr);
+        ~SelectionData();
 
-        //! Returns the name of the selection.
-        const char *name() const  { return name_.c_str(); }
         //! Returns the string that was parsed to produce this selection.
         const char *selectionText() const { return selectionText_.c_str(); }
         //! Returns true if the size of the selection (posCount()) is dynamic.
         bool isDynamic() const { return bDynamic_; }
-        //! Returns the type of positions in the selection.
-        e_index_t type() const { return rawPositions_.m.type; }
-
         //! Number of positions in the selection.
         int posCount() const { return rawPositions_.nr; }
-        //! Total number of atoms in the selection.
-        int atomCount() const
-        {
-            return rawPositions_.g != NULL ? rawPositions_.g->isize : 0;
-        }
-        //! Returns atom indices of all atoms in the selection.
-        ConstArrayRef<int> atomIndices() const
-        {
-            if (rawPositions_.g == NULL)
-            {
-                return ConstArrayRef<int>();
-            }
-            return ConstArrayRef<int>(rawPositions_.g->isize,
-                                      rawPositions_.g->index);
-        }
-        //! Access a single position.
-        SelectionPosition position(int i) const;
-        /*! \brief
-         * Sets the ID for the \p i'th position for use with
-         * SelectionPosition::mappedId().
-         *
-         * This method is not part of SelectionPosition because that interface
-         * only provides access to const data by design.
-         */
-        void setOriginalId(int i, int id) { rawPositions_.m.orgid[i] = id; }
+        //! Returns the root of the evaluation tree for this selection.
+        t_selelem *rootElement() { return rootElement_; }
 
         //! Returns whether the covered fraction can change between frames.
         bool isCoveredFractionDynamic() const { return bDynamicCoveredFraction_; }
-        //! Returns the covered fraction for the current frame.
-        real coveredFraction() const { return coveredFraction_; }
-
-        //! Deprecated method for direct access to position data.
-        const gmx_ana_pos_t *positions() const { return &rawPositions_; }
-        //! Deprecated method for direct access to atom index data.
-        gmx_ana_index_t *indexGroup() const { return rawPositions_.g; }
 
-        // TODO: Remove direct access to the flags from the public interface.
         //! Returns true if the given flag is set.
         bool hasFlag(SelectionFlag flag) const { return flags_.test(flag); }
         //! Sets the flags for this selection.
         void setFlags(SelectionFlags flags) { flags_ = flags; }
-        /*! \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
-         *      selection.
-         */
-        bool initCoveredFraction(e_coverfrac_t type);
-
-        /*! \brief
-         * Prints out one-line description of the selection.
-         *
-         * \param[in] fp      Where to print the information.
-         */
-        void printInfo(FILE *fp) const;
-        /*! \brief
-         * Prints out extended information about the selection for debugging.
-         *
-         * \param[in] fp      Where to print the information.
-         * \param[in] nmaxind Maximum number of values to print in lists
-         *      (-1 = print all).
-         */
-        void printDebugInfo(FILE *fp, int nmaxind) const;
-
-    private:
-        /*! \brief
-         * Additional information about positions.
-         *
-         * This structure contains information about positions in the
-         * selection that is not stored in ::gmx_ana_pos_t.
-         */
-        struct PositionInfo
-        {
-            //! Construct position information with unit mass and no charge.
-            PositionInfo() : mass(1.0), charge(0.0) {}
-            //! Construct position information with the given information.
-            PositionInfo(real mass, real charge) : mass(mass), charge(charge) {}
 
-            //! Total mass of atoms that make up the position.
-            real                mass;
-            //! Total charge of atoms that make up the position.
-            real                charge;
-        };
+        //! \copydoc Selection::initCoveredFraction()
+        bool initCoveredFraction(e_coverfrac_t type);
 
         /*! \brief
          * Computes total masses and charges for all selection positions.
@@ -221,6 +153,26 @@ class Selection
          */
         void restoreOriginalPositions();
 
+    private:
+        /*! \brief
+         * Additional information about positions.
+         *
+         * This structure contains information about positions in the
+         * selection that is not stored in ::gmx_ana_pos_t.
+         */
+        struct PositionInfo
+        {
+            //! Construct position information with unit mass and no charge.
+            PositionInfo() : mass(1.0), charge(0.0) {}
+            //! Construct position information with the given information.
+            PositionInfo(real mass, real charge) : mass(mass), charge(charge) {}
+
+            //! Total mass of atoms that make up the position.
+            real                mass;
+            //! Total charge of atoms that make up the position.
+            real                charge;
+        };
+
         //! Name of the selection.
         std::string             name_;
         //! The actual selection string.
@@ -246,22 +198,136 @@ class Selection
         bool                    bDynamicCoveredFraction_;
 
         /*! \brief
-         * Needed for the compiler to access initializeMassesAndCharges().
+         * Needed for to wrap access to information.
+         */
+        friend class gmx::Selection;
+        /*! \brief
+         * Needed for proper access to position information.
+         */
+        friend class gmx::SelectionPosition;
+
+        GMX_DISALLOW_COPY_AND_ASSIGN(SelectionData);
+};
+
+} // namespace internal
+
+/*! \brief
+ * Provides access to a single selection.
+ *
+ * \inpublicapi
+ * \ingroup module_selection
+ */
+class Selection
+{
+    public:
+        /*! \brief
+         * Creates a selection wrapper that has no associated selection.
+         *
+         * Any attempt to call methods in the object before a selection is
+         * assigned results in undefined behavior.
+         */
+        Selection() : sel_(NULL) {}
+        /*! \brief
+         * Creates a new selection object.
+         *
+         * \param  sel  Selection data to wrap.
+         */
+        explicit Selection(internal::SelectionData *sel) : sel_(sel) {}
+
+        //! Returns the name of the selection.
+        const char *name() const  { return data().name_.c_str(); }
+        //! Returns the string that was parsed to produce this selection.
+        const char *selectionText() const { return data().selectionText(); }
+        //! Returns true if the size of the selection (posCount()) is dynamic.
+        bool isDynamic() const { return data().isDynamic(); }
+        //! 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
+        {
+            return data().rawPositions_.g != NULL ? data().rawPositions_.g->isize : 0;
+        }
+        //! Returns atom indices of all atoms in the selection.
+        ConstArrayRef<int> atomIndices() const
+        {
+            if (data().rawPositions_.g == NULL)
+            {
+                return ConstArrayRef<int>();
+            }
+            return ConstArrayRef<int>(data().rawPositions_.g->isize,
+                                      data().rawPositions_.g->index);
+        }
+        //! Access a single position.
+        SelectionPosition position(int i) const;
+        /*! \brief
+         * Sets the ID for the \p i'th position for use with
+         * SelectionPosition::mappedId().
+         *
+         * This method is not part of SelectionPosition because that interface
+         * only provides access to const data by design.
+         */
+        void setOriginalId(int i, int id) { data().rawPositions_.m.orgid[i] = id; }
+
+        //! 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_; }
+        //! Deprecated method for direct access to atom index data.
+        gmx_ana_index_t *indexGroup() const { return data().rawPositions_.g; }
+
+        /*! \brief
+         * Initializes information about covered fractions.
          *
-         * Currently the compiler also used rootElement_ directly for
-         * simplicity, but does not modify it.
+         * \param[in] type Type of covered fraction required.
+         * \returns   True if the covered fraction can be calculated for the
+         *      selection.
          */
-        friend class SelectionCompiler;
+        bool initCoveredFraction(e_coverfrac_t type)
+        {
+            return data().initCoveredFraction(type);
+        }
+
         /*! \brief
-         * Needed for the evaluator to access the private methods.
+         * Prints out one-line description of the selection.
+         *
+         * \param[in] fp      Where to print the information.
          */
-        friend class SelectionEvaluator;
+        void printInfo(FILE *fp) const;
         /*! \brief
-         * Needed for proper access to position information.
+         * Prints out extended information about the selection for debugging.
+         *
+         * \param[in] fp      Where to print the information.
+         * \param[in] nmaxind Maximum number of values to print in lists
+         *      (-1 = print all).
          */
-        friend class SelectionPosition;
+        void printDebugInfo(FILE *fp, int nmaxind) const;
 
-        GMX_DISALLOW_COPY_AND_ASSIGN(Selection);
+    private:
+        internal::SelectionData &data()
+        {
+            GMX_ASSERT(sel_ != NULL,
+                       "Attempted to access uninitialized selection");
+            return *sel_;
+        }
+        const internal::SelectionData &data() const
+        {
+            GMX_ASSERT(sel_ != NULL,
+                       "Attempted to access uninitialized selection");
+            return *sel_;
+        }
+
+        internal::SelectionData *sel_;
+
+        /*! \brief
+         * Needed to access the data to adjust flags.
+         */
+        friend class SelectionOptionStorage;
 };
 
 /*! \brief
@@ -286,10 +352,10 @@ class SelectionPosition
          *
          * Does not throw.  Asserts if \p index is out of range.
          */
-        SelectionPosition(const Selection *sel, int index)
-            : sel_(sel), i_(index)
+        SelectionPosition(const internal::SelectionData &sel, int index)
+            : sel_(&sel), i_(index)
         {
-            GMX_ASSERT(index >= 0 && index < sel->posCount(),
+            GMX_ASSERT(index >= 0 && index < sel.posCount(),
                        "Invalid selection position index");
         }
 
@@ -406,15 +472,15 @@ class SelectionPosition
         }
 
     private:
-        const Selection        *sel_;
-        int                     i_;
+        const internal::SelectionData  *sel_;
+        int                             i_;
 };
 
 
 inline SelectionPosition
 Selection::position(int i) const
 {
-    return SelectionPosition(this, i);
+    return SelectionPosition(data(), i);
 }
 
 } // namespace gmx
index 4121f1deae1cf027918b1e7714adc3c9ab73cfc5..d70c4dc978e9f58d4470bb2f337953489108d883 100644 (file)
 #include "../utility/flags.h"
 #include "../utility/uniqueptr.h"
 #include "indexutil.h"
+#include "selection.h" // For gmx::SelectionList
 #include "selectioncollection.h"
 
 namespace gmx
 {
-class Selection;
-
-//! Smart pointer for managing a selection.
-typedef gmx_unique_ptr<Selection>::type SelectionPointer;
+//! 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.
-typedef std::vector<SelectionPointer> SelectionList;
+typedef std::vector<SelectionDataPointer> SelectionDataList;
 }
 
 /*! \internal \brief
@@ -71,8 +70,14 @@ struct gmx_ana_selcollection_t
 {
     /** Root of the selection element tree. */
     struct t_selelem           *root;
-    /** Array of compiled selections. */
-    gmx::SelectionList             sel;
+    /*! \brief
+     * Array of compiled selections.
+     *
+     * Has the responsibility of managing the memory for the contained objects,
+     * but note that gmx::Selection instances also hold pointers to the
+     * objects.
+     */
+    gmx::SelectionDataList         sel;
     /** Number of variables defined. */
     int                            nvars;
     /** Selection strings for variables. */
@@ -172,7 +177,7 @@ class SelectionCollection::Impl
          * Does not clear \p output.
          */
         void runParser(void *scanner, int maxnr,
-                       std::vector<Selection *> *output);
+                       SelectionList *output);
         /*! \brief
          * Adds a selection request for delayed user input.
          *
index a73750ff76c37a782625258096c1b5a96319607f..ed720559bff14ce495aa6e7f69cd2c4e2ae0fc1d 100644 (file)
@@ -149,7 +149,7 @@ SelectionCollection::Impl::clearSymbolTable()
 
 void
 SelectionCollection::Impl::runParser(yyscan_t scanner, int maxnr,
-                                     std::vector<Selection *> *output)
+                                     SelectionList *output)
 {
     gmx_ana_selcollection_t *sc = &_sc;
     GMX_ASSERT(sc == _gmx_sel_lexer_selcollection(scanner),
@@ -170,10 +170,10 @@ SelectionCollection::Impl::runParser(yyscan_t scanner, int maxnr,
 
     if (bOk)
     {
-        SelectionList::const_iterator i;
+        SelectionDataList::const_iterator i;
         for (i = _sc.sel.begin() + oldCount; i != _sc.sel.end(); ++i)
         {
-            output->push_back(i->get());
+            output->push_back(Selection(i->get()));
         }
     }
 
@@ -446,7 +446,7 @@ SelectionCollection::parseRequestedFromStdin(bool bInteractive)
             std::fprintf(stderr, "(one selection per line, 'help' for help%s)\n",
                          request.count() < 0 ? ", Ctrl-D to end" : "");
         }
-        std::vector<Selection *> selections;
+        SelectionList selections;
         parseFromStdin(request.count(), bInteractive, &selections);
         request.storage->addSelections(selections, true);
     }
@@ -458,11 +458,11 @@ SelectionCollection::parseRequestedFromString(const std::string &str)
 {
     Impl::RequestsClearer clearRequestsOnExit(&_impl->_requests);
 
-    std::vector<Selection *> selections;
+    SelectionList selections;
     parseFromString(str, &selections);
 
-    std::vector<Selection *>::const_iterator first = selections.begin();
-    std::vector<Selection *>::const_iterator last = first;
+    SelectionList::const_iterator first = selections.begin();
+    SelectionList::const_iterator last = first;
     Impl::RequestList::const_iterator i;
     for (i = _impl->_requests.begin(); i != _impl->_requests.end(); ++i)
     {
@@ -483,7 +483,7 @@ SelectionCollection::parseRequestedFromString(const std::string &str)
             }
             last = selections.end();
         }
-        std::vector<Selection *> curr(first, last);
+        SelectionList curr(first, last);
         request.storage->addSelections(curr, true);
         first = last;
     }
@@ -496,7 +496,7 @@ SelectionCollection::parseRequestedFromString(const std::string &str)
 
 void
 SelectionCollection::parseFromStdin(int nr, bool bInteractive,
-                                    std::vector<Selection *> *output)
+                                    SelectionList *output)
 {
     yyscan_t scanner;
 
@@ -511,7 +511,7 @@ SelectionCollection::parseFromStdin(int nr, bool bInteractive,
 
 void
 SelectionCollection::parseFromFile(const std::string &filename,
-                                   std::vector<Selection *> *output)
+                                   SelectionList *output)
 {
     yyscan_t scanner;
     FILE *fp;
@@ -537,7 +537,7 @@ SelectionCollection::parseFromFile(const std::string &filename,
 
 void
 SelectionCollection::parseFromString(const std::string &str,
-                                     std::vector<Selection *> *output)
+                                     SelectionList *output)
 {
     yyscan_t scanner;
 
index 4ff241499ca9fff03304ecb91bfe020e8ded2914..e873af9237e8aebd5758532d1d50ee03f9808ddb 100644 (file)
@@ -45,6 +45,7 @@
 #include "../legacyheaders/typedefs.h"
 
 #include "../utility/common.h"
+#include "selection.h" // For gmx::SelectionList
 
 struct gmx_ana_indexgrps_t;
 struct gmx_ana_poscalc_coll_t;
@@ -53,7 +54,6 @@ namespace gmx
 {
 
 class Options;
-class Selection;
 class SelectionCompiler;
 class SelectionEvaluator;
 class SelectionOptionStorage;
@@ -215,7 +215,7 @@ class SelectionCollection
          * compile() has been called.
          */
         void parseFromStdin(int count, bool bInteractive,
-                            std::vector<Selection *> *output);
+                            SelectionList *output);
         /*! \brief
          * Parses selection(s) from a file.
          *
@@ -233,7 +233,7 @@ class SelectionCollection
          * compile() has been called.
          */
         void parseFromFile(const std::string &filename,
-                           std::vector<Selection *> *output);
+                           SelectionList *output);
         /*! \brief
          * Parses selection(s) from a string.
          *
@@ -251,7 +251,7 @@ class SelectionCollection
          * compile() has been called.
          */
         void parseFromString(const std::string &str,
-                             std::vector<Selection *> *output);
+                             SelectionList *output);
         /*! \brief
          * Prepares the selections for evaluation and performs optimizations.
          *
index 9dc9e786ea5cf1336ba2ab626fcd8d44e5a318ef..0521cb6a48eb1cc59ff34594d041e443adada028 100644 (file)
@@ -72,13 +72,12 @@ SelectionOptionStorage::SelectionOptionStorage(const SelectionOption &settings)
 
 std::string SelectionOptionStorage::formatValue(int i) const
 {
-    Selection *sel = values().at(i);
-    return (sel != NULL ? sel->selectionText() : "");
+    return values()[i].selectionText();
 }
 
 
 void SelectionOptionStorage::addSelections(
-        const std::vector<Selection *> &selections,
+        const SelectionList &selections,
         bool bFullValue)
 {
     if (bFullValue && selections.size() < static_cast<size_t>(minValueCount()))
@@ -89,16 +88,15 @@ void SelectionOptionStorage::addSelections(
     {
         clearSet();
     }
-    std::vector<Selection *>::const_iterator i;
+    SelectionList::const_iterator i;
     for (i = selections.begin(); i != selections.end(); ++i)
     {
         // TODO: Having this check in the parser would make interactive input
         // behave better.
-        if (_selectionFlags.test(efOnlyStatic) && (*i)->isDynamic())
+        if (_selectionFlags.test(efOnlyStatic) && i->isDynamic())
         {
             GMX_THROW(InvalidInputError("Dynamic selections not supported"));
         }
-        (*i)->setFlags(_selectionFlags);
         addValue(*i);
     }
     if (bFullValue)
@@ -112,7 +110,7 @@ void SelectionOptionStorage::convertValue(const std::string &value)
 {
     GMX_RELEASE_ASSERT(_sc != NULL, "Selection collection is not set");
 
-    std::vector<Selection *> selections;
+    SelectionList selections;
     // TODO: Implement reading from a file.
     _sc->parseFromString(value, &selections);
     addSelections(selections, false);
@@ -124,6 +122,11 @@ void SelectionOptionStorage::processSetValues(ValueList *values)
     {
         GMX_THROW(InvalidInputError("Too few (valid) values provided"));
     }
+    ValueList::iterator i;
+    for (i = values->begin(); i != values->end(); ++i)
+    {
+        i->data().setFlags(_selectionFlags);
+    }
 }
 
 void SelectionOptionStorage::processAll()
@@ -168,10 +171,10 @@ void SelectionOptionStorage::setAllowedValueCount(int count)
 void SelectionOptionStorage::setSelectionFlag(SelectionFlag flag, bool bSet)
 {
     _selectionFlags.set(flag, bSet);
-    ValueList::const_iterator i;
+    ValueList::iterator i;
     for (i = values().begin(); i != values().end(); ++i)
     {
-        if (_selectionFlags.test(efOnlyStatic) && (*i)->isDynamic())
+        if (_selectionFlags.test(efOnlyStatic) && i->isDynamic())
         {
             MessageStringCollector errors;
             errors.startContext("In option '" + name() + "'");
@@ -179,7 +182,7 @@ void SelectionOptionStorage::setSelectionFlag(SelectionFlag flag, bool bSet)
             errors.finishContext();
             GMX_THROW(InvalidInputError(errors.toString()));
         }
-        (*i)->setFlags(_selectionFlags);
+        i->data().setFlags(_selectionFlags);
     }
 }
 
index d84ea4e41fe1d1fc37b263ccbf54fdc2de1e4755..a47b3517fe6f57dde9d5b40b75f27062b9434f04 100644 (file)
 #define GMX_SELECTION_SELECTIONOPTION_H
 
 #include "../options/abstractoption.h"
+#include "selection.h"
 #include "selectionenums.h"
 
 namespace gmx
 {
 
-class Selection;
 class SelectionOptionInfo;
 class SelectionOptionStorage;
 
@@ -55,7 +55,7 @@ class SelectionOptionStorage;
  * \inpublicapi
  * \ingroup module_selection
  */
-class SelectionOption : public OptionTemplate<Selection *, SelectionOption>
+class SelectionOption : public OptionTemplate<Selection, SelectionOption>
 {
     public:
         //! Initializes an option with the given name.
index 7b9729a356a965111981a5e9ef20efa3bab14cb4..b3a461cdff2cfae85e4f5a38ec4b71580fa371f8 100644 (file)
@@ -73,7 +73,7 @@ class SelectionOptionStorage;
  *
  * Example use:
  * \code
-std::vector<Selection *> sel;
+SelectionList sel;
 Options options("example", "Example options");
 SelectionOptionInfo *info;
 options.addOption(SelectionOption("sel").storeVector(&sel)
index eeb1b0755f5f543fdca654af070f5584778a8da7..582ed51d058203e13ff1aab7fd101871e75cc1e7 100644 (file)
 #define GMX_SELECTION_SELECTIONOPTIONSTORAGE_H
 
 #include "../options/optionstoragetemplate.h"
+#include "selection.h"
 #include "selectionenums.h"
 #include "selectionoptioninfo.h"
 
 namespace gmx
 {
 
-class Selection;
 class SelectionCollection;
 class SelectionOption;
 
@@ -54,7 +54,7 @@ class SelectionOption;
  *
  * \ingroup module_selection
  */
-class SelectionOptionStorage : public OptionStorageTemplate<Selection *>
+class SelectionOptionStorage : public OptionStorageTemplate<Selection>
 {
     public:
         /*! \brief
@@ -87,7 +87,7 @@ class SelectionOptionStorage : public OptionStorageTemplate<Selection *>
          * \p bFullValue set to true), as well as internally by the storage
          * class (called with \p bFullValue set to false).
          */
-        void addSelections(const std::vector<Selection *> &selections,
+        void addSelections(const SelectionList &selections,
                            bool bFullValue);
 
         // Required to access the number of values in selection requests.
index f0f162ead4e388ef2ae4f07d1344b9d82e961649..54225a928af6c62bb75a5946bc026b58024a7e1c 100644 (file)
@@ -39,8 +39,6 @@
 #include <config.h>
 #endif
 
-#include <vector>
-
 #include <gtest/gtest.h>
 
 #include "smalloc.h"
@@ -78,7 +76,7 @@ class SelectionCollectionTest : public ::testing::Test
         void loadTopology(const char *filename);
 
         gmx::SelectionCollection _sc;
-        std::vector<gmx::Selection *> _sel;
+        gmx::SelectionList       _sel;
         t_topology              *_top;
         t_trxframe              *_frame;
 };
@@ -160,7 +158,7 @@ class SelectionCollectionDataTest : public SelectionCollectionTest
 
     private:
         static void checkSelection(gmx::test::TestReferenceChecker *checker,
-                                   const gmx::Selection *sel, TestFlags flags);
+                                   const gmx::Selection &sel, TestFlags flags);
 
         void runParser(const char *const *selections);
         void runCompiler();
@@ -179,23 +177,23 @@ class SelectionCollectionDataTest : public SelectionCollectionTest
 void
 SelectionCollectionDataTest::checkSelection(
         gmx::test::TestReferenceChecker *checker,
-        const gmx::Selection *sel, TestFlags flags)
+        const gmx::Selection &sel, TestFlags flags)
 {
     using gmx::test::TestReferenceChecker;
 
     {
-        gmx::ConstArrayRef<int> atoms = sel->atomIndices();
+        gmx::ConstArrayRef<int> atoms = sel.atomIndices();
         checker->checkSequence(atoms.begin(), atoms.end(), "Atoms");
     }
     if (flags.test(efTestPositionAtoms)
         || flags.test(efTestPositionCoordinates))
     {
         TestReferenceChecker compound(
-                checker->checkSequenceCompound("Positions", sel->posCount()));
-        for (int i = 0; i < sel->posCount(); ++i)
+                checker->checkSequenceCompound("Positions", sel.posCount()));
+        for (int i = 0; i < sel.posCount(); ++i)
         {
             TestReferenceChecker poscompound(compound.checkCompound("Position", NULL));
-            gmx::SelectionPosition p = sel->position(i);
+            const gmx::SelectionPosition &p = sel.position(i);
             if (flags.test(efTestPositionAtoms))
             {
                 gmx::ConstArrayRef<int> atoms = p.atomIndices();
@@ -237,9 +235,9 @@ SelectionCollectionDataTest::runParser(const char *const *selections)
             TestReferenceChecker selcompound(
                     compound.checkCompound("ParsedSelection", id.c_str()));
             selcompound.checkString(selections[i], "Input");
-            selcompound.checkString(_sel[_count]->name(), "Name");
-            selcompound.checkString(_sel[_count]->selectionText(), "Text");
-            selcompound.checkBoolean(_sel[_count]->isDynamic(), "Dynamic");
+            selcompound.checkString(_sel[_count].name(), "Name");
+            selcompound.checkString(_sel[_count].selectionText(), "Text");
+            selcompound.checkBoolean(_sel[_count].isDynamic(), "Dynamic");
             ++_count;
         }
     }
@@ -265,7 +263,7 @@ SelectionCollectionDataTest::checkCompiled()
     for (size_t i = 0; i < _count; ++i)
     {
         SCOPED_TRACE(std::string("Checking selection \"") +
-                     _sel[i]->selectionText() + "\"");
+                     _sel[i].selectionText() + "\"");
         std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
         TestReferenceChecker selcompound(
                 compound.checkCompound("Selection", id.c_str()));
@@ -287,7 +285,7 @@ SelectionCollectionDataTest::runEvaluate()
     for (size_t i = 0; i < _count; ++i)
     {
         SCOPED_TRACE(std::string("Checking selection \"") +
-                     _sel[i]->selectionText() + "\"");
+                     _sel[i].selectionText() + "\"");
         std::string id = gmx::formatString("Selection%d", static_cast<int>(i + 1));
         TestReferenceChecker selcompound(
                 compound.checkCompound("Selection", id.c_str()));
index 22e5f7aeb7c6cd0d793b958d7c39236cac2b49e9..86cd6d5224af044467de12efb45301c6fb4ed9f7 100644 (file)
@@ -35,8 +35,6 @@
  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
  * \ingroup module_selection
  */
-#include <vector>
-
 #include <gtest/gtest.h>
 
 #include "gromacs/fatalerror/exceptions.h"
@@ -76,7 +74,7 @@ void SelectionOptionTest::setCollection()
 
 TEST_F(SelectionOptionTest, ParsesSimpleSelection)
 {
-    gmx::Selection *sel = NULL;
+    gmx::Selection sel;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(SelectionOption("sel").store(&sel)));
     setCollection();
@@ -89,14 +87,13 @@ TEST_F(SelectionOptionTest, ParsesSimpleSelection)
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(_options.finish());
 
-    ASSERT_TRUE(sel != NULL);
-    ASSERT_FALSE(sel->isDynamic());
+    ASSERT_FALSE(sel.isDynamic());
 }
 
 
 TEST_F(SelectionOptionTest, HandlesDynamicSelectionWhenStaticRequired)
 {
-    gmx::Selection *sel = NULL;
+    gmx::Selection sel;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").store(&sel).onlyStatic()));
@@ -114,7 +111,7 @@ TEST_F(SelectionOptionTest, HandlesDynamicSelectionWhenStaticRequired)
 
 TEST_F(SelectionOptionTest, HandlesTooManySelections)
 {
-    gmx::Selection *sel = NULL;
+    gmx::Selection sel;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(SelectionOption("sel").store(&sel)));
     setCollection();
@@ -127,13 +124,13 @@ TEST_F(SelectionOptionTest, HandlesTooManySelections)
     EXPECT_NO_THROW(assigner.finishOption());
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(_options.finish());
-    ASSERT_TRUE(sel != NULL);
+    ASSERT_STREQ("resname RA RB", sel.selectionText());
 }
 
 
 TEST_F(SelectionOptionTest, HandlesTooFewSelections)
 {
-    gmx::Selection *sel[2] = {NULL, NULL};
+    gmx::Selection sel[2];
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").store(sel).valueCount(2)));
@@ -151,7 +148,7 @@ TEST_F(SelectionOptionTest, HandlesTooFewSelections)
 
 TEST_F(SelectionOptionTest, HandlesAdjuster)
 {
-    std::vector<gmx::Selection *> sel;
+    gmx::SelectionList sel;
     gmx::SelectionOptionInfo *info;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
@@ -173,7 +170,7 @@ TEST_F(SelectionOptionTest, HandlesAdjuster)
 
 TEST_F(SelectionOptionTest, HandlesDynamicWhenStaticRequiredWithAdjuster)
 {
-    gmx::Selection *sel;
+    gmx::Selection sel;
     gmx::SelectionOptionInfo *info;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
@@ -194,7 +191,7 @@ TEST_F(SelectionOptionTest, HandlesDynamicWhenStaticRequiredWithAdjuster)
 
 TEST_F(SelectionOptionTest, HandlesTooManySelectionsWithAdjuster)
 {
-    std::vector<gmx::Selection *> sel;
+    gmx::SelectionList sel;
     gmx::SelectionOptionInfo *info;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
@@ -216,7 +213,7 @@ TEST_F(SelectionOptionTest, HandlesTooManySelectionsWithAdjuster)
 
 TEST_F(SelectionOptionTest, HandlesTooFewSelectionsWithAdjuster)
 {
-    std::vector<gmx::Selection *> sel;
+    gmx::SelectionList sel;
     gmx::SelectionOptionInfo *info;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
@@ -237,7 +234,7 @@ TEST_F(SelectionOptionTest, HandlesTooFewSelectionsWithAdjuster)
 
 TEST_F(SelectionOptionTest, HandlesDelayedRequiredSelection)
 {
-    gmx::Selection *sel = NULL;
+    gmx::Selection sel;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").store(&sel).required()));
@@ -248,13 +245,13 @@ TEST_F(SelectionOptionTest, HandlesDelayedRequiredSelection)
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(_options.finish());
     EXPECT_NO_THROW(_sc.parseRequestedFromString("resname RA RB"));
-    ASSERT_TRUE(sel != NULL);
+    ASSERT_STREQ("resname RA RB", sel.selectionText());
 }
 
 
 TEST_F(SelectionOptionTest, HandlesTooFewDelayedRequiredSelections)
 {
-    gmx::Selection *sel[2] = {NULL, NULL};
+    gmx::Selection sel[2];
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
                         SelectionOption("sel").store(sel).required()
@@ -271,7 +268,7 @@ TEST_F(SelectionOptionTest, HandlesTooFewDelayedRequiredSelections)
 
 TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
 {
-    gmx::Selection *sel = NULL;
+    gmx::Selection sel;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(SelectionOption("sel").store(&sel)));
     setCollection();
@@ -283,13 +280,13 @@ TEST_F(SelectionOptionTest, HandlesDelayedOptionalSelection)
     EXPECT_NO_THROW(assigner.finish());
     EXPECT_NO_THROW(_options.finish());
     EXPECT_NO_THROW(_sc.parseRequestedFromString("resname RA RB"));
-    ASSERT_TRUE(sel != NULL);
+    ASSERT_STREQ("resname RA RB", sel.selectionText());
 }
 
 
 TEST_F(SelectionOptionTest, HandlesDelayedSelectionWithAdjuster)
 {
-    std::vector<gmx::Selection *> sel;
+    gmx::SelectionList sel;
     gmx::SelectionOptionInfo *info;
     using gmx::SelectionOption;
     ASSERT_NO_THROW(_options.addOption(
index 48d042813d199885baca2686840bcd085f7ef8d9..3b9fe8f26c42c9a966c02c1b0879a2d70314f994 100644 (file)
@@ -42,6 +42,7 @@
 #include "gromacs/analysisdata/analysisdata.h"
 #include "gromacs/fatalerror/exceptions.h"
 #include "gromacs/fatalerror/gmxassert.h"
+#include "gromacs/selection/selection.h"
 
 #include "analysismodule-impl.h"
 
@@ -117,19 +118,20 @@ TrajectoryAnalysisModuleData::dataHandle(const AnalysisData &data)
 }
 
 
-Selection *TrajectoryAnalysisModuleData::parallelSelection(Selection *selection)
+Selection TrajectoryAnalysisModuleData::parallelSelection(const Selection &selection)
 {
     // TODO: Implement properly.
     return selection;
 }
 
 
-std::vector<Selection *>
-TrajectoryAnalysisModuleData::parallelSelections(const std::vector<Selection *> &selections)
+SelectionList
+TrajectoryAnalysisModuleData::parallelSelections(const SelectionList &selections)
 {
-    std::vector<Selection *> newSelections;
+    // TODO: Consider an implementation that does not allocate memory every time.
+    SelectionList newSelections;
     newSelections.reserve(selections.size());
-    std::vector<Selection *>::const_iterator i = selections.begin();
+    SelectionList::const_iterator i = selections.begin();
     for ( ; i != selections.end(); ++i)
     {
         newSelections.push_back(parallelSelection(*i));
index 37ce5dfc5ecb90bd48b2aab93f4ab14a5bb76aac..32bc2c6452962be0caf610d9194daa9611437d7c 100644 (file)
@@ -45,6 +45,7 @@
 
 #include "../legacyheaders/typedefs.h"
 
+#include "../selection/selection.h" // For gmx::SelectionList
 #include "../utility/common.h"
 #include "../utility/uniqueptr.h"
 
@@ -56,7 +57,6 @@ class AnalysisData;
 class AnalysisDataHandle;
 class AnalysisDataParallelOptions;
 class Options;
-class Selection;
 class SelectionCollection;
 class TopologyInformation;
 class TrajectoryAnalysisModule;
@@ -99,11 +99,11 @@ class TrajectoryAnalysisModuleData
         /*! \brief
          * Returns a selection that corresponds to the given selection.
          */
-        Selection *parallelSelection(Selection *selection);
+        Selection parallelSelection(const Selection &selection);
         /*! \brief
          * Returns a set of selection that corresponds to the given selections.
          */
-        std::vector<Selection *> parallelSelections(const std::vector<Selection *> &selections);
+        SelectionList parallelSelections(const SelectionList &selections);
 
     protected:
         /*! \brief
index 79c01e3b93274c44dde1050ab152ce12e2f3965f..63b32f972b64ebe92846f3cc736e878876b4faf4 100644 (file)
@@ -241,14 +241,14 @@ Angle::initOptionsDone(TrajectoryAnalysisSettings *settings)
 
 
 void
-Angle::checkSelections(const std::vector<Selection *> &sel1,
-                       const std::vector<Selection *> &sel2) const
+Angle::checkSelections(const SelectionList &sel1,
+                       const SelectionList &sel2) const
 {
     if (_bMulti)
     {
         for (size_t g = 0; g < sel1.size(); ++g)
         {
-            if (sel1[g]->posCount() % _natoms1 != 0)
+            if (sel1[g].posCount() % _natoms1 != 0)
             {
                 GMX_THROW(InconsistentInputError(formatString(
                     "Number of positions in selection %d not divisible by %d",
@@ -258,8 +258,8 @@ Angle::checkSelections(const std::vector<Selection *> &sel1,
         return;
     }
 
-    int na1 = sel1[0]->posCount();
-    int na2 = (_natoms2 > 0) ? sel2[0]->posCount() : 0;
+    int na1 = sel1[0].posCount();
+    int na2 = (_natoms2 > 0) ? sel2[0].posCount() : 0;
 
     if (!_bSplit1 && _natoms1 > 1 && na1 % _natoms1 != 0)
     {
@@ -278,7 +278,7 @@ Angle::checkSelections(const std::vector<Selection *> &sel1,
     {
         for (int g = 1; g < _natoms1; ++g)
         {
-            if (sel1[g]->posCount() != na1)
+            if (sel1[g].posCount() != na1)
             {
                 GMX_THROW(InconsistentInputError(
                           "All selections in the first group should contain "
@@ -296,7 +296,7 @@ Angle::checkSelections(const std::vector<Selection *> &sel1,
         {
             for (int g = 1; g < _natoms2; ++g)
             {
-                if (sel2[g]->posCount() != na2)
+                if (sel2[g].posCount() != na2)
                 {
                     GMX_THROW(InconsistentInputError(
                               "All selections in the second group should contain "
@@ -314,7 +314,7 @@ Angle::checkSelections(const std::vector<Selection *> &sel1,
         GMX_THROW(InconsistentInputError(
                   "Number of vectors defined by the two groups are not the same"));
     }
-    if (_g2type[0] == 's' && sel2[0]->posCount() != 1)
+    if (_g2type[0] == 's' && sel2[0].posCount() != 1)
     {
         GMX_THROW(InconsistentInputError(
                   "The second group should contain a single position with -g2 sphnorm"));
@@ -334,7 +334,7 @@ Angle::initAnalysis(const TrajectoryAnalysisSettings &settings,
     }
     else if (_bAll)
     {
-        int na = _sel1[0]->posCount();
+        int na = _sel1[0].posCount();
         if (!_bSplit1)
         {
             na /= _natoms1;
@@ -348,7 +348,7 @@ Angle::initAnalysis(const TrajectoryAnalysisSettings &settings,
 
     if (_g2type == "t0")
     {
-        int na = _sel1[0]->posCount();
+        int na = _sel1[0].posCount();
         if (!_bSplit1)
         {
             na /= _natoms1;
@@ -369,21 +369,21 @@ Angle::initAnalysis(const TrajectoryAnalysisSettings &settings,
 
 
 static void
-copy_pos(const std::vector<Selection *> &sel, bool bSplit, int natoms,
+copy_pos(const SelectionList &sel, bool bSplit, int natoms,
          int firstg, int first, rvec x[])
 {
     if (bSplit)
     {
         for (int k = 0; k < natoms; ++k)
         {
-            copy_rvec(sel[firstg + k]->position(first).x(), x[k]);
+            copy_rvec(sel[firstg + k].position(first).x(), x[k]);
         }
     }
     else
     {
         for (int k = 0; k < natoms; ++k)
         {
-            copy_rvec(sel[firstg]->position(first + k).x(), x[k]);
+            copy_rvec(sel[firstg].position(first + k).x(), x[k]);
         }
     }
 }
@@ -435,8 +435,8 @@ Angle::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
                     TrajectoryAnalysisModuleData *pdata)
 {
     AnalysisDataHandle       dh = pdata->dataHandle(_data);
-    std::vector<Selection *> sel1 = pdata->parallelSelections(_sel1);
-    std::vector<Selection *> sel2 = pdata->parallelSelections(_sel2);
+    const SelectionList     &sel1 = pdata->parallelSelections(_sel1);
+    const SelectionList     &sel2 = pdata->parallelSelections(_sel2);
 
     checkSelections(sel1, sel2);
 
@@ -450,7 +450,7 @@ Angle::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
             clear_rvec(c2);
             break;
         case 's':
-            copy_rvec(_sel2[0]->position(0).x(), c2);
+            copy_rvec(_sel2[0].position(0).x(), c2);
             break;
     }
 
@@ -465,7 +465,7 @@ Angle::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
         real ave = 0.0;
         int n = 0;
         int i, j;
-        for (i = j = 0; i < sel1[g]->posCount(); i += incr1)
+        for (i = j = 0; i < sel1[g].posCount(); i += incr1)
         {
             rvec x[4];
             real angle;
index 12901f33ae4b21a250cac26652f127423a9d8b03..df91f4fad9d1c3a159c65c1b8092c67ad2937d05 100644 (file)
 #define GMX_TRAJECTORYANALYSIS_MODULES_ANGLE_H
 
 #include <string>
-#include <vector>
 
 #include "../analysismodule.h"
 #include "gromacs/analysisdata/analysisdata.h"
 #include "gromacs/options/options.h"
+#include "gromacs/selection/selection.h"
 
 namespace gmx
 {
 
-class Selection;
 class SelectionOptionInfo;
 
 namespace analysismodules
@@ -74,13 +73,13 @@ class Angle : public TrajectoryAnalysisModule
         virtual void writeOutput();
 
     private:
-        void checkSelections(const std::vector<Selection *> &sel1,
-                             const std::vector<Selection *> &sel2) const;
+        void checkSelections(const SelectionList &sel1,
+                             const SelectionList &sel2) const;
 
         Options                 _options;
 
-        std::vector<Selection *> _sel1;
-        std::vector<Selection *> _sel2;
+        SelectionList           _sel1;
+        SelectionList           _sel2;
         SelectionOptionInfo    *_sel1info;
         SelectionOptionInfo    *_sel2info;
         std::string             _fnAngle;
index f16b6637402fe4c6d755fef416ee3baa9863559a..a7c338df196f88ae4fc9e4f40e56936f363d5a62 100644 (file)
@@ -62,7 +62,6 @@ namespace analysismodules
 Distance::Distance()
     : _options("distance", "Distance calculation"), _avem(new AnalysisDataAverageModule())
 {
-    _sel[0] = _sel[1] = NULL;
 }
 
 
@@ -95,11 +94,11 @@ void
 Distance::initAnalysis(const TrajectoryAnalysisSettings &settings,
                        const TopologyInformation & /*top*/)
 {
-    if (_sel[0]->posCount() != 1)
+    if (_sel[0].posCount() != 1)
     {
         GMX_THROW(InvalidInputError("The first selection does not define a single position"));
     }
-    if (_sel[1]->posCount() != 1)
+    if (_sel[1].posCount() != 1)
     {
         GMX_THROW(InvalidInputError("The second selection does not define a single position"));
     }
@@ -122,12 +121,12 @@ Distance::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
                        TrajectoryAnalysisModuleData *pdata)
 {
     AnalysisDataHandle  dh = pdata->dataHandle(_data);
-    Selection          *sel1 = pdata->parallelSelection(_sel[0]);
-    Selection          *sel2 = pdata->parallelSelection(_sel[1]);
+    const Selection    &sel1 = pdata->parallelSelection(_sel[0]);
+    const Selection    &sel2 = pdata->parallelSelection(_sel[1]);
     rvec                dx;
     real                r;
-    SelectionPosition   p1 = sel1->position(0);
-    SelectionPosition   p2 = sel2->position(0);
+    const SelectionPosition &p1 = sel1.position(0);
+    const SelectionPosition &p2 = sel2.position(0);
 
     if (pbc != NULL)
     {
index 081fdb50b1b5a6ea9fb111e4322fdc188c2b7b49..78e3e2196d2a16b4142ebbac1532076fecf3156c 100644 (file)
 #define GMX_TRAJECTORYANALYSIS_MODULES_DISTANCE_H
 
 #include <string>
-#include <vector>
 
 #include "../analysismodule.h"
 #include "gromacs/analysisdata/analysisdata.h"
 #include "gromacs/analysisdata/modules/average.h"
 #include "gromacs/options/options.h"
+#include "gromacs/selection/selection.h"
 
 namespace gmx
 {
 
-class Selection;
-
 namespace analysismodules
 {
 
@@ -75,7 +73,7 @@ class Distance : public TrajectoryAnalysisModule
     private:
         Options                          _options;
         std::string                      _fnDist;
-        Selection                       *_sel[2];
+        Selection                        _sel[2];
         AnalysisData                     _data;
         AnalysisDataAverageModulePointer _avem;
 
index 46a9b34151533ed048b9bacd2307b31572750ccf..db1ea5aba8b700538bb66658773e54e90ffc5ffc 100644 (file)
@@ -376,9 +376,9 @@ Select::initAnalysis(const TrajectoryAnalysisSettings &settings,
     }
     _bResInd = (_resNumberType == "index");
 
-    for (std::vector<Selection *>::const_iterator i = _sel.begin(); i != _sel.end(); ++i)
+    for (SelectionList::iterator i = _sel.begin(); i != _sel.end(); ++i)
     {
-        (*i)->initCoveredFraction(CFRAC_SOLIDANGLE);
+        i->initCoveredFraction(CFRAC_SOLIDANGLE);
     }
 
     // TODO: For large systems, a float may not have enough precision
@@ -387,7 +387,7 @@ Select::initAnalysis(const TrajectoryAnalysisSettings &settings,
     snew(_totsize, _sel.size());
     for (size_t g = 0; g < _sel.size(); ++g)
     {
-        _totsize[g] = _bTotNorm ? _sel[g]->posCount() : 1;
+        _totsize[g] = _bTotNorm ? _sel[g].posCount() : 1;
     }
     if (!_fnSize.empty())
     {
@@ -440,12 +440,12 @@ Select::initAnalysis(const TrajectoryAnalysisSettings &settings,
         writer->setFileName(_fnNdx);
         for (size_t g = 0; g < _sel.size(); ++g)
         {
-            writer->addGroup(_sel[g]->name(), _sel[g]->isDynamic());
+            writer->addGroup(_sel[g].name(), _sel[g].isDynamic());
         }
         _idata.addModule(writer);
     }
 
-    _mdata.setColumns(_sel[0]->posCount());
+    _mdata.setColumns(_sel[0].posCount());
     registerAnalysisDataset(&_mdata, "mask");
     if (!_fnMask.empty())
     {
@@ -453,7 +453,7 @@ Select::initAnalysis(const TrajectoryAnalysisSettings &settings,
         {
             fprintf(stderr, "WARNING: the mask (-om) will only be written for the first group\n");
         }
-        if (!_sel[0]->isDynamic())
+        if (!_sel[0].isDynamic())
         {
             fprintf(stderr, "WARNING: will not write the mask (-om) for a static selection\n");
         }
@@ -482,8 +482,8 @@ Select::startFrames(const AnalysisDataParallelOptions &opt,
 {
     ModuleData *pdata = new ModuleData(this, opt, selections);
     snew(pdata->_mmap, 1);
-    gmx_ana_indexmap_init(pdata->_mmap, pdata->parallelSelection(_sel[0])->indexGroup(),
-                          _top, _sel[0]->type());
+    gmx_ana_indexmap_init(pdata->_mmap, pdata->parallelSelection(_sel[0]).indexGroup(),
+                          _top, _sel[0].type());
     return TrajectoryAnalysisModuleDataPointer(pdata);
 }
 
@@ -497,33 +497,33 @@ Select::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
     AnalysisDataHandle cdh = pdata->dataHandle(_cdata);
     AnalysisDataHandle idh = pdata->dataHandle(_idata);
     AnalysisDataHandle mdh = pdata->dataHandle(_mdata);
-    std::vector<Selection *> sel(pdata->parallelSelections(_sel));
+    const SelectionList &sel = pdata->parallelSelections(_sel);
 
     sdh.startFrame(frnr, fr.time);
     for (size_t g = 0; g < sel.size(); ++g)
     {
-        real normfac = _bFracNorm ? 1.0 / sel[g]->coveredFraction() : 1.0;
+        real normfac = _bFracNorm ? 1.0 / sel[g].coveredFraction() : 1.0;
         normfac /= _totsize[g];
-        sdh.setPoint(g, sel[g]->posCount() * normfac);
+        sdh.setPoint(g, sel[g].posCount() * normfac);
     }
     sdh.finishFrame();
 
     cdh.startFrame(frnr, fr.time);
     for (size_t g = 0; g < sel.size(); ++g)
     {
-        cdh.setPoint(g, sel[g]->coveredFraction());
+        cdh.setPoint(g, sel[g].coveredFraction());
     }
     cdh.finishFrame();
 
     idh.startFrame(frnr, fr.time);
     for (size_t g = 0; g < sel.size(); ++g)
     {
-        idh.setPoint(0, sel[g]->posCount());
+        idh.setPoint(0, sel[g].posCount());
         idh.finishPointSet();
-        for (int i = 0; i < sel[g]->posCount(); ++i)
+        for (int i = 0; i < sel[g].posCount(); ++i)
         {
-            SelectionPosition p = sel[g]->position(i);
-            if (sel[g]->type() == INDEX_RES && !_bResInd)
+            const SelectionPosition &p = sel[g].position(i);
+            if (sel[g].type() == INDEX_RES && !_bResInd)
             {
                 idh.setPoint(1, _top->atoms.resinfo[p.mappedId()].nr);
             }
@@ -536,7 +536,7 @@ Select::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc,
     }
     idh.finishFrame();
 
-    gmx_ana_indexmap_update(d->_mmap, sel[0]->indexGroup(), true);
+    gmx_ana_indexmap_update(d->_mmap, sel[0].indexGroup(), true);
     mdh.startFrame(frnr, fr.time);
     for (int b = 0; b < d->_mmap->nr; ++b)
     {
index 3f58b93cc9df7fdb90de2da723809e63543f131e..4f1295931f3867391091778311c6e2fe066e2db2 100644 (file)
 #define GMX_TRAJECTORYANALYSIS_MODULES_SELECT_H
 
 #include <string>
-#include <vector>
 
 #include "../analysismodule.h"
 #include "gromacs/analysisdata/analysisdata.h"
 #include "gromacs/options/options.h"
+#include "gromacs/selection/selection.h"
 
 namespace gmx
 {
 
-class AnalysisDataPlotModule;
-class Selection;
-
 namespace analysismodules
 {
 
@@ -79,7 +76,7 @@ class Select : public TrajectoryAnalysisModule
         class ModuleData;
 
         Options                  _options;
-        std::vector<Selection *> _sel;
+        SelectionList            _sel;
 
         std::string              _fnSize;
         std::string              _fnFrac;
@@ -98,7 +95,6 @@ class Select : public TrajectoryAnalysisModule
         AnalysisData             _cdata;
         AnalysisData             _idata;
         AnalysisData             _mdata;
-        std::vector<std::string> _modnames;
 };
 
 } // namespace analysismodules
index 43e06cffc412dad9345408226e80cdab28e368e5..9405cf466e6388c02b8c85988e416ada9cd82ea0 100644 (file)
@@ -37,8 +37,6 @@
 #include <config.h>
 #endif
 
-#include <vector>
-
 #include <gromacs/fatalerror/exceptions.h>
 #include <gromacs/options/basicoptions.h>
 #include <gromacs/options/options.h>
@@ -71,7 +69,7 @@ class SelectionTester : public TrajectoryAnalysisModule
         void printSelections();
 
         Options                  _options;
-        std::vector<Selection *> _selections;
+        SelectionList            _selections;
         int                      _nmaxind;
 };
 
@@ -91,7 +89,7 @@ SelectionTester::printSelections()
     fprintf(stderr, "\nSelections:\n");
     for (size_t g = 0; g < _selections.size(); ++g)
     {
-        _selections[g]->printDebugInfo(stderr, _nmaxind);
+        _selections[g].printDebugInfo(stderr, _nmaxind);
     }
     fprintf(stderr, "\n");
 }
@@ -129,23 +127,23 @@ SelectionTester::analyzeFrame(int /*frnr*/, const t_trxframe &/*fr*/, t_pbc * /*
     fprintf(stderr, "\n");
     for (size_t g = 0; g < _selections.size(); ++g)
     {
-        const Selection *sel = _selections[g];
+        const Selection &sel = _selections[g];
 
-        gmx_ana_index_dump(stderr, sel->indexGroup(), g, _nmaxind);
-        fprintf(stderr, "  Positions (%d pcs):\n", sel->posCount());
-        int n = sel->posCount();
+        gmx_ana_index_dump(stderr, sel.indexGroup(), g, _nmaxind);
+        fprintf(stderr, "  Positions (%d pcs):\n", sel.posCount());
+        int n = sel.posCount();
         if (_nmaxind >= 0 && n > _nmaxind)
         {
             n = _nmaxind;
         }
         for (int i = 0; i < n; ++i)
         {
-            SelectionPosition p = sel->position(i);
+            const SelectionPosition &p = sel.position(i);
             fprintf(stderr, "    (%.2f,%.2f,%.2f) r=%d, m=%d, n=%d\n",
                     p.x()[XX], p.x()[YY], p.x()[ZZ],
                     p.refId(), p.mappedId(), p.atomCount());
         }
-        if (n < sel->posCount())
+        if (n < sel.posCount())
         {
             fprintf(stderr, "    ...\n");
         }