Fixing copyright issues and code contributors
[alexxy/gromacs.git] / src / gmxlib / selection / selection.c
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5  * Copyright (c) 2001-2009, The GROMACS development team,
6  * check out http://www.gromacs.org for more information.
7  * Copyright (c) 2012,2013, by the GROMACS development team, led by
8  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
9  * others, as listed in the AUTHORS file in the top-level source
10  * directory and at http://www.gromacs.org.
11  *
12  * GROMACS is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public License
14  * as published by the Free Software Foundation; either version 2.1
15  * of the License, or (at your option) any later version.
16  *
17  * GROMACS is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with GROMACS; if not, see
24  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
26  *
27  * If you want to redistribute modifications to GROMACS, please
28  * consider that scientific software is very special. Version
29  * control is crucial - bugs must be traceable. We will be happy to
30  * consider code for inclusion in the official distribution, but
31  * derived work must not be called official GROMACS. Details are found
32  * in the README & COPYING files - if they are missing, get the
33  * official version at http://www.gromacs.org.
34  *
35  * To help us fund GROMACS development, we humbly ask that you cite
36  * the research papers on the package. Check out http://www.gromacs.org.
37  */
38 /*! \internal \file
39  * \brief
40  * Implementation of functions in selection.h.
41  */
42 /*! \internal \dir src/gmxlib/selection
43  * \brief
44  * Source code for selection-related routines.
45  */
46 #ifdef HAVE_CONFIG_H
47 #include <config.h>
48 #endif
49
50 #include <smalloc.h>
51 #include <statutil.h>
52 #include <string2.h>
53 #include <xvgr.h>
54 #include <gmx_fatal.h>
55
56 #include <poscalc.h>
57 #include <selection.h>
58 #include <selmethod.h>
59
60 #include "mempool.h"
61 #include "selcollection.h"
62 #include "selelem.h"
63 #include "symrec.h"
64
65 /*!
66  * \param[out] scp Pointer to a newly allocated empty selection collection.
67  * \param[in]  pcc Position calculation data structure to use for selection
68  *   position evaluation.
69  * \returns    0 on success.
70  */
71 int
72 gmx_ana_selcollection_create(gmx_ana_selcollection_t **scp,
73                              gmx_ana_poscalc_coll_t *pcc)
74 {
75     gmx_ana_selcollection_t *sc;
76     
77     snew(sc, 1);
78     sc->rpost     = NULL;
79     sc->spost     = NULL;
80     sc->bMaskOnly = FALSE;
81     sc->bVelocities = FALSE;
82     sc->bForces   = FALSE;
83     sc->bDebugCompile = FALSE;
84     sc->root      = NULL;
85     sc->nr        = 0;
86     sc->sel       = NULL;
87     sc->nvars     = 0;
88     sc->varstrs   = NULL;
89     sc->top       = NULL;
90     gmx_ana_index_clear(&sc->gall);
91     sc->pcc       = pcc;
92     sc->mempool   = NULL;
93     _gmx_sel_symtab_create(&sc->symtab);
94     *scp = sc;
95     return 0;
96 }
97
98 /*!
99  * \param[in,out] sc Selection collection to free.
100  *
101  * The pointer \p sc is invalid after the call.
102  */
103 void
104 gmx_ana_selcollection_free(gmx_ana_selcollection_t *sc)
105 {
106     int  i;
107
108     _gmx_selelem_free_chain(sc->root);
109     if (sc->sel)
110     {
111         for (i = 0; i < sc->nr; ++i)
112         {
113             gmx_ana_selection_free(sc->sel[i]);
114         }
115     }
116     sfree(sc->sel);
117     for (i = 0; i < sc->nvars; ++i)
118     {
119         sfree(sc->varstrs[i]);
120     }
121     sfree(sc->varstrs);
122     gmx_ana_index_deinit(&sc->gall);
123     if (sc->mempool)
124     {
125         _gmx_sel_mempool_destroy(sc->mempool);
126     }
127     _gmx_selcollection_clear_symtab(sc);
128     sfree(sc);
129 }
130
131 /*!
132  * \param[in,out] sc Selection collection.
133  */
134 void
135 _gmx_selcollection_clear_symtab(gmx_ana_selcollection_t *sc)
136 {
137     if (sc->symtab)
138     {
139         _gmx_sel_symtab_free(sc->symtab);
140         sc->symtab = NULL;
141     }
142 }
143
144 /*!
145  * \param[in,out] sc        Selection collection to modify.
146  * \param[in]     type      Default selection reference position type
147  *   (one of the strings acceptable for gmx_ana_poscalc_type_from_enum()).
148  *
149  * Should be called before calling gmx_ana_selcollection_requires_top() or
150  * gmx_ana_selcollection_parse_*().
151  */
152 void
153 gmx_ana_selcollection_set_refpostype(gmx_ana_selcollection_t *sc,
154                                      const char *type)
155 {
156     sc->rpost     = type;
157 }
158
159 /*!
160  * \param[in,out] sc        Selection collection to modify.
161  * \param[in]     type      Default selection output position type
162  *   (one of the strings acceptable for gmx_ana_poslcalc_type_from_enum()).
163  * \param[in]     bMaskOnly If TRUE, the output positions are initialized
164  *   using \ref POS_MASKONLY.
165  *
166  * If \p type is NULL, the default type is not modified.
167  * Should be called before calling gmx_ana_selcollection_requires_top() or
168  * gmx_ana_selcollection_parse_*().
169  */
170 void
171 gmx_ana_selcollection_set_outpostype(gmx_ana_selcollection_t *sc,
172                                      const char *type, gmx_bool bMaskOnly)
173 {
174     if (type)
175     {
176         sc->spost     = type;
177     }
178     sc->bMaskOnly = bMaskOnly;
179 }
180
181 /*!
182  * \param[in,out] sc        Selection collection to modify.
183  * \param[in]     bVelOut   If TRUE, selections will also evaluate
184  *      velocities.
185  */
186 void
187 gmx_ana_selcollection_set_veloutput(gmx_ana_selcollection_t *sc,
188                                     gmx_bool bVelOut)
189 {
190     sc->bVelocities = bVelOut;
191 }
192
193 /*!
194  * \param[in,out] sc        Selection collection to modify.
195  * \param[in]     bForceOut If TRUE, selections will also evaluate
196  *      forces.
197  */
198 void
199 gmx_ana_selcollection_set_forceoutput(gmx_ana_selcollection_t *sc,
200                                       gmx_bool bForceOut)
201 {
202     sc->bForces = bForceOut;
203 }
204
205 /*!
206  * \param[in,out] sc        Selection collection to set the topology for.
207  * \param[in]     top       Topology data.
208  * \param[in]     natoms    Number of atoms. If <=0, the number of atoms in the
209  *   topology is used.
210  * \returns       0 on success, EINVAL if \p top is NULL and \p natoms <= 0.
211  *
212  * The topology is also set for the position calculation collection
213  * associated with \p sc.
214  *
215  * \p natoms determines the largest atom index that can be selected by the
216  * selection: even if the topology contains more atoms, they will not be
217  * selected.
218  */
219 int
220 gmx_ana_selcollection_set_topology(gmx_ana_selcollection_t *sc, t_topology *top,
221                                    int natoms)
222 {
223     gmx_ana_poscalc_coll_set_topology(sc->pcc, top);
224     sc->top = top;
225
226     /* Get the number of atoms from the topology if it is not given */
227     if (natoms <= 0)
228     {
229         if (!sc->top)
230         {
231             gmx_incons("selections need either the topology or the number of atoms");
232             return EINVAL;
233         }
234         natoms = sc->top->atoms.nr;
235     }
236     gmx_ana_index_init_simple(&sc->gall, natoms, NULL);
237     return 0;
238 }
239
240 /*!
241  * \param[in]  sc  Selection collection to query.
242  * \returns    Number of selections in \p sc.
243  *
244  * If gmx_ana_selcollection_parse_*() has not been called, returns 0.
245  *
246  * \see gmx_ana_selcollection_get_selection()
247  */
248 int
249 gmx_ana_selcollection_get_count(gmx_ana_selcollection_t *sc)
250 {
251     return sc->nr;
252 }
253
254 /*!
255  * \param[in]  sc  Selection collection to query.
256  * \param[in]  i   Number of the selection.
257  * \returns    Pointer to the \p i'th selection in \p sc,
258  *   or NULL if there is no such selection.
259  *
260  * \p i should be between 0 and the value returned by
261  * gmx_ana_selcollection_get_count().
262  * The returned pointer should not be freed.
263  * If gmx_ana_selcollection_compile() has not been called, the returned
264  * selection is not completely initialized (but the returned pointer will be
265  * valid even after compilation, and will point to the initialized selection).
266  *
267  * \see gmx_ana_selcollection_get_count()
268  */
269 gmx_ana_selection_t *
270 gmx_ana_selcollection_get_selection(gmx_ana_selcollection_t *sc, int i)
271 {
272     if (i < 0 || i >= sc->nr || !sc->sel)
273         return NULL;
274     return sc->sel[i];
275 }
276
277 /*!
278  * \param[in]  sc  Selection collection to query.
279  * \returns    TRUE if any selection in \p sc requires topology information,
280  *   FALSE otherwise.
281  *
282  * Before gmx_ana_selcollection_parse_*(), the return value is based just on
283  * the position types set.
284  * After gmx_ana_selcollection_parse_*(), the return value also takes into account the
285  * selection keywords used.
286  */
287 gmx_bool
288 gmx_ana_selcollection_requires_top(gmx_ana_selcollection_t *sc)
289 {
290     t_selelem   *sel;
291     e_poscalc_t  type;
292     int          flags;
293     int          rc;
294
295     if (sc->rpost)
296     {
297         flags = 0;
298         rc = gmx_ana_poscalc_type_from_enum(sc->rpost, &type, &flags);
299         if (rc == 0 && type != POS_ATOM)
300         {
301             return TRUE;
302         }
303     }
304     if (sc->spost)
305     {
306         flags = 0;
307         rc = gmx_ana_poscalc_type_from_enum(sc->spost, &type, &flags);
308         if (rc == 0 && type != POS_ATOM)
309         {
310             return TRUE;
311         }
312     }
313
314     sel = sc->root;
315     while (sel)
316     {
317         if (_gmx_selelem_requires_top(sel))
318         {
319             return TRUE;
320         }
321         sel = sel->next;
322     }
323     return FALSE;
324 }
325
326 /*!
327  * \param[in] fp      File handle to receive the output.
328  * \param[in] sc      Selection collection to print.
329  * \param[in] bValues If TRUE, the evaluated values of selection elements
330  *   are printed as well.
331  */
332 void
333 gmx_ana_selcollection_print_tree(FILE *fp, gmx_ana_selcollection_t *sc, gmx_bool bValues)
334 {
335     t_selelem *sel;
336
337     sel = sc->root;
338     while (sel)
339     {
340         _gmx_selelem_print_tree(fp, sel, bValues, 0);
341         sel = sel->next;
342     }
343 }
344
345 /*!
346  * \param[in] sel  Selection to free.
347  *
348  * After the call, the pointer \p sel is invalid.
349  */
350 void
351 gmx_ana_selection_free(gmx_ana_selection_t *sel)
352 {
353     sfree(sel->name);
354     sfree(sel->selstr);
355     gmx_ana_pos_deinit(&sel->p);
356     if (sel->m != sel->orgm)
357     {
358         sfree(sel->m);
359     }
360     if (sel->q != sel->orgq)
361     {
362         sfree(sel->q);
363     }
364     sfree(sel->orgm);
365     sfree(sel->orgq);
366     sfree(sel);
367 }
368
369 /*!
370  * \param[in] sel  Selection whose name is needed.
371  * \returns   Pointer to the name of the selection.
372  *
373  * The return value should not be freed by the caller.
374  */
375 char *
376 gmx_ana_selection_name(gmx_ana_selection_t *sel)
377 {
378     return sel->name;
379 }
380
381 /*!
382  * \param[in] sel  Selection for which information should be printed.
383  */
384 void
385 gmx_ana_selection_print_info(gmx_ana_selection_t *sel)
386 {
387     fprintf(stderr, "\"%s\" (%d position%s, %d atom%s%s)", sel->name,
388             sel->p.nr,     sel->p.nr     == 1 ? "" : "s",
389             sel->g->isize, sel->g->isize == 1 ? "" : "s",
390             sel->bDynamic ? ", dynamic" : "");
391     fprintf(stderr, "\n");
392 }
393
394 /*!
395  * \param[in] sel  Selection to initialize.
396  * \param[in] type Type of covered fraction required.
397  * \returns   TRUE if the covered fraction can be calculated for the selection,
398  *   FALSE otherwise.    
399  */
400 gmx_bool
401 gmx_ana_selection_init_coverfrac(gmx_ana_selection_t *sel, e_coverfrac_t type)
402 {
403     sel->cfractype = type;
404     if (type == CFRAC_NONE || !sel->selelem)
405     {
406         sel->bCFracDyn = FALSE;
407     }
408     else if (!_gmx_selelem_can_estimate_cover(sel->selelem))
409     {
410         sel->cfractype = CFRAC_NONE;
411         sel->bCFracDyn = FALSE;
412     }
413     else
414     {
415         sel->bCFracDyn = TRUE;
416     }
417     sel->cfrac     = sel->bCFracDyn ? 0.0 : 1.0;
418     sel->avecfrac  = sel->cfrac;
419     return type == CFRAC_NONE || sel->cfractype != CFRAC_NONE;
420 }
421
422 /*!
423  * \param[in] out  Output file.
424  * \param[in] sc   Selection collection which should be written.
425  * \param[in] oenv Output options structure.
426  */
427 void xvgr_selcollection(FILE *out, gmx_ana_selcollection_t *sc,
428                         const output_env_t oenv)
429 {
430     int  i;
431
432     if (output_env_get_xvg_format(oenv) != exvgNONE && sc)
433     {
434         fprintf(out, "# Selections:\n");
435         for (i = 0; i < sc->nvars; ++i)
436         {
437             fprintf(out, "#   %s\n", sc->varstrs[i]);
438         }
439         for (i = 0; i < sc->nr; ++i)
440         {
441             fprintf(out, "#   %s\n", sc->sel[i]->selstr);
442         }
443         fprintf(out, "#\n");
444     }
445 }