Skip to content

Commit

Permalink
Minimum mass for hydrogen guess in HydrogenBondAnalysis (#2516)
Browse files Browse the repository at this point in the history
* added minimum hydrogen mass
  • Loading branch information
RMeli authored Feb 12, 2020
1 parent abc9049 commit d873d36
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 7 deletions.
2 changes: 2 additions & 0 deletions package/CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ Enhancements
* Improve the distance search in water bridge analysis with capped_distance (PR #2480)

Changes
* Added `min_mass` parameter to `guess_hydrogens` function in `HydrogenBondAnalysis`
set to 0.9 by default (Issue #2472)
* Removes `save()` function from contacts, diffusionmap, hole, LinearDensity,
and rms (Issue #1745).
* Removes; `save_table()` from :class:`HydrogenBondAnalysis`,
Expand Down
22 changes: 17 additions & 5 deletions package/MDAnalysis/analysis/hydrogenbonds/hbond_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@
"""
from __future__ import absolute_import, division

import numpy as np
import numpy as np

from .. import base
from MDAnalysis.lib.distances import capped_distance, calc_angles
Expand Down Expand Up @@ -234,7 +234,12 @@ def __init__(self, universe, donors_sel=None, hydrogens_sel=None, acceptors_sel=
self.d_h_a_angle = d_h_a_angle_cutoff
self.update_selections = update_selections

def guess_hydrogens(self, selection='all', max_mass=1.1, min_charge=0.3):
def guess_hydrogens(self,
selection='all',
max_mass=1.1,
min_charge=0.3,
min_mass=0.9
):
"""Guesses which hydrogen atoms should be used in the analysis.
Parameters
Expand Down Expand Up @@ -263,14 +268,21 @@ def guess_hydrogens(self, selection='all', max_mass=1.1, min_charge=0.3):
Alternatively, this function may be used to quickly generate a :class:`str` of potential hydrogen atoms involved
in hydrogen bonding. This str may then be modified before being used to set the attribute
:attr:`hydrogens_sel`.
.. versionchanged: 1.0.0
Added `min_mass` parameter to specify minimum mass (Issue #2472)
"""

if min_mass > max_mass:
raise ValueError("min_mass is higher than (or equal to) max_mass")

ag = self.u.select_atoms(selection)
hydrogens_ag = ag[
np.logical_and(
np.logical_and.reduce((
ag.masses < max_mass,
ag.charges > min_charge
)
ag.charges > min_charge,
ag.masses > min_mass,
))
]

hydrogens_list = np.unique(
Expand Down
58 changes: 56 additions & 2 deletions testsuite/MDAnalysisTests/analysis/test_hydrogenbonds_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def h(self, universe):

def test_hbond_analysis(self, h):

assert len(np.unique(h.hbonds[:,0])) == 10
assert len(np.unique(h.hbonds[:, 0])) == 10
assert len(h.hbonds) == 32

reference = {
Expand Down Expand Up @@ -98,6 +98,7 @@ def test_count_by_ids(self, h):

assert_array_equal(counts, ref_counts)


class TestHydrogenBondAnalysisTIP3P_GuessAcceptors_GuessHydrogens_UseTopology_(TestHydrogenBondAnalysisTIP3P):
"""Uses the same distance and cutoff hydrogen bond criteria as :class:`TestHydrogenBondAnalysisTIP3P`, so the
results are identical, but the hydrogens and acceptors are guessed whilst the donor-hydrogen pairs are determined
Expand All @@ -111,6 +112,7 @@ class TestHydrogenBondAnalysisTIP3P_GuessAcceptors_GuessHydrogens_UseTopology_(T
'd_h_a_angle_cutoff': 120.0
}


class TestHydrogenBondAnalysisTIP3P_GuessDonors_NoTopology(object):
"""Guess the donor atoms involved in hydrogen bonds using the partial charges of the atoms.
"""
Expand Down Expand Up @@ -141,6 +143,58 @@ def test_guess_donors(self, h):
assert donors == ref_donors


class TestHydrogenBondAnalysisTIP3P_GuessHydrogens_NoTopology(object):
"""
Guess the hydrogen atoms involved in hydrogen bonds using the mass and
partial charge of the atoms.
"""

@staticmethod
@pytest.fixture(scope='class')
def universe():
return MDAnalysis.Universe(waterPSF, waterDCD)

kwargs = {
'donors_sel': None,
'hydrogens_sel': None,
'acceptors_sel': None,
'd_h_cutoff': 1.2,
'd_a_cutoff': 3.0,
'd_h_a_angle_cutoff': 120.0
}

@pytest.fixture(scope='class')
def h(self, universe):
h = HydrogenBondAnalysis(universe, **self.kwargs)
return h

def test_guess_hydrogens(self, h):

ref_hydrogens = "(resname TIP3 and name H1) or (resname TIP3 and name H2)"
hydrogens = h.guess_hydrogens(selection='all')
assert hydrogens == ref_hydrogens

pytest.mark.parametrize(
"min_mass, max_mass, min_charge",
[
(1.05, 1.10, 0.30),
(0.90, 0.95, 0.30),
(0.90, 1.10, 1.00)
]
)
def test_guess_hydrogens_empty_selection(self, h):

hydrogens = h.guess_hydrogens(selection='all', min_charge=1.0)
assert hydrogens == ""

def test_guess_hydrogens_min_max_mass(self, h):

errmsg = "min_mass is higher than \(or equal to\) max_mass"

with pytest.raises(ValueError, match=errmsg):

h.guess_hydrogens(selection='all', min_mass=1.1, max_mass=0.9)

class TestHydrogenBondAnalysisTIP3PStartStep(object):
"""Uses the same distance and cutoff hydrogen bond criteria as :class:`TestHydrogenBondAnalysisTIP3P` but starting
with the second frame and using every other frame in the analysis.
Expand Down Expand Up @@ -168,7 +222,7 @@ def h(self, universe):

def test_hbond_analysis(self, h):

assert len(np.unique(h.hbonds[:,0])) == 5
assert len(np.unique(h.hbonds[:, 0])) == 5
assert len(h.hbonds) == 15

reference = {
Expand Down

0 comments on commit d873d36

Please sign in to comment.