|
27 | 27 | from MDAnalysis.core.topology import Topology |
28 | 28 | from MDAnalysis.core.topologyattrs import Masses, Atomnames, Atomtypes |
29 | 29 | import MDAnalysis.tests.datafiles as datafiles |
| 30 | +from MDAnalysis.exceptions import NoDataError |
30 | 31 | from numpy.testing import assert_allclose, assert_equal |
31 | 32 |
|
| 33 | +from MDAnalysis import _TOPOLOGY_ATTRS, _GUESSERS |
| 34 | + |
32 | 35 |
|
33 | 36 | class TestBaseGuesser(): |
34 | 37 |
|
@@ -101,6 +104,141 @@ def test_partial_guess_attr_with_unknown_no_value_label(self): |
101 | 104 | u = mda.Universe(top, to_guess=['types']) |
102 | 105 | assert_equal(u.atoms.types, ['', '', '', '']) |
103 | 106 |
|
| 107 | + def test_guess_topology_objects_existing_read(self): |
| 108 | + u = mda.Universe(datafiles.CONECT) |
| 109 | + assert len(u.atoms.bonds) == 72 |
| 110 | + assert list(u.bonds[0].indices) == [623, 630] |
| 111 | + |
| 112 | + # delete some bonds |
| 113 | + u.delete_bonds(u.atoms.bonds[:10]) |
| 114 | + assert len(u.atoms.bonds) == 62 |
| 115 | + # first bond has changed |
| 116 | + assert list(u.bonds[0].indices) == [1545, 1552] |
| 117 | + # count number of (1545, 1552) bonds |
| 118 | + ag = u.atoms[[1545, 1552]] |
| 119 | + bonds = ag.bonds.atomgroup_intersection(ag, strict=True) |
| 120 | + assert len(bonds) == 1 |
| 121 | + assert not bonds[0].is_guessed |
| 122 | + |
| 123 | + all_indices = [tuple(x.indices) for x in u.bonds] |
| 124 | + assert (623, 630) not in all_indices |
| 125 | + |
| 126 | + # test guessing new bonds doesn't remove old ones |
| 127 | + u.guess_TopologyAttrs("default", to_guess=["bonds"]) |
| 128 | + assert len(u.atoms.bonds) == 1922 |
| 129 | + old_bonds = ag.bonds.atomgroup_intersection(ag, strict=True) |
| 130 | + assert len(old_bonds) == 1 |
| 131 | + # test guessing new bonds doesn't duplicate old ones |
| 132 | + assert not old_bonds[0].is_guessed |
| 133 | + |
| 134 | + new_ag = u.atoms[[623, 630]] |
| 135 | + new_bonds = new_ag.bonds.atomgroup_intersection(new_ag, strict=True) |
| 136 | + assert len(new_bonds) == 1 |
| 137 | + assert new_bonds[0].is_guessed |
| 138 | + |
| 139 | + def test_guess_topology_objects_existing_in_universe(self): |
| 140 | + u = mda.Universe(datafiles.CONECT, to_guess=["bonds"]) |
| 141 | + assert len(u.atoms.bonds) == 1922 |
| 142 | + assert list(u.bonds[0].indices) == [0, 1] |
| 143 | + |
| 144 | + # delete some bonds |
| 145 | + u.delete_bonds(u.atoms.bonds[:100]) |
| 146 | + assert len(u.atoms.bonds) == 1822 |
| 147 | + assert list(u.bonds[0].indices) == [94, 99] |
| 148 | + |
| 149 | + all_indices = [tuple(x.indices) for x in u.bonds] |
| 150 | + assert (0, 1) not in all_indices |
| 151 | + |
| 152 | + # guess old bonds back |
| 153 | + u.guess_TopologyAttrs("default", to_guess=["bonds"]) |
| 154 | + assert len(u.atoms.bonds) == 1922 |
| 155 | + # check TopologyGroup contains new (old) bonds |
| 156 | + assert list(u.bonds[0].indices) == [0, 1] |
| 157 | + |
| 158 | + def test_guess_topology_objects_force(self): |
| 159 | + u = mda.Universe(datafiles.CONECT, force_guess=["bonds"]) |
| 160 | + assert len(u.atoms.bonds) == 1922 |
| 161 | + |
| 162 | + with pytest.raises(NoDataError): |
| 163 | + u.atoms.angles |
| 164 | + |
| 165 | + def test_guess_topology_objects_out_of_order_init(self): |
| 166 | + u = mda.Universe( |
| 167 | + datafiles.PDB_small, |
| 168 | + to_guess=["dihedrals", "angles", "bonds"], |
| 169 | + guess_bonds=False |
| 170 | + ) |
| 171 | + assert len(u.atoms.angles) == 6123 |
| 172 | + assert len(u.atoms.dihedrals) == 8921 |
| 173 | + |
| 174 | + def test_guess_topology_objects_out_of_order_guess(self): |
| 175 | + u = mda.Universe(datafiles.PDB_small) |
| 176 | + with pytest.raises(NoDataError): |
| 177 | + u.atoms.angles |
| 178 | + |
| 179 | + u.guess_TopologyAttrs( |
| 180 | + "default", |
| 181 | + to_guess=["dihedrals", "angles", "bonds"] |
| 182 | + ) |
| 183 | + assert len(u.atoms.angles) == 6123 |
| 184 | + assert len(u.atoms.dihedrals) == 8921 |
| 185 | + |
| 186 | + def test_force_guess_overwrites_existing_bonds(self): |
| 187 | + u = mda.Universe(datafiles.CONECT) |
| 188 | + assert len(u.atoms.bonds) == 72 |
| 189 | + |
| 190 | + # This low radius should find no bonds |
| 191 | + vdw = dict.fromkeys(set(u.atoms.types), 0.1) |
| 192 | + u.guess_TopologyAttrs("default", to_guess=["bonds"], vdwradii=vdw) |
| 193 | + assert len(u.atoms.bonds) == 72 |
| 194 | + |
| 195 | + # Now force guess bonds |
| 196 | + u.guess_TopologyAttrs("default", force_guess=["bonds"], vdwradii=vdw) |
| 197 | + assert len(u.atoms.bonds) == 0 |
| 198 | + |
| 199 | + def test_guessing_angles_respects_bond_kwargs(self): |
| 200 | + u = mda.Universe(datafiles.PDB) |
| 201 | + assert not hasattr(u.atoms, "angles") |
| 202 | + |
| 203 | + # This low radius should find no angles |
| 204 | + vdw = dict.fromkeys(set(u.atoms.types), 0.01) |
| 205 | + |
| 206 | + u.guess_TopologyAttrs("default", to_guess=["angles"], vdwradii=vdw) |
| 207 | + assert len(u.atoms.angles) == 0 |
| 208 | + |
| 209 | + # set higher radii for lots of angles! |
| 210 | + vdw = dict.fromkeys(set(u.atoms.types), 1) |
| 211 | + u.guess_TopologyAttrs("default", force_guess=["angles"], vdwradii=vdw) |
| 212 | + assert len(u.atoms.angles) == 89466 |
| 213 | + |
| 214 | + def test_guessing_dihedrals_respects_bond_kwargs(self): |
| 215 | + u = mda.Universe(datafiles.CONECT) |
| 216 | + assert len(u.atoms.bonds) == 72 |
| 217 | + |
| 218 | + u.guess_TopologyAttrs("default", to_guess=["dihedrals"]) |
| 219 | + assert len(u.atoms.dihedrals) == 3548 |
| 220 | + assert not hasattr(u.atoms, "angles") |
| 221 | + |
| 222 | + def test_guess_invalid_attribute(self): |
| 223 | + default_guesser = get_guesser("default") |
| 224 | + err = "not a recognized MDAnalysis topology attribute" |
| 225 | + with pytest.raises(KeyError, match=err): |
| 226 | + default_guesser.guess_attr('not_an_attribute') |
| 227 | + |
| 228 | + def test_guess_unsupported_attribute(self): |
| 229 | + default_guesser = get_guesser("default") |
| 230 | + err = "cannot guess this attribute" |
| 231 | + with pytest.raises(ValueError, match=err): |
| 232 | + default_guesser.guess_attr('tempfactors') |
| 233 | + |
| 234 | + def test_guess_singular(self): |
| 235 | + default_guesser = get_guesser("default") |
| 236 | + u = mda.Universe(datafiles.PDB, to_guess=[]) |
| 237 | + assert not hasattr(u.atoms, "masses") |
| 238 | + |
| 239 | + default_guesser._universe = u |
| 240 | + masses = default_guesser.guess_attr('mass') |
| 241 | + |
104 | 242 |
|
105 | 243 | def test_Universe_guess_bonds_deprecated(): |
106 | 244 | with pytest.warns( |
|
0 commit comments