Skip to content

Commit

Permalink
Can build membranes
Browse files Browse the repository at this point in the history
  • Loading branch information
peastman committed Nov 30, 2017
1 parent 943fda1 commit 3f8ea2f
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 10 deletions.
18 changes: 15 additions & 3 deletions Manual.html
Expand Up @@ -4,7 +4,7 @@
</head>
<body>
<h1 style="text-align:center">PDBFixer</h1>
<div style="text-align:center">Copyright 2013-2015 by Peter Eastman and Stanford University</div>
<div style="text-align:center">Copyright 2013-2017 by Peter Eastman and Stanford University</div>

<h1>1. Introduction</h1>

Expand All @@ -18,6 +18,7 @@ <h1>1. Introduction</h1>
<li>The file may include more than what you want to simulate. For example, there may be salts, ligands, or other molecules that were added for experimental purposes. Or the crystallographic unit cell may contain multiple copies of a protein, but you only want to simulate a single copy.</li>
<li>There may be multiple locations listed for some atoms.</li>
<li>If you want to simulate the structure in explicit solvent, you will need to add a water box surrounding it.</li>
<li>For membrane proteins, you may also need to add a lipid membrane.</li>
</ol>

PDBFixer can fix all of these problems for you in a fully automated way. You simply select a file, tell it which problems to fix, and it does everything else.
Expand Down Expand Up @@ -71,13 +72,14 @@ <h3>Add Heavy Atoms</h3>

This page lists all heavy atoms that are missing from the file. They will be added automatically.

<h3>Add Hydrogens and Water</h3>
<h3>Add Hydrogens, Water, and Membrane</h3>

This page gives you the chance to make other optional changes:

<ul>
<li><b>Add Missing Hydrogens</b> If hydrogen atoms are missing from the file, PDBFixer can add them for you. Some residues can exist in multiple protonation states. To select which one to use, you can specify a pH, and the most common form of each residue at that pH will be used.</li>
<li><b>Add Water</b> Add a water box surrounding the system. In addition to water, counterions will be added to neutalize the system. You also may choose to add more ions based on a desired total ionic strength. Select the ionic strength and the types of ions to use.
<li><b>Add Water</b> Add a water box surrounding the system. In addition to water, counterions will be added to neutalize the system. You also may choose to add more ions based on a desired total ionic strength. Select the ionic strength and the types of ions to use.</li>
<li><b>Add Membrane</b> Add a lipid membrane. POPC and POPE lipids are supported.</li>
</ul>

<h3>Save File</h3>
Expand Down Expand Up @@ -212,6 +214,16 @@ <h3>Add Water</h3>
<p>
<tt>fixer.addSolvent(Vec3(5, 5, 5)*nanometer, positiveIon='K+', ionicStrength=0.1*molar)</tt>

<h3>Add Membrane</h3>

If you want to add a lipid membrane, call <tt>addMembrane()</tt>. This method also adds water, so you should not also call <tt>addSolvent()</tt> when using it. There are several optional arguments. The full definition is
<p>
<tt>addMembrane(self, lipidType='POPC', membraneCenterZ=0*nanometer, minimumPadding=1*nanometer, positiveIon='Na+', negativeIon='Cl-', ionicStrength=0*molar)</tt>
<p>
<tt>lipidType</tt> should be either <tt>'POPC'</tt> or <tt>'POPE'</tt>. <tt>membraneCenterZ</tt> is the position along the Z axis at which the center of the membrane will be located. <tt>minimumPadding</tt> is the minimum acceptable distance between the protein and the edges of the periodic box. All other arguments are the same as for <tt>addSolvent()</tt>. For example, the following line adds a POPE membrane centered at Z=0 with at least 1 nm of padding on all sides:
<p>
<tt>fixer.addMembrane('POPE')</tt>

<h3>Examples</h3>

Here is a complete example that ties this together. It adds all missing atoms including heavy atoms, missing residues, and hydrogens. It replaces all nonstandard residues by their standard equivalents then deletes all remaining heterogens except water. Finally, it fills in all gaps with water; that is, it adds a water box whose dimensions match the crystallographic unit cell. It saves the result to a file called output.pdb.
Expand Down
56 changes: 50 additions & 6 deletions pdbfixer/html/addHydrogens.html
Expand Up @@ -18,8 +18,20 @@
}
var geombox = document.getElementById("geometricBoxRadio").checked
var padsize = document.getElementById("geomPadding").value
if (geombox && !(padsize > 0)) {
alert("Box padding must be a positive number.")
if (geombox && padsize < 0) {
alert("Box padding cannot be negative.")
return false
}
var strength = document.getElementById("ionicstrengthfield").value
if (!(strength >= 0)) {
alert("Ionic strength must be a nonnegative number.")
return false
}
}
if (document.getElementById("addMembraneCheckbox").checked) {
var padsize = document.getElementById("membranePadding").value
if (padsize < 0) {
alert("Box padding cannot be negative.")
return false
}
var strength = document.getElementById("ionicstrengthfield").value
Expand All @@ -44,7 +56,21 @@
pbcxyz[i].value = Math.ceil((padding+molxyz[i])*1000) / 1000;
}
}
}
}
function waterBoxChanged() {
checked = document.getElementById('addWaterCheckbox').checked;
document.getElementById('addMembraneCheckbox').checked = false;
enableControls(document.getElementById('waterInputs'), checked);
enableControls(document.getElementById('ionInputs'), checked);
enableControls(document.getElementById('membraneInputs'), false);
}
function membraneBoxChanged() {
checked = document.getElementById('addMembraneCheckbox').checked;
document.getElementById('addWaterCheckbox').checked = false;
enableControls(document.getElementById('membraneInputs'), checked);
enableControls(document.getElementById('ionInputs'), checked);
enableControls(document.getElementById('waterInputs'), false);
}
</script>
<style>
a.tooltip {
Expand Down Expand Up @@ -90,10 +116,10 @@ <h1>Add Missing Hydrogens</h1>
Add missing hydrogen atoms?
<p>
<input type="checkbox" id="addHydrogensCheckbox" name="addhydrogens" onchange="document.getElementById('phfield').disabled=!document.getElementById('addHydrogensCheckbox').checked" checked> Add hydrogens appropriate for pH <input type="text" id="phfield" name="ph" value="7.0" size="5">
<h1>Add Water</h1>
Add a water box surrounding the model?
<h1>Add Water/Membrane</h1>
Add a water box or membrane surrounding the model?
<p>
<input type="checkbox" id="addWaterCheckbox" name="addwater" onchange="enableControls(document.getElementById('waterInputs'), document.getElementById('addWaterCheckbox').checked)"> Add water
<input type="checkbox" id="addWaterCheckbox" name="addwater" onchange="waterBoxChanged()"> Add water box
<div id="waterInputs" style="margin-left:50px">
<table style="text-align:right">
<tr>
Expand Down Expand Up @@ -122,6 +148,22 @@ <h1>Add Water</h1>
</tr>
%s
</table>
</div>
<p>
<input type="checkbox" id="addMembraneCheckbox" name="addmembrane" onchange="membraneBoxChanged()"> Add membrane and water
<div id="membraneInputs" style="margin-left:50px">
The membrane will lie in the XY plane and be centered at Z=0. Make sure the protein is properly oriented and positioned.
When possible, it is easiest to use a PDB file from <a href="http://opm.phar.umich.edu/">OPM</a> since they are already properly positioned.
<p>
Lipid type:
<select id="lipidType" name="lipidType">
<option value="POPC" selected="selected">POPC</option>
<option value="POPE">POPE</option>
</select>
<p>
Minimum padding around protein: <input type="text" id="membranePadding" name="membranePadding" value="1.0" size="5"> (nm)
</div>
<div id="ionInputs">
<p>
Ions will be added to neutralize the model. You can optionally add more ions based on a desired bulk ionic strength.
<p>
Expand All @@ -137,6 +179,8 @@ <h1>Add Water</h1>
<script>
setCurrentStep(6);
enableControls(document.getElementById('waterInputs'), false);
enableControls(document.getElementById('membraneInputs'), false);
enableControls(document.getElementById('ionInputs'), false);
var molxyz = [].slice.call(document.getElementById('boxContainingAllAtoms').getElementsByTagName('td')).splice(1,3).map(function(td){ return parseFloat(td.textContent)});
var hiddenInput = document.createElement("input");
hiddenInput.setAttribute("type", "hidden");
Expand Down
34 changes: 33 additions & 1 deletion pdbfixer/pdbfixer.py
Expand Up @@ -1063,11 +1063,43 @@ def addSolvent(self, boxSize=None, padding=None, boxVectors=None, positiveIon='N
self.topology = modeller.topology
self.positions = modeller.positions

def addMembrane(self, lipidType='POPC', membraneCenterZ=0*unit.nanometer, minimumPadding=1*unit.nanometer, positiveIon='Na+', negativeIon='Cl-', ionicStrength=0*unit.molar):
"""Add a lipid membrane to the structure.
This method adds both lipids and water, so you should call either addSolvent() or addMembrane(),
but not both. See Modeller.addMembrane() for more details.
Parameters
----------
lipidType : string='POPC'
the type of lipid to use. Supported values are 'POPC' and 'POPE'.
membraneCenterZ: distance=0*nanometer
the position along the Z axis of the center of the membrane
minimumPadding : distance=1*nanometer
the padding distance to use
positiveIon : str, optional, default='Na+'
The type of positive ion to add. Allowed values are 'Cs+', 'K+', 'Li+', 'Na+', and 'Rb+'.
negativeIon : str, optional, default='Cl-'
The type of negative ion to add. Allowed values are 'Cl-', 'Br-', 'F-', and 'I-'.
ionicStrength : simtk.unit.Quantity with units compatible with molar, optional, default=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.
"""
modeller = app.Modeller(self.topology, self.positions)
forcefield = self._createForceField(self.topology, True)
modeller.addMembrane(forcefield, lipidType=lipidType, minimumPadding=minimumPadding, positiveIon=positiveIon, negativeIon=negativeIon, ionicStrength=ionicStrength)
chains = list(modeller.topology.chains())
if len(chains) == 1:
chains[0].id = 'A'
else:
chains[-1].id = chr(ord(chains[-2].id)+1)
self.topology = modeller.topology
self.positions = modeller.positions

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

if water:
forcefield = app.ForceField('amber10.xml', 'tip3p.xml')
forcefield = app.ForceField('amber14-all.xml', 'amber14/tip3p.xml')
nonbonded = [f for f in forcefield._forces if isinstance(f, NonbondedGenerator)][0]
radii = {'H':0.198, 'Li':0.203, 'C':0.340, 'N':0.325, 'O':0.299, 'F':0.312, 'Na':0.333, 'Mg':0.141,
'P':0.374, 'S':0.356, 'Cl':0.347, 'K':0.474, 'Br':0.396, 'Rb':0.527, 'I':0.419, 'Cs':0.605}
Expand Down
7 changes: 7 additions & 0 deletions pdbfixer/ui.py
Expand Up @@ -128,6 +128,13 @@ def addHydrogensPageCallback(parameters, handler):
positiveIon = parameters.getfirst('positiveion')+'+'
negativeIon = parameters.getfirst('negativeion')+'-'
fixer.addSolvent(boxSize, padding, boxVectors, positiveIon, negativeIon, ionicStrength)
if 'addmembrane' in parameters:
lipidType = parameters.getfirst('lipidType')
padding = float(parameters.getfirst('membranePadding'))*unit.nanometer
ionicStrength = float(parameters.getfirst('ionicstrength'))*unit.molar
positiveIon = parameters.getfirst('positiveion')+'+'
negativeIon = parameters.getfirst('negativeion')+'-'
fixer.addMembrane(lipidType, 0*unit.nanometer, padding, positiveIon, negativeIon, ionicStrength)
displaySaveFilePage()

def saveFilePageCallback(parameters, handler):
Expand Down

0 comments on commit 3f8ea2f

Please sign in to comment.