Skip to content

Commit 268f1d7

Browse files
authored
Bugfixed chain ID assignment in addSolvent (#287) (#294)
* Bugfixed chain ID assignment in addSolvent (#287) * Simplify logic for alphabetic ID extension * Added `_renameNewChains()` for `addSolvent()` and `addMembrane()`
1 parent 6bf10e1 commit 268f1d7

File tree

1 file changed

+24
-10
lines changed

1 file changed

+24
-10
lines changed

pdbfixer/pdbfixer.py

+24-10
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,25 @@ def _addMissingResiduesToChain(self, chain, residueNames, startPosition, endPosi
534534
templatePosition = template.positions[atom.index].value_in_unit(unit.nanometer)
535535
newPositions.append(mm.Vec3(*np.dot(rotate, templatePosition))*unit.nanometer+translate)
536536

537+
def _renameNewChains(self, startIndex):
538+
"""Rename newly added chains to conform with existing naming conventions.
539+
540+
Parameters
541+
----------
542+
startIndex : int
543+
The index of the first new chain in self.topology.chains().
544+
"""
545+
# If all chains are new, nothing to do
546+
if startIndex == 0:
547+
return
548+
549+
# If the last chain ID was originally a letter, continue alphabetically until reaching Z
550+
chains = list(self.topology.chains())
551+
for newChainIndex in range(startIndex, len(chains)):
552+
prevChainId = chains[newChainIndex - 1].id
553+
if len(prevChainId) == 1 and "A" <= prevChainId < "Z":
554+
chains[newChainIndex].id = chr(ord(prevChainId) + 1)
555+
537556
def removeChains(self, chainIndices=None, chainIds=None):
538557
"""Remove a set of chains from the structure.
539558
@@ -1092,16 +1111,13 @@ def addSolvent(self, boxSize=None, padding=None, boxVectors=None, positiveIon='N
10921111
10931112
"""
10941113

1114+
nChains = sum(1 for _ in self.topology.chains())
10951115
modeller = app.Modeller(self.topology, self.positions)
10961116
forcefield = self._createForceField(self.topology, True)
10971117
modeller.addSolvent(forcefield, padding=padding, boxSize=boxSize, boxVectors=boxVectors, boxShape=boxShape, positiveIon=positiveIon, negativeIon=negativeIon, ionicStrength=ionicStrength)
1098-
chains = list(modeller.topology.chains())
1099-
if len(chains) == 1:
1100-
chains[0].id = 'A'
1101-
else:
1102-
chains[-1].id = chr(ord(chains[-2].id)+1)
11031118
self.topology = modeller.topology
11041119
self.positions = modeller.positions
1120+
self._renameNewChains(nChains)
11051121

11061122
def addMembrane(self, lipidType='POPC', membraneCenterZ=0*unit.nanometer, minimumPadding=1*unit.nanometer, positiveIon='Na+', negativeIon='Cl-', ionicStrength=0*unit.molar):
11071123
"""Add a lipid membrane to the structure.
@@ -1124,16 +1140,14 @@ def addMembrane(self, lipidType='POPC', membraneCenterZ=0*unit.nanometer, minimu
11241140
ionicStrength : openmm.unit.Quantity with units compatible with molar, optional, default=0*molar
11251141
The total concentration of ions (both positive and negative) to add. This does not include ions that are added to neutralize the system.
11261142
"""
1143+
1144+
nChains = sum(1 for _ in self.topology.chains())
11271145
modeller = app.Modeller(self.topology, self.positions)
11281146
forcefield = self._createForceField(self.topology, True)
11291147
modeller.addMembrane(forcefield, lipidType=lipidType, minimumPadding=minimumPadding, positiveIon=positiveIon, negativeIon=negativeIon, ionicStrength=ionicStrength)
1130-
chains = list(modeller.topology.chains())
1131-
if len(chains) == 1:
1132-
chains[0].id = 'A'
1133-
else:
1134-
chains[-1].id = chr(ord(chains[-2].id)+1)
11351148
self.topology = modeller.topology
11361149
self.positions = modeller.positions
1150+
self._renameNewChains(nChains)
11371151

11381152
def _createForceField(self, newTopology, water):
11391153
"""Create a force field to use for optimizing the positions of newly added atoms."""

0 commit comments

Comments
 (0)