/*! * \param[out] selp Pointer to receive a pointer to the created selection * element (set to NULL on error). * \param[in] method Keyword selection method to evaluate. * \param[in] param Parameter that gives the group to evaluate \p method in. * \param[in] scanner Scanner data structure. * \returns 0 on success, non-zero error code on error. * * Creates a \ref SEL_EXPRESSION selection element (pointer put in \c *selp) * that evaluates the keyword method given by \p method in the group given by * \p param. */ int _gmx_sel_init_keyword_evaluator(t_selelem **selp, gmx_ana_selmethod_t *method, t_selexpr_param *param, void *scanner) { t_selelem *sel; t_methoddata_kweval *data; gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner); char buf[1024]; sprintf(buf, "In evaluation of '%s'", method->name); gmx::MessageStringContext context(errors, buf); if ((method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL)) || method->outinit || method->pupdate) { _gmx_selexpr_free_params(param); GMX_ERROR(gmx::eeInternalError, "Unsupported keyword method for arbitrary group evaluation"); } *selp = NULL; sel = _gmx_selelem_create(SEL_EXPRESSION); _gmx_selelem_set_method(sel, method, scanner); snew(data, 1); data->kwmethod = sel->u.expr.method; data->kwmdata = sel->u.expr.mdata; gmx_ana_index_clear(&data->g); snew(sel->u.expr.method, 1); memcpy(sel->u.expr.method, data->kwmethod, sizeof(gmx_ana_selmethod_t)); sel->u.expr.method->flags |= SMETH_VARNUMVAL; sel->u.expr.method->init_data = NULL; sel->u.expr.method->set_poscoll = NULL; sel->u.expr.method->init = method->init ? &init_kweval : NULL; sel->u.expr.method->outinit = &init_output_kweval; sel->u.expr.method->free = &free_data_kweval; sel->u.expr.method->init_frame = method->init_frame ? &init_frame_kweval : NULL; sel->u.expr.method->update = &evaluate_kweval; sel->u.expr.method->pupdate = NULL; sel->u.expr.method->nparams = asize(smparams_kweval); sel->u.expr.method->param = smparams_kweval; _gmx_selelem_init_method_params(sel, scanner); sel->u.expr.mdata = data; sel->u.expr.method->param[0].val.u.g = &data->g; sfree(param->name); param->name = NULL; if (!_gmx_sel_parse_params(param, sel->u.expr.method->nparams, sel->u.expr.method->param, sel, scanner)) { _gmx_selelem_free(sel); return -1; } *selp = sel; return 0; }
int main(int argc, char *argv[]) { if (argc < 2) { CopyRight(stderr, argv[0]); GMX_ERROR(gmx::eeInvalidInput, "Not enough command-line arguments"); } std::auto_ptr<gmx::TrajectoryAnalysisModule> mod(gmx::createTrajectoryAnalysisModule(argv[1])); if (mod.get() == NULL) { CopyRight(stderr, argv[0]); GMX_ERROR(gmx::eeInvalidInput, "Unknown analysis module given as the first command-line argument"); } --argc; ++argv; gmx::TrajectoryAnalysisCommandLineRunner runner(mod.get()); return runner.run(argc, argv); }
int Angle::checkSelections(const std::vector<Selection *> &sel1, const std::vector<Selection *> &sel2) const { if (_bMulti) { for (size_t g = 0; g < sel1.size(); ++g) { if (sel1[g]->posCount() % _natoms1 != 0) { fatalErrorFormatted(eeInconsistentInput, GMX_ERRORLOC, "Number of positions in selection %d not divisible by %d", static_cast<int>(g + 1), _natoms1); return eeInconsistentInput; } } return 0; } int na1 = sel1[0]->posCount(); int na2 = (_natoms2 > 0) ? sel2[0]->posCount() : 0; if (!_bSplit1 && _natoms1 > 1 && na1 % _natoms1 != 0) { fatalErrorFormatted(eeInconsistentInput, GMX_ERRORLOC, "Number of positions in the first group not divisible by %d", _natoms1); return eeInconsistentInput; } if (!_bSplit2 && _natoms2 > 1 && na2 % _natoms2 != 0) { fatalErrorFormatted(eeInconsistentInput, GMX_ERRORLOC, "Number of positions in the second group not divisible by %d", _natoms2); return eeInconsistentInput; } if (_bSplit1) { for (int g = 1; g < _natoms1; ++g) { if (sel1[g]->posCount() != na1) { GMX_ERROR(eeInconsistentInput, "All selections in the first group should contain " "the same number of positions"); } } } else { na1 /= _natoms1; } if (_natoms2 > 1) { if (_bSplit2) { for (int g = 1; g < _natoms2; ++g) { if (sel2[g]->posCount() != na2) { GMX_ERROR(eeInconsistentInput, "All selections in the second group should contain " "the same number of positions"); } } } else { na2 /= _natoms2; } } if (_natoms1 > 0 && _natoms2 > 1 && na1 != na2) { GMX_ERROR(eeInconsistentInput, "Number of vectors defined by the two groups are not the same"); } if (_g2type[0] == 's' && sel2[0]->posCount() != 1) { GMX_ERROR(eeInconsistentInput, "The second group should contain a single position with -g2 sphnorm"); } return 0; }
int Angle::analyzeFrame(int frnr, const t_trxframe &fr, t_pbc *pbc, TrajectoryAnalysisModuleData *pdata) { AnalysisDataHandle *dh = pdata->dataHandle("angle"); std::vector<Selection *> sel1 = pdata->parallelSelections(_sel1); std::vector<Selection *> sel2 = pdata->parallelSelections(_sel2); int rc = checkSelections(sel1, sel2); if (rc != 0) { return rc; } rvec v1, v2; rvec c1, c2; switch (_g2type[0]) { case 'z': clear_rvec(v2); v2[ZZ] = 1.0; clear_rvec(c2); break; case 's': copy_rvec(_sel2[0]->x(0), c2); break; } dh->startFrame(frnr, fr.time); int incr1 = _bSplit1 ? 1 : _natoms1; int incr2 = _bSplit2 ? 1 : _natoms2; int ngrps = _bMulti ? _sel1.size() : 1; for (int g = 0; g < ngrps; ++g) { real ave = 0.0; int n = 0; int i, j; for (i = j = 0; i < sel1[g]->posCount(); i += incr1) { rvec x[4]; real angle; copy_pos(sel1, _bSplit1, _natoms1, g, i, x); switch (_g1type[0]) { case 'a': if (pbc) { pbc_dx(pbc, x[0], x[1], v1); pbc_dx(pbc, x[2], x[1], v2); } else { rvec_sub(x[0], x[1], v1); rvec_sub(x[2], x[1], v2); } angle = gmx_angle(v1, v2); break; case 'd': { rvec dx[3]; if (pbc) { pbc_dx(pbc, x[0], x[1], dx[0]); pbc_dx(pbc, x[2], x[1], dx[1]); pbc_dx(pbc, x[2], x[3], dx[2]); } else { rvec_sub(x[0], x[1], dx[0]); rvec_sub(x[2], x[1], dx[1]); rvec_sub(x[2], x[3], dx[2]); } cprod(dx[0], dx[1], v1); cprod(dx[1], dx[2], v2); angle = gmx_angle(v1, v2); real ipr = iprod(dx[0], v2); if (ipr < 0) { angle = -angle; } break; } case 'v': case 'p': calc_vec(_natoms1, x, pbc, v1, c1); switch (_g2type[0]) { case 'v': case 'p': copy_pos(sel2, _bSplit2, _natoms2, 0, j, x); calc_vec(_natoms2, x, pbc, v2, c2); j += incr2; break; case 't': // FIXME: This is not parallelizable. if (frnr == 0) { copy_rvec(v1, _vt0[n]); } copy_rvec(_vt0[n], v2); break; case 'z': c1[XX] = c1[YY] = 0.0; break; case 's': if (pbc) { pbc_dx(pbc, c1, c2, v2); } else { rvec_sub(c1, c2, v2); } break; default: GMX_ERROR(eeInternalError, "invalid -g2 value"); } angle = gmx_angle(v1, v2); break; default: GMX_ERROR(eeInternalError, "invalid -g1 value"); } angle *= RAD2DEG; real dist = 0.0; if (_bDumpDist) { if (pbc) { rvec dx; pbc_dx(pbc, c2, c1, dx); dist = norm(dx); } else { dist = sqrt(distance2(c1, c2)); } } if (_bAll) { dh->addPoint(n + 1, angle); } ave += angle; ++n; } if (n > 0) { ave /= n; } dh->addPoint(g, ave); } dh->finishFrame(); return 0; }
int Angle::initOptionsDone(TrajectoryAnalysisSettings *settings, AbstractErrorReporter *errors) { // Validity checks. bool bSingle = (_g1type[0] == 'a' || _g1type[0] == 'd'); if (bSingle && _g2type[0] != 'n') { errors->error("Cannot use a second group (-g2) with -g1 angle or dihedral"); return eeInconsistentInput; } if (bSingle && _options.isSet("group2")) { errors->error("Cannot provide a second selection (-group2) with " "-g1 angle or dihedral"); return eeInconsistentInput; } if (!bSingle && _g2type[0] == 'n') { errors->error("Should specify a second group (-g2) if the first group " "is not an angle or a dihedral"); return eeInconsistentInput; } if (bSingle && _bDumpDist) { errors->warning("Cannot calculate distances with -g1 angle or dihedral"); _bDumpDist = false; } if (_bMulti && _bSplit1) { errors->error("-mult can only be combined with -g1 angle or dihedral"); return eeInconsistentInput; } if (!bSingle && _bMulti) { errors->error("-mult can only be combined with -g1 angle or dihedral"); return eeInconsistentInput; } if (_bMulti && _bAll) { errors->error("-mult and -all are mutually exclusive options"); return eeInconsistentInput; } if (_bAll) { int rc = _sel1Adj->setOnlyStatic(true); if (rc != 0) { return rc; } } // Set up the number of positions per angle. switch (_g1type[0]) { case 'a': _natoms1 = 3; break; case 'd': _natoms1 = 4; break; case 'v': _natoms1 = 2; break; case 'p': _natoms1 = 3; break; default: GMX_ERROR(eeInternalError, "invalid -g1 value"); } switch (_g2type[0]) { case 'n': _natoms2 = 0; break; case 'v': _natoms2 = 2; break; case 'p': _natoms2 = 3; break; case 't': _natoms2 = 0; break; case 'z': _natoms2 = 0; break; case 's': _natoms2 = 1; break; default: GMX_ERROR(eeInternalError, "invalid -g2 value"); } if (_natoms2 == 0 && _options.isSet("group2")) { errors->error("Cannot provide a second selection (-group2) with -g2 t0 or z"); return eeInconsistentInput; } if (!_bMulti) { OptionAdjusterErrorContext context(_sel1Adj, errors); int rc = _sel1Adj->setValueCount(_bSplit1 ? _natoms1 : 1); if (rc != 0) { return rc; } } if (_natoms2 > 0) { OptionAdjusterErrorContext context(_sel2Adj, errors); int rc = _sel2Adj->setValueCount(_bSplit2 ? _natoms2 : 1); if (rc != 0) { return rc; } } return 0; }