Use Gromacs::gmx target to hint gmxapi tests.
[gromacs.git] / docs / doxygen / user / analysistemplate.md
blobf263297544d63a3e9a145e2af47bd7d6cd7d049b
1 Example code for writing trajectory analysis tools {#page_analysistemplate}
2 ==================================================
4 \Gromacs installation includes a template for writing trajectory analysis
5 tools using \ref page_analysisframework.
6 It can be found from `share/gromacs/template/` under the installation
7 directory, and from `share/template/` in the source distribution.
9 The full source code for the file is also included in this documentation:
10 \ref template.cpp "template.cpp"
11 The rest of this page walks through the code to explain the different parts.
13 \dontinclude template.cpp
15 Global definitions
16 ==================
18 We start by including some generic C++ headers:
19 \skip  <string>
20 \until <vector>
21 and continue by including the header for the analysis library:
22 \skipline <gromacs/trajectoryanalysis.h>
23 This header includes other headers that together define all the basic data
24 types needed for writing trajectory analysis tools.
25 For convenience, we also import all names from the ::gmx namespace into the
26 global scope to avoid repeating the name everywhere:
27 \skipline using namespace
30 Tool module class declaration
31 =============================
33 We then define a class that implements our analysis tool:
34 \skip  AnalysisTemplate
35 \until };
36 The analysis tool class inherits from gmx::TrajectoryAnalysisModule, which
37 is an interface with a few convenience functions for easier interfacing
38 with other code.
39 Below, we walk through the different methods as implemented in the
40 template (note that the template does not implement some of the virtual
41 methods because they are less often needed), discussing some issues that can
42 arise in more complex cases.
43 See documentation of gmx::TrajectoryAnalysisModule for a full description of
44 the available virtual methods and convenience functions.
45 The first block of member variables are used to contain values provided to
46 the different options.  They will vary depending on the needs of the
47 analysis tool.
48 The AnalysisNeighborhood object provides neighborhood searching that is used
49 in the analysis.
50 The final block of variables are used to process output data.
51 See initAnalysis() for details on how they are used.
53 For the template, we do not need any custom frame-local data.  If you think
54 you need some for more complex analysis needs, see documentation of
55 gmx::TrajectoryAnalysisModuleData for more details.
56 If you do not care about parallelization, you do not need to consider this
57 part.  You can simply declare all variables in the module class itself,
58 initialize them in gmx::TrajectoryAnalysisModule::initAnalysis(), and do any
59 postprocessing in gmx::TrajectoryAnalysisModule::finishAnalysis()).
62 Construction
63 ============
65 The constructor (and possible destructor) of the analysis module should be
66 simple: the constructor should just initialize default values, and the
67 destructor should free any memory managed by the module.  For the template,
68 we have no attributes in our class that need to be explicitly freed, so we
69 declare only a constructor:
70 \skip  AnalysisTemplate
71 \until }
74 Input options
75 =============
77 Initialization of the module is split into a few methods, two of which are
78 used in the template.  gmx::TrajectoryAnalysisModule::initOptions() is used
79 to set up options understood by the module, as well as for setting up
80 different options through gmx::TrajectoryAnalysisSettings (see the
81 documentation of that class for more details):
82 \skip  void
83 \until settings->
84 \until }
85 For the template, we first set a description text for the tool (used for
86 help text).  Then we declare an option to specify the output file name,
87 followed by options that are used to set selections, and finally an option
88 to set a cutoff value.  For the cutoff, the default value will be the one
89 that was set in the constructor, but it would also be possible to explicitly
90 set it here.  The values provided by the user for the options will be stored
91 in member variables.  Finally, we indicate that the tool always requires
92 topology information.  This is done for demonstration purposes only; the
93 code in the template works even without a topology.
95 For additional documentation on how to define different kinds of options, see
96 gmx::IOptionsContainer, basicoptions.h, and gmx::SelectionOption.  You only need to
97 define options that are specific to the analysis; common options, e.g., for
98 specifying input topology and trajectories are added by the framework.
100 To adjust settings or selection options (e.g., the number of accepted
101 selections) based on option values, you need to override
102 gmx::TrajectoryAnalysisModule::optionsFinished().  For simplicity,
103 this is not done in the template.
106 Analysis initialization
107 =======================
109 The actual analysis is initialized in
110 gmx::TrajectoryAnalysisModule::initAnalysis():
111 \skip  void
112 \until }
113 \until }
114 Information about the topology is passed as a parameter.  The settings
115 object can also be used to access information about user input.
117 One of the main tasks of this method is to set up appropriate
118 gmx::AnalysisData objects and modules for them (see
119 gmx::TrajectoryAnalysisModule for the general approach).
120 These objects will be used to process output from the tool.  Their main
121 purpose is to support parallelization, but even if you don't care about
122 parallelism, they still provide convenient building blocks, e.g., for
123 histogramming and file output.
125 For the template, we first set the cutoff for the neighborhood search.
127 Then, we create and register one gmx::AnalysisData object
128 that will contain, for each frame, one column for each input selection.
129 This will contain the main output from the tool: minimum distance between
130 the reference selection and that particular selection.
131 We then create and setup a module that will compute the average distance
132 for each selection (see writeOutput() for how it is used).
133 Finally, if an output file has been provided, we create and setup a module
134 that will plot the per-frame distances to a file.
136 If the analysis module needs some temporary storage during processing of a
137 frame (i.e., it uses a custom class derived from
138 gmx::TrajectoryAnalysisModuleData), this should be allocated in
139 gmx::TrajectoryAnalysisModule::startFrames() (see below) if parallelization
140 is to be supported.
142 If you need to do initialization based on data from the first frame (most
143 commonly, based on the box size), you need to override
144 gmx::TrajectoryAnalysisModule::initAfterFirstFrame(), but this is not used
145 in the template.
148 Analyzing the frames
149 ====================
151 There is one more initialization method that needs to be overridden to
152 support automatic parallelization: gmx::TrajectoryAnalysisModule::startFrames().
153 If you do not need custom frame-local data (or parallelization at all), you
154 can skip this method and ignore the last parameter to
155 gmx::TrajectoryAnalysisModule::analyzeFrame() to make things simpler.
156 In the template, this method is not necessary.
158 The main part of the analysis is (in most analysis codes) done in the
159 gmx::TrajectoryAnalysisModule::analyzeFrame() method, which is called once
160 for each frame:
161 \skip  void
162 \until {
163 The \p frnr parameter gives a zero-based index of the current frame
164 (mostly for use with gmx::AnalysisData), \p pbc contains the PBC
165 information for the current frame for distance calculations with,
166 e.g., pbc_dx(), and \p pdata points to a data structure created in
167 startFrames().
168 Although usually not necessary (except for the time field), raw frame
169 data can be accessed through \p fr.
170 In most cases, the analysis should be written such that it gets all
171 position data through selections, and does not assume a constant size for
172 them.  This is all that is required to support the full flexibility of the
173 selection engine.
175 For the template, we first get data from our custom data structure for
176 shorthand access (if you use a custom data object, you need a \c static_cast
177 here):
178 \skip  AnalysisDataHandle
179 \until parallelSelection
181 We then do a simple calculation and use the AnalysisDataHandle class to set
182 the per-frame output for the tool:
183 \skip  nb
184 \until finishFrame()
186 After all the frames have been processed,
187 gmx::TrajectoryAnalysisModule::finishAnalysis() is called once.  This is the
188 place to do any custom postprocessing of the data.  For the template, we do
189 nothing, because all necessary processing is done in the data modules:
190 \skip  void
191 \until }
193 If the data structure created in gmx::TrajectoryAnalysisModule::startFrames()
194 is used to aggregate data across frames, you need to override
195 gmx::TrajectoryAnalysisModule::finishFrames() to combine the data from the
196 data structures (see documentation of the method for details).
197 This is not necessary for the template, because the ModuleData structure
198 only contains data used during the analysis of a single frame.
201 Output
202 ======
204 Finally, most programs need to write out some values after the analysis is
205 complete.  In some cases, this can be achieved with proper chaining of data
206 modules, but often it is necessary to do some custom processing.
207 All such activities should be done in
208 gmx::TrajectoryAnalysisModule::writeOutput().  This makes it easier to reuse
209 analysis modules in, e.g., scripting languages, where output into files
210 might not be desired.  The template simply prints out the average distances
211 for each analysis group:
212 \skip  void
213 \until }
214 \until }
215 Here, we use the \c avem_ module, which we initialized in initAnalysis() to
216 aggregate the averages of the computed distances.
219 Definition of main()
220 ====================
222 Now, the only thing remaining is to define the main() function.
223 To implement a command-line tool, it should create a module and run it using
224 gmx::TrajectoryAnalysisCommandLineRunner using the boilerplate code below:
225 \skip  int
226 \until }
229 \if libapi
230 Tools within \Gromacs
231 ====================
233 Analysis tools implemented using the template can also be easily included into
234 the \Gromacs library.  To do this, follow these steps:
236  1. Put your tool source code into `src/gromacs/trajectoryanalysis/modules/`.
237  2. Remove `using namespace gmx;` and enclose all the code into
238     `gmx::analysismodules` namespace, and the tool class into an unnamed
239     namespace within this.
240  3. Create a header file corresponding to your tool and add the following class
241     into it withing `gmx::analysismodules` namespace (replace `Template` with
242     the name of your tool):
243 ~~~~{.cpp}
244     class TemplateInfo
245     {
246         public:
247             static const char name[];
248             static const char shortDescription[];
249             static TrajectoryAnalysisModulePointer create();
250     };
251 ~~~~
252  4. Add definition for these items in the source file, outside the unnamed
253     namespace (replace `Template`, `AnalysisTemplate` and the strings with
254     correct values):
255 ~~~~{.cpp}
256     const char TemplateInfo::name[]             = "template";
257     const char TemplateInfo::shortDescription[] =
258         "Compute something";
260     TrajectoryAnalysisModulePointer TemplateInfo::create()
261     {
262         return TrajectoryAnalysisModulePointer(new AnalysisTemplate);
263     }
264 ~~~~
265  5. Register your module in `src/gromacs/trajectoryanalysis/modules.cpp`.
266  6. Done.  Your tool can now be invoked as `gmx template`, using the string you
267     specified as the name.
269 See existing tools within the `src/gromacs/trajectoryanalysis/modules/` for
270 concrete examples and preferred layout of the files.  Please document yourself
271 as the author of the files, using Doxygen comments like in the existing files.
273 \endif