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