3 * This source code is part of
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
33 * Implements simple keyword selection methods.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36 * \ingroup module_selection
40 #include "gromacs/legacyheaders/macros.h"
42 #include "gromacs/selection/position.h"
43 #include "gromacs/selection/selmethod.h"
44 #include "gromacs/utility/exceptions.h"
46 /** Evaluates the \p all selection keyword. */
48 evaluate_all(t_topology *top, t_trxframe *fr, t_pbc *pbc,
49 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
50 /** Evaluates the \p none selection keyword. */
52 evaluate_none(t_topology *top, t_trxframe *fr, t_pbc *pbc,
53 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
54 /** Evaluates the \p atomnr selection keyword. */
56 evaluate_atomnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
57 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
58 /** Evaluates the \p resnr selection keyword. */
60 evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
61 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
62 /** Evaluates the \p resindex selection keyword. */
64 evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
65 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
66 /** Checks whether molecule information is present in the topology. */
68 check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
69 /** Evaluates the \p molindex selection keyword. */
71 evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
72 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
73 /** Evaluates the \p atomname selection keyword. */
75 evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
76 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
77 /** Evaluates the \p pdbatomname selection keyword. */
79 evaluate_pdbatomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
80 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
81 /** Checks whether atom types are present in the topology. */
83 check_atomtype(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
84 /** Evaluates the \p atomtype selection keyword. */
86 evaluate_atomtype(t_topology *top, t_trxframe *fr, t_pbc *pbc,
87 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
88 /** Evaluates the \p insertcode selection keyword. */
90 evaluate_insertcode(t_topology *top, t_trxframe *fr, t_pbc *pbc,
91 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
92 /** Evaluates the \p chain selection keyword. */
94 evaluate_chain(t_topology *top, t_trxframe *fr, t_pbc *pbc,
95 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
96 /** Evaluates the \p mass selection keyword. */
98 evaluate_mass(t_topology *top, t_trxframe *fr, t_pbc *pbc,
99 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
100 /** Evaluates the \p charge selection keyword. */
102 evaluate_charge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
103 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
104 /** Checks whether PDB info is present in the topology. */
106 check_pdbinfo(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
107 /** Evaluates the \p altloc selection keyword. */
109 evaluate_altloc(t_topology *top, t_trxframe *fr, t_pbc *pbc,
110 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
111 /** Evaluates the \p occupancy selection keyword. */
113 evaluate_occupancy(t_topology *top, t_trxframe *fr, t_pbc *pbc,
114 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
115 /** Evaluates the \p betafactor selection keyword. */
117 evaluate_betafactor(t_topology *top, t_trxframe *fr, t_pbc *pbc,
118 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
119 /** Evaluates the \p resname selection keyword. */
121 evaluate_resname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
122 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
124 /** Evaluates the \p x selection keyword. */
126 evaluate_x(t_topology *top, t_trxframe *fr, t_pbc *pbc,
127 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
128 /** Evaluates the \p y selection keyword. */
130 evaluate_y(t_topology *top, t_trxframe *fr, t_pbc *pbc,
131 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
132 /** Evaluates the \p z selection keyword. */
134 evaluate_z(t_topology *top, t_trxframe *fr, t_pbc *pbc,
135 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
137 /** Help text for atom name selection keywords. */
138 static const char *help_atomname[] = {
139 "ATOM NAME SELECTION KEYWORDS[PAR]",
141 "[TT]name[tt] [TT]pdbname[tt] [TT]atomname[tt] [TT]pdbatomname[tt][PAR]",
143 "These keywords select atoms by name. [TT]name[tt] selects atoms using",
144 "the Gromacs atom naming convention.",
145 "For input formats other than PDB, the atom names are matched exactly",
146 "as they appear in the input file. For PDB files, 4 character atom names",
147 "that start with a digit are matched after moving the digit to the end",
148 "(e.g., to match 3HG2 from a PDB file, use [TT]name HG23[tt]).",
149 "[TT]pdbname[tt] can only be used with a PDB input file, and selects",
150 "atoms based on the exact name given in the input file, without the",
151 "transformation described above.[PAR]",
153 "[TT]atomname[tt] and [TT]pdbatomname[tt] are synonyms for the above two",
157 /** \internal Selection method data for \p all selection keyword. */
158 gmx_ana_selmethod_t sm_all = {
159 "all", GROUP_VALUE, 0,
171 /** \internal Selection method data for \p none selection keyword. */
172 gmx_ana_selmethod_t sm_none = {
173 "none", GROUP_VALUE, 0,
185 /** \internal Selection method data for \p atomnr selection keyword. */
186 gmx_ana_selmethod_t sm_atomnr = {
187 "atomnr", INT_VALUE, 0,
199 /** \internal Selection method data for \p resnr selection keyword. */
200 gmx_ana_selmethod_t sm_resnr = {
201 "resnr", INT_VALUE, SMETH_REQTOP,
213 /** \internal Selection method data for \p resindex selection keyword. */
214 gmx_ana_selmethod_t sm_resindex = {
215 "resindex", INT_VALUE, SMETH_REQTOP,
227 /** \internal Selection method data for \p molindex selection keyword. */
228 gmx_ana_selmethod_t sm_molindex = {
229 "molindex", INT_VALUE, SMETH_REQTOP,
241 /** \internal Selection method data for \p atomname selection keyword. */
242 gmx_ana_selmethod_t sm_atomname = {
243 "atomname", STR_VALUE, SMETH_REQTOP,
253 {NULL, asize(help_atomname), help_atomname}
256 /** \internal Selection method data for \p pdbatomname selection keyword. */
257 gmx_ana_selmethod_t sm_pdbatomname = {
258 "pdbatomname", STR_VALUE, SMETH_REQTOP,
266 &evaluate_pdbatomname,
268 {NULL, asize(help_atomname), help_atomname}
271 /** \internal Selection method data for \p atomtype selection keyword. */
272 gmx_ana_selmethod_t sm_atomtype = {
273 "atomtype", STR_VALUE, SMETH_REQTOP,
285 /** \internal Selection method data for \p resname selection keyword. */
286 gmx_ana_selmethod_t sm_resname = {
287 "resname", STR_VALUE, SMETH_REQTOP,
299 /** \internal Selection method data for \p chain selection keyword. */
300 gmx_ana_selmethod_t sm_insertcode = {
301 "insertcode", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
309 &evaluate_insertcode,
313 /** \internal Selection method data for \p chain selection keyword. */
314 gmx_ana_selmethod_t sm_chain = {
315 "chain", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
327 /** \internal Selection method data for \p mass selection keyword. */
328 gmx_ana_selmethod_t sm_mass = {
329 "mass", REAL_VALUE, SMETH_REQTOP,
341 /** \internal Selection method data for \p charge selection keyword. */
342 gmx_ana_selmethod_t sm_charge = {
343 "charge", REAL_VALUE, SMETH_REQTOP,
355 /** \internal Selection method data for \p chain selection keyword. */
356 gmx_ana_selmethod_t sm_altloc = {
357 "altloc", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
369 /** \internal Selection method data for \p occupancy selection keyword. */
370 gmx_ana_selmethod_t sm_occupancy = {
371 "occupancy", REAL_VALUE, SMETH_REQTOP,
383 /** \internal Selection method data for \p betafactor selection keyword. */
384 gmx_ana_selmethod_t sm_betafactor = {
385 "betafactor", REAL_VALUE, SMETH_REQTOP,
393 &evaluate_betafactor,
397 /** \internal Selection method data for \p x selection keyword. */
398 gmx_ana_selmethod_t sm_x = {
399 "x", REAL_VALUE, SMETH_DYNAMIC,
411 /** \internal Selection method data for \p y selection keyword. */
412 gmx_ana_selmethod_t sm_y = {
413 "y", REAL_VALUE, SMETH_DYNAMIC,
425 /** \internal Selection method data for \p z selection keyword. */
426 gmx_ana_selmethod_t sm_z = {
427 "z", REAL_VALUE, SMETH_DYNAMIC,
440 * See sel_updatefunc() for description of the parameters.
441 * \p data is not used.
443 * Copies \p g to \p out->u.g.
446 evaluate_all(t_topology *top, t_trxframe *fr, t_pbc *pbc,
447 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
449 gmx_ana_index_copy(out->u.g, g, false);
453 * See sel_updatefunc() for description of the parameters.
454 * \p data is not used.
456 * Returns an empty \p out->u.g.
459 evaluate_none(t_topology *top, t_trxframe *fr, t_pbc *pbc,
460 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
466 * See sel_updatefunc() for description of the parameters.
467 * \p data is not used.
469 * Returns the indices for each atom in \p out->u.i.
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)
478 for (i = 0; i < g->isize; ++i)
480 out->u.i[i] = g->index[i] + 1;
485 * See sel_updatefunc() for description of the parameters.
486 * \p data is not used.
488 * Returns the residue numbers for each atom in \p out->u.i.
491 evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
492 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
498 for (i = 0; i < g->isize; ++i)
500 resind = top->atoms.atom[g->index[i]].resind;
501 out->u.i[i] = top->atoms.resinfo[resind].nr;
506 * See sel_updatefunc() for description of the parameters.
507 * \p data is not used.
509 * Returns the residue indices for each atom in \p out->u.i.
512 evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
513 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
518 for (i = 0; i < g->isize; ++i)
520 out->u.i[i] = top->atoms.atom[g->index[i]].resind + 1;
525 * \param[in] top Topology structure.
526 * \param npar Not used.
527 * \param param Not used.
528 * \param data Not used.
529 * \returns 0 if molecule info is present in the topology, -1 otherwise.
531 * If molecule information is not found, also prints an error message.
534 check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
538 bOk = (top != NULL && top->mols.nr > 0);
541 GMX_THROW(gmx::InconsistentInputError("Molecule information not available in topology"));
546 * See sel_updatefunc() for description of the parameters.
547 * \p data is not used.
549 * Returns the molecule indices for each atom in \p out->u.i.
552 evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
553 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
558 for (i = j = 0; i < g->isize; ++i)
560 while (top->mols.index[j + 1] <= g->index[i]) ++j;
566 * See sel_updatefunc() for description of the parameters.
567 * \p data is not used.
569 * Returns the atom name for each atom in \p out->u.s.
572 evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
573 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
578 for (i = 0; i < g->isize; ++i)
580 out->u.s[i] = *top->atoms.atomname[g->index[i]];
585 * See sel_updatefunc() for description of the parameters.
586 * \p data is not used.
588 * Returns the PDB atom name for each atom in \p out->u.s.
591 evaluate_pdbatomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
592 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
597 for (i = 0; i < g->isize; ++i)
599 char *s = top->atoms.pdbinfo[g->index[i]].atomnm;
600 while (std::isspace(*s))
609 * \param[in] top Topology structure.
610 * \param npar Not used.
611 * \param param Not used.
612 * \param data Not used.
613 * \returns 0 if atom types are present in the topology, -1 otherwise.
615 * If the atom types are not found, also prints an error message.
618 check_atomtype(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
622 bOk = (top != NULL && top->atoms.atomtype != NULL);
625 GMX_THROW(gmx::InconsistentInputError("Atom types not available in topology"));
630 * See sel_updatefunc() for description of the parameters.
631 * \p data is not used.
633 * Returns the atom type for each atom in \p out->u.s.
634 * Segfaults if atom types are not found in the topology.
637 evaluate_atomtype(t_topology *top, t_trxframe *fr, t_pbc *pbc,
638 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
643 for (i = 0; i < g->isize; ++i)
645 out->u.s[i] = *top->atoms.atomtype[g->index[i]];
650 * See sel_updatefunc() for description of the parameters.
651 * \p data is not used.
653 * Returns the residue name for each atom in \p out->u.s.
656 evaluate_resname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
657 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
663 for (i = 0; i < g->isize; ++i)
665 resind = top->atoms.atom[g->index[i]].resind;
666 out->u.s[i] = *top->atoms.resinfo[resind].name;
671 * See sel_updatefunc() for description of the parameters.
672 * \p data is not used.
674 * Returns the insertion code for each atom in \p out->u.s.
677 evaluate_insertcode(t_topology *top, t_trxframe *fr, t_pbc *pbc,
678 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
684 for (i = 0; i < g->isize; ++i)
686 resind = top->atoms.atom[g->index[i]].resind;
687 out->u.s[i][0] = top->atoms.resinfo[resind].ic;
692 * See sel_updatefunc() for description of the parameters.
693 * \p data is not used.
695 * Returns the chain for each atom in \p out->u.s.
698 evaluate_chain(t_topology *top, t_trxframe *fr, t_pbc *pbc,
699 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
705 for (i = 0; i < g->isize; ++i)
707 resind = top->atoms.atom[g->index[i]].resind;
708 out->u.s[i][0] = top->atoms.resinfo[resind].chainid;
713 * See sel_updatefunc() for description of the parameters.
714 * \p data is not used.
716 * Returns the mass for each atom in \p out->u.r.
719 evaluate_mass(t_topology *top, t_trxframe *fr, t_pbc *pbc,
720 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
725 for (i = 0; i < g->isize; ++i)
727 out->u.r[i] = top->atoms.atom[g->index[i]].m;
732 * See sel_updatefunc() for description of the parameters.
733 * \p data is not used.
735 * Returns the charge for each atom in \p out->u.r.
738 evaluate_charge(t_topology *top, t_trxframe *fr, t_pbc *pbc,
739 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
744 for (i = 0; i < g->isize; ++i)
746 out->u.r[i] = top->atoms.atom[g->index[i]].q;
751 * \param[in] top Topology structure.
752 * \param npar Not used.
753 * \param param Not used.
754 * \param data Not used.
755 * \returns 0 if PDB info is present in the topology, -1 otherwise.
757 * If PDB info is not found, also prints an error message.
760 check_pdbinfo(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
764 bOk = (top != NULL && top->atoms.pdbinfo != NULL);
767 GMX_THROW(gmx::InconsistentInputError("PDB info not available in topology"));
772 * See sel_updatefunc() for description of the parameters.
773 * \p data is not used.
775 * Returns the alternate location identifier for each atom in \p out->u.s.
778 evaluate_altloc(t_topology *top, t_trxframe *fr, t_pbc *pbc,
779 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
784 for (i = 0; i < g->isize; ++i)
786 out->u.s[i][0] = top->atoms.pdbinfo[g->index[i]].altloc;
791 * See sel_updatefunc() for description of the parameters.
792 * \p data is not used.
794 * Returns the occupancy numbers for each atom in \p out->u.r.
795 * Segfaults if PDB info is not found in the topology.
798 evaluate_occupancy(t_topology *top, t_trxframe *fr, t_pbc *pbc,
799 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
804 for (i = 0; i < g->isize; ++i)
806 out->u.r[i] = top->atoms.pdbinfo[g->index[i]].occup;
811 * See sel_updatefunc() for description of the parameters.
812 * \p data is not used.
814 * Returns the B-factors for each atom in \p out->u.r.
815 * Segfaults if PDB info is not found in the topology.
818 evaluate_betafactor(t_topology *top, t_trxframe *fr, t_pbc *pbc,
819 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
824 for (i = 0; i < g->isize; ++i)
826 out->u.r[i] = top->atoms.pdbinfo[g->index[i]].bfac;
831 * Internal utility function for position keyword evaluation.
833 * \param[in] fr Current frame.
834 * \param[in] g Index group for which the coordinates should be evaluated.
835 * \param[out] out Output array.
836 * \param[in] pos Position data to use instead of atomic coordinates
838 * \param[in] d Coordinate index to evaluate (\p XX, \p YY or \p ZZ).
840 * This function is used internally by evaluate_x(), evaluate_y() and
841 * evaluate_z() to do the actual evaluation.
844 evaluate_coord(t_trxframe *fr, gmx_ana_index_t *g, real out[],
845 gmx_ana_pos_t *pos, int d)
852 for (b = 0; b < pos->nr; ++b)
855 for (i = pos->m.mapb.index[b]; i < pos->m.mapb.index[b+1]; ++i)
863 for (i = 0; i < g->isize; ++i)
865 out[i] = fr->x[g->index[i]][d];
871 * See sel_updatefunc_pos() for description of the parameters.
872 * \p data is not used.
874 * Returns the \p x coordinate for each atom in \p out->u.r.
877 evaluate_x(t_topology *top, t_trxframe *fr, t_pbc *pbc,
878 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
880 out->nr = pos->g->isize;
881 evaluate_coord(fr, pos->g, out->u.r, pos, XX);
885 * See sel_updatefunc() for description of the parameters.
886 * \p data is not used.
888 * Returns the \p y coordinate for each atom in \p out->u.r.
891 evaluate_y(t_topology *top, t_trxframe *fr, t_pbc *pbc,
892 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
894 out->nr = pos->g->isize;
895 evaluate_coord(fr, pos->g, out->u.r, pos, YY);
899 * See sel_updatefunc() for description of the parameters.
900 * \p data is not used.
902 * Returns the \p z coordinate for each atom in \p out->u.r.
905 evaluate_z(t_topology *top, t_trxframe *fr, t_pbc *pbc,
906 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data)
908 out->nr = pos->g->isize;
909 evaluate_coord(fr, pos->g, out->u.r, pos, ZZ);