Skip to content

Commit 9cbc8ea

Browse files
FIX: Handle a non-linear FrameIterator in HydrogenBondAnalysis (#5202)
* Fixes #5200 * Refactor count_by_time() to handle returning values on a non-linear FrameIterator - refactored whole function - returned counts array is now guaranteed to have the same shape as frames and elements correspond directly to each other * add test * update changelog
1 parent 528b512 commit 9cbc8ea

4 files changed

Lines changed: 30 additions & 11 deletions

File tree

package/AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ Chronological list of authors
266266
- Pranay Pelapkar
267267
- Shreejan Dolai
268268
- Tanisha Dubey
269+
- Brady Johnston
269270

270271
External code
271272
-------------

package/CHANGELOG

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ The rules for this file:
1515

1616
-------------------------------------------------------------------------------
1717
??/??/?? IAlibay, orbeckst, marinegor, tylerjereddy, ljwoods2, marinegor,
18-
spyke7, talagayev, tanii1125
18+
spyke7, talagayev, tanii1125, BradyAJohnston
1919

2020
* 2.11.0
2121

2222
Fixes
23+
* HydrogenBondAnalysis: Fixed `count_by_time()` when using `run(FrameIterator)` that
24+
results in `self.start` and `self.end` being None (Issue #5200, PR #5202)
2325
* NoJump shows a more informative message and fails when applied
2426
outside of the first frame (Issue #4915, PR #5201)
2527
* DSSP now explicitly checks for a minimum of 6 residues and raises a clear

package/MDAnalysis/analysis/hydrogenbonds/hbond_analysis.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -911,17 +911,13 @@ def count_by_time(self):
911911
Can be used along with :attr:`HydrogenBondAnalysis.times` to plot
912912
the number of hydrogen bonds over time.
913913
"""
914+
hbond_frames = self.results.hbonds[:, 0].astype(int)
915+
frame_unique, frame_counts = np.unique(hbond_frames, return_counts=True)
916+
frame_min, frame_max = self.frames.min(), self.frames.max()
914917

915-
indices, tmp_counts = np.unique(self.results.hbonds[:, 0], axis=0,
916-
return_counts=True)
917-
918-
indices -= self.start
919-
indices /= self.step
920-
921-
counts = np.zeros_like(self.frames)
922-
counts[indices.astype(np.intp)] = tmp_counts
923-
924-
return counts
918+
counts = np.zeros(frame_max - frame_min + 1, dtype=int)
919+
counts[frame_unique - frame_min] = frame_counts
920+
return counts[self.frames - frame_min]
925921

926922
def count_by_type(self):
927923
"""Counts the total number of each unique type of hydrogen bond.

testsuite/MDAnalysisTests/analysis/test_hydrogenbonds_analysis.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -760,3 +760,23 @@ def test_hbond_analysis(self, universe, client_HydrogenBondAnalysis):
760760
assert h.hydrogens_sel == ""
761761
assert h.acceptors_sel == ""
762762
assert h.results.hbonds.size == 0
763+
764+
765+
class TestHydrogenBondAnalysisFrameIterator:
766+
@staticmethod
767+
@pytest.fixture(scope="class")
768+
def universe():
769+
return MDAnalysis.Universe(waterPSF, waterDCD)
770+
771+
def test_frame_iterator(self, universe):
772+
frames = np.array([0, 1, 2, 5, 6, 7, 8])
773+
hbonds = HydrogenBondAnalysis(
774+
universe=universe,
775+
hydrogens_sel="name H1 H2",
776+
acceptors_sel="name OH2",
777+
update_selections=False,
778+
)
779+
hbonds.run(frames=frames)
780+
assert np.array_equal(
781+
hbonds.count_by_time(), np.array([2, 1, 4, 3, 3, 2, 2])
782+
)

0 commit comments

Comments
 (0)