Minor clean-up to sample_restraint tests.
[alexxy/gromacs.git] / python_packaging / sample_restraint / README.md
1 Sample MD restraint plugin
2 ==========================
3
4 This [repository](https://github.com/kassonlab/sample_restraint)
5 provides a complete and working implementation of a few GROMACS
6 restraint potentials. It is intended as both a tutorial and as a
7 template for implementing new custom restraint potentials.
8
9 Restraint potentials are implemented as \"plugins\" to GROMACS.
10 GROMACS must be [configured with
11 GMXAPI=ON](http://manual.gromacs.org/current/install-guide/index.html#gmxapi-external-api)
12
13 The plugin potentials are loaded and configured via Python and are
14 compatible with the [gmxapi](https://github.com/kassonlab/gmxapi) Python
15 package for MD simulation workflows.
16
17 For a quick start, consider pulling a recent Docker image that has
18 already been configured for gmxapi and this plug-in.
19 **todo:** check and update (ref: [GitHub issue 230](https://github.com/kassonlab/gmxapi/issues/230))
20
21 Reference:
22
23 Irrgang, M. E., Hays, J. M., & Kasson, P. M. gmxapi: a high-level
24 interface for advanced control and extension of molecular dynamics
25 simulations. *Bioinformatics* 2018. DOI:
26 [10.1093/bioinformatics/bty484](https://doi.org/10.1093/bioinformatics/bty484)
27
28 Repository Contents
29 -------------------
30
31 This repository uses CMake to build and install a Python C++ extension
32 package.
33
34 -   `CMakeLists.txt`, `cmake/FindGROMACS.cmake`, and
35     `src/CMakeLists.txt` provide necessary CMake infrastructure. You
36     should not need to edit these.
37 -   `src/cpp` contains a header and `cpp` file for each restraint
38     potential built with this module. When adding new potentials, you
39     will update `CMakeLists.txt` to create build targets. Use the
40     existing potentials as examples.
41 -   `src/pythonmodule/` contains `CMakeLists.txt`, `export_plugin.h`,
42     and `export_plugin.cpp`. When you have written a new potential, you
43     can add it to `CMakeLists.txt` and `export_plugin.cpp`. This is the
44     code that produces the C++ extension for Python.
45     `EnsemblePotential` applies a restrained ensemble potential and
46     uses additional facilities provided by gmxapi.
47 -   <strike>`src/pybind11` is just a copy of the Python bindings framework from
48     the Pybind project (ref <https://github.com/pybind/pybind11> ). It
49     is used to wrap the C++ restraint code and give it a Python
50     interface.</strike> Note: pybind is currently retrieved while configuring
51     with CMake. Ref issues [3027](https://gitlab.com/gromacs/gromacs/-/issues/3027)
52     and [3033](https://gitlab.com/gromacs/gromacs/-/issues/3033)
53 -   `tests/` contains C++ and Python tests for the provided code. Update
54     `CMakeLists.txt` to add your own, based on these examples. C++ unit
55     tests use [googletest](https://github.com/google/googletest). Python
56     tests use the [pytest](https://docs.pytest.org/en/latest/). Refer to
57     those respective projects for more about how they make test-writing
58     easier. Note: googletest is currently downloaded while configuring with
59     CMake. Ref [3033](https://gitlab.com/gromacs/gromacs/-/issues/3033)
60 -   `examples` contains a sample SLURM job script and
61     `restrained-ensemble.py` gmxapi script that have been used to do
62     restrained ensemble simulations. `example.py` and `example.ipynb`
63     explore a toy alanine dipeptide system. `strip_notebook.py` is a
64     helper script to remove extra output and state data from an iPython
65     notebook before checking updates back into the repository.
66 -   `Dockerfile` is a recipe to build a Docker image from the root of
67     the repository. **todo:** Check and update.
68     ref: GitHub issue [230](https://github.com/kassonlab/gmxapi/issues/230)
69
70 Docker quick-start
71 ------------------
72
73 **todo: check and update** ref: [GitHub issue 230](https://github.com/kassonlab/gmxapi/issues/230)
74
75 Pull the docker image and launch a container with port 8888 on the host
76 mapped to port 8888 in the container. :
77
78     docker run --rm -ti -p 8888:8888 gmxapi/sample_restraint:devel
79
80 Note that the `--rm` option tells docker not to save any changes you
81 make after launching the container. You can, however, download any
82 changes you make to the notebook through the web interface. Refer to the
83 [Docker documentation](https://docs.docker.com) for more options on
84 managing containers.
85
86 You should then see something like the following, but with a different
87 `token` for the URL. Open the URL in a browser on the same (host)
88 machine to access the notebook server. Browse to `sample_restraint` and
89 `examples` and then launch the `example` notebook for an interactive
90 walk-through. Example output:
91
92     Execute the command: jupyter notebook
93     [I 15:26:07.683 NotebookApp] Writing notebook server cookie secret to /home/jovyan/.local/share/jupyter/runtime/notebook_cookie_secret
94     [W 15:26:08.184 NotebookApp] WARNING: The notebook server is listening on all IP addresses and not using encryption. This is not recommended.
95     [I 15:26:08.223 NotebookApp] JupyterLab alpha preview extension loaded from /opt/conda/lib/python3.6/site-packages/jupyterlab
96     [I 15:26:08.230 NotebookApp] Serving notebooks from local directory: /home/jovyan
97     [I 15:26:08.230 NotebookApp] 0 active kernels
98     [I 15:26:08.230 NotebookApp] The Jupyter Notebook is running at:
99     [I 15:26:08.230 NotebookApp] http://[all ip addresses on your system]:8888/?token=948d611453ea3f03ad406dc375bfc186c4315fa68c50e23d
100     [I 15:26:08.230 NotebookApp] Use Control-C to stop this server and shut down all kernels (twice to skip confirmation).
101     [C 15:26:08.231 NotebookApp]
102
103         Copy/paste this URL into your browser when you connect for the first time,
104         to login with a token:
105             http://localhost:8888/?token=948d611453ea3f03ad406dc375bfc186c4315fa68c50e23d
106
107 The basics
108 ----------
109
110 This repository provides a potentially useful plugin, but also serves as
111 documentation by example and as a template for developing GROMACS
112 extension code in the gmxapi framework.
113
114 ### Build and install
115
116 To download, build, and install, you may need to first install `wget`,
117 `git`, and/or `cmake`.
118
119 The plugin requires libgmxapi to build. See
120 [gmxapi](http://manual.gromacs.org/current/install-guide/index.html#gmxapi-external-api).
121 Download an official release from http://www.gromacs.org or the latest gmxapi
122 development branch from https://github.com/kassonlab/gmxapi/
123
124 We use CMake to configure and build a C++ library and a Python module
125 for interacting with it.
126
127 After installing GROMACS, either source the GMXRC file provided with the GROMACS
128 installation or set `gmxapi_DIR` to the GROMACS installation path.
129
130 The GROMACS installation provides some additional CMake infrastructure to help us build compatible client software.
131 To help set the correct compilers, specify the CMake toolchains file with,
132 *e.g.*, `-DCMAKE_TOOLCHAIN_FILE=/usr/local/gromacs/share/cmake/gromacs/gromacs-toolchain.cmake` (for GROMACS installed
133  to `/usr/local/gromacs`).
134 **todo:** Link to GROMACS docs for the toolchains file.
135
136 We recommend installing and using this code in a Python virtual
137 environment. (See the documentation for your `gmxapi` distribution or
138 <http://gmxapi.readthedocs.io/en/latest/install.html> ) Accordingly, if
139 you choose to install the plugin rather than just to use it out of
140 its build directory, consider whether you want to have to set your
141 `PYTHONPATH` environment variable or where you can install it that
142 Python will find it. You can explicitly set the installation location by
143 setting `-DGMXPLUGIN_INSTALL_PATH=/path/to/install/directory` or you can
144 let CMake determine an appropriate location automatically for your
145 Python interpreter. If you have administrative privileges (such as when
146 running on a desktop computer) or if you are using a Python virtual
147 environment (recommended), you don\'t need to specify anything
148 additional. If you are an unprivileged user (such as on a shared
149 machine) and are not in a Python virtual environment, set
150 -DGMXPLUGIN\_USER\_INSTALL=ON to install into the \"user\" Python
151 packages directory in your home directory. (Equivalent to the `--user`
152 option to `pip`)
153
154 If you have multiple Python installations or just want to be
155 unambiguous, provide CMake with the Python interpreter you wish to use
156 (the same as you are using for `gmxapi`) with
157 `-DPYTHON_EXECUTABLE=/path/to/python3`.
158
159 From the root directory of the GROMACS source, the sample_restraint source code is in
160 `python_packaging/sample_restraint`
161
162     cd python_packaging/sample_restraint
163     mkdir build
164     cd build
165     # Get the GROMACS environment settings.
166     source $HOME/gromacs/bin/GMXRC
167     # Configure the build environment with CMake
168     cmake ..
169     # or
170     # cmake .. -DGMXPLUGIN_INSTALL_PATH=/path/to/install/directory
171     # or
172     # cmake .. -DGMXPLUGIN_USER_INSTALL=ON -DPYTHON_EXECUTABLE=`which python3`
173     # Build myplugin.
174     make
175     # build and run C++ tests
176     make tests
177     make test
178     # optionally, install
179     make install
180
181 If you choose not to install the plugin module, you can tell Python
182 where to find it by setting your PYTHONPATH environment variable. For
183 instance, while still in the build directory:
184
185     export PYTHONPATH=`pwd`/src/pythonmodule
186
187 The Python `gmxapi` package is required for testing.
188 See the [README.md](../README.md) 
189 file in the parent directory.
190
191 ### Running
192
193 The `examples` directory contains some sample scripts for running
194 `gmxapi` workflows using the restraint potential samples in this
195 repository. You may also find [tests/test_binding.py](tests/test_binding.py) informative.
196
197 For a basic walk-through with a toy system, launch a Jupyter notebook
198 server and navigate to `examples/example.py`
199
200 **todo** These scripts have not been checked since migrating to the GROMACS source repository.
201
202 ### What\'s going on
203
204 This sample project builds several C++ object files, which are used to build a
205 Python module named `myplugin`.
206
207 When setting up a workflow, a Python script provides gmxapi with
208 parameters and a factory function for a plugin restraint potential. This
209 Python interface is defined in `src/pythonmodule/export_plugin.cpp`.
210 When a Session is launched, a C++ object that performs restraint force
211 calculations is created and given to the GROMACS library. During each MD
212 step, part of the MD force evaluation includes a call to the
213 calculations performed by the restraint. For the pair restraints
214 demonstrated here, GROMACS provides relative coordinates of two atomic
215 sites to the calculation code in the plugin. If multiple restrained
216 pairs are needed, multiple restraints are attached to the simulation.
217 Coordination across an ensemble of simulations is possible using
218 resources provided by the Session.
219
220 Fundamentally, a new restraint potential is implemented by creating a
221 class that provides a `calculate()` method and using wrappers to give it
222 interfaces to GROMACS and to Python. C++ wrappers allow the basic class
223 implementing the potential to be presented to the GROMACS library in a
224 way that can be used to evaluate forces during a simulation. Other C++
225 template code wraps the potential in a portable way so that it can be
226 passed to GROMACS through a Python interface and to receive parameters
227 from the Python interpreter. Pybind11 syntax in `export_plugin.cpp`
228 provides the code to actually expose the plugin as a class in a Python
229 module that is compatible with the `gmx` package provided in the
230 `gmxapi` project.
231
232 By version 0.1.0, additional wrappers and boilerplate code will be
233 migrated out of the files that define the `calculate()` methods. Until
234 then, some amount of copy-and-paste or editing is necessary to implement
235 a new potential. Refer to `src/cpp/harmonicpotential.h` and to
236 `src/cpp/harmonicpotential.cpp` for a documented example of a simple
237 pair restraint. A more complex example is found in the
238 `ensemblepotential` files. The code in `src/cpp` is sufficient to
239 produce testable object code, but the Python module is exported in
240 `src/pythonmodule/export_plugin.cpp`. If you add additional source files
241 for a new potential, you will need to update `src/cpp/CMakeLists.txt` as
242 well.
243
244 Python tests
245 ------------
246
247 For the Python-level testing, you will need `pytest` and `gmxapi`. We
248 recommend setting up a Python virtual environment as described in the gmxapi installation instructions.
249
250 You will also need a functioning MPI installation and the `mpi4py`
251 package.
252
253 Python tests can be run from the root directory of the repository after
254 building. Assuming you built in a subdirecory of the repository named
255 `build` (as above):
256
257     PYTHONPATH=build/src/pythonmodule/ python -m pytest tests
258
259 This command causes the directory named `tests` to be explored for
260 Python files with names like `test_*.py` or `*_test.py`. Matching files
261 will be imported and any functions with similarly obvious names will be
262 run and errors reported. In particular, `assert` statements will be
263 evaluated to perform individual tests. See also
264 <https://docs.pytest.org/en/latest/goodpractices.html#test-discovery>
265
266 The tests assume that the package is already installed or is available
267 on the default Python path (such as by setting the `PYTHONPATH`
268 environment variable). If you just run `pytest` with no arguments, it
269 will discover and try to run tests from elsewhere in the repository that
270 were not intended, and they will fail.
271
272 To run the full set of tests for the ensemble workflow features, first
273 make sure that you have an MPI-capable environment and `mpi4py`
274 installed. Refer to <http://mpi4py.readthedocs.io/en/stable/> and
275 <https://github.com/kassonlab/gmxapi> for more information.
276
277 The ensemble tests assume that 2 ranks are available. After installing
278 the plugin, run (for example):
279
280     mpiexec -n 2 python -m mpi4py -m pytest
281
282 **todo** check and update the following. (ref: [GitHub issue 230](https://github.com/kassonlab/gmxapi/issues/230))
283
284 If you do not have MPI set up for your system, you could build a docker
285 image using the Dockerfile in this repository.
286
287     docker build -t samplerestraint . Dockerfile
288     docker run --cpus 2 --rm -ti samplerestraint bash -c \
289         "cd /home/jovyan/sample_restraint/tests && 
290         mpiexec -n 2 python -m mpi4py -m pytest"
291
292 To test with a pre-built image from our docker hub repository, do
293
294     docker run --cpus 2 --rm -ti gmxapi/sample_restraint bash -c \
295             "cd /home/jovyan/sample_restraint/tests && 
296             mpiexec -n 2 python -m mpi4py -m pytest"