669dda7e9dee6f8cb47de6dc2bb6d7db1456b7e1
[alexxy/gromacs.git] / src / gmxlib / selection / sm_simple.c
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
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.
13
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.
18  *
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.
25  *
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.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \internal \file
32  * \brief Implementations of simple keyword selection methods.
33  */
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include <string2.h>
39 #include <macros.h>
40
41 #include <position.h>
42 #include <selmethod.h>
43
44 /** Evaluates the \p all selection keyword. */
45 static int
46 evaluate_all(t_topology *top, t_trxframe *fr, t_pbc *pbc,
47              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
48 /** Evaluates the \p none selection keyword. */
49 static int
50 evaluate_none(t_topology *top, t_trxframe *fr, t_pbc *pbc,
51               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
52 /** Evaluates the \p atomnr selection keyword. */
53 static int
54 evaluate_atomnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
55                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
56 /** Evaluates the \p resnr selection keyword. */
57 static int
58 evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
59                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
60 /** Evaluates the \p resindex selection keyword. */
61 static int
62 evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
63                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
64 /** Checks whether molecule information is present in the topology. */
65 static int
66 check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
67 /** Evaluates the \p molindex selection keyword. */
68 static int
69 evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
70                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
71 /** Evaluates the \p atomname selection keyword. */
72 static int
73 evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
74                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
75 /** Evaluates the \p pdbatomname selection keyword. */
76 static int
77 evaluate_pdbatomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
78                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
79 /** Checks whether atom types are present in the topology. */
80 static int
81 check_atomtype(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
82 /** Evaluates the \p atomtype selection keyword. */
83 static int
84 evaluate_atomtype(t_topology *top, t_trxframe *fr, t_pbc *pbc,
85                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
86 /** Evaluates the \p insertcode selection keyword. */
87 static int
88 evaluate_insertcode(t_topology *top, t_trxframe *fr, t_pbc *pbc,
89                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
90 /** Evaluates the \p chain selection keyword. */
91 static int
92 evaluate_chain(t_topology *top, t_trxframe *fr, t_pbc *pbc,
93                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
94 /** Evaluates the \p mass selection keyword. */
95 static int
96 evaluate_mass(t_topology *top, t_trxframe *fr, t_pbc *pbc,
97               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
98 /** Evaluates the \p charge selection keyword. */
99 static int
100 evaluate_charge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
101                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
102 /** Checks whether PDB info is present in the topology. */
103 static int
104 check_pdbinfo(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
105 /** Evaluates the \p altloc selection keyword. */
106 static int
107 evaluate_altloc(t_topology *top, t_trxframe *fr, t_pbc *pbc,
108                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
109 /** Evaluates the \p occupancy selection keyword. */
110 static int
111 evaluate_occupancy(t_topology *top, t_trxframe *fr, t_pbc *pbc,
112                    gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
113 /** Evaluates the \p betafactor selection keyword. */
114 static int
115 evaluate_betafactor(t_topology *top, t_trxframe *fr, t_pbc *pbc,
116                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
117 /** Evaluates the \p resname selection keyword. */
118 static int
119 evaluate_resname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
120                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
121
122 /** Evaluates the \p x selection keyword. */
123 static int
124 evaluate_x(t_topology *top, t_trxframe *fr, t_pbc *pbc,
125            gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
126 /** Evaluates the \p y selection keyword. */
127 static int
128 evaluate_y(t_topology *top, t_trxframe *fr, t_pbc *pbc,
129            gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
130 /** Evaluates the \p z selection keyword. */
131 static int
132 evaluate_z(t_topology *top, t_trxframe *fr, t_pbc *pbc,
133            gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
134
135 /** Help text for atom name selection keywords. */
136 static const char *help_atomname[] = {
137     "ATOM NAME SELECTION KEYWORDS[PAR]",
138
139     "[TT]name[tt] [TT]pdbname[tt] [TT]atomname[tt] [TT]pdbatomname[tt][PAR]",
140
141     "These keywords select atoms by name. [TT]name[tt] selects atoms using",
142     "the Gromacs atom naming convention.",
143     "For input formats other than PDB, the atom names are matched exactly",
144     "as they appear in the input file. For PDB files, 4 character atom names",
145     "that start with a digit are matched after moving the digit to the end",
146     "(e.g., to match 3HG2 from a PDB file, use [TT]name HG23[tt]).",
147     "[TT]pdbname[tt] can only be used with a PDB input file, and selects",
148     "atoms based on the exact name given in the input file, without the",
149     "transformation described above.[PAR]",
150
151     "[TT]atomname[tt] and [TT]pdbatomname[tt] are synonyms for the above two",
152     "keywords."
153 };
154
155 /** \internal Selection method data for \p all selection keyword. */
156 gmx_ana_selmethod_t sm_all = {
157     "all", GROUP_VALUE, 0,
158     0, NULL,
159     NULL,
160     NULL,
161     NULL,
162     NULL,
163     NULL,
164     NULL,
165     &evaluate_all,
166     NULL,
167 };
168
169 /** \internal Selection method data for \p none selection keyword. */
170 gmx_ana_selmethod_t sm_none = {
171     "none", GROUP_VALUE, 0,
172     0, NULL,
173     NULL,
174     NULL,
175     NULL,
176     NULL,
177     NULL,
178     NULL,
179     &evaluate_none,
180     NULL,
181 };
182
183 /** \internal Selection method data for \p atomnr selection keyword. */
184 gmx_ana_selmethod_t sm_atomnr = {
185     "atomnr", INT_VALUE, 0,
186     0, NULL,
187     NULL,
188     NULL,
189     NULL,
190     NULL,
191     NULL,
192     NULL,
193     &evaluate_atomnr,
194     NULL,
195 };
196
197 /** \internal Selection method data for \p resnr selection keyword. */
198 gmx_ana_selmethod_t sm_resnr = {
199     "resnr", INT_VALUE, SMETH_REQTOP,
200     0, NULL,
201     NULL,
202     NULL,
203     NULL,
204     NULL,
205     NULL,
206     NULL,
207     &evaluate_resnr,
208     NULL,
209 };
210
211 /** \internal Selection method data for \p resindex selection keyword. */
212 gmx_ana_selmethod_t sm_resindex = {
213     "resindex", INT_VALUE, SMETH_REQTOP,
214     0, NULL,
215     NULL,
216     NULL,
217     NULL,
218     NULL,
219     NULL,
220     NULL,
221     &evaluate_resindex,
222     NULL,
223 };
224
225 /** \internal Selection method data for \p molindex selection keyword. */
226 gmx_ana_selmethod_t sm_molindex = {
227     "molindex", INT_VALUE, SMETH_REQTOP,
228     0, NULL,
229     NULL,
230     NULL,
231     &check_molecules,
232     NULL,
233     NULL,
234     NULL,
235     &evaluate_molindex,
236     NULL,
237 };
238
239 /** \internal Selection method data for \p name selection keyword. */
240 gmx_ana_selmethod_t sm_atomname = {
241     "atomname", STR_VALUE, SMETH_REQTOP,
242     0, NULL,
243     NULL,
244     NULL,
245     NULL,
246     NULL,
247     NULL,
248     NULL,
249     &evaluate_atomname,
250     NULL,
251     {NULL, asize(help_atomname), help_atomname}
252 };
253
254 /** \internal Selection method data for \p pdbatomname selection keyword. */
255 gmx_ana_selmethod_t sm_pdbatomname = {
256     "pdbatomname", STR_VALUE, SMETH_REQTOP,
257     0, NULL,
258     NULL,
259     NULL,
260     &check_pdbinfo,
261     NULL,
262     NULL,
263     NULL,
264     &evaluate_pdbatomname,
265     NULL,
266     {NULL, asize(help_atomname), help_atomname}
267 };
268
269 /** \internal Selection method data for \p type selection keyword. */
270 gmx_ana_selmethod_t sm_atomtype = {
271     "atomtype", STR_VALUE, SMETH_REQTOP,
272     0, NULL,
273     NULL,
274     NULL,
275     &check_atomtype,
276     NULL,
277     NULL,
278     NULL,
279     &evaluate_atomtype,
280     NULL,
281 };
282
283 /** \internal Selection method data for \p resname selection keyword. */
284 gmx_ana_selmethod_t sm_resname = {
285     "resname", STR_VALUE, SMETH_REQTOP,
286     0, NULL,
287     NULL,
288     NULL,
289     NULL,
290     NULL,
291     NULL,
292     NULL,
293     &evaluate_resname,
294     NULL,
295 };
296
297 /** \internal Selection method data for \p chain selection keyword. */
298 gmx_ana_selmethod_t sm_insertcode = {
299     "insertcode", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
300     0, NULL,
301     NULL,
302     NULL,
303     NULL,
304     NULL,
305     NULL,
306     NULL,
307     &evaluate_insertcode,
308     NULL,
309 };
310
311 /** \internal Selection method data for \p chain selection keyword. */
312 gmx_ana_selmethod_t sm_chain = {
313     "chain", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
314     0, NULL,
315     NULL,
316     NULL,
317     NULL,
318     NULL,
319     NULL,
320     NULL,
321     &evaluate_chain,
322     NULL,
323 };
324
325 /** \internal Selection method data for \p mass selection keyword. */
326 gmx_ana_selmethod_t sm_mass = {
327     "mass", REAL_VALUE, SMETH_REQTOP,
328     0, NULL,
329     NULL,
330     NULL,
331     NULL,
332     NULL,
333     NULL,
334     NULL,
335     &evaluate_mass,
336     NULL,
337 };
338
339 /** \internal Selection method data for \p charge selection keyword. */
340 gmx_ana_selmethod_t sm_charge = {
341     "charge", REAL_VALUE, SMETH_REQTOP,
342     0, NULL,
343     NULL,
344     NULL,
345     NULL,
346     NULL,
347     NULL,
348     NULL,
349     &evaluate_charge,
350     NULL,
351 };
352
353 /** \internal Selection method data for \p chain selection keyword. */
354 gmx_ana_selmethod_t sm_altloc = {
355     "altloc", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
356     0, NULL,
357     NULL,
358     NULL,
359     &check_pdbinfo,
360     NULL,
361     NULL,
362     NULL,
363     &evaluate_altloc,
364     NULL,
365 };
366
367 /** \internal Selection method data for \p occupancy selection keyword. */
368 gmx_ana_selmethod_t sm_occupancy = {
369     "occupancy", REAL_VALUE, SMETH_REQTOP,
370     0, NULL,
371     NULL,
372     NULL,
373     &check_pdbinfo,
374     NULL,
375     NULL,
376     NULL,
377     &evaluate_occupancy,
378     NULL,
379 };
380
381 /** \internal Selection method data for \p betafactor selection keyword. */
382 gmx_ana_selmethod_t sm_betafactor = {
383     "betafactor", REAL_VALUE, SMETH_REQTOP,
384     0, NULL,
385     NULL,
386     NULL,
387     &check_pdbinfo,
388     NULL,
389     NULL,
390     NULL,
391     &evaluate_betafactor,
392     NULL,
393 };
394
395 /** \internal Selection method data for \p x selection keyword. */
396 gmx_ana_selmethod_t sm_x = {
397     "x", REAL_VALUE, SMETH_DYNAMIC,
398     0, NULL,
399      NULL,
400      NULL,
401      NULL,
402      NULL,
403      NULL,
404      NULL,
405      NULL,
406     &evaluate_x,
407 };
408
409 /** \internal Selection method data for \p y selection keyword. */
410 gmx_ana_selmethod_t sm_y = {
411     "y", REAL_VALUE, SMETH_DYNAMIC,
412     0, NULL,
413      NULL,
414      NULL,
415      NULL,
416      NULL,
417      NULL,
418      NULL,
419      NULL,
420     &evaluate_y,
421 };
422
423 /** \internal Selection method data for \p z selection keyword. */
424 gmx_ana_selmethod_t sm_z = {
425     "z", REAL_VALUE, SMETH_DYNAMIC,
426     0, NULL,
427      NULL,
428      NULL,
429      NULL,
430      NULL,
431      NULL,
432      NULL,
433      NULL,
434     &evaluate_z,
435 };
436
437 /*!
438  * See sel_updatefunc() for description of the parameters.
439  * \p data is not used.
440  *
441  * Copies \p g to \p out->u.g.
442  */
443 static int
444 evaluate_all(t_topology *top, t_trxframe *fr, t_pbc *pbc,
445              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
446 {
447     gmx_ana_index_copy(out->u.g, g, FALSE);
448     return 0;
449 }
450
451 /*!
452  * See sel_updatefunc() for description of the parameters.
453  * \p data is not used.
454  *
455  * Returns an empty \p out->u.g.
456  */
457 static int
458 evaluate_none(t_topology *top, t_trxframe *fr, t_pbc *pbc,
459               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
460 {
461     out->u.g->isize = 0;
462     return 0;
463 }
464
465 /*!
466  * See sel_updatefunc() for description of the parameters.
467  * \p data is not used.
468  *
469  * Returns the indices for each atom in \p out->u.i.
470  */
471 static int
472 evaluate_atomnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
473                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
474 {
475     int  i;
476
477     out->nr = g->isize;
478     for (i = 0; i < g->isize; ++i)
479     {
480         out->u.i[i] = g->index[i] + 1;
481     }
482     return 0;
483 }
484
485 /*!
486  * See sel_updatefunc() for description of the parameters.
487  * \p data is not used.
488  *
489  * Returns the residue numbers for each atom in \p out->u.i.
490  */
491 static int
492 evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
493                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
494 {
495     int  i;
496     int  resind;
497
498     out->nr = g->isize;
499     for (i = 0; i < g->isize; ++i)
500     {
501         resind = top->atoms.atom[g->index[i]].resind;
502         out->u.i[i] = top->atoms.resinfo[resind].nr;
503     }
504     return 0;
505 }
506
507 /*!
508  * See sel_updatefunc() for description of the parameters.
509  * \p data is not used.
510  *
511  * Returns the residue indices for each atom in \p out->u.i.
512  */
513 static int
514 evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
515                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
516 {
517     int  i;
518
519     out->nr = g->isize;
520     for (i = 0; i < g->isize; ++i)
521     {
522         out->u.i[i] = top->atoms.atom[g->index[i]].resind + 1;
523     }
524     return 0;
525 }
526
527 /*!
528  * \param[in] top  Topology structure.
529  * \param     npar Not used.
530  * \param     param Not used.
531  * \param     data Not used.
532  * \returns   0 if molecule info is present in the topology, -1 otherwise.
533  *
534  * If molecule information is not found, also prints an error message.
535  */
536 static int
537 check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
538 {
539     gmx_bool bOk;
540
541     bOk = (top != NULL && top->mols.nr > 0);
542     if (!bOk)
543     {
544         fprintf(stderr, "Molecule information not available in topology!\n");
545         return -1;
546     }
547     return 0;
548 }
549
550 /*!
551  * See sel_updatefunc() for description of the parameters.
552  * \p data is not used.
553  *
554  * Returns the molecule indices for each atom in \p out->u.i.
555  */
556 static int
557 evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
558                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
559 {
560     int  i, j;
561
562     out->nr = g->isize;
563     for (i = j = 0; i < g->isize; ++i)
564     {
565         while (top->mols.index[j + 1] <= g->index[i]) ++j;
566         out->u.i[i] = j + 1;
567     }
568     return 0;
569 }
570
571 /*!
572  * See sel_updatefunc() for description of the parameters.
573  * \p data is not used.
574  *
575  * Returns the atom name for each atom in \p out->u.s.
576  */
577 static int
578 evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
579                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
580 {
581     int  i;
582
583     out->nr = g->isize;
584     for (i = 0; i < g->isize; ++i)
585     {
586         out->u.s[i] = *top->atoms.atomname[g->index[i]];
587     }
588     return 0;
589 }
590
591 /*!
592  * See sel_updatefunc() for description of the parameters.
593  * \p data is not used.
594  *
595  * Returns the PDB atom name for each atom in \p out->u.s.
596  */
597 static int
598 evaluate_pdbatomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
599                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
600 {
601     int  i;
602
603     out->nr = g->isize;
604     for (i = 0; i < g->isize; ++i)
605     {
606         char *s = top->atoms.pdbinfo[g->index[i]].atomnm;
607         while (isspace(*s))
608         {
609             ++s;
610         }
611         out->u.s[i] = s;
612     }
613     return 0;
614 }
615
616 /*!
617  * \param[in] top  Topology structure.
618  * \param     npar Not used.
619  * \param     param Not used.
620  * \param     data Not used.
621  * \returns   0 if atom types are present in the topology, -1 otherwise.
622  *
623  * If the atom types are not found, also prints an error message.
624  */
625 static int
626 check_atomtype(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
627 {
628     gmx_bool bOk;
629
630     bOk = (top != NULL && top->atoms.atomtype != NULL);
631     if (!bOk)
632     {
633         fprintf(stderr, "Atom types not available in topology!\n");
634         return -1;
635     }
636     return 0;
637 }
638
639 /*!
640  * See sel_updatefunc() for description of the parameters.
641  * \p data is not used.
642  *
643  * Returns the atom type for each atom in \p out->u.s.
644  * Segfaults if atom types are not found in the topology.
645  */
646 static int
647 evaluate_atomtype(t_topology *top, t_trxframe *fr, t_pbc *pbc,
648                   gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
649 {
650     int  i;
651
652     out->nr = g->isize;
653     for (i = 0; i < g->isize; ++i)
654     {
655         out->u.s[i] = *top->atoms.atomtype[g->index[i]];
656     }
657     return 0;
658 }
659
660 /*!
661  * See sel_updatefunc() for description of the parameters.
662  * \p data is not used.
663  *
664  * Returns the residue name for each atom in \p out->u.s.
665  */
666 static int
667 evaluate_resname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
668                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
669 {
670     int  i;
671     int  resind;
672
673     out->nr = g->isize;
674     for (i = 0; i < g->isize; ++i)
675     {
676         resind = top->atoms.atom[g->index[i]].resind;
677         out->u.s[i] = *top->atoms.resinfo[resind].name;
678     }
679     return 0;
680 }
681
682 /*!
683  * See sel_updatefunc() for description of the parameters.
684  * \p data is not used.
685  *
686  * Returns the insertion code for each atom in \p out->u.s.
687  */
688 static int
689 evaluate_insertcode(t_topology *top, t_trxframe *fr, t_pbc *pbc,
690                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
691 {
692     int  i;
693     int  resind;
694
695     out->nr = g->isize;
696     for (i = 0; i < g->isize; ++i)
697     {
698         resind = top->atoms.atom[g->index[i]].resind;
699         out->u.s[i][0] = top->atoms.resinfo[resind].ic;
700     }
701     return 0;
702 }
703
704 /*!
705  * See sel_updatefunc() for description of the parameters.
706  * \p data is not used.
707  *
708  * Returns the chain for each atom in \p out->u.s.
709  */
710 static int
711 evaluate_chain(t_topology *top, t_trxframe *fr, t_pbc *pbc,
712                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
713 {
714     int  i;
715     int  resind;
716
717     out->nr = g->isize;
718     for (i = 0; i < g->isize; ++i)
719     {
720         resind = top->atoms.atom[g->index[i]].resind;
721         out->u.s[i][0] = top->atoms.resinfo[resind].chainid;
722     }
723     return 0;
724 }
725
726 /*!
727  * See sel_updatefunc() for description of the parameters.
728  * \p data is not used.
729  *
730  * Returns the mass for each atom in \p out->u.r.
731  */
732 static int
733 evaluate_mass(t_topology *top, t_trxframe *fr, t_pbc *pbc,
734               gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
735 {
736     int  i;
737
738     out->nr = g->isize;
739     for (i = 0; i < g->isize; ++i)
740     {
741         out->u.r[i] = top->atoms.atom[g->index[i]].m;
742     }
743     return 0;
744 }
745
746 /*!
747  * See sel_updatefunc() for description of the parameters.
748  * \p data is not used.
749  *
750  * Returns the charge for each atom in \p out->u.r.
751  */
752 static int
753 evaluate_charge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
754                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
755 {
756     int  i;
757
758     out->nr = g->isize;
759     for (i = 0; i < g->isize; ++i)
760     {
761         out->u.r[i] = top->atoms.atom[g->index[i]].q;
762     }
763     return 0;
764 }
765
766 /*!
767  * \param[in] top  Topology structure.
768  * \param     npar Not used.
769  * \param     param Not used.
770  * \param     data Not used.
771  * \returns   0 if PDB info is present in the topology, -1 otherwise.
772  *
773  * If PDB info is not found, also prints an error message.
774  */
775 static int
776 check_pdbinfo(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
777 {
778     gmx_bool bOk;
779
780     bOk = (top != NULL && top->atoms.pdbinfo != NULL);
781     if (!bOk)
782     {
783         fprintf(stderr, "PDB info not available in topology!\n");
784         return -1;
785     }
786     return 0;
787 }
788
789 /*!
790  * See sel_updatefunc() for description of the parameters.
791  * \p data is not used.
792  *
793  * Returns the alternate location identifier for each atom in \p out->u.s.
794  */
795 static int
796 evaluate_altloc(t_topology *top, t_trxframe *fr, t_pbc *pbc,
797                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
798 {
799     int  i;
800
801     out->nr = g->isize;
802     for (i = 0; i < g->isize; ++i)
803     {
804         out->u.s[i][0] = top->atoms.pdbinfo[g->index[i]].altloc;
805     }
806     return 0;
807 }
808
809 /*!
810  * See sel_updatefunc() for description of the parameters.
811  * \p data is not used.
812  *
813  * Returns the occupancy numbers for each atom in \p out->u.r.
814  * Segfaults if PDB info is not found in the topology.
815  */
816 static int
817 evaluate_occupancy(t_topology *top, t_trxframe *fr, t_pbc *pbc,
818                    gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
819 {
820     int  i;
821
822     out->nr = g->isize;
823     for (i = 0; i < g->isize; ++i)
824     {
825         out->u.r[i] = top->atoms.pdbinfo[g->index[i]].occup;
826     }
827     return 0;
828 }
829
830 /*!
831  * See sel_updatefunc() for description of the parameters.
832  * \p data is not used.
833  *
834  * Returns the B-factors for each atom in \p out->u.r.
835  * Segfaults if PDB info is not found in the topology.
836  */
837 static int
838 evaluate_betafactor(t_topology *top, t_trxframe *fr, t_pbc *pbc,
839                     gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
840 {
841     int  i;
842
843     out->nr = g->isize;
844     for (i = 0; i < g->isize; ++i)
845     {
846         out->u.r[i] = top->atoms.pdbinfo[g->index[i]].bfac;
847     }
848     return 0;
849 }
850
851 /*! \brief
852  * Internal utility function for position keyword evaluation.
853  *
854  * \param[in]  fr   Current frame.
855  * \param[in]  g    Index group for which the coordinates should be evaluated.
856  * \param[out] out  Output array.
857  * \param[in]  pos  Position data to use instead of atomic coordinates
858  *   (can be NULL).
859  * \param[in]  d    Coordinate index to evaluate (\p XX, \p YY or \p ZZ).
860  *
861  * This function is used internally by evaluate_x(), evaluate_y() and
862  * evaluate_z() to do the actual evaluation.
863  */
864 static void
865 evaluate_coord(t_trxframe *fr, gmx_ana_index_t *g, real out[],
866                gmx_ana_pos_t *pos, int d)
867 {
868     int  b, i;
869     real v;
870
871     if (pos)
872     {
873         for (b = 0; b < pos->nr; ++b)
874         {
875             v = pos->x[b][d];
876             for (i = pos->m.mapb.index[b]; i < pos->m.mapb.index[b+1]; ++i)
877             {
878                 out[i] = v;
879             }
880         }
881     }
882     else
883     {
884         for (i = 0; i < g->isize; ++i)
885         {
886             out[i] = fr->x[g->index[i]][d];
887         }
888     }
889 }
890
891 /*!
892  * See sel_updatefunc_pos() for description of the parameters.
893  * \p data is not used.
894  *
895  * Returns the \p x coordinate for each atom in \p out->u.r.
896  */
897 static int
898 evaluate_x(t_topology *top, t_trxframe *fr, t_pbc *pbc,
899            gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
900 {
901     out->nr = pos->g->isize;
902     evaluate_coord(fr, pos->g, out->u.r, pos, XX);
903     return 0;
904 }
905
906 /*!
907  * See sel_updatefunc() for description of the parameters.
908  * \p data is not used.
909  *
910  * Returns the \p y coordinate for each atom in \p out->u.r.
911  */
912 static int
913 evaluate_y(t_topology *top, t_trxframe *fr, t_pbc *pbc,
914            gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
915 {
916     out->nr = pos->g->isize;
917     evaluate_coord(fr, pos->g, out->u.r, pos, YY);
918     return 0;
919 }
920
921 /*!
922  * See sel_updatefunc() for description of the parameters.
923  * \p data is not used.
924  *
925  * Returns the \p z coordinate for each atom in \p out->u.r.
926  */
927 static int
928 evaluate_z(t_topology *top, t_trxframe *fr, t_pbc *pbc,
929            gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
930 {
931     out->nr = pos->g->isize;
932     evaluate_coord(fr, pos->g, out->u.r, pos, ZZ);
933     return 0;
934 }