Update copyright statements and change license to LGPL
[alexxy/gromacs.git] / src / gmxlib / selection / selhelp.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, 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 Implementation of functions in selhelp.c.
40  */
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif
44
45 #include <macros.h>
46 #include <string2.h>
47 #include <wman.h>
48
49 #include "selcollection.h"
50 #include "selmethod.h"
51 #include "selhelp.h"
52 #include "symrec.h"
53
54 typedef struct {
55     const char  *topic;
56     int          nl;
57     const char **text;
58 } t_selection_help_item;
59
60 static const char *help_common[] = {
61     "SELECTION HELP[PAR]",
62
63     "This program supports selections in addition to traditional index files.",
64     "Please read the subtopic pages (available through \"help topic\") for",
65     "more information.",
66     "Explanation of command-line arguments for specifying selections can be",
67     "found under the \"cmdline\" subtopic, and general selection syntax is",
68     "described under \"syntax\". Available keywords can be found under",
69     "\"keywords\", and concrete examples under \"examples\".",
70     "Other subtopics give more details on certain aspects.",
71     "\"help all\" prints the help for all subtopics.",
72 };
73
74 static const char *help_arithmetic[] = {
75     "ARITHMETIC EXPRESSIONS IN SELECTIONS[PAR]",
76
77     "Basic arithmetic evaluation is supported for numeric expressions.",
78     "Supported operations are addition, subtraction, negation, multiplication,",
79     "division, and exponentiation (using ^).",
80     "Result of a division by zero or other illegal operations is undefined.",
81 };
82
83 static const char *help_cmdline[] = {
84     "SELECTION COMMAND-LINE ARGUMENTS[PAR]",
85
86     "There are two alternative command-line arguments for specifying",
87     "selections:[BR]",
88     "1. [TT]-select[tt] can be used to specify the complete selection as a",
89     "string on the command line.[BR]",
90     "2. [TT]-sf[tt] can be used to specify a file name from which the",
91     "selection is read.[BR]",
92     "If both options are specified, [TT]-select[tt] takes precedence.",
93     "If neither of the above is present, the user is prompted to type the",
94     "selection on the standard input (a pipe can also be used to provide",
95     "the selections in this case).",
96     "This is also done if an empty string is passed to [TT]-select[tt].[PAR]",
97
98     "Option [TT]-n[tt] can be used to provide an index file.",
99     "If no index file is provided, default groups are generated.",
100     "In both cases, the user can also select an index group instead of",
101     "writing a full selection.",
102     "The default groups are generated by reading selections from a file",
103     "[TT]defselection.dat[tt]. If such a file is found in the current",
104     "directory, it is used instead of the one provided by default.[PAR]",
105
106     "Depending on the tool, two additional command-line arguments may be",
107     "available to control the behavior:[BR]",
108     "1. [TT]-seltype[tt] can be used to specify the default type of",
109     "positions to calculate for each selection.[BR]",
110     "2. [TT]-selrpos[tt] can be used to specify the default type of",
111     "positions used in selecting atoms by coordinates.[BR]",
112     "See \"help positions\" for more information on these options.",
113 };
114
115 static const char *help_eval[] = {
116     "SELECTION EVALUATION AND OPTIMIZATION[PAR]",
117
118     "Boolean evaluation proceeds from left to right and is short-circuiting",
119     "i.e., as soon as it is known whether an atom will be selected, the",
120     "remaining expressions are not evaluated at all.",
121     "This can be used to optimize the selections: you should write the",
122     "most restrictive and/or the most inexpensive expressions first in",
123     "boolean expressions.",
124     "The relative ordering between dynamic and static expressions does not",
125     "matter: all static expressions are evaluated only once, before the first",
126     "frame, and the result becomes the leftmost expression.[PAR]",
127
128     "Another point for optimization is in common subexpressions: they are not",
129     "automatically recognized, but can be manually optimized by the use of",
130     "variables. This can have a big impact on the performance of complex",
131     "selections, in particular if you define several index groups like this:",
132     "  [TT]rdist = distance from com of resnr 1 to 5;[tt][BR]",
133     "  [TT]resname RES and rdist < 2;[tt][BR]",
134     "  [TT]resname RES and rdist < 4;[tt][BR]",
135     "  [TT]resname RES and rdist < 6;[tt][BR]",
136     "Without the variable assignment, the distances would be evaluated three",
137     "times, although they are exactly the same within each selection.",
138     "Anything assigned into a variable becomes a common subexpression that",
139     "is evaluated only once during a frame.",
140     "Currently, in some cases the use of variables can actually lead to a small",
141     "performance loss because of the checks necessary to determine for which",
142     "atoms the expression has already been evaluated, but this should not be",
143     "a major problem.",
144 };
145
146 static const char *help_examples[] = {
147     "SELECTION EXAMPLES[PAR]",
148
149     "Below, examples of increasingly complex selections are given.[PAR]",
150
151     "Selection of all water oxygens:[BR]",
152     "  resname SOL and name OW",
153     "[PAR]",
154
155     "Centers of mass of residues 1 to 5 and 10:[BR]",
156     "  res_com of resnr 1 to 5 10",
157     "[PAR]",
158
159     "All atoms farther than 1 nm of a fixed position:[BR]",
160     "  not within 1 of (1.2, 3.1, 2.4)",
161     "[PAR]",
162
163     "All atoms of a residue LIG within 0.5 nm of a protein (with a custom name):[BR]",
164     "  \"Close to protein\" resname LIG and within 0.5 of group \"Protein\"",
165     "[PAR]",
166
167     "All protein residues that have at least one atom within 0.5 nm of a residue LIG:[BR]",
168     "  group \"Protein\" and same residue as within 0.5 of resname LIG",
169     "[PAR]",
170
171     "All RES residues whose COM is between 2 and 4 nm from the COM of all of them:[BR]",
172     "  rdist = res_com distance from com of resname RES[BR]",
173     "  resname RES and rdist >= 2 and rdist <= 4",
174     "[PAR]",
175
176     "Selection like C1 C2 C2 C3 C3 C4 ... C8 C9 (e.g., for g_bond):[BR]",
177     "  name \"C[1-8]\" merge name \"C[2-9]\"",
178 };
179
180 static const char *help_keywords[] = {
181     "SELECTION KEYWORDS[PAR]",
182
183     "The following selection keywords are currently available.",
184     "For keywords marked with a star, additional help is available through",
185     "\"help KEYWORD\", where KEYWORD is the name of the keyword.",
186 };
187
188 static const char *help_limits[] = {
189     "SELECTION LIMITATIONS[PAR]",
190
191     "Some analysis programs may require a special structure for the input",
192     "selections (e.g., [TT]g_angle[tt] requires the index group to be made",
193     "of groups of three or four atoms).",
194     "For such programs, it is up to the user to provide a proper selection",
195     "expression that always returns such positions.",
196     "[PAR]",
197
198     "Due to technical reasons, having a negative value as the first value in",
199     "expressions like[BR]",
200     "[TT]charge -1 to -0.7[tt][BR]",
201     "result in a syntax error. A workaround is to write[BR]",
202     "[TT]charge {-1 to -0.7}[tt][BR]",
203     "instead.[PAR]",
204
205     "When [TT]name[tt] selection keyword is used together with PDB input",
206     "files, the behavior may be unintuitive. When Gromacs reads in a PDB",
207     "file, 4 character atom names that start with a digit are transformed",
208     "such that, e.g., 1HG2 becomes HG21, and the latter is what is matched",
209     "by the [TT]name[tt] keyword. Use [TT]pdbname[tt] to match the atom name",
210     "as it appears in the input PDB file.",
211 };
212
213 static const char *help_positions[] = {
214     "SPECIFYING POSITIONS[PAR]",
215
216     "Possible ways of specifying positions in selections are:[PAR]",
217
218     "1. A constant position can be defined as [TT][XX, YY, ZZ][tt], where",
219     "[TT]XX[tt], [TT]YY[tt] and [TT]ZZ[tt] are real numbers.[PAR]",
220
221     "2. [TT]com of ATOM_EXPR [pbc][tt] or [TT]cog of ATOM_EXPR [pbc][tt]",
222     "calculate the center of mass/geometry of [TT]ATOM_EXPR[tt]. If",
223     "[TT]pbc[tt] is specified, the center is calculated iteratively to try",
224     "to deal with cases where [TT]ATOM_EXPR[tt] wraps around periodic",
225     "boundary conditions.[PAR]",
226
227     "3. [TT]POSTYPE of ATOM_EXPR[tt] calculates the specified positions for",
228     "the atoms in [TT]ATOM_EXPR[tt].",
229     "[TT]POSTYPE[tt] can be [TT]atom[tt], [TT]res_com[tt], [TT]res_cog[tt],",
230     "[TT]mol_com[tt] or [TT]mol_cog[tt], with an optional prefix [TT]whole_[tt]",
231     "[TT]part_[tt] or [TT]dyn_[tt].",
232     "[TT]whole_[tt] calculates the centers for the whole residue/molecule,",
233     "even if only part of it is selected.",
234     "[TT]part_[tt] prefix calculates the centers for the selected atoms, but",
235     "uses always the same atoms for the same residue/molecule. The used atoms",
236     "are determined from the the largest group allowed by the selection.",
237     "[TT]dyn_[tt] calculates the centers strictly only for the selected atoms.",
238     "If no prefix is specified, whole selections default to [TT]part_[tt] and",
239     "other places default to [TT]whole_[tt].",
240     "The latter is often desirable to select the same molecules in different",
241     "tools, while the first is a compromise between speed ([TT]dyn_[tt]",
242     "positions can be slower to evaluate than [TT]part_[tt]) and intuitive",
243     "behavior.[PAR]",
244
245     "4. [TT]ATOM_EXPR[tt], when given for whole selections, is handled as 3.",
246     "above, using the position type from the command-line argument",
247     "[TT]-seltype[tt].[PAR]",
248
249     "Selection keywords that select atoms based on their positions, such as",
250     "[TT]dist from[tt], use by default the positions defined by the",
251     "[TT]-selrpos[tt] command-line option.",
252     "This can be overridden by prepending a [TT]POSTYPE[tt] specifier to the",
253     "keyword. For example, [TT]res_com dist from POS[tt] evaluates the",
254     "residue center of mass distances. In the example, all atoms of a residue",
255     "are either selected or not, based on the single distance calculated.",
256 };
257
258 static const char *help_syntax[] = {
259     "SELECTION SYNTAX[PAR]",
260
261     "A set of selections consists of one or more selections, separated by",
262     "semicolons. Each selection defines a set of positions for the analysis.",
263     "Each selection can also be preceded by a string that gives a name for",
264     "the selection for use in, e.g., graph legends.",
265     "If no name is provided, the string used for the selection is used",
266     "automatically as the name.[PAR]",
267
268     "For interactive input, the syntax is slightly altered: line breaks can",
269     "also be used to separate selections. \\ followed by a line break can",
270     "be used to continue a line if necessary.",
271     "Notice that the above only applies to real interactive input,",
272     "not if you provide the selections, e.g., from a pipe.[PAR]",
273
274     "It is possible to use variables to store selection expressions.",
275     "A variable is defined with the following syntax:[BR]",
276     "[TT]VARNAME = EXPR ;[tt][BR]",
277     "where [TT]EXPR[tt] is any valid selection expression.",
278     "After this, [TT]VARNAME[tt] can be used anywhere where [TT]EXPR[tt]",
279     "would be valid.[PAR]",
280
281     "Selections are composed of three main types of expressions, those that",
282     "define atoms ([TT]ATOM_EXPR[tt]s), those that define positions",
283     "([TT]POS_EXPR[tt]s), and those that evaluate to numeric values",
284     "([TT]NUM_EXPR[tt]s). Each selection should be a [TT]POS_EXPR[tt]",
285     "or a [TT]ATOM_EXPR[tt] (the latter is automatically converted to",
286     "positions). The basic rules are as follows:[BR]",
287     "1. An expression like [TT]NUM_EXPR1 < NUM_EXPR2[tt] evaluates to an",
288     "[TT]ATOM_EXPR[tt] that selects all the atoms for which the comparison",
289     "is true.[BR]",
290     "2. Atom expressions can be combined with gmx_boolean operations such as",
291     "[TT]not ATOM_EXPR[tt], [TT]ATOM_EXPR and ATOM_EXPR[tt], or",
292     "[TT]ATOM_EXPR or ATOM_EXPR[tt]. Parentheses can be used to alter the",
293     "evaluation order.[BR]",
294     "3. [TT]ATOM_EXPR[tt] expressions can be converted into [TT]POS_EXPR[tt]",
295     "expressions in various ways, see \"help positions\" for more details.[PAR]",
296
297     "Some keywords select atoms based on string values such as the atom name.",
298     "For these keywords, it is possible to use wildcards ([TT]name \"C*\"[tt])",
299     "or regular expressions (e.g., [TT]resname \"R[AB]\"[tt]).",
300     "The match type is automatically guessed from the string: if it contains",
301     "other characters than letters, numbers, '*', or '?', it is interpreted",
302     "as a regular expression.",
303     "Strings that contain non-alphanumeric characters should be enclosed in",
304     "double quotes as in the examples. For other strings, the quotes are",
305     "optional, but if the value conflicts with a reserved keyword, a syntax",
306     "error will occur. If your strings contain uppercase letters, this should",
307     "not happen.[PAR]",
308
309     "Index groups provided with the [TT]-n[tt] command-line option or",
310     "generated by default can be accessed with [TT]group NR[tt] or",
311     "[TT]group NAME[tt], where [TT]NR[tt] is a zero-based index of the group",
312     "and [TT]NAME[tt] is part of the name of the desired group.",
313     "The keyword [TT]group[tt] is optional if the whole selection is",
314     "provided from an index group.",
315     "To see a list of available groups in the interactive mode, press enter",
316     "in the beginning of a line.",
317 };
318
319 static const t_selection_help_item helpitems[] = {
320     {NULL,          asize(help_common),     help_common},
321     {"cmdline",     asize(help_cmdline),    help_cmdline},
322     {"syntax",      asize(help_syntax),     help_syntax},
323     {"positions",   asize(help_positions),  help_positions},
324     {"arithmetic",  asize(help_arithmetic), help_arithmetic},
325     {"keywords",    asize(help_keywords),   help_keywords},
326     {"evaluation",  asize(help_eval),       help_eval},
327     {"limitations", asize(help_limits),     help_limits},
328     {"examples",    asize(help_examples),   help_examples},
329 };
330
331 /*! \brief
332  * Prints a brief list of keywords (selection methods) available.
333  *
334  * \param[in] sc    Selection collection for which the list should be printed.
335  * \param[in] type  Only methods that return this type are printed.
336  * \param[in] bMod  If FALSE, \ref SMETH_MODIFIER methods are excluded, otherwise
337  *     only them are printed.
338  */
339 static void
340 print_keyword_list(struct gmx_ana_selcollection_t *sc, e_selvalue_t type,
341                    gmx_bool bMod)
342 {
343     gmx_sel_symrec_t *symbol;
344
345     symbol = _gmx_sel_first_symbol(sc->symtab, SYMBOL_METHOD);
346     while (symbol)
347     {
348         gmx_ana_selmethod_t *method = _gmx_sel_sym_value_method(symbol);
349         gmx_bool                 bShow;
350         bShow = (method->type == type)
351             && ((bMod && (method->flags & SMETH_MODIFIER))
352                 || (!bMod && !(method->flags & SMETH_MODIFIER)));
353         if (bShow)
354         {
355             fprintf(stderr, " %c ",
356                     (method->help.nlhelp > 0 && method->help.help) ? '*' : ' ');
357             if (method->help.syntax)
358             {
359                 fprintf(stderr, "%s\n", method->help.syntax);
360             }
361             else
362             {
363                 const char *symname = _gmx_sel_sym_name(symbol);
364
365                 fprintf(stderr, "%s", symname);
366                 if (strcmp(symname, method->name) != 0)
367                 {
368                     fprintf(stderr, " (synonym for %s)", method->name);
369                 }
370                 fprintf(stderr, "\n");
371             }
372         }
373         symbol = _gmx_sel_next_symbol(symbol, SYMBOL_METHOD);
374     }
375 }
376
377 /*!
378  * \param[in]  sc    Selection collection for which help should be printed.
379  * \param[in]  topic Topic to print help on, or NULL for general help.
380  *
381  * \p sc is used to get information on which keywords are available in the
382  * present context.
383  */
384 void
385 _gmx_sel_print_help(struct gmx_ana_selcollection_t *sc, const char *topic)
386 {
387     const t_selection_help_item *item = NULL;
388     size_t i;
389
390     /* Find the item for the topic */
391     if (!topic)
392     {
393         item = &helpitems[0];
394     }
395     else if (strcmp(topic, "all") == 0)
396     {
397         for (i = 0; i < asize(helpitems); ++i)
398         {
399             item = &helpitems[i];
400             _gmx_sel_print_help(sc, item->topic);
401             if (i != asize(helpitems) - 1)
402             {
403                 fprintf(stderr, "\n\n");
404             }
405         }
406         return;
407     }
408     else
409     {
410         for (i = 1; i < asize(helpitems); ++i)
411         {
412             if (strncmp(helpitems[i].topic, topic, strlen(topic)) == 0)
413             {
414                 item = &helpitems[i];
415                 break;
416             }
417         }
418     }
419     /* If the topic is not found, check the available methods.
420      * If they don't provide any help either, tell the user and exit. */
421     if (!item)
422     {
423         gmx_sel_symrec_t *symbol;
424
425         symbol = _gmx_sel_first_symbol(sc->symtab, SYMBOL_METHOD);
426         while (symbol)
427         {
428             gmx_ana_selmethod_t *method = _gmx_sel_sym_value_method(symbol);
429             if (method->help.nlhelp > 0 && method->help.help
430                 && strncmp(method->name, topic, strlen(topic)) == 0)
431             {
432                 print_tty_formatted(stderr, method->help.nlhelp,
433                         method->help.help, 0, NULL, NULL, FALSE);
434                 return;
435             }
436             symbol = _gmx_sel_next_symbol(symbol, SYMBOL_METHOD);
437         }
438
439         fprintf(stderr, "No help available for '%s'.\n", topic);
440         return;
441     }
442     /* Print the help */
443     print_tty_formatted(stderr, item->nl, item->text, 0, NULL, NULL, FALSE);
444     /* Special handling of certain pages */
445     if (!topic)
446     {
447         int len = 0;
448
449         /* Print the subtopics on the main page */
450         fprintf(stderr, "\nAvailable subtopics:\n");
451         for (i = 1; i < asize(helpitems); ++i)
452         {
453             int len1 = strlen(helpitems[i].topic) + 2;
454
455             len += len1;
456             if (len > 79)
457             {
458                 fprintf(stderr, "\n");
459                 len = len1;
460             }
461             fprintf(stderr, "  %s", helpitems[i].topic);
462         }
463         fprintf(stderr, "\n");
464     }
465     else if (strcmp(item->topic, "keywords") == 0)
466     {
467         /* Print the list of keywords */
468         fprintf(stderr, "\nKeywords that select atoms by an integer property:\n");
469         fprintf(stderr, "(use in expressions or like \"atomnr 1 to 5 7 9\")\n");
470         print_keyword_list(sc, INT_VALUE, FALSE);
471
472         fprintf(stderr, "\nKeywords that select atoms by a numeric property:\n");
473         fprintf(stderr, "(use in expressions or like \"occupancy 0.5 to 1\")\n");
474         print_keyword_list(sc, REAL_VALUE, FALSE);
475
476         fprintf(stderr, "\nKeywords that select atoms by a string property:\n");
477         fprintf(stderr, "(use like \"name PATTERN [PATTERN] ...\")\n");
478         print_keyword_list(sc, STR_VALUE, FALSE);
479
480         fprintf(stderr, "\nAdditional keywords that directly select atoms:\n");
481         print_keyword_list(sc, GROUP_VALUE, FALSE);
482
483         fprintf(stderr, "\nKeywords that directly evaluate to positions:\n");
484         fprintf(stderr, "(see also \"help positions\")\n");
485         print_keyword_list(sc, POS_VALUE, FALSE);
486
487         fprintf(stderr, "\nAdditional keywords:\n");
488         print_keyword_list(sc, POS_VALUE, TRUE);
489         print_keyword_list(sc, NO_VALUE, TRUE);
490     }
491 }