예제 #1
0
/*! \brief
 * Initializes position calculation using the maximum possible input index.
 *
 * \param[in,out] pc  Position calculation data structure.
 * \param[in]     g   Maximum index group for the calculation.
 * \param[in]     bBase Whether \p pc will be used as a base or not.
 *
 * \p bBase affects on how the \p pc->gmax field is initialized.
 */
static void
set_poscalc_maxindex(gmx_ana_poscalc_t *pc, gmx_ana_index_t *g, bool bBase)
{
    e_index_t          ptype;

    ptype = index_type_for_poscalc(pc->type);
    gmx_ana_index_make_block(&pc->b, pc->coll->top, g, ptype, pc->flags & POS_COMPLWHOLE);
    /* Set the type to POS_ATOM if the calculation in fact is such. */
    if (pc->b.nr == pc->b.nra)
    {
        pc->type   = POS_ATOM; 
        pc->flags &= ~(POS_MASS | POS_COMPLMAX | POS_COMPLWHOLE);
    }
    /* Set the POS_COMPLWHOLE flag if the calculation in fact always uses
     * complete residues and molecules. */
    if (!(pc->flags & POS_COMPLWHOLE)
        && (!(pc->flags & POS_DYNAMIC) || (pc->flags & POS_COMPLMAX))
        && (pc->type == POS_RES || pc->type == POS_MOL)
        && gmx_ana_index_has_complete_elems(g, ptype, pc->coll->top))
    {
        pc->flags &= ~POS_COMPLMAX;
        pc->flags |= POS_COMPLWHOLE;
    }
    /* Setup the gmax field */
    if ((pc->flags & POS_COMPLWHOLE) && !bBase && pc->b.nra > g->isize)
    {
        gmx_ana_index_copy(&pc->gmax, g, TRUE);
        sfree(pc->gmax.name);
        pc->gmax.name  = NULL;
    }
    else
    {
        gmx_ana_index_set(&pc->gmax, pc->b.nra, pc->b.a, NULL, 0);
    }
}
예제 #2
0
/*!
 * \param[in] data Data for the current frame.
 * \param[in] sel  Selection element being evaluated.
 * \param[in] g    Group for which \p sel should be evaluated.
 * \returns   0 on success, a non-zero error code on error.
 *
 * If this is the first call for this frame, evaluates the child element
 * there should be exactly one in \p g.
 * The compiler has taken care that the child actually stores the evaluated
 * value in the value pointer of this element.
 * Assumes that \p g is persistent for the duration of the whole evaluation.
 *
 * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
 * elements that have a static evaluation group, and hence do not need full
 * subexpression handling.
 */
void
_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
{
    if (sel->u.cgrp.isize == 0)
    {
        sel->child->evaluate(data, sel->child, g);
        sel->v.nr = sel->child->v.nr;
        gmx_ana_index_set(&sel->u.cgrp, g->isize, g->index, sel->u.cgrp.name, 0);
    }
}
예제 #3
0
void SelectionTreeElement::resolveIndexGroupReference(
    gmx_ana_indexgrps_t *grps, int natoms)
{
    GMX_RELEASE_ASSERT(type == SEL_GROUPREF,
                       "Should only be called for index group reference elements");
    if (grps == NULL)
    {
        std::string message = formatString(
                                  "Cannot match '%s', because index groups are not available.",
                                  name().c_str());
        GMX_THROW(InconsistentInputError(message));
    }

    gmx_ana_index_t foundGroup;
    std::string     foundName;
    if (u.gref.name != NULL)
    {
        if (!gmx_ana_indexgrps_find(&foundGroup, &foundName, grps, u.gref.name))
        {
            std::string message = formatString(
                                      "Cannot match '%s', because no such index group can be found.",
                                      name().c_str());
            GMX_THROW(InconsistentInputError(message));
        }
    }
    else
    {
        if (!gmx_ana_indexgrps_extract(&foundGroup, &foundName, grps, u.gref.id))
        {
            std::string message = formatString(
                                      "Cannot match '%s', because no such index group can be found.",
                                      name().c_str());
            GMX_THROW(InconsistentInputError(message));
        }
    }

    if (!gmx_ana_index_check_sorted(&foundGroup))
    {
        flags |= SEL_UNSORTED;
    }

    sfree(u.gref.name);
    type = SEL_CONST;
    gmx_ana_index_set(&u.cgrp, foundGroup.isize, foundGroup.index,
                      foundGroup.nalloc_index);
    setName(foundName);

    if (natoms > 0)
    {
        checkIndexGroup(natoms);
    }
}
예제 #4
0
/*!
 * \param[out] g     Index group structure.
 * \param[in]  ngrps Number of index groups.
 * \param[in]  isize Array of index group sizes.
 * \param[in]  index Array of pointers to indices of each group.
 * \param[in]  name  Array of names of the groups.
 * \param[in]  bFree If TRUE, the \p isize, \p index and \p name arrays
 *   are freed after they have been copied.
 */
void
gmx_ana_indexgrps_set(gmx_ana_indexgrps_t **g, int ngrps, int *isize,
                      atom_id **index, char **name, bool bFree)
{
    int  i;

    gmx_ana_indexgrps_alloc(g, ngrps);
    for (i = 0; i < ngrps; ++i)
    {
        gmx_ana_index_set(&(*g)->g[i], isize[i], index[i], name[i], isize[i]);
    }
    if (bFree)
    {
        sfree(isize);
        sfree(index);
        sfree(name);
    }
}
예제 #5
0
/*! \brief
 * Checks whether two position calculations should use a common base.
 *
 * \param[in]     pc1 Calculation 1 to check for.
 * \param[in]     pc2 Calculation 2 to check for.
 * \param[in]     g1  Index group structure that contains the atoms from
 *   \p pc1.
 * \param[in,out] g   Working space, should have enough allocated memory to
 *   contain the intersection of the atoms in \p pc1 and \p pc2.
 * \returns   TRUE if the two calculations should be merged to use a common
 *   base, FALSE otherwise.
 */
static bool
should_merge(gmx_ana_poscalc_t *pc1, gmx_ana_poscalc_t *pc2,
             gmx_ana_index_t *g1, gmx_ana_index_t *g)
{
    gmx_ana_index_t  g2;

    /* Do not merge calculations with different mass weighting. */
    if ((pc1->flags & POS_MASS) != (pc2->flags & POS_MASS))
    {
        return FALSE;
    }
    /* Avoid messing up complete calculations. */
    if ((pc1->flags & POS_COMPLWHOLE) != (pc2->flags & POS_COMPLWHOLE))
    {
        return FALSE;
    }
    /* Find the overlap between the calculations. */
    gmx_ana_index_set(&g2, pc2->b.nra, pc2->b.a, NULL, 0);
    gmx_ana_index_intersection(g, g1, &g2);
    /* Do not merge if there is no overlap. */
    if (g->isize == 0)
    {
        return FALSE;
    }
    /* Full completion calculations always match if the type is correct. */
    if ((pc1->flags & POS_COMPLWHOLE) && (pc2->flags & POS_COMPLWHOLE)
        && pc1->type == pc2->type)
    {
        return TRUE;
    }
    /* The calculations also match if the intersection consists of full
     * blocks. */
    if (gmx_ana_index_has_full_ablocks(g, &pc1->b)
        && gmx_ana_index_has_full_ablocks(g, &pc2->b))
    {
        return TRUE;
    }
    return FALSE;
}
예제 #6
0
/*! \brief
 * Setups the static base calculation for a position calculation.
 *
 * \param[in,out] pc   Position calculation to setup the base for.
 */
static void
setup_base(gmx_ana_poscalc_t *pc)
{
    gmx_ana_poscalc_t *base, *pbase, *next;
    gmx_ana_index_t    gp, g;

    /* Exit immediately if pc should not have a base. */
    if (!can_use_base(pc))
    {
        return;
    }

    gmx_ana_index_set(&gp, pc->b.nra, pc->b.a, NULL, 0);
    gmx_ana_index_clear(&g);
    gmx_ana_index_reserve(&g, pc->b.nra);
    pbase = pc;
    base = pc->coll->first;
    while (base)
    {
        /* Save the next calculation so that we can safely delete base */
        next = base->next;
        /* Skip pc, calculations that already have a base (we should match the
         * base instead), as well as calculations that should not have a base.
         * If the above conditions are met, check whether we should do a
         * merge.
         */
        if (base != pc && !base->sbase && can_use_base(base)
            && should_merge(pbase, base, &gp, &g))
        {
            /* Check whether this is the first base found */
            if (pbase == pc)
            {
                /* Create a real base if one is not present */
                if (!base->p)
                {
                    pbase = create_simple_base(base);
                }
                else
                {
                    pbase = base;
                }
                /* Make it a base for pc as well */
                merge_to_base(pbase, pc);
                pc->sbase = pbase;
                pbase->refcount++;
            }
            else /* This was not the first base */
            {
                if (!base->p)
                {
                    /* If it is not a real base, just make the new base as
                     * the base for it as well. */
                    merge_to_base(pbase, base);
                    base->sbase = pbase;
                    pbase->refcount++;
                }
                else
                {
                    /* If base is a real base, merge it with the new base
                     * and delete it. */
                    merge_bases(pbase, base);
                }
            }
            gmx_ana_index_set(&gp, pbase->b.nra, pbase->b.a, NULL, 0);
            gmx_ana_index_reserve(&g, pc->b.nra);
        }
        /* Proceed to the next unchecked calculation */
        base = next;
    }

    gmx_ana_index_deinit(&g);

    /* If no base was found, create one if one is required */
    if (!pc->sbase && (pc->flags & POS_DYNAMIC)
        && (pc->flags & (POS_COMPLMAX | POS_COMPLWHOLE)))
    {
        create_simple_base(pc);
    }
}
예제 #7
0
/*! \brief
 * Merges a calculation into another calculation such that the new calculation
 * can be used as a base.
 *
 * \param[in,out] base Base calculation to merge to.
 * \param[in,out] pc   Position calculation to merge to \p base.
 *
 * After the call, \p base can be used as a base for \p pc (or any calculation
 * that used it as a base).
 * It is assumed that any overlap between \p base and \p pc is in complete
 * blocks, i.e., that the merge is possible.
 */
static void
merge_to_base(gmx_ana_poscalc_t *base, gmx_ana_poscalc_t *pc)
{
    gmx_ana_index_t  gp, gb, g;
    int              isize, bnr;
    int              i, j, bi, bj, bo;

    gmx_ana_index_set(&gp, pc->b.nra, pc->b.a, NULL, 0);
    gmx_ana_index_set(&gb, base->b.nra, base->b.a, NULL, 0);
    isize = gmx_ana_index_difference_size(&gp, &gb);
    if (isize > 0)
    {
        gmx_ana_index_clear(&g);
        gmx_ana_index_reserve(&g, base->b.nra + isize);
        /* Find the new blocks */
        gmx_ana_index_difference(&g, &gp, &gb);
        /* Count the blocks in g */
        i = bi = bnr = 0;
        while (i < g.isize)
        {
            while (pc->b.a[pc->b.index[bi]] != g.index[i])
            {
                ++bi;
            }
            i += pc->b.index[bi+1] - pc->b.index[bi];
            ++bnr;
            ++bi;
        }
        /* Merge the atoms into a temporary structure */
        gmx_ana_index_merge(&g, &gb, &g);
        /* Merge the blocks */
        srenew(base->b.index, base->b.nr + bnr + 1);
        i  = g.isize - 1;
        bi = base->b.nr - 1;
        bj = pc->b.nr - 1;
        bo = base->b.nr + bnr - 1;
        base->b.index[bo+1] = i + 1;
        while (bo >= 0)
        {
            if (bi < 0 || base->b.a[base->b.index[bi+1]-1] != g.index[i])
            {
                i -= pc->b.index[bj+1] - pc->b.index[bj];
                --bj;
            }
            else
            {
                if (bj >= 0 && pc->b.a[pc->b.index[bj+1]-1] == g.index[i])
                {
                    --bj;
                }
                i -= base->b.index[bi+1] - base->b.index[bi];
                --bi;
            }
            base->b.index[bo] = i + 1;
            --bo;
        }
        base->b.nr           += bnr;
        base->b.nalloc_index += bnr;
        sfree(base->b.a);
        base->b.nra      = g.isize;
        base->b.a        = g.index;
        base->b.nalloc_a = g.isize;
        /* Refresh the gmax field */
        gmx_ana_index_set(&base->gmax, base->b.nra, base->b.a, NULL, 0);
    }
}
void
Selection::printDebugInfo(FILE *fp, int nmaxind) const
{
    const gmx_ana_pos_t &p = data().rawPositions_;

    fprintf(fp, "  ");
    printInfo(fp);
    fprintf(fp, "    Group ");
    gmx_ana_index_t g;
    gmx_ana_index_set(&g, p.m.mapb.nra, p.m.mapb.a, 0);
    gmx_ana_index_dump(fp, &g, 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");
}