Commit 92dfd1ff authored by peastman's avatar peastman
Browse files

Added option to add a fixed number of solvent molecules

parent 7b67c27b
...@@ -240,7 +240,7 @@ class Modeller(object): ...@@ -240,7 +240,7 @@ class Modeller(object):
self.topology = newTopology self.topology = newTopology
self.positions = newPositions self.positions = newPositions
def addSolvent(self, forcefield, model='tip3p', boxSize=None, boxVectors=None, padding=None, positiveIon='Na+', negativeIon='Cl-', ionicStrength=0*molar): def addSolvent(self, forcefield, model='tip3p', boxSize=None, boxVectors=None, padding=None, numAdded=None, positiveIon='Na+', negativeIon='Cl-', ionicStrength=0*molar):
"""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.
The algorithm works as follows: The algorithm works as follows:
...@@ -250,11 +250,15 @@ class Modeller(object): ...@@ -250,11 +250,15 @@ class Modeller(object):
randomly selecting a water molecule and replacing it with the ion. randomly selecting a water molecule and replacing it with the ion.
4. Ion pairs are added to give the requested total ionic strength. 4. Ion pairs are added to give the requested total ionic strength.
The box size can be specified in four ways. First, you can explicitly give the vectors defining the periodic box to The box size can be specified in any of several ways:
use. Alternatively, for a rectangular box you can simply give the dimensions of the unit cell. Third, you can
give a padding distance. The largest dimension of the solute (along the x, y, or z axis) is determined, and a cubic 1. You can explicitly give the vectors defining the periodic box to use.
box of size (largest dimension)+2*padding is used. Finally, if neither box vectors, box size, nor padding distance is specified, 2. Alternatively, for a rectangular box you can simply give the dimensions of the unit cell.
the existing Topology's box vectors are used. 3. You can give a padding distance. The largest dimension of the solute (along the x, y, or z axis) is determined, and a cubic
box of size (largest dimension)+2*padding is used.
4. You can specify the total number of molecules (both waters and ions) to add. A cubic box is then created whose size is
just large enough hold the specified amount of solvent.
5. Finally, if none of the above options is specified, the existing Topology's box vectors are used.
Parameters: Parameters:
- forcefield (ForceField) the ForceField to use for determining van der Waals radii and atomic charges - forcefield (ForceField) the ForceField to use for determining van der Waals radii and atomic charges
...@@ -262,14 +266,43 @@ class Modeller(object): ...@@ -262,14 +266,43 @@ class Modeller(object):
- boxSize (Vec3=None) the size of the box to fill with water - boxSize (Vec3=None) the size of the box to fill with water
- boxVectors (tuple of Vec3=None) the vectors defining the periodic box to fill with water - boxVectors (tuple of Vec3=None) the vectors defining the periodic box to fill with water
- padding (distance=None) the padding distance to use - padding (distance=None) the padding distance to use
- numAdded (int=None) the total number of molecules (waters and ions) to add
- positiveIon (string='Na+') the type of positive ion to add. Allowed values are 'Cs+', 'K+', 'Li+', 'Na+', and 'Rb+' - positiveIon (string='Na+') the type of positive ion to add. Allowed values are 'Cs+', 'K+', 'Li+', 'Na+', and 'Rb+'
- negativeIon (string='Cl-') the type of negative ion to add. Allowed values are 'Cl-', 'Br-', 'F-', and 'I-'. Be aware - negativeIon (string='Cl-') the type of negative ion to add. Allowed values are 'Cl-', 'Br-', 'F-', and 'I-'. Be aware
that not all force fields support all ion types. that not all force fields support all ion types.
- ionicStrength (concentration=0*molar) the total concentration of ions (both positive and negative) to add. This - ionicStrength (concentration=0*molar) the total concentration of ions (both positive and negative) to add. This
does not include ions that are added to neutralize the system. does not include ions that are added to neutralize the system.
""" """
if len([x for x in (boxSize, boxVectors, padding, numAdded) if x is not None]) > 1:
raise ValueError('At most one of the following arguments may be specified: boxSize, boxVectors, padding, numAdded')
# Load the pre-equilibrated water box.
vdwRadiusPerSigma = 0.5612310241546864907
if model == 'tip3p':
waterRadius = 0.31507524065751241*vdwRadiusPerSigma
elif model == 'spce':
waterRadius = 0.31657195050398818*vdwRadiusPerSigma
elif model == 'tip4pew':
waterRadius = 0.315365*vdwRadiusPerSigma
elif model == 'tip5p':
waterRadius = 0.312*vdwRadiusPerSigma
else:
raise ValueError('Unknown water model: %s' % model)
pdb = PDBFile(os.path.join(os.path.dirname(__file__), 'data', model+'.pdb'))
pdbTopology = pdb.getTopology()
pdbPositions = pdb.getPositions().value_in_unit(nanometer)
pdbResidues = list(pdbTopology.residues())
pdbBoxSize = pdbTopology.getUnitCellDimensions().value_in_unit(nanometer)
# Pick a unit cell size. # Pick a unit cell size.
if numAdded is not None:
# Select a padding distance which is guaranteed to give more than the specified number of molecules.
padding = 1.1*(numAdded/((len(pdbResidues)/pdbBoxSize[0]**3)*8))**(1.0/3.0)
if padding < 0.5:
padding = 0.5 # Ensure we have enough when adding very small numbers of molecules
if boxVectors is not None: if boxVectors is not None:
if is_quantity(boxVectors[0]): if is_quantity(boxVectors[0]):
boxVectors = (boxVectors[0].value_in_unit(nanometer), boxVectors[1].value_in_unit(nanometer), boxVectors[2].value_in_unit(nanometer)) boxVectors = (boxVectors[0].value_in_unit(nanometer), boxVectors[1].value_in_unit(nanometer), boxVectors[2].value_in_unit(nanometer))
...@@ -305,25 +338,6 @@ class Modeller(object): ...@@ -305,25 +338,6 @@ class Modeller(object):
positiveElement = posIonElements[positiveIon] positiveElement = posIonElements[positiveIon]
negativeElement = negIonElements[negativeIon] negativeElement = negIonElements[negativeIon]
# Load the pre-equilibrated water box.
vdwRadiusPerSigma = 0.5612310241546864907
if model == 'tip3p':
waterRadius = 0.31507524065751241*vdwRadiusPerSigma
elif model == 'spce':
waterRadius = 0.31657195050398818*vdwRadiusPerSigma
elif model == 'tip4pew':
waterRadius = 0.315365*vdwRadiusPerSigma
elif model == 'tip5p':
waterRadius = 0.312*vdwRadiusPerSigma
else:
raise ValueError('Unknown water model: %s' % model)
pdb = PDBFile(os.path.join(os.path.dirname(__file__), 'data', model+'.pdb'))
pdbTopology = pdb.getTopology()
pdbPositions = pdb.getPositions().value_in_unit(nanometer)
pdbResidues = list(pdbTopology.residues())
pdbBoxSize = pdbTopology.getUnitCellDimensions().value_in_unit(nanometer)
# Have the ForceField build a System for the solute from which we can determine van der Waals radii. # Have the ForceField build a System for the solute from which we can determine van der Waals radii.
system = forcefield.createSystem(self.topology) system = forcefield.createSystem(self.topology)
...@@ -424,27 +438,42 @@ class Modeller(object): ...@@ -424,27 +438,42 @@ class Modeller(object):
addedWaters.append((residue.index, atomPos)) addedWaters.append((residue.index, atomPos))
# There could be clashes between water molecules at the box edges. Find ones to remove. if numAdded is not None:
# We added many more waters than we actually want. Sort them based on distance to the nearest box edge and
upperCutoff = center+box/2-Vec3(waterCutoff, waterCutoff, waterCutoff) # only keep the ones in the middle.
lowerCutoff = center-box/2+Vec3(waterCutoff, waterCutoff, waterCutoff)
lowerSkinPositions = [pos for index, pos in addedWaters if pos[0] < lowerCutoff[0] or pos[1] < lowerCutoff[1] or pos[2] < lowerCutoff[2]] lowerBound = center-box/2
filteredWaters = [] upperBound = center+box/2
cells = {} distToEdge = [min(min(pos-lowerBound), min(upperBound-pos)) for index, pos in addedWaters]
for i in range(len(lowerSkinPositions)): sortedIndex = [i[0] for i in sorted(enumerate(distToEdge), key=lambda x: -x[1])]
cell = tuple((int(floor(lowerSkinPositions[i][j]/cellSize[j]))%numCells[j] for j in range(3))) addedWaters = [addedWaters[i] for i in sortedIndex[:numAdded]]
if cell in cells:
cells[cell].append(i) # Compute a new periodic box size.
else:
cells[cell] = [i] maxSize = max(max((pos[i] for index, pos in addedWaters))-min((pos[i] for index, pos in addedWaters)) for i in range(3))
for entry in addedWaters: newTopology.setUnitCellDimensions(Vec3(maxSize, maxSize, maxSize))
pos = entry[1] else:
if pos[0] < upperCutoff[0] and pos[1] < upperCutoff[1] and pos[2] < upperCutoff[2]: # There could be clashes between water molecules at the box edges. Find ones to remove.
filteredWaters.append(entry)
else: upperCutoff = center+box/2-Vec3(waterCutoff, waterCutoff, waterCutoff)
if not any((periodicDistance(lowerSkinPositions[i], pos) < waterCutoff and norm(lowerSkinPositions[i]-pos) > waterCutoff for i in neighbors(pos))): lowerCutoff = center-box/2+Vec3(waterCutoff, waterCutoff, waterCutoff)
lowerSkinPositions = [pos for index, pos in addedWaters if pos[0] < lowerCutoff[0] or pos[1] < lowerCutoff[1] or pos[2] < lowerCutoff[2]]
filteredWaters = []
cells = {}
for i in range(len(lowerSkinPositions)):
cell = tuple((int(floor(lowerSkinPositions[i][j]/cellSize[j]))%numCells[j] for j in range(3)))
if cell in cells:
cells[cell].append(i)
else:
cells[cell] = [i]
for entry in addedWaters:
pos = entry[1]
if pos[0] < upperCutoff[0] and pos[1] < upperCutoff[1] and pos[2] < upperCutoff[2]:
filteredWaters.append(entry) filteredWaters.append(entry)
addedWaters = filteredWaters else:
if not any((periodicDistance(lowerSkinPositions[i], pos) < waterCutoff and norm(lowerSkinPositions[i]-pos) > waterCutoff for i in neighbors(pos))):
filteredWaters.append(entry)
addedWaters = filteredWaters
# Add ions to neutralize the system. # Add ions to neutralize the system.
......
...@@ -308,7 +308,7 @@ class TestModeller(unittest.TestCase): ...@@ -308,7 +308,7 @@ class TestModeller(unittest.TestCase):
self.assertTrue(len(matoms)==0 and len(m1atoms)==1 and len(m2atoms)==1) self.assertTrue(len(matoms)==0 and len(m1atoms)==1 and len(m2atoms)==1)
def test_addSolventPeriodicBox(self): def test_addSolventPeriodicBox(self):
""" Test the addSolvent() method; test that the four ways of passing in the periodic box all work. """ """ Test the addSolvent() method; test that the five ways of passing in the periodic box all work. """
# First way of passing in periodic box vectors: set it in the original topology. # First way of passing in periodic box vectors: set it in the original topology.
topology_start = self.pdb.topology topology_start = self.pdb.topology
...@@ -358,17 +358,25 @@ class TestModeller(unittest.TestCase): ...@@ -358,17 +358,25 @@ class TestModeller(unittest.TestCase):
self.assertVecAlmostEqual(dim3[0]/nanometers, Vec3(2.8802, 0, 0)) self.assertVecAlmostEqual(dim3[0]/nanometers, Vec3(2.8802, 0, 0))
self.assertVecAlmostEqual(dim3[1]/nanometers, Vec3(0, 2.8802, 0)) self.assertVecAlmostEqual(dim3[1]/nanometers, Vec3(0, 2.8802, 0))
self.assertVecAlmostEqual(dim3[2]/nanometers, Vec3(0, 0, 2.8802)) self.assertVecAlmostEqual(dim3[2]/nanometers, Vec3(0, 0, 2.8802))
# Fifth way: specify a number of molecules to add instead of a box size
topology_start = self.pdb.topology
modeller = Modeller(topology_start, self.positions)
modeller.deleteWater()
numInitial = len(list(modeller.topology.residues()))
modeller.addSolvent(self.forcefield, numAdded=1000)
self.assertEqual(numInitial+1000, len(list(modeller.topology.residues())))
def test_addSolventNeutralSolvent(self): def test_addSolventNeutralSolvent(self):
""" Test the addSolvent() method; test adding ions to neutral solvent. """ """ Test the addSolvent() method; test adding ions to neutral solvent. """
topology_start = self.pdb.topology topology_start = self.pdb.topology
topology_start.setUnitCellDimensions(Vec3(3.5, 3.5, 3.5)*nanometers) topology_start.setUnitCellDimensions(Vec3(3.5, 3.5, 3.5)*nanometers)
modeller = Modeller(topology_start, self.positions) modeller = Modeller(topology_start, self.positions)
modeller.deleteWater() modeller.deleteWater()
modeller.addSolvent(self.forcefield, ionicStrength = 2.0*molar) modeller.addSolvent(self.forcefield, ionicStrength = 2.0*molar)
topology_after = modeller.getTopology() topology_after = modeller.getTopology()
water_count=0 water_count=0
sodium_count=0 sodium_count=0
chlorine_count=0 chlorine_count=0
...@@ -379,24 +387,24 @@ class TestModeller(unittest.TestCase): ...@@ -379,24 +387,24 @@ class TestModeller(unittest.TestCase):
sodium_count += 1 sodium_count += 1
elif residue.name=='CL': elif residue.name=='CL':
chlorine_count += 1 chlorine_count += 1
total_added = water_count+sodium_count+chlorine_count total_added = water_count+sodium_count+chlorine_count
self.assertEqual(total_added, 1364) self.assertEqual(total_added, 1364)
expected_ion_fraction = 2.0*molar/(55.4*molar) expected_ion_fraction = 2.0*molar/(55.4*molar)
expected_ions = math.floor(total_added*expected_ion_fraction/2+0.5) expected_ions = math.floor(total_added*expected_ion_fraction/2+0.5)
self.assertEqual(sodium_count, expected_ions) self.assertEqual(sodium_count, expected_ions)
self.assertEqual(chlorine_count, expected_ions) self.assertEqual(chlorine_count, expected_ions)
def test_addSolventNegativeSolvent(self): def test_addSolventNegativeSolvent(self):
""" Test the addSolvent() method; test adding ions to a negatively charged solvent. """ """ Test the addSolvent() method; test adding ions to a negatively charged solvent. """
topology_start = self.pdb.topology topology_start = self.pdb.topology
topology_start.setUnitCellDimensions(Vec3(3.5, 3.5, 3.5)*nanometers) topology_start.setUnitCellDimensions(Vec3(3.5, 3.5, 3.5)*nanometers)
# set up modeller with no solvent # set up modeller with no solvent
modeller = Modeller(topology_start, self.positions) modeller = Modeller(topology_start, self.positions)
modeller.deleteWater() modeller.deleteWater()
# add 5 Cl- ions to the original topology # add 5 Cl- ions to the original topology
topology_toAdd = Topology() topology_toAdd = Topology()
newChain = topology_toAdd.addChain() newChain = topology_toAdd.addChain()
...@@ -410,7 +418,7 @@ class TestModeller(unittest.TestCase): ...@@ -410,7 +418,7 @@ class TestModeller(unittest.TestCase):
modeller.add(topology_toAdd, positions_toAdd) modeller.add(topology_toAdd, positions_toAdd)
modeller.addSolvent(self.forcefield, ionicStrength=1.0*molar) modeller.addSolvent(self.forcefield, ionicStrength=1.0*molar)
topology_after = modeller.getTopology() topology_after = modeller.getTopology()
water_count = 0 water_count = 0
sodium_count = 0 sodium_count = 0
chlorine_count = 0 chlorine_count = 0
...@@ -421,23 +429,23 @@ class TestModeller(unittest.TestCase): ...@@ -421,23 +429,23 @@ class TestModeller(unittest.TestCase):
sodium_count += 1 sodium_count += 1
elif residue.name=='CL': elif residue.name=='CL':
chlorine_count += 1 chlorine_count += 1
total_water_ions = water_count+sodium_count+chlorine_count total_water_ions = water_count+sodium_count+chlorine_count
expected_ion_fraction = 1.0*molar/(55.4*molar) expected_ion_fraction = 1.0*molar/(55.4*molar)
expected_ions = math.floor((total_water_ions-10)*expected_ion_fraction/2+0.5)+5 expected_ions = math.floor((total_water_ions-10)*expected_ion_fraction/2+0.5)+5
self.assertEqual(sodium_count, expected_ions) self.assertEqual(sodium_count, expected_ions)
self.assertEqual(chlorine_count, expected_ions) self.assertEqual(chlorine_count, expected_ions)
def test_addSolventPositiveSolvent(self): def test_addSolventPositiveSolvent(self):
""" Test the addSolvent() method; test adding ions to a positively charged solvent. """ """ Test the addSolvent() method; test adding ions to a positively charged solvent. """
topology_start = self.pdb.topology topology_start = self.pdb.topology
topology_start.setUnitCellDimensions(Vec3(3.5, 3.5, 3.5)*nanometers) topology_start.setUnitCellDimensions(Vec3(3.5, 3.5, 3.5)*nanometers)
# set up modeller with no solvent # set up modeller with no solvent
modeller = Modeller(topology_start, self.positions) modeller = Modeller(topology_start, self.positions)
modeller.deleteWater() modeller.deleteWater()
# add 5 Na+ ions to the original topology # add 5 Na+ ions to the original topology
topology_toAdd = Topology() topology_toAdd = Topology()
newChain = topology_toAdd.addChain() newChain = topology_toAdd.addChain()
...@@ -448,12 +456,12 @@ class TestModeller(unittest.TestCase): ...@@ -448,12 +456,12 @@ class TestModeller(unittest.TestCase):
topology_toAdd.addAtom('Na',Element.getBySymbol('Na'), residues[i]) topology_toAdd.addAtom('Na',Element.getBySymbol('Na'), residues[i])
positions_toAdd = [Vec3(1.0,1.2,1.5), Vec3(1.7,1.0,1.4), Vec3(1.5,2.0,1.0), positions_toAdd = [Vec3(1.0,1.2,1.5), Vec3(1.7,1.0,1.4), Vec3(1.5,2.0,1.0),
Vec3(2.0,2.0,2.0), Vec3(2.0,1.5,1.0)]*nanometers Vec3(2.0,2.0,2.0), Vec3(2.0,1.5,1.0)]*nanometers
# positions_toAdd doesn't need to change # positions_toAdd doesn't need to change
modeller.add(topology_toAdd, positions_toAdd) modeller.add(topology_toAdd, positions_toAdd)
modeller.addSolvent(self.forcefield, ionicStrength=1.0*molar) modeller.addSolvent(self.forcefield, ionicStrength=1.0*molar)
topology_after = modeller.getTopology() topology_after = modeller.getTopology()
water_count = 0 water_count = 0
sodium_count = 0 sodium_count = 0
chlorine_count = 0 chlorine_count = 0
...@@ -464,25 +472,25 @@ class TestModeller(unittest.TestCase): ...@@ -464,25 +472,25 @@ class TestModeller(unittest.TestCase):
sodium_count += 1 sodium_count += 1
elif residue.name=='CL': elif residue.name=='CL':
chlorine_count += 1 chlorine_count += 1
total_water_ions = water_count+sodium_count+chlorine_count total_water_ions = water_count+sodium_count+chlorine_count
expected_ion_fraction = 1.0*molar/(55.4*molar) expected_ion_fraction = 1.0*molar/(55.4*molar)
expected_ions = math.floor((total_water_ions-10)*expected_ion_fraction/2+0.5)+5 expected_ions = math.floor((total_water_ions-10)*expected_ion_fraction/2+0.5)+5
self.assertEqual(sodium_count, expected_ions) self.assertEqual(sodium_count, expected_ions)
self.assertEqual(chlorine_count, expected_ions) self.assertEqual(chlorine_count, expected_ions)
def test_addSolventIons(self): def test_addSolventIons(self):
""" Test the addSolvent() method with all possible choices for positive and negative ions. """ """ Test the addSolvent() method with all possible choices for positive and negative ions. """
topology_start = self.pdb.topology topology_start = self.pdb.topology
topology_start.setUnitCellDimensions(Vec3(3.5, 3.5, 3.5)*nanometers) topology_start.setUnitCellDimensions(Vec3(3.5, 3.5, 3.5)*nanometers)
# set up modeller with no solvent # set up modeller with no solvent
modeller = Modeller(topology_start, self.positions) modeller = Modeller(topology_start, self.positions)
modeller.deleteWater() modeller.deleteWater()
topology_nowater = modeller.getTopology() topology_nowater = modeller.getTopology()
positions_nowater = modeller.getPositions() positions_nowater = modeller.getPositions()
expected_ion_fraction = 1.0*molar/(55.4*molar) expected_ion_fraction = 1.0*molar/(55.4*molar)
for positiveIon in ['Cs+', 'K+', 'Li+', 'Na+', 'Rb+']: for positiveIon in ['Cs+', 'K+', 'Li+', 'Na+', 'Rb+']:
...@@ -490,7 +498,7 @@ class TestModeller(unittest.TestCase): ...@@ -490,7 +498,7 @@ class TestModeller(unittest.TestCase):
modeller = Modeller(topology_nowater, positions_nowater) modeller = Modeller(topology_nowater, positions_nowater)
modeller.addSolvent(self.forcefield, positiveIon=positiveIon, ionicStrength=1.0*molar) modeller.addSolvent(self.forcefield, positiveIon=positiveIon, ionicStrength=1.0*molar)
topology_after = modeller.getTopology() topology_after = modeller.getTopology()
water_count = 0 water_count = 0
positive_ion_count = 0 positive_ion_count = 0
chlorine_count = 0 chlorine_count = 0
...@@ -501,20 +509,20 @@ class TestModeller(unittest.TestCase): ...@@ -501,20 +509,20 @@ class TestModeller(unittest.TestCase):
positive_ion_count += 1 positive_ion_count += 1
elif residue.name=='CL': elif residue.name=='CL':
chlorine_count += 1 chlorine_count += 1
total_added = water_count+positive_ion_count+chlorine_count total_added = water_count+positive_ion_count+chlorine_count
self.assertEqual(total_added, 1364) self.assertEqual(total_added, 1364)
expected_ions = math.floor(total_added*expected_ion_fraction/2+0.5) expected_ions = math.floor(total_added*expected_ion_fraction/2+0.5)
self.assertEqual(positive_ion_count, expected_ions) self.assertEqual(positive_ion_count, expected_ions)
self.assertEqual(chlorine_count, expected_ions) self.assertEqual(chlorine_count, expected_ions)
for negativeIon in ['Cl-', 'Br-', 'F-', 'I-']: for negativeIon in ['Cl-', 'Br-', 'F-', 'I-']:
ionName = negativeIon[:-1].upper() ionName = negativeIon[:-1].upper()
modeller = Modeller(topology_nowater, positions_nowater) modeller = Modeller(topology_nowater, positions_nowater)
modeller.addSolvent(self.forcefield, negativeIon=negativeIon, ionicStrength=1.0*molar) modeller.addSolvent(self.forcefield, negativeIon=negativeIon, ionicStrength=1.0*molar)
topology_after = modeller.getTopology() topology_after = modeller.getTopology()
water_count = 0 water_count = 0
sodium_count = 0 sodium_count = 0
negative_ion_count = 0 negative_ion_count = 0
...@@ -531,7 +539,7 @@ class TestModeller(unittest.TestCase): ...@@ -531,7 +539,7 @@ class TestModeller(unittest.TestCase):
expected_ions = math.floor(total_added*expected_ion_fraction/2+0.5) expected_ions = math.floor(total_added*expected_ion_fraction/2+0.5)
self.assertEqual(positive_ion_count, expected_ions) self.assertEqual(positive_ion_count, expected_ions)
self.assertEqual(chlorine_count, expected_ions) self.assertEqual(chlorine_count, expected_ions)
def test_addHydrogensPdb2(self): def test_addHydrogensPdb2(self):
""" Test the addHydrogens() method on the T4-lysozyme-L99A pdb file. """ """ Test the addHydrogens() method on the T4-lysozyme-L99A pdb file. """
...@@ -539,11 +547,11 @@ class TestModeller(unittest.TestCase): ...@@ -539,11 +547,11 @@ class TestModeller(unittest.TestCase):
topology_start = self.topology_start2 topology_start = self.topology_start2
positions = self.positions2 positions = self.positions2
modeller = Modeller(topology_start, positions) modeller = Modeller(topology_start, positions)
# remove hydrogens from the topology # remove hydrogens from the topology
toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')] toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')]
modeller.delete(toDelete) modeller.delete(toDelete)
# Create a variants list to force the one histidine to be of the right variation. # Create a variants list to force the one histidine to be of the right variation.
residues = [residue for residue in topology_start.residues()] residues = [residue for residue in topology_start.residues()]
variants = [None]*len(residues) variants = [None]*len(residues)
...@@ -551,13 +559,13 @@ class TestModeller(unittest.TestCase): ...@@ -551,13 +559,13 @@ class TestModeller(unittest.TestCase):
# By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so # By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so
# that it will match the topology in topology_start. # that it will match the topology in topology_start.
variants[30] = 'HIE' variants[30] = 'HIE'
# add the hydrogens back # add the hydrogens back
modeller.addHydrogens(self.forcefield, variants=variants) modeller.addHydrogens(self.forcefield, variants=variants)
topology_after = modeller.getTopology() topology_after = modeller.getTopology()
validate_equivalence(self, topology_start, topology_after) validate_equivalence(self, topology_start, topology_after)
def test_addHydrogensPdb3(self): def test_addHydrogensPdb3(self):
""" Test the addHydrogens() method on the metallothionein pdb file. """ """ Test the addHydrogens() method on the metallothionein pdb file. """
...@@ -565,31 +573,31 @@ class TestModeller(unittest.TestCase): ...@@ -565,31 +573,31 @@ class TestModeller(unittest.TestCase):
topology_start = self.topology_start3 topology_start = self.topology_start3
positions = self.positions3 positions = self.positions3
modeller = Modeller(topology_start, positions) modeller = Modeller(topology_start, positions)
# remove hydrogens from the topology # remove hydrogens from the topology
toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')] toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')]
modeller.delete(toDelete) modeller.delete(toDelete)
# add the hydrogens back # add the hydrogens back
modeller.addHydrogens(self.forcefield) modeller.addHydrogens(self.forcefield)
topology_after = modeller.getTopology() topology_after = modeller.getTopology()
validate_equivalence(self, topology_start, topology_after) validate_equivalence(self, topology_start, topology_after)
def test_addHydrogensASH(self): def test_addHydrogensASH(self):
""" Test of addHydrogens() in which we force ASH to be a variant using the variants parameter. """ """ Test of addHydrogens() in which we force ASH to be a variant using the variants parameter. """
# use the T4-lysozyme-L99A pdb file # use the T4-lysozyme-L99A pdb file
topology_start = self.topology_start2 topology_start = self.topology_start2
positions = self.positions2 positions = self.positions2
# build the Modeller # build the Modeller
modeller = Modeller(topology_start, positions) modeller = Modeller(topology_start, positions)
# remove hydrogens from the topology # remove hydrogens from the topology
toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')] toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')]
modeller.delete(toDelete) modeller.delete(toDelete)
# Create a variants list to force the one histidine to be of the right variation. # Create a variants list to force the one histidine to be of the right variation.
residues = [residue for residue in topology_start.residues()] residues = [residue for residue in topology_start.residues()]
variants = [None]*len(residues) variants = [None]*len(residues)
...@@ -597,15 +605,15 @@ class TestModeller(unittest.TestCase): ...@@ -597,15 +605,15 @@ class TestModeller(unittest.TestCase):
# By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so # By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so
# that it will match the topology in topology_start. # that it will match the topology in topology_start.
variants[30] = 'HIE' variants[30] = 'HIE'
ASP_residue_list = [9,19,46,60,69,71,88,91,126,158] ASP_residue_list = [9,19,46,60,69,71,88,91,126,158]
for residue_index in ASP_residue_list: for residue_index in ASP_residue_list:
variants[residue_index] = 'ASH' variants[residue_index] = 'ASH'
# add the hydrogens back, using the variants list we just built # add the hydrogens back, using the variants list we just built
modeller.addHydrogens(self.forcefield, variants=variants) modeller.addHydrogens(self.forcefield, variants=variants)
topology_ASH = modeller.getTopology() topology_ASH = modeller.getTopology()
# There should be extra hydrogens on the ASP residues. Assert that they exist, # There should be extra hydrogens on the ASP residues. Assert that they exist,
# then we delete them and validate that the topology matches what we started with. # then we delete them and validate that the topology matches what we started with.
index_list_ASH = [176, 357, 761, 976, 1121, 1150, 1430, 1473, 2028, 2556] index_list_ASH = [176, 357, 761, 976, 1121, 1150, 1430, 1473, 2028, 2556]
...@@ -616,41 +624,41 @@ class TestModeller(unittest.TestCase): ...@@ -616,41 +624,41 @@ class TestModeller(unittest.TestCase):
toDelete2.append(atoms[index]) toDelete2.append(atoms[index])
modeller.delete(toDelete2) modeller.delete(toDelete2)
topology_ASP = modeller.getTopology() topology_ASP = modeller.getTopology()
validate_equivalence(self, topology_ASP, topology_start) validate_equivalence(self, topology_ASP, topology_start)
def test_addHydrogensCYX(self): def test_addHydrogensCYX(self):
""" Test of addHydrogens() in which we force CYX to be a variant using the variants parameter. """ """ Test of addHydrogens() in which we force CYX to be a variant using the variants parameter. """
# use the metallothionein pdb file # use the metallothionein pdb file
topology_start = self.topology_start3 topology_start = self.topology_start3
positions = self.positions3 positions = self.positions3
# build the Modeller # build the Modeller
modeller = Modeller(topology_start, positions) modeller = Modeller(topology_start, positions)
# remove hydrogens from the topology # remove hydrogens from the topology
toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')] toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')]
modeller.delete(toDelete) modeller.delete(toDelete)
# Create a variants list to force the cysteins to be of the CYX variety. # Create a variants list to force the cysteins to be of the CYX variety.
residues = [residue for residue in topology_start.residues()] residues = [residue for residue in topology_start.residues()]
variants = [None]*len(residues) variants = [None]*len(residues)
CYS_residues = [2,4,10,12,16,18,21] CYS_residues = [2,4,10,12,16,18,21]
for index in CYS_residues: for index in CYS_residues:
variants[index] = 'CYX' variants[index] = 'CYX'
# add the hydrogens # add the hydrogens
modeller.addHydrogens(self.forcefield, variants=variants) modeller.addHydrogens(self.forcefield, variants=variants)
topology_CYX = modeller.getTopology() topology_CYX = modeller.getTopology()
# create a second modeller that we will attempt to match with topology_CYX # create a second modeller that we will attempt to match with topology_CYX
modeller2 = Modeller(topology_start, positions) modeller2 = Modeller(topology_start, positions)
topology2 = modeller2.getTopology() topology2 = modeller2.getTopology()
# There should be extra hydrogens on the CYS residues. Assert that they exist # There should be extra hydrogens on the CYS residues. Assert that they exist
# on modeller2, then delete them and validate that the topologies match. # on modeller2, then delete them and validate that the topologies match.
# These are the indices of the hydrogens to delete from CYS to make CYX. # These are the indices of the hydrogens to delete from CYS to make CYX.
index_list_CYS = [31, 49, 110, 135, 171, 193, 229] index_list_CYS = [31, 49, 110, 135, 171, 193, 229]
atoms = [atom for atom in topology2.atoms()] atoms = [atom for atom in topology2.atoms()]
...@@ -660,23 +668,23 @@ class TestModeller(unittest.TestCase): ...@@ -660,23 +668,23 @@ class TestModeller(unittest.TestCase):
toDelete2.append(atoms[index]) toDelete2.append(atoms[index])
modeller2.delete(toDelete2) modeller2.delete(toDelete2)
topology_after = modeller2.getTopology() topology_after = modeller2.getTopology()
validate_equivalence(self, topology_CYX, topology_after) validate_equivalence(self, topology_CYX, topology_after)
def test_addHydrogensGLH(self): def test_addHydrogensGLH(self):
""" Test of addHydrogens() in which we force GLH to be a variant using the variants parameter. """ """ Test of addHydrogens() in which we force GLH to be a variant using the variants parameter. """
# use the T4-lysozyme-L99A pdb file # use the T4-lysozyme-L99A pdb file
topology_start = self.topology_start2 topology_start = self.topology_start2
positions = self.positions2 positions = self.positions2
# build the Modeller # build the Modeller
modeller = Modeller(topology_start, positions) modeller = Modeller(topology_start, positions)
# remove hydrogens from the topology # remove hydrogens from the topology
toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')] toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')]
modeller.delete(toDelete) modeller.delete(toDelete)
# Create a variants list to force the one histidine to be of the right variation. # Create a variants list to force the one histidine to be of the right variation.
residues = [residue for residue in topology_start.residues()] residues = [residue for residue in topology_start.residues()]
variants = [None]*len(residues) variants = [None]*len(residues)
...@@ -684,15 +692,15 @@ class TestModeller(unittest.TestCase): ...@@ -684,15 +692,15 @@ class TestModeller(unittest.TestCase):
# By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so # By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so
# that it will match the topology in topology_start. # that it will match the topology in topology_start.
variants[30] = 'HIE' variants[30] = 'HIE'
GLU_residue_list = [4,10,21,44,61,63,107,127] GLU_residue_list = [4,10,21,44,61,63,107,127]
for residue_index in GLU_residue_list: for residue_index in GLU_residue_list:
variants[residue_index] = 'GLH' variants[residue_index] = 'GLH'
# add the hydrogens back, this time with the GLH variant in place of GLU # add the hydrogens back, this time with the GLH variant in place of GLU
modeller.addHydrogens(self.forcefield, variants=variants) modeller.addHydrogens(self.forcefield, variants=variants)
topology_GLH = modeller.getTopology() topology_GLH = modeller.getTopology()
# There should be extra hydrogens on the GLU residues. Assert that they exist, # There should be extra hydrogens on the GLU residues. Assert that they exist,
# then we delete them and validate that the topology matches what we started with. # then we delete them and validate that the topology matches what we started with.
index_list_GLH = [85, 192, 387, 731, 992, 1018, 1718, 2042] index_list_GLH = [85, 192, 387, 731, 992, 1018, 1718, 2042]
...@@ -703,23 +711,23 @@ class TestModeller(unittest.TestCase): ...@@ -703,23 +711,23 @@ class TestModeller(unittest.TestCase):
toDelete2.append(atoms[index]) toDelete2.append(atoms[index])
modeller.delete(toDelete2) modeller.delete(toDelete2)
topology_GLU = modeller.getTopology() topology_GLU = modeller.getTopology()
validate_equivalence(self, topology_GLU, topology_start) validate_equivalence(self, topology_GLU, topology_start)
def test_addHydrogensLYN(self): def test_addHydrogensLYN(self):
""" Test of addHydrogens() in which we force LYN to be a variant using the variants parameter. """ """ Test of addHydrogens() in which we force LYN to be a variant using the variants parameter. """
# use the T4-lysozyme-L99A pdb file # use the T4-lysozyme-L99A pdb file
topology_start = self.topology_start2 topology_start = self.topology_start2
positions = self.positions2 positions = self.positions2
# build the Modeller # build the Modeller
modeller = Modeller(topology_start, positions) modeller = Modeller(topology_start, positions)
# remove hydrogens from topology # remove hydrogens from topology
toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')] toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')]
modeller.delete(toDelete) modeller.delete(toDelete)
# Create a variants list to force the one histidine to be of the right variation. # Create a variants list to force the one histidine to be of the right variation.
residues = [residue for residue in topology_start.residues()] residues = [residue for residue in topology_start.residues()]
variants = [None]*len(residues) variants = [None]*len(residues)
...@@ -727,25 +735,25 @@ class TestModeller(unittest.TestCase): ...@@ -727,25 +735,25 @@ class TestModeller(unittest.TestCase):
# By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so # By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so
# that it will match the topology in topology_start. # that it will match the topology in topology_start.
variants[30] = 'HIE' variants[30] = 'HIE'
# Here we add the residues in which LYS is present to the variant list. The final # Here we add the residues in which LYS is present to the variant list. The final
# LYS residue, 161, is not on the list because Amber force fields do not have an # LYS residue, 161, is not on the list because Amber force fields do not have an
# entry for a terminal LYN residue. # entry for a terminal LYN residue.
residue_list_LYS = [15,18,34,42,47,59,64,82,84,123,134,146] residue_list_LYS = [15,18,34,42,47,59,64,82,84,123,134,146]
for residue_index in residue_list_LYS: for residue_index in residue_list_LYS:
variants[residue_index] = 'LYN' variants[residue_index] = 'LYN'
# add the hydrogens back, using the variants list we just built # add the hydrogens back, using the variants list we just built
modeller.addHydrogens(self.forcefield, variants=variants) modeller.addHydrogens(self.forcefield, variants=variants)
topology_LYN = modeller.getTopology() topology_LYN = modeller.getTopology()
# create a second modeller that we will attempt to match with topology_LYN # create a second modeller that we will attempt to match with topology_LYN
modeller2 = Modeller(topology_start, positions) modeller2 = Modeller(topology_start, positions)
# There should be extra hydrogens on the LYS residues. Assert that they exist # There should be extra hydrogens on the LYS residues. Assert that they exist
# on modeller2, then delete them and validate that the topologies match. # on modeller2, then delete them and validate that the topologies match.
# These are the indices of the hydrogens to delete from LYN to make LYS. # These are the indices of the hydrogens to delete from LYN to make LYS.
index_list_LYN = [281,343,590,701,780,960,1034,1319,1360,1959,2135,2344] index_list_LYN = [281,343,590,701,780,960,1034,1319,1360,1959,2135,2344]
atoms = [atom for atom in topology_start.atoms()] atoms = [atom for atom in topology_start.atoms()]
...@@ -755,23 +763,23 @@ class TestModeller(unittest.TestCase): ...@@ -755,23 +763,23 @@ class TestModeller(unittest.TestCase):
toDelete2.append(atoms[index]) toDelete2.append(atoms[index])
modeller2.delete(toDelete2) modeller2.delete(toDelete2)
topology_after = modeller2.getTopology() topology_after = modeller2.getTopology()
validate_equivalence(self, topology_LYN, topology_after) validate_equivalence(self, topology_LYN, topology_after)
def test_addHydrogenspH4(self): def test_addHydrogenspH4(self):
""" Test of addHydrogens() with pH=4. """ """ Test of addHydrogens() with pH=4. """
# use the T4-lysozyme-L99A pdb file # use the T4-lysozyme-L99A pdb file
topology_start = self.topology_start2 topology_start = self.topology_start2
positions = self.positions2 positions = self.positions2
# build the Modeller # build the Modeller
modeller = Modeller(topology_start, positions) modeller = Modeller(topology_start, positions)
# remove hydrogens from the topology # remove hydrogens from the topology
toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')] toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')]
modeller.delete(toDelete) modeller.delete(toDelete)
# Create a variants list to force the one histidine to be of the right variation. # Create a variants list to force the one histidine to be of the right variation.
residues = [residue for residue in topology_start.residues()] residues = [residue for residue in topology_start.residues()]
variants = [None]*len(residues) variants = [None]*len(residues)
...@@ -779,12 +787,12 @@ class TestModeller(unittest.TestCase): ...@@ -779,12 +787,12 @@ class TestModeller(unittest.TestCase):
# By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so # By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so
# that it will match the topology in topology_start. # that it will match the topology in topology_start.
variants[30] = 'HIE' variants[30] = 'HIE'
# add the hydrogens back, this time at a lower pH # add the hydrogens back, this time at a lower pH
modeller.addHydrogens(self.forcefield, variants=variants, pH=4.0) modeller.addHydrogens(self.forcefield, variants=variants, pH=4.0)
topology_ASH_GLH = modeller.getTopology() topology_ASH_GLH = modeller.getTopology()
# There should be extra hydrogens on the ASP and GLU residues. Assert that they exist, # There should be extra hydrogens on the ASP and GLU residues. Assert that they exist,
# then we delete them and validate that the topology matches what we started with. # then we delete them and validate that the topology matches what we started with.
index_list_ASH = [177, 359, 765, 980, 1127, 1156, 1436, 1479, 2035, 2564] index_list_ASH = [177, 359, 765, 980, 1127, 1156, 1436, 1479, 2035, 2564]
...@@ -799,34 +807,34 @@ class TestModeller(unittest.TestCase): ...@@ -799,34 +807,34 @@ class TestModeller(unittest.TestCase):
toDelete2.append(atoms[index]) toDelete2.append(atoms[index])
modeller.delete(toDelete2) modeller.delete(toDelete2)
topology_ASP_GLU = modeller.getTopology() topology_ASP_GLU = modeller.getTopology()
validate_equivalence(self, topology_ASP_GLU, topology_start) validate_equivalence(self, topology_ASP_GLU, topology_start)
def test_addHydrogenspH9(self): def test_addHydrogenspH9(self):
""" Test of addHydrogens() with pH=9. """ """ Test of addHydrogens() with pH=9. """
# use the metallothionein pdb file # use the metallothionein pdb file
topology_start = self.topology_start3 topology_start = self.topology_start3
positions = self.positions3 positions = self.positions3
# build the Modeller # build the Modeller
modeller = Modeller(topology_start, positions) modeller = Modeller(topology_start, positions)
# remove hydrogens from topology # remove hydrogens from topology
toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')] toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')]
modeller.delete(toDelete) modeller.delete(toDelete)
# add hydrogens with pH=9, so that the variation CYX will be chosen # add hydrogens with pH=9, so that the variation CYX will be chosen
modeller.addHydrogens(self.forcefield, pH=9.0) modeller.addHydrogens(self.forcefield, pH=9.0)
topology_CYX = modeller.getTopology() topology_CYX = modeller.getTopology()
# create a second modeller that we will attempt to match with topology_CYX # create a second modeller that we will attempt to match with topology_CYX
modeller2 = Modeller(topology_start, positions) modeller2 = Modeller(topology_start, positions)
topology2 = modeller2.getTopology() topology2 = modeller2.getTopology()
# There should be extra hydrogens on the CYS residues. Assert that they exist # There should be extra hydrogens on the CYS residues. Assert that they exist
# on modeller2, then delete them and validate that the topologies match. # on modeller2, then delete them and validate that the topologies match.
# These are the indices of the hydrogens to delete from CYS to make CYX. # These are the indices of the hydrogens to delete from CYS to make CYX.
index_list_CYS = [31, 49, 110, 135, 171, 193, 229] index_list_CYS = [31, 49, 110, 135, 171, 193, 229]
atoms = [atom for atom in topology2.atoms()] atoms = [atom for atom in topology2.atoms()]
...@@ -836,23 +844,23 @@ class TestModeller(unittest.TestCase): ...@@ -836,23 +844,23 @@ class TestModeller(unittest.TestCase):
toDelete2.append(atoms[index]) toDelete2.append(atoms[index])
modeller2.delete(toDelete2) modeller2.delete(toDelete2)
topology_after = modeller2.getTopology() topology_after = modeller2.getTopology()
validate_equivalence(self, topology_CYX, topology_after) validate_equivalence(self, topology_CYX, topology_after)
def test_addHydrogenspH11(self): def test_addHydrogenspH11(self):
""" Test of addHydrogens() with pH=11. """ """ Test of addHydrogens() with pH=11. """
# use the T4-lysozyme-L99A pdb file # use the T4-lysozyme-L99A pdb file
topology_start = self.topology_start2 topology_start = self.topology_start2
positions = self.positions2 positions = self.positions2
# build the Modeller # build the Modeller
modeller = Modeller(topology_start, positions) modeller = Modeller(topology_start, positions)
# remove hydrogens from topology # remove hydrogens from topology
toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')] toDelete = [atom for atom in topology_start.atoms() if atom.element==Element.getBySymbol('H')]
modeller.delete(toDelete) modeller.delete(toDelete)
# Create a variants list to force the one histidine to be of the right variation. # Create a variants list to force the one histidine to be of the right variation.
residues = [residue for residue in topology_start.residues()] residues = [residue for residue in topology_start.residues()]
variants = [None]*len(residues) variants = [None]*len(residues)
...@@ -860,18 +868,18 @@ class TestModeller(unittest.TestCase): ...@@ -860,18 +868,18 @@ class TestModeller(unittest.TestCase):
# By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so # By setting variants[30] to 'HIE', we force the hydrogen onto the epsilon nitrogen, so
# that it will match the topology in topology_start. # that it will match the topology in topology_start.
variants[30] = 'HIE' variants[30] = 'HIE'
# The Amber force fields do not have an entry for terminal LYN residues, so we need to # The Amber force fields do not have an entry for terminal LYN residues, so we need to
# force residue 161 to be the LYS variant. # force residue 161 to be the LYS variant.
variants[161] = 'LYS' variants[161] = 'LYS'
# add the hydrogens back at pH = 11 # add the hydrogens back at pH = 11
modeller.addHydrogens(self.forcefield, variants=variants, pH=11.0) modeller.addHydrogens(self.forcefield, variants=variants, pH=11.0)
topology_LYN = modeller.getTopology() topology_LYN = modeller.getTopology()
# create a second modeller that we will attempt to match with topology_LYN # create a second modeller that we will attempt to match with topology_LYN
modeller2 = Modeller(topology_start, positions) modeller2 = Modeller(topology_start, positions)
# There should be extra hydrogens on the LYS residues. Assert that they exist # There should be extra hydrogens on the LYS residues. Assert that they exist
# on modeller2, then delete them and validate that the topologies match. # on modeller2, then delete them and validate that the topologies match.
index_list_LYN = [281,343,590,701,780,960,1034,1319,1360,1959,2135,2344] index_list_LYN = [281,343,590,701,780,960,1034,1319,1360,1959,2135,2344]
...@@ -880,24 +888,24 @@ class TestModeller(unittest.TestCase): ...@@ -880,24 +888,24 @@ class TestModeller(unittest.TestCase):
for index in index_list_LYN: for index in index_list_LYN:
self.assertTrue(atoms[index].element.symbol=='H') self.assertTrue(atoms[index].element.symbol=='H')
toDelete2.append(atoms[index]) toDelete2.append(atoms[index])
modeller2.delete(toDelete2) modeller2.delete(toDelete2)
topology_after = modeller2.getTopology() topology_after = modeller2.getTopology()
validate_equivalence(self, topology_LYN, topology_after) validate_equivalence(self, topology_LYN, topology_after)
def test_addExtraParticles(self): def test_addExtraParticles(self):
"""Test addExtraParticles().""" """Test addExtraParticles()."""
# Create a box of water. # Create a box of water.
ff1 = ForceField('tip3p.xml') ff1 = ForceField('tip3p.xml')
modeller = Modeller(Topology(), []*nanometers) modeller = Modeller(Topology(), []*nanometers)
modeller.addSolvent(ff1, 'tip3p', boxSize=Vec3(2,2,2)*nanometers) modeller.addSolvent(ff1, 'tip3p', boxSize=Vec3(2,2,2)*nanometers)
# Now convert the water to TIP4P. # Now convert the water to TIP4P.
ff2 = ForceField('tip4pew.xml') ff2 = ForceField('tip4pew.xml')
modeller.addExtraParticles(ff2) modeller.addExtraParticles(ff2)
for residue in modeller.topology.residues(): for residue in modeller.topology.residues():
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment