Commit a11b141c by Jaime RGP

Support for additional solvation boxes

parent 1e02b130
......@@ -8,14 +8,21 @@ function validateForm() {
}
}
if (document.getElementById("addWaterCheckbox").checked) {
var custombox = document.getElementById("customBoxRadio").checked
var xsize = document.getElementById("boxxfield").value
var ysize = document.getElementById("boxyfield").value
var zsize = document.getElementById("boxzfield").value
var strength = document.getElementById("ionicstrengthfield").value
if (!(xsize > 0 && ysize > 0 && zsize > 0)) {
if (custombox && !(xsize > 0 && ysize > 0 && zsize > 0)) {
alert("Box dimensions must be positive numbers.")
return false
}
var geombox = document.getElementById("geometricBoxRadio").checked
var padsize = document.getElementById("geomPadding").value
if (geombox && !(padsize > 0)) {
alert("Box padding must be a positive number.")
return false
}
var strength = document.getElementById("ionicstrengthfield").value
if (!(strength >= 0)) {
alert("Ionic strength must be a nonnegative number.")
return false
......@@ -59,15 +66,28 @@ Add a water box surrounding the model?
<div id="waterInputs" style="margin-left:50px">
<table style="text-align:right">
<tr>
<td>Type box dimensions (in nm):</td>
<td style="text-align:left"><input id="customBoxRadio" type="radio" name="boxType" value="custom" checked>Custom box dimensions (in nm):</td>
<div id="customBoxDimensions">
<td><input type="text" id="boxxfield" name="boxx" size="8"></td>
<td><input type="text" id="boxyfield" name="boxy" size="8"></td>
<td><input type="text" id="boxzfield" name="boxz" size="8"></td>
</div>
</tr>
<tr>
<td>... or set them from padding:</td>
<td><input type="text" id="xyzpadding" name="xyzpad" size="8" oninput="applyPaddingToWaterBox(this.value)"></td>
<td colspan="2"><input type="checkbox" id="cubicPaddingCheckBox" name="cubicPaddingCheckBox" checked>Force cubic geometry <span title="All sides are equal to the biggest dimension plus padding" style="border-bottom: 1px dotted black; cursor: help">?</span></td>
<td style="text-align:left"><input id="geometricBoxRadio" type="radio" name="boxType" value="geometry">Geometry with padding (in nm):</td>
<div id="geometricBoxDimensions">
<td><input type="text" id="geomPadding" name="geomPadding" size="8">
</td>
<td colspan="2">
<select id="geometryDropdown" name="geometryDropdown">
<option value="cube" selected="selected">Cube</option>
<option value="truncatedOctahedron">Truncated octahedron</option>
<option value="rhombicDodecahedron">Rhombic dodecahedron</option>
</select>
<span title="The specified padding will be applied on the largest molecular axis, maintaining selected geometry" style="border-bottom: 1px dotted black; cursor: help">?</span>
</div>
</td>
</tr>
%s
</table>
......@@ -87,7 +107,11 @@ Add a water box surrounding the model?
setCurrentStep(6);
enableControls(document.getElementById('waterInputs'), false);
var molxyz = [].slice.call(document.getElementById('boxContainingAllAtoms').getElementsByTagName('td')).splice(1,3).map(function(td){ return parseFloat(td.textContent)});
var pbcxyz = [document.getElementById('boxxfield'), document.getElementById('boxyfield'), document.getElementById('boxzfield')];
var hiddenInput = document.createElement("input");
hiddenInput.setAttribute("type", "hidden");
hiddenInput.setAttribute("name", "maxMolecularAxis");
hiddenInput.setAttribute("value", Math.max.apply(Math, molxyz));
document.getElementById("mainform").appendChild(hiddenInput);
</script>
</body>
<html>
......@@ -1021,15 +1021,17 @@ class PDBFixer(object):
self.topology = modeller.topology
self.positions = modeller.positions
def addSolvent(self, boxSize=None, padding=None, positiveIon='Na+', negativeIon='Cl-', ionicStrength=0*unit.molar):
def addSolvent(self, boxSize=None, padding=None, boxVectors=None, positiveIon='Na+', negativeIon='Cl-', ionicStrength=0*unit.molar):
"""Add a solvent box surrounding the structure.
Parameters
----------
boxSize : simtk.openmm.Vec3, optional, default=None
The size of the box to fill with water. If specified, padding must not be specified.
The size of the box to fill with water. If specified, padding and boxVectors must not be specified.
padding : simtk.unit.Quantity compatible with nanometers, optional, default=None
Padding around macromolecule for filling box with water. If specified, boxSize must not be specified.
Padding around macromolecule for filling box with water. If specified, boxSize and boxVectors must not be specified.
boxVectors : 3-tuple of simtk.openmm.Vec3, optional, default=None
Three vectors specifying the geometry of the box. If specified, padding and boxSize must not be specified.
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-'
......@@ -1053,7 +1055,7 @@ class PDBFixer(object):
modeller = app.Modeller(self.topology, self.positions)
forcefield = self._createForceField(self.topology, True)
modeller.addSolvent(forcefield, padding=padding, boxSize=boxSize, positiveIon=positiveIon, negativeIon=negativeIon, ionicStrength=ionicStrength)
modeller.addSolvent(forcefield, padding=padding, boxSize=boxSize, boxVectors=boxVectors, positiveIon=positiveIon, negativeIon=negativeIon, ionicStrength=ionicStrength)
chains = list(modeller.topology.chains())
if len(chains) == 1:
chains[0].id = 'A'
......
......@@ -3,9 +3,11 @@ from __future__ import absolute_import
import webbrowser
import os.path
import time
from math import sqrt
import simtk.openmm.app as app
import simtk.unit as unit
from simtk.openmm.vec3 import Vec3
from .pdbfixer import PDBFixer, proteinResidues, dnaResidues, rnaResidues, _guessFileFormat
from . import uiserver
......@@ -111,11 +113,25 @@ def addHydrogensPageCallback(parameters, handler):
pH = float(parameters.getfirst('ph'))
fixer.addMissingHydrogens(pH)
if 'addwater' in parameters:
boxSize = (float(parameters.getfirst('boxx')), float(parameters.getfirst('boxy')), float(parameters.getfirst('boxz')))*unit.nanometer
padding, boxSize, boxVectors = None, None, None
if parameters.getfirst('boxType') == 'geometry':
geompadding = float(parameters.getfirst('geomPadding')) * unit.nanometer
geometry = parameters.getfirst('geometryDropdown')
base_size = float(parameters.getfirst('maxMolecularAxis')) * unit.nanometer
if geometry == 'cube':
padding = geompadding
elif geometry == 'truncatedOctahedron':
vectors = Vec3(1,0,0), Vec3(1/3,2*sqrt(2)/3,0), Vec3(-1/3,1/3,sqrt(6)/3)
boxVectors = [(base_size+geompadding)*v for v in vectors]
elif geometry == 'rhombicDodecahedron':
vectors = Vec3(1,0,0), Vec3(0,1,0), Vec3(0.5,0.5,sqrt(2)/2)
boxVectors = [(base_size+geompadding)*v for v in vectors]
else:
boxSize = (float(parameters.getfirst('boxx')), float(parameters.getfirst('boxy')), float(parameters.getfirst('boxz')))*unit.nanometer
ionicStrength = float(parameters.getfirst('ionicstrength'))*unit.molar
positiveIon = parameters.getfirst('positiveion')+'+'
negativeIon = parameters.getfirst('negativeion')+'-'
fixer.addSolvent(boxSize, None, positiveIon, negativeIon, ionicStrength)
fixer.addSolvent(boxSize, padding, boxVectors, positiveIon, negativeIon, ionicStrength)
displaySaveFilePage()
def saveFilePageCallback(parameters, handler):
......@@ -123,7 +139,10 @@ def saveFilePageCallback(parameters, handler):
output = StringIO()
if fixer.source is not None:
output.write("REMARK 1 PDBFIXER FROM: %s\n" % fixer.source)
app.PDBFile.writeFile(fixer.topology, fixer.positions, output, True)
try:
app.PDBFile.writeFile(fixer.topology, fixer.positions, output, True)
except AssertionError:
print
handler.sendDownload(output.getvalue(), 'output.pdb')
else:
displayStartPage()
......
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