Skip to content

Commit aae4531

Browse files
committed
small update
1 parent a1022a2 commit aae4531

1 file changed

Lines changed: 23 additions & 37 deletions

File tree

src/openfe_analysis/utils/universe_utils.py

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@
99
from rdkit import Chem
1010

1111
# B-factor values used to identify atoms present at a given lambda state.
12-
# 0.25 marks atoms unique to state A, 0.75 marks atoms unique to state B,
13-
# and 0.5 marks atoms shared by both end states.
12+
# 0.25 : atoms unique to state A
13+
# 0.75 : atoms unique to state B
14+
# 0.5 : atoms shared by both end states.
1415
_BFACTOR_STATE_A = (0.25, 0.5)
1516
_BFACTOR_STATE_B = (0.75, 0.5)
1617

@@ -22,8 +23,7 @@ def select_state_atoms(
2223
"""
2324
Select all atoms present at a given end state.
2425
25-
Atoms are identified by their b-factor values, following the OpenFE
26-
PDB convention:
26+
Atoms are identified by their b-factor values:
2727
2828
- ``0.25`` — unique to state A
2929
- ``0.75`` — unique to state B
@@ -45,13 +45,6 @@ def select_state_atoms(
4545
------
4646
ValueError
4747
If ``end_state`` is not ``"A"`` or ``"B"``.
48-
49-
Examples
50-
--------
51-
Select all state A atoms, then further filter to just the ligand::
52-
53-
state_a = select_state_atoms(universe, end_state="A")
54-
ligand_a = state_a.select_atoms("resname UNK")
5548
"""
5649
if end_state == "A":
5750
bfactor_values = _BFACTOR_STATE_A
@@ -77,9 +70,8 @@ def guess_ligand_bonds(
7770
Ligand atoms for which bonds will be guessed.
7871
delete_existing : bool, optional
7972
If ``True``, delete existing bonds on the atomgroup before guessing.
80-
This ensures a clean re-guess from scratch, removing any
81-
bonds (e.g. cross-state bonds in hybrid topologies). Default is
82-
``False``.
73+
This may be necessary to avoid cross-state bonds in hybrid topologies.
74+
Default is ``False``.
8375
"""
8476
if delete_existing:
8577
atomgroup.universe.delete_bonds(atomgroup.bonds)
@@ -102,39 +94,37 @@ def correct_elements(
10294
atom_mapping: dict[int, int] | None = None,
10395
) -> None:
10496
"""
105-
Correct element and atom name assignments in an AtomGroup in-place
97+
Correct element and atom names in an AtomGroup in-place
10698
using an RDKit molecule as the source of truth.
10799
108-
This is particularly useful for hybrid topologies where mapped atoms
109-
undergoing element changes carry state A's element types, even when
110-
state B's ligand is selected. Correcting elements ensures accurate
111-
bond guessing and subsequent analyses.
100+
This is needed for hybrid topologies where mapped atoms that
101+
undergo element changes carry state A's element types, even when
102+
state B's ligand is selected.
112103
113104
Parameters
114105
----------
115106
atomgroup : mda.AtomGroup
116-
Ligand atoms whose elements and names will be corrected. Modified
117-
in-place.
107+
Ligand atoms whose elements and names will be corrected.
118108
rdmol : Chem.Mol
119-
RDKit molecule providing the correct element and atom name
120-
information.
109+
RDKit molecule with the correct element and atom name information.
121110
atom_mapping : dict[int, int], optional
122111
A mapping of ``{atomgroup_index: rdmol_index}`` defining the
123112
correspondence between atoms in ``atomgroup`` and ``rdmol``. If
124-
``None``, atoms are matched by position — the i-th atom in
125-
``atomgroup`` corresponds to the i-th atom in ``rdmol``. A
126-
warning is issued in this case since positional correspondence
127-
is not guaranteed when the RDKit molecule comes from an external
128-
source such as an SDF file.
113+
``None``, atoms are matched by position which gives wrong results if
114+
the atom order was not the same.
129115
130116
Raises
131117
------
132118
ValueError
133-
If the number of atoms in ``atomgroup`` and ``rdmol`` do not match
134-
and no ``atom_mapping`` is provided.
119+
If the number of atoms in ``atomgroup`` and ``rdmol`` do not match.
135120
"""
136121
periodic_table = Chem.GetPeriodicTable()
137122

123+
if len(atomgroup) != rdmol.GetNumAtoms():
124+
raise ValueError(
125+
f"atomgroup has {len(atomgroup)} atoms but rdmol has {rdmol.GetNumAtoms()} atoms."
126+
)
127+
138128
if atom_mapping is not None:
139129
for ag_idx, rd_idx in atom_mapping.items():
140130
mda_atom = atomgroup[ag_idx]
@@ -144,14 +134,10 @@ def correct_elements(
144134
mda_atom.element = element
145135
mda_atom.name = rd_atom.GetSymbol()
146136
else:
147-
if len(atomgroup) != rdmol.GetNumAtoms():
148-
raise ValueError(
149-
f"atomgroup has {len(atomgroup)} atoms but rdmol has {rdmol.GetNumAtoms()} atoms."
150-
)
151137
warnings.warn(
152-
"No atom_mapping provided to correct_elements — assuming positional "
153-
"correspondence between atomgroup and rdmol. This may give incorrect "
154-
"results if the atom ordering differs between the two.",
138+
"No atom_mapping provided to correct_elements. Assuming that "
139+
"atom ordering is the same between atomgroup and rdmol. This may "
140+
"give incorrect results if the atom ordering differs between the two.",
155141
UserWarning,
156142
)
157143
for mda_atom, rd_atom in zip(atomgroup, rdmol.GetAtoms()):

0 commit comments

Comments
 (0)