void
SelectionCollection::compile()
{
    if (_impl->_sc.top == NULL && requiresTopology())
    {
        GMX_THROW(InconsistentInputError("Selection requires topology information, but none provided"));
    }
    if (!_impl->hasFlag(Impl::efExternalGroupsSet))
    {
        setIndexGroups(NULL);
    }
    if (_impl->_debugLevel >= 1)
    {
        printTree(stderr, false);
    }

    SelectionCompiler compiler;
    compiler.compile(this);

    if (_impl->hasFlag(Impl::efOwnPositionCollection))
    {
        if (_impl->_debugLevel >= 1)
        {
            std::fprintf(stderr, "\n");
            printTree(stderr, false);
            std::fprintf(stderr, "\n");
            gmx_ana_poscalc_coll_print_tree(stderr, _impl->_sc.pcc);
            std::fprintf(stderr, "\n");
        }
        gmx_ana_poscalc_init_eval(_impl->_sc.pcc);
        if (_impl->_debugLevel >= 1)
        {
            gmx_ana_poscalc_coll_print_tree(stderr, _impl->_sc.pcc);
            std::fprintf(stderr, "\n");
        }
    }
}
示例#2
0
/*!
 * \param[in,out] d     Trajectory analysis data structure.
 * \returns       0 on success, a non-zero error code on error.
 *
 * Initializes the selection data in \c gmx_ana_traj_t based on
 * the selection options and/or index files provided on the command line.
 *
 * This function is called automatically by parse_trjana_args() and should
 * not be called directly unless \ref ANA_USER_SELINIT is specified.
 *
 * \see ANA_USER_SELINIT
 */
int
gmx_ana_init_selections(gmx_ana_traj_t *d)
{
    int                  rc;
    int                  i;
    int                  nr;
    gmx_ana_indexgrps_t *grps;
    int                  natoms;
    bool                 bStdIn;
    bool                 bInteractive;
    bool                 bOk;

    if (d->sel)
    {
        gmx_call("init_selections called more than once\n"
                 "perhaps you forgot ANA_USER_SELINIT");
        return -1;
    }

    /* Check if we need some information from the topology */
    if (gmx_ana_selcollection_requires_top(d->sc))
    {
        rc = load_topology(d, TRUE);
        if (rc != 0)
        {
            return rc;
        }
    }
    /* Load the topology and init the index groups */
    gmx_ana_indexgrps_init(&grps, d->top, d->ndxfile);
    /* Parse the selection */
    rc = gmx_ana_selmethod_register_defaults(d->sc);
    if (rc != 0)
    {
        gmx_fatal(FARGS, "default selection method registration failed");
        return rc;
    }
    bStdIn = (d->selfile && d->selfile[0] == '-' && d->selfile[1] == 0)
             || (d->selection && d->selection[0] == 0)
             || (!d->selfile && !d->selection);
    bInteractive = bStdIn && isatty(fileno(stdin));
    if (bStdIn && bInteractive)
    {
        /* Parse from stdin */
        /* First we parse the reference groups if there are any */
        if (d->nrefgrps > 0)
        {
            fprintf(stderr, "\nSpecify ");
            if (d->nrefgrps == 1)
            {
                fprintf(stderr, "a reference selection");
            }
            else
            {
                fprintf(stderr, "%d reference selections", d->nrefgrps);
            }
            fprintf(stderr, ":\n");
            fprintf(stderr, "(one selection per line, use \\ for line continuation)\n");
            rc = gmx_ana_selcollection_parse_stdin(d->sc, d->nrefgrps, grps, TRUE);
            nr = gmx_ana_selcollection_get_count(d->sc);
            if (rc != 0 || nr != d->nrefgrps)
            {
                gmx_ana_traj_free(d);
                gmx_input("unrecoverable error in selection parsing");
                return rc;
            }
        }
        /* Then, we parse the analysis groups */
        fprintf(stderr, "\nSpecify ");
        if (d->nanagrps == 1)
        {
            fprintf(stderr, "a selection");
        }
        else if (d->nanagrps == -1)
        {
            fprintf(stderr, "any number of selections");
        }
        else
        {
            fprintf(stderr, "%d selections", d->nanagrps);
        }
        fprintf(stderr, " for analysis:\n");
        fprintf(stderr, "(one selection per line, use \\ for line continuation%s)\n",
                d->nanagrps == -1 ? ", Ctrl-D to end" : "");
        rc = gmx_ana_selcollection_parse_stdin(d->sc, d->nanagrps, grps, TRUE);
        fprintf(stderr, "\n");
    }
    else if (bStdIn)
    {
        rc = gmx_ana_selcollection_parse_stdin(d->sc, -1, grps, FALSE);
    }
    else if (d->selection)
    {
        rc = gmx_ana_selcollection_parse_str(d->sc, d->selection, grps);
    }
    else
    {
        rc = gmx_ana_selcollection_parse_file(d->sc, d->selfile, grps);
    }
    gmx_ana_indexgrps_free(grps);
    if (rc != 0)
    {
        /* Free memory for memory leak checking */
        gmx_ana_traj_free(d);
        gmx_input("selection(s) could not be parsed");
        return rc;
    }

    /* Check the number of groups */
    nr = gmx_ana_selcollection_get_count(d->sc);
    if (nr <= d->nrefgrps)
    {
        gmx_input("selection does not specify enough index groups");
        return -1;
    }
    if (d->nanagrps <= 0)
    {
        d->nanagrps = nr - d->nrefgrps;
    }
    else if (nr != d->nrefgrps + d->nanagrps)
    {
        gmx_input("selection does not specify the correct number of index groups");
        return -1;
    }

    if (d->flags & ANA_DEBUG_SELECTION)
    {
        gmx_ana_selcollection_print_tree(stderr, d->sc, FALSE);
    }
    if (gmx_ana_selcollection_requires_top(d->sc))
    {
        rc = load_topology(d, TRUE);
        if (rc != 0)
        {
            return rc;
        }
    }
    if (d->top)
    {
        natoms = -1;
    }
    else
    {
        rc = init_first_frame(d);
        if (rc != 0)
        {
            return rc;
        }
        natoms = d->fr->natoms;
    }
    gmx_ana_selcollection_set_topology(d->sc, d->top, natoms);
    rc = gmx_ana_selcollection_compile(d->sc);
    if (rc != 0)
    {
        /* Free memory for memory leak checking */
        gmx_ana_traj_free(d);
        gmx_input("selection could not be compiled");
        return rc;
    }
    /* Create the selection array */
    d->ngrps = gmx_ana_selcollection_get_count(d->sc);
    if (!(d->flags & ANA_USE_FULLGRPS))
    {
        d->ngrps -= d->nrefgrps;
    }
    snew(d->sel, d->ngrps);
    for (i = 0; i < d->ngrps; ++i)
    {
        if (d->flags & ANA_USE_FULLGRPS)
        {
            d->sel[i] = gmx_ana_selcollection_get_selection(d->sc, i);
        }
        else
        {
            d->sel[i] = gmx_ana_selcollection_get_selection(d->sc, i + d->nrefgrps);
        }
    }
    if (d->flags & ANA_DEBUG_SELECTION)
    {
        fprintf(stderr, "\n");
        gmx_ana_selcollection_print_tree(stderr, d->sc, FALSE);
        fprintf(stderr, "\n");
        gmx_ana_poscalc_coll_print_tree(stderr, d->pcc);
        fprintf(stderr, "\n");
    }

    /* Initialize the position evaluation */
    gmx_ana_poscalc_init_eval(d->pcc);
    if (d->flags & ANA_DEBUG_SELECTION)
    {
        gmx_ana_poscalc_coll_print_tree(stderr, d->pcc);
        fprintf(stderr, "\n");
    }

    /* Check that dynamic selections are not provided if not allowed */
    if (d->flags & ANA_NO_DYNSEL)
    {
        for (i = 0; i < d->nrefgrps + d->nanagrps; ++i)
        {
            gmx_ana_selection_t *sel;

            sel = gmx_ana_selcollection_get_selection(d->sc, i);
            if (sel->bDynamic)
            {
                gmx_fatal(FARGS, "%s does not support dynamic selections",
                          ShortProgram());
                return -1;
            }
        }
    }
    /* Check that non-atom positions are not provided if not allowed.
     * TODO: It would be better to have these checks in the parser. */
    if (d->flags & ANA_ONLY_ATOMPOS)
    {
        for (i = 0; i < d->nanagrps; ++i)
        {
            gmx_ana_selection_t *sel;

            sel = gmx_ana_selcollection_get_selection(d->sc, i + d->nrefgrps);
            if (sel->p.m.type != INDEX_ATOM)
            {
                gmx_fatal(FARGS, "%s does not support non-atom positions",
                          ShortProgram());
                return -1;
            }
        }
    }
    /* Create the names array */
    snew(d->grpnames, d->ngrps);
    for (i = 0; i < d->ngrps; ++i)
    {
        d->grpnames[i] = gmx_ana_selection_name(d->sel[i]);
    }

    return 0;
}