Commit 3515f0da by Peter Eastman

Improvements to the user interface

parent 8f391650
pdbfixer PDBFixer
======== ========
PDBFixer is an easy to use application for fixing problems in Protein Data Bank files in preparation for simulating them. It can automatically fix the following problems:
- Add missing heavy atoms.
- Add missing hydrogen atoms.
- Build missing loops.
- Convert non-standard amino acids to their standard equivalents.
- Select a single position for atoms with multiple alternate positions listed.
- Delete unwanted chains from the model.
\ No newline at end of file
<html>
<head><title>PDB Fixer</title></head>
<body>
The following residues are missing heavy atoms, which will be added.
<p>
<form method="post" action="/">
<table border="1">
<tr><th>Chain</th><th>Residue</th><th>Missing Atoms</th></tr>
%s
</table>
<p>
<input type="submit" value="Continue"/>
</form>
</body>
<html>
<html>
<head><title>PDB Fixer</title>
<script>
function validateForm() {
if (document.getElementById("addCheckbox").checked) {
var ph = document.getElementById("phfield").value;
if (ph > 0 && ph < 14)
return true;
alert("pH must be a number between 0 and 14.")
return false;
}
}
</script>
</head>
<body>
Add missing hydrogen atoms?
<p>
<form method="post" action="/" onsubmit="return validateForm()">
<input type="checkbox" id="addCheckbox" name="add" checked> Add hydrogens appropriate for pH <input type="text" id="phfield" name="ph" value="7.0" size="5">
<p>
<input type="submit" value="Continue"/>
</form>
</body>
<html>
\ No newline at end of file
<html>
<head>
<title>PDB Fixer</title>
<script>
function setCheckboxes(selected) {
checkboxes = document.getElementById("table").getElementsByTagName("input");
for (var i = 0; i < checkboxes.length; i++)
checkboxes[i].checked = selected
}
</script>
</head>
<body>
The SEQRES records in this PDB file include residues that are missing from the atom data section. Do you want to add the missing residues?
<p>
<form method="post" action="/">
<table border="1" id="table">
<tr><th>Chain</th><th>Residue Positions</th><th>Sequence</th><th>Add?</th></tr>
%s
</table>
<input type="button" value="Select All" onclick="setCheckboxes(true);"/><input type="button" value="Select None" onclick="setCheckboxes(false);"/>
<p>
<input type="submit" value="Continue"/>
</form>
</body>
<html>
<html>
<head>
<title>PDB Fixer</title>
<script>
function setCheckboxes(selected) {
checkboxes = document.getElementById("table").getElementsByTagName("input");
for (var i = 0; i < checkboxes.length; i++)
checkboxes[i].checked = selected
}
</script>
</head>
<body>
This PDB file contains non-standard residues. Do you want to convert them to the corresponding standard residues?
<p>
<form method="post" action="/">
<table border="1" id="table">
<tr><th>Chain</th><th>Residue</th><th>Convert To</th><th>Convert?</th></tr>
%s
</table>
<input type="button" value="Select All" onclick="setCheckboxes(true);"/><input type="button" value="Select None" onclick="setCheckboxes(false);"/>
<p>
<input type="submit" value="Continue"/>
</form>
</body>
<html>
\ No newline at end of file
<html>
<head>
<title>PDB Fixer</title>
<script>
function setCheckboxes(selected) {
checkboxes = document.getElementById("table").getElementsByTagName("input");
for (var i = 0; i < checkboxes.length; i++)
checkboxes[i].checked = selected
}
</script>
</head>
<body>
This PDB file contains %d chains. Select which ones to include.
<p>
<form method="post" action="/">
<table border="1" id="table">
<tr><th>Chain</th><th># Residues</th><th>Content</th><th>Include?</th></tr>
%s
</table>
<input type="button" value="Select All" onclick="setCheckboxes(true);"/><input type="button" value="Select None" onclick="setCheckboxes(false);"/>
<p>
<input type="submit" value="Continue"/>
</form>
</body>
<html>
\ No newline at end of file
<html>
<head><title>PDB Fixer</title></head>
<body>
The fixed PDB file is ready to save.
<p>
<form method="post" action="/">
<input type="submit" name="save" value="Save File"/>
<input type="submit" name="newfile" value="Process Another File"/>
</form>
</body>
<html>
<html>
<head><title>PDBFixer</title></head>
<body>
<h1>Welcome To PDBFixer!</h1>
Select a PDB file to load. It will be analyzed for problems.
<p>
<form method="post" action="/" enctype="multipart/form-data">
PDB File: <input type="file" name="pdbfile" onchange="document.getElementById('submit').disabled=false;"/>
<p>
<input type="submit" id="submit" value="Analyze File" disabled/>
</form>
</body>
</html>
...@@ -3,8 +3,14 @@ from simtk.openmm.app.internal.pdbstructure import PdbStructure ...@@ -3,8 +3,14 @@ from simtk.openmm.app.internal.pdbstructure import PdbStructure
from pdbfixer import PDBFixer, substitutions from pdbfixer import PDBFixer, substitutions
import uiserver import uiserver
import webbrowser import webbrowser
import os.path
from cStringIO import StringIO from cStringIO import StringIO
def loadHtmlFile(name):
htmlPath = os.path.join(os.path.dirname(__file__), 'html')
file = os.path.join(htmlPath, name)
return open(file).read()
def startPageCallback(parameters, handler): def startPageCallback(parameters, handler):
if 'pdbfile' in parameters: if 'pdbfile' in parameters:
global fixer global fixer
...@@ -38,10 +44,10 @@ def addHydrogensPageCallback(parameters, handler): ...@@ -38,10 +44,10 @@ def addHydrogensPageCallback(parameters, handler):
if 'add' in parameters: if 'add' in parameters:
pH = float(parameters.getfirst('ph')) pH = float(parameters.getfirst('ph'))
fixer.addMissingHydrogens(pH) fixer.addMissingHydrogens(pH)
displayDownloadPage() displaySaveFilePage()
def downloadPageCallback(parameters, handler): def saveFilePageCallback(parameters, handler):
if 'download' in parameters: if 'save' in parameters:
output = StringIO() output = StringIO()
app.PDBFile.writeFile(fixer.topology, fixer.positions, output) app.PDBFile.writeFile(fixer.topology, fixer.positions, output)
handler.sendDownload(output.getvalue(), 'output.pdb') handler.sendDownload(output.getvalue(), 'output.pdb')
...@@ -50,21 +56,7 @@ def downloadPageCallback(parameters, handler): ...@@ -50,21 +56,7 @@ def downloadPageCallback(parameters, handler):
def displayStartPage(): def displayStartPage():
uiserver.setCallback(startPageCallback) uiserver.setCallback(startPageCallback)
uiserver.setContent(""" uiserver.setContent(loadHtmlFile("start.html"))
<html>
<head><title>PDBFixer</title></head>
<body>
<h1>Welcome To PDBFixer!</h1>
Select a PDB file to load. It will be analyzed for problems.
<p>
<form method="post" action="/" enctype="multipart/form-data">
PDB File: <input type="file" name="pdbfile"/>
<p>
<input type="submit" value="Analyze File"/>
</form>
</body>
</html>
""")
def displayDeleteChainsPage(): def displayDeleteChainsPage():
uiserver.setCallback(deleteChainsPageCallback) uiserver.setCallback(deleteChainsPageCallback)
...@@ -87,23 +79,7 @@ def displayDeleteChainsPage(): ...@@ -87,23 +79,7 @@ def displayDeleteChainsPage():
else: else:
content = ', '.join(set(residues)) content = ', '.join(set(residues))
table += ' <tr><td>%d</td><td>%d</td><td>%s</td><td><input type="checkbox" name="include%d" checked></td></tr>\n' % (chain.index+1, len(residues), content, i) table += ' <tr><td>%d</td><td>%d</td><td>%s</td><td><input type="checkbox" name="include%d" checked></td></tr>\n' % (chain.index+1, len(residues), content, i)
uiserver.setContent(""" uiserver.setContent(loadHtmlFile("removeChains.html") % (numChains, table))
<html>
<head><title>PDB Fixer</title></head>
<body>
This PDB file contains %d chains. Select which ones to include.
<p>
<form method="post" action="/">
<table border="1">
<tr><th>Chain</th><th># Residues</th><th>Content</th><th>Include?</th></tr>
%s
</table>
<p>
<input type="submit" value="Continue"/>
</form>
</body>
<html>
""" % (numChains, table))
def displayAddResiduesPage(): def displayAddResiduesPage():
uiserver.setCallback(addResiduesPageCallback) uiserver.setCallback(addResiduesPageCallback)
...@@ -115,23 +91,7 @@ def displayAddResiduesPage(): ...@@ -115,23 +91,7 @@ def displayAddResiduesPage():
for i, key in enumerate(sorted(fixer.missingResidues)): for i, key in enumerate(sorted(fixer.missingResidues)):
residues = fixer.missingResidues[key] residues = fixer.missingResidues[key]
table += ' <tr><td>%d</td><td>%d to %d</td><td>%s</td><td><input type="checkbox" name="add%d" checked></td></tr>\n' % (key[0]+1, key[1]+1, key[1]+len(residues), ', '.join(residues), i) table += ' <tr><td>%d</td><td>%d to %d</td><td>%s</td><td><input type="checkbox" name="add%d" checked></td></tr>\n' % (key[0]+1, key[1]+1, key[1]+len(residues), ', '.join(residues), i)
uiserver.setContent(""" uiserver.setContent(loadHtmlFile("addResidues.html") % table)
<html>
<head><title>PDB Fixer</title></head>
<body>
The SEQRES records in this PDB file include residues that are missing from the atom data section. Do you want to add the missing residues?
<p>
<form method="post" action="/">
<table border="1">
<tr><th>Chain</th><th>Residue Positions</th><th>Sequence</th><th>Add?</th></tr>
%s
</table>
<p>
<input type="submit" value="Continue"/>
</form>
</body>
<html>
""" % table)
def displayConvertResiduesPage(): def displayConvertResiduesPage():
uiserver.setCallback(convertResiduesPageCallback) uiserver.setCallback(convertResiduesPageCallback)
...@@ -146,23 +106,7 @@ def displayConvertResiduesPage(): ...@@ -146,23 +106,7 @@ def displayConvertResiduesPage():
table = "" table = ""
for i, residue in enumerate(fixer.nonstandardResidues): for i, residue in enumerate(fixer.nonstandardResidues):
table += ' <tr><td>%d</td><td>%s %d</td><td>%s</td><td><input type="checkbox" name="convert%d" checked></td></tr>\n' % (residue.chain.index+1, residue.name, indexInChain[residue], substitutions[residue.name], i) table += ' <tr><td>%d</td><td>%s %d</td><td>%s</td><td><input type="checkbox" name="convert%d" checked></td></tr>\n' % (residue.chain.index+1, residue.name, indexInChain[residue], substitutions[residue.name], i)
uiserver.setContent(""" uiserver.setContent(loadHtmlFile("convertResidues.html") % table)
<html>
<head><title>PDB Fixer</title></head>
<body>
This PDB file contains non-standard residues. Do you want to convert them to the corresponding standard residues?
<p>
<form method="post" action="/">
<table border="1">
<tr><th>Chain</th><th>Residue</th><th>Convert To</th><th>Convert?</th></tr>
%s
</table>
<p>
<input type="submit" value="Continue"/>
</form>
</body>
<html>
""" % table)
def displayMissingAtomsPage(): def displayMissingAtomsPage():
uiserver.setCallback(missingAtomsPageCallback) uiserver.setCallback(missingAtomsPageCallback)
...@@ -184,58 +128,17 @@ def displayMissingAtomsPage(): ...@@ -184,58 +128,17 @@ def displayMissingAtomsPage():
if residue in fixer.missingTerminals: if residue in fixer.missingTerminals:
atoms.extend(atom for atom in fixer.missingTerminals[residue]) atoms.extend(atom for atom in fixer.missingTerminals[residue])
table += ' <tr><td>%d</td><td>%s %d</td><td>%s</td></tr>\n' % (residue.chain.index+1, residue.name, indexInChain[residue], ', '.join(atoms)) table += ' <tr><td>%d</td><td>%s %d</td><td>%s</td></tr>\n' % (residue.chain.index+1, residue.name, indexInChain[residue], ', '.join(atoms))
uiserver.setContent(""" uiserver.setContent(loadHtmlFile("addHeavyAtoms.html")% table)
<html>
<head><title>PDB Fixer</title></head>
<body>
The following residues are missing heavy atoms, which will be added.
<p>
<form method="post" action="/">
<table border="1">
<tr><th>Chain</th><th>Residue</th><th>Missing Atoms</th></tr>
%s
</table>
<p>
<input type="submit" value="Continue"/>
</form>
</body>
<html>
""" % table)
def displayAddHydrogensPage(): def displayAddHydrogensPage():
uiserver.setCallback(addHydrogensPageCallback) uiserver.setCallback(addHydrogensPageCallback)
uiserver.setContent(""" uiserver.setContent(loadHtmlFile("addHydrogens.html"))
<html>
<head><title>PDB Fixer</title></head> def displaySaveFilePage():
<body> uiserver.setCallback(saveFilePageCallback)
Add missing hydrogen atoms? uiserver.setContent(loadHtmlFile("saveFile.html"))
<p>
<form method="post" action="/">
<input type="checkbox" name="add" checked> Add hydrogens appropriate for pH <input type="text" name="ph" value="7.0" size="5">
<p>
<input type="submit" value="Continue"/>
</form>
</body>
<html>
""")
def displayDownloadPage():
uiserver.setCallback(downloadPageCallback)
uiserver.setContent("""
<html>
<head><title>PDB Fixer</title></head>
<body>
The fixed PDB file is ready to download.
<p>
<form method="post" action="/">
<input type="submit" name="download" value="Download"/>
<input type="submit" name="newfile" value="Process Another File"/>
</form>
</body>
<html>
""")
def launchUI(): def launchUI():
uiserver.beginServing() uiserver.beginServing()
displayStartPage() displayStartPage()
webbrowser.open('http://'+uiserver.serverAddress) webbrowser.open('http://localhost:'+str(uiserver.server.server_address[1]))
\ No newline at end of file \ No newline at end of file
...@@ -48,7 +48,6 @@ class _ThreadingHTTPServer(ThreadingMixIn, HTTPServer): ...@@ -48,7 +48,6 @@ class _ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
content = "" content = ""
callback = None callback = None
server = _ThreadingHTTPServer(("localhost", 8000), _Handler) server = _ThreadingHTTPServer(("localhost", 8000), _Handler)
serverAddress = server.server_address[0]+':'+str(server.server_address[1])
def beginServing(): def beginServing():
Thread(target=server.serve_forever).start() Thread(target=server.serve_forever).start()
......
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