File: test_atomicdistances.py

package info (click to toggle)
mdanalysis 2.10.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 116,696 kB
  • sloc: python: 92,135; ansic: 8,156; makefile: 215; sh: 138
file content (135 lines) | stat: -rw-r--r-- 4,853 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# -*- Mode: python; tab-width: 4; indent-tabs-mode:nil; coding:utf-8 -*-
# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 fileencoding=utf-8
#
# MDAnalysis --- https://www.mdanalysis.org
# Copyright (c) 2006-2017 The MDAnalysis Development Team and contributors
# (see the file AUTHORS for the full list of names)
#
# Released under the Lesser GNU Public Licence, v2.1 or any higher version
#
# Please cite your use of MDAnalysis in published work:
#
# R. J. Gowers, M. Linke, J. Barnoud, T. J. E. Reddy, M. N. Melo, S. L. Seyler,
# D. L. Dotson, J. Domanski, S. Buchoux, I. M. Kenney, and O. Beckstein.
# MDAnalysis: A Python package for the rapid analysis of molecular dynamics
# simulations. In S. Benthall and S. Rostrup editors, Proceedings of the 15th
# Python in Science Conference, pages 102-109, Austin, TX, 2016. SciPy.
# doi: 10.25080/majora-629e541a-00e
#
# N. Michaud-Agrawal, E. J. Denning, T. B. Woolf, and O. Beckstein.
# MDAnalysis: A Toolkit for the Analysis of Molecular Dynamics Simulations.
# J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787
#
import pytest

import MDAnalysis as mda

import MDAnalysis.analysis.atomicdistances as ad
from MDAnalysis.lib.distances import calc_bonds
import MDAnalysis.transformations.boxdimensions as bd

from numpy.testing import assert_allclose
import numpy as np


class TestAtomicDistances(object):
    @staticmethod
    @pytest.fixture()
    def ad_u():
        # Universe from scratch with 100 atoms
        natoms = 100
        u = mda.Universe.empty(natoms, trajectory=True)

        # randomly generate 10 frames of x, y, z coordinates of 0 to 100
        rng = np.random.default_rng()
        coords = rng.integers(101, size=(10, natoms, 3))

        # load frames and coordinates into Universe
        u.load_new(coords)

        # set box dimensions to dim of [lx, ly, lz, alpha, beta, gamma]
        dim = np.array([80, 80, 80, 60, 60, 90])
        transform = bd.set_dimensions(dim)
        u.trajectory.add_transformations(transform)
        return u

    @staticmethod
    @pytest.fixture()
    def ad_ag1(ad_u):
        return ad_u.atoms[10:20]

    @staticmethod
    @pytest.fixture()
    def ad_ag2(ad_u):
        return ad_u.atoms[70:80]

    @staticmethod
    @pytest.fixture()
    def ad_ag3(ad_u):
        # more atoms than expected (exception)
        return ad_u.atoms[:7]

    @staticmethod
    @pytest.fixture()
    def ad_ag4():
        u_other = mda.Universe.empty(20, trajectory=True)
        # different trajectory (exception)
        return u_other.atoms[-10:]

    @staticmethod
    @pytest.fixture()
    def expected_dist(ad_ag1, ad_ag2):
        expected = np.zeros(
            (len(ad_ag1.universe.trajectory), ad_ag1.atoms.n_atoms)
        )

        # calculate distances without PBCs using dist()
        for i, ts in enumerate(ad_ag1.universe.trajectory):
            expected[i] = calc_bonds(ad_ag1, ad_ag2)
        return expected

    @staticmethod
    @pytest.fixture()
    def expected_pbc_dist(ad_ag1, ad_ag2):
        expected = np.zeros(
            (len(ad_ag1.universe.trajectory), ad_ag1.atoms.n_atoms)
        )

        # calculate distances with PBCs using dist()
        for i, ts in enumerate(ad_ag1.universe.trajectory):
            expected[i] = calc_bonds(ad_ag1, ad_ag2, box=ad_ag1.dimensions)
        return expected

    def test_ad_exceptions(self, ad_ag1, ad_ag3, ad_ag4):
        """Test exceptions raised when number of atoms do not
        match or AtomGroups come from different trajectories."""

        # number of atoms do not match
        match_exp_atoms = "AtomGroups do not"
        with pytest.raises(ValueError, match=match_exp_atoms):
            ad_atoms = ad.AtomicDistances(ad_ag1, ad_ag3)

        # AtomGroups come from different trajectories
        match_exp_traj = "AtomGroups are not"
        with pytest.raises(ValueError, match=match_exp_traj):
            ad_traj = ad.AtomicDistances(ad_ag1, ad_ag4)

    # only need to test that this class correctly applies distance calcs
    # calc_bonds() is tested elsewhere
    def test_ad_pairwise_dist(self, ad_ag1, ad_ag2, expected_dist):
        """Ensure that pairwise distances between atoms are
        correctly calculated without PBCs."""
        pairwise_no_pbc = ad.AtomicDistances(ad_ag1, ad_ag2, pbc=False).run()
        actual = pairwise_no_pbc.results

        # compare with expected values from dist()
        assert_allclose(actual, expected_dist)

    def test_ad_pairwise_dist_pbc(self, ad_ag1, ad_ag2, expected_pbc_dist):
        """Ensure that pairwise distances between atoms are
        correctly calculated with PBCs."""
        pairwise_pbc = ad.AtomicDistances(ad_ag1, ad_ag2).run()
        actual = pairwise_pbc.results

        # compare with expected values from dist()
        assert_allclose(actual, expected_pbc_dist)