7dff38ca63e8a48a20065752086d12f456c37cd6
[alexxy/gromacs.git] / python_packaging / sample_restraint / tests / test_binding.py
1 # The myplugin module must be locatable by Python.
2 # If you configured CMake in the build directory ``/path/to/repo/build`` then,
3 # assuming you are in ``/path/to/repo``, run the tests with something like
4 #     PYTHONPATH=./cmake-build-debug/src/pythonmodule mpiexec -n 2 python -m mpi4py -m pytest tests/
5
6 # This test is not currently run automatically in any way. Build the module, point your PYTHONPATH at it,
7 # and run pytest in the tests directory.
8
9 import logging
10 import os
11
12 import gmxapi as gmx
13 from gmxapi.simulation.context import Context
14 from gmxapi.simulation.workflow import WorkElement, from_tpr
15 from gmxapi import version as gmx_version
16 import pytest
17
18 # create console handler
19 ch = logging.StreamHandler()
20 ch.setLevel(logging.DEBUG)
21 # create formatter and add it to the handler
22 formatter = logging.Formatter('%(asctime)s:%(name)s:%(levelname)s: %(message)s')
23 ch.setFormatter(formatter)
24 # add the handlers to the logger
25 logging.getLogger().addHandler(ch)
26
27 logger = logging.getLogger()
28
29
30 def test_import():
31     # Suppress inspection warning outside of testing context.
32     # noinspection PyUnresolvedReferences
33     import myplugin
34     assert myplugin
35
36
37 @pytest.mark.usefixtures("cleandir")
38 def test_ensemble_potential_nompi(spc_water_box):
39     """Test ensemble potential without an ensemble.
40     """
41     tpr_filename = spc_water_box
42     print("Testing plugin potential with input file {}".format(os.path.abspath(tpr_filename)))
43
44     assert gmx.version.api_is_at_least(0, 0, 5)
45     # Note that *threads* argument causes errors for MPI-enabled GROMACS.
46     # Ref #3563 and #3573
47     md = from_tpr([tpr_filename], append_output=False, threads=2)
48
49     # Create a WorkElement for the potential
50     params = {'sites': [1, 4],
51               'nbins': 10,
52               'binWidth': 0.1,
53               'min_dist': 0.,
54               'max_dist': 10.,
55               'experimental': [1.] * 10,
56               'nsamples': 1,
57               'sample_period': 0.001,
58               'nwindows': 4,
59               'k': 10000.,
60               'sigma': 1.}
61     potential = WorkElement(namespace="myplugin",
62                             operation="ensemble_restraint",
63                             params=params)
64     # Note that we could flexibly capture accessor methods as workflow elements, too. Maybe we can
65     # hide the extra Python bindings by letting myplugin.HarmonicRestraint automatically convert
66     # to a WorkElement when add_dependency is called on it.
67     potential.name = "ensemble_restraint"
68     md.add_dependency(potential)
69
70     context = Context(md)
71
72     with context as session:
73         session.run()
74
75
76 @pytest.mark.withmpi_only
77 @pytest.mark.usefixtures("cleandir")
78 def test_ensemble_potential_withmpi(spc_water_box):
79     tpr_filename = spc_water_box
80
81     logger.info("Testing plugin potential with input file {}".format(os.path.abspath(tpr_filename)))
82
83     assert gmx_version.api_is_at_least(0, 0, 5)
84     # Note that *threads* argument causes errors for MPI-enabled GROMACS.
85     # Ref #3563 and #3573
86     md = from_tpr([tpr_filename, tpr_filename], append_output=False, threads=2)
87
88     # Create a WorkElement for the potential
89     params = {'sites': [1, 4],
90               'nbins': 10,
91               'binWidth': 0.1,
92               'min_dist': 0.,
93               'max_dist': 10.,
94               'experimental': [0.5] * 10,
95               'nsamples': 1,
96               'sample_period': 0.001,
97               'nwindows': 4,
98               'k': 10000.,
99               'sigma': 1.}
100
101     potential = WorkElement(namespace="myplugin",
102                             operation="ensemble_restraint",
103                             params=params)
104     # Note that we could flexibly capture accessor methods as workflow elements, too. Maybe we can
105     # hide the extra Python bindings by letting myplugin.HarmonicRestraint automatically convert
106     # to a WorkElement when add_dependency is called on it.
107     potential.name = "ensemble_restraint"
108     md.add_dependency(potential)
109
110     context = Context(md)
111     with context as session:
112         session.run()