* \author Teemu Murtola <teemu.murtola@gmail.com>
* \ingroup module_selection
*/
+#include "gmxpre.h"
+
#include "selectioncollection.h"
#include <cctype>
#include <boost/shared_ptr.hpp>
+#include "gromacs/fileio/trx.h"
#include "gromacs/legacyheaders/oenv.h"
-#include "gromacs/legacyheaders/xvgr.h"
-
#include "gromacs/onlinehelp/helpmanager.h"
#include "gromacs/onlinehelp/helpwritercontext.h"
#include "gromacs/options/basicoptions.h"
#include "gromacs/options/options.h"
#include "gromacs/selection/selection.h"
+#include "gromacs/selection/selhelp.h"
+#include "gromacs/topology/topology.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/file.h"
#include "gromacs/utility/gmxassert.h"
#include "parser.h"
#include "poscalc.h"
#include "scanner.h"
-#include "selection.h"
#include "selectioncollection-impl.h"
#include "selelem.h"
-#include "selhelp.h"
#include "selmethod.h"
#include "symrec.h"
*/
SelectionCollection::Impl::Impl()
- : debugLevel_(0), bExternalGroupsSet_(false), grps_(NULL)
+ : maxAtomIndex_(0), debugLevel_(0), bExternalGroupsSet_(false), grps_(NULL)
{
sc_.nvars = 0;
sc_.varstrs = NULL;
return result;
}
+/*! \brief
+ * Checks that index groups have valid atom indices.
+ *
+ * \param[in] root Root of selection tree to process.
+ * \param[in] natoms Maximum number of atoms that the selections are set
+ * to evaluate.
+ * \param errors Object for reporting any error messages.
+ * \throws std::bad_alloc if out of memory.
+ *
+ * Recursively checks the selection tree for index groups.
+ * Each found group is checked that it only contains atom indices that match
+ * the topology/maximum number of atoms set for the selection collection.
+ * Any issues are reported to \p errors.
+ */
+void checkExternalGroups(const SelectionTreeElementPointer &root,
+ int natoms,
+ ExceptionInitializer *errors)
+{
+ if (root->type == SEL_CONST && root->v.type == GROUP_VALUE)
+ {
+ try
+ {
+ root->checkIndexGroup(natoms);
+ }
+ catch (const UserInputError &)
+ {
+ errors->addCurrentExceptionAsNested();
+ }
+ }
+
+ SelectionTreeElementPointer child = root->child;
+ while (child)
+ {
+ checkExternalGroups(child, natoms, errors);
+ child = child->next;
+ }
+}
+
} // namespace
{
try
{
- root->resolveIndexGroupReference(grps_);
+ root->resolveIndexGroupReference(grps_, sc_.gall.isize);
}
catch (const UserInputError &)
{
while (child)
{
resolveExternalGroups(child, errors);
- child = child->next;
+ root->flags |= (child->flags & SEL_UNSORTED);
+ child = child->next;
}
}
{
natoms = top->atoms.nr;
}
+ if (impl_->bExternalGroupsSet_)
+ {
+ ExceptionInitializer errors("Invalid index group references encountered");
+ SelectionTreeElementPointer root = impl_->sc_.root;
+ while (root)
+ {
+ checkExternalGroups(root, natoms, &errors);
+ root = root->next;
+ }
+ if (errors.hasNestedExceptions())
+ {
+ GMX_THROW(InconsistentInputError(errors));
+ }
+ }
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);
impl_->grps_ = grps;
impl_->bExternalGroupsSet_ = true;
- ExceptionInitializer errors("Unknown index group references encountered");
+ ExceptionInitializer errors("Invalid index group reference(s)");
SelectionTreeElementPointer root = impl_->sc_.root;
while (root)
{
impl_->resolveExternalGroups(root, &errors);
+ root->checkUnsortedAtoms(true, &errors);
root = root->next;
}
if (errors.hasNestedExceptions())
const internal::SelectionData &sel = **iter;
if (sel.hasFlag(efSelection_OnlyAtoms))
{
- if (sel.type() != INDEX_ATOM)
+ if (!sel.hasOnlyAtoms())
{
std::string message = formatString(
"Selection '%s' does not evaluate to individual atoms. "
void
SelectionCollection::evaluate(t_trxframe *fr, t_pbc *pbc)
{
+ if (fr->natoms <= impl_->maxAtomIndex_)
+ {
+ std::string message = formatString(
+ "Trajectory has less atoms (%d) than what is required for "
+ "evaluating the provided selections (atoms up to index %d "
+ "are required).", fr->natoms, impl_->maxAtomIndex_ + 1);
+ GMX_THROW(InconsistentInputError(message));
+ }
impl_->sc_.pcc.initFrame();
SelectionEvaluator evaluator;
}
}
-// static
-HelpTopicPointer
-SelectionCollection::createDefaultHelpTopic()
-{
- return createSelectionHelpTopic();
-}
-
} // namespace gmx