Add gmx convert-trj
[gromacs.git] / src / gromacs / selection / sm_simple.cpp
blobc66fe166b993cd24dcbfe138aaf4ba19e4a840ce
1 /*
2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019, by the GROMACS development team, led by
5 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6 * and including many others, as listed in the AUTHORS file in the
7 * top-level source directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
35 /*! \internal \file
36 * \brief
37 * Implements simple keyword selection methods.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_selection
42 #include "gmxpre.h"
44 #include <cctype>
46 #include "gromacs/topology/mtop_lookup.h"
47 #include "gromacs/topology/topology.h"
48 #include "gromacs/utility/arraysize.h"
49 #include "gromacs/utility/exceptions.h"
50 #include "gromacs/utility/gmxassert.h"
52 #include "position.h"
53 #include "selmethod.h"
54 #include "selmethod_impl.h"
56 /** Evaluates the \p all selection keyword. */
57 static void
58 evaluate_all(const gmx::SelMethodEvalContext &context,
59 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
60 /** Evaluates the \p none selection keyword. */
61 static void
62 evaluate_none(const gmx::SelMethodEvalContext &context,
63 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
64 /** Evaluates the \p atomnr selection keyword. */
65 static void
66 evaluate_atomnr(const gmx::SelMethodEvalContext &context,
67 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
68 /** Evaluates the \p resnr selection keyword. */
69 static void
70 evaluate_resnr(const gmx::SelMethodEvalContext &context,
71 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
72 /** Evaluates the \p resindex selection keyword. */
73 static void
74 evaluate_resindex(const gmx::SelMethodEvalContext &context,
75 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
76 /*! \brief
77 * Checks whether molecule information is present in the topology.
79 * \param[in] top Topology structure.
80 * \param npar Not used.
81 * \param param Not used.
82 * \param data Not used.
83 * \returns 0 if molecule info is present in the topology, -1 otherwise.
85 * If molecule information is not found, also prints an error message.
87 static void
88 check_molecules(const gmx_mtop_t *top, int npar, gmx_ana_selparam_t *param, void *data);
89 /** Evaluates the \p molindex selection keyword. */
90 static void
91 evaluate_molindex(const gmx::SelMethodEvalContext &context,
92 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
93 /** Evaluates the \p atomname selection keyword. */
94 static void
95 evaluate_atomname(const gmx::SelMethodEvalContext &context,
96 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
97 /** Evaluates the \p pdbatomname selection keyword. */
98 static void
99 evaluate_pdbatomname(const gmx::SelMethodEvalContext &context,
100 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
101 /*! \brief
102 * Checks whether atom types are present in the topology.
104 * \param[in] top Topology structure.
105 * \param npar Not used.
106 * \param param Not used.
107 * \param data Not used.
109 static void
110 check_atomtype(const gmx_mtop_t *top, int npar, gmx_ana_selparam_t *param, void *data);
111 /** Evaluates the \p atomtype selection keyword. */
112 static void
113 evaluate_atomtype(const gmx::SelMethodEvalContext &context,
114 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
115 /** Evaluates the \p insertcode selection keyword. */
116 static void
117 evaluate_insertcode(const gmx::SelMethodEvalContext &context,
118 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
119 /** Evaluates the \p chain selection keyword. */
120 static void
121 evaluate_chain(const gmx::SelMethodEvalContext &context,
122 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
123 /** Evaluates the \p mass selection keyword. */
124 static void
125 evaluate_mass(const gmx::SelMethodEvalContext &context,
126 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
127 /*! \brief
128 * Checks whether charges are present in the topology.
130 * \param[in] top Topology structure.
131 * \param npar Not used.
132 * \param param Not used.
133 * \param data Not used.
135 static void
136 check_charge(const gmx_mtop_t *top, int npar, gmx_ana_selparam_t *param, void *data);
137 /** Evaluates the \p charge selection keyword. */
138 static void
139 evaluate_charge(const gmx::SelMethodEvalContext &context,
140 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
141 /*! \brief
142 * Checks whether PDB info is present in the topology.
144 * \param[in] top Topology structure.
145 * \param npar Not used.
146 * \param param Not used.
147 * \param data Not used.
148 * \returns 0 if PDB info is present in the topology, -1 otherwise.
150 * If PDB info is not found, also prints an error message.
152 static void
153 check_pdbinfo(const gmx_mtop_t *top, int npar, gmx_ana_selparam_t *param, void *data);
154 /** Evaluates the \p altloc selection keyword. */
155 static void
156 evaluate_altloc(const gmx::SelMethodEvalContext &context,
157 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
158 /** Evaluates the \p occupancy selection keyword. */
159 static void
160 evaluate_occupancy(const gmx::SelMethodEvalContext &context,
161 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
162 /** Evaluates the \p betafactor selection keyword. */
163 static void
164 evaluate_betafactor(const gmx::SelMethodEvalContext &context,
165 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
166 /** Evaluates the \p resname selection keyword. */
167 static void
168 evaluate_resname(const gmx::SelMethodEvalContext &context,
169 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
171 /** Evaluates the \p x selection keyword. */
172 static void
173 evaluate_x(const gmx::SelMethodEvalContext &context,
174 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
175 /** Evaluates the \p y selection keyword. */
176 static void
177 evaluate_y(const gmx::SelMethodEvalContext &context,
178 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
179 /** Evaluates the \p z selection keyword. */
180 static void
181 evaluate_z(const gmx::SelMethodEvalContext &context,
182 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void *data);
184 //! Help title for atom name selection keywords.
185 static const char helptitle_atomname[] = "Selecting atoms by name";
186 //! Help text for atom name selection keywords.
187 static const char *const help_atomname[] = {
188 "::",
190 " name",
191 " pdbname",
192 " atomname",
193 " pdbatomname",
195 "These keywords select atoms by name. [TT]name[tt] selects atoms using",
196 "the GROMACS atom naming convention.",
197 "For input formats other than PDB, the atom names are matched exactly",
198 "as they appear in the input file. For PDB files, 4 character atom names",
199 "that start with a digit are matched after moving the digit to the end",
200 "(e.g., to match 3HG2 from a PDB file, use [TT]name HG23[tt]).",
201 "[TT]pdbname[tt] can only be used with a PDB input file, and selects",
202 "atoms based on the exact name given in the input file, without the",
203 "transformation described above.[PAR]",
205 "[TT]atomname[tt] and [TT]pdbatomname[tt] are synonyms for the above two",
206 "keywords."
209 //! Help title for residue index selection keywords.
210 static const char helptitle_resindex[] = "Selecting atoms by residue number";
211 //! Help text for residue index selection keywords.
212 static const char *const help_resindex[] = {
213 "::",
215 " resnr",
216 " resid",
217 " resindex",
218 " residue",
220 "[TT]resnr[tt] selects atoms using the residue numbering in the input",
221 "file. [TT]resid[tt] is synonym for this keyword for VMD compatibility.",
223 "[TT]resindex N[tt] selects the [TT]N[tt] th residue starting from the",
224 "beginning of the input file. This is useful for uniquely identifying",
225 "residues if there are duplicate numbers in the input file (e.g., in",
226 "multiple chains).",
227 "[TT]residue[tt] is a synonym for [TT]resindex[tt]. This allows",
228 "[TT]same residue as[tt] to work as expected."
231 /** Selection method data for \p all selection keyword. */
232 gmx_ana_selmethod_t sm_all = {
233 "all", GROUP_VALUE, 0,
234 0, nullptr,
235 nullptr,
236 nullptr,
237 nullptr,
238 nullptr,
239 nullptr,
240 nullptr,
241 &evaluate_all,
242 nullptr,
245 /** Selection method data for \p none selection keyword. */
246 gmx_ana_selmethod_t sm_none = {
247 "none", GROUP_VALUE, 0,
248 0, nullptr,
249 nullptr,
250 nullptr,
251 nullptr,
252 nullptr,
253 nullptr,
254 nullptr,
255 &evaluate_none,
256 nullptr,
259 /** Selection method data for \p atomnr selection keyword. */
260 gmx_ana_selmethod_t sm_atomnr = {
261 "atomnr", INT_VALUE, 0,
262 0, nullptr,
263 nullptr,
264 nullptr,
265 nullptr,
266 nullptr,
267 nullptr,
268 nullptr,
269 &evaluate_atomnr,
270 nullptr,
273 /** Selection method data for \p resnr selection keyword. */
274 gmx_ana_selmethod_t sm_resnr = {
275 "resnr", INT_VALUE, SMETH_REQTOP,
276 0, nullptr,
277 nullptr,
278 nullptr,
279 nullptr,
280 nullptr,
281 nullptr,
282 nullptr,
283 &evaluate_resnr,
284 nullptr,
285 {nullptr, helptitle_resindex, asize(help_resindex), help_resindex}
288 /** Selection method data for \p resindex selection keyword. */
289 gmx_ana_selmethod_t sm_resindex = {
290 "resindex", INT_VALUE, SMETH_REQTOP,
291 0, nullptr,
292 nullptr,
293 nullptr,
294 nullptr,
295 nullptr,
296 nullptr,
297 nullptr,
298 &evaluate_resindex,
299 nullptr,
300 {nullptr, helptitle_resindex, asize(help_resindex), help_resindex}
303 /** Selection method data for \p molindex selection keyword. */
304 gmx_ana_selmethod_t sm_molindex = {
305 "molindex", INT_VALUE, SMETH_REQTOP,
306 0, nullptr,
307 nullptr,
308 nullptr,
309 &check_molecules,
310 nullptr,
311 nullptr,
312 nullptr,
313 &evaluate_molindex,
314 nullptr,
317 /** Selection method data for \p atomname selection keyword. */
318 gmx_ana_selmethod_t sm_atomname = {
319 "atomname", STR_VALUE, SMETH_REQTOP,
320 0, nullptr,
321 nullptr,
322 nullptr,
323 nullptr,
324 nullptr,
325 nullptr,
326 nullptr,
327 &evaluate_atomname,
328 nullptr,
329 {nullptr, helptitle_atomname, asize(help_atomname), help_atomname}
332 /** Selection method data for \p pdbatomname selection keyword. */
333 gmx_ana_selmethod_t sm_pdbatomname = {
334 "pdbatomname", STR_VALUE, SMETH_REQTOP,
335 0, nullptr,
336 nullptr,
337 nullptr,
338 &check_pdbinfo,
339 nullptr,
340 nullptr,
341 nullptr,
342 &evaluate_pdbatomname,
343 nullptr,
344 {nullptr, helptitle_atomname, asize(help_atomname), help_atomname}
347 /** Selection method data for \p atomtype selection keyword. */
348 gmx_ana_selmethod_t sm_atomtype = {
349 "atomtype", STR_VALUE, SMETH_REQTOP,
350 0, nullptr,
351 nullptr,
352 nullptr,
353 &check_atomtype,
354 nullptr,
355 nullptr,
356 nullptr,
357 &evaluate_atomtype,
358 nullptr,
361 /** Selection method data for \p resname selection keyword. */
362 gmx_ana_selmethod_t sm_resname = {
363 "resname", STR_VALUE, SMETH_REQTOP,
364 0, nullptr,
365 nullptr,
366 nullptr,
367 nullptr,
368 nullptr,
369 nullptr,
370 nullptr,
371 &evaluate_resname,
372 nullptr,
375 /** Selection method data for \p chain selection keyword. */
376 gmx_ana_selmethod_t sm_insertcode = {
377 "insertcode", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
378 0, nullptr,
379 nullptr,
380 nullptr,
381 nullptr,
382 nullptr,
383 nullptr,
384 nullptr,
385 &evaluate_insertcode,
386 nullptr,
389 /** Selection method data for \p chain selection keyword. */
390 gmx_ana_selmethod_t sm_chain = {
391 "chain", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
392 0, nullptr,
393 nullptr,
394 nullptr,
395 nullptr,
396 nullptr,
397 nullptr,
398 nullptr,
399 &evaluate_chain,
400 nullptr,
403 /** Selection method data for \p mass selection keyword. */
404 gmx_ana_selmethod_t sm_mass = {
405 "mass", REAL_VALUE, SMETH_REQMASS,
406 0, nullptr,
407 nullptr,
408 nullptr,
409 nullptr,
410 nullptr,
411 nullptr,
412 nullptr,
413 &evaluate_mass,
414 nullptr,
417 /** Selection method data for \p charge selection keyword. */
418 gmx_ana_selmethod_t sm_charge = {
419 "charge", REAL_VALUE, SMETH_REQTOP,
420 0, nullptr,
421 nullptr,
422 nullptr,
423 &check_charge,
424 nullptr,
425 nullptr,
426 nullptr,
427 &evaluate_charge,
428 nullptr,
431 /** Selection method data for \p chain selection keyword. */
432 gmx_ana_selmethod_t sm_altloc = {
433 "altloc", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
434 0, nullptr,
435 nullptr,
436 nullptr,
437 &check_pdbinfo,
438 nullptr,
439 nullptr,
440 nullptr,
441 &evaluate_altloc,
442 nullptr,
445 /** Selection method data for \p occupancy selection keyword. */
446 gmx_ana_selmethod_t sm_occupancy = {
447 "occupancy", REAL_VALUE, SMETH_REQTOP,
448 0, nullptr,
449 nullptr,
450 nullptr,
451 &check_pdbinfo,
452 nullptr,
453 nullptr,
454 nullptr,
455 &evaluate_occupancy,
456 nullptr,
459 /** Selection method data for \p betafactor selection keyword. */
460 gmx_ana_selmethod_t sm_betafactor = {
461 "betafactor", REAL_VALUE, SMETH_REQTOP,
462 0, nullptr,
463 nullptr,
464 nullptr,
465 &check_pdbinfo,
466 nullptr,
467 nullptr,
468 nullptr,
469 &evaluate_betafactor,
470 nullptr,
473 /** Selection method data for \p x selection keyword. */
474 gmx_ana_selmethod_t sm_x = {
475 "x", REAL_VALUE, SMETH_DYNAMIC,
476 0, nullptr,
477 nullptr,
478 nullptr,
479 nullptr,
480 nullptr,
481 nullptr,
482 nullptr,
483 nullptr,
484 &evaluate_x,
487 /** Selection method data for \p y selection keyword. */
488 gmx_ana_selmethod_t sm_y = {
489 "y", REAL_VALUE, SMETH_DYNAMIC,
490 0, nullptr,
491 nullptr,
492 nullptr,
493 nullptr,
494 nullptr,
495 nullptr,
496 nullptr,
497 nullptr,
498 &evaluate_y,
501 /** Selection method data for \p z selection keyword. */
502 gmx_ana_selmethod_t sm_z = {
503 "z", REAL_VALUE, SMETH_DYNAMIC,
504 0, nullptr,
505 nullptr,
506 nullptr,
507 nullptr,
508 nullptr,
509 nullptr,
510 nullptr,
511 nullptr,
512 &evaluate_z,
516 * See sel_updatefunc() for description of the parameters.
517 * \p data is not used.
519 * Copies \p g to \p out->u.g.
521 static void
522 evaluate_all(const gmx::SelMethodEvalContext & /*context*/,
523 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
525 gmx_ana_index_copy(out->u.g, g, false);
529 * See sel_updatefunc() for description of the parameters.
530 * \p data is not used.
532 * Returns an empty \p out->u.g.
534 static void
535 evaluate_none(const gmx::SelMethodEvalContext & /*context*/,
536 gmx_ana_index_t * /* g */, gmx_ana_selvalue_t *out, void * /* data */)
538 out->u.g->isize = 0;
542 * See sel_updatefunc() for description of the parameters.
543 * \p data is not used.
545 * Returns the indices for each atom in \p out->u.i.
547 static void
548 evaluate_atomnr(const gmx::SelMethodEvalContext & /*context*/,
549 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
551 int i;
553 out->nr = g->isize;
554 for (i = 0; i < g->isize; ++i)
556 out->u.i[i] = g->index[i] + 1;
561 * See sel_updatefunc() for description of the parameters.
562 * \p data is not used.
564 * Returns the residue numbers for each atom in \p out->u.i.
566 static void
567 evaluate_resnr(const gmx::SelMethodEvalContext &context,
568 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
570 out->nr = g->isize;
571 int molb = 0;
572 for (int i = 0; i < g->isize; ++i)
574 mtopGetAtomAndResidueName(context.top, g->index[i], &molb,
575 nullptr, &out->u.i[i], nullptr, nullptr);
580 * See sel_updatefunc() for description of the parameters.
581 * \p data is not used.
583 * Returns the residue indices for each atom in \p out->u.i.
585 static void
586 evaluate_resindex(const gmx::SelMethodEvalContext &context,
587 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
589 out->nr = g->isize;
590 int molb = 0;
591 for (int i = 0; i < g->isize; ++i)
593 int resind;
594 mtopGetAtomAndResidueName(context.top, g->index[i], &molb,
595 nullptr, nullptr, nullptr, &resind);
596 out->u.i[i] = resind + 1;
600 static void
601 check_molecules(const gmx_mtop_t *top, int /* npar */, gmx_ana_selparam_t * /* param */, void * /* data */)
603 bool bOk;
605 bOk = (top != nullptr && top->haveMoleculeIndices);
606 if (!bOk)
608 GMX_THROW(gmx::InconsistentInputError("Molecule information not available in topology"));
613 * See sel_updatefunc() for description of the parameters.
614 * \p data is not used.
616 * Returns the molecule indices for each atom in \p out->u.i.
618 static void
619 evaluate_molindex(const gmx::SelMethodEvalContext &context,
620 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
622 out->nr = g->isize;
623 int molb = 0;
624 for (int i = 0; i < g->isize; ++i)
626 out->u.i[i] = mtopGetMoleculeIndex(context.top, g->index[i], &molb) + 1;
631 * See sel_updatefunc() for description of the parameters.
632 * \p data is not used.
634 * Returns the atom name for each atom in \p out->u.s.
636 static void
637 evaluate_atomname(const gmx::SelMethodEvalContext &context,
638 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
640 out->nr = g->isize;
641 int molb = 0;
642 for (int i = 0; i < g->isize; ++i)
644 const char *atom_name;
645 mtopGetAtomAndResidueName(context.top, g->index[i], &molb,
646 &atom_name, nullptr, nullptr, nullptr);
647 out->u.s[i] = const_cast<char *>(atom_name);
652 * See sel_updatefunc() for description of the parameters.
653 * \p data is not used.
655 * Returns the PDB atom name for each atom in \p out->u.s.
657 static void
658 evaluate_pdbatomname(const gmx::SelMethodEvalContext &context,
659 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
661 out->nr = g->isize;
662 int molb = 0;
663 for (int i = 0; i < g->isize; ++i)
665 const char *s = mtopGetAtomPdbInfo(context.top, g->index[i], &molb).atomnm;
666 while (std::isspace(*s))
668 ++s;
670 out->u.s[i] = const_cast<char *>(s);
674 static void
675 check_atomtype(const gmx_mtop_t *top, int /* npar */, gmx_ana_selparam_t * /* param */, void * /* data */)
677 if (!gmx_mtop_has_atomtypes(top))
679 GMX_THROW(gmx::InconsistentInputError("Atom types not available in topology"));
684 * See sel_updatefunc() for description of the parameters.
685 * \p data is not used.
687 * Returns the atom type for each atom in \p out->u.s.
688 * Segfaults if atom types are not found in the topology.
690 static void
691 evaluate_atomtype(const gmx::SelMethodEvalContext &context,
692 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
694 out->nr = g->isize;
695 int molb = 0;
696 for (int i = 0; i < g->isize; ++i)
698 int atomIndexInMolecule;
699 mtopGetMolblockIndex(context.top, g->index[i], &molb,
700 nullptr, &atomIndexInMolecule);
701 const gmx_moltype_t &moltype = context.top->moltype[context.top->molblock[molb].type];
702 out->u.s[i] = *moltype.atoms.atomtype[atomIndexInMolecule];
707 * See sel_updatefunc() for description of the parameters.
708 * \p data is not used.
710 * Returns the residue name for each atom in \p out->u.s.
712 static void
713 evaluate_resname(const gmx::SelMethodEvalContext &context,
714 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
716 out->nr = g->isize;
717 int molb = 0;
718 for (int i = 0; i < g->isize; ++i)
720 out->u.s[i] = *mtopGetResidueInfo(context.top, g->index[i], &molb).name;
725 * See sel_updatefunc() for description of the parameters.
726 * \p data is not used.
728 * Returns the insertion code for each atom in \p out->u.s.
730 static void
731 evaluate_insertcode(const gmx::SelMethodEvalContext &context,
732 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
734 out->nr = g->isize;
735 int molb = 0;
736 for (int i = 0; i < g->isize; ++i)
738 out->u.s[i][0] = mtopGetResidueInfo(context.top, g->index[i], &molb).ic;
743 * See sel_updatefunc() for description of the parameters.
744 * \p data is not used.
746 * Returns the chain for each atom in \p out->u.s.
748 static void
749 evaluate_chain(const gmx::SelMethodEvalContext &context,
750 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
752 out->nr = g->isize;
753 int molb = 0;
754 for (int i = 0; i < g->isize; ++i)
756 out->u.s[i][0] = mtopGetResidueInfo(context.top, g->index[i], &molb).chainid;
761 * See sel_updatefunc() for description of the parameters.
762 * \p data is not used.
764 * Returns the mass for each atom in \p out->u.r.
766 static void
767 evaluate_mass(const gmx::SelMethodEvalContext &context,
768 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
770 GMX_RELEASE_ASSERT(gmx_mtop_has_masses(context.top),
771 "Masses not available for evaluation");
772 out->nr = g->isize;
773 int molb = 0;
774 for (int i = 0; i < g->isize; ++i)
776 out->u.r[i] = mtopGetAtomMass(context.top, g->index[i], &molb);
781 static void
782 check_charge(const gmx_mtop_t *top, int /* npar */, gmx_ana_selparam_t * /* param */, void * /* data */)
784 if (!gmx_mtop_has_charges(top))
786 GMX_THROW(gmx::InconsistentInputError("Charges not available in topology"));
791 * See sel_updatefunc() for description of the parameters.
792 * \p data is not used.
794 * Returns the charge for each atom in \p out->u.r.
796 static void
797 evaluate_charge(const gmx::SelMethodEvalContext &context,
798 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
800 out->nr = g->isize;
801 int molb = 0;
802 for (int i = 0; i < g->isize; ++i)
804 out->u.r[i] = mtopGetAtomParameters(context.top, g->index[i], &molb).q;
808 static void
809 check_pdbinfo(const gmx_mtop_t *top, int /* npar */, gmx_ana_selparam_t * /* param */, void * /* data */)
811 if (!gmx_mtop_has_pdbinfo(top))
813 GMX_THROW(gmx::InconsistentInputError("PDB info not available in topology"));
818 * See sel_updatefunc() for description of the parameters.
819 * \p data is not used.
821 * Returns the alternate location identifier for each atom in \p out->u.s.
823 static void
824 evaluate_altloc(const gmx::SelMethodEvalContext &context,
825 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
827 out->nr = g->isize;
828 int molb = 0;
829 for (int i = 0; i < g->isize; ++i)
831 out->u.s[i][0] = mtopGetAtomPdbInfo(context.top, g->index[i], &molb).altloc;
836 * See sel_updatefunc() for description of the parameters.
837 * \p data is not used.
839 * Returns the occupancy numbers for each atom in \p out->u.r.
840 * Segfaults if PDB info is not found in the topology.
842 static void
843 evaluate_occupancy(const gmx::SelMethodEvalContext &context,
844 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
846 out->nr = g->isize;
847 int molb = 0;
848 for (int i = 0; i < g->isize; ++i)
850 out->u.r[i] = mtopGetAtomPdbInfo(context.top, g->index[i], &molb).occup;
855 * See sel_updatefunc() for description of the parameters.
856 * \p data is not used.
858 * Returns the B-factors for each atom in \p out->u.r.
859 * Segfaults if PDB info is not found in the topology.
861 static void
862 evaluate_betafactor(const gmx::SelMethodEvalContext &context,
863 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void * /* data */)
865 out->nr = g->isize;
866 int molb = 0;
867 for (int i = 0; i < g->isize; ++i)
869 out->u.r[i] = mtopGetAtomPdbInfo(context.top, g->index[i], &molb).bfac;
873 /*! \brief
874 * Internal utility function for position keyword evaluation.
876 * \param[out] out Output array.
877 * \param[in] pos Position data to use instead of atomic coordinates.
878 * \param[in] d Coordinate index to evaluate (\p XX, \p YY or \p ZZ).
880 * This function is used internally by evaluate_x(), evaluate_y() and
881 * evaluate_z() to do the actual evaluation.
883 static void
884 evaluate_coord(real out[], gmx_ana_pos_t *pos, int d)
886 for (int i = 0; i < pos->count(); ++i)
888 out[i] = pos->x[i][d];
890 // TODO: Make this more efficient by directly extracting the coordinates
891 // from the frame coordinates for atomic positions instead of going through
892 // a position calculation.
896 * See sel_updatefunc_pos() for description of the parameters.
897 * \p data is not used.
899 * Returns the \p x coordinate for each position in \p out->u.r.
901 static void
902 evaluate_x(const gmx::SelMethodEvalContext & /*context*/,
903 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void * /*data*/)
905 out->nr = pos->count();
906 evaluate_coord(out->u.r, pos, XX);
910 * See sel_updatefunc() for description of the parameters.
911 * \p data is not used.
913 * Returns the \p y coordinate for each position in \p out->u.r.
915 static void
916 evaluate_y(const gmx::SelMethodEvalContext & /*context*/,
917 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void * /*data*/)
919 out->nr = pos->count();
920 evaluate_coord(out->u.r, pos, YY);
924 * See sel_updatefunc() for description of the parameters.
925 * \p data is not used.
927 * Returns the \p z coordinate for each position in \p out->u.r.
929 static void
930 evaluate_z(const gmx::SelMethodEvalContext & /*context*/,
931 gmx_ana_pos_t *pos, gmx_ana_selvalue_t *out, void * /*data*/)
933 out->nr = pos->count();
934 evaluate_coord(out->u.r, pos, ZZ);