Merge release-4-6 into master
[alexxy/gromacs.git] / src / gromacs / selection / sm_keywords.cpp
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
33  * Implements internal selection methods for numeric and string keyword
34  * evaluation.
35  *
36  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
37  * \ingroup module_selection
38  */
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #include <ctype.h>
44 #ifdef HAVE_SYS_TYPES_H
45 #include <sys/types.h>  /*old Mac needs types before regex.h*/
46 #endif
47 #ifdef HAVE_REGEX_H
48 #include <regex.h>
49 #define USE_REGEX
50 #endif
51
52 #include <macros.h>
53 #include <smalloc.h>
54 #include <string2.h>
55
56 #include "gromacs/fatalerror/errorcodes.h"
57 #include "gromacs/fatalerror/messagestringcollector.h"
58 #include "gromacs/selection/selmethod.h"
59
60 #include "keywords.h"
61 #include "parsetree.h"
62 #include "scanner.h"
63 #include "selelem.h"
64
65 /** Allocates data for integer keyword evaluation. */
66 static void *
67 init_data_kwint(int npar, gmx_ana_selparam_t *param);
68 /** Allocates data for real keyword evaluation. */
69 static void *
70 init_data_kwreal(int npar, gmx_ana_selparam_t *param);
71 /** Allocates data for string keyword evaluation. */
72 static void *
73 init_data_kwstr(int npar, gmx_ana_selparam_t *param);
74 /** Initializes data for integer keyword evaluation. */
75 static void
76 init_kwint(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
77 /** Initializes data for real keyword evaluation. */
78 static void
79 init_kwreal(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
80 /** Initializes data for string keyword evaluation. */
81 static void
82 init_kwstr(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
83 /** Frees the memory allocated for string keyword evaluation. */
84 static void
85 free_data_kwstr(void *data);
86 /** Evaluates integer selection keywords. */
87 static void
88 evaluate_keyword_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
89                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
90 /** Evaluates real selection keywords. */
91 static void
92 evaluate_keyword_real(t_topology *top, t_trxframe *fr, t_pbc *pbc,
93                       gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
94 /** Evaluates string selection keywords. */
95 static void
96 evaluate_keyword_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
97                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
98
99 /*! \internal \brief
100  * Data structure for integer keyword expression evaluation.
101  */
102 typedef struct t_methoddata_kwint
103 {
104     /** Array of values for the keyword. */
105     int               *v;
106     /** Number of ranges in the \p r array. */
107     int                n;
108     /*! \brief
109      * Array of sorted integer ranges to match against.
110      *
111      * Each range is made of two integers, giving the endpoints (inclusive).
112      * This field stores the pointer to the ranges allocated by the
113      * parameter parser; see \ref SPAR_RANGES for more information.
114      */
115     int               *r;
116 } t_methoddata_kwint;
117
118 /*! \internal \brief
119  * Data structure for real keyword expression evaluation.
120  */
121 typedef struct t_methoddata_kwreal
122 {
123     /** Array of values for the keyword. */
124     real              *v;
125     /** Number of ranges in the \p r array. */
126     int                n;
127     /*! \brief
128      * Array of sorted ranges to match against.
129      *
130      * Each range is made of two values, giving the endpoints (inclusive).
131      * This field stores the pointer to the ranges allocated by the
132      * parameter parser; see \ref SPAR_RANGES for more information.
133      */
134     real              *r;
135 } t_methoddata_kwreal;
136
137 /*! \internal \brief
138  * Data structure for string keyword expression evaluation.
139  */
140 typedef struct t_methoddata_kwstr
141 {
142     /** Array of values for the keyword. */
143     char             **v;
144     /** Number of elements in the \p val array. */
145     int                n;
146     /*! \internal \brief
147      * Array of strings/regular expressions to match against.
148      */
149     struct t_methoddata_kwstr_match {
150         /** true if the expression is a regular expression, false otherwise. */
151         bool           bRegExp;
152         /** The value to match against. */
153         union {
154 #ifdef USE_REGEX
155             /** Compiled regular expression if \p bRegExp is true. */
156             regex_t    r;
157 #endif
158             /** The string if \p bRegExp is false; */
159             char      *s;
160         }              u;
161     }                 *m;
162 } t_methoddata_kwstr;
163
164 /** Parameters for integer keyword evaluation. */
165 static gmx_ana_selparam_t smparams_keyword_int[] = {
166     {NULL, {INT_VALUE, -1, {NULL}}, NULL, SPAR_ATOMVAL},
167     {NULL, {INT_VALUE, -1, {NULL}}, NULL, SPAR_RANGES | SPAR_VARNUM},
168 };
169
170 /** Parameters for real keyword evaluation. */
171 static gmx_ana_selparam_t smparams_keyword_real[] = {
172     {NULL, {REAL_VALUE, -1, {NULL}}, NULL, SPAR_ATOMVAL | SPAR_DYNAMIC},
173     {NULL, {REAL_VALUE, -1, {NULL}}, NULL, SPAR_RANGES | SPAR_VARNUM},
174 };
175
176 /** Parameters for string keyword evaluation. */
177 static gmx_ana_selparam_t smparams_keyword_str[] = {
178     {NULL, {STR_VALUE, -1, {NULL}}, NULL, SPAR_ATOMVAL},
179     {NULL, {STR_VALUE, -1, {NULL}}, NULL, SPAR_VARNUM},
180 };
181
182 /** \internal Selection method data for integer keyword evaluation. */
183 gmx_ana_selmethod_t sm_keyword_int = {
184     "kw_int", GROUP_VALUE, SMETH_SINGLEVAL,
185     asize(smparams_keyword_int), smparams_keyword_int,
186     &init_data_kwint,
187      NULL,
188     &init_kwint,
189      NULL,
190      NULL,
191      NULL,
192     &evaluate_keyword_int,
193      NULL,
194     {NULL, 0, NULL},
195 };
196
197 /** \internal Selection method data for real keyword evaluation. */
198 gmx_ana_selmethod_t sm_keyword_real = {
199     "kw_real", GROUP_VALUE, SMETH_SINGLEVAL,
200     asize(smparams_keyword_real), smparams_keyword_real,
201     &init_data_kwreal,
202      NULL,
203     &init_kwreal,
204      NULL,
205      NULL,
206      NULL,
207     &evaluate_keyword_real,
208      NULL,
209     {NULL, 0, NULL},
210 };
211
212 /** \internal Selection method data for string keyword evaluation. */
213 gmx_ana_selmethod_t sm_keyword_str = {
214     "kw_str", GROUP_VALUE, SMETH_SINGLEVAL,
215     asize(smparams_keyword_str), smparams_keyword_str,
216     &init_data_kwstr,
217      NULL,
218     &init_kwstr,
219      NULL,
220     &free_data_kwstr,
221      NULL,
222     &evaluate_keyword_str,
223      NULL,
224     {NULL, 0, NULL},
225 };
226
227 /** Initializes keyword evaluation for an arbitrary group. */
228 static void
229 init_kweval(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
230 /** Initializes output for keyword evaluation in an arbitrary group. */
231 static void
232 init_output_kweval(t_topology *top, gmx_ana_selvalue_t *out, void *data);
233 /** Frees the data allocated for keyword evaluation in an arbitrary group. */
234 static void
235 free_data_kweval(void *data);
236 /** Initializes frame evaluation for keyword evaluation in an arbitrary group. */
237 static void
238 init_frame_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
239 /** Evaluates keywords in an arbitrary group. */
240 static void
241 evaluate_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc,
242                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
243
244 /*! \internal \brief
245  * Data structure for keyword evaluation in arbitrary groups.
246  */
247 typedef struct
248 {
249     /** Wrapped keyword method for evaluating the values. */
250     gmx_ana_selmethod_t  *kwmethod;
251     /** Method data for \p kwmethod. */
252     void                 *kwmdata;
253     /** Group in which \p kwmethod should be evaluated. */
254     gmx_ana_index_t       g;
255 } t_methoddata_kweval;
256
257 /** Parameters for keyword evaluation in an arbitrary group. */
258 static gmx_ana_selparam_t smparams_kweval[] = {
259     {NULL,   {GROUP_VALUE, 1, {NULL}}, NULL, SPAR_DYNAMIC},
260 };
261
262
263 /********************************************************************
264  * INTEGER KEYWORD EVALUATION
265  ********************************************************************/
266
267 /*!
268  * \param[in] npar  Not used.
269  * \param     param Not used.
270  * \returns   Pointer to the allocated data (\ref t_methoddata_kwint).
271  *
272  * Allocates memory for a \ref t_methoddata_kwint structure.
273  */
274 static void *
275 init_data_kwint(int npar, gmx_ana_selparam_t *param)
276 {
277     t_methoddata_kwint *data;
278
279     snew(data, 1);
280     return data;
281 }
282
283 /*!
284  * \param[in] top   Not used.
285  * \param[in] npar  Not used (should be 2).
286  * \param[in] param Method parameters (should point to \ref smparams_keyword_int).
287  * \param[in] data  Should point to \ref t_methoddata_kwint.
288  */
289 static void
290 init_kwint(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
291 {
292     t_methoddata_kwint *d = (t_methoddata_kwint *)data;
293
294     d->v = param[0].val.u.i;
295     d->n = param[1].val.nr;
296     d->r = param[1].val.u.i;
297 }
298
299 /*!
300  * See sel_updatefunc() for description of the parameters.
301  * \p data should point to a \c t_methoddata_kwint.
302  *
303  * Does a binary search to find which atoms match the ranges in the
304  * \c t_methoddata_kwint structure for this selection.
305  * Matching atoms are stored in \p out->u.g.
306  */
307 static void
308 evaluate_keyword_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
309                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
310 {
311     t_methoddata_kwint *d = (t_methoddata_kwint *)data;
312     int                 n, i, j, jmin, jmax;
313     int                 val;
314
315     out->u.g->isize = 0;
316     n    = d->n;
317     for (i = 0; i < g->isize; ++i)
318     {
319         val = d->v[i];
320         if (d->r[0] > val || d->r[2*n-1] < val)
321         {
322             continue;
323         }
324         jmin = 0;
325         jmax = n;
326         while (jmax - jmin > 1)
327         {
328             j = jmin + (jmax - jmin) / 2;
329             if (val < d->r[2*j])
330             {
331                 jmax = j;
332             }
333             else
334             {
335                 jmin = j;
336                 if (val <= d->r[2*j+1])
337                 {
338                     break;
339                 }
340                 /* ++jmin;*/
341             }
342         }
343         if (val <= d->r[2*jmin+1])
344         {
345             out->u.g->index[out->u.g->isize++] = g->index[i];
346         }
347     }
348 }
349
350
351 /********************************************************************
352  * REAL KEYWORD EVALUATION
353  ********************************************************************/
354
355 /*!
356  * \param[in] npar  Not used.
357  * \param     param Not used.
358  * \returns   Pointer to the allocated data (\ref t_methoddata_kwreal).
359  *
360  * Allocates memory for a \ref t_methoddata_kwreal structure.
361  */
362 static void *
363 init_data_kwreal(int npar, gmx_ana_selparam_t *param)
364 {
365     t_methoddata_kwreal *data;
366
367     snew(data, 1);
368     return data;
369 }
370
371 /*!
372  * \param[in] top   Not used.
373  * \param[in] npar  Not used (should be 2).
374  * \param[in] param Method parameters (should point to \ref smparams_keyword_real).
375  * \param[in] data  Should point to \ref t_methoddata_kwreal.
376  * \returns   0 (the initialization always succeeds).
377  */
378 static void
379 init_kwreal(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
380 {
381     t_methoddata_kwreal *d = (t_methoddata_kwreal *)data;
382
383     d->v = param[0].val.u.r;
384     d->n = param[1].val.nr;
385     d->r = param[1].val.u.r;
386 }
387
388 /*!
389  * See sel_updatefunc() for description of the parameters.
390  * \p data should point to a \c t_methoddata_kwreal.
391  *
392  * Does a binary search to find which atoms match the ranges in the
393  * \c t_methoddata_kwreal structure for this selection.
394  * Matching atoms are stored in \p out->u.g.
395  */
396 static void
397 evaluate_keyword_real(t_topology *top, t_trxframe *fr, t_pbc *pbc,
398                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
399 {
400     t_methoddata_kwreal *d = (t_methoddata_kwreal *)data;
401     int                  n, i, j, jmin, jmax;
402     real                 val;
403
404     out->u.g->isize = 0;
405     n    = d->n;
406     for (i = 0; i < g->isize; ++i)
407     {
408         val = d->v[i];
409         if (d->r[0] > val || d->r[2*n-1] < val)
410         {
411             continue;
412         }
413         jmin = 0;
414         jmax = n;
415         while (jmax - jmin > 1)
416         {
417             j = jmin + (jmax - jmin) / 2;
418             if (val < d->r[2*j])
419             {
420                 jmax = j;
421             }
422             else
423             {
424                 jmin = j;
425                 if (val <= d->r[2*j+1])
426                 {
427                     break;
428                 }
429                 /* ++jmin;*/
430             }
431         }
432         if (val <= d->r[2*jmin+1])
433         {
434             out->u.g->index[out->u.g->isize++] = g->index[i];
435         }
436     }
437 }
438
439
440 /********************************************************************
441  * STRING KEYWORD EVALUATION
442  ********************************************************************/
443
444 /*!
445  * \param[in] npar  Not used.
446  * \param     param Not used.
447  * \returns Pointer to the allocated data (\ref t_methoddata_kwstr).
448  *
449  * Allocates memory for a \ref t_methoddata_kwstr structure.
450  */
451 static void *
452 init_data_kwstr(int npar, gmx_ana_selparam_t *param)
453 {
454     t_methoddata_kwstr *data;
455
456     snew(data, 1);
457     return data;
458 }
459
460 /*!
461  * \param[in] top   Not used.
462  * \param[in] npar  Not used (should be 2).
463  * \param[in] param Method parameters (should point to \ref smparams_keyword_str).
464  * \param[in] data  Should point to \ref t_methoddata_kwstr.
465  */
466 static void
467 init_kwstr(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
468 {
469     t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
470     char               *buf;
471     char               *s;
472     int                 i;
473     size_t              j;
474     bool                bRegExp;
475
476     d->v   = param[0].val.u.s;
477     d->n   = param[1].val.nr;
478     /* Return if this is not the first time */
479     if (d->m)
480     {
481         return;
482     }
483     snew(d->m, d->n);
484     for (i = 0; i < d->n; ++i)
485     {
486         s = param[1].val.u.s[i];
487         bRegExp = false;
488         for (j = 0; j < strlen(s); ++j)
489         {
490             if (ispunct(s[j]) && s[j] != '?' && s[j] != '*')
491             {
492                 bRegExp = true;
493                 break;
494             }
495         }
496         if (bRegExp)
497         {
498             // TODO: Get rid of these prints to stderr
499 #ifdef USE_REGEX
500             snew(buf, strlen(s) + 3);
501             sprintf(buf, "^%s$", s);
502             if (regcomp(&d->m[i].u.r, buf, REG_EXTENDED | REG_NOSUB))
503             {
504                 bRegExp = false;
505                 fprintf(stderr, "WARNING: error in regular expression,\n"
506                                 "         will match '%s' as a simple string\n", s);
507             }
508             sfree(buf);
509 #else
510             bRegExp = false;
511             fprintf(stderr, "WARNING: no regular expressions support,\n"
512                             "         will match '%s' as a simple string\n", s);
513 #endif
514         }
515         if (!bRegExp)
516         {
517             d->m[i].u.s = s;
518         }
519         d->m[i].bRegExp = bRegExp;
520     }
521 }
522
523 /*!
524  * \param data Data to free (should point to a \ref t_methoddata_kwstr).
525  *
526  * Frees the memory allocated for t_methoddata_kwstr::val.
527  */
528 static void
529 free_data_kwstr(void *data)
530 {
531     t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
532     int                 i;
533
534     for (i = 0; i < d->n; ++i)
535     {
536         if (d->m[i].bRegExp)
537         {
538 #ifdef USE_REGEX
539             /* This branch should only be taken if regular expressions
540              * are available, but the ifdef is still needed. */
541             regfree(&d->m[i].u.r);
542 #endif
543         }
544     }
545     sfree(d->m);
546 }
547
548 /*!
549  * See sel_updatefunc() for description of the parameters.
550  * \p data should point to a \c t_methoddata_kwstr.
551  *
552  * Does a linear search to find which atoms match the strings in the
553  * \c t_methoddata_kwstr structure for this selection.
554  * Wildcards are allowed in the strings.
555  * Matching atoms are stored in \p out->u.g.
556  */
557 static void
558 evaluate_keyword_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
559                      gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
560 {
561     t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
562     int                 i, j;
563     bool                bFound;
564
565     out->u.g->isize = 0;
566     for (i = 0; i < g->isize; ++i)
567     {
568         bFound = false;
569         for (j = 0; j < d->n && !bFound; ++j)
570         {
571             if (d->m[j].bRegExp)
572             {
573 #ifdef USE_REGEX
574                 /* This branch should only be taken if regular expressions
575                  * are available, but the ifdef is still needed. */
576                 if (!regexec(&d->m[j].u.r, d->v[i], 0, NULL, 0))
577                 {
578                     bFound = true;
579                 }
580 #endif
581             }
582             else
583             {
584                 if (gmx_wcmatch(d->m[j].u.s, d->v[i]) == 0)
585                 {
586                     bFound = true;
587                 }
588             }
589         }
590         if (bFound)
591         {
592             out->u.g->index[out->u.g->isize++] = g->index[i];
593         }
594     }
595 }
596
597
598 /********************************************************************
599  * KEYWORD EVALUATION FOR ARBITRARY GROUPS
600  ********************************************************************/
601
602 /*!
603  * \param[in] top   Not used.
604  * \param[in] npar  Not used.
605  * \param[in] param Not used.
606  * \param[in] data  Should point to \ref t_methoddata_kweval.
607  * \returns   0 on success, a non-zero error code on return.
608  *
609  * Calls the initialization method of the wrapped keyword.
610  */
611 static void
612 init_kweval(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
613 {
614     t_methoddata_kweval *d = (t_methoddata_kweval *)data;
615
616     d->kwmethod->init(top, 0, NULL, d->kwmdata);
617 }
618
619 /*!
620  * \param[in]     top   Not used.
621  * \param[in,out] out   Pointer to output data structure.
622  * \param[in,out] data  Should point to \c t_methoddata_kweval.
623  * \returns       0 for success.
624  */
625 static void
626 init_output_kweval(t_topology *top, gmx_ana_selvalue_t *out, void *data)
627 {
628     t_methoddata_kweval *d = (t_methoddata_kweval *)data;
629
630     out->nr = d->g.isize;
631 }
632
633 /*!
634  * \param data Data to free (should point to a \c t_methoddata_kweval).
635  *
636  * Frees the memory allocated for all the members of \c t_methoddata_kweval.
637  */
638 static void
639 free_data_kweval(void *data)
640 {
641     t_methoddata_kweval *d = (t_methoddata_kweval *)data;
642
643     _gmx_selelem_free_method(d->kwmethod, d->kwmdata);
644 }
645
646 /*!
647  * \param[in]  top  Topology.
648  * \param[in]  fr   Current frame.
649  * \param[in]  pbc  PBC structure.
650  * \param      data Should point to a \ref t_methoddata_kweval.
651  * \returns    0 on success, a non-zero error code on error.
652  *
653  * Creates a lookup structure that enables fast queries of whether a point
654  * is within the solid angle or not.
655  */
656 static void
657 init_frame_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
658 {
659     t_methoddata_kweval *d = (t_methoddata_kweval *)data;
660
661     d->kwmethod->init_frame(top, fr, pbc, d->kwmdata);
662 }
663
664 /*!
665  * See sel_updatefunc() for description of the parameters.
666  * \p data should point to a \c t_methoddata_kweval.
667  *
668  * Calls the evaluation function of the wrapped keyword with the given
669  * parameters, with the exception of using \c t_methoddata_kweval::g for the
670  * evaluation group.
671  */
672 static void
673 evaluate_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc,
674                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
675 {
676     t_methoddata_kweval *d = (t_methoddata_kweval *)data;
677
678     d->kwmethod->update(top, fr, pbc, &d->g, out, d->kwmdata);
679 }
680
681 /*!
682  * \param[out]  selp    Pointer to receive a pointer to the created selection
683  *      element (set to NULL on error).
684  * \param[in]   method  Keyword selection method to evaluate.
685  * \param[in]   param   Parameter that gives the group to evaluate \p method in.
686  * \param[in]   scanner Scanner data structure.
687  * \returns     0 on success, non-zero error code on error.
688  *
689  * Creates a \ref SEL_EXPRESSION selection element (pointer put in \c *selp)
690  * that evaluates the keyword method given by \p method in the group given by
691  * \p param.
692  */
693 int
694 _gmx_sel_init_keyword_evaluator(t_selelem **selp, gmx_ana_selmethod_t *method,
695                                 t_selexpr_param *param, void *scanner)
696 {
697     t_selelem            *sel;
698     t_methoddata_kweval  *data;
699
700     gmx::MessageStringCollector *errors = _gmx_sel_lexer_error_reporter(scanner);
701     char  buf[1024];
702     sprintf(buf, "In evaluation of '%s'", method->name);
703     gmx::MessageStringContext   context(errors, buf);
704
705     if ((method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL))
706         || method->outinit || method->pupdate)
707     {
708         _gmx_selexpr_free_params(param);
709         GMX_ERROR(gmx::eeInternalError,
710                   "Unsupported keyword method for arbitrary group evaluation");
711     }
712
713     *selp = NULL;
714     sel = _gmx_selelem_create(SEL_EXPRESSION);
715     _gmx_selelem_set_method(sel, method, scanner);
716
717     snew(data, 1);
718     data->kwmethod = sel->u.expr.method;
719     data->kwmdata  = sel->u.expr.mdata;
720     gmx_ana_index_clear(&data->g);
721
722     snew(sel->u.expr.method, 1);
723     memcpy(sel->u.expr.method, data->kwmethod, sizeof(gmx_ana_selmethod_t));
724     sel->u.expr.method->flags       |= SMETH_VARNUMVAL;
725     sel->u.expr.method->init_data    = NULL;
726     sel->u.expr.method->set_poscoll  = NULL;
727     sel->u.expr.method->init         = method->init ? &init_kweval : NULL;
728     sel->u.expr.method->outinit      = &init_output_kweval;
729     sel->u.expr.method->free         = &free_data_kweval;
730     sel->u.expr.method->init_frame   = method->init_frame ? &init_frame_kweval : NULL;
731     sel->u.expr.method->update       = &evaluate_kweval;
732     sel->u.expr.method->pupdate      = NULL;
733     sel->u.expr.method->nparams      = asize(smparams_kweval);
734     sel->u.expr.method->param        = smparams_kweval;
735     _gmx_selelem_init_method_params(sel, scanner);
736     sel->u.expr.mdata = data;
737
738     sel->u.expr.method->param[0].val.u.g = &data->g;
739
740     sfree(param->name);
741     param->name = NULL;
742     if (!_gmx_sel_parse_params(param, sel->u.expr.method->nparams,
743                                sel->u.expr.method->param, sel, scanner))
744     {
745         _gmx_selelem_free(sel);
746         return -1;
747     }
748     *selp = sel;
749     return 0;
750 }