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