/*! * \param[in] pc Position calculation data structure. * \param[out] p Output positions. * * Calls to gmx_ana_poscalc_update() using \p pc should use only positions * initialized with this function. * The \c p->g pointer is initialized to point to an internal group that * contains the maximum index group set with gmx_ana_poscalc_set_maxindex(). */ void gmx_ana_poscalc_init_pos(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p) { e_index_t ptype; ptype = index_type_for_poscalc(pc->type); gmx_ana_indexmap_init(&p->m, &pc->gmax, pc->coll->top, ptype); gmx_ana_pos_reserve(p, p->m.nr, 0); p->g = &pc->gmax; }
/*! * \param[out] pos Position data structure to initialize. * \param[in] x Position vector to use. */ void gmx_ana_pos_init_const(gmx_ana_pos_t *pos, const rvec x) { snew(pos->x, 1); snew(pos->v, 1); snew(pos->f, 1); pos->nalloc_x = 1; copy_rvec(x, pos->x[0]); clear_rvec(pos->v[0]); clear_rvec(pos->f[0]); gmx_ana_indexmap_init(&pos->m, NULL, NULL, INDEX_UNKNOWN); }
/*! * \param[in] pc Position calculation data structure. * \param[out] p Output positions. * * Calls to gmx_ana_poscalc_update() using \p pc should use only positions * initialized with this function. * The \c p->g pointer is initialized to point to an internal group that * contains the maximum index group set with gmx_ana_poscalc_set_maxindex(). */ void gmx_ana_poscalc_init_pos(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p) { gmx_ana_indexmap_init(&p->m, &pc->gmax, pc->coll->top_, pc->itype); /* Only do the static optimization when there is no completion */ if (!(pc->flags & POS_DYNAMIC) && pc->b.nra == pc->gmax.isize) { gmx_ana_indexmap_set_static(&p->m, &pc->b); } gmx_ana_pos_reserve(p, p->m.mapb.nr, 0); if (pc->flags & POS_VELOCITIES) { gmx_ana_pos_reserve_velocities(p); } if (pc->flags & POS_FORCES) { gmx_ana_pos_reserve_forces(p); } }
int gmx_select(int argc, char *argv[]) { const char *desc[] = { "g_select writes out basic data about dynamic selections.", "It can be used for some simple analyses, or the output can", "be combined with output from other programs and/or external", "analysis programs to calculate more complex things.", "Any combination of the output options is possible, but note", "that [TT]-om[tt] only operates on the first selection.[PAR]", "With [TT]-os[tt], calculates the number of positions in each", "selection for each frame. With [TT]-norm[tt], the output is", "between 0 and 1 and describes the fraction from the maximum", "number of positions (e.g., for selection 'resname RA and x < 5'", "the maximum number of positions is the number of atoms in", "RA residues). With [TT]-cfnorm[tt], the output is divided", "by the fraction covered by the selection.", "[TT]-norm[tt] and [TT]-cfnorm[tt] can be specified independently", "of one another.[PAR]", "With [TT]-oc[tt], the fraction covered by each selection is", "written out as a function of time.[PAR]", "With [TT]-oi[tt], the selected atoms/residues/molecules are", "written out as a function of time. In the output, the first", "column contains the frame time, the second contains the number", "of positions, followed by the atom/residue/molecule numbers.", "If more than one selection is specified, the size of the second", "group immediately follows the last number of the first group", "and so on. With [TT]-dump[tt], the frame time and the number", "of positions is omitted from the output. In this case, only one", "selection can be given.[PAR]", "With [TT]-om[tt], a mask is printed for the first selection", "as a function of time. Each line in the output corresponds to", "one frame, and contains either 0/1 for each atom/residue/molecule", "possibly selected. 1 stands for the atom/residue/molecule being", "selected for the current frame, 0 for not selected.", "With [TT]-dump[tt], the frame time is omitted from the output.", }; bool bDump = FALSE; bool bFracNorm = FALSE; bool bTotNorm = FALSE; t_pargs pa[] = { {"-dump", FALSE, etBOOL, {&bDump}, "Do not print the frame time (-om, -oi) or the index size (-oi)"}, {"-norm", FALSE, etBOOL, {&bTotNorm}, "Normalize by total number of positions with -os"}, {"-cfnorm", FALSE, etBOOL, {&bFracNorm}, "Normalize by covered fraction with -os"}, }; t_filenm fnm[] = { {efXVG, "-os", "size.xvg", ffOPTWR}, {efXVG, "-oc", "cfrac.xvg", ffOPTWR}, {efDAT, "-oi", "index.dat", ffOPTWR}, {efDAT, "-om", "mask.dat", ffOPTWR}, }; #define NFILE asize(fnm) gmx_ana_traj_t *trj; t_topology *top; int ngrps; gmx_ana_selection_t **sel; char **grpnames; t_dsdata d; char *fnSize, *fnFrac, *fnIndex, *fnMask; int g; int rc; CopyRight(stderr, argv[0]); gmx_ana_traj_create(&trj, 0); gmx_ana_set_nanagrps(trj, -1); parse_trjana_args(trj, &argc, argv, 0, NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, NULL); gmx_ana_get_nanagrps(trj, &ngrps); gmx_ana_get_anagrps(trj, &sel); gmx_ana_init_coverfrac(trj, CFRAC_SOLIDANGLE); /* Get output file names */ fnSize = opt2fn_null("-os", NFILE, fnm); fnFrac = opt2fn_null("-oc", NFILE, fnm); fnIndex = opt2fn_null("-oi", NFILE, fnm); fnMask = opt2fn_null("-om", NFILE, fnm); /* Write out sizes if nothing specified */ if (!fnFrac && !fnIndex && !fnMask) { fnSize = opt2fn("-os", NFILE, fnm); } if (bDump && ngrps > 1) { gmx_fatal(FARGS, "Only one index group allowed with -dump"); } if (fnMask && ngrps > 1) { fprintf(stderr, "warning: the mask (-om) will only be written for the first group\n"); } if (fnMask && !sel[0]->bDynamic) { fprintf(stderr, "warning: will not write the mask (-om) for a static selection\n"); fnMask = NULL; } /* Initialize reference calculation for masks */ if (fnMask) { gmx_ana_get_topology(trj, FALSE, &top, NULL); snew(d.mmap, 1); gmx_ana_indexmap_init(d.mmap, sel[0]->g, top, sel[0]->p.m.type); } /* Initialize calculation data */ d.bDump = bDump; d.bFracNorm = bFracNorm; snew(d.size, ngrps); for (g = 0; g < ngrps; ++g) { d.size[g] = bTotNorm ? sel[g]->p.nr : 1; } /* Open output files */ d.sfp = d.cfp = d.ifp = d.mfp = NULL; gmx_ana_get_grpnames(trj, &grpnames); if (fnSize) { d.sfp = xvgropen(fnSize, "Selection size", "Time (ps)", "Number"); xvgr_selections(d.sfp, trj); xvgr_legend(d.sfp, ngrps, grpnames); } if (fnFrac) { d.cfp = xvgropen(fnFrac, "Covered fraction", "Time (ps)", "Fraction"); xvgr_selections(d.cfp, trj); xvgr_legend(d.cfp, ngrps, grpnames); } if (fnIndex) { d.ifp = ffopen(fnIndex, "w"); xvgr_selections(d.ifp, trj); } if (fnMask) { d.mfp = ffopen(fnMask, "w"); xvgr_selections(d.mfp, trj); } /* Do the analysis and write out results */ gmx_ana_do(trj, 0, &print_data, &d); /* Close the files */ if (d.sfp) { fclose(d.sfp); } if (d.cfp) { fclose(d.cfp); } if (d.ifp) { fclose(d.ifp); } if (d.mfp) { fclose(d.mfp); } thanx(stderr); return 0; }
/*! \brief * Parses the values for a parameter that takes a variable number of values. * * \param[in] nval Number of values in \p values. * \param[in] values Pointer to the list of values. * \param param Parameter to parse. * \param root Selection element to which child expressions are added. * \returns TRUE if the values were parsed successfully, FALSE otherwise. * * For integer ranges, the sequence of numbers from the first to second value * is stored, each as a separate value. */ static gmx_bool parse_values_varnum(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param, t_selelem *root) { t_selexpr_value *value; int i, j; param->flags &= ~SPAR_DYNAMIC; /* Update nval if there are integer ranges. */ if (param->val.type == INT_VALUE) { value = values; while (value) { if (value->type == INT_VALUE && !value->bExpr) { nval += abs(value->u.i.i2 - value->u.i.i1); } value = value->next; } } /* Check that the value type is actually implemented */ if (param->val.type != INT_VALUE && param->val.type != REAL_VALUE && param->val.type != STR_VALUE && param->val.type != POS_VALUE) { gmx_bug("internal error"); return FALSE; } /* Reserve appropriate amount of memory */ if (param->val.type == POS_VALUE) { gmx_ana_pos_reserve(param->val.u.p, nval, 0); gmx_ana_pos_set_nr(param->val.u.p, nval); gmx_ana_indexmap_init(¶m->val.u.p->m, NULL, NULL, INDEX_UNKNOWN); } else { _gmx_selvalue_reserve(¶m->val, nval); } value = values; i = 0; while (value) { if (value->bExpr) { _gmx_selparser_error("expressions not supported within value lists"); return FALSE; } if (value->type != param->val.type) { gmx_bug("internal error"); return FALSE; } switch (param->val.type) { case INT_VALUE: if (value->u.i.i1 <= value->u.i.i2) { for (j = value->u.i.i1; j <= value->u.i.i2; ++j) { param->val.u.i[i++] = j; } } else { for (j = value->u.i.i1; j >= value->u.i.i2; --j) { param->val.u.i[i++] = j; } } break; case REAL_VALUE: if (value->u.r.r1 != value->u.r.r2) { _gmx_selparser_error("real ranges not supported for parameter '%s'", param->name); return FALSE; } param->val.u.r[i++] = value->u.r.r1; break; case STR_VALUE: param->val.u.s[i++] = strdup(value->u.s); break; case POS_VALUE: copy_rvec(value->u.x, param->val.u.p->x[i++]); break; default: /* Should not be reached */ gmx_bug("internal error"); return FALSE; } value = value->next; } param->val.nr = i; if (param->nvalptr) { *param->nvalptr = param->val.nr; } param->nvalptr = NULL; /* Create a dummy child element to store the string values. * This element is responsible for freeing the values, but carries no * other function. */ if (param->val.type == STR_VALUE) { t_selelem *child; child = _gmx_selelem_create(SEL_CONST); _gmx_selelem_set_vtype(child, STR_VALUE); child->name = param->name; child->flags &= ~SEL_ALLOCVAL; child->flags |= SEL_FLAGSSET | SEL_VARNUMVAL | SEL_ALLOCDATA; child->v.nr = param->val.nr; _gmx_selvalue_setstore(&child->v, param->val.u.s); /* Because the child is not group-valued, the u union is not used * for anything, so we can abuse it by storing the parameter value * as place_child() expects, but this is really ugly... */ child->u.param = param; place_child(root, child, param); } return TRUE; }