99from 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