/*
* This file is part of the GROMACS molecular simulation package.
*
- * Copyright (c) 2009,2010,2011,2012,2013, by the GROMACS development team, led by
- * David van der Spoel, Berk Hess, Erik Lindahl, and including many
- * others, as listed in the AUTHORS file in the top-level source
- * directory and at http://www.gromacs.org.
+ * Copyright (c) 2009,2010,2011,2012,2013,2014, by the GROMACS development team, led by
+ * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
+ * and including many others, as listed in the AUTHORS file in the
+ * top-level source directory and at http://www.gromacs.org.
*
* GROMACS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
#include <string>
#include <vector>
-#include "../legacyheaders/typedefs.h"
+#include "gromacs/selection/position.h"
+#include "gromacs/selection/selectionenums.h"
+#include "gromacs/utility/arrayref.h"
+#include "gromacs/utility/common.h"
+#include "gromacs/utility/gmxassert.h"
-#include "../utility/arrayref.h"
-#include "../utility/common.h"
-#include "../utility/gmxassert.h"
-
-#include "position.h"
-#include "indexutil.h"
-#include "selectionenums.h"
+struct t_topology;
namespace gmx
{
namespace internal
{
-/*! \internal \brief
+/*! \internal
+ * \brief
* Internal data for a single selection.
*
* This class is internal to the selection module, but resides in a public
SelectionData(SelectionTreeElement *elem, const char *selstr);
~SelectionData();
+ //! Returns the name for this 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; }
+ //! Returns true if the selection only contains positions with a single atom each.
+ bool hasOnlyAtoms() const { return type() == INDEX_ATOM; }
//! Number of positions in the selection.
- int posCount() const { return rawPositions_.nr; }
+ int posCount() const { return rawPositions_.count(); }
//! Returns the root of the evaluation tree for this selection.
SelectionTreeElement &rootElement() { return rootElement_; }
//! \copydoc Selection::initCoveredFraction()
bool initCoveredFraction(e_coverfrac_t type);
+ /*! \brief
+ * Updates the name of the selection if missing.
+ *
+ * \throws std::bad_alloc if out of memory.
+ *
+ * If selections get their value from a group reference that cannot be
+ * resolved during parsing, the name is final only after group
+ * references have been resolved.
+ *
+ * This function is called by SelectionCollection::setIndexGroups().
+ */
+ void refreshName();
/*! \brief
* Computes total masses and charges for all selection positions.
*
*
* Any attempt to call methods in the object before a selection is
* assigned results in undefined behavior.
+ * isValid() returns `false` for the selection until it is initialized.
*/
Selection() : sel_(NULL) {}
/*! \brief
*/
explicit Selection(internal::SelectionData *sel) : sel_(sel) {}
+ //! Returns whether the selection object is initialized.
+ bool isValid() const { return sel_ != NULL; }
+
+ //! Returns whether two selection objects wrap the same selection.
+ bool operator==(const Selection &other) const
+ {
+ return sel_ == other.sel_;
+ }
+ //! Returns whether two selection objects wrap different selections.
+ bool operator!=(const Selection &other) const
+ {
+ return !operator==(other);
+ }
+
//! Returns the name of the selection.
- const char *name() const { return data().name_.c_str(); }
+ const char *name() const { return data().name(); }
//! 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().type(); }
+ //! Returns true if the selection only contains positions with a single atom each.
+ bool hasOnlyAtoms() const { return data().hasOnlyAtoms(); }
//! Total number of atoms in the selection.
int atomCount() const
{
- return data().rawPositions_.g != NULL ? data().rawPositions_.g->isize : 0;
+ return data().rawPositions_.m.mapb.nra;
}
//! 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->index,
- data().rawPositions_.g->isize);
+ return constArrayRefFromArray(sel_->rawPositions_.m.mapb.a,
+ sel_->rawPositions_.m.mapb.nra);
}
//! Number of positions in the selection.
int posCount() const { return data().posCount(); }
//! Returns coordinates for this selection as a continuous array.
ConstArrayRef<rvec> coordinates() const
{
- return ConstArrayRef<rvec>(data().rawPositions_.x, posCount());
+ return constArrayRefFromArray(data().rawPositions_.x, posCount());
}
//! Returns whether velocities are available for this selection.
bool hasVelocities() const { return data().rawPositions_.v != NULL; }
ConstArrayRef<rvec> velocities() const
{
GMX_ASSERT(hasVelocities(), "Velocities accessed, but unavailable");
- return ConstArrayRef<rvec>(data().rawPositions_.v, posCount());
+ return constArrayRefFromArray(data().rawPositions_.v, posCount());
}
//! Returns whether forces are available for this selection.
bool hasForces() const { return sel_->rawPositions_.f != NULL; }
ConstArrayRef<rvec> forces() const
{
GMX_ASSERT(hasForces(), "Forces accessed, but unavailable");
- return ConstArrayRef<rvec>(data().rawPositions_.f, posCount());
+ return constArrayRefFromArray(data().rawPositions_.f, posCount());
}
//! Returns masses for this selection as a continuous array.
ConstArrayRef<real> masses() const
// (and thus the masses and charges are fixed).
GMX_ASSERT(data().posMass_.size() >= static_cast<size_t>(posCount()),
"Internal inconsistency");
- return ConstArrayRef<real>(data().posMass_.begin(),
- data().posMass_.begin() + posCount());
+ return constArrayRefFromVector<real>(data().posMass_.begin(),
+ data().posMass_.begin() + posCount());
}
//! Returns charges for this selection as a continuous array.
ConstArrayRef<real> charges() const
// (and thus the masses and charges are fixed).
GMX_ASSERT(data().posCharge_.size() >= static_cast<size_t>(posCount()),
"Internal inconsistency");
- return ConstArrayRef<real>(data().posCharge_.begin(),
- data().posCharge_.begin() + posCount());
+ return constArrayRefFromVector<real>(data().posCharge_.begin(),
+ data().posCharge_.begin() + posCount());
}
/*! \brief
* Returns reference IDs for this selection as a continuous array.
*/
ConstArrayRef<int> refIds() const
{
- return ConstArrayRef<int>(data().rawPositions_.m.refid, posCount());
+ return constArrayRefFromArray(data().rawPositions_.m.refid, posCount());
}
/*! \brief
* Returns mapped IDs for this selection as a continuous array.
*/
ConstArrayRef<int> mappedIds() const
{
- return ConstArrayRef<int>(data().rawPositions_.m.mapid, posCount());
+ return constArrayRefFromArray(data().rawPositions_.m.mapid, posCount());
}
//! Returns whether the covered fraction can change between frames.
//! Return atom indices that make up this position.
ConstArrayRef<int> atomIndices() const
{
- if (sel_->rawPositions_.g == NULL)
+ const int *atoms = sel_->rawPositions_.m.mapb.a;
+ if (atoms == NULL)
{
return ConstArrayRef<int>();
}
- int first = sel_->rawPositions_.m.mapb.index[i_];
- return ConstArrayRef<int>(&sel_->rawPositions_.g->index[first],
- atomCount());
+ const int first = sel_->rawPositions_.m.mapb.index[i_];
+ return constArrayRefFromArray(&atoms[first], atomCount());
}
/*! \brief
* Returns whether this position is selected in the current frame.