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.
37 * Implements simple keyword selection methods.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_selection
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"
53 #include "selmethod.h"
54 #include "selmethod_impl.h"
56 /** Evaluates the \p all selection keyword. */
57 static void evaluate_all(const gmx::SelMethodEvalContext& context,
59 gmx_ana_selvalue_t* out,
61 /** Evaluates the \p none selection keyword. */
62 static void evaluate_none(const gmx::SelMethodEvalContext& context,
64 gmx_ana_selvalue_t* out,
66 /** Evaluates the \p atomnr selection keyword. */
67 static void evaluate_atomnr(const gmx::SelMethodEvalContext& context,
69 gmx_ana_selvalue_t* out,
71 /** Evaluates the \p resnr selection keyword. */
72 static void evaluate_resnr(const gmx::SelMethodEvalContext& context,
74 gmx_ana_selvalue_t* out,
76 /** Evaluates the \p resindex selection keyword. */
77 static void evaluate_resindex(const gmx::SelMethodEvalContext& context,
79 gmx_ana_selvalue_t* out,
82 * Checks whether molecule information is present in the topology.
84 * \param[in] top Topology structure.
85 * \param npar Not used.
86 * \param param Not used.
87 * \param data Not used.
88 * \returns 0 if molecule info is present in the topology, -1 otherwise.
90 * If molecule information is not found, also prints an error message.
92 static void check_molecules(const gmx_mtop_t* top, int npar, gmx_ana_selparam_t* param, void* data);
93 /** Evaluates the \p molindex selection keyword. */
94 static void evaluate_molindex(const gmx::SelMethodEvalContext& context,
96 gmx_ana_selvalue_t* out,
98 /** Evaluates the \p atomname selection keyword. */
99 static void evaluate_atomname(const gmx::SelMethodEvalContext& context,
101 gmx_ana_selvalue_t* out,
103 /** Evaluates the \p pdbatomname selection keyword. */
104 static void evaluate_pdbatomname(const gmx::SelMethodEvalContext& context,
106 gmx_ana_selvalue_t* out,
109 * Checks whether atom types are present in the topology.
111 * \param[in] top Topology structure.
112 * \param npar Not used.
113 * \param param Not used.
114 * \param data Not used.
116 static void check_atomtype(const gmx_mtop_t* top, int npar, gmx_ana_selparam_t* param, void* data);
117 /** Evaluates the \p atomtype selection keyword. */
118 static void evaluate_atomtype(const gmx::SelMethodEvalContext& context,
120 gmx_ana_selvalue_t* out,
122 /** Evaluates the \p insertcode selection keyword. */
123 static void evaluate_insertcode(const gmx::SelMethodEvalContext& context,
125 gmx_ana_selvalue_t* out,
127 /** Evaluates the \p chain selection keyword. */
128 static void evaluate_chain(const gmx::SelMethodEvalContext& context,
130 gmx_ana_selvalue_t* out,
132 /** Evaluates the \p mass selection keyword. */
133 static void evaluate_mass(const gmx::SelMethodEvalContext& context,
135 gmx_ana_selvalue_t* out,
138 * Checks whether charges are present in the topology.
140 * \param[in] top Topology structure.
141 * \param npar Not used.
142 * \param param Not used.
143 * \param data Not used.
145 static void check_charge(const gmx_mtop_t* top, int npar, gmx_ana_selparam_t* param, void* data);
146 /** Evaluates the \p charge selection keyword. */
147 static void evaluate_charge(const gmx::SelMethodEvalContext& context,
149 gmx_ana_selvalue_t* out,
152 * Checks whether PDB info is present in the topology.
154 * \param[in] top Topology structure.
155 * \param npar Not used.
156 * \param param Not used.
157 * \param data Not used.
158 * \returns 0 if PDB info is present in the topology, -1 otherwise.
160 * If PDB info is not found, also prints an error message.
162 static void check_pdbinfo(const gmx_mtop_t* top, int npar, gmx_ana_selparam_t* param, void* data);
163 /** Evaluates the \p altloc selection keyword. */
164 static void evaluate_altloc(const gmx::SelMethodEvalContext& context,
166 gmx_ana_selvalue_t* out,
168 /** Evaluates the \p occupancy selection keyword. */
169 static void evaluate_occupancy(const gmx::SelMethodEvalContext& context,
171 gmx_ana_selvalue_t* out,
173 /** Evaluates the \p betafactor selection keyword. */
174 static void evaluate_betafactor(const gmx::SelMethodEvalContext& context,
176 gmx_ana_selvalue_t* out,
178 /** Evaluates the \p resname selection keyword. */
179 static void evaluate_resname(const gmx::SelMethodEvalContext& context,
181 gmx_ana_selvalue_t* out,
184 /** Evaluates the \p x selection keyword. */
185 static void evaluate_x(const gmx::SelMethodEvalContext& context,
187 gmx_ana_selvalue_t* out,
189 /** Evaluates the \p y selection keyword. */
190 static void evaluate_y(const gmx::SelMethodEvalContext& context,
192 gmx_ana_selvalue_t* out,
194 /** Evaluates the \p z selection keyword. */
195 static void evaluate_z(const gmx::SelMethodEvalContext& context,
197 gmx_ana_selvalue_t* out,
200 //! Help title for atom name selection keywords.
201 static const char helptitle_atomname[] = "Selecting atoms by name";
202 //! Help text for atom name selection keywords.
203 static const char* const help_atomname[] = {
211 "These keywords select atoms by name. [TT]name[tt] selects atoms using",
212 "the GROMACS atom naming convention.",
213 "For input formats other than PDB, the atom names are matched exactly",
214 "as they appear in the input file. For PDB files, 4 character atom names",
215 "that start with a digit are matched after moving the digit to the end",
216 "(e.g., to match 3HG2 from a PDB file, use [TT]name HG23[tt]).",
217 "[TT]pdbname[tt] can only be used with a PDB input file, and selects",
218 "atoms based on the exact name given in the input file, without the",
219 "transformation described above.[PAR]",
221 "[TT]atomname[tt] and [TT]pdbatomname[tt] are synonyms for the above two",
225 //! Help title for residue index selection keywords.
226 static const char helptitle_resindex[] = "Selecting atoms by residue number";
227 //! Help text for residue index selection keywords.
228 static const char* const help_resindex[] = {
236 "[TT]resnr[tt] selects atoms using the residue numbering in the input",
237 "file. [TT]resid[tt] is synonym for this keyword for VMD compatibility.",
239 "[TT]resindex N[tt] selects the [TT]N[tt] th residue starting from the",
240 "beginning of the input file. This is useful for uniquely identifying",
241 "residues if there are duplicate numbers in the input file (e.g., in",
243 "[TT]residue[tt] is a synonym for [TT]resindex[tt]. This allows",
244 "[TT]same residue as[tt] to work as expected."
247 /** Selection method data for \p all selection keyword. */
248 gmx_ana_selmethod_t sm_all = {
249 "all", GROUP_VALUE, 0, 0, nullptr, nullptr, nullptr,
250 nullptr, nullptr, nullptr, nullptr, &evaluate_all, nullptr,
253 /** Selection method data for \p none selection keyword. */
254 gmx_ana_selmethod_t sm_none = {
255 "none", GROUP_VALUE, 0, 0, nullptr, nullptr, nullptr,
256 nullptr, nullptr, nullptr, nullptr, &evaluate_none, nullptr,
259 /** Selection method data for \p atomnr selection keyword. */
260 gmx_ana_selmethod_t sm_atomnr = {
261 "atomnr", INT_VALUE, 0, 0, nullptr, nullptr, nullptr,
262 nullptr, nullptr, nullptr, nullptr, &evaluate_atomnr, nullptr,
265 /** Selection method data for \p resnr selection keyword. */
266 gmx_ana_selmethod_t sm_resnr = {
272 nullptr, &evaluate_resnr,
273 nullptr, { nullptr, helptitle_resindex, asize(help_resindex), help_resindex }
276 /** Selection method data for \p resindex selection keyword. */
277 gmx_ana_selmethod_t sm_resindex = {
278 "resindex", INT_VALUE,
283 nullptr, &evaluate_resindex,
284 nullptr, { nullptr, helptitle_resindex, asize(help_resindex), help_resindex }
287 /** Selection method data for \p molindex selection keyword. */
288 gmx_ana_selmethod_t sm_molindex = {
289 "molindex", INT_VALUE, SMETH_REQTOP, 0, nullptr, nullptr,
290 nullptr, &check_molecules, nullptr, nullptr, nullptr, &evaluate_molindex,
294 /** Selection method data for \p atomname selection keyword. */
295 gmx_ana_selmethod_t sm_atomname = {
296 "atomname", STR_VALUE,
301 nullptr, &evaluate_atomname,
302 nullptr, { nullptr, helptitle_atomname, asize(help_atomname), help_atomname }
305 /** Selection method data for \p pdbatomname selection keyword. */
306 gmx_ana_selmethod_t sm_pdbatomname = {
307 "pdbatomname", STR_VALUE,
310 nullptr, &check_pdbinfo,
312 nullptr, &evaluate_pdbatomname,
313 nullptr, { nullptr, helptitle_atomname, asize(help_atomname), help_atomname }
316 /** Selection method data for \p atomtype selection keyword. */
317 gmx_ana_selmethod_t sm_atomtype = {
318 "atomtype", STR_VALUE, SMETH_REQTOP, 0, nullptr, nullptr,
319 nullptr, &check_atomtype, nullptr, nullptr, nullptr, &evaluate_atomtype,
323 /** Selection method data for \p resname selection keyword. */
324 gmx_ana_selmethod_t sm_resname = {
325 "resname", STR_VALUE, SMETH_REQTOP, 0, nullptr, nullptr, nullptr,
326 nullptr, nullptr, nullptr, nullptr, &evaluate_resname, nullptr,
329 /** Selection method data for \p chain selection keyword. */
330 gmx_ana_selmethod_t sm_insertcode = {
333 SMETH_REQTOP | SMETH_CHARVAL,
342 &evaluate_insertcode,
346 /** Selection method data for \p chain selection keyword. */
347 gmx_ana_selmethod_t sm_chain = {
348 "chain", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
350 nullptr, nullptr, nullptr,
351 nullptr, nullptr, &evaluate_chain,
355 /** Selection method data for \p mass selection keyword. */
356 gmx_ana_selmethod_t sm_mass = {
357 "mass", REAL_VALUE, SMETH_REQMASS, 0, nullptr, nullptr, nullptr,
358 nullptr, nullptr, nullptr, nullptr, &evaluate_mass, nullptr,
361 /** Selection method data for \p charge selection keyword. */
362 gmx_ana_selmethod_t sm_charge = {
363 "charge", REAL_VALUE, SMETH_REQTOP, 0, nullptr, nullptr, nullptr,
364 &check_charge, nullptr, nullptr, nullptr, &evaluate_charge, nullptr,
367 /** Selection method data for \p chain selection keyword. */
368 gmx_ana_selmethod_t sm_altloc = {
369 "altloc", STR_VALUE, SMETH_REQTOP | SMETH_CHARVAL,
371 nullptr, &check_pdbinfo, nullptr,
372 nullptr, nullptr, &evaluate_altloc,
376 /** Selection method data for \p occupancy selection keyword. */
377 gmx_ana_selmethod_t sm_occupancy = {
378 "occupancy", REAL_VALUE, SMETH_REQTOP, 0, nullptr, nullptr,
379 nullptr, &check_pdbinfo, nullptr, nullptr, nullptr, &evaluate_occupancy,
383 /** Selection method data for \p betafactor selection keyword. */
384 gmx_ana_selmethod_t sm_betafactor = {
385 "betafactor", REAL_VALUE, SMETH_REQTOP, 0, nullptr, nullptr,
386 nullptr, &check_pdbinfo, nullptr, nullptr, nullptr, &evaluate_betafactor,
390 /** Selection method data for \p x selection keyword. */
391 gmx_ana_selmethod_t sm_x = {
392 "x", REAL_VALUE, SMETH_DYNAMIC, 0, nullptr, nullptr, nullptr,
393 nullptr, nullptr, nullptr, nullptr, nullptr, &evaluate_x,
396 /** Selection method data for \p y selection keyword. */
397 gmx_ana_selmethod_t sm_y = {
398 "y", REAL_VALUE, SMETH_DYNAMIC, 0, nullptr, nullptr, nullptr,
399 nullptr, nullptr, nullptr, nullptr, nullptr, &evaluate_y,
402 /** Selection method data for \p z selection keyword. */
403 gmx_ana_selmethod_t sm_z = {
404 "z", REAL_VALUE, SMETH_DYNAMIC, 0, nullptr, nullptr, nullptr,
405 nullptr, nullptr, nullptr, nullptr, nullptr, &evaluate_z,
409 * See sel_updatefunc() for description of the parameters.
410 * \p data is not used.
412 * Copies \p g to \p out->u.g.
414 static void evaluate_all(const gmx::SelMethodEvalContext& /*context*/,
416 gmx_ana_selvalue_t* out,
419 gmx_ana_index_copy(out->u.g, g, false);
423 * See sel_updatefunc() for description of the parameters.
424 * \p data is not used.
426 * Returns an empty \p out->u.g.
428 static void evaluate_none(const gmx::SelMethodEvalContext& /*context*/,
429 gmx_ana_index_t* /* g */,
430 gmx_ana_selvalue_t* out,
437 * See sel_updatefunc() for description of the parameters.
438 * \p data is not used.
440 * Returns the indices for each atom in \p out->u.i.
442 static void evaluate_atomnr(const gmx::SelMethodEvalContext& /*context*/,
444 gmx_ana_selvalue_t* out,
450 for (i = 0; i < g->isize; ++i)
452 out->u.i[i] = g->index[i] + 1;
457 * See sel_updatefunc() for description of the parameters.
458 * \p data is not used.
460 * Returns the residue numbers for each atom in \p out->u.i.
462 static void evaluate_resnr(const gmx::SelMethodEvalContext& context,
464 gmx_ana_selvalue_t* out,
469 for (int i = 0; i < g->isize; ++i)
471 mtopGetAtomAndResidueName(context.top, g->index[i], &molb, nullptr, &out->u.i[i], nullptr, nullptr);
476 * See sel_updatefunc() for description of the parameters.
477 * \p data is not used.
479 * Returns the residue indices for each atom in \p out->u.i.
481 static void evaluate_resindex(const gmx::SelMethodEvalContext& context,
483 gmx_ana_selvalue_t* out,
488 for (int i = 0; i < g->isize; ++i)
491 mtopGetAtomAndResidueName(context.top, g->index[i], &molb, nullptr, nullptr, nullptr, &resind);
492 out->u.i[i] = resind + 1;
496 static void check_molecules(const gmx_mtop_t* top, int /* npar */, gmx_ana_selparam_t* /* param */, void* /* data */)
500 bOk = (top != nullptr && top->haveMoleculeIndices);
503 GMX_THROW(gmx::InconsistentInputError("Molecule information not available in topology"));
508 * See sel_updatefunc() for description of the parameters.
509 * \p data is not used.
511 * Returns the molecule indices for each atom in \p out->u.i.
513 static void evaluate_molindex(const gmx::SelMethodEvalContext& context,
515 gmx_ana_selvalue_t* out,
520 for (int i = 0; i < g->isize; ++i)
522 out->u.i[i] = mtopGetMoleculeIndex(context.top, g->index[i], &molb) + 1;
527 * See sel_updatefunc() for description of the parameters.
528 * \p data is not used.
530 * Returns the atom name for each atom in \p out->u.s.
532 static void evaluate_atomname(const gmx::SelMethodEvalContext& context,
534 gmx_ana_selvalue_t* out,
539 for (int i = 0; i < g->isize; ++i)
541 const char* atom_name;
542 mtopGetAtomAndResidueName(context.top, g->index[i], &molb, &atom_name, nullptr, nullptr, nullptr);
543 out->u.s[i] = const_cast<char*>(atom_name);
548 * See sel_updatefunc() for description of the parameters.
549 * \p data is not used.
551 * Returns the PDB atom name for each atom in \p out->u.s.
553 static void evaluate_pdbatomname(const gmx::SelMethodEvalContext& context,
555 gmx_ana_selvalue_t* out,
560 for (int i = 0; i < g->isize; ++i)
562 const char* s = mtopGetAtomPdbInfo(context.top, g->index[i], &molb).atomnm;
563 while (std::isspace(*s))
567 out->u.s[i] = const_cast<char*>(s);
571 static void check_atomtype(const gmx_mtop_t* top, int /* npar */, gmx_ana_selparam_t* /* param */, void* /* data */)
573 if (!gmx_mtop_has_atomtypes(top))
575 GMX_THROW(gmx::InconsistentInputError("Atom types not available in topology"));
580 * See sel_updatefunc() for description of the parameters.
581 * \p data is not used.
583 * Returns the atom type for each atom in \p out->u.s.
584 * Segfaults if atom types are not found in the topology.
586 static void evaluate_atomtype(const gmx::SelMethodEvalContext& context,
588 gmx_ana_selvalue_t* out,
593 for (int i = 0; i < g->isize; ++i)
595 int atomIndexInMolecule;
596 mtopGetMolblockIndex(context.top, g->index[i], &molb, nullptr, &atomIndexInMolecule);
597 const gmx_moltype_t& moltype = context.top->moltype[context.top->molblock[molb].type];
598 out->u.s[i] = *moltype.atoms.atomtype[atomIndexInMolecule];
603 * See sel_updatefunc() for description of the parameters.
604 * \p data is not used.
606 * Returns the residue name for each atom in \p out->u.s.
608 static void evaluate_resname(const gmx::SelMethodEvalContext& context,
610 gmx_ana_selvalue_t* out,
615 for (int i = 0; i < g->isize; ++i)
617 out->u.s[i] = *mtopGetResidueInfo(context.top, g->index[i], &molb).name;
622 * See sel_updatefunc() for description of the parameters.
623 * \p data is not used.
625 * Returns the insertion code for each atom in \p out->u.s.
627 static void evaluate_insertcode(const gmx::SelMethodEvalContext& context,
629 gmx_ana_selvalue_t* out,
634 for (int i = 0; i < g->isize; ++i)
636 out->u.s[i][0] = mtopGetResidueInfo(context.top, g->index[i], &molb).ic;
641 * See sel_updatefunc() for description of the parameters.
642 * \p data is not used.
644 * Returns the chain for each atom in \p out->u.s.
646 static void evaluate_chain(const gmx::SelMethodEvalContext& context,
648 gmx_ana_selvalue_t* out,
653 for (int i = 0; i < g->isize; ++i)
655 out->u.s[i][0] = mtopGetResidueInfo(context.top, g->index[i], &molb).chainid;
660 * See sel_updatefunc() for description of the parameters.
661 * \p data is not used.
663 * Returns the mass for each atom in \p out->u.r.
665 static void evaluate_mass(const gmx::SelMethodEvalContext& context,
667 gmx_ana_selvalue_t* out,
670 GMX_RELEASE_ASSERT(gmx_mtop_has_masses(context.top), "Masses not available for evaluation");
673 for (int i = 0; i < g->isize; ++i)
675 out->u.r[i] = mtopGetAtomMass(context.top, g->index[i], &molb);
680 static void check_charge(const gmx_mtop_t* top, int /* npar */, gmx_ana_selparam_t* /* param */, void* /* data */)
682 if (!gmx_mtop_has_charges(top))
684 GMX_THROW(gmx::InconsistentInputError("Charges not available in topology"));
689 * See sel_updatefunc() for description of the parameters.
690 * \p data is not used.
692 * Returns the charge for each atom in \p out->u.r.
694 static void evaluate_charge(const gmx::SelMethodEvalContext& context,
696 gmx_ana_selvalue_t* out,
701 for (int i = 0; i < g->isize; ++i)
703 out->u.r[i] = mtopGetAtomParameters(context.top, g->index[i], &molb).q;
707 static void check_pdbinfo(const gmx_mtop_t* top, int /* npar */, gmx_ana_selparam_t* /* param */, void* /* data */)
709 if (!gmx_mtop_has_pdbinfo(top))
711 GMX_THROW(gmx::InconsistentInputError("PDB info not available in topology"));
716 * See sel_updatefunc() for description of the parameters.
717 * \p data is not used.
719 * Returns the alternate location identifier for each atom in \p out->u.s.
721 static void evaluate_altloc(const gmx::SelMethodEvalContext& context,
723 gmx_ana_selvalue_t* out,
728 for (int i = 0; i < g->isize; ++i)
730 out->u.s[i][0] = mtopGetAtomPdbInfo(context.top, g->index[i], &molb).altloc;
735 * See sel_updatefunc() for description of the parameters.
736 * \p data is not used.
738 * Returns the occupancy numbers for each atom in \p out->u.r.
739 * Segfaults if PDB info is not found in the topology.
741 static void evaluate_occupancy(const gmx::SelMethodEvalContext& context,
743 gmx_ana_selvalue_t* out,
748 for (int i = 0; i < g->isize; ++i)
750 out->u.r[i] = mtopGetAtomPdbInfo(context.top, g->index[i], &molb).occup;
755 * See sel_updatefunc() for description of the parameters.
756 * \p data is not used.
758 * Returns the B-factors for each atom in \p out->u.r.
759 * Segfaults if PDB info is not found in the topology.
761 static void evaluate_betafactor(const gmx::SelMethodEvalContext& context,
763 gmx_ana_selvalue_t* out,
768 for (int i = 0; i < g->isize; ++i)
770 out->u.r[i] = mtopGetAtomPdbInfo(context.top, g->index[i], &molb).bfac;
775 * Internal utility function for position keyword evaluation.
777 * \param[out] out Output array.
778 * \param[in] pos Position data to use instead of atomic coordinates.
779 * \param[in] d Coordinate index to evaluate (\p XX, \p YY or \p ZZ).
781 * This function is used internally by evaluate_x(), evaluate_y() and
782 * evaluate_z() to do the actual evaluation.
784 static void evaluate_coord(real out[], gmx_ana_pos_t* pos, int d)
786 for (int i = 0; i < pos->count(); ++i)
788 out[i] = pos->x[i][d];
790 // TODO: Make this more efficient by directly extracting the coordinates
791 // from the frame coordinates for atomic positions instead of going through
792 // a position calculation.
796 * See sel_updatefunc_pos() for description of the parameters.
797 * \p data is not used.
799 * Returns the \p x coordinate for each position in \p out->u.r.
801 static void evaluate_x(const gmx::SelMethodEvalContext& /*context*/,
803 gmx_ana_selvalue_t* out,
806 out->nr = pos->count();
807 evaluate_coord(out->u.r, pos, XX);
811 * See sel_updatefunc() for description of the parameters.
812 * \p data is not used.
814 * Returns the \p y coordinate for each position in \p out->u.r.
816 static void evaluate_y(const gmx::SelMethodEvalContext& /*context*/,
818 gmx_ana_selvalue_t* out,
821 out->nr = pos->count();
822 evaluate_coord(out->u.r, pos, YY);
826 * See sel_updatefunc() for description of the parameters.
827 * \p data is not used.
829 * Returns the \p z coordinate for each position in \p out->u.r.
831 static void evaluate_z(const gmx::SelMethodEvalContext& /*context*/,
833 gmx_ana_selvalue_t* out,
836 out->nr = pos->count();
837 evaluate_coord(out->u.r, pos, ZZ);