Skip to content

Commit ccec37b

Browse files
committed
more tests
1 parent 1dda698 commit ccec37b

2 files changed

Lines changed: 83 additions & 43 deletions

File tree

‎CodeEntropy/levels/mda.py‎

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -121,30 +121,6 @@ def extract_fragment(
121121
selection_string = f"index {frag.indices[0]}:{frag.indices[-1]}"
122122
return self.select_atoms(universe, selection_string)
123123

124-
def extract_fragments(
125-
self, universe: mda.Universe, molecule_ids: list[int]
126-
) -> mda.Universe:
127-
"""Extract a single molecule (fragment) as a standalone reduced universe.
128-
129-
Args:
130-
universe: The source universe.
131-
molecule_id: Fragment index in `universe.atoms.fragments`.
132-
133-
Returns:
134-
A reduced universe containing only the atoms of the selected fragment.
135-
"""
136-
group_indices = []
137-
for mol_id in molecule_ids:
138-
frag = universe.atoms.fragments[mol_id]
139-
group_indices.extend(frag.indices)
140-
141-
selection_string = "index "
142-
for i in group_indices:
143-
group_indices[i] = int(group_indices[i])
144-
selection_string += f"{group_indices[i]} "
145-
146-
return self.select_atoms(universe, selection_string)
147-
148124
def merge_forces(
149125
self,
150126
tprfile: str,

‎tests/unit/CodeEntropy/levels/test_dihedrals.py‎

Lines changed: 83 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,14 @@ def test_identify_peaks_wraps_negative_angles_and_calls_find_histogram_peaks():
123123

124124
mol = MagicMock()
125125
mol.trajectory = [0, 1]
126+
mol.residues = [MagicMock()]
127+
mol.residues[0].atoms.indices = np.array([0, 1, 2, 3], dtype=int)
126128
uops.extract_fragment.return_value = mol
127129

128130
dihedral = MagicMock()
129131
angles = np.array([[-10.0], [10.0]], dtype=float)
130132

133+
dt._select_heavy_residue = MagicMock(return_value=mol)
131134
dt._get_dihedrals = MagicMock(return_value=dihedral)
132135
dt._process_dihedral_phi = MagicMock(return_value=angles)
133136

@@ -142,15 +145,16 @@ def run(self):
142145
patch("CodeEntropy.levels.dihedrals.Dihedral", _FakeDihedral),
143146
patch.object(dt, "_process_histogram", return_value=[15.0]) as peaks_spy,
144147
):
145-
out = dt._identify_peaks(
148+
out_ua, out_res = dt._identify_peaks(
146149
data_container=MagicMock(),
147150
molecules=[0],
148151
bin_width=10.0,
149-
level_list=["residue"],
152+
level_list=["united_atom", "residue"],
150153
)
151154

152-
assert out == ([], [15.0])
153-
peaks_spy.assert_called_once()
155+
assert out_ua[0] == [15.0]
156+
assert out_res == [15.0]
157+
assert peaks_spy.call_count == 2
154158

155159

156160
def test_find_histogram_peaks_hits_interior_and_wraparound_last_bin():
@@ -168,16 +172,19 @@ def test_assign_states_initialises_then_extends_for_multiple_molecules():
168172

169173
mol = MagicMock()
170174
mol.trajectory = [0, 1]
175+
mol.residues = [MagicMock()]
176+
mol.residues[0].atoms.indices = np.array([0, 1, 2, 3], dtype=int)
171177
uops.extract_fragment.return_value = mol
172178

173179
dihedrals = ["D0"]
174180
angles = np.array([[5.0], [15.0]], dtype=float)
175181
peaks = [[5.0, 15.0]]
176-
states_ua = []
182+
states_ua = {}
177183
states_res = []
178-
flexible_ua = []
184+
flexible_ua = {}
179185
flexible_res = []
180186

187+
dt._select_heavy_residue = MagicMock(return_value=mol)
181188
dt._get_dihedrals = MagicMock(return_value=dihedrals)
182189

183190
class _FakeDihedral:
@@ -192,15 +199,17 @@ def run(self):
192199
data_container=MagicMock(),
193200
group_id=0,
194201
molecules=[0, 1],
195-
level_list=["residue"],
196-
peaks_ua=[],
202+
level_list=["united_atom", "residue"],
203+
peaks_ua=[peaks],
197204
peaks_res=peaks,
198205
states_ua=states_ua,
199206
states_res=states_res,
200207
flexible_ua=flexible_ua,
201208
flexible_res=flexible_res,
202209
)
203210

211+
assert states_ua[(0, 0)] == ["0", "1", "0", "1"]
212+
assert flexible_ua[(0, 0)] == 1
204213
assert states_res[0] == ["0", "1", "0", "1"]
205214
assert flexible_res[0] == 1
206215

@@ -233,6 +242,8 @@ def test_identify_peaks_handles_multiple_dihedrals():
233242

234243
mol = MagicMock()
235244
mol.trajectory = [0, 1]
245+
mol.residues = [MagicMock()]
246+
mol.residues[0].atoms.indices = np.array([0, 1, 2, 3], dtype=int)
236247
uops.extract_fragment.return_value = mol
237248

238249
dihedrals = (["D0", "D1"],)
@@ -244,6 +255,7 @@ def test_identify_peaks_handles_multiple_dihedrals():
244255
dtype=float,
245256
)
246257

258+
dt._select_heavy_residue = MagicMock(return_value=mol)
247259
dt._get_dihedrals = MagicMock(return_value=dihedrals)
248260
dt._process_dihedral_phi = MagicMock(return_value=angles)
249261
dt._process_histogram = MagicMock(return_value=[1, 2])
@@ -256,14 +268,15 @@ def run(self):
256268
return SimpleNamespace(results=SimpleNamespace(angles=angles))
257269

258270
with patch("CodeEntropy.levels.dihedrals.Dihedral", _FakeDihedral):
259-
out = dt._identify_peaks(
271+
out_ua, out_res = dt._identify_peaks(
260272
data_container=MagicMock(),
261273
molecules=[0],
262274
bin_width=30.0,
263275
level_list=["united_atom", "residue"],
264276
)
265277

266-
assert len(out) == 2
278+
assert len(out_ua[0]) == 2
279+
assert len(out_res) == 2
267280

268281

269282
def test_assign_states_filters_out_empty_state_strings_when_no_dihedrals():
@@ -272,14 +285,17 @@ def test_assign_states_filters_out_empty_state_strings_when_no_dihedrals():
272285

273286
mol = MagicMock()
274287
mol.trajectory = [0, 1, 2]
288+
mol.residues = [MagicMock()]
289+
mol.residues[0].atoms.indices = np.array([0, 1, 2, 3], dtype=int)
275290
uops.extract_fragment.return_value = mol
276291

277292
dihedrals = []
278-
states_ua = []
293+
states_ua = {}
279294
states_res = []
280-
flexible_ua = []
295+
flexible_ua = {}
281296
flexible_res = []
282297

298+
dt._select_heavy_residue = MagicMock(return_value=mol)
283299
dt._get_dihedrals = MagicMock(return_value=dihedrals)
284300

285301
class _FakeDihedral:
@@ -294,7 +310,7 @@ def run(self):
294310
data_container=MagicMock(),
295311
group_id=0,
296312
molecules=[0],
297-
level_list=["residue"],
313+
level_list=["united_atom", "residue"],
298314
peaks_ua=[],
299315
peaks_res=[],
300316
states_ua=states_ua,
@@ -303,6 +319,8 @@ def run(self):
303319
flexible_res=flexible_res,
304320
)
305321

322+
assert states_ua[(0, 0)] == []
323+
assert flexible_ua[(0, 0)] == 0
306324
assert states_res[0] == []
307325
assert flexible_res[0] == 0
308326

@@ -313,8 +331,12 @@ def test_identify_peaks_multiple_molecules_real_histogram():
313331

314332
mol0 = MagicMock()
315333
mol0.trajectory = [0, 1]
334+
mol0.residues = [MagicMock()]
335+
mol0.residues[0].atoms.indices = np.array([0, 1, 2, 3], dtype=int)
316336
mol1 = MagicMock()
317337
mol1.trajectory = [0, 1]
338+
mol1.residues = [MagicMock()]
339+
mol1.residues[0].atoms.indices = np.array([0, 1, 2, 3], dtype=int)
318340

319341
uops.extract_fragment.side_effect = [mol0, mol0, mol1]
320342

@@ -323,6 +345,7 @@ def test_identify_peaks_multiple_molecules_real_histogram():
323345
phi_values = {}
324346
phi_values[0] = np.array([[10.0], [20.0]], dtype=float)
325347

348+
dt._select_heavy_residue = MagicMock(return_value=mol0)
326349
dt._get_dihedrals = MagicMock(return_value=dihedrals)
327350
dt._process_dihedral_phi = MagicMock(return_value=phi_values)
328351

@@ -344,10 +367,10 @@ def run(self):
344367
data_container=MagicMock(),
345368
molecules=[0, 1],
346369
bin_width=90.0,
347-
level_list=["residue"],
370+
level_list=["united_atom", "residue"],
348371
)
349372

350-
assert len(peaks_ua) == 0
373+
assert len(peaks_ua) == 1
351374
assert len(peaks_res) == 1
352375

353376

@@ -357,16 +380,19 @@ def test_assign_states_wraps_negative_angles():
357380

358381
mol = MagicMock()
359382
mol.trajectory = [0, 1]
383+
mol.residues = [MagicMock()]
384+
mol.residues[0].atoms.indices = np.array([0, 1, 2, 3], dtype=int)
360385
uops.extract_fragment.return_value = mol
361386

362387
angles = np.array([[-10.0], [10.0]], dtype=float)
363388
peaks = [[10.0, 350.0]]
364389
dihedrals = ["D0"]
365-
states_ua = []
390+
states_ua = {}
366391
states_res = []
367-
flexible_ua = []
392+
flexible_ua = {}
368393
flexible_res = []
369394

395+
dt._select_heavy_residue = MagicMock(return_value=mol)
370396
dt._get_dihedrals = MagicMock(return_value=dihedrals)
371397

372398
class _FakeDihedral:
@@ -381,15 +407,17 @@ def run(self):
381407
data_container=MagicMock(),
382408
group_id=0,
383409
molecules=[0, 1],
384-
level_list=["residue"],
385-
peaks_ua=[],
410+
level_list=["united_atom", "residue"],
411+
peaks_ua=[peaks],
386412
peaks_res=peaks,
387413
states_ua=states_ua,
388414
states_res=states_res,
389415
flexible_ua=flexible_ua,
390416
flexible_res=flexible_res,
391417
)
392418

419+
assert states_ua[(0, 0)] == ["1", "0", "1", "0"]
420+
assert flexible_ua[(0, 0)] == 1
393421
assert states_res[0] == ["1", "0", "1", "0"]
394422
assert flexible_res[0] == 1
395423

@@ -464,3 +492,39 @@ def test_build_conformational_states_with_progress_updates_title_per_group(monke
464492

465493
progress.update.assert_any_call(9, title="Group 1")
466494
progress.advance.assert_called_with(9)
495+
496+
497+
def test_process_dihedral_phi():
498+
uops = MagicMock()
499+
dt = ConformationStateBuilder(universe_operations=uops)
500+
501+
dihedral_results = MagicMock()
502+
dihedral_results.results.angles = [[0, 1, 2], [3, 4, 5]]
503+
num_dihedrals = 3
504+
number_frames = 2
505+
phi_values = {}
506+
507+
phi_values = dt._process_dihedral_phi(
508+
dihedral_results, num_dihedrals, number_frames, phi_values
509+
)
510+
511+
assert len(phi_values) == 3
512+
assert phi_values[0] == [0, 3]
513+
514+
515+
def test_process_dihedral_phi_negative():
516+
uops = MagicMock()
517+
dt = ConformationStateBuilder(universe_operations=uops)
518+
519+
dihedral_results = MagicMock()
520+
dihedral_results.results.angles = [[0, 1, 2], [-3, 4, 5]]
521+
num_dihedrals = 3
522+
number_frames = 2
523+
phi_values = {}
524+
525+
phi_values = dt._process_dihedral_phi(
526+
dihedral_results, num_dihedrals, number_frames, phi_values
527+
)
528+
529+
assert len(phi_values) == 3
530+
assert phi_values[0] == [0, 357]

0 commit comments

Comments
 (0)