Updated selection documentation.
[gromacs/qmmm-gamess-us.git] / src / gmxlib / trajana / trajana.c
blob923b83219a1cd365189be29cbad563a70093de5c
1 /*
3 * This source code is part of
5 * G R O M A C S
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
31 /*! \page libtrajana Library for trajectory analysis
33 * This is a trajectory analysis library for Gromacs.
35 * The main features of the library are:
36 * - \subpage selengine "Flexible handling of textual selections" that can
37 * also be dynamic, i.e., depend of the trajectory frame through
38 * positions of the particles.
39 * Selections evaluate directly to positions, which can then be used in
40 * the analysis program.
41 * - \subpage selmethods "Custom selection keywords" can also be easily
42 * implemented, also on a tool-by-tool basis.
43 * - Efficient \subpage nbsearch "neighborhood searching"
44 * (currently not very efficient...).
45 * - \subpage displacements "On-the-fly calculation of displacement vectors"
46 * during a single pass over the trajectory.
47 * - \subpage histograms "Calculation of histograms" with error estimates
48 * through block averaging.
50 * The functions also automate several things common to most analysis programs
51 * such as making molecules whole if required, reading input files, and
52 * setting up index groups for analysis.
53 * The library unifies the structure of analysis programs (at least a bit)
54 * and makes it easier to add common functionality to all analysis programs.
57 * \section main_using Using the library
59 * There is a \ref share/template/template.c "template" for writing
60 * analysis programs, the documentation for it and links from there should
61 * help getting started.
64 * \internal
65 * \section libtrajana_impl Implementation details
67 * Some internal implementation details of the library are documented on
68 * separate pages:
69 * - \subpage poscalcengine
70 * - \subpage selparser
71 * - \subpage selcompiler
73 /*! \page selengine Text-based selections
75 * \section selection_basics Basics
77 * Selections are enabled automatically for an analysis program that uses
78 * the library. The selection syntax is described in an online help that is
79 * accessible from all tools that use the library.
80 * By default, dynamic selections are allowed, and the user can freely
81 * choose whether to analyze atoms or centers of mass/geometry of
82 * residues/molecules.
83 * These defaults, as well as some others, can be changed by specifying
84 * flags for gmx_ana_traj_create().
86 * The analysis program can then access the selected positions for each frame
87 * through a \p gmx_ana_selection_t array that is passed to the frame
88 * analysis function (see gmx_analysisfunc()).
89 * As long as the analysis program is written such that it does not assume
90 * that the number of positions or the atoms in the groups groups remain
91 * constant, any kind of selection expression can be used.
93 * Some analysis programs may require a special structure for the index groups
94 * (e.g., \c g_angle requires the index group to be made of groups of three or
95 * four atoms).
96 * For such programs, it is up to the user to provide a proper selection
97 * expression that always returns such positions.
98 * Such analysis program can define \ref ANA_REQUIRE_WHOLE to make the
99 * default behavior appropriate for the most common uses where the groups
100 * should consist of atoms within a single residue/molecule.
102 * \note
103 * Currently, it is not possible to write selection expressions that would
104 * evaluate to index groups where the same atom occurs more than once.
105 * Such index groups may be useful with tools like \c g_angle to calculate
106 * the averages over several angles.
107 * It is possible to implement such a feature, but currently the best solution is to
108 * write/modify the tool such that it can deal with multiple index groups,
109 * each of which then defines angles that don't have overlapping atoms.
111 * \section selection_methods Implementing new keywords
113 * New selection keywords can be easily implemented, either directly into the
114 * library or as part of analysis programs (the latter may be useful for
115 * testing or methods very specific to some analysis).
116 * For both cases, you should first create a \c gmx_ana_selmethod_t structure
117 * and fill it with the necessary information.
118 * Details can be found on a separate page: \ref selmethods.
120 /*! \internal \file
121 * \brief Implementation of functions in trajana.h.
123 /*! \internal \dir src/gmxlib/trajana
124 * \brief Source code for common trajectory analysis functions.
126 * Selection handling is found in \ref src/gmxlib/selection.
128 #ifdef HAVE_CONFIG_H
129 #include <config.h>
130 #endif
132 #include <string.h>
134 #include <filenm.h>
135 #include <futil.h>
136 #include <macros.h>
137 #include <pbc.h>
138 #include <rmpbc.h>
139 #include <smalloc.h>
140 #include <statutil.h>
141 #include <typedefs.h>
142 #include <tpxio.h>
143 #include <vec.h>
145 #include <poscalc.h>
146 #include <selection.h>
147 #include <selmethod.h>
148 #include <trajana.h>
150 /*! \internal \brief
151 * Data structure for trajectory analysis tools.
153 struct gmx_ana_traj_t
155 /*! \brief
156 * Flags that alter the behavior of the analysis library.
158 * This variable stores the flags passed to gmx_ana_traj_create() for use
159 * in the other functions.
161 unsigned long flags;
162 /** Number of input reference groups. */
163 int nrefgrps;
164 /*! \brief
165 * Number of input analysis groups.
167 * This is the number of groups in addition to the reference groups
168 * that are required.
169 * If -1, any number of groups (at least one) is acceptable.
171 int nanagrps;
172 /*! \brief
173 * Flags for init_first_frame() to specify what to read from the
174 * trajectory.
176 int frflags;
177 /** TRUE if molecules should be made whole for each frame. */
178 bool bRmPBC;
179 /*! \brief
180 * TRUE if periodic boundary conditions should be used.
182 * If the flag is FALSE, the \p pbc pointer passed to gmx_analysisfunc()
183 * is NULL.
185 bool bPBC;
187 /** Name of the trajectory file (NULL if not provided). */
188 const char *trjfile;
189 /** Name of the topology file (NULL if no topology loaded). */
190 const char *topfile;
191 /** Non-NULL name of the topology file. */
192 const char *topfile_notnull;
193 /** Name of the index file (NULL if no index file provided). */
194 const char *ndxfile;
195 /** Name of the selection file (NULL if no file provided). */
196 const char *selfile;
197 /** The selection string (NULL if not provided). */
198 const char *selection;
200 /** The topology structure, or \p NULL if no topology loaded. */
201 t_topology *top;
202 /** TRUE if full tpx file was loaded, FALSE otherwise. */
203 bool bTop;
204 /** Coordinates from the topology (see \p bTopX). */
205 rvec *xtop;
206 /** The box loaded from the topology file. */
207 matrix boxtop;
208 /** The ePBC field loaded from the topology file. */
209 int ePBC;
211 /** The current frame, or \p NULL if no frame loaded yet. */
212 t_trxframe *fr;
213 /** Used to store the status variable from read_first_frame(). */
214 int status;
215 /** The number of frames read. */
216 int nframes;
218 /** Number of elements in the \p sel array. */
219 int ngrps;
220 /*! \brief
221 * Array of selection information (one element for each index group).
223 * After the call to gmx_ana_init_selections(), this array contains
224 * information about the selections the user has provided.
225 * The array contains \p ngrps elements;
226 * if \p nanagrps was -1, the number may vary.
227 * See \c gmx_ana_selection_t for details of the contents.
229 * The largest possible index groups for dynamic selections can be found
230 * in \p sel[i]->g, i.e., the program can assume that any index group
231 * passed to gmx_analysisfunc() is a subset of the provided group.
232 * After gmx_ana_do(), the same groups can be used in post-processing.
234 gmx_ana_selection_t **sel;
235 /** Array of names of the selections for convenience. */
236 char **grpnames;
237 /** Position calculation data. */
238 gmx_ana_poscalc_coll_t *pcc;
239 /** Selection data. */
240 gmx_ana_selcollection_t *sc;
242 /** Data for statutil.c utilities. */
243 output_env_t oenv;
246 /** Loads the topology. */
247 static int load_topology(gmx_ana_traj_t *d, bool bReq);
248 /** Loads the first frame and does some checks. */
249 static int init_first_frame(gmx_ana_traj_t *d);
251 static int add_fnmarg(int nfile, t_filenm *fnm, t_filenm *fnm_add)
253 memcpy(&(fnm[nfile]), fnm_add, sizeof(*fnm_add));
254 return nfile + 1;
257 /* Copied from src/gmxlib/statutil.c */
258 static int
259 add_parg(int npargs, t_pargs *pa, t_pargs *pa_add)
261 memcpy(&(pa[npargs]), pa_add, sizeof(*pa_add));
262 return npargs + 1;
266 * \param[out] data Trajectory analysis data structure poitner to initialize.
267 * \param[in] flags Combination of flags (see \ref analysis_flags).
268 * \returns 0 on success.
271 gmx_ana_traj_create(gmx_ana_traj_t **data, unsigned long flags)
273 gmx_ana_traj_t *d;
274 int rc;
276 snew(d, 1);
278 d->nrefgrps = 0;
279 d->nanagrps = 1;
280 d->frflags = TRX_NEED_X;
281 d->bRmPBC = TRUE;
282 d->bPBC = TRUE;
284 d->trjfile = NULL;
285 d->topfile = NULL;
286 d->ndxfile = NULL;
287 d->selfile = NULL;
288 d->selection = NULL;
290 d->top = NULL;
291 d->bTop = FALSE;
292 d->xtop = NULL;
293 d->ePBC = -1;
294 d->fr = NULL;
295 d->nframes = 0;
297 d->ngrps = 0;
298 d->sel = NULL;
299 d->grpnames = NULL;
301 d->flags = flags;
302 d->topfile_notnull = NULL;
303 rc = gmx_ana_poscalc_coll_create(&d->pcc);
304 if (rc != 0)
306 sfree(d);
307 *data = NULL;
308 return rc;
310 rc = gmx_ana_selcollection_create(&d->sc, d->pcc);
311 if (rc != 0)
313 gmx_ana_poscalc_coll_free(d->pcc);
314 sfree(d);
315 *data = NULL;
316 return rc;
318 d->status = -1;
319 d->oenv = NULL;
321 *data = d;
322 return 0;
326 * \param d Trajectory analysis data to free.
328 void
329 gmx_ana_traj_free(gmx_ana_traj_t *d)
331 int i;
333 if (d->top)
335 done_top(d->top);
336 sfree(d->top);
338 if (d->fr)
340 /* Gromacs does not seem to have a function for freeing frame data */
341 sfree(d->fr->x);
342 sfree(d->fr->v);
343 sfree(d->fr->f);
344 sfree(d->fr);
346 sfree(d->xtop);
347 sfree(d->sel);
348 gmx_ana_selcollection_free(d->sc);
349 gmx_ana_poscalc_coll_free(d->pcc);
350 sfree(d->grpnames);
351 sfree(d);
355 * \param[in,out] d Trajectory analysis data structure.
356 * \param[in] flags Additional flags to set.
357 * \returns 0 on success, a non-zero error code on error.
359 * Currently there are no checks whether the flags make sense or not.
362 gmx_ana_add_flags(gmx_ana_traj_t *d, unsigned long flags)
364 d->flags |= flags;
365 return 0;
369 * \param[in,out] d Trajectory analysis data structure.
370 * \param[in] bPBC TRUE if periodic boundary conditions should be used.
371 * \returns 0 on success.
373 * If this function is called before parse_trjana_args(), it sets the default
374 * for whether PBC are used in the analysis or not.
375 * If \ref ANA_NOUSER_PBC is not set, a command-line option is provided for the
376 * user to override the default value.
377 * If called after parse_trjana_args(), it overrides the setting provided by
378 * the user or an earlier call.
380 * If this function is not called, the default is to use PBC.
382 * If PBC are not used, the \p pbc pointer passed to gmx_analysisfunc()
383 * is NULL.
385 * \see \ref ANA_NOUSER_PBC
388 gmx_ana_set_pbc(gmx_ana_traj_t *d, bool bPBC)
390 d->bPBC = bPBC;
391 return 0;
395 * \param[in] d Trajectory analysis data structure.
396 * \returns TRUE if periodic boundary conditions are set to be used.
398 bool
399 gmx_ana_has_pbc(gmx_ana_traj_t *d)
401 return d->bPBC;
405 * \param[in,out] d Trajectory analysis data structure.
406 * \param[in] bRmPBC TRUE if molecules should be made whole.
407 * \returns 0 on success.
409 * If this function is called before parse_trjana_args(), it sets the default
410 * for whether molecules are made whole.
411 * If \ref ANA_NOUSER_RMPBC is not set, a command-line option is provided for
412 * the user to override the default value.
413 * If called after parse_trjana_args(), it overrides the setting provided by
414 * the user or an earlier call.
416 * If this function is not called, the default is to make molecules whole.
418 * The main use of this function is to call it with FALSE if your analysis
419 * program does not require whole molecules as this can increase the
420 * performance.
421 * In such a case, you can also specify \ref ANA_NOUSER_RMPBC to not to
422 * confuse the user with an option that would only slow the program
423 * down.
425 * \see \ref ANA_NOUSER_RMPBC
428 gmx_ana_set_rmpbc(gmx_ana_traj_t *d, bool bRmPBC)
430 d->bRmPBC = bRmPBC;
431 return 0;
435 * \param[in,out] d Trajectory analysis data structure.
436 * \param[in] frflags Flags for what to read from the trajectory file.
437 * \returns 0 on success, an error code on error.
439 * The TRX_NEED_X flag is always set.
440 * If the analysis tools needs some other information (velocities, forces),
441 * it can call this function to load additional information from the
442 * trajectory.
445 gmx_ana_set_frflags(gmx_ana_traj_t *d, int frflags)
447 if (d->fr)
449 gmx_call("cannot set trajectory flags after the first frame has been read");
450 return -1;
452 frflags |= TRX_NEED_X;
453 d->frflags = frflags;
454 return 0;
458 * \param[in,out] d Trajectory analysis data structure.
459 * \param[in] nrefgrps Number of reference groups required.
460 * \returns 0 on success, a non-zero error code on error.
462 * \p nrefgrps should be a non-negative integer.
463 * If this function is not called (or \p nrefgrps is 0), all selections are
464 * treated as reference groups.
467 gmx_ana_set_nrefgrps(gmx_ana_traj_t *d, int nrefgrps)
469 if (nrefgrps < 0)
471 d->nrefgrps = 0;
472 gmx_incons("number of reference groups is negative");
473 return EINVAL;
475 d->nrefgrps = nrefgrps;
476 return 0;
480 * \param[in,out] d Trajectory analysis data structure.
481 * \param[in] nanagrps Number of analysis groups required
482 * (-1 stands for any number of analysis groups).
483 * \returns 0 on success, a non-zero error code on error.
485 * \p nanagrps should be a positive integer or -1.
486 * In the latter case, any number of groups (but at least one) is acceptable.
487 * gmx_ana_get_nanagrps() can be used to access the actual value after
488 * gmx_ana_init_selections() has been called.
489 * If this function is not called, a single analysis group is expected.
492 gmx_ana_set_nanagrps(gmx_ana_traj_t *d, int nanagrps)
494 if (nanagrps <= 0 && nanagrps != -1)
496 d->nanagrps = 1;
497 gmx_incons("number of analysis groups is invalid");
498 return EINVAL;
500 d->nanagrps = nanagrps;
501 return 0;
505 * \param[in] d Trajectory analysis data structure.
506 * \param[out] ngrps Total number of selections specified by the user.
507 * \returns 0 on success, a non-zero error code on error.
509 * The value stored in \p *ngrps is the sum of the number of reference groups
510 * and the number of analysis groups.
511 * If a specific number (not -1) of analysis groups has been set with
512 * gmx_ana_set_nanagrps(), the value is always the sum of the values provided
513 * to gmx_ana_set_nrefgrps() and gmx_ana_set_nanagrps().
515 * Should only be called after gmx_ana_init_selections().
518 gmx_ana_get_ngrps(gmx_ana_traj_t *d, int *ngrps)
520 if (d->nanagrps == -1)
522 *ngrps = 0;
523 gmx_call("gmx_ana_init_selections() not called");
524 return EINVAL;
526 *ngrps = d->nrefgrps + d->nanagrps;
527 return 0;
531 * \param[in] d Trajectory analysis data structure.
532 * \param[out] nanagrps Number of analysis groups specified by the user.
533 * \returns 0 on success, a non-zero error code on error.
535 * If a specific number (not -1) of analysis groups has been set with
536 * gmx_ana_set_nanagrps(), the value is always the same value.
537 * Hence, you only need to call this function if gmx_ana_set_nanagrps() has
538 * been called with \p nanagrps set to -1.
540 * Should only be called after gmx_ana_init_selections().
543 gmx_ana_get_nanagrps(gmx_ana_traj_t *d, int *nanagrps)
545 if (d->nanagrps == -1)
547 *nanagrps = 0;
548 gmx_call("gmx_ana_init_selections() not called");
549 return EINVAL;
551 *nanagrps = d->nanagrps;
552 return 0;
556 * \param[in] d Trajectory analysis data structure.
557 * \param[in] i Ordinal number of the reference selection to get.
558 * \param[out] sel Selection object for the \p i'th reference group.
559 * \returns 0 on success, a non-zero error code on error.
561 * The pointer returned in \p *sel should not be freed.
562 * Should only be called after gmx_ana_init_selections().
565 gmx_ana_get_refsel(gmx_ana_traj_t *d, int i, gmx_ana_selection_t **sel)
567 if (i < 0 || i >= d->nrefgrps)
569 *sel = NULL;
570 gmx_call("invalid reference group number");
571 return EINVAL;
573 *sel = gmx_ana_selcollection_get_selection(d->sc, i);
574 if (!*sel)
576 gmx_incons("gmx_ana_init_selections() not called");
577 return EINVAL;
579 return 0;
583 * \param[in] d Trajectory analysis data structure.
584 * \param[out] sel Array of analysis selections.
585 * \returns 0 on success, a non-zero error code on error.
587 * The pointer returned in \p *sel should not be freed.
588 * Should only be called after gmx_ana_init_selections().
591 gmx_ana_get_anagrps(gmx_ana_traj_t *d, gmx_ana_selection_t ***sel)
593 if (!d->sel)
595 *sel = NULL;
596 gmx_incons("gmx_ana_init_selections() not called");
597 return EINVAL;
599 *sel = d->sel;
600 return 0;
604 * \param[in] d Trajectory analysis data structure.
605 * \param[out] grpnames Array of selection names.
606 * \returns 0 on success, a non-zero error code on error.
608 * The pointer returned in \p *grpnames should not be freed.
609 * Should only be called after gmx_ana_init_selections().
612 gmx_ana_get_grpnames(gmx_ana_traj_t *d, char ***grpnames)
614 if (!d->grpnames)
616 *grpnames = NULL;
617 gmx_call("gmx_ana_init_selections() not called");
618 return EINVAL;
620 *grpnames = d->grpnames;
621 return 0;
625 * \param[in] d Trajectory analysis data structure.
626 * \param[out] sc Selection collection object.
627 * \returns 0 on success.
629 * This function is mostly useful for debugging purposes.
630 * The information commonly required in analysis programs is accessible
631 * more conveniently through other means.
633 * The pointer returned in \p *sc should not be freed.
634 * Can be called at any point.
637 gmx_ana_get_selcollection(gmx_ana_traj_t *d, gmx_ana_selcollection_t **sc)
639 *sc = d->sc;
640 return 0;
644 * \param[in,out] d Trajectory analysis data structure.
645 * \returns 0 on success, a non-zero error code on error.
647 * This function should be called first in the analysis program, much in
648 * the same way as parse_common_args() in traditional Gromacs analysis
649 * programs. It adds some command-line arguments of its own, and uses
650 * parse_common_args() to parse the command-line arguments.
651 * It also loads topology information if required or if a topology is
652 * provided on the command line.
653 * Selection handling is also initialized if it is enabled and
654 * the user has selected it on the command line.
656 * The rest of the parameters are passed on to the Gromacs routine
657 * parse_common_args(), and the use of this function should be identical
658 * to parse_common_args(), with the exception that for \p pca_flags,
659 * \p PCA_CAN_TIME and \p PCA_BE_NICE flags are automatically added.
660 * \param argc
661 * \param argv
662 * \param pca_flags
663 * \param nfile
664 * \param fnm
665 * \param npargs
666 * \param pa
667 * \param ndesc
668 * \param desc
669 * \param nbugs
670 * \param bugs
671 * \param oenv
674 parse_trjana_args(gmx_ana_traj_t *d,
675 int *argc, char *argv[], unsigned long pca_flags,
676 int nfile, t_filenm fnm[], int npargs, t_pargs *pa,
677 int ndesc, const char **desc,
678 int nbugs, const char **bugs,
679 output_env_t *oenv)
681 t_filenm *all_fnm = NULL;
682 int max_fnm, nfall;
683 int *fnm_map;
684 t_pargs *all_pa = NULL;
685 int max_pa, npall;
686 size_t i;
687 int k;
688 int rc;
690 t_filenm def_fnm[] = {
691 {efTRX, NULL, NULL, ffOPTRD},
692 {efTPS, NULL, NULL, ffREAD},
693 {efDAT, "-sf", "selection", ffOPTRD},
694 {efNDX, NULL, NULL, ffOPTRD},
696 bool bPBC = TRUE;
697 t_pargs pbc_pa[] = {
698 {"-pbc", FALSE, etBOOL, {&bPBC},
699 "Use periodic boundary conditions for distance calculation"},
701 bool bRmPBC = TRUE;
702 t_pargs rmpbc_pa[] = {
703 {"-rmpbc", FALSE, etBOOL, {&bRmPBC},
704 "Make molecules whole for each frame"},
706 char *selection = NULL;
707 const char **rpost = NULL;
708 bool bSelDump = FALSE;
709 t_pargs sel_pa[] = {
710 {"-select", FALSE, etSTR, {&selection},
711 "Selection string (use 'help' for help)"},
712 {"-seldebug", FALSE, etBOOL, {&bSelDump},
713 "HIDDENPrint out the parsed and compiled selection trees"},
715 t_pargs dsel_pa[] = {
716 {"-selrpos", FALSE, etENUM, {NULL},
717 "Selection reference position"},
719 const char **spost = NULL;
720 t_pargs selpt_pa[] = {
721 {"-seltype", FALSE, etENUM, {NULL},
722 "Default analysis positions"},
724 #define MAX_PA asize(sel_pa)+asize(dsel_pa)+5
726 if (d->nrefgrps < 0)
728 gmx_incons("number of reference groups is negative");
729 return EINVAL;
732 if (d->flags & ANA_DEBUG_SELECTION)
734 bSelDump = TRUE;
737 rpost = gmx_ana_poscalc_create_type_enum(!(d->flags & ANA_REQUIRE_WHOLE));
738 if (rpost == NULL)
740 return ENOMEM;
742 spost = gmx_ana_poscalc_create_type_enum(TRUE);
743 if (spost == NULL)
745 sfree(rpost);
746 return ENOMEM;
749 /* Construct the file name argument array */
750 max_fnm = nfile + asize(def_fnm);
751 snew(all_fnm, max_fnm);
752 nfall = 0;
753 if (!(d->flags & ANA_REQUIRE_TOP))
755 def_fnm[1].flag |= ffOPT;
757 snew(fnm_map, nfile);
758 for (k = 0; k < nfile; ++k)
760 fnm_map[k] = -1;
763 for (i = 0; i < asize(def_fnm); ++i)
765 for (k = 0; k < nfile; ++k)
767 if (fnm_map[k] == -1 && def_fnm[i].opt == NULL
768 && fnm[k].opt == NULL && fnm[k].ftp == def_fnm[i].ftp)
770 break;
773 if (k < nfile)
775 fnm_map[k] = nfall;
776 nfall = add_fnmarg(nfall, all_fnm, &(fnm[k]));
778 else
780 nfall = add_fnmarg(nfall, all_fnm, &(def_fnm[i]));
784 for (k = 0; k < nfile; ++k)
786 if (fnm_map[k] == -1)
788 fnm_map[k] = nfall;
789 nfall = add_fnmarg(nfall, all_fnm, &(fnm[k]));
793 /* Construct the argument array */
794 max_pa = npargs + MAX_PA;
795 snew(all_pa, max_pa);
796 npall = 0;
798 if (!(d->flags & ANA_NOUSER_RMPBC))
800 for (i = 0; i < asize(rmpbc_pa); ++i)
802 npall = add_parg(npall, all_pa, &(rmpbc_pa[i]));
805 if (!(d->flags & ANA_NOUSER_PBC))
807 for (i = 0; i < asize(pbc_pa); ++i)
809 npall = add_parg(npall, all_pa, &(pbc_pa[i]));
813 for (i = 0; i < asize(sel_pa); ++i)
815 npall = add_parg(npall, all_pa, &(sel_pa[i]));
817 if (!(d->flags & ANA_NO_DYNSEL))
819 dsel_pa[0].u.c = rpost;
820 for (i = 0; i < asize(dsel_pa); ++i)
822 npall = add_parg(npall, all_pa, &(dsel_pa[i]));
826 if (!(d->flags & ANA_ONLY_ATOMPOS))
828 selpt_pa[0].u.c = spost;
829 for (i = 0; i < asize(selpt_pa); ++i)
831 npall = add_parg(npall, all_pa, &(selpt_pa[i]));
835 for (k = 0; k < npargs; ++k)
837 npall = add_parg(npall, all_pa, &(pa[k]));
840 pca_flags |= PCA_CAN_TIME | PCA_BE_NICE;
841 parse_common_args(argc, argv, pca_flags, nfall, all_fnm, npall, all_pa,
842 ndesc, desc, nbugs, bugs,oenv);
843 d->oenv = *oenv;
845 /* Copy the results back */
846 for (k = 0; k < nfile; ++k)
848 memcpy(&(fnm[k]), &(all_fnm[fnm_map[k]]), sizeof(fnm[k]));
850 for (i = 0, k = npall - npargs; i < (size_t)npargs; ++i, ++k)
852 memcpy(&(pa[i]), &(all_pa[k]), sizeof(pa[i]));
855 d->trjfile = ftp2fn_null(efTRX, nfall, all_fnm);
856 d->topfile = ftp2fn_null(efTPS, nfall, all_fnm);
857 d->topfile_notnull = ftp2fn(efTPS, nfall, all_fnm);
858 d->ndxfile = ftp2fn_null(efNDX, nfall, all_fnm);
859 if (!(d->flags & ANA_NOUSER_RMPBC))
861 d->bRmPBC = bRmPBC;
863 if (!(d->flags & ANA_NOUSER_PBC))
865 d->bPBC = bPBC;
867 d->selection = selection;
868 d->selfile = opt2fn_null("-sf", nfall, all_fnm);
870 sfree(all_fnm);
871 sfree(fnm_map);
872 sfree(all_pa);
874 if (!(d->flags & ANA_NO_DYNSEL))
876 gmx_ana_selcollection_set_refpostype(d->sc, rpost[0]);
878 else
880 gmx_ana_selcollection_set_refpostype(d->sc, rpost[1]);
882 sfree(rpost);
883 if (bSelDump)
885 d->flags |= ANA_DEBUG_SELECTION;
887 else
889 d->flags &= ~ANA_DEBUG_SELECTION;
892 if (!(d->flags & ANA_ONLY_ATOMPOS))
894 gmx_ana_selcollection_set_outpostype(d->sc, spost[0], d->flags & ANA_USE_POSMASK);
896 else
898 gmx_ana_selcollection_set_outpostype(d->sc, spost[1], d->flags & ANA_USE_POSMASK);
900 sfree(spost);
902 /* Check if the user requested help on selections.
903 * If so, call gmx_ana_init_selections() to print the help and exit. */
904 if (selection && strncmp(selection, "help", 4) == 0)
906 gmx_ana_init_selections(d);
909 /* If no trajectory file is given, we need to set some flags to be able
910 * to prepare a frame from the loaded topology information. Also, check
911 * that a topology is provided. */
912 if (!d->trjfile)
914 if (!d->topfile)
916 gmx_input("No trajectory or topology provided, nothing to do!");
917 return -1;
919 d->flags |= ANA_REQUIRE_TOP;
920 d->flags |= ANA_USE_TOPX;
923 /* Load the topology if so requested. */
924 rc = load_topology(d, (d->flags & ANA_REQUIRE_TOP));
925 if (rc != 0)
927 return rc;
930 /* Initialize the selections/index groups */
931 if (!(d->flags & ANA_USER_SELINIT))
933 rc = gmx_ana_init_selections(d);
936 return rc;
940 * \param[in,out] d Trajectory analysis data structure.
941 * \param[in] bReq If TRUE, topology loading is forced.
942 * \returns 0 on success, a non-zero error code on error.
944 * Initializes the \c gmx_ana_traj_t::top, \c gmx_ana_traj_t::bTop,
945 * \c gmx_ana_traj_t::boxtop and \c gmx_ana_traj_t::ePBC fields of the
946 * analysis structure.
947 * If \p bReq is TRUE, the topology is loaded even if it is not given on
948 * the command line.
950 * The function can be called multiple times safely; extra calls are
951 * ignored.
953 static int load_topology(gmx_ana_traj_t *d, bool bReq)
955 char title[STRLEN];
957 /* Return if topology already loaded */
958 if (d->top)
960 return 0;
963 if (d->topfile || bReq)
965 snew(d->top, 1);
966 d->bTop = read_tps_conf(d->topfile_notnull, title, d->top,
967 &d->ePBC, &d->xtop, NULL, d->boxtop, TRUE);
968 if (!(d->flags & ANA_USE_TOPX))
970 sfree(d->xtop);
971 d->xtop = NULL;
974 return 0;
978 * \param[in] d Trajectory analysis data structure.
979 * \param[in] bReq If TRUE, topology loading is forced.
980 * \param[out] top Topology data pointer to initialize.
981 * \param[out] bTop TRUE if a full tpx file was loaded, FALSE otherwise
982 * (can be NULL, in which case it is not used).
983 * \returns 0 on success, a non-zero error code on error.
985 * If \ref ANA_REQUIRE_TOP has not been specified and \p bReq is FALSE,
986 * the pointer stored in \p *top may be NULL if no topology has been provided
987 * on the command line.
989 * The pointer returned in \p *top should not be freed.
992 gmx_ana_get_topology(gmx_ana_traj_t *d, bool bReq, t_topology **top, bool *bTop)
994 int rc;
996 rc = load_topology(d, bReq);
997 if (rc != 0)
999 *top = NULL;
1000 return rc;
1002 *top = d->top;
1003 if (bTop)
1005 *bTop = d->bTop;
1007 return 0;
1011 * \param[in] d Trajectory analysis data structure.
1012 * \param[out] x Topology data pointer to initialize.
1013 * (can be NULL, in which case it is not used).
1014 * \param[out] box Box size from the topology file
1015 * (can be NULL, in which case it is not used).
1016 * \param[out] ePBC The ePBC field from the topology
1017 * (can be NULL, in which case it is not used).
1018 * \returns 0 on success, a non-zero error code on error.
1020 * If \ref ANA_USE_TOPX has not been specified, the \p x parameter should be
1021 * NULL.
1023 * The pointer returned in \p *x should not be freed.
1026 gmx_ana_get_topconf(gmx_ana_traj_t *d, rvec **x, matrix box, int *ePBC)
1028 if (box)
1030 copy_mat(d->boxtop, box);
1032 if (ePBC)
1034 *ePBC = d->ePBC;
1036 if (x)
1038 if (!(d->flags & ANA_USE_TOPX))
1040 gmx_incons("topology coordinates requested by ANA_USE_TOPX not set");
1041 *x = NULL;
1042 return EINVAL;
1044 *x = d->xtop;
1046 return 0;
1049 /*! \brief
1050 * Loads default index groups from a selection file.
1052 * \param[in,out] d Trajectory analysis data structure.
1053 * \param[out] grps Pointer to receive the default groups.
1054 * \returns 0 on success, a non-zero error code on error.
1056 static int
1057 init_default_selections(gmx_ana_traj_t *d, gmx_ana_indexgrps_t **grps)
1059 gmx_ana_selcollection_t *sc;
1060 char *fnm;
1061 int nr, nr_notempty, i;
1062 int rc;
1064 /* If an index file is provided, just load it and exit. */
1065 if (d->ndxfile)
1067 gmx_ana_indexgrps_init(grps, d->top, d->ndxfile);
1068 return 0;
1070 /* Initialize groups to NULL if we return prematurely. */
1071 *grps = NULL;
1072 /* Return immediately if no topology provided. */
1073 if (!d->top)
1075 return 0;
1078 /* Find the default selection file, return if none found. */
1079 fnm = low_libfn("defselection.dat", FALSE);
1080 if (fnm == NULL)
1082 return 0;
1085 /* Create a temporary selection collection. */
1086 rc = gmx_ana_selcollection_create(&sc, d->pcc);
1087 if (rc != 0)
1089 sfree(fnm);
1090 return rc;
1092 rc = gmx_ana_selmethod_register_defaults(sc);
1093 if (rc != 0)
1095 gmx_ana_selcollection_free(sc);
1096 sfree(fnm);
1097 gmx_fatal(FARGS, "default selection method registration failed");
1098 return rc;
1100 /* FIXME: It would be better to not have the strings here hard-coded. */
1101 gmx_ana_selcollection_set_refpostype(sc, "atom");
1102 gmx_ana_selcollection_set_outpostype(sc, "atom", FALSE);
1104 /* Parse and compile the file with no external groups. */
1105 rc = gmx_ana_selcollection_parse_file(sc, fnm, NULL);
1106 sfree(fnm);
1107 if (rc != 0)
1109 gmx_ana_selcollection_free(sc);
1110 fprintf(stderr, "\nWARNING: default selection(s) could not be parsed\n");
1111 return rc;
1113 gmx_ana_selcollection_set_topology(sc, d->top, -1);
1114 rc = gmx_ana_selcollection_compile(sc);
1115 if (rc != 0)
1117 gmx_ana_selcollection_free(sc);
1118 fprintf(stderr, "\nWARNING: default selection(s) could not be compiled\n");
1119 return rc;
1122 /* Count the non-empty groups and check that there are no dynamic
1123 * selections. */
1124 nr = gmx_ana_selcollection_get_count(sc);
1125 nr_notempty = 0;
1126 for (i = 0; i < nr; ++i)
1128 gmx_ana_selection_t *sel;
1130 sel = gmx_ana_selcollection_get_selection(sc, i);
1131 if (sel->bDynamic)
1133 fprintf(stderr, "\nWARNING: dynamic default selection ignored\n");
1135 else if (sel->g->isize > 0)
1137 ++nr_notempty;
1141 /* Copy the groups to the output structure */
1142 gmx_ana_indexgrps_alloc(grps, nr_notempty);
1143 nr_notempty = 0;
1144 for (i = 0; i < nr; ++i)
1146 gmx_ana_selection_t *sel;
1148 sel = gmx_ana_selcollection_get_selection(sc, i);
1149 if (!sel->bDynamic && sel->g->isize > 0)
1151 gmx_ana_index_t *g;
1153 g = gmx_ana_indexgrps_get_grp(*grps, nr_notempty);
1154 gmx_ana_index_copy(g, sel->g, TRUE);
1155 g->name = strdup(sel->name);
1156 ++nr_notempty;
1160 gmx_ana_selcollection_free(sc);
1161 return 0;
1165 * \param[in,out] d Trajectory analysis data structure.
1166 * \returns 0 on success, a non-zero error code on error.
1168 * Initializes the selection data in \c gmx_ana_traj_t based on
1169 * the selection options and/or index files provided on the command line.
1171 * This function is called automatically by parse_trjana_args() and should
1172 * not be called directly unless \ref ANA_USER_SELINIT is specified.
1174 * \see ANA_USER_SELINIT
1177 gmx_ana_init_selections(gmx_ana_traj_t *d)
1179 int rc;
1180 int i;
1181 int nr;
1182 gmx_ana_indexgrps_t *grps;
1183 int natoms;
1184 bool bStdIn;
1185 bool bInteractive;
1186 bool bOk;
1188 if (d->sel)
1190 gmx_call("init_selections called more than once\n"
1191 "perhaps you forgot ANA_USER_SELINIT");
1192 return -1;
1195 /* Check if we need some information from the topology */
1196 if (gmx_ana_selcollection_requires_top(d->sc))
1198 rc = load_topology(d, TRUE);
1199 if (rc != 0)
1201 return rc;
1204 /* Initialize the default selection methods */
1205 rc = gmx_ana_selmethod_register_defaults(d->sc);
1206 if (rc != 0)
1208 gmx_fatal(FARGS, "default selection method registration failed");
1209 return rc;
1211 /* Initialize index groups.
1212 * We ignore the return value to continue without the default groups if
1213 * there is an error there. */
1214 init_default_selections(d, &grps);
1215 /* Parse the selections */
1216 bStdIn = (d->selfile && d->selfile[0] == '-' && d->selfile[1] == 0)
1217 || (d->selection && d->selection[0] == 0)
1218 || (!d->selfile && !d->selection);
1219 /* Behavior is not very pretty if we cannot check for interactive input,
1220 * but at least it should compile and work in most cases. */
1221 #ifdef HAVE_UNISTD_H
1222 bInteractive = bStdIn && isatty(fileno(stdin));
1223 #else
1224 bInteractive = bStdIn;
1225 #endif
1226 if (bStdIn && bInteractive)
1228 /* Parse from stdin */
1229 /* First we parse the reference groups if there are any */
1230 if (d->nrefgrps > 0)
1232 fprintf(stderr, "\nSpecify ");
1233 if (d->nrefgrps == 1)
1235 fprintf(stderr, "a reference selection");
1237 else
1239 fprintf(stderr, "%d reference selections", d->nrefgrps);
1241 fprintf(stderr, ":\n");
1242 fprintf(stderr, "(one selection per line, use \\ for line continuation)\n");
1243 rc = gmx_ana_selcollection_parse_stdin(d->sc, d->nrefgrps, grps, TRUE);
1244 nr = gmx_ana_selcollection_get_count(d->sc);
1245 if (rc != 0 || nr != d->nrefgrps)
1247 gmx_ana_traj_free(d);
1248 gmx_input("unrecoverable error in selection parsing");
1249 return rc;
1252 /* Then, we parse the analysis groups */
1253 fprintf(stderr, "\nSpecify ");
1254 if (d->nanagrps == 1)
1256 fprintf(stderr, "a selection");
1258 else if (d->nanagrps == -1)
1260 fprintf(stderr, "any number of selections");
1262 else
1264 fprintf(stderr, "%d selections", d->nanagrps);
1266 fprintf(stderr, " for analysis:\n");
1267 fprintf(stderr, "(one selection per line, use \\ for line continuation%s)\n",
1268 d->nanagrps == -1 ? ", Ctrl-D to end" : "");
1269 rc = gmx_ana_selcollection_parse_stdin(d->sc, d->nanagrps, grps, TRUE);
1270 fprintf(stderr, "\n");
1272 else if (bStdIn)
1274 rc = gmx_ana_selcollection_parse_stdin(d->sc, -1, grps, FALSE);
1276 else if (d->selection)
1278 rc = gmx_ana_selcollection_parse_str(d->sc, d->selection, grps);
1280 else
1282 rc = gmx_ana_selcollection_parse_file(d->sc, d->selfile, grps);
1284 if (grps)
1286 gmx_ana_indexgrps_free(grps);
1288 if (rc != 0)
1290 /* Free memory for memory leak checking */
1291 gmx_ana_traj_free(d);
1292 gmx_input("selection(s) could not be parsed");
1293 return rc;
1296 /* Check the number of groups */
1297 nr = gmx_ana_selcollection_get_count(d->sc);
1298 if (nr == 0)
1300 /* TODO: Don't print this if the user has requested help */
1301 fprintf(stderr, "Nothing selected, finishing up.\n");
1302 gmx_ana_traj_free(d);
1303 /* TODO: It would be better to return some code that tells the caller
1304 * that one should exit. */
1305 exit(0);
1307 if (nr <= d->nrefgrps)
1309 gmx_input("selection does not specify enough index groups");
1310 return -1;
1312 if (d->nanagrps <= 0)
1314 d->nanagrps = nr - d->nrefgrps;
1316 else if (nr != d->nrefgrps + d->nanagrps)
1318 gmx_input("selection does not specify the correct number of index groups");
1319 return -1;
1322 if (d->flags & ANA_DEBUG_SELECTION)
1324 gmx_ana_selcollection_print_tree(stderr, d->sc, FALSE);
1326 if (gmx_ana_selcollection_requires_top(d->sc))
1328 rc = load_topology(d, TRUE);
1329 if (rc != 0)
1331 return rc;
1334 if (d->top)
1336 natoms = -1;
1338 else
1340 rc = init_first_frame(d);
1341 if (rc != 0)
1343 return rc;
1345 natoms = d->fr->natoms;
1347 gmx_ana_selcollection_set_topology(d->sc, d->top, natoms);
1348 rc = gmx_ana_selcollection_compile(d->sc);
1349 if (rc != 0)
1351 /* Free memory for memory leak checking */
1352 gmx_ana_traj_free(d);
1353 gmx_input("selection could not be compiled");
1354 return rc;
1356 /* Create the selection array */
1357 d->ngrps = gmx_ana_selcollection_get_count(d->sc);
1358 if (!(d->flags & ANA_USE_FULLGRPS))
1360 d->ngrps -= d->nrefgrps;
1362 snew(d->sel, d->ngrps);
1363 for (i = 0; i < d->ngrps; ++i)
1365 if (d->flags & ANA_USE_FULLGRPS)
1367 d->sel[i] = gmx_ana_selcollection_get_selection(d->sc, i);
1369 else
1371 d->sel[i] = gmx_ana_selcollection_get_selection(d->sc, i + d->nrefgrps);
1374 if (d->flags & ANA_DEBUG_SELECTION)
1376 fprintf(stderr, "\n");
1377 gmx_ana_selcollection_print_tree(stderr, d->sc, FALSE);
1378 fprintf(stderr, "\n");
1379 gmx_ana_poscalc_coll_print_tree(stderr, d->pcc);
1380 fprintf(stderr, "\n");
1383 /* Initialize the position evaluation */
1384 gmx_ana_poscalc_init_eval(d->pcc);
1385 if (d->flags & ANA_DEBUG_SELECTION)
1387 gmx_ana_poscalc_coll_print_tree(stderr, d->pcc);
1388 fprintf(stderr, "\n");
1391 /* Check that dynamic selections are not provided if not allowed */
1392 if (d->flags & ANA_NO_DYNSEL)
1394 for (i = 0; i < d->nrefgrps + d->nanagrps; ++i)
1396 gmx_ana_selection_t *sel;
1398 sel = gmx_ana_selcollection_get_selection(d->sc, i);
1399 if (sel->bDynamic)
1401 gmx_fatal(FARGS, "%s does not support dynamic selections",
1402 ShortProgram());
1403 return -1;
1407 /* Check that non-atom positions are not provided if not allowed.
1408 * TODO: It would be better to have these checks in the parser. */
1409 if (d->flags & ANA_ONLY_ATOMPOS)
1411 for (i = 0; i < d->nanagrps; ++i)
1413 gmx_ana_selection_t *sel;
1415 sel = gmx_ana_selcollection_get_selection(d->sc, i + d->nrefgrps);
1416 if (sel->p.m.type != INDEX_ATOM)
1418 gmx_fatal(FARGS, "%s does not support non-atom positions",
1419 ShortProgram());
1420 return -1;
1424 /* Create the names array */
1425 snew(d->grpnames, d->ngrps);
1426 for (i = 0; i < d->ngrps; ++i)
1428 d->grpnames[i] = gmx_ana_selection_name(d->sel[i]);
1431 return 0;
1435 * \param[in,out] d Trajectory analysis data structure.
1436 * \param[in] type Type of covered fractions to calculate.
1437 * \returns 0 on success, a non-zero error code on error.
1439 * By default, covered fractions are not calculated.
1440 * If this function is called, the covered fraction calculation is
1441 * initialize to calculate the fractions of type \p type for each selection.
1442 * The function must be called after gmx_ana_init_selections() has been
1443 * called.
1445 * For more fine-grained control of the calculation, you can use
1446 * gmx_ana_selection_init_coverfrac(): if you initialize some selections
1447 * this function to something else than CFRAC_NONE before calling
1448 * gmx_ana_init_coverfrac(), these settings are not overwritten.
1450 * You only need to call this function if your program needs to have
1451 * information about the covered fractions, e.g., for normalization.
1453 * \see gmx_ana_selection_init_coverfrac()
1456 gmx_ana_init_coverfrac(gmx_ana_traj_t *d, e_coverfrac_t type)
1458 int g;
1460 if (type == CFRAC_NONE)
1462 return 0;
1465 for (g = 0; g < d->ngrps; ++g)
1467 if (d->sel[g]->cfractype == CFRAC_NONE)
1469 gmx_ana_selection_init_coverfrac(d->sel[g], type);
1472 return 0;
1476 * \param[in] out Output file.
1477 * \param[in] d Trajectory analysis data structure.
1478 * \returns 0 on success, a non-zero error code on error.
1480 int xvgr_selections(FILE *out, gmx_ana_traj_t *d)
1482 xvgr_selcollection(out, d->sc, d->oenv);
1483 return 0;
1487 * \param[in,out] d Trajectory analysis data structure.
1488 * \returns 0 on success, a non-zero error code on error.
1490 static int init_first_frame(gmx_ana_traj_t *d)
1492 int i;
1494 /* Return if we have already initialized the trajectory */
1495 if (d->fr)
1497 return 0;
1500 d->frflags |= TRX_NEED_X;
1502 snew(d->fr, 1);
1504 if (d->trjfile)
1506 if (!read_first_frame(d->oenv, &d->status, d->trjfile, d->fr, d->frflags))
1508 gmx_input("could not read coordinates from trajectory");
1509 return EIO;
1512 if (d->top && d->fr->natoms > d->top->atoms.nr)
1514 gmx_fatal(FARGS, "Trajectory (%d atoms) does not match topology (%d atoms)",
1515 d->fr->natoms, d->top->atoms.nr);
1516 return -1;
1518 /* check index groups */
1519 for (i = 0; i < d->ngrps; ++i)
1521 gmx_ana_index_check(d->sel[i]->g, d->fr->natoms);
1524 else
1526 /* Prepare a frame from topology information */
1527 /* TODO: Initialize more of the fields */
1528 if (d->frflags & (TRX_NEED_V))
1530 gmx_impl("Velocity reading from a topology not implemented");
1531 return -1;
1533 if (d->frflags & (TRX_NEED_F))
1535 gmx_input("Forces cannot be read from a topology");
1536 return -1;
1538 d->fr->flags = d->frflags;
1539 d->fr->natoms = d->top->atoms.nr;
1540 d->fr->bX = TRUE;
1541 snew(d->fr->x, d->fr->natoms);
1542 memcpy(d->fr->x, d->xtop, sizeof(*d->fr->x)*d->fr->natoms);
1543 d->fr->bBox = TRUE;
1544 copy_mat(d->boxtop, d->fr->box);
1547 set_trxframe_ePBC(d->fr, d->ePBC);
1549 return 0;
1553 * \param[in,out] d Trajectory analysis data structure.
1554 * \param[out] fr First frame in the trajectory.
1555 * \returns 0 on success, a non-zero error code on error.
1557 * The pointer stored in \p *fr should not be freed by the caller.
1559 * You only need to call this function if your program needs to do some
1560 * initialization for which it requires data from the first frame.
1562 * \see gmx_ana_do()
1564 int gmx_ana_get_first_frame(gmx_ana_traj_t *d, t_trxframe **fr)
1566 int rc;
1568 rc = init_first_frame(d);
1569 if (rc != 0)
1571 *fr = NULL;
1572 return rc;
1574 *fr = d->fr;
1575 return 0;
1579 * \param[in,out] d Trajectory analysis data structure.
1580 * \param[in] flags Combination of flags
1581 * (currently, there are no flags defined).
1582 * \param[in] analyze Pointer to frame analysis function.
1583 * \param data User data to be passed to \p analyze.
1584 * \returns 0 on success, a non-zero error code on error.
1586 * This function performs the actual analysis of the trajectory.
1587 * It loops through all the frames in the trajectory, and calls
1588 * \p analyze for each frame to perform the actual analysis.
1589 * Before calling \p analyze, selections are updated (if there are any).
1590 * See gmx_analysisfunc() for description of \p analyze parameters.
1592 * This function also calculates the number of frames during the run.
1594 int gmx_ana_do(gmx_ana_traj_t *d, int flags, gmx_analysisfunc analyze, void *data)
1596 t_pbc pbc;
1597 t_pbc *ppbc;
1598 int rc;
1600 rc = init_first_frame(d);
1601 if (rc != 0)
1603 return rc;
1606 ppbc = d->bPBC ? &pbc : 0;
1607 if (!d->top)
1609 d->bRmPBC = FALSE;
1612 d->nframes = 0;
1615 if (d->bRmPBC)
1617 rm_pbc(&d->top->idef, d->ePBC, d->fr->natoms, d->fr->box,
1618 d->fr->x, d->fr->x);
1620 if (ppbc)
1622 set_pbc(&pbc, d->ePBC, d->fr->box);
1625 gmx_ana_poscalc_init_frame(d->pcc);
1626 rc = gmx_ana_selcollection_evaluate(d->sc, d->fr, ppbc);
1627 if (rc != 0)
1629 close_trj(d->status);
1630 gmx_fatal(FARGS, "selection evaluation failed");
1631 return rc;
1633 rc = analyze(d->top, d->fr, ppbc, d->ngrps, d->sel, data);
1634 if (rc != 0)
1636 close_trj(d->status);
1637 return rc;
1640 d->nframes++;
1642 while (d->trjfile && read_next_frame(d->oenv, d->status, d->fr));
1644 if (d->trjfile)
1646 close_trj(d->status);
1647 fprintf(stderr, "Analyzed %d frames, last time %.3f\n",
1648 d->nframes, d->fr->time);
1650 else
1652 fprintf(stderr, "Analyzed topology coordinates\n");
1655 /* Restore the maximal groups for dynamic selections */
1656 rc = gmx_ana_selcollection_evaluate_fin(d->sc, d->nframes);
1657 if (rc != 0)
1659 gmx_fatal(FARGS, "selection evaluation failed");
1662 return rc;
1666 * \param[in,out] d Trajectory analysis data structure.
1667 * \param[out] nframes Number of frames.
1668 * \returns 0 on success, a non-zero error code on error.
1670 * If called before gmx_ana_do(), the behavior is currently undefined.
1672 extern int
1673 gmx_ana_get_nframes(gmx_ana_traj_t *d, int *nframes)
1675 *nframes = d->nframes;
1676 return 0;