Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
tsoc
openmm
Commits
5a613f45
Commit
5a613f45
authored
Oct 22, 2019
by
João Rodrigues
Browse files
Fixed bug in calculation of number of ionic species to add in addMembrane. Addresses #2439
parent
138de127
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
84 additions
and
73 deletions
+84
-73
wrappers/python/simtk/openmm/app/modeller.py
wrappers/python/simtk/openmm/app/modeller.py
+84
-73
No files found.
wrappers/python/simtk/openmm/app/modeller.py
View file @
5a613f45
...
@@ -258,13 +258,16 @@ class Modeller(object):
...
@@ -258,13 +258,16 @@ class Modeller(object):
self
.
topology
=
newTopology
self
.
topology
=
newTopology
self
.
positions
=
newPositions
self
.
positions
=
newPositions
def
_addIons
(
self
,
forcefield
,
replaceableMols
,
ionCutoff
=
0.05
*
nanometer
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
):
def
_addIons
(
self
,
forcefield
,
numWaters
,
replaceableMols
,
ionCutoff
=
0.05
*
nanometer
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
):
"""Adds ions to the system by replacing certain molecules.
"""Adds ions to the system by replacing certain molecules.
Parameters
Parameters
----------
----------
forcefield : ForceField
forcefield : ForceField
the ForceField to use to determine the total charge of the system.
the ForceField to use to determine the total charge of the system.
numWaters : int
the total number of water molecules in the simulation box, used to
calculate the number of ions / concentration to add.
replaceableMols : dict
replaceableMols : dict
the molecules to replace by ions, as a dictionary of residue:positions
the molecules to replace by ions, as a dictionary of residue:positions
ionCutoff: distance=0.5*nanometer
ionCutoff: distance=0.5*nanometer
...
@@ -326,51 +329,52 @@ class Modeller(object):
...
@@ -326,51 +329,52 @@ class Modeller(object):
numPositive
-=
totalCharge
numPositive
-=
totalCharge
if
ionicStrength
>
0
*
molar
:
if
ionicStrength
>
0
*
molar
:
numIons
=
(
num
ReplaceableMol
s
-
numPositive
-
numNegative
)
*
ionicStrength
/
(
55.4
*
molar
)
# Pure water is about 55.4 molar (depending on temperature)
numIons
=
(
num
Water
s
-
numPositive
-
numNegative
)
*
ionicStrength
/
(
55.4
*
molar
)
# Pure water is about 55.4 molar (depending on temperature)
numPairs
=
int
(
floor
(
numIons
+
0.5
))
numPairs
=
int
(
floor
(
numIons
+
0.5
))
numPositive
+=
numPairs
numPositive
+=
numPairs
numNegative
+=
numPairs
numNegative
+=
numPairs
totalIons
=
numPositive
+
numNegative
totalIons
=
numPositive
+
numNegative
# Randomly select a set of waters
if
totalIons
>
0
:
# while ensuring ions are not placed too close to each other.
# Randomly select a set of waters
modeller
=
Modeller
(
self
.
topology
,
self
.
positions
)
# while ensuring ions are not placed too close to each other.
modeller
=
Modeller
(
self
.
topology
,
self
.
positions
)
replaceableList
=
list
(
replaceableMols
.
keys
())
numAddedIons
=
0
replaceableList
=
list
(
replaceableMols
.
keys
())
numTrials
=
10
# Attempts to add ions N times before quitting
numAddedIons
=
0
toReplace
=
[]
# list of molecules to be replaced
numTrials
=
10
# Attempts to add ions N times before quitting
while
numAddedIons
<
totalIons
:
toReplace
=
[]
# list of molecules to be replaced
pickedMol
=
random
.
choice
(
replaceableList
)
while
numAddedIons
<
totalIons
:
replaceableList
.
remove
(
pickedMol
)
pickedMol
=
random
.
choice
(
replaceableList
)
# Check distance to other ions
replaceableList
.
remove
(
pickedMol
)
for
pos
in
ionPositions
:
# Check distance to other ions
distance
=
norm
(
pos
-
replaceableMols
[
pickedMol
])
for
pos
in
ionPositions
:
if
distance
<=
ionCutoff
:
distance
=
norm
(
pos
-
replaceableMols
[
pickedMol
])
numTrials
-=
1
if
distance
<=
ionCutoff
:
break
numTrials
-=
1
else
:
break
toReplace
.
append
(
pickedMol
)
else
:
ionPositions
.
append
(
replaceableMols
[
pickedMol
])
toReplace
.
append
(
pickedMol
)
numAddedIons
+=
1
ionPositions
.
append
(
replaceableMols
[
pickedMol
])
numAddedIons
+=
1
n_trials
=
10
n_trials
=
10
if
n_trials
==
0
:
if
n_trials
==
0
:
raise
ValueError
(
'Could not add more than {} ions to the system'
.
format
(
numAddedIons
))
raise
ValueError
(
'Could not add more than {} ions to the system'
.
format
(
numAddedIons
))
# Replace waters/ions in the topology
# Replace waters/ions in the topology
modeller
.
delete
(
toReplace
)
modeller
.
delete
(
toReplace
)
ionChain
=
modeller
.
topology
.
addChain
()
ionChain
=
modeller
.
topology
.
addChain
()
for
i
,
water
in
enumerate
(
toReplace
):
for
i
,
water
in
enumerate
(
toReplace
):
element
=
(
positiveElement
if
i
<
numPositive
else
negativeElement
)
element
=
(
positiveElement
if
i
<
numPositive
else
negativeElement
)
newResidue
=
modeller
.
topology
.
addResidue
(
element
.
symbol
.
upper
(),
ionChain
)
newResidue
=
modeller
.
topology
.
addResidue
(
element
.
symbol
.
upper
(),
ionChain
)
modeller
.
topology
.
addAtom
(
element
.
symbol
,
element
,
newResidue
)
modeller
.
topology
.
addAtom
(
element
.
symbol
,
element
,
newResidue
)
modeller
.
positions
.
append
(
replaceableMols
[
water
])
modeller
.
positions
.
append
(
replaceableMols
[
water
])
# Update topology/positions
# Update topology/positions
self
.
topology
=
modeller
.
topology
self
.
topology
=
modeller
.
topology
self
.
positions
=
modeller
.
positions
self
.
positions
=
modeller
.
positions
def
addSolvent
(
self
,
forcefield
,
model
=
'tip3p'
,
boxSize
=
None
,
boxVectors
=
None
,
padding
=
None
,
numAdded
=
None
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
):
def
addSolvent
(
self
,
forcefield
,
model
=
'tip3p'
,
boxSize
=
None
,
boxVectors
=
None
,
padding
=
None
,
numAdded
=
None
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
):
"""Add solvent (both water and ions) to the model to fill a rectangular box.
"""Add solvent (both water and ions) to the model to fill a rectangular box.
...
@@ -621,8 +625,11 @@ class Modeller(object):
...
@@ -621,8 +625,11 @@ class Modeller(object):
if
atom
.
element
==
_oxygen
:
if
atom
.
element
==
_oxygen
:
waterPos
[
residue
]
=
newPositions
[
atom
.
index
]
waterPos
[
residue
]
=
newPositions
[
atom
.
index
]
# Total number of waters in the box
numTotalWaters
=
len
(
waterPos
)
# Add ions to neutralize the system.
# Add ions to neutralize the system.
self
.
_addIons
(
forcefield
,
waterPos
,
positiveIon
=
positiveIon
,
negativeIon
=
negativeIon
,
ionicStrength
=
ionicStrength
,
neutralize
=
neutralize
)
self
.
_addIons
(
forcefield
,
numTotalWaters
,
waterPos
,
positiveIon
=
positiveIon
,
negativeIon
=
negativeIon
,
ionicStrength
=
ionicStrength
,
neutralize
=
neutralize
)
class
_ResidueData
:
class
_ResidueData
:
"""Inner class used to encapsulate data about the hydrogens for a residue."""
"""Inner class used to encapsulate data about the hydrogens for a residue."""
...
@@ -1221,33 +1228,33 @@ class Modeller(object):
...
@@ -1221,33 +1228,33 @@ class Modeller(object):
def
addMembrane
(
self
,
forcefield
,
lipidType
=
'POPC'
,
membraneCenterZ
=
0
*
nanometer
,
minimumPadding
=
1
*
nanometer
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
):
def
addMembrane
(
self
,
forcefield
,
lipidType
=
'POPC'
,
membraneCenterZ
=
0
*
nanometer
,
minimumPadding
=
1
*
nanometer
,
positiveIon
=
'Na+'
,
negativeIon
=
'Cl-'
,
ionicStrength
=
0
*
molar
,
neutralize
=
True
):
"""Add a lipid membrane to the model.
"""Add a lipid membrane to the model.
This method actually adds both a membrane and a water box. It is best to build them together,
This method actually adds both a membrane and a water box. It is best to build them together,
both to avoid adding waters inside the membrane and to ensure that lipid head groups are properly
both to avoid adding waters inside the membrane and to ensure that lipid head groups are properly
solvated. For that reason, this method includes many of the same arguments as addSolvent().
solvated. For that reason, this method includes many of the same arguments as addSolvent().
The membrane is added in the XY plane, and the existing protein is assumed to already be oriented
The membrane is added in the XY plane, and the existing protein is assumed to already be oriented
and positioned correctly. When possible, it is recommended to start with a model from the
and positioned correctly. When possible, it is recommended to start with a model from the
Orientations of Proteins in Membranes (OPM) database at http://opm.phar.umich.edu. Otherwise, it
Orientations of Proteins in Membranes (OPM) database at http://opm.phar.umich.edu. Otherwise, it
is up to you to select the protein position yourself.
is up to you to select the protein position yourself.
The algorithm is based on the one described in Wolf et al., J. Comp. Chem. 31, pp. 2169-2174 (2010).
The algorithm is based on the one described in Wolf et al., J. Comp. Chem. 31, pp. 2169-2174 (2010).
It begins by tiling copies of a pre-equilibrated membrane patch to create a membrane of the desired
It begins by tiling copies of a pre-equilibrated membrane patch to create a membrane of the desired
size. Next it scales down the protein by 50% along the X and Y axes. Any lipid within a cutoff
size. Next it scales down the protein by 50% along the X and Y axes. Any lipid within a cutoff
distance of the scaled protein is removed. It also ensures that equal numbers of lipids are removed
distance of the scaled protein is removed. It also ensures that equal numbers of lipids are removed
from each leaf of the membrane. Finally, 1000 steps of molecular dynamics are performed to let
from each leaf of the membrane. Finally, 1000 steps of molecular dynamics are performed to let
the membrane relax while the protein is gradually scaled back up to its original size.
the membrane relax while the protein is gradually scaled back up to its original size.
The size of the membrane and water box are determined by the minimumPadding argument. All
The size of the membrane and water box are determined by the minimumPadding argument. All
pre-existing atoms are guaranteed to be at least this far from any edge of the periodic box. It
pre-existing atoms are guaranteed to be at least this far from any edge of the periodic box. It
is also possible for the periodic box to have more padding than requested. In particular, it only
is also possible for the periodic box to have more padding than requested. In particular, it only
adds whole copies of the pre-equilibrated membrane patch, so the box dimensions will always be
adds whole copies of the pre-equilibrated membrane patch, so the box dimensions will always be
integer multiples of the patch size. That may lead to a larger membrane than what you requested.
integer multiples of the patch size. That may lead to a larger membrane than what you requested.
This method has built in support for POPC and POPE lipids. You can also build other types of
This method has built in support for POPC and POPE lipids. You can also build other types of
membranes by providing a pre-equilibrated, solvated membrane patch that can be tiled in the XY
membranes by providing a pre-equilibrated, solvated membrane patch that can be tiled in the XY
plane to form the membrane.
plane to form the membrane.
Parameters
Parameters
----------
----------
forcefield : ForceField
forcefield : ForceField
...
@@ -1282,8 +1289,8 @@ class Modeller(object):
...
@@ -1282,8 +1289,8 @@ class Modeller(object):
membraneCenterZ
=
membraneCenterZ
.
value_in_unit
(
nanometer
)
membraneCenterZ
=
membraneCenterZ
.
value_in_unit
(
nanometer
)
if
is_quantity
(
minimumPadding
):
if
is_quantity
(
minimumPadding
):
minimumPadding
=
minimumPadding
.
value_in_unit
(
nanometer
)
minimumPadding
=
minimumPadding
.
value_in_unit
(
nanometer
)
# Figure out how many copies of the membrane patch we need in each direction.
# Figure out how many copies of the membrane patch we need in each direction.
proteinPos
=
self
.
positions
.
value_in_unit
(
nanometer
)
proteinPos
=
self
.
positions
.
value_in_unit
(
nanometer
)
proteinMinPos
=
Vec3
(
*
[
min
((
p
[
i
]
for
p
in
proteinPos
))
for
i
in
range
(
3
)])
proteinMinPos
=
Vec3
(
*
[
min
((
p
[
i
]
for
p
in
proteinPos
))
for
i
in
range
(
3
)])
...
@@ -1298,15 +1305,15 @@ class Modeller(object):
...
@@ -1298,15 +1305,15 @@ class Modeller(object):
patchCenterPos
=
(
patchMinPos
+
patchMaxPos
)
/
2
patchCenterPos
=
(
patchMinPos
+
patchMaxPos
)
/
2
nx
=
int
(
ceil
((
proteinSize
[
0
]
+
2
*
minimumPadding
)
/
patchSize
[
0
]))
nx
=
int
(
ceil
((
proteinSize
[
0
]
+
2
*
minimumPadding
)
/
patchSize
[
0
]))
ny
=
int
(
ceil
((
proteinSize
[
1
]
+
2
*
minimumPadding
)
/
patchSize
[
1
]))
ny
=
int
(
ceil
((
proteinSize
[
1
]
+
2
*
minimumPadding
)
/
patchSize
[
1
]))
# Record the bonds for each residue.
# Record the bonds for each residue.
resBonds
=
defaultdict
(
list
)
resBonds
=
defaultdict
(
list
)
for
bond
in
patch
.
topology
.
bonds
():
for
bond
in
patch
.
topology
.
bonds
():
resBonds
[
bond
[
0
].
residue
].
append
(
bond
)
resBonds
[
bond
[
0
].
residue
].
append
(
bond
)
# Identify which leaf of the membrane each lipid is in.
# Identify which leaf of the membrane each lipid is in.
numLipidAtoms
=
0
numLipidAtoms
=
0
resMeanZ
=
{}
resMeanZ
=
{}
membraneMeanZ
=
0.0
membraneMeanZ
=
0.0
...
@@ -1322,17 +1329,17 @@ class Modeller(object):
...
@@ -1322,17 +1329,17 @@ class Modeller(object):
resMeanZ
[
res
]
=
sumZ
/
numResAtoms
resMeanZ
[
res
]
=
sumZ
/
numResAtoms
membraneMeanZ
/=
numLipidAtoms
membraneMeanZ
/=
numLipidAtoms
lipidLeaf
=
dict
((
res
,
0
if
resMeanZ
[
res
]
<
membraneMeanZ
else
1
)
for
res
in
resMeanZ
)
lipidLeaf
=
dict
((
res
,
0
if
resMeanZ
[
res
]
<
membraneMeanZ
else
1
)
for
res
in
resMeanZ
)
# Compute scaled positions for the protein.
# Compute scaled positions for the protein.
scaledProteinPos
=
[
None
]
*
len
(
proteinPos
)
scaledProteinPos
=
[
None
]
*
len
(
proteinPos
)
for
i
,
p
in
enumerate
(
proteinPos
):
for
i
,
p
in
enumerate
(
proteinPos
):
p
=
p
-
proteinCenterPos
p
=
p
-
proteinCenterPos
p
=
Vec3
(
0.5
*
p
[
0
],
0.5
*
p
[
1
],
p
[
2
])
p
=
Vec3
(
0.5
*
p
[
0
],
0.5
*
p
[
1
],
p
[
2
])
scaledProteinPos
[
i
]
=
p
+
proteinCenterPos
scaledProteinPos
[
i
]
=
p
+
proteinCenterPos
# Create a new Topology for the membrane.
# Create a new Topology for the membrane.
membraneTopology
=
Topology
()
membraneTopology
=
Topology
()
membranePos
=
[]
membranePos
=
[]
boxSizeZ
=
patchSize
[
2
]
boxSizeZ
=
patchSize
[
2
]
...
@@ -1341,14 +1348,13 @@ class Modeller(object):
...
@@ -1341,14 +1348,13 @@ class Modeller(object):
else
:
else
:
boxSizeZ
=
max
(
boxSizeZ
,
proteinSize
[
2
]
+
2
*
minimumPadding
)
boxSizeZ
=
max
(
boxSizeZ
,
proteinSize
[
2
]
+
2
*
minimumPadding
)
membraneTopology
.
setUnitCellDimensions
((
nx
*
patchSize
[
0
],
ny
*
patchSize
[
1
],
boxSizeZ
))
membraneTopology
.
setUnitCellDimensions
((
nx
*
patchSize
[
0
],
ny
*
patchSize
[
1
],
boxSizeZ
))
# Add membrane patches. We exclude any water that is within a cutoff distance of either the actual or scaled
# Add membrane patches. We exclude any water that is within a cutoff distance of either the actual or scaled
# protein, and any lipid that is within a cutoff distance of the scaled protein. We also keep track of how
# protein, and any lipid that is within a cutoff distance of the scaled protein. We also keep track of how
# many lipids have been excluded from each leaf of the membrane, so we can make sure exactly the same
# many lipids have been excluded from each leaf of the membrane, so we can make sure exactly the same
# number get removed from each leaf.
# number get removed from each leaf.
overlapCutoff
=
0.22
overlapCutoff
=
0.22
chain
=
membraneTopology
.
addChain
()
addedWater
=
[]
addedWater
=
[]
addedLipids
=
[]
addedLipids
=
[]
removedFromLeaf
=
[
0
,
0
]
removedFromLeaf
=
[
0
,
0
]
...
@@ -1395,9 +1401,9 @@ class Modeller(object):
...
@@ -1395,9 +1401,9 @@ class Modeller(object):
del
cellLists
del
cellLists
del
cells
del
cells
del
proteinCells
del
proteinCells
# Add the lipids.
# Add the lipids.
newAtoms
=
{}
newAtoms
=
{}
lipidChain
=
membraneTopology
.
addChain
()
lipidChain
=
membraneTopology
.
addChain
()
lipidResNum
=
1
# renumber lipid residues to handle large patches
lipidResNum
=
1
# renumber lipid residues to handle large patches
...
@@ -1408,7 +1414,7 @@ class Modeller(object):
...
@@ -1408,7 +1414,7 @@ class Modeller(object):
else
:
else
:
newResidue
=
membraneTopology
.
addResidue
(
residue
.
name
,
lipidChain
,
lipidResNum
,
residue
.
insertionCode
)
newResidue
=
membraneTopology
.
addResidue
(
residue
.
name
,
lipidChain
,
lipidResNum
,
residue
.
insertionCode
)
lipidResNum
+=
1
lipidResNum
+=
1
for
atom
in
residue
.
atoms
():
for
atom
in
residue
.
atoms
():
newAtom
=
membraneTopology
.
addAtom
(
atom
.
name
,
atom
.
element
,
newResidue
,
atom
.
id
)
newAtom
=
membraneTopology
.
addAtom
(
atom
.
name
,
atom
.
element
,
newResidue
,
atom
.
id
)
newAtoms
[
atom
]
=
newAtom
newAtoms
[
atom
]
=
newAtom
...
@@ -1418,9 +1424,9 @@ class Modeller(object):
...
@@ -1418,9 +1424,9 @@ class Modeller(object):
del
lipidLeaf
del
lipidLeaf
del
addedLipids
del
addedLipids
# Add the solvent.
# Add the solvent.
solventChain
=
membraneTopology
.
addChain
()
solventChain
=
membraneTopology
.
addChain
()
for
(
residue
,
pos
)
in
addedWater
:
for
(
residue
,
pos
)
in
addedWater
:
newResidue
=
membraneTopology
.
addResidue
(
residue
.
name
,
solventChain
,
residue
.
id
,
residue
.
insertionCode
)
newResidue
=
membraneTopology
.
addResidue
(
residue
.
name
,
solventChain
,
residue
.
id
,
residue
.
insertionCode
)
...
@@ -1436,7 +1442,7 @@ class Modeller(object):
...
@@ -1436,7 +1442,7 @@ class Modeller(object):
gc
.
collect
()
gc
.
collect
()
# Create a System for the lipids, then add in the protein as stationary particles.
# Create a System for the lipids, then add in the protein as stationary particles.
system
=
forcefield
.
createSystem
(
membraneTopology
,
nonbondedMethod
=
CutoffPeriodic
)
system
=
forcefield
.
createSystem
(
membraneTopology
,
nonbondedMethod
=
CutoffPeriodic
)
proteinSystem
=
forcefield
.
createSystem
(
self
.
topology
,
nonbondedMethod
=
CutoffNonPeriodic
)
proteinSystem
=
forcefield
.
createSystem
(
self
.
topology
,
nonbondedMethod
=
CutoffNonPeriodic
)
numMembraneParticles
=
system
.
getNumParticles
()
numMembraneParticles
=
system
.
getNumParticles
()
...
@@ -1458,9 +1464,9 @@ class Modeller(object):
...
@@ -1458,9 +1464,9 @@ class Modeller(object):
del
membranePos
del
membranePos
del
scaledProteinCells
del
scaledProteinCells
gc
.
collect
()
gc
.
collect
()
# Run a simulation while slowly scaling up the protein so the membrane can relax.
# Run a simulation while slowly scaling up the protein so the membrane can relax.
integrator
=
LangevinIntegrator
(
10.0
,
50.0
,
0.001
)
integrator
=
LangevinIntegrator
(
10.0
,
50.0
,
0.001
)
context
=
Context
(
system
,
integrator
)
context
=
Context
(
system
,
integrator
)
context
.
setPositions
(
mergedPositions
)
context
.
setPositions
(
mergedPositions
)
...
@@ -1483,24 +1489,24 @@ class Modeller(object):
...
@@ -1483,24 +1489,24 @@ class Modeller(object):
mergedPositions
[
j
+
numMembraneParticles
]
=
(
weight1
*
proteinPos
[
j
]
+
weight2
*
scaledProteinPos
[
j
])
mergedPositions
[
j
+
numMembraneParticles
]
=
(
weight1
*
proteinPos
[
j
]
+
weight2
*
scaledProteinPos
[
j
])
context
.
setPositions
(
mergedPositions
)
context
.
setPositions
(
mergedPositions
)
integrator
.
step
(
20
)
integrator
.
step
(
20
)
# Add the membrane to the protein.
# Add the membrane to the protein.
modeller
=
Modeller
(
self
.
topology
,
self
.
positions
)
modeller
=
Modeller
(
self
.
topology
,
self
.
positions
)
modeller
.
add
(
membraneTopology
,
context
.
getState
(
getPositions
=
True
).
getPositions
()[:
numMembraneParticles
])
modeller
.
add
(
membraneTopology
,
context
.
getState
(
getPositions
=
True
).
getPositions
()[:
numMembraneParticles
])
modeller
.
topology
.
setPeriodicBoxVectors
(
membraneTopology
.
getPeriodicBoxVectors
())
modeller
.
topology
.
setPeriodicBoxVectors
(
membraneTopology
.
getPeriodicBoxVectors
())
del
context
del
context
del
system
del
system
del
integrator
del
integrator
# Depending on the box size, we may need to add more water beyond what was included with the membrane patch.
# Depending on the box size, we may need to add more water beyond what was included with the membrane patch.
needExtraWater
=
(
boxSizeZ
>
patchSize
[
2
])
needExtraWater
=
(
boxSizeZ
>
patchSize
[
2
])
if
needExtraWater
:
if
needExtraWater
:
modeller
.
addSolvent
(
forcefield
,
neutralize
=
False
)
modeller
.
addSolvent
(
forcefield
,
neutralize
=
False
)
# Record the positions of all waters that have been added.
# Record the positions of all waters that have been added.
waterPos
=
{}
waterPos
=
{}
for
chain
in
list
(
modeller
.
topology
.
chains
())[
-
2
:]:
for
chain
in
list
(
modeller
.
topology
.
chains
())[
-
2
:]:
for
residue
in
chain
.
residues
():
for
residue
in
chain
.
residues
():
...
@@ -1538,6 +1544,11 @@ class Modeller(object):
...
@@ -1538,6 +1544,11 @@ class Modeller(object):
if
atom
.
element
==
elem
.
oxygen
:
if
atom
.
element
==
elem
.
oxygen
:
waterPos
[
residue
]
=
modeller
.
positions
[
atom
.
index
]
waterPos
[
residue
]
=
modeller
.
positions
[
atom
.
index
]
# Total number of water molecules
# Use this number to avoid underestimating the concentration of ions
# in _addIons after we exclude waters close to lipids.
numTotalWaters
=
len
(
waterPos
)
# Calculate lipid Z boundaries
# Calculate lipid Z boundaries
lipidNames
=
{
res
.
name
for
res
in
patch
.
topology
.
residues
()
if
res
.
name
!=
'HOH'
}
lipidNames
=
{
res
.
name
for
res
in
patch
.
topology
.
residues
()
if
res
.
name
!=
'HOH'
}
lipidZMax
=
sys
.
float_info
.
min
lipidZMax
=
sys
.
float_info
.
min
...
@@ -1559,12 +1570,12 @@ class Modeller(object):
...
@@ -1559,12 +1570,12 @@ class Modeller(object):
if
lowerZBoundary
<
waterZ
.
value_in_unit
(
nanometer
)
<
upperZBoundary
:
if
lowerZBoundary
<
waterZ
.
value_in_unit
(
nanometer
)
<
upperZBoundary
:
del
waterPos
[
wRes
]
del
waterPos
[
wRes
]
self
.
_addIons
(
forcefield
,
waterPos
,
positiveIon
=
positiveIon
,
negativeIon
=
negativeIon
,
ionicStrength
=
ionicStrength
,
neutralize
=
neutralize
)
self
.
_addIons
(
forcefield
,
numTotalWaters
,
waterPos
,
positiveIon
=
positiveIon
,
negativeIon
=
negativeIon
,
ionicStrength
=
ionicStrength
,
neutralize
=
neutralize
)
class
_CellList
(
object
):
class
_CellList
(
object
):
"""This class organizes atom positions into cells, so the neighbors of a point can be quickly retrieved"""
"""This class organizes atom positions into cells, so the neighbors of a point can be quickly retrieved"""
def
__init__
(
self
,
positions
,
maxCutoff
,
vectors
,
periodic
):
def
__init__
(
self
,
positions
,
maxCutoff
,
vectors
,
periodic
):
self
.
positions
=
positions
[:]
self
.
positions
=
positions
[:]
self
.
cells
=
{}
self
.
cells
=
{}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment