https://wiki.pymol.org/api.php?action=feedcontributions&user=Mglerner&feedformat=atomPyMOL Wiki - User contributions [en]2024-03-29T09:13:37ZUser contributionsMediaWiki 1.35.1https://wiki.pymol.org/index.php?title=Ccp4_ncont&diff=1004Ccp4 ncont2011-05-26T13:49:00Z<p>Mglerner: /* The Code */</p>
<hr />
<div>[[File:HhaExample.png|thumb|300px|right|Interface residues (at cutoff <4A) in the 2c7r.pdb were found using NCONT. Usage of ContactsNCONT script in PyMOL allows easy selection of residues and atoms listed in ncont.log file. Interacting protein and DNA residues are colored in red and slate, respectively. Atoms in contact are shown in dots.]]<br />
<br />
== Overview ==<br />
<br />
The script selects residues and atoms from the list of the contacts found by NCONT from CCP4 Program Suite (NCONT analyses contacts between subsets of atoms in a PDB file).<br />
First, we run NCONT on our pdb file to find interface residues. Then by using the ContactsNCONT script in PyMOL we separately select residues and atoms listed in a ncont.log file. This generates two selections (atoms and residues) for each interacting chain, allowing quick manipulation of (sometimes) extensive lists in NCONT log file.<br />
<br />
This script works best for intermolecular contacts (when NCONT target and source selections don't overlap). If crystal contacts (NCONT parameter cell = 1 or 2) are included then additional coding is required to distinguish inter from intramolecular contacts.<br />
<br />
== Usage ==<br />
<br />
selectContacts( contactsfile, selName1 = "source", selName2 = "target" )<br />
<br />
<br />
== Examples ==<br />
<br />
<br />
First use NCONT to find interface residues/atoms in the pdb file. Once you have ncont.log file proceed to PyMOL.<br />
Make sure you've run the ContactsNCONT script first.<br />
<br />
fetch 2c7r<br />
selectContacts ncont.log, selName1=prot, selName2=dna<br />
<br />
[[File:HhaI20example.png|thumb|300px|right|Quick and easy selection of interacting residues and atoms listed in the NCONT log file. Protein and DNA residues are colored in red and slate, respectively. Atoms in contact are shown in dots.]]<br />
<br />
== The Code ==<br />
<source lang="python"><br />
import re<br />
<br />
def parseContacts( f ):<br />
# /1/B/ 282(PHE). / CE1[ C]: /1/E/ 706(GLN). / O [ O]: 3.32<br />
# conParser = re.compile("\s*/(\d+)/([A-Z])/\s*(\d+).*?/\s*([A-Z0-9]*).*?:")<br />
conParser = re.compile("\s*/(\d+)/([A-Z]*)/\s*(\d+).*?/\s*([A-Z0-9]*).*?:") # * is needed when chain code is blank<br />
mode = 0<br />
s1 = []<br />
s2 = []<br />
pairs = []<br />
for line in f:<br />
if mode == 0:<br />
if line.strip().startswith("SOURCE ATOMS"):<br />
mode = 1<br />
elif mode == 1:<br />
mode = 2<br />
elif mode == 2:<br />
matches = conParser.findall(line)<br />
if len(matches) == 0:<br />
return (s1, s2, pairs)<br />
if len(matches) == 2:<br />
s1.append(matches[0])<br />
s2.append(matches[1])<br />
elif len(matches) == 1:<br />
s2.append(matches[0])<br />
pairs.append((len(s1)-1, len(s2)-1))<br />
else:<br />
print "Unknown mode", mode<br />
<br />
def selectContacts( contactsfile, selName1 = "source", selName2 = "target" ):<br />
"""<br />
selectContacts -- parses CCP4 NCONT log file and selects residues and atoms from the list of the contacts found.<br />
<br />
PARAMS<br />
contactsfile<br />
filename of the CCP4 NCONT contacts log file<br />
<br />
selName1<br />
the name prefix for the _res and _atom selections returned for the<br />
source set of chain<br />
<br />
selName2<br />
the name prefix for the _res and _atom selections returned for the <br />
target set of chain<br />
<br />
RETURNS<br />
* 2 selections of interface residues and atoms for each chain are created and named<br />
depending on what you passed into selName1 and selName2<br />
<br />
AUTHOR:<br />
Gerhard Reitmayr and Dalia Daujotyte, 2009. <br />
"""<br />
# read and parse contacts file into two lists of contact atoms and contact pair list<br />
s1, s2, pairs = parseContacts(open(contactsfile))<br />
# create a selection for the first contact list<br />
resName = selName1 + "_res"<br />
atomName = selName1 + "_atom"<br />
cmd.select(resName, None)<br />
cmd.select(atomName, None)<br />
for (thing, chain, residue, atom) in s1:<br />
cmd.select( resName, resName + " or " + chain+"/"+residue+"/")<br />
cmd.select( atomName, atomName + " or " + chain+"/"+residue+"/"+atom)<br />
<br />
# create a selection for the second contact list<br />
resName = selName2 + "_res"<br />
atomName = selName2 + "_atom"<br />
cmd.select(resName, None)<br />
cmd.select(atomName, None)<br />
for (thing, chain, residue, atom) in s2:<br />
cmd.select( resName, resName + " or " + chain+"/"+residue+"/")<br />
cmd.select( atomName, atomName + " or " + chain+"/"+residue+"/"+atom)<br />
<br />
cmd.extend("selectContacts", selectContacts)<br />
</source><br />
<br />
[[Category:Script_Library]] [[Category:ThirdParty Scripts]] [[Category:Structural Biology Scripts]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=FindSurfaceResidues&diff=7339FindSurfaceResidues2011-05-05T13:56:11Z<p>Mglerner: Unprotected "FindSurfaceResidues"</p>
<hr />
<div><gallery><br />
Image:FindExRes.png|thumb|right|300px|Result of $TUT/1hpv.pdb at 2.5 Ang cutoff.<br />
Image:Surface_residues_ex.png|300px|Example coloring of surface residues<br />
</gallery><br />
<br />
<br />
= Overview =<br />
This script will select (and color if requested) surface residues on an object or selection. See the options below.<br />
<br />
<br />
Each time, the script will create a new selection called, 'exposedXYZ' where XYZ is some random number. This is done so that no other selections/objects are overwritten.<br />
<br />
<br />
<br />
= Usage =<br />
<source lang="python"><br />
findSurfaceResidues [objSel=(all)[, cutoff=2.5[, doShow=False[, verbose=False ]]]]<br />
</source><br />
The parameters are:<br />
<br />
'''objSel'''<br />
:: The object or selection for which to find exposed residues;<br />
:: DEFAULT = (all)<br />
'''cutoff'''<br />
:: The cutoff in square Angstroms that defines exposed or not. Those residues with > cutoff Ang^2 exposed will be considered ''exposed'';<br />
:: DEFAULT = 2.5 Ang^2<br />
'''doShow'''<br />
:: Change the visualization to highlight the exposed residues vs interior<br />
:: DEFAULT = False/Blank<br />
'''verbose'''<br />
:: Level of verbosity.<br />
:: DEFAULT = False/Blank<br />
<br />
== Examples ==<br />
<source lang="python"><br />
# make sure you download and run the code below, before trying these examples.<br />
load $TUT/1hpv.pdb<br />
findSurfaceResidues<br />
# now show the exposed<br />
findSurface residues doShow=True<br />
<br />
# watch how the visualization changes:<br />
findSurfaceResidues doShow=True, cutoff=0.5<br />
findSurfaceResidues doShow=True, cutoff=1.0<br />
findSurfaceResidues doShow=True, cutoff=1.5<br />
findSurfaceResidues doShow=True, cutoff=2.0<br />
findSurfaceResidues doShow=True, cutoff=2.5<br />
findSurfaceResidues doShow=True, cutoff=3.0<br />
</source><br />
<br />
= The Code =<br />
<source lang="python"><br />
# -*- coding: utf-8 -*-<br />
import pymol<br />
from pymol import cmd<br />
import random<br />
<br />
def findSurfaceResidues(objSel="(all)", cutoff=2.5, doShow=False, verbose=False):<br />
"""<br />
findSurfaceResidues<br />
finds those residues on the surface of a protein<br />
that have at least 'cutoff' exposed A**2 surface area.<br />
<br />
PARAMS<br />
objSel (string)<br />
the object or selection in which to find<br />
exposed residues<br />
DEFAULT: (all)<br />
<br />
cutoff (float)<br />
your cutoff of what is exposed or not. <br />
DEFAULT: 2.5 Ang**2<br />
<br />
asSel (boolean)<br />
make a selection out of the residues found<br />
<br />
RETURNS<br />
(list: (chain, resv ) )<br />
A Python list of residue numbers corresponding<br />
to those residues w/more exposure than the cutoff.<br />
<br />
"""<br />
tmpObj="__tmp"<br />
cmd.create( tmpObj, objSel + " and polymer");<br />
if verbose!=False:<br />
print "WARNING: I'm setting dot_solvent. You may not care for this."<br />
cmd.set("dot_solvent");<br />
cmd.get_area(selection=tmpObj, load_b=1)<br />
<br />
# threshold on what one considers an "exposed" atom (in A**2):<br />
cmd.remove( tmpObj + " and b < " + str(cutoff) )<br />
<br />
stored.tmp_dict = {}<br />
cmd.iterate(tmpObj, "stored.tmp_dict[(chain,resv)]=1")<br />
exposed = stored.tmp_dict.keys()<br />
exposed.sort()<br />
<br />
selName = "exposed_" + str(random.randint(0,10000))<br />
if verbose!=False:<br />
print "Exposed residues are selected in: " + selName<br />
cmd.select(selName, objSel + " in " + tmpObj )<br />
<br />
if doShow!=False:<br />
cmd.show_as("spheres", objSel + " and poly")<br />
cmd.color("white", objSel)<br />
cmd.color("red", selName)<br />
<br />
cmd.delete(tmpObj)<br />
<br />
return exposed<br />
<br />
<br />
cmd.extend("findSurfaceResidues", findSurfaceResidues)<br />
</source><br />
<br />
[[Category:Script_Library]]<br />
[[Category:ObjSel_Scripts]]<br />
[[Category:Biochemical_Scripts]]<br />
[[Category:Structural_Biology_Scripts]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=FindSurfaceResidues&diff=7338FindSurfaceResidues2011-05-05T13:55:59Z<p>Mglerner: Protected "FindSurfaceResidues" ([edit=sysop] (indefinite) [move=sysop] (indefinite))</p>
<hr />
<div><gallery><br />
Image:FindExRes.png|thumb|right|300px|Result of $TUT/1hpv.pdb at 2.5 Ang cutoff.<br />
Image:Surface_residues_ex.png|300px|Example coloring of surface residues<br />
</gallery><br />
<br />
<br />
= Overview =<br />
This script will select (and color if requested) surface residues on an object or selection. See the options below.<br />
<br />
<br />
Each time, the script will create a new selection called, 'exposedXYZ' where XYZ is some random number. This is done so that no other selections/objects are overwritten.<br />
<br />
<br />
<br />
= Usage =<br />
<source lang="python"><br />
findSurfaceResidues [objSel=(all)[, cutoff=2.5[, doShow=False[, verbose=False ]]]]<br />
</source><br />
The parameters are:<br />
<br />
'''objSel'''<br />
:: The object or selection for which to find exposed residues;<br />
:: DEFAULT = (all)<br />
'''cutoff'''<br />
:: The cutoff in square Angstroms that defines exposed or not. Those residues with > cutoff Ang^2 exposed will be considered ''exposed'';<br />
:: DEFAULT = 2.5 Ang^2<br />
'''doShow'''<br />
:: Change the visualization to highlight the exposed residues vs interior<br />
:: DEFAULT = False/Blank<br />
'''verbose'''<br />
:: Level of verbosity.<br />
:: DEFAULT = False/Blank<br />
<br />
== Examples ==<br />
<source lang="python"><br />
# make sure you download and run the code below, before trying these examples.<br />
load $TUT/1hpv.pdb<br />
findSurfaceResidues<br />
# now show the exposed<br />
findSurface residues doShow=True<br />
<br />
# watch how the visualization changes:<br />
findSurfaceResidues doShow=True, cutoff=0.5<br />
findSurfaceResidues doShow=True, cutoff=1.0<br />
findSurfaceResidues doShow=True, cutoff=1.5<br />
findSurfaceResidues doShow=True, cutoff=2.0<br />
findSurfaceResidues doShow=True, cutoff=2.5<br />
findSurfaceResidues doShow=True, cutoff=3.0<br />
</source><br />
<br />
= The Code =<br />
<source lang="python"><br />
# -*- coding: utf-8 -*-<br />
import pymol<br />
from pymol import cmd<br />
import random<br />
<br />
def findSurfaceResidues(objSel="(all)", cutoff=2.5, doShow=False, verbose=False):<br />
"""<br />
findSurfaceResidues<br />
finds those residues on the surface of a protein<br />
that have at least 'cutoff' exposed A**2 surface area.<br />
<br />
PARAMS<br />
objSel (string)<br />
the object or selection in which to find<br />
exposed residues<br />
DEFAULT: (all)<br />
<br />
cutoff (float)<br />
your cutoff of what is exposed or not. <br />
DEFAULT: 2.5 Ang**2<br />
<br />
asSel (boolean)<br />
make a selection out of the residues found<br />
<br />
RETURNS<br />
(list: (chain, resv ) )<br />
A Python list of residue numbers corresponding<br />
to those residues w/more exposure than the cutoff.<br />
<br />
"""<br />
tmpObj="__tmp"<br />
cmd.create( tmpObj, objSel + " and polymer");<br />
if verbose!=False:<br />
print "WARNING: I'm setting dot_solvent. You may not care for this."<br />
cmd.set("dot_solvent");<br />
cmd.get_area(selection=tmpObj, load_b=1)<br />
<br />
# threshold on what one considers an "exposed" atom (in A**2):<br />
cmd.remove( tmpObj + " and b < " + str(cutoff) )<br />
<br />
stored.tmp_dict = {}<br />
cmd.iterate(tmpObj, "stored.tmp_dict[(chain,resv)]=1")<br />
exposed = stored.tmp_dict.keys()<br />
exposed.sort()<br />
<br />
selName = "exposed_" + str(random.randint(0,10000))<br />
if verbose!=False:<br />
print "Exposed residues are selected in: " + selName<br />
cmd.select(selName, objSel + " in " + tmpObj )<br />
<br />
if doShow!=False:<br />
cmd.show_as("spheres", objSel + " and poly")<br />
cmd.color("white", objSel)<br />
cmd.color("red", selName)<br />
<br />
cmd.delete(tmpObj)<br />
<br />
return exposed<br />
<br />
<br />
cmd.extend("findSurfaceResidues", findSurfaceResidues)<br />
</source><br />
<br />
[[Category:Script_Library]]<br />
[[Category:ObjSel_Scripts]]<br />
[[Category:Biochemical_Scripts]]<br />
[[Category:Structural_Biology_Scripts]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=Group&diff=6122Group2011-02-17T14:36:57Z<p>Mglerner: </p>
<hr />
<div>The [[Group]] command creates or updates a "group" object. The grouped objects are collected underneath a '''+''' sign in the object tree (see images).<br />
<br />
[[Group]] is tremendously helpful with multi-state or multi-structure sessions. Wildcards work great, for example:<br />
<source lang="python"><br />
# put all of objState into the group "ensemble".<br />
group ensemble, objState*<br />
</source><br />
<br />
<gallery><br />
Image:group_off.png|Three EF-Hand proteins loaded into PyMOL<br />
Image:group_on1.png|Applied the group command to the proteins via: "group efHand, *"<br />
Image:group_on2.png|The plus was clicked and expanded to show the hierarchy of objects.<br />
</gallery><br />
<br />
== Usage ==<br />
<source lang="python"><br />
group name, members, action<br />
</source><br />
<br />
== Examples ==<br />
<br />
=== Creating, opening and closing ===<br />
<source lang="python"><br />
group efHand, 1cll 1ggz 1sra<br />
<br />
# allow addition and removal from the group<br />
group efHand, open<br />
# disallow addition/removal from the group<br />
group efHand, close<br />
</source><br />
<br />
=== More advanced usage of groups and naming ===<br />
<br />
<source lang="python"><br />
# names with dots are treated special<br />
<br />
set group_auto_mode, 2<br />
<br />
# load the example protein<br />
<br />
load $TUT/1hpv.pdb, 1hpv.other<br />
<br />
# create the new entry called ".protein" in group 1hpv<br />
<br />
extract 1hpv.protein, 1hpv.other and polymer<br />
<br />
# create ".ligand in the 1hpv group<br />
<br />
extract 1hpv.ligand, 1hpv.other and organic<br />
<br />
# supports wildcards<br />
<br />
show sticks, *.ligand<br />
<br />
hide lines, *.protein<br />
<br />
show surface, *.protein within 6 of *.ligand<br />
<br />
show lines, byres *.protein within 4 of *.ligand<br />
<br />
set two_sided_lighting<br />
<br />
set transparency, 0.5<br />
<br />
set surface_color, white<br />
<br />
# Also, to lexicographically sort the names in the control panel:<br />
<br />
order *, yes<br />
</source><br />
== Notes ==<br />
Group objects can usually be used as arguments to commands. It can be processed as a group or as a selection, in which case all the atoms from all objects in the group will be used.<br />
<br />
<br />
== See Also ==<br />
[[ungroup]] [[order]] [[select]]<br />
<br />
[[Category:Commands|Group]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3169User:Mglerner2011-02-15T15:16:54Z<p>Mglerner: /* APBS Plugin FAQ */</p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= Check out a new pre-release version of the PyMOL-APBS plugin! =<br />
<br />
== New Features ==<br />
<br />
I've been working with Jason Vertrees on a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are several big advantages of the new version:<br />
<br />
* It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
* It allows you to call through to PDB2PQR directly.<br />
* It allows you to show the electric field lines.<br />
* It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
* It defaults to using PDB2PQR for PQR generation and APBS's psize.py for grid sizing/spacing.<br />
<br />
I've also upped the default maximum allowed memory since typical users have bigger and faster computers these days.<br />
<br />
The main reason that I'm sending this out now is to get bug reports. I think it runs everywhere, but *please* let me know if you have problems with it. Once it's shown to be stable, it'll be included in the next PyMOL release.<br />
<br />
A slightly longer list of changes is included below. <br />
<br />
== How to get it ==<br />
<br />
There are two ways to get the new plugin<br />
<br />
* If you have subversion installed, you can always get the latest version via<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
<br />
* You can download it from http://pymolapbsplugin.svn.sourceforge.net/viewvc/pymolapbsplugin/trunk/src/apbsplugin.py<br />
<br />
That should give you a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
Note that the plugin will be installed as "APBS Tools2" so that you can continue to use your old version.<br />
<br />
== Longer feature list ==<br />
<br />
* The ability to call through directly to PDB2PQR<br />
* Visualization of field lines<br />
* More modern apbs input files<br />
* Two visualization panels. It's often quite useful to look at two different electrostatic potentials at once. It's also quite useful to look at electrostatic potentials mapped onto two different surfaces at once. Multiple visualization panels makes this a snap: just set up one surface on panel 1 and another surface on panel 2.<br />
* Defaults to using PDB2PQR for PQR generation and APBS's psize.py for grid sizing/spacing.<br />
* Fixes several bugs that caused crashes on both OS X and Linux systems<br />
* Increased maximum allowed memory<br />
* Switch from os.system to subprocess for running external programs<br />
* Deals with paths on Windows properly<br />
* Gives better diagnostic information so that PyMOL/APBS developers can find bugs more easily<br />
* Lots of internal code cleanup<br />
<br />
<br />
= APBS Plugin FAQ =<br />
<br />
== Visualizing multiple maps at once ==<br />
<br />
=== Method 1: all at once ===<br />
<br />
If you're looking at, e.g., a protein-protein interface, it may be useful to map two different electrostatic potentials to two different PyMOL objects. Here's my overly-cautious recipe for doing that:<br />
<br />
#. Load up PyMOL with one of your structures.<br />
#. Fire up the plugin. Click on "Choose Externally Generated PQR File" and point it at your PQR file.<br />
#. Click on the Temp File Locations tab and change the name of the temporary DX file to something meaningful, e.g. structure1.dx<br />
#. Set grid and Run APBS as normal.<br />
#. Close the plugin.<br />
#. Type "delete all"<br />
#. Load up the second structure.<br />
#. Repeat steps 2-4, changing the name to something like structure2.dx this time.<br />
<br />
Now you have two correctly generated electrostatics potential maps (note: the reason I had you do things with one structure at a time loaded in PyMOL is so that you wouldn't have to fiddle around with the "Selection to use" section of the Main options tab). Use the load command to load up the other pqr file and the other dx map, then use the visualization panes as normal.<br />
<br />
=== Method 2: side by side (from Jason) ===<br />
<br />
I used this technique to look at two similar<br />
proteins side-by-side in PyMOL (see the 2nd image on<br />
http://www.pymolwiki.org/index.php/APBS). The trick is to (1) use<br />
grid_mode and grid_slots; and (2) rename the maps as appropriate.<br />
It's not hard, but will take a couple minutes. Here's how:<br />
<br />
1. get two proteins; use whatever you like<br />
fetch 1rx1 1rx2, async=0<br />
<br />
2. put them in the same frame of reference for grid mode<br />
align 1rx1, 1rx2<br />
<br />
3. run APBS on protein #1, 1rx1<br />
Plugin > APBS Tools2 > ...<br />
Under "selection to use" type "(polymer) and 1rx1"<br />
<br />
4. rename the map<br />
set_name pymol-generated, 1rx1_map<br />
<br />
5. run APBS on protein 2, 1rx2; remove the waters<br />
Plugin > APBS Tools2<br />
Under "selection to use" type "(polymer) and 1rx2"<br />
<br />
6. rename the map<br />
set_name pymol-generated, 1rx2_map<br />
<br />
7. Now, using APBS show the surfaces make sure you choose 1rx1_map for 1rx1 and 1rx2_map for 1rx2; click "Update" if those map names are not present.<br />
...<br />
<br />
8. turn on grid mode<br />
set grid_mode<br />
<br />
9. assign grid slots just to be sure the right maps and proteins are in the right places<br />
set grid_slot, 1, 1rx1<br />
set grid_slot, 1, 1rx1_map<br />
set grid_slot, 1, e_lvl_0_1<br />
<br />
set grid_slot, 2, 1rx2<br />
set grid_slot, 2, 1rx2_map<br />
set grid_slot, 2, e_lvl_1_1<br />
<br />
<br />
== Saving default locations ==<br />
<br />
=== Via environment variables ===<br />
<br />
Set the environment variables APBS_BINARY_DIR, APBS_WEB_DIR, APBS_PSIZE_DIR, APBS_PDB2PQR_DIR, and/or TEMP, and things should work properly as long as you're using the most recent version of the plugin.<br />
<br />
=== Via editing the plugin ===<br />
<br />
Open up the python file associated with the plugin (typically apbsplugin.py), look for the section near the top labeled "Global config variables" and change the values from None to a string.<br />
<br />
== There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. ==<br />
<br />
=== Leopard and Snow Leopard (10.5 and 10.6) ===<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
=== Tiger (10.4) ===<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D and 3D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=PyMOLWiki:About&diff=435PyMOLWiki:About2011-01-23T03:57:01Z<p>Mglerner: Undo revision 8803 by Cocktails019 (Talk)</p>
<hr />
<div>==About==<br />
<br />
Reading the [[PyMol list]] for years, we users noticed a trend: person A would ask a question, person B would answer and then two months later person C would ask the same question again, but now to get the answer everyone had to search for it. We have a growing corpus of knowledge; it's now time to organize it.<br />
<br />
This site came from acknowledging that.<br />
<br />
=== Site ===<br />
This site is <b>very</b> graciously hosted by [http://www.bitgnome.net/ BitGnome]. Any donations, kind words, thanks etc. can be forwarded there.<br />
<br />
The Wiki is a version of [http://mediawiki.org/ MediaWiki].<br />
<br />
The site was originally created by Jason Vertrees for the purpose of founding a knowledgebase for PyMOL users. The site also espouses the open-source mode: to post any code on this site, you must first have ownership be the copyright holder and then release it to the world under an Open Source Initiative-approved license.<br />
<br />
=== PyMol ===<br />
<br />
PyMol was launched over Christmas break in December 1999</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3168User:Mglerner2011-01-04T16:35:56Z<p>Mglerner: /* My open-source toolchain */</p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= Check out a new pre-release version of the PyMOL-APBS plugin! =<br />
<br />
== New Features ==<br />
<br />
I've been working with Jason Vertrees on a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are several big advantages of the new version:<br />
<br />
* It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
* It allows you to call through to PDB2PQR directly.<br />
* It allows you to show the electric field lines.<br />
* It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
* It defaults to using PDB2PQR for PQR generation and APBS's psize.py for grid sizing/spacing.<br />
<br />
I've also upped the default maximum allowed memory since typical users have bigger and faster computers these days.<br />
<br />
The main reason that I'm sending this out now is to get bug reports. I think it runs everywhere, but *please* let me know if you have problems with it. Once it's shown to be stable, it'll be included in the next PyMOL release.<br />
<br />
A slightly longer list of changes is included below. <br />
<br />
== How to get it ==<br />
<br />
There are two ways to get the new plugin<br />
<br />
* If you have subversion installed, you can always get the latest version via<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
<br />
* You can download it from http://pymolapbsplugin.svn.sourceforge.net/viewvc/pymolapbsplugin/trunk/src/apbsplugin.py<br />
<br />
That should give you a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
Note that the plugin will be installed as "APBS Tools2" so that you can continue to use your old version.<br />
<br />
== Longer feature list ==<br />
<br />
* The ability to call through directly to PDB2PQR<br />
* Visualization of field lines<br />
* More modern apbs input files<br />
* Two visualization panels. It's often quite useful to look at two different electrostatic potentials at once. It's also quite useful to look at electrostatic potentials mapped onto two different surfaces at once. Multiple visualization panels makes this a snap: just set up one surface on panel 1 and another surface on panel 2.<br />
* Defaults to using PDB2PQR for PQR generation and APBS's psize.py for grid sizing/spacing.<br />
* Fixes several bugs that caused crashes on both OS X and Linux systems<br />
* Increased maximum allowed memory<br />
* Switch from os.system to subprocess for running external programs<br />
* Deals with paths on Windows properly<br />
* Gives better diagnostic information so that PyMOL/APBS developers can find bugs more easily<br />
* Lots of internal code cleanup<br />
<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D and 3D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=Talk:APBS&diff=25Talk:APBS2010-11-05T00:43:18Z<p>Mglerner: </p>
<hr />
<div>I've added some details about where and how to download and install apbs and its dependencies. I have cross-referenced a description of how this can be done on OS X. <br />
<br />
I've put a few very tentative lines in about linux.<br />
<br />
== Well done! ==<br />
<br />
Hey, thanks for this plugin. It worked on an SMP 64-bit Linux machine with little effort. Still crashes a bit, but the effort is worth it.<br />
[[User:Inchoate|Tree]] 18:21, 21 February 2008 (CST)<br />
<br />
== Question/Crash ==<br />
<br />
I ran APBS on 2ILK. When I try to show the solv. acc. map, it computes something for a sec, then crashes taking PyMOL with it. Is this common? Any ideas on fixing it? It's probably my lack of understanding on how APBS works.<br />
[[User:Inchoate|Tree]] 07:40, 22 February 2008 (CST)<br />
<br />
For me it doesn't crash, but asks me to calculate the pqr file myself. Than it calculates the map fine.<br />
[[User:Desastre|Desastre]] 27 April 2008<br />
<br />
== Making the default paths to work? ==<br />
<br />
I saw a discussion in the Pymolbb dated April 15, 2010 [http://www.mail-archive.com/pymol-users@lists.sourceforge.net/msg07858.html] about the default paths for binaries, psize.py, and temp files not loading automatically or even saving the paths.<br />
<br />
I am wondering if anyone has solved this issue. <br />
<br />
After installing pymol through fink, none of the binaries show up. After installing pdb2pqr through fink, the apbs plugin (Apbs Tools 2) does load /sw/share/pdb2pqr/pdb2pqr.py automatically. However, after installing apbs-mpi-openmpi through fink, neither APBS binary nor APBS psize.py load. <br />
<br />
I have tried modifying apbs_tools.py (/sw/lib/pymol-py26/modules/pmg_tk/startup/apbs_tools.py) in lines 112 through 115 to:<br />
APBS_BINARY_LOCATION = '/sw/bin/apbs-mpi-openmpi'<br />
APBS_PSIZE_LOCATION = '/sw/share/apbs-mpi-openmpi/tools/manip/psize.py'<br />
APBS_PDB2PQR_LOCATION = None<br />
TEMPORARY_FILE_DIR = None<br />
<br />
My $APBS_PSIZE returns /sw/share/apbs-mpi-openmpi/tools/manip by default, as installed through fink. I use 64-bit fink, pymol 1.3, and Snow Leopard OSX.<br />
<br />
The default temporary file locations also do not work. I have also tried to make apbs plugin save these these to no avail.<br />
<br />
I hope a solution to this issue can be posted in the wiki.<br />
<br />
PS.: I have looked at the output from X11 when pymol loads, and it seems it tries to load <br />
trying /sw/bin/apbs-mpi-openmpi/psize.py<br />
trying '''/sw/share/apbs-mpi-openmpi/tools/manip/psize.py'''/psize.py<br />
trying /sw/share/pdb2pqr/psize.py<br />
<br />
and <br />
trying '''/sw/bin/apbs-mpi-openmpi'''/apbs.exe<br />
trying /sw/share/apbs-mpi-openmpi/tools/manip/psize.py/apbs.exe<br />
trying /sw/share/pdb2pqr/apbs.exe<br />
trying /sw/share/apbs/tools/manip/apbs.exe<br />
trying /sw/bin/apbs.exe<br />
<br />
Which are obviously wrong. The correct paths should be '''/sw/share/apbs-mpi-openmpi/tools/manip/psize.py''' and '''/sw/bin/apbs-mpi-openmpi'''.<br />
--[[User:Rendereason|Rendereason]] 22:40, 20 July 2010 (UTC)<br />
<br />
'''Fixed''' in the current version of the plugin, which you can download from [http://pymolwiki.org/index.php/User:Mglerner my user page]. The issue was that the plugin just didn't know about MPI-enabled versions. --[[User:Mglerner|michael]] 23:48, 22 July 2010 (UTC)<br />
<br />
==Running with APBS 1.3 not working==<br />
Well, I tried making the plugin run with APBS 1.3 and this is what I got:<br />
Running:<br />
prog=/usr/local/apbs-1.3-mac-univ/bin/apbs<br />
args=('/usr/local/apbs-1.3-mac-univ/bin/apbs', '--version')<br />
Results were:<br />
Return value: -5<br />
Output:<br />
dyld: Library not loaded: /usr/local/lib/x86_64/libgomp.1.dylib<br />
Referenced from: /usr/local/apbs-1.3-mac-univ/bin/apbs<br />
Reason: image not found<br />
Skipping /usr/local/apbs-1.3-mac-univ/bin/apbs because it appears to be broken (dyld)<br />
<br />
Just wondering if you get the same. --[[User:Rendereason|Rendereason]] 16:36, 29 October 2010 (UTC)<br />
<br />
I think I see why it's doing that. My folder structure is not right. APBS needs to update its install instructions/README. I'll try moving the folders to /sw64/bin/apbs, /sw64/share/apbs, etc.--[[User:Rendereason|Rendereason]] 16:49, 29 October 2010 (UTC)<br />
<br />
The installation guide says:<br />
"The APBS binaries do not contain dependencies on special data files, etc. and can be moved out of this directory structure without causing any problems for APBS execution." [http://www.poissonboltzmann.org/apbs/user-guide/installation-and-avil From APBS webpage.]<br />
I have tried setting the variable ${APBS_PREFIX} to /usr/local/apbs-.13-mac-univ.<br />
I've added these to my .zshrc but none of it works<br />
APBS_PREFIX=/usr/local/apbs-1.3-mac-univ/<br />
APBS_BINARY_DIR=/usr/local/apbs-1.3-mac-univ/bin/<br />
APBS_PSIZE_DIR=/usr/local/apbs-1.3-mac-univ/share/tools/manip/<br />
export APBS_PREFIX<br />
export APBS_BINARY_DIR<br />
export APBS_PSIZE_DIR<br />
None of this had any effect on the unmodified apbsplugin.py. (When parameters set to ''None'')<br />
Changing the parameters within apbsplugin.py to their desired folders gives the error above.<br />
--[[User:Rendereason|Rendereason]] 16:57, 29 October 2010 (UTC)<br />
<br />
Have you tried the pre-release version available on my page? I fixed some things recently, and this bug doesn't happen for me any more. --[[User:Mglerner|michael]] 19:40, 29 October 2010 (UTC)<br />
<br />
Yes. Those errors happen with the pre-release version you posted. It also ignores the binary I have configured it to use in /usr/local/apbs/bin/ for the fink one in /sw64/bin/. <br />
Also, I get this problem when running the plugin:<br />
GENERATING PQR FILE via PDB2PQR<br />
Erasing contents of /tmp/pymol-generated.pdb in order to generate new PDB file<br />
Erasing contents of /tmp/pymol-generated.pdb in order to clean it up<br />
TESTING<br />
DONE TESTING<br />
Appended /sw64<br />
Unexpected error encountered while trying to import pdb2pqr: (<type 'exceptions.ImportError'>, ImportError('No module named pdb2pqr.pdb2pqr',), <traceback object at 0x116714908>)<br />
In show error 2<br />
Could not generate PDB2PQR file. _generatePdb2pqrPqrFile failed.<br />
Could not generate PQR file!<br />
--[[User:Rendereason|Rendereason]] 22:48, 4 November 2010 (UTC)<br />
<br />
OK, I think I know what's causing at least some of the problems. I find email a lot easier than wiki pages for sorting all of this out. Can you send a list of the current errors you're getting along with your PyMOL version, APBS version, PDB2PQR version and operating system to me at my gmail account (mglerner)? Thanks! --[[User:Mglerner|michael]] 00:43, 5 November 2010 (UTC)</div>Mglernerhttps://wiki.pymol.org/index.php?title=APBS&diff=4150APBS2010-10-29T19:43:00Z<p>Mglerner: </p>
<hr />
<div>== Pre-release version ==<br />
<br />
There is often a more current pre-release version available on my user page. If you're experiencing bugs, please test the pre-release version to see if they've already been fixed. Thanks! --[[User:Mglerner|michael]] 19:43, 29 October 2010 (UTC)<br />
<br />
== Introduction ==<br />
[[Image:Rna_surface_apbs.png|thumb|APBS-generated electrostatic surface displayed in PyMOL]]<br />
[http://apbs.sourceforge.net APBS], the Adaptive Poisson-Boltzmann Solver, is a [http://www.oreilly.com/openbook/freedom/ freely] available macromolecular electrostatics calculation program released under the [http://www.gnu.org/copyleft/gpl.html GPL]. It is a cost-effective but uncompromised alternative to [http://trantor.bioc.columbia.edu/grasp/ GRASP], and it can be used within PyMOL. PyMOL can display the results of the calculations as an electrostatic potential molecular surface.<br />
<br />
=== APBS Plugin with New Features ===<br />
PyMol currently supports the '''APBS plugin''' written by [http://pymolwiki.org/index.php/User:Mglerner Michael Lerner]. This plugin makes it possible to run APBS from within PyMOL, and then display the results as a color-coded electrostatic surface (units <math>K_bT/e_c</math>) in the molecular display window (as with the image to the right). This wiki page has updated instructions on how to download, install and use the plugin.<br />
<br />
'''Nucleic acids may prove problematic for the apbs plugin.''' If so, use the [http://pdb2pqr.sourceforge.net/ pdb2pqr] command-line tool to create a pqr file manually, instead of using the plugin to generate it. Then direct the APBS GUI on the [http://www-personal.umich.edu/~mlerner/PyMOL/images/main.png main menu] to read the pqr file you '''externally generated.'''<br />
<br />
There is a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are several big advantages of the new version:<br />
<br />
* It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
* It allows you to call through to PDB2PQR directly.<br />
* It allows you to show the electric field lines.<br />
* It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
* It defaults to using PDB2PQR for PQR generation and APBS's psize.py for grid sizing/spacing.<br />
* It has also an increased default maximum allowed memory since typical users have bigger and faster computers these days.<br />
* It calls on the correct paths and binaries for multi-threaded APBS (apbs-mpi-openmpi).<br />
<br />
The main reason it is not included in the latest PyMOL release is to receive bug reports. Once it's shown to be stable, it'll be included in the next PyMOL release. See [http://pymolwiki.org/index.php/User:Mglerner Michael Lerner]'s page.<br />
<br />
==== How to get it ====<br />
<br />
There are two ways to get the new plugin<br />
<br />
* If you have subversion installed, you can always get the latest version via<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
''Subversion is not up to date. Download it instead from the link below.''<br />
<br />
* You can download it from http://pymolapbsplugin.svn.sourceforge.net/viewvc/pymolapbsplugin/trunk/src/apbsplugin.py<br />
<br />
That should give you a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
You may have to run PyMOL with sudo privileges.<br />
<br />
Note that the plugin will be installed as "APBS Tools2.1" so that you can continue to use your old version.<br />
<br />
Further details, as well as screen shots, are given [http://www.pymolwiki.org/index.php/MAC_Install#Install_APBS_and_friends_with_fink elsewhere in this wiki].<br />
<br />
==Required Dependencies==<br />
[http://apbs.sourceforge.net APBS] and its dependencies like [http://pdb2pqr.sourceforge.net pdb2pqr] and [http://scicomp.ucsd.edu/~mholst/codes/maloc/ maloc] are [http://www.oreilly.com/openbook/freedom/ freely] available under the [http://www.gnu.org/copyleft/gpl.html GPL]. The author of the software however [http://agave.wustl.edu/apbs/download/ asks that users register] with him to aid him in obtaining grant funding.<br />
<br />
----<br />
===Installing the Dependencies on OS X===<br />
#First, [http://agave.wustl.edu/apbs/download/ register] your use of the software. This will keep everyone happy.<br />
#Second, if you don't already have the [http://fink.sourceforge.net fink package management system], now is a good time to get it. Here is a [http://xanana.ucsc.edu/~wgscott/xtal/wiki/index.php/Quick_Start quick-start set of instructions] for getting X-windows, compilers, and fink all installed. <br />
#Once you are up and going, [http://xanana.ucsc.edu/~wgscott/xtal/wiki/index.php/How_to_Activate_the_Unstable_Branch activate the unstable branch in fink], and then issue the commands<br />
<source lang="bash"><br />
fink self-update<br />
fink install apbs<br />
</source><br />
or if you want to use the multi-processor version, issue<br />
<source lang="bash"><br />
fink self-update<br />
fink install apbs-mpi-openmpi<br />
</source><br />
Then install the X-windows based version of pymol using the command<br />
<source lang="bash"><br />
fink install pymol-py25<br />
</source><br />
It is recommended to install the latest pdb2pqr as well as the APBS plugin makes use of it<br />
<source lang="bash"><br />
fink install pdb2pqr<br />
</source><br />
Note that the fink version of PyMOL as of 1.3-4 does not have the latest version of the APBS plugin. Make sure you get the new version!<br />
<br />
===Installing the Dependencies on Linux===<br />
<br />
====From Scratch====<br />
Note that this tutorial assumes you're using the bash shell and have root privileges<br />
<OL><LI><br />
Obtain APBS and MALOC from...<br><br />
APBS = http://apbs.sourceforge.net (currently 0.4)<br><br />
MALOC = http://www.fetk.org/codes/maloc/index.html#download (currently 0.1-2)<BR><br />
<LI>Set up some environment variables & directories (temporary for building)<br />
<source lang="bash"><br />
$ export FETK_SRC=/<building directory>/temp_apbs<br />
$ export FETK_PREFIX=/usr/local/apbs-0.4.0 (or wherever you want it to live)<br />
$ export FETK_INCLUDE=${FETK_PREFIX}/include<br />
$ export FETK_LIBRARY=${FETK_PREFIX}/lib<br />
$ mkdir -p ${FETK_SRC} ${FETK_INCLUDE} ${FETK_LIBRARY}<br />
</source></LI><br />
<LI>Unpack the source packages<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}<br />
$ gzip -dc maloc-0.1-2.tar.gz | tar xvf -<br />
$ gzip -dc apbs-0.4.0.tar.gz | tar xvf -<br />
</source><br />
</LI><br />
<LI>Compile MALOC<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}/maloc<br />
$ ./configure --prefix=${FETK_PREFIX}</source><br />
If everything went well, then<br />
<source lang="bash"><br />
$ make; make install</source></LI><br />
<LI>Go get a coffee. Compilation/installation takes about 15 minutes on a 3GHz computer with 1GB of RAM.</LI><br />
<LI>Now on to compiling APBS itself<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}/apbs-0.4.0<br />
$ ./configure --prefix=${FETK_PREFIX}</source><br />
If all goes well:<br />
<source lang="bash"><br />
$ make all; make install</source></LI><br />
<LI>No time for coffee. Takes about 5 minutes on that fast computer.</LI><br />
<LI> There will now be an APBS binary at<br />
<source lang="bash">/usr/local/apbs-0.4.0/bin/i686-intel-linux/apbs</source></LI><br />
<LI> Make appropriate links<br />
<source lang="bash"><br />
$ ln -s /usr/local/apbs-0.4.0/bin/i686-intel-linux/apbs /usr/local/bin/apbs<br />
</source></LI><br />
<LI> Get rid of /<building directory dir>/temp_apbs<br />
<LI> Open PyMOL and make sure that the APBS plugin points to /usr/local/bin/apbs<br />
<LI> Rock and or Roll.<br />
</OL><br />
<br />
====Pre-Packaged====<br />
=====RPMs=====<br />
<br />
A variety of RPMs are available from the [http://sourceforge.net/project/showfiles.php?group_id=148472&package_id=163734&release_id=378273 APBS downloads website]. Again, please [http://agave.wustl.edu/apbs/download/ register] your use of the software if you have not yet done so.<br />
<br />
=====Debian packages=====<br />
<br />
For ubuntu and other debian linux distributions, probably the simplest thing is to download a promising looking rpm, convert it with the program [http://kitenet.net/programs/alien/ alien], and then install the [http://xanana.ucsc.edu/linux newly generated debian package] with the command<br />
<source lang="bash"><br />
sudo dpkg -i apbs*.deb<br />
</source><br />
<br />
=====Gentoo=====<br />
<br />
You have to install apbs and pdb2pqr. Both are masked via keywords atm. Type as root:<br />
<source lang="bash"><br />
echo sci-chemistry/pdb2pqr >> /etc/portage/package.keywords<br />
echo sci-chemistry/apbs >> /etc/portage/package.keywords<br />
emerge -av sci-chemistry/apbs sci-chemistry/pdb2pqr<br />
</source><br />
<br />
== Troubleshooting ==<br />
* If the B-factor is <math>\geq 100,</math> then APBS doesn't properly read in the PDB file and thus outputs garbage (or dies). To fix this, set all b factors to be less than 100. <source lang="python">alter all, b=min(b,99.9)</source> The problem stems from how to parse a PDB file. The PDB file originally was written when most people used FORTRAN programs, and so the file format was specified by columns, not by the more modern comma separated value format we tend to prefer today. For the latest on the PDB format see the [http://www.wwpdb.org/docs.html new PDB format docs].<br />
* APBS has problems, sometimes, in reading atoms with alternate conformations. You can remove the alternate locations with a simple script [[removeAlt]].<br />
* ObjectMapLoadDXFile-Error: as of this writing (9-23-2008) a known problem exists, and the Baker lab is working on it. It is typically caused by the use of directories with spaces in their names under Windows.<br />
<br />
== Problems with the bundled version of APBS ==<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
=== Leopard and Snow Leopard (10.5 and 10.6) ===<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
=== Tiger (10.4) ===<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
==Using APBS==<br />
There is a nice tutorial on the APBS homepage: [http://www.poissonboltzmann.org/apbs/examples/visualization/apbs-electrostatics-in-pymol] For further help, there is a mailing list [https://lists.sourceforge.net/lists/listinfo/apbs-users] with the corresponding archive [http://sourceforge.net/mailarchive/forum.php?forum_name=apbs-users]<br />
<br />
<br />
==Further contributions and edits are needed.==<br />
<br />
[[Category:Electrostatics]]<br />
[[Category:Biochemical_Properties]]<br />
[[Category:Plugins]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=Talk:APBS&diff=21Talk:APBS2010-10-29T19:40:44Z<p>Mglerner: </p>
<hr />
<div>I've added some details about where and how to download and install apbs and its dependencies. I have cross-referenced a description of how this can be done on OS X. <br />
<br />
I've put a few very tentative lines in about linux.<br />
<br />
== Well done! ==<br />
<br />
Hey, thanks for this plugin. It worked on an SMP 64-bit Linux machine with little effort. Still crashes a bit, but the effort is worth it.<br />
[[User:Inchoate|Tree]] 18:21, 21 February 2008 (CST)<br />
<br />
== Question/Crash ==<br />
<br />
I ran APBS on 2ILK. When I try to show the solv. acc. map, it computes something for a sec, then crashes taking PyMOL with it. Is this common? Any ideas on fixing it? It's probably my lack of understanding on how APBS works.<br />
[[User:Inchoate|Tree]] 07:40, 22 February 2008 (CST)<br />
<br />
For me it doesn't crash, but asks me to calculate the pqr file myself. Than it calculates the map fine.<br />
[[User:Desastre|Desastre]] 27 April 2008<br />
<br />
== Making the default paths to work? ==<br />
<br />
I saw a discussion in the Pymolbb dated April 15, 2010 [http://www.mail-archive.com/pymol-users@lists.sourceforge.net/msg07858.html] about the default paths for binaries, psize.py, and temp files not loading automatically or even saving the paths.<br />
<br />
I am wondering if anyone has solved this issue. <br />
<br />
After installing pymol through fink, none of the binaries show up. After installing pdb2pqr through fink, the apbs plugin (Apbs Tools 2) does load /sw/share/pdb2pqr/pdb2pqr.py automatically. However, after installing apbs-mpi-openmpi through fink, neither APBS binary nor APBS psize.py load. <br />
<br />
I have tried modifying apbs_tools.py (/sw/lib/pymol-py26/modules/pmg_tk/startup/apbs_tools.py) in lines 112 through 115 to:<br />
APBS_BINARY_LOCATION = '/sw/bin/apbs-mpi-openmpi'<br />
APBS_PSIZE_LOCATION = '/sw/share/apbs-mpi-openmpi/tools/manip/psize.py'<br />
APBS_PDB2PQR_LOCATION = None<br />
TEMPORARY_FILE_DIR = None<br />
<br />
My $APBS_PSIZE returns /sw/share/apbs-mpi-openmpi/tools/manip by default, as installed through fink. I use 64-bit fink, pymol 1.3, and Snow Leopard OSX.<br />
<br />
The default temporary file locations also do not work. I have also tried to make apbs plugin save these these to no avail.<br />
<br />
I hope a solution to this issue can be posted in the wiki.<br />
<br />
PS.: I have looked at the output from X11 when pymol loads, and it seems it tries to load <br />
trying /sw/bin/apbs-mpi-openmpi/psize.py<br />
trying '''/sw/share/apbs-mpi-openmpi/tools/manip/psize.py'''/psize.py<br />
trying /sw/share/pdb2pqr/psize.py<br />
<br />
and <br />
trying '''/sw/bin/apbs-mpi-openmpi'''/apbs.exe<br />
trying /sw/share/apbs-mpi-openmpi/tools/manip/psize.py/apbs.exe<br />
trying /sw/share/pdb2pqr/apbs.exe<br />
trying /sw/share/apbs/tools/manip/apbs.exe<br />
trying /sw/bin/apbs.exe<br />
<br />
Which are obviously wrong. The correct paths should be '''/sw/share/apbs-mpi-openmpi/tools/manip/psize.py''' and '''/sw/bin/apbs-mpi-openmpi'''.<br />
--[[User:Rendereason|Rendereason]] 22:40, 20 July 2010 (UTC)<br />
<br />
'''Fixed''' in the current version of the plugin, which you can download from [http://pymolwiki.org/index.php/User:Mglerner my user page]. The issue was that the plugin just didn't know about MPI-enabled versions. --[[User:Mglerner|michael]] 23:48, 22 July 2010 (UTC)<br />
<br />
==Running with APBS 1.3 not working==<br />
Well, I tried making the plugin run with APBS 1.3 and this is what I got:<br />
Running:<br />
prog=/usr/local/apbs-1.3-mac-univ/bin/apbs<br />
args=('/usr/local/apbs-1.3-mac-univ/bin/apbs', '--version')<br />
Results were:<br />
Return value: -5<br />
Output:<br />
dyld: Library not loaded: /usr/local/lib/x86_64/libgomp.1.dylib<br />
Referenced from: /usr/local/apbs-1.3-mac-univ/bin/apbs<br />
Reason: image not found<br />
Skipping /usr/local/apbs-1.3-mac-univ/bin/apbs because it appears to be broken (dyld)<br />
<br />
Just wondering if you get the same. --[[User:Rendereason|Rendereason]] 16:36, 29 October 2010 (UTC)<br />
<br />
I think I see why it's doing that. My folder structure is not right. APBS needs to update its install instructions/README. I'll try moving the folders to /sw64/bin/apbs, /sw64/share/apbs, etc.--[[User:Rendereason|Rendereason]] 16:49, 29 October 2010 (UTC)<br />
<br />
The installation guide says:<br />
"The APBS binaries do not contain dependencies on special data files, etc. and can be moved out of this directory structure without causing any problems for APBS execution." [http://www.poissonboltzmann.org/apbs/user-guide/installation-and-avil From APBS webpage.]<br />
I have tried setting the variable ${APBS_PREFIX} to /usr/local/apbs-.13-mac-univ.<br />
I've added these to my .zshrc but none of it works<br />
APBS_PREFIX=/usr/local/apbs-1.3-mac-univ/<br />
APBS_BINARY_DIR=/usr/local/apbs-1.3-mac-univ/bin/<br />
APBS_PSIZE_DIR=/usr/local/apbs-1.3-mac-univ/share/tools/manip/<br />
export APBS_PREFIX<br />
export APBS_BINARY_DIR<br />
export APBS_PSIZE_DIR<br />
None of this had any effect on the unmodified apbsplugin.py. (When parameters set to ''None'')<br />
Changing the parameters within apbsplugin.py to their desired folders gives the error above.<br />
--[[User:Rendereason|Rendereason]] 16:57, 29 October 2010 (UTC)<br />
<br />
Have you tried the pre-release version available on my page? I fixed some things recently, and this bug doesn't happen for me any more. --[[User:Mglerner|michael]] 19:40, 29 October 2010 (UTC)</div>Mglernerhttps://wiki.pymol.org/index.php?title=Talk:APBS&diff=12Talk:APBS2010-07-22T23:48:58Z<p>Mglerner: /* Making the default paths to work? */</p>
<hr />
<div>I've added some details about where and how to download and install apbs and its dependencies. I have cross-referenced a description of how this can be done on OS X. <br />
<br />
I've put a few very tentative lines in about linux.<br />
<br />
== Well done! ==<br />
<br />
Hey, thanks for this plugin. It worked on an SMP 64-bit Linux machine with little effort. Still crashes a bit, but the effort is worth it.<br />
[[User:Inchoate|Tree]] 18:21, 21 February 2008 (CST)<br />
<br />
== Question/Crash ==<br />
<br />
I ran APBS on 2ILK. When I try to show the solv. acc. map, it computes something for a sec, then crashes taking PyMOL with it. Is this common? Any ideas on fixing it? It's probably my lack of understanding on how APBS works.<br />
[[User:Inchoate|Tree]] 07:40, 22 February 2008 (CST)<br />
<br />
For me it doesn't crash, but asks me to calculate the pqr file myself. Than it calculates the map fine.<br />
[[User:Desastre|Desastre]] 27 April 2008<br />
<br />
== Making the default paths to work? ==<br />
<br />
I saw a discussion in the Pymolbb dated April 15, 2010 [http://www.mail-archive.com/pymol-users@lists.sourceforge.net/msg07858.html] about the default paths for binaries, psize.py, and temp files not loading automatically or even saving the paths.<br />
<br />
I am wondering if anyone has solved this issue. <br />
<br />
After installing pymol through fink, none of the binaries show up. After installing pdb2pqr through fink, the apbs plugin (Apbs Tools 2) does load /sw/share/pdb2pqr/pdb2pqr.py automatically. However, after installing apbs-mpi-openmpi through fink, neither APBS binary nor APBS psize.py load. <br />
<br />
I have tried modifying apbs_tools.py (/sw/lib/pymol-py26/modules/pmg_tk/startup/apbs_tools.py) in lines 112 through 115 to:<br />
APBS_BINARY_LOCATION = '/sw/bin/apbs-mpi-openmpi'<br />
APBS_PSIZE_LOCATION = '/sw/share/apbs-mpi-openmpi/tools/manip/psize.py'<br />
APBS_PDB2PQR_LOCATION = None<br />
TEMPORARY_FILE_DIR = None<br />
<br />
My $APBS_PSIZE returns /sw/share/apbs-mpi-openmpi/tools/manip by default, as installed through fink. I use 64-bit fink, pymol 1.3, and Snow Leopard OSX.<br />
<br />
The default temporary file locations also do not work. I have also tried to make apbs plugin save these these to no avail.<br />
<br />
I hope a solution to this issue can be posted in the wiki.<br />
<br />
PS.: I have looked at the output from X11 when pymol loads, and it seems it tries to load <br />
trying /sw/bin/apbs-mpi-openmpi/psize.py<br />
trying '''/sw/share/apbs-mpi-openmpi/tools/manip/psize.py'''/psize.py<br />
trying /sw/share/pdb2pqr/psize.py<br />
<br />
and <br />
trying '''/sw/bin/apbs-mpi-openmpi'''/apbs.exe<br />
trying /sw/share/apbs-mpi-openmpi/tools/manip/psize.py/apbs.exe<br />
trying /sw/share/pdb2pqr/apbs.exe<br />
trying /sw/share/apbs/tools/manip/apbs.exe<br />
trying /sw/bin/apbs.exe<br />
<br />
Which are obviously wrong. The correct paths should be '''/sw/share/apbs-mpi-openmpi/tools/manip/psize.py''' and '''/sw/bin/apbs-mpi-openmpi'''.<br />
--[[User:Rendereason|Rendereason]] 22:40, 20 July 2010 (UTC)<br />
<br />
'''Fixed''' in the current version of the plugin, which you can download from [http://pymolwiki.org/index.php/User:Mglerner my user page]. The issue was that the plugin just didn't know about MPI-enabled versions. --[[User:Mglerner|michael]] 23:48, 22 July 2010 (UTC)</div>Mglernerhttps://wiki.pymol.org/index.php?title=User_talk:Mglerner&diff=10747User talk:Mglerner2010-06-16T18:27:08Z<p>Mglerner: </p>
<hr />
<div>Michael,<br />
<br />
Check out [[Fetch_Path]] for a cool setting. I don't use [[load]] much now b/c of this.<br />
<br />
[[User:Inchoate|Tree]] 15:54, 1 December 2009 (UTC)<br />
: cool!--[[User:Mglerner|-michael]] 16:20, 1 December 2009 (UTC)<br />
<br />
Problem with Tools2<br />
<br />
Hi Mike,<br />
<br />
Trying your new APBS tools2 plugin. First I noticed that the isopotential surface it creates with the same PDB and PQR is different to that produced from APBS original version. Second, when I tried to raytrace a usual scene with a protein cartoon with two isopotential surfaces, it processed for 20% and then crashed, complaining about a python error. The original APBS tools does not crash. I am using Pymol 1.2r3 for windows (vista). Anyway thanks for making such a nice tools.<br />
<br />
Wai<br />
<br />
Hi Wai,<br />
<br />
Can you give me an example PDB/PQR file to reproduce the discrepancies you're seeing with isopotential surfaces?</div>Mglernerhttps://wiki.pymol.org/index.php?title=PluginArchitecture&diff=7184PluginArchitecture2010-04-09T18:16:28Z<p>Mglerner: /* More than one file per plugin */</p>
<hr />
<div>This page concerns the development for new PyMOL Plugin Architecture. We are requesting ideas, code, etc on how to best implement a successful plug in system.<br />
<br />
= Review of Current Plugin System =<br />
<br />
= Ideas/Features for the New Plugin System =<br />
<br />
== More than one file per plugin ==<br />
<br />
I'd like plugins that behave like proper Python modules with the ability to span multiple files/directories. One simple way to do this would be to distribute plugins as zip files. E.g. if we have a directory Foo that contains<br />
<br />
<source lang="Python"><br />
MyMod<br />
__init__.py<br />
"""Some documentation here"""<br />
Foo.py<br />
def doit():<br />
print "It is done!"<br />
</source><br />
<br />
We can zip it up like<br />
<br />
<source lang="bash"><br />
zip MyMod.zip Foo/*<br />
</source><br />
<br />
If you stick MyMod.zip in a plugins directory like /blahblah/Pymol/plugins/MyMod.zip<br />
you can then say this:<br />
<br />
<source lang="Python"><br />
sys.path.append('/blahblah/Pymol/plugins/MyMod.zip')<br />
from MyMod import Foo<br />
Foo.doit()<br />
</source><br />
<br />
Python does not impose the restriction that the module/directory name (MyMod) should be the same as the zip file name (MyMod.zip), but we might want to.<br />
<br />
Then we need to formally spell out the API by which the Plugin is launched.<br />
<br />
This makes it very easy to install/uninstall plugins, and PyMOL can just have a simple loop that iterates over the plugins directory, adds the appropriate things to sys.path, verifies that the resulting objects support the API, and adds them to the menu.<br />
<br />
== Config files ==<br />
<br />
Some sort of persistent config files where users can store things like paths to relevant files, settings, etc. would be very useful. The APBS plugin, for instance, is a bit of a bother to use when you have APBS installed in a non-standard location. It would be very convenient if you could set the location once and have it persist.<br />
<br />
= Liked Plugin Systems =<br />
* [https://addons.mozilla.org/en-US/developers FireFox Devel/Docs]<br />
* Google Chrome -- URL?<br />
<br />
= Disliked Plugin Systems =<br />
<br />
<br />
= The Name =<br />
* Plugins, Plug-Ins?<br />
* Add-ons?<br />
* Extensions?<br />
<br />
<br />
[[Category:Development]]<br />
[[Category:Developers]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=PluginArchitecture&diff=7183PluginArchitecture2010-04-09T18:08:46Z<p>Mglerner: /* Ideas/Features for the New Plugin System */</p>
<hr />
<div>This page concerns the development for new PyMOL Plugin Architecture. We are requesting ideas, code, etc on how to best implement a successful plug in system.<br />
<br />
= Review of Current Plugin System =<br />
<br />
= Ideas/Features for the New Plugin System =<br />
<br />
== More than one file per plugin ==<br />
<br />
I'd like plugins that behave like proper Python modules with the ability to span multiple files/directories. One simple way to do this would be to distribute plugins as zip files. E.g. if we have a directory Foo that contains<br />
<br />
<source lang="Python"><br />
MyMod<br />
__init__.py<br />
"""Some documentation here"""<br />
Foo.py<br />
def doit():<br />
print "It is done!"<br />
</source><br />
<br />
We can zip it up like<br />
<br />
<source lang="bash"<br />
zip MyMod.zip Foo/*<br />
</source><br />
<br />
If you stick MyMod.zip in a plugins directory like /blahblah/Pymol/plugins/MyMod.zip<br />
you can then say this:<br />
<br />
<source lang="Python"><br />
sys.path.append('/blahblah/Pymol/plugins/MyMod.zip')<br />
from MyMod import Foo<br />
Foo.doit()<br />
</source><br />
<br />
Python does not impose the restriction that the module/directory name (MyMod) should be the same as the zip file name (MyMod.zip), but we might want to.<br />
<br />
Then we need to formally spell out the API by which the Plugin is launched.<br />
<br />
This makes it very easy to install/uninstall plugins, and PyMOL can just have a simple loop that iterates over the plugins directory, adds the appropriate things to sys.path, verifies that the resulting objects support the API, and adds them to the menu.<br />
<br />
== Config files ==<br />
<br />
Some sort of persistent config files where users can store things like paths to relevant files, settings, etc. would be very useful. The APBS plugin, for instance, is a bit of a bother to use when you have APBS installed in a non-standard location. It would be very convenient if you could set the location once and have it persist.<br />
<br />
= Liked Plugin Systems =<br />
* [https://addons.mozilla.org/en-US/developers FireFox Devel/Docs]<br />
* Google Chrome -- URL?<br />
<br />
= Disliked Plugin Systems =<br />
<br />
<br />
= The Name =<br />
* Plugins, Plug-Ins?<br />
* Add-ons?<br />
* Extensions?<br />
<br />
<br />
[[Category:Development]]<br />
[[Category:Developers]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3167User:Mglerner2010-03-01T22:01:59Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= Check out a new pre-release version of the PyMOL-APBS plugin! =<br />
<br />
== New Features ==<br />
<br />
I've been working with Jason Vertrees on a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are several big advantages of the new version:<br />
<br />
* It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
* It allows you to call through to PDB2PQR directly.<br />
* It allows you to show the electric field lines.<br />
* It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
* It defaults to using PDB2PQR for PQR generation and APBS's psize.py for grid sizing/spacing.<br />
<br />
I've also upped the default maximum allowed memory since typical users have bigger and faster computers these days.<br />
<br />
The main reason that I'm sending this out now is to get bug reports. I think it runs everywhere, but *please* let me know if you have problems with it. Once it's shown to be stable, it'll be included in the next PyMOL release.<br />
<br />
A slightly longer list of changes is included below. <br />
<br />
== How to get it ==<br />
<br />
There are two ways to get the new plugin<br />
<br />
* If you have subversion installed, you can always get the latest version via<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
<br />
* You can download it from http://pymolapbsplugin.svn.sourceforge.net/viewvc/pymolapbsplugin/trunk/src/apbsplugin.py<br />
<br />
That should give you a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
Note that the plugin will be installed as "APBS Tools2" so that you can continue to use your old version.<br />
<br />
== Longer feature list ==<br />
<br />
* The ability to call through directly to PDB2PQR<br />
* Visualization of field lines<br />
* More modern apbs input files<br />
* Two visualization panels. It's often quite useful to look at two different electrostatic potentials at once. It's also quite useful to look at electrostatic potentials mapped onto two different surfaces at once. Multiple visualization panels makes this a snap: just set up one surface on panel 1 and another surface on panel 2.<br />
* Defaults to using PDB2PQR for PQR generation and APBS's psize.py for grid sizing/spacing.<br />
* Fixes several bugs that caused crashes on both OS X and Linux systems<br />
* Increased maximum allowed memory<br />
* Switch from os.system to subprocess for running external programs<br />
* Deals with paths on Windows properly<br />
* Gives better diagnostic information so that PyMOL/APBS developers can find bugs more easily<br />
* Lots of internal code cleanup<br />
<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3166User:Mglerner2010-03-01T21:52:59Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= Check out a new pre-release version of the PyMOL-APBS plugin! =<br />
<br />
== New Features ==<br />
<br />
I've been working with Jason Vertrees on a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are three big advantages of the new version:<br />
<br />
* It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
* It allows you to call through to PDB2PQR directly.<br />
* It allows you to show the electric field lines.<br />
* It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
* It defaults to using PDB2PQR for PQR generation and APBS's psize.py for grid sizing/spacing.<br />
<br />
I've also upped the default maximum allowed memory since typical users have bigger and faster computers these days.<br />
<br />
The main reason that I'm sending this out now is to get bug reports. I think it runs everywhere, but *please* let me know if you have problems with it. Once it's shown to be stable, it'll be included in the next PyMOL release.<br />
<br />
A slightly longer list of changes is included below. <br />
<br />
== How to get it ==<br />
<br />
There are two ways to get the new plugin<br />
<br />
* If you have subversion installed, you can always get the latest version via<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
<br />
* You can download it from http://pymolapbsplugin.svn.sourceforge.net/viewvc/pymolapbsplugin/trunk/src/apbsplugin.py<br />
<br />
That should give you a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
Note that the plugin will be installed as "APBS Tools2" so that you can continue to use your old version.<br />
<br />
== Longer feature list ==<br />
<br />
* The ability to call through directly to PDB2PQR<br />
* Visualization of field lines<br />
* More modern apbs input files<br />
* Two visualization panels. It's often quite useful to look at two different electrostatic potentials at once. It's also quite useful to look at electrostatic potentials mapped onto two different surfaces at once. Multiple visualization panels makes this a snap: just set up one surface on panel 1 and another surface on panel 2.<br />
* Defaults to using PDB2PQR for PQR generation and APBS's psize.py for grid sizing/spacing.<br />
* Fixes several bugs that caused crashes on both OS X and Linux systems<br />
* Increased maximum allowed memory<br />
* Switch from os.system to subprocess for running external programs<br />
* Deals with paths on Windows properly<br />
* Gives better diagnostic information so that PyMOL/APBS developers can find bugs more easily<br />
* Lots of internal code cleanup<br />
<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=APBS&diff=4144APBS2010-01-29T03:04:53Z<p>Mglerner: </p>
<hr />
<div>== Pre-release version ==<br />
<br />
There's a pre-release version available on my user page. Please test it out and let me know if it works for you: --[[User:Mglerner|michael]] 03:04, 29 January 2010 (UTC)<br />
<br />
== Introduction ==<br />
[[Image:Rna_surface_apbs.png|thumb|APBS-generated electrostatic surface displayed in PyMOL]]<br />
[http://apbs.sourceforge.net APBS], the Adaptive Poisson-Boltzmann Solver, is a [http://www.oreilly.com/openbook/freedom/ freely] available macromolecular electrostatics calculation program released under the [http://www.gnu.org/copyleft/gpl.html GPL]. It is a cost-effective but uncompromised alternative to [http://trantor.bioc.columbia.edu/grasp/ GRASP], and it can be used within pymol. Pymol can display the results of the calculations as an electrostatic potential molecular surface.<br />
<br />
PyMol currently supports the '''APBS plugin''' written by Michael Lerner. This plugin makes it possible to run APBS from within PyMOL, and then display the results as a color-coded electrostatic surface (units <math>K_bT/e_c</math>) in the molecular display window (as with the image to the right). See [http://apbs.wustl.edu/MediaWiki/index.php/APBS_electrostatics_in_PyMOL the APBS wiki] for more details, including instructions on how to download, install and use the plugin.<br />
<br />
'''Nucleic acids may prove problematic for the apbs plugin.''' If so, use the [http://pdb2pqr.sourceforge.net/ pdb2pqr] command-line tool to create a pqr file manually, instead of using the plugin to generate it. Then direct the APBS GUI on the [http://www-personal.umich.edu/~mlerner/PyMOL/images/main.png main menu] to read the pqr file you '''externally generated.'''<br />
<br />
==Required Dependencies==<br />
[http://apbs.sourceforge.net APBS] and its dependencies like [http://pdb2pqr.sourceforge.net pdb2pqr] and [http://scicomp.ucsd.edu/~mholst/codes/maloc/ maloc] are [http://www.oreilly.com/openbook/freedom/ freely] available under the [http://www.gnu.org/copyleft/gpl.html GPL]. The author of the software however [http://agave.wustl.edu/apbs/download/ asks that users register] with him to aid him in obtaining grant funding.<br />
<br />
----<br />
===Installing the Dependencies on OS X===<br />
#First, [http://agave.wustl.edu/apbs/download/ register] your use of the software. This will keep everyone happy.<br />
#Second, if you don't already have the [http://fink.sourceforge.net fink package management system], now is a good time to get it. Here is a [http://xanana.ucsc.edu/~wgscott/xtal/wiki/index.php/Quick_Start quick-start set of instructions] for getting X-windows, compilers, and fink all installed. <br />
#Once you are up and going, [http://xanana.ucsc.edu/~wgscott/xtal/wiki/index.php/How_to_Activate_the_Unstable_Branch activate the unstable branch in fink], and then issue the commands<br />
<source lang="bash"><br />
fink self-update<br />
fink install apbs<br />
</source><br />
or if you want to use the multi-processor version, issue<br />
<source lang="bash"><br />
fink self-update<br />
fink install apbs-mpi-openmpi<br />
</source><br />
Then install the X-windows based version of pymol using the command<br />
<source lang="bash"><br />
fink install pymol-py25<br />
</source><br />
Note that the fink version of pymol '''already has''' the latest version of the APBS plugin. You are set to go!<br />
<br />
Further details, as well as screen shots, are given [http://www.pymolwiki.org/index.php/MAC_Install#Install_APBS_and_friends_with_fink elsewhere in this wiki].<br />
<br />
===Installing the Dependencies on Linux===<br />
<br />
====From Scratch====<br />
Note that this tutorial assumes you're using the bash shell and have root privileges<br />
<OL><LI><br />
Obtain APBS and MALOC from...<br><br />
APBS = http://apbs.sourceforge.net (currently 0.4)<br><br />
MALOC = http://www.fetk.org/codes/maloc/index.html#download (currently 0.1-2)<BR><br />
<LI>Set up some environment variables & directories (temporary for building)<br />
<source lang="bash"><br />
$ export FETK_SRC=/<building directory>/temp_apbs<br />
$ export FETK_PREFIX=/usr/local/apbs-0.4.0 (or wherever you want it to live)<br />
$ export FETK_INCLUDE=${FETK_PREFIX}/include<br />
$ export FETK_LIBRARY=${FETK_PREFIX}/lib<br />
$ mkdir -p ${FETK_SRC} ${FETK_INCLUDE} ${FETK_LIBRARY}<br />
</source></LI><br />
<LI>Unpack the source packages<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}<br />
$ gzip -dc maloc-0.1-2.tar.gz | tar xvf -<br />
$ gzip -dc apbs-0.4.0.tar.gz | tar xvf -<br />
</source><br />
</LI><br />
<LI>Compile MALOC<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}/maloc<br />
$ ./configure --prefix=${FETK_PREFIX}</source><br />
If everything went well, then<br />
<source lang="bash"><br />
$ make; make install</source></LI><br />
<LI>Go get a coffee. Compilation/installation takes about 15 minutes on a 3GHz computer with 1GB of RAM.</LI><br />
<LI>Now on to compiling APBS itself<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}/apbs-0.4.0<br />
$ ./configure --prefix=${FETK_PREFIX}</source><br />
If all goes well:<br />
<source lang="bash"><br />
$ make all; make install</source></LI><br />
<LI>No time for coffee. Takes about 5 minutes on that fast computer.</LI><br />
<LI> There will now be an APBS binary at<br />
<source lang="bash">/usr/local/apbs-0.4.0/bin/i686-intel-linux/apbs</source></LI><br />
<LI> Make appropriate links<br />
<source lang="bash"><br />
$ ln -s /usr/local/apbs-0.4.0/bin/i686-intel-linux/apbs /usr/local/bin/apbs<br />
</source></LI><br />
<LI> Get rid of /<building directory dir>/temp_apbs<br />
<LI> Open PyMOL and make sure that the APBS plugin points to /usr/local/bin/apbs<br />
<LI> Rock and or Roll.<br />
</OL><br />
<br />
====Pre-Packaged====<br />
=====RPMs=====<br />
<br />
A variety of RPMs are available from the [http://sourceforge.net/project/showfiles.php?group_id=148472&package_id=163734&release_id=378273 APBS downloads website]. Again, please [http://agave.wustl.edu/apbs/download/ register] your use of the software if you have not yet done so.<br />
<br />
=====Debian packages=====<br />
<br />
For ubuntu and other debian linux distributions, probably the simplest thing is to download a promising looking rpm, convert it with the program [http://kitenet.net/programs/alien/ alien], and then install the [http://xanana.ucsc.edu/linux newly generated debian package] with the command<br />
<source lang="bash"><br />
sudo dpkg -i apbs*.deb<br />
</source><br />
<br />
=====Gentoo=====<br />
<br />
You have to install apbs and pdb2pqr. Both are masked via keywords atm. Type as root:<br />
<source lang="bash"><br />
echo sci-chemistry/pdb2pqr >> /etc/portage/package.keywords<br />
echo sci-chemistry/apbs >> /etc/portage/package.keywords<br />
emerge -av sci-chemistry/apbs sci-chemistry/pdb2pqr<br />
</source><br />
<br />
== Troubleshooting ==<br />
* If the B-factor is <math>\geq 100,</math> then APBS doesn't properly read in the PDB file and thus outputs garbage (or dies). To fix this, set all b factors to be less than 100. <source lang="python">alter all, b=min(b,99.9)</source> The problem stems from how to parse a PDB file. The PDB file originally was written when most people used FORTRAN programs, and so the file format was specified by columns, not by the more modern comma separated value format we tend to prefer today. For the latest on the PDB format see the [http://www.wwpdb.org/docs.html new PDB format docs].<br />
* APBS has problems, sometimes, in reading atoms with alternate conformations. You can remove the alternate locations with a simple script [[removeAlt]].<br />
* ObjectMapLoadDXFile-Error: as of this writing (9-23-2008) a known problem exists, and the Baker lab is working on it. It is typically caused by the use of directories with spaces in their names under Windows.<br />
<br />
== Problems with the bundled version of APBS ==<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
=== Leopard and Snow Leopard (10.5 and 10.6) ===<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
=== Tiger (10.4) ===<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
<br />
==Further contributions and edits are needed.==<br />
<br />
[[Category:Electrostatics]]<br />
[[Category:Biochemical_Properties]]<br />
[[Category:Plugins]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3165User:Mglerner2010-01-28T20:36:39Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= Check out a new pre-release version of the PyMOL-APBS plugin! =<br />
<br />
== New Features ==<br />
<br />
I've been working with Jason Vertrees on a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are three big advantages of the new version:<br />
<br />
* It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
* It allows you to call through to PDB2PQR directly.<br />
* It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
<br />
I've also upped the default maximum allowed memory since typical users have bigger and faster computers these days.<br />
<br />
The main reason that I'm sending this out now is to get bug reports. I think it runs everywhere, but *please* let me know if you have problems with it. Once it's shown to be stable, it'll be included in the next PyMOL release.<br />
<br />
A slightly longer list of changes is included below. <br />
<br />
== How to get it ==<br />
<br />
There are two ways to get the new plugin<br />
<br />
* If you have subversion installed, you can always get the latest version via<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
<br />
* You can download it from http://pymolapbsplugin.svn.sourceforge.net/viewvc/pymolapbsplugin/trunk/src/apbsplugin.py<br />
<br />
That should give you a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
Note that the plugin will be installed as "APBS Tools2" so that you can continue to use your old version.<br />
<br />
== Longer feature list ==<br />
<br />
* The ability to call through directly to PDB2PQR<br />
* More modern apbs input files<br />
* Two visualization panels. It's often quite useful to look at two different electrostatic potentials at once. It's also quite useful to look at electrostatic potentials mapped onto two different surfaces at once. Multiple visualization panels makes this a snap: just set up one surface on panel 1 and another surface on panel 2.<br />
* Fixes several bugs that caused crashes on both OS X and Linux systems<br />
* Increased maximum allowed memory<br />
* Switch from os.system to subprocess for running external programs<br />
* Deals with paths on Windows properly<br />
* Gives better diagnostic information so that PyMOL/APBS developers can find bugs more easily<br />
* Lots of internal code cleanup<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3164User:Mglerner2010-01-28T20:29:11Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= Check out a new pre-release version of the PyMOL-APBS plugin! =<br />
<br />
== New Features ==<br />
<br />
I've been working with Jason Vertrees on a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are three big advantages of the new version:<br />
<br />
* It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
* It allows you to call through to PDB2PQR directly.<br />
* It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
<br />
I've also upped the default maximum allowed memory since typical users have bigger and faster computers these days.<br />
<br />
The main reason that I'm sending this out now is to get bug reports. I think it runs everywhere, but *please* let me know if you have problems with it. Once it's shown to be stable, it'll be included in the next PyMOL release.<br />
<br />
A slightly longer list of changes is included below. <br />
<br />
== How to get it ==<br />
<br />
There are two ways to get the new plugin<br />
<br />
* If you have subversion installed, you can always get the latest version via<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
<br />
* You can download the it from http://pymolapbsplugin.svn.sourceforge.net/viewvc/pymolapbsplugin/trunk/src/apbsplugin.py<br />
<br />
That should give you a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
Note that the plugin will be installed as "APBS Tools2" so that you can continue to use your old version.<br />
<br />
== Longer feature list ==<br />
<br />
* The ability to call through directly to PDB2PQR<br />
* More modern apbs input files<br />
* Two visualization panels. It's often quite useful to look at two different electrostatic potentials at once. It's also quite useful to look at electrostatic potentials mapped onto two different surfaces at once. Multiple visualization panels makes this a snap: just set up one surface on panel 1 and another surface on panel 2.<br />
* Fixes several bugs that caused crashes on both OS X and Linux systems<br />
* Increased maximum allowed memory<br />
* Switch from os.system to subprocess for running external programs<br />
* Deals with paths on Windows properly<br />
* Gives better diagnostic information so that PyMOL/APBS developers can find bugs more easily<br />
* Lots of internal code cleanup<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3163User:Mglerner2010-01-28T20:23:43Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= Check out a new pre-release version of the PyMOL-APBS plugin! =<br />
<br />
== New Features ==<br />
<br />
I've been working with Jason Vertrees on a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are three big advantages of the new version:<br />
<br />
* It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
* It allows you to call through to PDB2PQR directly.<br />
* It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
<br />
I've also upped the default maximum allowed memory since typical users have bigger and faster computers these days.<br />
<br />
A slightly longer list of changes is included below. <br />
<br />
== How to get it ==<br />
<br />
There are two ways to get the new plugin<br />
<br />
* If you have subversion installed, you can always get the latest version via<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
<br />
* You can download the zip file from http://pymolwiki.org/index.php/User:Mglerner . Upon unzipping it, you should have a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
Note that the plugin will be installed as "APBS Tools2" so that you can continue to use your old version.<br />
<br />
== Longer feature list ==<br />
<br />
* The ability to call through directly to PDB2PQR<br />
* More modern apbs input files<br />
* Two visualization panels. It's often quite useful to look at two different electrostatic potentials at once. It's also quite useful to look at electrostatic potentials mapped onto two different surfaces at once. Multiple visualization panels makes this a snap: just set up one surface on panel 1 and another surface on panel 2.<br />
* Fixes several bugs that caused crashes on both OS X and Linux systems<br />
* Increased maximum allowed memory<br />
* Switch from os.system to subprocess for running external programs<br />
* Deals with paths on Windows properly<br />
* Gives better diagnostic information so that PyMOL/APBS developers can find bugs more easily<br />
* Lots of internal code cleanup<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3162User:Mglerner2010-01-28T20:14:55Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= Check out a new pre-release version of the PyMOL-APBS plugin! =<br />
<br />
== New Features ==<br />
<br />
I've been working with Jason Vertrees on a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are three big advantages of the new version:<br />
<br />
* It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
* It allows you to call through to PDB2PQR directly.<br />
* It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
<br />
I've also upped the default maximum allowed memory since typical users have bigger and faster computers these days.<br />
<br />
A slightly longer list of changes is included below. <br />
<br />
== How to get it ==<br />
<br />
There are two ways to get the new plugin<br />
<br />
* If you have subversion installed,<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
<br />
* Copy the text directly from http://pymolwiki.org/index.php/User:Mglerner and put it in a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
Note that the plugin will be installed as "APBS Tools2" so that you can continue to use your old version.<br />
<br />
== Longer feature list ==<br />
<br />
* The ability to call through directly to PDB2PQR<br />
* More modern apbs input files<br />
* Two visualization panels. It's often quite useful to look at two different electrostatic potentials at once. It's also quite useful to look at electrostatic potentials mapped onto two different surfaces at once. Multiple visualization panels makes this a snap: just set up one surface on panel 1 and another surface on panel 2.<br />
* Fixes several bugs that caused crashes on both OS X and Linux systems<br />
* Increased maximum allowed memory<br />
* Switch from os.system to subprocess for running external programs<br />
* Deals with paths on Windows properly<br />
* Gives better diagnostic information so that PyMOL/APBS developers can find bugs more easily<br />
* Lots of internal code cleanup<br />
<br />
== Plugin code ==<br />
<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
<br />
# TODO:<br />
# - provide diff for pdb2pqr freemol<br />
# - use remove_alt to count alternate atom locations and warn the user<br />
#<br />
# - Note to users that they should remove freemol's pymol.exe on OS X.<br />
<br />
### (all) and resn glu and resi 154+157<br />
### flag ignore, atom-selection, clear<br />
<br />
# APBS TOOLS Copyright Notice<br />
# ============================<br />
#<br />
# The APBS TOOLS source code is copyrighted, but you can freely use and<br />
# copy it as long as you don't change or remove any of the copyright<br />
# notices.<br />
#<br />
# ----------------------------------------------------------------------<br />
# APBS TOOLS is Copyright (C) 2009 by Michael G. Lerner<br />
#<br />
# All Rights Reserved<br />
#<br />
# Permission to use, copy, modify, distribute, and distribute modified<br />
# versions of this software and its documentation for any purpose and<br />
# without fee is hereby granted, provided that the above copyright<br />
# notice appear in all copies and that both the copyright notice and<br />
# this permission notice appear in supporting documentation, and that<br />
# the name of Michael G. Lerner not be used in advertising or publicity<br />
# pertaining to distribution of the software without specific, written<br />
# prior permission.<br />
#<br />
# MICHAEL G. LERNER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS<br />
# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND<br />
# FITNESS. IN NO EVENT SHALL MICHAEL G. LERNER BE LIABLE FOR ANY<br />
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER<br />
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF<br />
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN<br />
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.<br />
# ----------------------------------------------------------------------<br />
<br />
"""<br />
<br />
A NOTE TO USERS:<br />
<br />
You can change the default locations for the APBS and PDB2PQR binaries<br />
as well as the default temporary file directory below. If you set them<br />
in this file, they will be preserved each time you load up the<br />
plugin. Scroll down to the section entitled "Global config variables"<br />
(no quotes) below.<br />
<br />
A NOTE TO OTHER DEVELOPERS:<br />
<br />
I understand that I'm giving this code away for Free, and that there's<br />
not a ton of great sample PyMOL plugin code out there, so you're<br />
certainly encouraged to use this as a template. However, please<br />
acknowledge me in some way if you do (somewhere in the comments if you<br />
only use a little bit of code or something more if you use a lot).<br />
<br />
Thanks.<br />
<br />
-Michael<br />
<br />
Features under consideration:<br />
<br />
- Use 'acc' to calculate solvent-accessible surface areas. We'll use<br />
the PyMOL 'standard' method and store this data as B-factors.<br />
- Show the field lines. Relevant code from menu.py:<br />
<br />
def map_gradient(self_cmd, sele):<br />
return [[ 2, 'Gradient:', '' ],<br />
[ 1, 'default' , 'cmd.gradient("'+sele+'_grad","'+sele+'");cmd.ramp_new("'+sele+<br />
'_grad_ramp","'+sele+'");cmd.color("'+sele+'_grad_ramp","'+sele+'_grad");' ]<br />
]<br />
<br />
Known hacks:<br />
<br />
<br />
1. (code in execute() )There's a bug in the version of APBS shipped<br />
with Ubuntu 9.10 (version 1.1.0) that causes the name to become<br />
foo-PE0.dx instead of foo.dx. This would normally only occur in<br />
mg-para calcs or MPI versions of apbs. It's clearly bug-possible,<br />
but we will check for foo-PE0 if we can't find foo.dx.<br />
<br />
2. We look for dylib errors in the APBS executable that's shipped with<br />
freemol on OS X. Code in get_default()'s verify().<br />
<br />
"""<br />
from __future__ import division<br />
from __future__ import generators<br />
<br />
global DEBUG<br />
DEBUG = 1<br />
<br />
APBS_DEFAULT=True<br />
<br />
import os,math,re<br />
import string<br />
import Tkinter<br />
from Tkinter import *<br />
import Pmw<br />
import distutils.spawn # used for find_executable<br />
import traceback<br />
import pymol<br />
<br />
#<br />
# Global config variables<br />
#<br />
# To change the default locations, change these to something like<br />
# APBS_BINARY_LOCATION = '/opt/bin/apbs'<br />
#<br />
APBS_BINARY_LOCATION = None<br />
APBS_PSIZE_LOCATION = None<br />
APBS_PDB2PQR_LOCATION = None<br />
TEMPORARY_FILE_DIR = None<br />
<br />
apbs_plea = ("IMPORTANT REQUEST: If you have not already done so, please register\n"<br />
"your use of the open-source Adaptive Poisson-Boltzmann Solver (APBS) at\n"<br />
"-> http://agave.wustl.edu/apbs/download\n"<br />
"Such proof of usage is vital in securing funding for APBS development!\n")<br />
<br />
pdb2pqr_plea = ("IMPORTANT REQUEST: If you have not already done so, please register\n"<br />
"your use of the open-source PDB2PQR at\n"<br />
"-> http://www.poissonboltzmann.org/pdb2pqr/d\n"<br />
"Such proof of usage is vital in securing funding for PDB2PQR development!\n")<br />
global apbs_message, pdb2pqr_message<br />
apbs_message = """You must have APBS installed on your system."""<br />
pdb2pqr_message = """PDB2PQR can be used to generate .PQR files."""<br />
<br />
def get_default_location(name):<br />
"""<br />
Given the name of an APBS-related binary, look in<br />
* pymol path,<br />
* freemol path,<br />
* user defined places,<br />
* the system path,<br />
* Known other paths (/usr/local/bin and /opt/local/bin)<br />
for the parameter, name.<br />
<br />
Some programs are verified with additional tests. In particular,<br />
some versions of PyMOL ship with a broken apbs.exe, so we verify<br />
that it can be run.<br />
<br />
PARAMS<br />
name, (string) the basename of the file we're looking for<br />
EXAMPLE<br />
get_default_location("apbs.exe")<br />
RETURNS<br />
(string) path/to/file on success or "" on failure<br />
NOTES<br />
For any program name <foo>.exe we will also search for<br />
<foo>. We'll search for the .exe version first. We do not<br />
automatically check for .exe versions of programs when .exe is<br />
not specified.<br />
"""<br />
def verify(name,f):<br />
if name in 'apbs.exe apbs'.split():<br />
# You'd think we could just check the return code, but<br />
# APBS doesn't return zero on success. Instead, it returns<br />
# things like 3328. It seems to return 5 or -5 in this<br />
# particular failure case, but I'm not sure we can depend<br />
# on that always.<br />
(retcode,prog_out) = run(f,'--version')<br />
if 'dyld: Library not loaded' in prog_out:<br />
print "Skipping",f,"because it appears to be broken (dyld)"<br />
return False<br />
return True<br />
searchDirs = []<br />
if "FREEMOL" in os.environ:<br />
searchDirs.append(os.environ["FREEMOL"])<br />
if "PYMOL_PATH" in os.environ:<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "ext", "bin"))<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "freemol", "bin"))<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "freemol", "share", "apbs"))<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "freemol", "share", "pdb2pqr"))<br />
for x in (APBS_BINARY_LOCATION, APBS_PSIZE_LOCATION, APBS_PDB2PQR_LOCATION):<br />
if x != None and x != "":<br />
searchDirs.append(x)<br />
if name=="temp":<br />
searchDirs = []<br />
if TEMPORARY_FILE_DIR != None and TEMPORARY_FILE_DIR != "":<br />
searchDirs.append(TEMPORARY_FILE_DIR)<br />
searchDirs.append("/tmp")<br />
searchDirs.append(".")<br />
<br />
searchDirs.extend(string.split(os.environ["PATH"], ":"))<br />
searchDirs.append(os.path.join("/usr", "local", "bin"))<br />
searchDirs.append(os.path.join("/opt", "local", "bin"))<br />
<br />
print "Search dirs",searchDirs<br />
<br />
if DEBUG:<br />
print "get_default_location will search the following: ", searchDirs<br />
for d in searchDirs:<br />
if name=="temp":<br />
f = d # just search for the directory<br />
else:<br />
f = os.path.join( d, name ) # make path/name.py<br />
print "trying",f<br />
if os.path.exists(f) and verify(name,f):<br />
return f<br />
elif name.endswith('.exe'):<br />
f = os.path.join( d, name[:-4] ) # make path/name.py<br />
if os.path.exists(f) and verify(name,f):<br />
return f<br />
<br />
print "Could not find default location for file: %s" % name<br />
return ""<br />
<br />
def __init__(self):<br />
"""<br />
Init PyMOL, by adding APBSTools to the GUI under Plugins<br />
<br />
Creates the APBS widget/notebook. Once the event is received,<br />
we create a new instance of APBSTools2 which is a Pmw, which upon<br />
creation shows itself.<br />
"""<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Launch APBS Tools2',<br />
label='APBS Tools2...',<br />
command = lambda s=self: APBSTools2(s))<br />
<br />
def run(prog,args):<br />
'''<br />
wrapper to handle spaces on windows.<br />
prog is the full path to the program.<br />
args is a string that we will split up for you.<br />
or a tuple. or a list. your call.<br />
<br />
return value is (retval,prog_out)<br />
<br />
e.g.<br />
<br />
(retval,prog_out) = run("/bin/ls","-al /tmp/myusername")<br />
'''<br />
import subprocess,tempfile<br />
<br />
if type(args) == type(''):<br />
args = tuple(args.split())<br />
elif type(args) in (type([]),type(())):<br />
args = tuple(args)<br />
args = (prog,) + args<br />
<br />
try:<br />
output_file = tempfile.TemporaryFile(mode="w+") # <-- shouldn't this point to the temp dir<br />
except IOError:<br />
print "Error opening output_file when trying to run the APBS command."<br />
<br />
print "Running",args<br />
retcode = subprocess.call(args,stdout=output_file.fileno(),stderr=subprocess.STDOUT)<br />
output_file.seek(0)<br />
#prog_out = output_file.read()<br />
prog_out = ''.join(output_file.readlines())<br />
output_file.close() #windows doesn't do this automatically<br />
if DEBUG:<br />
print "Results were:"<br />
print "Return value:",retcode<br />
print "Output:"<br />
print prog_out<br />
return (retcode,prog_out)<br />
<br />
class util:<br />
"""<br />
A quick collection of utility functions.<br />
"""<br />
#@staticmethod<br />
def getMolecules():<br />
"""returns all molecules that PyMOL knows about"""<br />
return [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule']<br />
getMolecules = staticmethod(getMolecules)<br />
#@staticmethod<br />
def getMaps():<br />
"""returns all maps that PyMOL knows about"""<br />
return [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map']<br />
getMaps = staticmethod(getMaps)<br />
#def hasAlt(sel):<br />
# """returns true if non-standard locations (rotamers) are present for this selection"""<br />
# return cmd.count_atoms(sel + " and not alt ''")!=0<br />
#hasAlt = staticmethod(hasAlt)<br />
<br />
util = util()<br />
<br />
##############################################################################<br />
##############################################################################<br />
### ###<br />
### ApbsInterface ###<br />
### ###<br />
##############################################################################<br />
##############################################################################<br />
<br />
def getApbsInputFile(pqr_filename,<br />
grid_points,<br />
cglen,<br />
fglen,<br />
cent,<br />
apbs_mode,<br />
bcfl,<br />
ion_plus_one_conc,ion_plus_one_rad,<br />
ion_minus_one_conc,ion_minus_one_rad,<br />
ion_plus_two_conc,ion_plus_two_rad,<br />
ion_minus_two_conc,ion_minus_two_rad,<br />
interior_dielectric, solvent_dielectric,<br />
chgm,<br />
srfm,<br />
solvent_radius,<br />
system_temp,<br />
sdens,<br />
dx_filename,<br />
):<br />
print "Getting APBS input"<br />
#print "system_temp",system_temp,type(system_temp)<br />
#print "sdens",sdens,type(sdens)<br />
#<br />
# How shall we set up the grid? We'll use cglen, fglen, cgcent, fgcent<br />
# and dime.<br />
# This allows people to automate things (e.g. "Alanine scanning")<br />
#<br />
<br />
#<br />
# New template using mg-auto<br />
# See http://agave.wustl.edu/apbs/doc/api/html/#mg-auto<br />
#<br />
<br />
apbs_template = """#<br />
# Note that most of the comments here were taken from sample<br />
# input files that came with APBS. You can find APBS at<br />
# http://agave.wustl.edu/apbs/<br />
# Note that APBS is GPL'd code.<br />
#<br />
read<br />
mol pqr %s # read molecule 1<br />
end<br />
elec<br />
mg-auto<br />
dime %d %d %d # number of find grid points<br />
# calculated by psize.py<br />
cglen %f %f %f # coarse mesh lengths (A)<br />
fglen %f %f %f # fine mesh lengths (A)<br />
# calculated by psize.py<br />
cgcent %f %f %f # (could also give (x,y,z) form psize.py) #known center<br />
fgcent %f %f %f # (could also give (x,y,z) form psize.py) #known center<br />
%s # solve the full nonlinear PBE with npbe<br />
#lpbe # solve the linear PBE with lpbe<br />
bcfl %s # Boundary condition flag<br />
# 0 => Zero<br />
# 1 => Single DH sphere<br />
# 2 => Multiple DH spheres<br />
# 4 => Focusing<br />
#<br />
#ion 1 0.000 2.0 # Counterion declaration:<br />
ion charge 1 conc %f radius %f # Counterion declaration:<br />
ion charge -1 conc %f radius %f # ion <charge> <conc (M)> <radius><br />
ion charge 2 conc %f radius %f # ion <charge> <conc (M)> <radius><br />
ion charge -2 conc %f radius %f # ion <charge> <conc (M)> <radius><br />
pdie %f # Solute dielectric<br />
sdie %f # Solvent dielectric<br />
chgm %s # Charge disc method<br />
# 0 is linear splines<br />
# 1 is cubic b-splines<br />
mol 1 # which molecule to use<br />
srfm smol # Surface calculation method<br />
# 0 => Mol surface for epsilon;<br />
# inflated VdW for kappa; no<br />
# smoothing<br />
# 1 => As 0 with harmoinc average<br />
# smoothing<br />
# 2 => Cubic spline <br />
srad %f # Solvent radius (1.4 for water)<br />
swin 0.3 # Surface cubic spline window .. default 0.3<br />
temp %f # System temperature (298.15 default)<br />
sdens %f # Specify the number of grid points per square-angstrom to use in Vacc object. Ignored when srad is 0.0 (see srad) or srfm is spl2 (see srfm). There is a direct correlation between the value used for the Vacc sphere density, the accuracy of the Vacc object, and the APBS calculation time. APBS default value is 10.0.<br />
#gamma 0.105 # Surface tension parameter for apolar forces (in kJ/mol/A^2)<br />
# only used for force calculations, so we don't care, but<br />
# it *used to be* always required, and 0.105 is the default<br />
calcenergy no # Energy I/O to stdout<br />
# 0 => don't write out energy<br />
# 1 => write out total energy<br />
# 2 => write out total energy and all<br />
# components<br />
calcforce no # Atomic forces I/O (to stdout)<br />
# 0 => don't write out forces<br />
# 1 => write out net forces on molecule<br />
# 2 => write out atom-level forces<br />
write pot dx %s # What to write .. this says write the potential in dx<br />
# format to a file.<br />
end<br />
quit<br />
<br />
"""<br />
return apbs_template % (pqr_filename,<br />
grid_points[0], grid_points[1], grid_points[2],<br />
cglen[0],cglen[1],cglen[2],<br />
fglen[0],fglen[1],fglen[2],<br />
cent[0],cent[1],cent[2],<br />
cent[0],cent[1],cent[2],<br />
apbs_mode,<br />
bcfl,<br />
ion_plus_one_conc,ion_plus_one_rad,<br />
ion_minus_one_conc,ion_minus_one_rad,<br />
ion_plus_two_conc,ion_plus_two_rad,<br />
ion_minus_two_conc,ion_minus_two_rad,<br />
interior_dielectric, solvent_dielectric,<br />
chgm,<br />
solvent_radius,<br />
system_temp,<br />
sdens,<br />
dx_filename,<br />
)<br />
<br />
<br />
<br />
##############################################################################<br />
##############################################################################<br />
### ###<br />
### PluginCode ###<br />
### ###<br />
##############################################################################<br />
##############################################################################<br />
<br />
<br />
<br />
class APBSTools2:<br />
# The current goal is to factor all of the APBS-specific code into<br />
# an ApbsInterface class. The functions defined here before<br />
# __init__, as well as the functions defined on the various<br />
# Panels/Panes, will call through to self.ApbsInterface.<br />
def setPqrFile(self,name):<br />
print " APBS Tools: set pqr file to",name<br />
self.pqr_to_use.setvalue(name)<br />
self.radiobuttons.setvalue('Use another PQR')<br />
def getPqrFilename(self):<br />
if self.radiobuttons.getvalue() != 'Use another PQR':<br />
return self.pymol_generated_pqr_filename.getvalue()<br />
else:<br />
return self.pqr_to_use.getvalue()<br />
def setPsizeLocation(self,value):<br />
self.psize.setvalue(value)<br />
def setBinaryLocation(self,value):<br />
self.binary.setvalue(value)<br />
def setPdb2pqrLocation(self,value):<br />
self.pdb2pqr.setvalue(value)<br />
<br />
def setPymolGeneratedPqrFilename(self,value):<br />
self.pymol_generated_pqr_filename.setvalue(value)<br />
def setPymolGeneratedPdbFilename(self,value):<br />
self.pymol_generated_pdb_filename.setvalue(value)<br />
def setPymolGeneratedDxFilename(self,value):<br />
self.pymol_generated_dx_filename.setvalue(value)<br />
def setPymolGeneratedInFilename(self,value):<br />
self.pymol_generated_in_filename.setvalue(value)<br />
<br />
<br />
def getPymolGeneratedPqrFilename(self):<br />
return self.pymol_generated_pqr_filename.getvalue()<br />
def getPymolGeneratedPdbFilename(self):<br />
return self.pymol_generated_pdb_filename.getvalue()<br />
def getPymolGeneratedDxFilename(self):<br />
return self.pymol_generated_dx_filename.getvalue()<br />
def getPymolGeneratedInFilename(self):<br />
return self.pymol_generated_in_filename.getvalue()<br />
defaults = {<br />
"interior_dielectric" : 2.0,<br />
"solvent_dielectric" : 78.0,<br />
"solvent_radius" : 1.4,<br />
"system_temp" : 310.0,<br />
"apbs_mode" : 'Linearized Poisson-Boltzmann Equation',<br />
"ion_plus_one_conc" : 0.15,<br />
"ion_plus_one_rad" : 2.0,<br />
"ion_plus_two_conc" : 0.0,<br />
"ion_plus_two_rad" : 2.0,<br />
"ion_minus_one_conc" : 0.15,<br />
"ion_minus_one_rad" : 1.8,<br />
"ion_minus_two_conc" : 0.0,<br />
"ion_minus_two_rad" : 2.0,<br />
#"max_mem_allowed" : 400,<br />
"max_mem_allowed" : 1500,<br />
"potential_at_sas" : 0,<br />
"surface_solvent" : 1,<br />
"show_surface_for_scanning" : 1,<br />
#"grid_buffer" : 0,<br />
#"grid_buffer" : 20,<br />
"bcfl" : 'Single DH sphere', # Boundary condition flag for APBS<br />
"sdens": 10.0, # Specify the number of grid points per<br />
# square-angstrom to use in Vacc<br />
# object. Ignored when srad is 0.0 (see srad)<br />
# or srfm is spl2 (see srfm). There is a direct<br />
# correlation between the value used for the<br />
# Vacc sphere density, the accuracy of the Vacc<br />
# object, and the APBS calculation time. APBS<br />
# default value is 10.0.<br />
"chgm" : 'Cubic B-splines', # Charge disc method for APBS<br />
}<br />
<br />
def __init__(self,app):<br />
self.parent = app.root<br />
<br />
# Create the dialog.<br />
self.dialog = Pmw.Dialog(self.parent,<br />
buttons = ('Register APBS Use', 'Register PDB2PQR Use', 'Set grid', 'Run APBS', 'Exit APBS tools'),<br />
title = 'PyMOL APBS Tools',<br />
command = self.execute)<br />
self.dialog.withdraw()<br />
Pmw.setbusycursorattributes(self.dialog.component('hull'))<br />
<br />
w = Tkinter.Label(self.dialog.interior(),<br />
text = 'PyMOL APBS Tools\nMichael G. Lerner, Heather A. Carlson, 2009 - http://pymolwiki.org/index.php/APBS\n(incorporates modifications by Warren L. DeLano)',<br />
background = 'black',<br />
foreground = 'white',<br />
#pady = 20,<br />
)<br />
w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)<br />
<br />
self.notebook = Pmw.NoteBook(self.dialog.interior())<br />
self.notebook.pack(fill='both',expand=1,padx=10,pady=10)<br />
<br />
# Set up the Main page<br />
page = self.notebook.add('Main')<br />
group = Pmw.Group(page,tag_text='Main options')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.selection = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Selection to use: ',<br />
value='(polymer)',<br />
)<br />
self.map = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='What to call the resulting map: ',<br />
value='apbs_map',<br />
)<br />
self.radiobuttons = Pmw.RadioSelect(group.interior(),<br />
buttontype = 'radiobutton',<br />
orient = 'vertical',<br />
labelpos = 'w',<br />
)<br />
for text in ('Use PyMOL generated PQR and existing Hydrogens and termini',<br />
'Use PyMOL generated PQR and PyMOL generated Hydrogens and termini',<br />
'Use another PQR',<br />
'Use PDB2PQR',):<br />
self.radiobuttons.add(text)<br />
self.radiobuttons.setvalue('Use PyMOL generated PQR and PyMOL generated Hydrogens and termini')<br />
<br />
self.pdb2pqr_options = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='pdb2pqr command line options: ',<br />
value='--ff=AMBER',<br />
)<br />
self.pqr_to_use = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPqrFile,'*.pqr'),<br />
label_text='\tChoose Externally Generated PQR:',<br />
)<br />
<br />
<br />
<br />
for entry in (self.selection,self.map,self.radiobuttons,self.pdb2pqr_options,self.pqr_to_use):<br />
#for entry in (self.selection,self.map,self.radiobuttons,):<br />
entry.pack(fill='x',padx=4,pady=1) # vertical<br />
<br />
<br />
# Set up the main "Calculation" page<br />
page = self.notebook.add('Configuration')<br />
<br />
group = Pmw.Group(page,tag_text='Dielectric Constants')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column=0, row=0)<br />
self.interior_dielectric = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Protein Dielectric:',<br />
value = str(APBSTools2.defaults['interior_dielectric']),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
self.solvent_dielectric = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Solvent Dielectric:',<br />
value = str(APBSTools2.defaults['solvent_dielectric']),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
entries = (self.interior_dielectric,self.solvent_dielectric)<br />
for entry in entries:<br />
#entry.pack(side='left',fill='both',expand=1,padx=4) # side-by-side<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
group = Pmw.Group(page,tag_text='Other')<br />
group.pack(fill='both',expand=1, padx=4, pady=5)<br />
group.grid(column=1, row=1,columnspan=4)<br />
self.max_mem_allowed = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Maximum Memory Allowed (MB):',<br />
value = str(APBSTools2.defaults['max_mem_allowed']),<br />
validate = {'validator' : 'real',<br />
'min':1,}<br />
)<br />
self.apbs_mode = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'APBS Mode',<br />
items = ('Nonlinear Poisson-Boltzmann Equation','Linearized Poisson-Boltzmann Equation',),<br />
initialitem = APBSTools2.defaults['apbs_mode'],<br />
)<br />
self.apbs_mode.pack(fill='x',expand=1,padx=4)<br />
#self.apbs_mode.grid(column=0,row=0,columnspan=3)<br />
self.solvent_radius = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Solvent Radius:',<br />
validate = {'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['solvent_radius']),<br />
)<br />
self.system_temp = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'System Temperature:',<br />
validate = {'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['system_temp']),<br />
)<br />
self.sdens = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Vacc sphere density (grid points/A^2)',<br />
validate = {'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['sdens']),<br />
)<br />
self.bcfl = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Boundary Condition',<br />
items = ('Zero','Single DH sphere','Multiple DH spheres',), #'Focusing',),<br />
initialitem = APBSTools2.defaults['bcfl'],<br />
)<br />
self.chgm = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Charge disc method',<br />
items = ('Linear','Cubic B-splines','Quintic B-splines',),<br />
initialitem = APBSTools2.defaults['chgm'],<br />
)<br />
self.srfm = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Surface Calculation Method',<br />
items = ('Mol surf for epsilon; inflated VdW for kappa, no smoothing','Same, but with harmonic average smoothing','Cubic spline','Similar to cubic spline, but with 7th order polynomial'),<br />
initialitem = 'Same, but with harmonic average smoothing',<br />
)<br />
#for entry in (self.apbs_mode,self.system_temp,self.solvent_radius,):<br />
for entry in (self.max_mem_allowed,self.solvent_radius,self.system_temp,self.sdens,self.apbs_mode,self.bcfl,self.chgm,self.srfm):<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
<br />
<br />
group = Pmw.Group(page,tag_text='Ions')<br />
group.pack(fill='both',expand=1, padx=4, pady=5)<br />
group.grid(column=0, row=1, )<br />
self.ion_plus_one_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (+1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_one_conc']),<br />
)<br />
self.ion_plus_one_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (+1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_one_rad']),<br />
)<br />
self.ion_minus_one_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (-1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_one_conc']),<br />
)<br />
self.ion_minus_one_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (-1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_one_rad']),<br />
)<br />
self.ion_plus_two_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (+2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_two_conc']),<br />
)<br />
self.ion_plus_two_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (+2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_two_rad']),<br />
)<br />
self.ion_minus_two_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (-2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_two_conc']),<br />
)<br />
self.ion_minus_two_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (-2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_two_rad']),<br />
)<br />
entries = (self.ion_plus_one_conc,self.ion_plus_one_rad,<br />
self.ion_minus_one_conc,self.ion_minus_one_rad,<br />
self.ion_plus_two_conc,self.ion_plus_two_rad,<br />
self.ion_minus_two_conc,self.ion_minus_two_rad,<br />
)<br />
for entry in entries:<br />
entry.pack(fill='x',expand=1,padx=4)<br />
<br />
group = Pmw.Group(page,tag_text = 'Coarse Mesh Length')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 1, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_coarse_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'real','min':0},<br />
value = -1,<br />
entry_width=15,<br />
)<br />
)<br />
getattr(self,'grid_coarse_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
<br />
group = Pmw.Group(page,tag_text = 'Fine Mesh Length')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 2, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_fine_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'real','min':0},<br />
value = -1,<br />
entry_width=15,<br />
)<br />
)<br />
getattr(self,'grid_fine_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
<br />
group = Pmw.Group(page,tag_text = 'Grid Center')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 3, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_center_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'real'},<br />
value = 0,<br />
entry_width=10,<br />
)<br />
)<br />
getattr(self,'grid_center_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
group = Pmw.Group(page,tag_text = 'Grid Points')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 4, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_points_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'integer','min':0},<br />
value = -1,<br />
entry_width=8,<br />
)<br />
)<br />
getattr(self,'grid_points_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
<br />
page.grid_rowconfigure(2,weight=1)<br />
page.grid_columnconfigure(5,weight=1)<br />
page = self.notebook.add('Program Locations')<br />
group = Pmw.Group(page,tag_text='Locations')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
def quickFileValidation(s):<br />
if s == '': return Pmw.PARTIAL<br />
elif os.path.isfile(s): return Pmw.OK<br />
elif os.path.exists(s): return Pmw.PARTIAL<br />
else: return Pmw.PARTIAL<br />
def quickFileDirValidation(s):<br />
'''<br />
assumes s ends in filename<br />
'''<br />
if os.path.exists(s) and not os.path.isfile(s):<br />
return Pmw.PARTIAL<br />
if os.path.isdir(os.path.split(s)[0]):<br />
return Pmw.OK<br />
return Pmw.PARTIAL<br />
self.binary = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setBinaryLocation),<br />
validate = {'validator':quickFileValidation,},<br />
value = get_default_location('apbs.exe'),<br />
label_text = 'APBS binary location:',<br />
)<br />
self.binary.pack(fill = 'x', padx = 20, pady = 10)<br />
self.psize = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPsizeLocation),<br />
validate = {'validator':quickFileValidation,},<br />
#value = '/usr/local/apbs-0.3.1/tools/manip/psize.py',<br />
value = get_default_location('psize.py'),<br />
label_text = 'APBS psize.py location:',<br />
)<br />
self.psize.pack(fill = 'x', padx = 20, pady = 10)<br />
self.pdb2pqr = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPdb2pqrLocation),<br />
validate = {'validator':quickFileValidation,},<br />
value = get_default_location('pdb2pqr.py'),<br />
label_text = 'pdb2pqr location:',<br />
)<br />
self.pdb2pqr.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
label = Tkinter.Label(group.interior(),<br />
pady = 10,<br />
justify=LEFT,<br />
text = """<br />
The PyMOL APBS tools can calculate proper grid dimensions and spacing (we attempt to make<br />
the fine mesh spacing 0.5A or finer, but we will make it coarser if forced to by the<br />
Maximum Grid Points setting in the configuration pane). If you wish to use APBS's psize.py<br />
to set up the grid, make sure that the path is set correctly above.<br />
<br />
PyMOL can generate PQR files using standard protein residues and AMBER charges. If you<br />
wish to use PDB2PQR instead, make sure that it is installed and that the path is set<br />
correctly above.<br />
<br />
If PyMOL does not automatically find apbs, psize.py, or pdb2pqr, you may set the environment<br />
variables APBS_BINARY, APBS_PSIZE and APBS_PDB2PQR to point to them respectively.<br />
""",<br />
)<br />
label.pack()<br />
<br />
<br />
page = self.notebook.add('Temp File Locations')<br />
group = Pmw.Group(page,tag_text='Locations')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.pymol_generated_pqr_filename = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedPqrFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
label_text = 'Temporary PQR file: ',<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.pqr'),<br />
)<br />
self.pymol_generated_pqr_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
self.pymol_generated_pdb_filename = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedPdbFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
label_text = 'Temporary PDB file: ',<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.pdb'),<br />
)<br />
self.pymol_generated_pdb_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
self.pymol_generated_dx_filename = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedDxFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
label_text = 'Temporary DX file: ',<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.dx'),<br />
)<br />
self.pymol_generated_dx_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
<br />
self.pymol_generated_in_filename = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedInFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.in'),<br />
label_text = 'APBS input file:')<br />
self.pymol_generated_in_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
label = Tkinter.Label(group.interior(),<br />
pady = 10,<br />
justify=LEFT,<br />
text = """You can automatically set the default location of temporary files<br />
by setting the environment variable TEMP.<br />
""",<br />
)<br />
label.pack()<br />
# Create the visualization pages<br />
page = self.notebook.add('Visualization (1)')<br />
group = VisualizationGroup(page,tag_text='Visualization',visgroup_num=1)<br />
self.visualization_group_1 = group<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
<br />
page = self.notebook.add('Visualization (2)')<br />
group = VisualizationGroup(page,tag_text='Visualization',visgroup_num=2)<br />
self.visualization_group_2 = group<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
<br />
# Create a couple of other empty pages<br />
page = self.notebook.add('About')<br />
group = Pmw.Group(page, tag_text='About PyMOL APBS Tools')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
text = """This plugin integrates PyMOL (http://PyMOL.org/) with APBS (http://www.poissonboltzmann.org/apbs/).<br />
<br />
Documentation may be found at<br />
http://pymolwiki.org/index.php/APBS<br />
and<br />
http://apbs.wustl.edu/MediaWiki/index.php/APBS_electrostatics_in_PyMOL<br />
<br />
It requires APBS version >= 0.5.0.<br />
<br />
In the simplest case,<br />
<br />
1) Load a structure into PyMOL.<br />
2) Start this plugin.<br />
3) Make sure that the path to the APBS binary is correct on the "Program Locations" tab.<br />
4) Click the "Set grid" button to set up the grid.<br />
5) Click the "Run APBS" button.<br />
<br />
Many thanks to<br />
- Warren DeLano and Jason Vertrees for everything involving PyMOL<br />
- Nathan Baker, Todd Dolinsky and David Gohara for everything involving APBS<br />
- William G. Scott for help with several APBS+PyMOL issues and documentation<br />
<br />
Created by Michael Lerner (http://pymolwiki.org/index.php/User:Mglerner) mglerner@gmail.com<br />
Carlson Group, University of Michigan (http://www.umich.edu/~carlsonh/)<br />
<br />
Please contact the author and cite this plugin if you use it in a publication.<br />
<br />
Citation for this plugin:<br />
MG Lerner and HA Carlson. APBS plugin for PyMOL, 2006,<br />
University of Michigan, Ann Arbor.<br />
<br />
Citation for PyMOL may be found here:<br />
http://pymol.sourceforge.net/faq.html#CITE<br />
<br />
Citation for APBS:<br />
Baker NA, Sept D, Joseph S, Holst MJ, McCammon JA. Electrostatics of<br />
nanosystems: application to microtubules and the ribosome. Proc.<br />
Natl. Acad. Sci. USA 98, 10037-10041 2001.<br />
<br />
Citation for PDB2PQR:<br />
Dolinsky TJ, Nielsen JE, McCammon JA, Baker NA.<br />
PDB2PQR: an automated pipeline for the setup, execution,<br />
and analysis of Poisson-Boltzmann electrostatics calculations.<br />
Nucleic Acids Research 32 W665-W667 (2004).<br />
"""<br />
#<br />
# Add this as text in a scrollable pane.<br />
# Code based on Caver plugin<br />
# http://loschmidt.chemi.muni.cz/caver/index.php<br />
#<br />
interior_frame=Frame(group.interior())<br />
bar=Scrollbar(interior_frame,)<br />
text_holder=Text(interior_frame,yscrollcommand=bar.set,background="#ddddff",font="Times 14")<br />
bar.config(command=text_holder.yview)<br />
text_holder.insert(END,text)<br />
text_holder.pack(side=LEFT,expand="yes",fill="both")<br />
bar.pack(side=LEFT,expand="yes",fill="y")<br />
interior_frame.pack(expand="yes",fill="both")<br />
<br />
self.notebook.setnaturalsize()<br />
self.showAppModal()<br />
<br />
def showAppModal(self):<br />
#self.dialog.activate() #geometry = 'centerscreenfirst',globalMode = 'nograb')<br />
self.dialog.show()<br />
def execute(self, result, refocus=True):<br />
if result == 'Register APBS Use':<br />
import webbrowser<br />
webbrowser.open("http://agave.wustl.edu/apbs/download")<br />
elif result == 'Register PDB2PQR Use':<br />
import webbrowser<br />
webbrowser.open("http://www.poissonboltzmann.org/pdb2pqr/d/downloads")<br />
elif result == 'Run APBS':<br />
good = self.generateApbsInputFile()<br />
if not good:<br />
if DEBUG:<br />
print "ERROR: Something went wrong trying to generate the APBS input file."<br />
return False<br />
if self.radiobuttons.getvalue() == 'Use another PQR':<br />
pass<br />
elif self.radiobuttons.getvalue() == 'Use PDB2PQR':<br />
if DEBUG: print "GENERATING PQR FILE via PDB2PQR"<br />
good = self.generatePdb2pqrPqrFile()<br />
if not good:<br />
if DEBUG:<br />
print "Could not generate PDB2PQR file. generatePdb2pqrPqrFile failed."<br />
return False<br />
if DEBUG: print "GENERATED"<br />
else: # it's one of the pymol-generated options<br />
if DEBUG: print "GENERATING PQR FILE via PyMOL"<br />
good = self.generatePymolPqrFile()<br />
if not good:<br />
if DEBUG:<br />
print "Could not generate the PyMOL-basd PQR file. generatePyMOLPqrFile failed."<br />
return False<br />
if DEBUG: print "GENERATED"<br />
if os.path.exists(self.pymol_generated_dx_filename.getvalue()):<br />
try:<br />
os.unlink(self.pymol_generated_dx_filename.getvalue())<br />
except:<br />
traceback.print_exc()<br />
pass<br />
#command = "%s %s" % (self.binary.getvalue(),self.pymol_generated_in_filename.getvalue())<br />
#os.system(command)<br />
<br />
#<br />
# NOTE: if there are spaces in the directory name that contains pymol_generated_in_filename,<br />
# our run command will want to split it up into several arguments if we pass it as a<br />
# string. So, we pass it as a tuple.<br />
#<br />
(retval,progout) = run(self.binary.getvalue(),(self.pymol_generated_in_filename.getvalue(),))<br />
if refocus:<br />
#<br />
# There's a bug in the version of APBS shipped with<br />
# Ubuntu 9.10 (version 1.1.0) that causes the name to<br />
# become foo-PE0.dx instead of foo.dx. This would<br />
# normally only occur in mg-para calcs or MPI versions<br />
# of apbs. It's clearly bug-possible, but we will<br />
# check for foo-PE0 if we can't find foo.dx.<br />
#<br />
fname = self.pymol_generated_dx_filename.getvalue()<br />
if not os.path.isfile(fname):<br />
print "Could not find",fname,"so searching for",<br />
fname = '-PE0'.join(os.path.splitext(fname))<br />
print fname<br />
pymol.cmd.load(fname)<br />
self.visualization_group_1.refresh()<br />
self.visualization_group_2.refresh()<br />
self.notebook.tab('Visualization (1)').focus_set()<br />
self.notebook.selectpage('Visualization (1)')<br />
elif result == 'Set grid':<br />
self.runPsize()<br />
else:<br />
#<br />
# Doing it this way takes care of clicking on the x in the top of the<br />
# window, which as result set to None.<br />
#<br />
global APBS_BINARY_LOCATION, APBS_PSIZE_LOCATION<br />
APBS_BINARY_LOCATION = self.binary.getvalue()<br />
APBS_PSIZE_LOCATION = self.psize.getvalue()<br />
self.quit()<br />
def quit(self):<br />
self.dialog.destroy() # stops CPU hogging, perhaps fixes Ubuntu bug MGL<br />
<br />
def runPsize(self):<br />
class NoPsize(Exception):<br />
pass<br />
class NoPDB(Exception):<br />
pass<br />
try:<br />
if not self.psize.valid():<br />
raise NoPsize<br />
pqr_filename = self.pymol_generated_pqr_filename.getvalue()<br />
try:<br />
f = file(pqr_filename,'w')<br />
f.close()<br />
except:<br />
raise NoPDB<br />
#<br />
# Do some magic to load the psize module<br />
#<br />
import imp<br />
f,fname,description = imp.find_module('psize',[os.path.split(self.psize.getvalue())[0]])<br />
psize = imp.load_module('psize',f,fname,description)<br />
# WLD<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
<br />
if pymol.cmd.count_atoms( self.selection.getvalue() + " and not alt ''")!=0:<br />
print "WARNING: You have alternate locations for some of your atoms!"<br />
pymol.cmd.save(pqr_filename,sel)<br />
f.close()<br />
size = psize.Psize()<br />
size.setConstant('gmemceil',int(self.max_mem_allowed.getvalue()))<br />
size.runPsize(pqr_filename)<br />
coarsedim = size.getCoarseGridDims() # cglen<br />
finedim = size.getFineGridDims() # fglen<br />
# could use procgrid for multiprocessors<br />
finegridpoints = size.getFineGridPoints() # dime<br />
center = size.getCenter() # cgcent and fgcent<br />
print "APBS's psize.py was used to calculated grid dimensions"<br />
except (NoPsize,ImportError):<br />
print "This plugin was used to calculated grid dimensions"<br />
#<br />
# First, we need to get the dimensions of the molecule<br />
#<br />
# WLD<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
model = pymol.cmd.get_model(sel)<br />
mins = [None,None,None]<br />
maxs = [None,None,None]<br />
for a in model.atom:<br />
for i in (0,1,2):<br />
if mins[i] is None or a.coord[i] < mins[i]:<br />
mins[i] = a.coord[i]<br />
if maxs[i] is None or a.coord[i] > maxs[i]:<br />
maxs[i] = a.coord[i]<br />
if None in mins or None in maxs:<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "No atoms were in your selection",<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
<br />
box_length = [maxs[i] - mins[i] for i in range(3)]<br />
center = [(maxs[i] + mins[i])/2.0 for i in range(3)]<br />
#<br />
# psize expands the molecular dimensions by CFAC (which defaults<br />
# to 1.7) for the coarse grid<br />
#<br />
CFAC = 1.7<br />
coarsedim = [length*CFAC for length in box_length]<br />
<br />
#<br />
# psize also does something strange .. it adds a buffer FADD to<br />
# the box lengths to get the fine lengths. you'd think it'd also<br />
# have FFAC or CADD, but we'll mimic it here. it also has the<br />
# requirement that the fine grid lengths must be <= the corase<br />
# grid lengths. FADD defaults to 20.<br />
#<br />
FADD = 20<br />
finedim = [min(coarsedim[i],box_length[i] + FADD) for i in range(3)]<br />
<br />
#<br />
# And now the hard part .. setting up the grid points.<br />
# From the APBS manual at http://agave.wustl.edu/apbs/doc/html/user-guide/x594.html#dime<br />
# we have the formula<br />
# n = c*2^(l+1) + 1<br />
# where l is the number of levels in the MG hierarchy. The typical<br />
# number of levels is 4.<br />
#<br />
nlev = 4<br />
mult_fac = 2**(nlev + 1) # this will typically be 2^5==32<br />
# and c must be a non-zero integer<br />
<br />
# If we didn't have to be c*mult_fac + 1, this is what our grid points<br />
# would look like (we use the ceiling to be on the safe side .. it never<br />
# hurts to do too much.<br />
SPACE = 0.5 # default desired spacing = 0.5A<br />
#desired_points = [int(math.ceil(flen / SPACE)) for flen in finedim] # as integers<br />
desired_points = [flen / SPACE for flen in finedim] # as floats .. use int(math.ceil(..)) later<br />
<br />
# Now we set up our cs, taking into account mult_fac<br />
# (we use the ceiling to be on the safe side .. it never hurts to do<br />
# too much.)<br />
cs = [int(math.ceil(dp/mult_fac)) for dp in desired_points]<br />
<br />
finegridpoints = [mult_fac * c + 1 for c in cs]<br />
<br />
print "cs",cs<br />
print "finedim",finedim<br />
print "nlev",nlev<br />
print "mult_fac",mult_fac<br />
print "finegridpoints",finegridpoints<br />
<br />
except NoPDB:<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "Please set a temporary PDB file location",<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
<br />
if (finegridpoints[0]>0) and (finegridpoints[1]>0) and (finegridpoints[2]>0):<br />
max_mem_allowed = float(self.max_mem_allowed.getvalue())<br />
def memofgrid(finegridpoints):<br />
return 200. * float(finegridpoints[0] * finegridpoints[1] * finegridpoints[2]) / 1024. / 1024<br />
def gridofmem(mem):<br />
return mem * 1024. * 1024. / 200.<br />
max_grid_points = gridofmem(max_mem_allowed)<br />
print "Estimated memory usage",memofgrid(finegridpoints),'MB out of maximum allowed',max_mem_allowed<br />
if memofgrid(finegridpoints) > max_mem_allowed:<br />
print "Maximum memory usage exceeded. Old grid dimensions were",finegridpoints<br />
product = float(finegridpoints[0] * finegridpoints[1] * finegridpoints[2])<br />
factor = pow(max_grid_points/product,0.333333333)<br />
finegridpoints[0] = (int(factor*finegridpoints[0]/2))*2+1<br />
finegridpoints[1] = (int(factor*finegridpoints[1]/2))*2+1<br />
finegridpoints[2] = (int(factor*finegridpoints[2]/2))*2+1<br />
print "Fine grid points rounded down from",finegridpoints<br />
#<br />
# Now we have to make sure that this still fits the equation n = c*2^(l+1) + 1. Here, we'll<br />
# just assume nlev == 4, which means that we need to be (some constant times 32) + 1.<br />
#<br />
# This can be annoying if, e.g., you're trying to set [99, 123, 99] .. it'll get rounded to [99, 127, 99].<br />
# First, I'll try to round to the nearest 32*c+1. If that doesn't work, I'll just round down.<br />
#<br />
new_gp = [0,0,0]<br />
for i in 0,1,2:<br />
dm = divmod(finegridpoints[i] - 1,32)<br />
if dm[1]>16:<br />
new_gp[i] = (dm[0]+1)*32+1<br />
else:<br />
new_gp[i] = (dm[0])*32+1<br />
new_prod = new_gp[0]*new_gp[1]*new_gp[2]<br />
#print "tried new_prod",new_prod,"max_grid_points",max_grid_points,"small enough?",new_prod <= max_grid_points<br />
if new_prod <= max_grid_points:<br />
#print "able to round to closest"<br />
for i in 0,1,2: finegridpoints[i] = new_gp[i]<br />
else:<br />
# darn .. have to round down.<br />
# Note that this can still fail a little bit .. it can only get you back down to the next multiple <= what was in<br />
# finegridpoints. So, if finegridpoints was exactly on a multiple, like (99,129,99), you'll get rounded down to<br />
# (99,127,99), which is still just a bit over the default max of 1200000. I think that's ok. It's the rounding error<br />
# from int(factor*finegridpoints ..) above, but it'll never be a huge error. If we needed to, we could easily fix this.<br />
#<br />
#print "rounding down more"<br />
for i in 0,1,2:<br />
#print finegridpoints[i],divmod(finegridpoints[i] - 1,32),<br />
finegridpoints[i] = divmod(finegridpoints[i] - 1,32)[0]*32 + 1<br />
print "New grid dimensions are",finegridpoints<br />
print " APBS Tools: coarse grid: (%5.3f,%5.3f,%5.3f)"%tuple(coarsedim)<br />
self.grid_coarse_x.setvalue(coarsedim[0])<br />
self.grid_coarse_y.setvalue(coarsedim[1])<br />
self.grid_coarse_z.setvalue(coarsedim[2])<br />
print " APBS Tools: fine grid: (%5.3f,%5.3f,%5.3f)"%tuple(finedim)<br />
self.grid_fine_x.setvalue(finedim[0])<br />
self.grid_fine_y.setvalue(finedim[1])<br />
self.grid_fine_z.setvalue(finedim[2])<br />
print " APBS Tools: center: (%5.3f,%5.3f,%5.3f)"%tuple(center)<br />
self.grid_center_x.setvalue(center[0])<br />
self.grid_center_y.setvalue(center[1])<br />
self.grid_center_z.setvalue(center[2])<br />
print " APBS Tools: fine grid points (%d,%d,%d)"%tuple(finegridpoints)<br />
self.grid_points_x.setvalue(finegridpoints[0])<br />
self.grid_points_y.setvalue(finegridpoints[1])<br />
self.grid_points_z.setvalue(finegridpoints[2])<br />
<br />
def fixColumns(self,sel):<br />
"""<br />
Make sure that everything fits into the correct columns.<br />
This means doing some rounding. It also means getting rid of<br />
chain, occupancy and b-factor information.<br />
"""<br />
#pymol.cmd.alter_state(1,'all','(x,y,z)=(int(x*1000)/1000.0, int(y*1000)/1000.0, int(z*1000)/1000.0)')<br />
#pymol.cmd.alter_state(1,'all','(x,y,z)=float("%.2f"%x),float("%.2f"%y),float("%.2f"%z)')<br />
pymol.cmd.alter_state(1,'all','(x,y,z)=float("%.3f"%x),float("%.3f"%y),float("%.3f"%z)')<br />
pymol.cmd.alter(sel,'chain=""')<br />
pymol.cmd.alter(sel,'b=0')<br />
pymol.cmd.alter(sel,'q=0')<br />
<br />
def cleanupGeneratedPdbOrPqrFile(self,filename):<br />
"""<br />
More cleanup on PQR files.<br />
<br />
pdb2pqr will happily write out a file where the coordinate<br />
columns overlap if you have -100.something as one of the<br />
coordinates, like<br />
<br />
90.350 97.230-100.010<br />
<br />
and so will PyMOL. We can't just assume that it's 0-1<br />
because pdb2pqr will debump things and write them out with<br />
3 digits post-decimal. Bleh.<br />
"""<br />
f = file(filename,'r')<br />
txt = f.read()<br />
f.close()<br />
f = file(filename,'w')<br />
# APBS accepts whitespace-delimited columns<br />
# it doesn't care about non-coord lines, so there's not need to be careful about<br />
# where we replace dashes.<br />
txt = txt.replace('-',' -')<br />
f.write(txt)<br />
f.close()<br />
<br />
def getUnassignedAtomsFromPqr(self,fname):<br />
"""<br />
Here is a comment from Todd Dolinsky via email:<br />
<br />
There's a couple of different errors which can be printed out via REMARK 5 lines; a good sample is:<br />
<br />
REMARK 1 PQR file generated by PDB2PQR (Version 1.2.0)<br />
REMARK 1<br />
REMARK 1 Forcefield Used: charmm<br />
REMARK 1<br />
REMARK 1 pKas calculated by propka and assigned using pH 7.00<br />
REMARK 1<br />
REMARK 5 WARNING: Propka determined the following residues to be<br />
REMARK 5 in a protonation state not supported by the<br />
REMARK 5 charmm forcefield!<br />
REMARK 5 All were reset to their standard pH 7.0 state.<br />
REMARK 5 <br />
REMARK 5 CYS 61 2 (negative)<br />
REMARK 5 CYS 79 2 (negative)<br />
REMARK 5 <br />
REMARK 5 WARNING: Unable to debump ALA 1 19<br />
REMARK 5 WARNING: Unable to debump MET 1 151<br />
REMARK 5 WARNING: Unable to debump PRO 1 258<br />
REMARK 5 WARNING: Unable to debump GLY 2 8<br />
REMARK 5 WARNING: Unable to debump THR 3 118<br />
REMARK 5<br />
REMARK 5 WARNING: PDB2PQR was unable to assign charges<br />
REMARK 5 to the following atoms (omitted below):<br />
REMARK 5 6657 O1 in TRS 900<br />
REMARK 5 6658 C2 in TRS 900<br />
REMARK 5 6659 C3 in TRS 900<br />
REMARK 5 6660 C4 in TRS 900<br />
REMARK 5 6661 O5 in TRS 900<br />
REMARK 5 6662 C6 in TRS 900<br />
REMARK 5 6663 O7 in TRS 900<br />
REMARK 5 6664 N8 in TRS 900<br />
REMARK 5<br />
REMARK 6 Total charge on this protein: -1.0000 e<br />
REMARK 6<br />
<br />
If all you care about is the atom number, you can probably regexp match on the 'in' field, something like<br />
<br />
>>> re.compile('REMARK 5 *(\d)* \w* in').findall(text) # Text contains PQR output string<br />
['6657', '6658', '6659', '6660', '6661', '6662', '6663', '6664']<br />
<br />
Or you can grab any other useful information - I'd say that using a regular expression like this would be the best option to ensure you don't get false positives. <br />
"""<br />
f = file(fname)<br />
unassigned = re.compile('REMARK 5 *(\d+) \w* in').findall(f.read()) # Text contains PQR output string<br />
f.close()<br />
return '+'.join(unassigned)<br />
<br />
<br />
def generateApbsInputFile(self):<br />
if self.checkInput(silent=False):<br />
#<br />
# set up our variables<br />
#<br />
pqr_filename = self.getPqrFilename()<br />
<br />
grid_points = [int(getattr(self,'grid_points_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
cglen = [float(getattr(self,'grid_coarse_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
fglen = [float(getattr(self,'grid_fine_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
cent = [float(getattr(self,'grid_center_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
<br />
apbs_mode = self.apbs_mode.getvalue()<br />
if apbs_mode == 'Nonlinear Poisson-Boltzmann Equation':<br />
apbs_mode = 'npbe'<br />
else:<br />
apbs_mode = 'lpbe'<br />
<br />
bcflmap = {'Zero': 'zero',<br />
'Single DH sphere': 'sdh',<br />
'Multiple DH spheres': 'mdh',<br />
#'Focusing': 'focus',<br />
}<br />
bcfl = bcflmap[self.bcfl.getvalue()]<br />
<br />
chgmmap = {'Linear':'spl0',<br />
'Cubic B-splines':'spl2',<br />
'Quintic B-splines':'spl4',<br />
}<br />
chgm = chgmmap[self.chgm.getvalue()]<br />
<br />
srfmmap = {'Mol surf for epsilon; inflated VdW for kappa, no smoothing':'mol',<br />
'Same, but with harmonic average smoothing':'smol',<br />
'Cubic spline':'spl2',<br />
'Similar to cubic spline, but with 7th order polynomial':'spl4',}<br />
<br />
srfm = srfmmap[self.srfm.getvalue()]<br />
<br />
dx_filename = self.pymol_generated_dx_filename.getvalue()<br />
if dx_filename.endswith('.dx'):<br />
dx_filename = dx_filename[:-3]<br />
apbs_input_text = getApbsInputFile(pqr_filename,<br />
grid_points,<br />
cglen,<br />
fglen,<br />
cent,<br />
apbs_mode,<br />
bcfl,<br />
float(self.ion_plus_one_conc.getvalue()), float(self.ion_plus_one_rad.getvalue()),<br />
float(self.ion_minus_one_conc.getvalue()), float(self.ion_minus_one_rad.getvalue()),<br />
float(self.ion_plus_two_conc.getvalue()), float(self.ion_plus_two_rad.getvalue()),<br />
float(self.ion_minus_two_conc.getvalue()), float(self.ion_minus_two_rad.getvalue()),<br />
float(self.interior_dielectric.getvalue()), float(self.solvent_dielectric.getvalue()),<br />
chgm,<br />
srfm,<br />
float(self.solvent_radius.getvalue()),<br />
float(self.system_temp.getvalue()),<br />
float(self.sdens.getvalue()),<br />
dx_filename,<br />
)<br />
if DEBUG:<br />
print "GOT THE APBS INPUT FILE"<br />
<br />
#<br />
# write out the input text<br />
#<br />
try:<br />
f = file(self.pymol_generated_in_filename.getvalue(),'w')<br />
f.write(apbs_input_text)<br />
f.close()<br />
except IOError:<br />
print "ERROR: Got the input file from APBS, but failed when trying to write to %s" % self.pymol_generated_in_filename.getvalue()<br />
return True<br />
else:<br />
self.checkInput()<br />
return False<br />
<br />
def checkInput(self,silent=False):<br />
"""If silent is True, we'll just return a True/False value<br />
"""<br />
if not silent:<br />
def show_error(message):<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = message,<br />
)<br />
junk = error_dialog.activate()<br />
else:<br />
def show_error(message):<br />
pass<br />
<br />
#<br />
# First, check to make sure we have valid locations for apbs and psize<br />
#<br />
if not self.binary.valid():<br />
show_error('Please set the APBS binary location')<br />
return False<br />
#<br />
# If the path to psize is not correct, that's fine .. we'll<br />
# do the calculations ourself.<br />
#<br />
<br />
#if not self.psize.valid():<br />
# show_error("Please set APBS's psize location")<br />
# return False<br />
<br />
#<br />
# Now check the temporary filenames<br />
#<br />
if self.radiobuttons.getvalue() != 'Use another PQR':<br />
if not self.pymol_generated_pqr_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated PQR file')<br />
return False<br />
elif not self.pqr_to_use.valid():<br />
show_error('Please select a valid pqr file or tell\nPyMOL to generate one')<br />
return False<br />
if not self.pymol_generated_pdb_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated PDB file')<br />
return False<br />
if not self.pymol_generated_dx_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated DX file')<br />
return False<br />
if not self.pymol_generated_in_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated APBS input file')<br />
return False<br />
if not self.map.getvalue():<br />
show_error('Please choose a name for the generated map.')<br />
return False<br />
<br />
<br />
#<br />
# Now, the ions<br />
#<br />
for sign in 'plus minus'.split():<br />
for value in 'one two'.split():<br />
for parm in 'conc rad'.split():<br />
if not getattr(self,'ion_%s_%s_%s'%(sign,value,parm)).valid():<br />
show_error('Please correct Ion concentrations and radii')<br />
return False<br />
#<br />
# Now the grid<br />
#<br />
for grid_type in 'coarse fine points center'.split():<br />
for coord in 'x y z'.split():<br />
if not getattr(self,'grid_%s_%s'%(grid_type,coord)).valid():<br />
show_error('Please correct grid dimensions\nby clicking on the "Set grid" button')<br />
return False<br />
<br />
#<br />
# Now other easy things<br />
#<br />
for (message, thing) in (('solvent dielectric',self.solvent_dielectric),<br />
('protein dielectric',self.interior_dielectric),<br />
('solvent radius',self.solvent_radius),<br />
('system temperature',self.system_temp),<br />
('sdens',self.sdens),<br />
):<br />
if not thing.valid():<br />
show_error('Please correct %s'%message)<br />
return False<br />
<br />
return True<br />
<br />
<br />
def generatePdb2pqrPqrFile(self,silent=False):<br />
"""use pdb2pqr to generate a pqr file<br />
"""<br />
if not silent:<br />
def show_error(message):<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = message,<br />
)<br />
junk = error_dialog.activate()<br />
else:<br />
def show_error(message):<br />
pass<br />
<br />
#<br />
# First, generate a PDB file<br />
#<br />
pdb_filename = self.pymol_generated_pdb_filename.getvalue()<br />
try:<br />
f = file(pdb_filename,'w')<br />
f.close()<br />
except:<br />
show_error('Please set a temporary PDB file location that you have permission to edit')<br />
return False<br />
# copied from WLD code<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
self.fixColumns(sel)<br />
pymol.cmd.save(pdb_filename,sel)<br />
self.cleanupGeneratedPdbOrPqrFile(pdb_filename)<br />
<br />
#<br />
# Now, generate a PQR file<br />
#<br />
## command_line = '%s %s %s %s'%(self.pdb2pqr.getvalue(),<br />
## self.pdb2pqr_options.getvalue(),<br />
## pdb_filename,<br />
## self.pymol_generated_pqr_filename.getvalue(),<br />
## )<br />
## print "RAN",command_line<br />
## result = os.system(command_line)<br />
#<br />
# We have to be a little cute about args, because pdb2pqr_options could have several options in it.<br />
args = '%s %s %s' %(self.pdb2pqr_options.getvalue(),<br />
pdb_filename,<br />
self.pymol_generated_pqr_filename.getvalue(),<br />
) <br />
(retval,progout) = run(self.pdb2pqr.getvalue(),args)<br />
<br />
<br />
if retval != 0:<br />
show_error('Could not run pdb2pqr: %s %s\n\n%s'%(self.pdb2pqr.getvalue(),<br />
args,<br />
progout)<br />
)<br />
return False<br />
self.cleanupGeneratedPdbOrPqrFile(self.pymol_generated_pqr_filename.getvalue())<br />
unassigned_atoms = self.getUnassignedAtomsFromPqr(self.pymol_generated_pqr_filename.getvalue())<br />
if unassigned_atoms:<br />
pymol.cmd.select('unassigned','ID %s'%unassigned_atoms)<br />
message_text = "Unable to assign parameters for the %s atoms in selection 'unassigned'.\nPlease either remove these unassigned atoms and re-start the calculation\nor fix their parameters in the generated PQR file and run the calculation\nusing the modified PQR file (select 'Use another PQR' in 'Main')."%len(unassigned_atoms.split('+'))<br />
print "Unassigned atom IDs",unassigned_atoms<br />
show_error(message_text)<br />
return False<br />
return True<br />
<br />
<br />
def generatePymolPqrFile(self):<br />
"""generate a pqr file from pymol<br />
<br />
This will also call through to champ to set the Hydrogens and charges<br />
if it needs to. If it does that, it may change the value self.selection<br />
to take the new Hydrogens into account.<br />
<br />
To make it worse, APBS seems to freak out when there are chain ids. So,<br />
this gets rid of the chain ids.<br />
<br />
"""<br />
# CHAMP will break in many cases if retain_order is set. So,<br />
# we unset it here and reset it later. Note that it's fine to<br />
# reset it before things are written out.<br />
ret_order = pymol.cmd.get('retain_order')<br />
pymol.cmd.set('retain_order',0)<br />
<br />
# WLD<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
<br />
pqr_filename = self.getPqrFilename()<br />
try:<br />
f = file(pqr_filename,'w')<br />
f.close()<br />
except:<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "Could not write PQR file.\nPlease check that temporary PQR filename is valid.",<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
<br />
# PyMOL + champ == pqr<br />
from chempy.champ import assign<br />
if self.radiobuttons.getvalue() == 'Use PyMOL generated PQR and PyMOL generated Hydrogens and termini':<br />
pymol.cmd.remove('hydro and %s'%sel)<br />
assign.missing_c_termini(sel)<br />
assign.formal_charges(sel)<br />
pymol.cmd.h_add(sel)<br />
# WLD (code now unnecessary)<br />
# new_hydros = '(hydro and neighbor %s)'%sel<br />
# sel = '%s or %s' % (sel,new_hydros)<br />
assign.amber99(sel)<br />
pymol.cmd.set('retain_order',ret_order)<br />
<br />
# WLD (code now unnecessary)<br />
# if not self.selection.getvalue() in '(all) all'.split():<br />
# self.selection.setvalue(sel)<br />
<br />
#<br />
# Get rid of chain information<br />
#<br />
# WLD -- PyMOL now does this automatically with PQR files <br />
# pymol.cmd.alter(sel,'chain = ""')<br />
self.fixColumns(sel)<br />
pymol.cmd.save(pqr_filename,sel)<br />
self.cleanupGeneratedPdbOrPqrFile(pqr_filename)<br />
missed_count = pymol.cmd.count_atoms("("+sel+") and flag 23")<br />
if missed_count > 0:<br />
pymol.cmd.select("unassigned","("+sel+") and flag 23")<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "Unable to assign parameters for the %s atoms in selection 'unassigned'.\nPlease either remove these unassigned atoms and re-start the calculation\nor fix their parameters in the generated PQR file and run the calculation\nusing the modified PQR file (select 'Use another PQR' in 'Main')."%missed_count,<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
return True<br />
<br />
<br />
############################################################<br />
############################################################<br />
############################################################<br />
## ##<br />
## PmwExtensions ##<br />
## ##<br />
############################################################<br />
############################################################<br />
############################################################<br />
<br />
"""<br />
This contains all of the visualization groups that we'll use for our<br />
PMW interface.<br />
"""<br />
<br />
#<br />
# Generically useful PMW extensions<br />
<br />
import os,fnmatch,time<br />
import Tkinter,Pmw<br />
#Pmw.setversion("0.8.5")<br />
<br />
#<br />
# The classes PmwFileDialog and PmwExistingFileDialog and the _errorpop function<br />
# are taken from the Pmw contrib directory. The attribution given in that file<br />
# is:<br />
################################################################################<br />
# Filename dialogs using Pmw<br />
#<br />
# (C) Rob W.W. Hooft, Nonius BV, 1998<br />
#<br />
# Modifications:<br />
#<br />
# J. Willem M. Nissink, Cambridge Crystallographic Data Centre, 8/2002<br />
# Added optional information pane at top of dialog; if option<br />
# 'info' is specified, the text given will be shown (in blue).<br />
# Modified example to show both file and directory-type dialog<br />
#<br />
# No Guarantees. Distribute Freely. <br />
# Please send bug-fixes/patches/features to <r.hooft@euromail.com><br />
#<br />
################################################################################<br />
<br />
def _errorpop(master,text):<br />
d=Pmw.MessageDialog(master,<br />
title="Error", <br />
message_text=text,<br />
buttons=("OK",))<br />
d.component('message').pack(ipadx=15,ipady=15)<br />
d.activate()<br />
d.destroy()<br />
<br />
class PmwFileDialog(Pmw.Dialog):<br />
"""File Dialog using Pmw"""<br />
def __init__(self, parent = None, **kw):<br />
# Define the megawidget options.<br />
optiondefs = (<br />
('filter', '*', self.newfilter),<br />
('directory', os.getcwd(), self.newdir),<br />
('filename', '', self.newfilename),<br />
('historylen',10, None),<br />
('command', None, None),<br />
('info', None, None),<br />
)<br />
self.defineoptions(kw, optiondefs)<br />
# Initialise base class (after defining options).<br />
Pmw.Dialog.__init__(self, parent)<br />
<br />
self.withdraw()<br />
<br />
# Create the components.<br />
interior = self.interior()<br />
<br />
if self['info'] is not None:<br />
rowoffset=1<br />
dn = self.infotxt()<br />
dn.grid(row=0,column=0,columnspan=2,padx=3,pady=3)<br />
else:<br />
rowoffset=0<br />
<br />
dn = self.mkdn()<br />
dn.grid(row=0+rowoffset,column=0,columnspan=2,padx=3,pady=3)<br />
del dn<br />
<br />
# Create the directory list component.<br />
dnb = self.mkdnb()<br />
dnb.grid(row=1+rowoffset,column=0,sticky='news',padx=3,pady=3)<br />
del dnb<br />
<br />
# Create the filename list component.<br />
fnb = self.mkfnb()<br />
fnb.grid(row=1+rowoffset,column=1,sticky='news',padx=3,pady=3)<br />
del fnb<br />
<br />
# Create the filter entry<br />
ft = self.mkft()<br />
ft.grid(row=2+rowoffset,column=0,columnspan=2,padx=3,pady=3)<br />
del ft<br />
<br />
# Create the filename entry<br />
fn = self.mkfn()<br />
fn.grid(row=3+rowoffset,column=0,columnspan=2,padx=3,pady=3)<br />
fn.bind('<Return>',self.okbutton)<br />
del fn<br />
<br />
# Buttonbox already exists<br />
bb=self.component('buttonbox')<br />
bb.add('OK',command=self.okbutton)<br />
bb.add('Cancel',command=self.cancelbutton)<br />
del bb<br />
<br />
Pmw.alignlabels([self.component('filename'),<br />
self.component('filter'),<br />
self.component('dirname')])<br />
<br />
def infotxt(self):<br />
""" Make information block component at the top """<br />
return self.createcomponent(<br />
'infobox',<br />
(), None,<br />
Tkinter.Label, (self.interior(),),<br />
width=51,<br />
relief='groove',<br />
foreground='darkblue',<br />
justify='left',<br />
text=self['info']<br />
)<br />
<br />
def mkdn(self):<br />
"""Make directory name component"""<br />
return self.createcomponent(<br />
'dirname',<br />
(), None,<br />
Pmw.ComboBox, (self.interior(),),<br />
entryfield_value=self['directory'],<br />
entryfield_entry_width=40,<br />
entryfield_validate=self.dirvalidate,<br />
selectioncommand=self.setdir,<br />
labelpos='w',<br />
label_text='Directory:')<br />
<br />
def mkdnb(self):<br />
"""Make directory name box"""<br />
return self.createcomponent(<br />
'dirnamebox',<br />
(), None,<br />
Pmw.ScrolledListBox, (self.interior(),),<br />
label_text='directories',<br />
labelpos='n',<br />
hscrollmode='none',<br />
dblclickcommand=self.selectdir)<br />
<br />
def mkft(self):<br />
"""Make filter"""<br />
return self.createcomponent(<br />
'filter',<br />
(), None,<br />
Pmw.ComboBox, (self.interior(),),<br />
entryfield_value=self['filter'],<br />
entryfield_entry_width=40,<br />
selectioncommand=self.setfilter,<br />
labelpos='w',<br />
label_text='Filter:')<br />
<br />
def mkfnb(self):<br />
"""Make filename list box"""<br />
return self.createcomponent(<br />
'filenamebox',<br />
(), None,<br />
Pmw.ScrolledListBox, (self.interior(),),<br />
label_text='files',<br />
labelpos='n',<br />
hscrollmode='none',<br />
selectioncommand=self.singleselectfile,<br />
dblclickcommand=self.selectfile)<br />
<br />
def mkfn(self):<br />
"""Make file name entry"""<br />
return self.createcomponent(<br />
'filename',<br />
(), None,<br />
Pmw.ComboBox, (self.interior(),),<br />
entryfield_value=self['filename'],<br />
entryfield_entry_width=40,<br />
entryfield_validate=self.filevalidate,<br />
selectioncommand=self.setfilename,<br />
labelpos='w',<br />
label_text='Filename:')<br />
<br />
def dirvalidate(self,string):<br />
if os.path.isdir(string):<br />
return Pmw.OK<br />
else:<br />
return Pmw.PARTIAL<br />
<br />
def filevalidate(self,string):<br />
if string=='':<br />
return Pmw.PARTIAL<br />
elif os.path.isfile(string):<br />
return Pmw.OK<br />
elif os.path.exists(string):<br />
return Pmw.PARTIAL<br />
else:<br />
return Pmw.OK<br />
<br />
def okbutton(self):<br />
"""OK action: user thinks he has input valid data and wants to<br />
proceed. This is also called by <Return> in the filename entry"""<br />
fn=self.component('filename').get()<br />
self.setfilename(fn)<br />
if self.validate(fn):<br />
self.canceled=0<br />
self.deactivate()<br />
<br />
def cancelbutton(self):<br />
"""Cancel the operation"""<br />
self.canceled=1<br />
self.deactivate()<br />
<br />
def tidy(self,w,v):<br />
"""Insert text v into the entry and at the top of the list of <br />
the combobox w, remove duplicates"""<br />
if not v:<br />
return<br />
entry=w.component('entry')<br />
entry.delete(0,'end')<br />
entry.insert(0,v)<br />
list=w.component('scrolledlist')<br />
list.insert(0,v)<br />
index=1<br />
while index<list.index('end'):<br />
k=list.get(index)<br />
if k==v or index>self['historylen']:<br />
list.delete(index)<br />
else:<br />
index=index+1<br />
w.checkentry()<br />
<br />
def setfilename(self,value):<br />
if not value:<br />
return<br />
value=os.path.join(self['directory'],value)<br />
dir,fil=os.path.split(value)<br />
self.configure(directory=dir,filename=value)<br />
<br />
c=self['command']<br />
if callable(c):<br />
c()<br />
<br />
def newfilename(self):<br />
"""Make sure a newly set filename makes it into the combobox list"""<br />
self.tidy(self.component('filename'),self['filename'])<br />
<br />
def setfilter(self,value):<br />
self.configure(filter=value)<br />
<br />
def newfilter(self):<br />
"""Make sure a newly set filter makes it into the combobox list"""<br />
self.tidy(self.component('filter'),self['filter'])<br />
self.fillit()<br />
<br />
def setdir(self,value):<br />
self.configure(directory=value)<br />
<br />
def newdir(self):<br />
"""Make sure a newly set dirname makes it into the combobox list"""<br />
self.tidy(self.component('dirname'),self['directory'])<br />
self.fillit()<br />
<br />
def singleselectfile(self):<br />
"""Single click in file listbox. Move file to "filename" combobox"""<br />
cs=self.component('filenamebox').curselection()<br />
if cs!=():<br />
value=self.component('filenamebox').get(cs)<br />
self.setfilename(value)<br />
<br />
def selectfile(self):<br />
"""Take the selected file from the filename, normalize it, and OK"""<br />
self.singleselectfile()<br />
value=self.component('filename').get()<br />
self.setfilename(value)<br />
if value:<br />
self.okbutton()<br />
<br />
def selectdir(self):<br />
"""Take selected directory from the dirnamebox into the dirname"""<br />
cs=self.component('dirnamebox').curselection()<br />
if cs!=():<br />
value=self.component('dirnamebox').get(cs)<br />
dir=self['directory']<br />
if not dir:<br />
dir=os.getcwd()<br />
if value:<br />
if value=='..':<br />
dir=os.path.split(dir)[0]<br />
else:<br />
dir=os.path.join(dir,value)<br />
self.configure(directory=dir)<br />
self.fillit()<br />
<br />
def askfilename(self,directory=None,filter=None):<br />
"""The actual client function. Activates the dialog, and<br />
returns only after a valid filename has been entered <br />
(return value is that filename) or when canceled (return <br />
value is None)"""<br />
if directory!=None:<br />
self.configure(directory=directory)<br />
if filter!=None:<br />
self.configure(filter=filter)<br />
self.fillit()<br />
self.canceled=1 # Needed for when user kills dialog window<br />
self.activate()<br />
if self.canceled:<br />
return None<br />
else:<br />
return self.component('filename').get()<br />
<br />
lastdir=""<br />
lastfilter=None<br />
lasttime=0<br />
def fillit(self):<br />
"""Get the directory list and show it in the two listboxes"""<br />
# Do not run unnecesarily<br />
if self.lastdir==self['directory'] and self.lastfilter==self['filter'] and self.lasttime>os.stat(self.lastdir)[8]:<br />
return<br />
self.lastdir=self['directory']<br />
self.lastfilter=self['filter']<br />
self.lasttime=time.time()<br />
dir=self['directory']<br />
if not dir:<br />
dir=os.getcwd()<br />
dirs=['..']<br />
files=[]<br />
try:<br />
fl=os.listdir(dir)<br />
fl.sort()<br />
except os.error,arg:<br />
if arg[0] in (2,20):<br />
return<br />
raise<br />
for f in fl:<br />
if os.path.isdir(os.path.join(dir,f)):<br />
dirs.append(f)<br />
else:<br />
filter=self['filter']<br />
if not filter:<br />
filter='*'<br />
if fnmatch.fnmatch(f,filter):<br />
files.append(f)<br />
self.component('filenamebox').setlist(files)<br />
self.component('dirnamebox').setlist(dirs)<br />
<br />
def validate(self,filename):<br />
"""Validation function. Should return 1 if the filename is valid, <br />
0 if invalid. May pop up dialogs to tell user why. Especially <br />
suited to subclasses: i.e. only return 1 if the file does/doesn't <br />
exist"""<br />
return 1<br />
<br />
<br />
class PmwExistingFileDialog(PmwFileDialog):<br />
def filevalidate(self,string):<br />
if os.path.isfile(string):<br />
return Pmw.OK<br />
else:<br />
return Pmw.PARTIAL<br />
<br />
def validate(self,filename):<br />
if os.path.isfile(filename):<br />
return 1<br />
elif os.path.exists(filename):<br />
_errorpop(self.interior(),"This is not a plain file")<br />
return 0<br />
else:<br />
_errorpop(self.interior(),"Please select an existing file")<br />
return 0<br />
<br />
class FileDialogButtonClassFactory:<br />
def get(fn,filter='*'):<br />
"""This returns a FileDialogButton class that will<br />
call the specified function with the resulting file.<br />
"""<br />
class FileDialogButton(Tkinter.Button):<br />
# This is just an ordinary button with special colors.<br />
<br />
def __init__(self, master=None, cnf={}, **kw):<br />
'''when we get a file, we call fn(filename)'''<br />
self.fn = fn<br />
self.__toggle = 0<br />
apply(Tkinter.Button.__init__, (self, master, cnf), kw)<br />
self.configure(command=self.set)<br />
def set(self):<br />
fd = PmwFileDialog(self.master,filter=filter)<br />
fd.title('Please choose a file')<br />
n=fd.askfilename()<br />
if n is not None:<br />
self.fn(n)<br />
return FileDialogButton<br />
get = staticmethod(get)<br />
<br />
############################################################<br />
############################################################<br />
############################################################<br />
## ##<br />
## PmwGroups ##<br />
## ##<br />
############################################################<br />
############################################################<br />
############################################################<br />
class VisualizationGroup(Pmw.Group):<br />
def __init__(self,*args,**kwargs):<br />
my_options = 'visgroup_num'.split()<br />
for option in my_options:<br />
# use these options as attributes of this class<br />
# and remove them from the kwargs dict before<br />
# passing on to Pmw.Group.__init__().<br />
setattr(self,option,kwargs.pop(option))<br />
kwargs['tag_text'] = kwargs['tag_text'] + ' (%s)'%self.visgroup_num<br />
Pmw.Group.__init__(self,*args,**kwargs)<br />
self.refresh()<br />
self.show_ms = False<br />
self.show_pi = False<br />
self.show_ni = False<br />
def refresh(self):<br />
things_to_kill = 'error_label update_buttonbox mm_group ms_group pi_group ni_group'.split()<br />
for thing in things_to_kill:<br />
try:<br />
getattr(self,thing).destroy()<br />
#print "destroyed",thing<br />
except AttributeError:<br />
#print "couldn't destroy",thing<br />
<br />
# note: this attributeerror will also hit if getattr(self,thing) misses.<br />
# another note: both halves of the if/else make an update_buttonbox.<br />
# if you rename the one in the top half to something else, you'll cause nasty Pmw errors.<br />
pass<br />
if [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'] and [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule']:<br />
self.mm_group = Pmw.Group(self.interior(),tag_text = 'Maps and Molecules')<br />
self.map = Pmw.OptionMenu(self.mm_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Map',<br />
items = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'],<br />
)<br />
self.map.pack(padx=4,side=LEFT)<br />
<br />
self.molecule = Pmw.OptionMenu(self.mm_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Molecule',<br />
items = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule'],<br />
)<br />
self.molecule.pack(padx=4,side=LEFT)<br />
self.update_buttonbox = Pmw.ButtonBox(self.mm_group.interior(), padx=0)<br />
self.update_buttonbox.pack(side=LEFT)<br />
self.update_buttonbox.add('Update',command=self.refresh)<br />
self.mm_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=TOP)<br />
<br />
self.ms_group = Pmw.Group(self.interior(),tag_text='Molecular Surface')<br />
self.ms_buttonbox = Pmw.ButtonBox(self.ms_group.interior(), padx=0)<br />
self.ms_buttonbox.pack()<br />
self.ms_buttonbox.add('Show',command=self.showMolSurface)<br />
self.ms_buttonbox.add('Hide',command=self.hideMolSurface)<br />
self.ms_buttonbox.add('Update',command=self.updateMolSurface)<br />
self.ms_buttonbox.alignbuttons()<br />
self.surface_solvent = IntVar()<br />
self.surface_solvent.set(APBSTools2.defaults['surface_solvent'])<br />
self.sol_checkbutton = Checkbutton(self.ms_group.interior(),<br />
text = "Solvent accessible surface",<br />
variable = self.surface_solvent)<br />
self.sol_checkbutton.pack() <br />
self.potential_at_sas = IntVar()<br />
self.potential_at_sas.set(APBSTools2.defaults['potential_at_sas'])<br />
self.pot_checkbutton = Checkbutton(self.ms_group.interior(),<br />
text = "Color by potential on sol. acc. surf.",<br />
variable = self.potential_at_sas)<br />
self.pot_checkbutton.pack()<br />
self.mol_surf_low = Pmw.Counter(self.ms_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Low',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = -1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real'},<br />
)<br />
self.mol_surf_middle = Pmw.Counter(self.ms_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Middle',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = 0,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real'}<br />
)<br />
self.mol_surf_high = Pmw.Counter(self.ms_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'High',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = 1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real'}<br />
)<br />
bars = (self.mol_surf_low,self.mol_surf_middle,self.mol_surf_high)<br />
Pmw.alignlabels(bars)<br />
for bar in bars: bar.pack(side=LEFT)<br />
self.ms_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=LEFT)<br />
<br />
self.pi_group = Pmw.Group(self.interior(),tag_text='Positive Isosurface')<br />
self.pi_buttonbox = Pmw.ButtonBox(self.pi_group.interior(), padx=0)<br />
self.pi_buttonbox.pack()<br />
self.pi_buttonbox.add('Show',command=self.showPosSurface)<br />
self.pi_buttonbox.add('Hide',command=self.hidePosSurface)<br />
self.pi_buttonbox.add('Update',command=self.updatePosSurface)<br />
self.pi_buttonbox.alignbuttons()<br />
self.pos_surf_val = Pmw.Counter(self.pi_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Contour (kT/e)',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = 1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real', 'min':0}<br />
)<br />
self.pos_surf_val.pack(side=LEFT)<br />
self.pi_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=LEFT)<br />
<br />
self.ni_group = Pmw.Group(self.interior(),tag_text='Negative Isosurface')<br />
self.ni_buttonbox = Pmw.ButtonBox(self.ni_group.interior(), padx=0)<br />
self.ni_buttonbox.pack()<br />
self.ni_buttonbox.add('Show',command=self.showNegSurface)<br />
self.ni_buttonbox.add('Hide',command=self.hideNegSurface)<br />
self.ni_buttonbox.add('Update',command=self.updateNegSurface)<br />
self.ni_buttonbox.alignbuttons()<br />
self.neg_surf_val = Pmw.Counter(self.ni_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Contour (kT/e)',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = -1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real', 'max':0}<br />
)<br />
self.neg_surf_val.pack(side=LEFT)<br />
self.ni_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=LEFT)<br />
<br />
else:<br />
self.error_label = Tkinter.Label(self.interior(),<br />
pady = 10,<br />
justify=LEFT,<br />
text = '''You must have at least a molecule and a map loaded.<br />
If you have a molecule and a map loaded, please click "Update"''',<br />
)<br />
self.error_label.pack()<br />
self.update_buttonbox = Pmw.ButtonBox(self.interior(), padx=0)<br />
self.update_buttonbox.pack()<br />
self.update_buttonbox.add('Update',command=self.refresh)<br />
<br />
def showMolSurface(self):<br />
self.updateMolSurface()<br />
<br />
def hideMolSurface(self):<br />
pymol.cmd.hide('surface',self.molecule.getvalue())<br />
<br />
def getRampName(self):<br />
#return 'e_lvl'<br />
idx = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule'].index(self.molecule.getvalue())<br />
return '_'.join(('e_lvl',str(idx),str(self.visgroup_num)))<br />
<br />
def getIsoPosName(self):<br />
idx = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'].index(self.map.getvalue())<br />
return '_'.join(('iso_pos',str(idx),str(self.visgroup_num)))<br />
<br />
def getIsoNegName(self):<br />
idx = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'].index(self.map.getvalue())<br />
return '_'.join(('iso_neg',str(idx),str(self.visgroup_num)))<br />
<br />
def updateMolSurface(self):<br />
molecule_name = self.molecule.getvalue()<br />
ramp_name = self.getRampName()<br />
map_name = self.map.getvalue()<br />
low = float(self.mol_surf_low.getvalue())<br />
mid = float(self.mol_surf_middle.getvalue())<br />
high = float(self.mol_surf_high.getvalue())<br />
range = [low,mid,high]<br />
print " APBS Tools: range is",range<br />
pymol.cmd.delete(ramp_name)<br />
pymol.cmd.ramp_new(ramp_name,map_name,range)<br />
pymol.cmd.set('surface_color',ramp_name,molecule_name)<br />
if self.surface_solvent.get()==1:<br />
pymol.cmd.set('surface_solvent',1,molecule_name)<br />
pymol.cmd.set('surface_ramp_above_mode',0,molecule_name)<br />
else:<br />
pymol.cmd.set('surface_solvent',0,molecule_name)<br />
pymol.cmd.set('surface_ramp_above_mode',self.potential_at_sas.get(),molecule_name)<br />
pymol.cmd.show('surface',molecule_name)<br />
pymol.cmd.refresh()<br />
pymol.cmd.recolor(molecule_name)<br />
<br />
def showPosSurface(self):<br />
self.updatePosSurface()<br />
def hidePosSurface(self):<br />
pymol.cmd.hide('everything',self.getIsoPosName())<br />
def updatePosSurface(self):<br />
pymol.cmd.delete(self.getIsoPosName())<br />
pymol.cmd.isosurface(self.getIsoPosName(),self.map.getvalue(),float(self.pos_surf_val.getvalue()))<br />
pymol.cmd.color('blue',self.getIsoPosName())<br />
pymol.cmd.show('everything',self.getIsoPosName())<br />
def showNegSurface(self):<br />
self.updateNegSurface()<br />
def hideNegSurface(self):<br />
pymol.cmd.hide('everything',self.getIsoNegName())<br />
def updateNegSurface(self):<br />
pymol.cmd.delete(self.getIsoNegName())<br />
pymol.cmd.isosurface(self.getIsoNegName(),self.map.getvalue(),float(self.neg_surf_val.getvalue()))<br />
pymol.cmd.color('red',self.getIsoNegName())<br />
pymol.cmd.show('everything',self.getIsoNegName())<br />
<br />
<br />
</source><br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3161User:Mglerner2010-01-28T20:14:06Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= Check out a new pre-release version of the PyMOL-APBS plugin! =<br />
<br />
== New Features ==<br />
<br />
I've been working with Jason Vertrees on a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are three big advantages of the new version:<br />
<br />
#. It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
#. It allows you to call through to PDB2PQR directly.<br />
#. It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
<br />
I've also upped the default maximum allowed memory since typical users have bigger and faster computers these days.<br />
<br />
A slightly longer list of changes is included below. <br />
<br />
== How to get it ==<br />
<br />
There are two ways to get the new plugin<br />
<br />
#. If you have subversion installed,<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
<br />
#. Copy the text directly from http://pymolwiki.org/index.php/User:Mglerner and put it in a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
Note that the plugin will be installed as "APBS Tools2" so that you can continue to use your old version.<br />
<br />
== Longer feature list ==<br />
<br />
* The ability to call through directly to PDB2PQR<br />
* More modern apbs input files<br />
* Two visualization panels. It's often quite useful to look at two different electrostatic potentials at once. It's also quite useful to look at electrostatic potentials mapped onto two different surfaces at once. Multiple visualization panels makes this a snap: just set up one surface on panel 1 and another surface on panel 2.<br />
* Fixes several bugs that caused crashes on both OS X and Linux systems<br />
* Increased maximum allowed memory<br />
* Switch from os.system to subprocess for running external programs<br />
* Deals with paths on Windows properly<br />
* Gives better diagnostic information so that PyMOL/APBS developers can find bugs more easily<br />
* Lots of internal code cleanup<br />
<br />
== Plugin code ==<br />
<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
<br />
# TODO:<br />
# - provide diff for pdb2pqr freemol<br />
# - use remove_alt to count alternate atom locations and warn the user<br />
#<br />
# - Note to users that they should remove freemol's pymol.exe on OS X.<br />
<br />
### (all) and resn glu and resi 154+157<br />
### flag ignore, atom-selection, clear<br />
<br />
# APBS TOOLS Copyright Notice<br />
# ============================<br />
#<br />
# The APBS TOOLS source code is copyrighted, but you can freely use and<br />
# copy it as long as you don't change or remove any of the copyright<br />
# notices.<br />
#<br />
# ----------------------------------------------------------------------<br />
# APBS TOOLS is Copyright (C) 2009 by Michael G. Lerner<br />
#<br />
# All Rights Reserved<br />
#<br />
# Permission to use, copy, modify, distribute, and distribute modified<br />
# versions of this software and its documentation for any purpose and<br />
# without fee is hereby granted, provided that the above copyright<br />
# notice appear in all copies and that both the copyright notice and<br />
# this permission notice appear in supporting documentation, and that<br />
# the name of Michael G. Lerner not be used in advertising or publicity<br />
# pertaining to distribution of the software without specific, written<br />
# prior permission.<br />
#<br />
# MICHAEL G. LERNER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS<br />
# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND<br />
# FITNESS. IN NO EVENT SHALL MICHAEL G. LERNER BE LIABLE FOR ANY<br />
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER<br />
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF<br />
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN<br />
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.<br />
# ----------------------------------------------------------------------<br />
<br />
"""<br />
<br />
A NOTE TO USERS:<br />
<br />
You can change the default locations for the APBS and PDB2PQR binaries<br />
as well as the default temporary file directory below. If you set them<br />
in this file, they will be preserved each time you load up the<br />
plugin. Scroll down to the section entitled "Global config variables"<br />
(no quotes) below.<br />
<br />
A NOTE TO OTHER DEVELOPERS:<br />
<br />
I understand that I'm giving this code away for Free, and that there's<br />
not a ton of great sample PyMOL plugin code out there, so you're<br />
certainly encouraged to use this as a template. However, please<br />
acknowledge me in some way if you do (somewhere in the comments if you<br />
only use a little bit of code or something more if you use a lot).<br />
<br />
Thanks.<br />
<br />
-Michael<br />
<br />
Features under consideration:<br />
<br />
- Use 'acc' to calculate solvent-accessible surface areas. We'll use<br />
the PyMOL 'standard' method and store this data as B-factors.<br />
- Show the field lines. Relevant code from menu.py:<br />
<br />
def map_gradient(self_cmd, sele):<br />
return [[ 2, 'Gradient:', '' ],<br />
[ 1, 'default' , 'cmd.gradient("'+sele+'_grad","'+sele+'");cmd.ramp_new("'+sele+<br />
'_grad_ramp","'+sele+'");cmd.color("'+sele+'_grad_ramp","'+sele+'_grad");' ]<br />
]<br />
<br />
Known hacks:<br />
<br />
<br />
1. (code in execute() )There's a bug in the version of APBS shipped<br />
with Ubuntu 9.10 (version 1.1.0) that causes the name to become<br />
foo-PE0.dx instead of foo.dx. This would normally only occur in<br />
mg-para calcs or MPI versions of apbs. It's clearly bug-possible,<br />
but we will check for foo-PE0 if we can't find foo.dx.<br />
<br />
2. We look for dylib errors in the APBS executable that's shipped with<br />
freemol on OS X. Code in get_default()'s verify().<br />
<br />
"""<br />
from __future__ import division<br />
from __future__ import generators<br />
<br />
global DEBUG<br />
DEBUG = 1<br />
<br />
APBS_DEFAULT=True<br />
<br />
import os,math,re<br />
import string<br />
import Tkinter<br />
from Tkinter import *<br />
import Pmw<br />
import distutils.spawn # used for find_executable<br />
import traceback<br />
import pymol<br />
<br />
#<br />
# Global config variables<br />
#<br />
# To change the default locations, change these to something like<br />
# APBS_BINARY_LOCATION = '/opt/bin/apbs'<br />
#<br />
APBS_BINARY_LOCATION = None<br />
APBS_PSIZE_LOCATION = None<br />
APBS_PDB2PQR_LOCATION = None<br />
TEMPORARY_FILE_DIR = None<br />
<br />
apbs_plea = ("IMPORTANT REQUEST: If you have not already done so, please register\n"<br />
"your use of the open-source Adaptive Poisson-Boltzmann Solver (APBS) at\n"<br />
"-> http://agave.wustl.edu/apbs/download\n"<br />
"Such proof of usage is vital in securing funding for APBS development!\n")<br />
<br />
pdb2pqr_plea = ("IMPORTANT REQUEST: If you have not already done so, please register\n"<br />
"your use of the open-source PDB2PQR at\n"<br />
"-> http://www.poissonboltzmann.org/pdb2pqr/d\n"<br />
"Such proof of usage is vital in securing funding for PDB2PQR development!\n")<br />
global apbs_message, pdb2pqr_message<br />
apbs_message = """You must have APBS installed on your system."""<br />
pdb2pqr_message = """PDB2PQR can be used to generate .PQR files."""<br />
<br />
def get_default_location(name):<br />
"""<br />
Given the name of an APBS-related binary, look in<br />
* pymol path,<br />
* freemol path,<br />
* user defined places,<br />
* the system path,<br />
* Known other paths (/usr/local/bin and /opt/local/bin)<br />
for the parameter, name.<br />
<br />
Some programs are verified with additional tests. In particular,<br />
some versions of PyMOL ship with a broken apbs.exe, so we verify<br />
that it can be run.<br />
<br />
PARAMS<br />
name, (string) the basename of the file we're looking for<br />
EXAMPLE<br />
get_default_location("apbs.exe")<br />
RETURNS<br />
(string) path/to/file on success or "" on failure<br />
NOTES<br />
For any program name <foo>.exe we will also search for<br />
<foo>. We'll search for the .exe version first. We do not<br />
automatically check for .exe versions of programs when .exe is<br />
not specified.<br />
"""<br />
def verify(name,f):<br />
if name in 'apbs.exe apbs'.split():<br />
# You'd think we could just check the return code, but<br />
# APBS doesn't return zero on success. Instead, it returns<br />
# things like 3328. It seems to return 5 or -5 in this<br />
# particular failure case, but I'm not sure we can depend<br />
# on that always.<br />
(retcode,prog_out) = run(f,'--version')<br />
if 'dyld: Library not loaded' in prog_out:<br />
print "Skipping",f,"because it appears to be broken (dyld)"<br />
return False<br />
return True<br />
searchDirs = []<br />
if "FREEMOL" in os.environ:<br />
searchDirs.append(os.environ["FREEMOL"])<br />
if "PYMOL_PATH" in os.environ:<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "ext", "bin"))<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "freemol", "bin"))<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "freemol", "share", "apbs"))<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "freemol", "share", "pdb2pqr"))<br />
for x in (APBS_BINARY_LOCATION, APBS_PSIZE_LOCATION, APBS_PDB2PQR_LOCATION):<br />
if x != None and x != "":<br />
searchDirs.append(x)<br />
if name=="temp":<br />
searchDirs = []<br />
if TEMPORARY_FILE_DIR != None and TEMPORARY_FILE_DIR != "":<br />
searchDirs.append(TEMPORARY_FILE_DIR)<br />
searchDirs.append("/tmp")<br />
searchDirs.append(".")<br />
<br />
searchDirs.extend(string.split(os.environ["PATH"], ":"))<br />
searchDirs.append(os.path.join("/usr", "local", "bin"))<br />
searchDirs.append(os.path.join("/opt", "local", "bin"))<br />
<br />
print "Search dirs",searchDirs<br />
<br />
if DEBUG:<br />
print "get_default_location will search the following: ", searchDirs<br />
for d in searchDirs:<br />
if name=="temp":<br />
f = d # just search for the directory<br />
else:<br />
f = os.path.join( d, name ) # make path/name.py<br />
print "trying",f<br />
if os.path.exists(f) and verify(name,f):<br />
return f<br />
elif name.endswith('.exe'):<br />
f = os.path.join( d, name[:-4] ) # make path/name.py<br />
if os.path.exists(f) and verify(name,f):<br />
return f<br />
<br />
print "Could not find default location for file: %s" % name<br />
return ""<br />
<br />
def __init__(self):<br />
"""<br />
Init PyMOL, by adding APBSTools to the GUI under Plugins<br />
<br />
Creates the APBS widget/notebook. Once the event is received,<br />
we create a new instance of APBSTools2 which is a Pmw, which upon<br />
creation shows itself.<br />
"""<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Launch APBS Tools2',<br />
label='APBS Tools2...',<br />
command = lambda s=self: APBSTools2(s))<br />
<br />
def run(prog,args):<br />
'''<br />
wrapper to handle spaces on windows.<br />
prog is the full path to the program.<br />
args is a string that we will split up for you.<br />
or a tuple. or a list. your call.<br />
<br />
return value is (retval,prog_out)<br />
<br />
e.g.<br />
<br />
(retval,prog_out) = run("/bin/ls","-al /tmp/myusername")<br />
'''<br />
import subprocess,tempfile<br />
<br />
if type(args) == type(''):<br />
args = tuple(args.split())<br />
elif type(args) in (type([]),type(())):<br />
args = tuple(args)<br />
args = (prog,) + args<br />
<br />
try:<br />
output_file = tempfile.TemporaryFile(mode="w+") # <-- shouldn't this point to the temp dir<br />
except IOError:<br />
print "Error opening output_file when trying to run the APBS command."<br />
<br />
print "Running",args<br />
retcode = subprocess.call(args,stdout=output_file.fileno(),stderr=subprocess.STDOUT)<br />
output_file.seek(0)<br />
#prog_out = output_file.read()<br />
prog_out = ''.join(output_file.readlines())<br />
output_file.close() #windows doesn't do this automatically<br />
if DEBUG:<br />
print "Results were:"<br />
print "Return value:",retcode<br />
print "Output:"<br />
print prog_out<br />
return (retcode,prog_out)<br />
<br />
class util:<br />
"""<br />
A quick collection of utility functions.<br />
"""<br />
#@staticmethod<br />
def getMolecules():<br />
"""returns all molecules that PyMOL knows about"""<br />
return [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule']<br />
getMolecules = staticmethod(getMolecules)<br />
#@staticmethod<br />
def getMaps():<br />
"""returns all maps that PyMOL knows about"""<br />
return [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map']<br />
getMaps = staticmethod(getMaps)<br />
#def hasAlt(sel):<br />
# """returns true if non-standard locations (rotamers) are present for this selection"""<br />
# return cmd.count_atoms(sel + " and not alt ''")!=0<br />
#hasAlt = staticmethod(hasAlt)<br />
<br />
util = util()<br />
<br />
##############################################################################<br />
##############################################################################<br />
### ###<br />
### ApbsInterface ###<br />
### ###<br />
##############################################################################<br />
##############################################################################<br />
<br />
def getApbsInputFile(pqr_filename,<br />
grid_points,<br />
cglen,<br />
fglen,<br />
cent,<br />
apbs_mode,<br />
bcfl,<br />
ion_plus_one_conc,ion_plus_one_rad,<br />
ion_minus_one_conc,ion_minus_one_rad,<br />
ion_plus_two_conc,ion_plus_two_rad,<br />
ion_minus_two_conc,ion_minus_two_rad,<br />
interior_dielectric, solvent_dielectric,<br />
chgm,<br />
srfm,<br />
solvent_radius,<br />
system_temp,<br />
sdens,<br />
dx_filename,<br />
):<br />
print "Getting APBS input"<br />
#print "system_temp",system_temp,type(system_temp)<br />
#print "sdens",sdens,type(sdens)<br />
#<br />
# How shall we set up the grid? We'll use cglen, fglen, cgcent, fgcent<br />
# and dime.<br />
# This allows people to automate things (e.g. "Alanine scanning")<br />
#<br />
<br />
#<br />
# New template using mg-auto<br />
# See http://agave.wustl.edu/apbs/doc/api/html/#mg-auto<br />
#<br />
<br />
apbs_template = """#<br />
# Note that most of the comments here were taken from sample<br />
# input files that came with APBS. You can find APBS at<br />
# http://agave.wustl.edu/apbs/<br />
# Note that APBS is GPL'd code.<br />
#<br />
read<br />
mol pqr %s # read molecule 1<br />
end<br />
elec<br />
mg-auto<br />
dime %d %d %d # number of find grid points<br />
# calculated by psize.py<br />
cglen %f %f %f # coarse mesh lengths (A)<br />
fglen %f %f %f # fine mesh lengths (A)<br />
# calculated by psize.py<br />
cgcent %f %f %f # (could also give (x,y,z) form psize.py) #known center<br />
fgcent %f %f %f # (could also give (x,y,z) form psize.py) #known center<br />
%s # solve the full nonlinear PBE with npbe<br />
#lpbe # solve the linear PBE with lpbe<br />
bcfl %s # Boundary condition flag<br />
# 0 => Zero<br />
# 1 => Single DH sphere<br />
# 2 => Multiple DH spheres<br />
# 4 => Focusing<br />
#<br />
#ion 1 0.000 2.0 # Counterion declaration:<br />
ion charge 1 conc %f radius %f # Counterion declaration:<br />
ion charge -1 conc %f radius %f # ion <charge> <conc (M)> <radius><br />
ion charge 2 conc %f radius %f # ion <charge> <conc (M)> <radius><br />
ion charge -2 conc %f radius %f # ion <charge> <conc (M)> <radius><br />
pdie %f # Solute dielectric<br />
sdie %f # Solvent dielectric<br />
chgm %s # Charge disc method<br />
# 0 is linear splines<br />
# 1 is cubic b-splines<br />
mol 1 # which molecule to use<br />
srfm smol # Surface calculation method<br />
# 0 => Mol surface for epsilon;<br />
# inflated VdW for kappa; no<br />
# smoothing<br />
# 1 => As 0 with harmoinc average<br />
# smoothing<br />
# 2 => Cubic spline <br />
srad %f # Solvent radius (1.4 for water)<br />
swin 0.3 # Surface cubic spline window .. default 0.3<br />
temp %f # System temperature (298.15 default)<br />
sdens %f # Specify the number of grid points per square-angstrom to use in Vacc object. Ignored when srad is 0.0 (see srad) or srfm is spl2 (see srfm). There is a direct correlation between the value used for the Vacc sphere density, the accuracy of the Vacc object, and the APBS calculation time. APBS default value is 10.0.<br />
#gamma 0.105 # Surface tension parameter for apolar forces (in kJ/mol/A^2)<br />
# only used for force calculations, so we don't care, but<br />
# it *used to be* always required, and 0.105 is the default<br />
calcenergy no # Energy I/O to stdout<br />
# 0 => don't write out energy<br />
# 1 => write out total energy<br />
# 2 => write out total energy and all<br />
# components<br />
calcforce no # Atomic forces I/O (to stdout)<br />
# 0 => don't write out forces<br />
# 1 => write out net forces on molecule<br />
# 2 => write out atom-level forces<br />
write pot dx %s # What to write .. this says write the potential in dx<br />
# format to a file.<br />
end<br />
quit<br />
<br />
"""<br />
return apbs_template % (pqr_filename,<br />
grid_points[0], grid_points[1], grid_points[2],<br />
cglen[0],cglen[1],cglen[2],<br />
fglen[0],fglen[1],fglen[2],<br />
cent[0],cent[1],cent[2],<br />
cent[0],cent[1],cent[2],<br />
apbs_mode,<br />
bcfl,<br />
ion_plus_one_conc,ion_plus_one_rad,<br />
ion_minus_one_conc,ion_minus_one_rad,<br />
ion_plus_two_conc,ion_plus_two_rad,<br />
ion_minus_two_conc,ion_minus_two_rad,<br />
interior_dielectric, solvent_dielectric,<br />
chgm,<br />
solvent_radius,<br />
system_temp,<br />
sdens,<br />
dx_filename,<br />
)<br />
<br />
<br />
<br />
##############################################################################<br />
##############################################################################<br />
### ###<br />
### PluginCode ###<br />
### ###<br />
##############################################################################<br />
##############################################################################<br />
<br />
<br />
<br />
class APBSTools2:<br />
# The current goal is to factor all of the APBS-specific code into<br />
# an ApbsInterface class. The functions defined here before<br />
# __init__, as well as the functions defined on the various<br />
# Panels/Panes, will call through to self.ApbsInterface.<br />
def setPqrFile(self,name):<br />
print " APBS Tools: set pqr file to",name<br />
self.pqr_to_use.setvalue(name)<br />
self.radiobuttons.setvalue('Use another PQR')<br />
def getPqrFilename(self):<br />
if self.radiobuttons.getvalue() != 'Use another PQR':<br />
return self.pymol_generated_pqr_filename.getvalue()<br />
else:<br />
return self.pqr_to_use.getvalue()<br />
def setPsizeLocation(self,value):<br />
self.psize.setvalue(value)<br />
def setBinaryLocation(self,value):<br />
self.binary.setvalue(value)<br />
def setPdb2pqrLocation(self,value):<br />
self.pdb2pqr.setvalue(value)<br />
<br />
def setPymolGeneratedPqrFilename(self,value):<br />
self.pymol_generated_pqr_filename.setvalue(value)<br />
def setPymolGeneratedPdbFilename(self,value):<br />
self.pymol_generated_pdb_filename.setvalue(value)<br />
def setPymolGeneratedDxFilename(self,value):<br />
self.pymol_generated_dx_filename.setvalue(value)<br />
def setPymolGeneratedInFilename(self,value):<br />
self.pymol_generated_in_filename.setvalue(value)<br />
<br />
<br />
def getPymolGeneratedPqrFilename(self):<br />
return self.pymol_generated_pqr_filename.getvalue()<br />
def getPymolGeneratedPdbFilename(self):<br />
return self.pymol_generated_pdb_filename.getvalue()<br />
def getPymolGeneratedDxFilename(self):<br />
return self.pymol_generated_dx_filename.getvalue()<br />
def getPymolGeneratedInFilename(self):<br />
return self.pymol_generated_in_filename.getvalue()<br />
defaults = {<br />
"interior_dielectric" : 2.0,<br />
"solvent_dielectric" : 78.0,<br />
"solvent_radius" : 1.4,<br />
"system_temp" : 310.0,<br />
"apbs_mode" : 'Linearized Poisson-Boltzmann Equation',<br />
"ion_plus_one_conc" : 0.15,<br />
"ion_plus_one_rad" : 2.0,<br />
"ion_plus_two_conc" : 0.0,<br />
"ion_plus_two_rad" : 2.0,<br />
"ion_minus_one_conc" : 0.15,<br />
"ion_minus_one_rad" : 1.8,<br />
"ion_minus_two_conc" : 0.0,<br />
"ion_minus_two_rad" : 2.0,<br />
#"max_mem_allowed" : 400,<br />
"max_mem_allowed" : 1500,<br />
"potential_at_sas" : 0,<br />
"surface_solvent" : 1,<br />
"show_surface_for_scanning" : 1,<br />
#"grid_buffer" : 0,<br />
#"grid_buffer" : 20,<br />
"bcfl" : 'Single DH sphere', # Boundary condition flag for APBS<br />
"sdens": 10.0, # Specify the number of grid points per<br />
# square-angstrom to use in Vacc<br />
# object. Ignored when srad is 0.0 (see srad)<br />
# or srfm is spl2 (see srfm). There is a direct<br />
# correlation between the value used for the<br />
# Vacc sphere density, the accuracy of the Vacc<br />
# object, and the APBS calculation time. APBS<br />
# default value is 10.0.<br />
"chgm" : 'Cubic B-splines', # Charge disc method for APBS<br />
}<br />
<br />
def __init__(self,app):<br />
self.parent = app.root<br />
<br />
# Create the dialog.<br />
self.dialog = Pmw.Dialog(self.parent,<br />
buttons = ('Register APBS Use', 'Register PDB2PQR Use', 'Set grid', 'Run APBS', 'Exit APBS tools'),<br />
title = 'PyMOL APBS Tools',<br />
command = self.execute)<br />
self.dialog.withdraw()<br />
Pmw.setbusycursorattributes(self.dialog.component('hull'))<br />
<br />
w = Tkinter.Label(self.dialog.interior(),<br />
text = 'PyMOL APBS Tools\nMichael G. Lerner, Heather A. Carlson, 2009 - http://pymolwiki.org/index.php/APBS\n(incorporates modifications by Warren L. DeLano)',<br />
background = 'black',<br />
foreground = 'white',<br />
#pady = 20,<br />
)<br />
w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)<br />
<br />
self.notebook = Pmw.NoteBook(self.dialog.interior())<br />
self.notebook.pack(fill='both',expand=1,padx=10,pady=10)<br />
<br />
# Set up the Main page<br />
page = self.notebook.add('Main')<br />
group = Pmw.Group(page,tag_text='Main options')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.selection = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Selection to use: ',<br />
value='(polymer)',<br />
)<br />
self.map = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='What to call the resulting map: ',<br />
value='apbs_map',<br />
)<br />
self.radiobuttons = Pmw.RadioSelect(group.interior(),<br />
buttontype = 'radiobutton',<br />
orient = 'vertical',<br />
labelpos = 'w',<br />
)<br />
for text in ('Use PyMOL generated PQR and existing Hydrogens and termini',<br />
'Use PyMOL generated PQR and PyMOL generated Hydrogens and termini',<br />
'Use another PQR',<br />
'Use PDB2PQR',):<br />
self.radiobuttons.add(text)<br />
self.radiobuttons.setvalue('Use PyMOL generated PQR and PyMOL generated Hydrogens and termini')<br />
<br />
self.pdb2pqr_options = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='pdb2pqr command line options: ',<br />
value='--ff=AMBER',<br />
)<br />
self.pqr_to_use = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPqrFile,'*.pqr'),<br />
label_text='\tChoose Externally Generated PQR:',<br />
)<br />
<br />
<br />
<br />
for entry in (self.selection,self.map,self.radiobuttons,self.pdb2pqr_options,self.pqr_to_use):<br />
#for entry in (self.selection,self.map,self.radiobuttons,):<br />
entry.pack(fill='x',padx=4,pady=1) # vertical<br />
<br />
<br />
# Set up the main "Calculation" page<br />
page = self.notebook.add('Configuration')<br />
<br />
group = Pmw.Group(page,tag_text='Dielectric Constants')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column=0, row=0)<br />
self.interior_dielectric = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Protein Dielectric:',<br />
value = str(APBSTools2.defaults['interior_dielectric']),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
self.solvent_dielectric = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Solvent Dielectric:',<br />
value = str(APBSTools2.defaults['solvent_dielectric']),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
entries = (self.interior_dielectric,self.solvent_dielectric)<br />
for entry in entries:<br />
#entry.pack(side='left',fill='both',expand=1,padx=4) # side-by-side<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
group = Pmw.Group(page,tag_text='Other')<br />
group.pack(fill='both',expand=1, padx=4, pady=5)<br />
group.grid(column=1, row=1,columnspan=4)<br />
self.max_mem_allowed = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Maximum Memory Allowed (MB):',<br />
value = str(APBSTools2.defaults['max_mem_allowed']),<br />
validate = {'validator' : 'real',<br />
'min':1,}<br />
)<br />
self.apbs_mode = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'APBS Mode',<br />
items = ('Nonlinear Poisson-Boltzmann Equation','Linearized Poisson-Boltzmann Equation',),<br />
initialitem = APBSTools2.defaults['apbs_mode'],<br />
)<br />
self.apbs_mode.pack(fill='x',expand=1,padx=4)<br />
#self.apbs_mode.grid(column=0,row=0,columnspan=3)<br />
self.solvent_radius = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Solvent Radius:',<br />
validate = {'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['solvent_radius']),<br />
)<br />
self.system_temp = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'System Temperature:',<br />
validate = {'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['system_temp']),<br />
)<br />
self.sdens = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Vacc sphere density (grid points/A^2)',<br />
validate = {'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['sdens']),<br />
)<br />
self.bcfl = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Boundary Condition',<br />
items = ('Zero','Single DH sphere','Multiple DH spheres',), #'Focusing',),<br />
initialitem = APBSTools2.defaults['bcfl'],<br />
)<br />
self.chgm = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Charge disc method',<br />
items = ('Linear','Cubic B-splines','Quintic B-splines',),<br />
initialitem = APBSTools2.defaults['chgm'],<br />
)<br />
self.srfm = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Surface Calculation Method',<br />
items = ('Mol surf for epsilon; inflated VdW for kappa, no smoothing','Same, but with harmonic average smoothing','Cubic spline','Similar to cubic spline, but with 7th order polynomial'),<br />
initialitem = 'Same, but with harmonic average smoothing',<br />
)<br />
#for entry in (self.apbs_mode,self.system_temp,self.solvent_radius,):<br />
for entry in (self.max_mem_allowed,self.solvent_radius,self.system_temp,self.sdens,self.apbs_mode,self.bcfl,self.chgm,self.srfm):<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
<br />
<br />
group = Pmw.Group(page,tag_text='Ions')<br />
group.pack(fill='both',expand=1, padx=4, pady=5)<br />
group.grid(column=0, row=1, )<br />
self.ion_plus_one_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (+1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_one_conc']),<br />
)<br />
self.ion_plus_one_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (+1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_one_rad']),<br />
)<br />
self.ion_minus_one_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (-1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_one_conc']),<br />
)<br />
self.ion_minus_one_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (-1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_one_rad']),<br />
)<br />
self.ion_plus_two_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (+2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_two_conc']),<br />
)<br />
self.ion_plus_two_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (+2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_two_rad']),<br />
)<br />
self.ion_minus_two_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (-2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_two_conc']),<br />
)<br />
self.ion_minus_two_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (-2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_two_rad']),<br />
)<br />
entries = (self.ion_plus_one_conc,self.ion_plus_one_rad,<br />
self.ion_minus_one_conc,self.ion_minus_one_rad,<br />
self.ion_plus_two_conc,self.ion_plus_two_rad,<br />
self.ion_minus_two_conc,self.ion_minus_two_rad,<br />
)<br />
for entry in entries:<br />
entry.pack(fill='x',expand=1,padx=4)<br />
<br />
group = Pmw.Group(page,tag_text = 'Coarse Mesh Length')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 1, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_coarse_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'real','min':0},<br />
value = -1,<br />
entry_width=15,<br />
)<br />
)<br />
getattr(self,'grid_coarse_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
<br />
group = Pmw.Group(page,tag_text = 'Fine Mesh Length')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 2, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_fine_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'real','min':0},<br />
value = -1,<br />
entry_width=15,<br />
)<br />
)<br />
getattr(self,'grid_fine_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
<br />
group = Pmw.Group(page,tag_text = 'Grid Center')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 3, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_center_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'real'},<br />
value = 0,<br />
entry_width=10,<br />
)<br />
)<br />
getattr(self,'grid_center_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
group = Pmw.Group(page,tag_text = 'Grid Points')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 4, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_points_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'integer','min':0},<br />
value = -1,<br />
entry_width=8,<br />
)<br />
)<br />
getattr(self,'grid_points_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
<br />
page.grid_rowconfigure(2,weight=1)<br />
page.grid_columnconfigure(5,weight=1)<br />
page = self.notebook.add('Program Locations')<br />
group = Pmw.Group(page,tag_text='Locations')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
def quickFileValidation(s):<br />
if s == '': return Pmw.PARTIAL<br />
elif os.path.isfile(s): return Pmw.OK<br />
elif os.path.exists(s): return Pmw.PARTIAL<br />
else: return Pmw.PARTIAL<br />
def quickFileDirValidation(s):<br />
'''<br />
assumes s ends in filename<br />
'''<br />
if os.path.exists(s) and not os.path.isfile(s):<br />
return Pmw.PARTIAL<br />
if os.path.isdir(os.path.split(s)[0]):<br />
return Pmw.OK<br />
return Pmw.PARTIAL<br />
self.binary = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setBinaryLocation),<br />
validate = {'validator':quickFileValidation,},<br />
value = get_default_location('apbs.exe'),<br />
label_text = 'APBS binary location:',<br />
)<br />
self.binary.pack(fill = 'x', padx = 20, pady = 10)<br />
self.psize = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPsizeLocation),<br />
validate = {'validator':quickFileValidation,},<br />
#value = '/usr/local/apbs-0.3.1/tools/manip/psize.py',<br />
value = get_default_location('psize.py'),<br />
label_text = 'APBS psize.py location:',<br />
)<br />
self.psize.pack(fill = 'x', padx = 20, pady = 10)<br />
self.pdb2pqr = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPdb2pqrLocation),<br />
validate = {'validator':quickFileValidation,},<br />
value = get_default_location('pdb2pqr.py'),<br />
label_text = 'pdb2pqr location:',<br />
)<br />
self.pdb2pqr.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
label = Tkinter.Label(group.interior(),<br />
pady = 10,<br />
justify=LEFT,<br />
text = """<br />
The PyMOL APBS tools can calculate proper grid dimensions and spacing (we attempt to make<br />
the fine mesh spacing 0.5A or finer, but we will make it coarser if forced to by the<br />
Maximum Grid Points setting in the configuration pane). If you wish to use APBS's psize.py<br />
to set up the grid, make sure that the path is set correctly above.<br />
<br />
PyMOL can generate PQR files using standard protein residues and AMBER charges. If you<br />
wish to use PDB2PQR instead, make sure that it is installed and that the path is set<br />
correctly above.<br />
<br />
If PyMOL does not automatically find apbs, psize.py, or pdb2pqr, you may set the environment<br />
variables APBS_BINARY, APBS_PSIZE and APBS_PDB2PQR to point to them respectively.<br />
""",<br />
)<br />
label.pack()<br />
<br />
<br />
page = self.notebook.add('Temp File Locations')<br />
group = Pmw.Group(page,tag_text='Locations')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.pymol_generated_pqr_filename = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedPqrFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
label_text = 'Temporary PQR file: ',<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.pqr'),<br />
)<br />
self.pymol_generated_pqr_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
self.pymol_generated_pdb_filename = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedPdbFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
label_text = 'Temporary PDB file: ',<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.pdb'),<br />
)<br />
self.pymol_generated_pdb_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
self.pymol_generated_dx_filename = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedDxFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
label_text = 'Temporary DX file: ',<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.dx'),<br />
)<br />
self.pymol_generated_dx_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
<br />
self.pymol_generated_in_filename = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedInFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.in'),<br />
label_text = 'APBS input file:')<br />
self.pymol_generated_in_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
label = Tkinter.Label(group.interior(),<br />
pady = 10,<br />
justify=LEFT,<br />
text = """You can automatically set the default location of temporary files<br />
by setting the environment variable TEMP.<br />
""",<br />
)<br />
label.pack()<br />
# Create the visualization pages<br />
page = self.notebook.add('Visualization (1)')<br />
group = VisualizationGroup(page,tag_text='Visualization',visgroup_num=1)<br />
self.visualization_group_1 = group<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
<br />
page = self.notebook.add('Visualization (2)')<br />
group = VisualizationGroup(page,tag_text='Visualization',visgroup_num=2)<br />
self.visualization_group_2 = group<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
<br />
# Create a couple of other empty pages<br />
page = self.notebook.add('About')<br />
group = Pmw.Group(page, tag_text='About PyMOL APBS Tools')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
text = """This plugin integrates PyMOL (http://PyMOL.org/) with APBS (http://www.poissonboltzmann.org/apbs/).<br />
<br />
Documentation may be found at<br />
http://pymolwiki.org/index.php/APBS<br />
and<br />
http://apbs.wustl.edu/MediaWiki/index.php/APBS_electrostatics_in_PyMOL<br />
<br />
It requires APBS version >= 0.5.0.<br />
<br />
In the simplest case,<br />
<br />
1) Load a structure into PyMOL.<br />
2) Start this plugin.<br />
3) Make sure that the path to the APBS binary is correct on the "Program Locations" tab.<br />
4) Click the "Set grid" button to set up the grid.<br />
5) Click the "Run APBS" button.<br />
<br />
Many thanks to<br />
- Warren DeLano and Jason Vertrees for everything involving PyMOL<br />
- Nathan Baker, Todd Dolinsky and David Gohara for everything involving APBS<br />
- William G. Scott for help with several APBS+PyMOL issues and documentation<br />
<br />
Created by Michael Lerner (http://pymolwiki.org/index.php/User:Mglerner) mglerner@gmail.com<br />
Carlson Group, University of Michigan (http://www.umich.edu/~carlsonh/)<br />
<br />
Please contact the author and cite this plugin if you use it in a publication.<br />
<br />
Citation for this plugin:<br />
MG Lerner and HA Carlson. APBS plugin for PyMOL, 2006,<br />
University of Michigan, Ann Arbor.<br />
<br />
Citation for PyMOL may be found here:<br />
http://pymol.sourceforge.net/faq.html#CITE<br />
<br />
Citation for APBS:<br />
Baker NA, Sept D, Joseph S, Holst MJ, McCammon JA. Electrostatics of<br />
nanosystems: application to microtubules and the ribosome. Proc.<br />
Natl. Acad. Sci. USA 98, 10037-10041 2001.<br />
<br />
Citation for PDB2PQR:<br />
Dolinsky TJ, Nielsen JE, McCammon JA, Baker NA.<br />
PDB2PQR: an automated pipeline for the setup, execution,<br />
and analysis of Poisson-Boltzmann electrostatics calculations.<br />
Nucleic Acids Research 32 W665-W667 (2004).<br />
"""<br />
#<br />
# Add this as text in a scrollable pane.<br />
# Code based on Caver plugin<br />
# http://loschmidt.chemi.muni.cz/caver/index.php<br />
#<br />
interior_frame=Frame(group.interior())<br />
bar=Scrollbar(interior_frame,)<br />
text_holder=Text(interior_frame,yscrollcommand=bar.set,background="#ddddff",font="Times 14")<br />
bar.config(command=text_holder.yview)<br />
text_holder.insert(END,text)<br />
text_holder.pack(side=LEFT,expand="yes",fill="both")<br />
bar.pack(side=LEFT,expand="yes",fill="y")<br />
interior_frame.pack(expand="yes",fill="both")<br />
<br />
self.notebook.setnaturalsize()<br />
self.showAppModal()<br />
<br />
def showAppModal(self):<br />
#self.dialog.activate() #geometry = 'centerscreenfirst',globalMode = 'nograb')<br />
self.dialog.show()<br />
def execute(self, result, refocus=True):<br />
if result == 'Register APBS Use':<br />
import webbrowser<br />
webbrowser.open("http://agave.wustl.edu/apbs/download")<br />
elif result == 'Register PDB2PQR Use':<br />
import webbrowser<br />
webbrowser.open("http://www.poissonboltzmann.org/pdb2pqr/d/downloads")<br />
elif result == 'Run APBS':<br />
good = self.generateApbsInputFile()<br />
if not good:<br />
if DEBUG:<br />
print "ERROR: Something went wrong trying to generate the APBS input file."<br />
return False<br />
if self.radiobuttons.getvalue() == 'Use another PQR':<br />
pass<br />
elif self.radiobuttons.getvalue() == 'Use PDB2PQR':<br />
if DEBUG: print "GENERATING PQR FILE via PDB2PQR"<br />
good = self.generatePdb2pqrPqrFile()<br />
if not good:<br />
if DEBUG:<br />
print "Could not generate PDB2PQR file. generatePdb2pqrPqrFile failed."<br />
return False<br />
if DEBUG: print "GENERATED"<br />
else: # it's one of the pymol-generated options<br />
if DEBUG: print "GENERATING PQR FILE via PyMOL"<br />
good = self.generatePymolPqrFile()<br />
if not good:<br />
if DEBUG:<br />
print "Could not generate the PyMOL-basd PQR file. generatePyMOLPqrFile failed."<br />
return False<br />
if DEBUG: print "GENERATED"<br />
if os.path.exists(self.pymol_generated_dx_filename.getvalue()):<br />
try:<br />
os.unlink(self.pymol_generated_dx_filename.getvalue())<br />
except:<br />
traceback.print_exc()<br />
pass<br />
#command = "%s %s" % (self.binary.getvalue(),self.pymol_generated_in_filename.getvalue())<br />
#os.system(command)<br />
<br />
#<br />
# NOTE: if there are spaces in the directory name that contains pymol_generated_in_filename,<br />
# our run command will want to split it up into several arguments if we pass it as a<br />
# string. So, we pass it as a tuple.<br />
#<br />
(retval,progout) = run(self.binary.getvalue(),(self.pymol_generated_in_filename.getvalue(),))<br />
if refocus:<br />
#<br />
# There's a bug in the version of APBS shipped with<br />
# Ubuntu 9.10 (version 1.1.0) that causes the name to<br />
# become foo-PE0.dx instead of foo.dx. This would<br />
# normally only occur in mg-para calcs or MPI versions<br />
# of apbs. It's clearly bug-possible, but we will<br />
# check for foo-PE0 if we can't find foo.dx.<br />
#<br />
fname = self.pymol_generated_dx_filename.getvalue()<br />
if not os.path.isfile(fname):<br />
print "Could not find",fname,"so searching for",<br />
fname = '-PE0'.join(os.path.splitext(fname))<br />
print fname<br />
pymol.cmd.load(fname)<br />
self.visualization_group_1.refresh()<br />
self.visualization_group_2.refresh()<br />
self.notebook.tab('Visualization (1)').focus_set()<br />
self.notebook.selectpage('Visualization (1)')<br />
elif result == 'Set grid':<br />
self.runPsize()<br />
else:<br />
#<br />
# Doing it this way takes care of clicking on the x in the top of the<br />
# window, which as result set to None.<br />
#<br />
global APBS_BINARY_LOCATION, APBS_PSIZE_LOCATION<br />
APBS_BINARY_LOCATION = self.binary.getvalue()<br />
APBS_PSIZE_LOCATION = self.psize.getvalue()<br />
self.quit()<br />
def quit(self):<br />
self.dialog.destroy() # stops CPU hogging, perhaps fixes Ubuntu bug MGL<br />
<br />
def runPsize(self):<br />
class NoPsize(Exception):<br />
pass<br />
class NoPDB(Exception):<br />
pass<br />
try:<br />
if not self.psize.valid():<br />
raise NoPsize<br />
pqr_filename = self.pymol_generated_pqr_filename.getvalue()<br />
try:<br />
f = file(pqr_filename,'w')<br />
f.close()<br />
except:<br />
raise NoPDB<br />
#<br />
# Do some magic to load the psize module<br />
#<br />
import imp<br />
f,fname,description = imp.find_module('psize',[os.path.split(self.psize.getvalue())[0]])<br />
psize = imp.load_module('psize',f,fname,description)<br />
# WLD<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
<br />
if pymol.cmd.count_atoms( self.selection.getvalue() + " and not alt ''")!=0:<br />
print "WARNING: You have alternate locations for some of your atoms!"<br />
pymol.cmd.save(pqr_filename,sel)<br />
f.close()<br />
size = psize.Psize()<br />
size.setConstant('gmemceil',int(self.max_mem_allowed.getvalue()))<br />
size.runPsize(pqr_filename)<br />
coarsedim = size.getCoarseGridDims() # cglen<br />
finedim = size.getFineGridDims() # fglen<br />
# could use procgrid for multiprocessors<br />
finegridpoints = size.getFineGridPoints() # dime<br />
center = size.getCenter() # cgcent and fgcent<br />
print "APBS's psize.py was used to calculated grid dimensions"<br />
except (NoPsize,ImportError):<br />
print "This plugin was used to calculated grid dimensions"<br />
#<br />
# First, we need to get the dimensions of the molecule<br />
#<br />
# WLD<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
model = pymol.cmd.get_model(sel)<br />
mins = [None,None,None]<br />
maxs = [None,None,None]<br />
for a in model.atom:<br />
for i in (0,1,2):<br />
if mins[i] is None or a.coord[i] < mins[i]:<br />
mins[i] = a.coord[i]<br />
if maxs[i] is None or a.coord[i] > maxs[i]:<br />
maxs[i] = a.coord[i]<br />
if None in mins or None in maxs:<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "No atoms were in your selection",<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
<br />
box_length = [maxs[i] - mins[i] for i in range(3)]<br />
center = [(maxs[i] + mins[i])/2.0 for i in range(3)]<br />
#<br />
# psize expands the molecular dimensions by CFAC (which defaults<br />
# to 1.7) for the coarse grid<br />
#<br />
CFAC = 1.7<br />
coarsedim = [length*CFAC for length in box_length]<br />
<br />
#<br />
# psize also does something strange .. it adds a buffer FADD to<br />
# the box lengths to get the fine lengths. you'd think it'd also<br />
# have FFAC or CADD, but we'll mimic it here. it also has the<br />
# requirement that the fine grid lengths must be <= the corase<br />
# grid lengths. FADD defaults to 20.<br />
#<br />
FADD = 20<br />
finedim = [min(coarsedim[i],box_length[i] + FADD) for i in range(3)]<br />
<br />
#<br />
# And now the hard part .. setting up the grid points.<br />
# From the APBS manual at http://agave.wustl.edu/apbs/doc/html/user-guide/x594.html#dime<br />
# we have the formula<br />
# n = c*2^(l+1) + 1<br />
# where l is the number of levels in the MG hierarchy. The typical<br />
# number of levels is 4.<br />
#<br />
nlev = 4<br />
mult_fac = 2**(nlev + 1) # this will typically be 2^5==32<br />
# and c must be a non-zero integer<br />
<br />
# If we didn't have to be c*mult_fac + 1, this is what our grid points<br />
# would look like (we use the ceiling to be on the safe side .. it never<br />
# hurts to do too much.<br />
SPACE = 0.5 # default desired spacing = 0.5A<br />
#desired_points = [int(math.ceil(flen / SPACE)) for flen in finedim] # as integers<br />
desired_points = [flen / SPACE for flen in finedim] # as floats .. use int(math.ceil(..)) later<br />
<br />
# Now we set up our cs, taking into account mult_fac<br />
# (we use the ceiling to be on the safe side .. it never hurts to do<br />
# too much.)<br />
cs = [int(math.ceil(dp/mult_fac)) for dp in desired_points]<br />
<br />
finegridpoints = [mult_fac * c + 1 for c in cs]<br />
<br />
print "cs",cs<br />
print "finedim",finedim<br />
print "nlev",nlev<br />
print "mult_fac",mult_fac<br />
print "finegridpoints",finegridpoints<br />
<br />
except NoPDB:<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "Please set a temporary PDB file location",<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
<br />
if (finegridpoints[0]>0) and (finegridpoints[1]>0) and (finegridpoints[2]>0):<br />
max_mem_allowed = float(self.max_mem_allowed.getvalue())<br />
def memofgrid(finegridpoints):<br />
return 200. * float(finegridpoints[0] * finegridpoints[1] * finegridpoints[2]) / 1024. / 1024<br />
def gridofmem(mem):<br />
return mem * 1024. * 1024. / 200.<br />
max_grid_points = gridofmem(max_mem_allowed)<br />
print "Estimated memory usage",memofgrid(finegridpoints),'MB out of maximum allowed',max_mem_allowed<br />
if memofgrid(finegridpoints) > max_mem_allowed:<br />
print "Maximum memory usage exceeded. Old grid dimensions were",finegridpoints<br />
product = float(finegridpoints[0] * finegridpoints[1] * finegridpoints[2])<br />
factor = pow(max_grid_points/product,0.333333333)<br />
finegridpoints[0] = (int(factor*finegridpoints[0]/2))*2+1<br />
finegridpoints[1] = (int(factor*finegridpoints[1]/2))*2+1<br />
finegridpoints[2] = (int(factor*finegridpoints[2]/2))*2+1<br />
print "Fine grid points rounded down from",finegridpoints<br />
#<br />
# Now we have to make sure that this still fits the equation n = c*2^(l+1) + 1. Here, we'll<br />
# just assume nlev == 4, which means that we need to be (some constant times 32) + 1.<br />
#<br />
# This can be annoying if, e.g., you're trying to set [99, 123, 99] .. it'll get rounded to [99, 127, 99].<br />
# First, I'll try to round to the nearest 32*c+1. If that doesn't work, I'll just round down.<br />
#<br />
new_gp = [0,0,0]<br />
for i in 0,1,2:<br />
dm = divmod(finegridpoints[i] - 1,32)<br />
if dm[1]>16:<br />
new_gp[i] = (dm[0]+1)*32+1<br />
else:<br />
new_gp[i] = (dm[0])*32+1<br />
new_prod = new_gp[0]*new_gp[1]*new_gp[2]<br />
#print "tried new_prod",new_prod,"max_grid_points",max_grid_points,"small enough?",new_prod <= max_grid_points<br />
if new_prod <= max_grid_points:<br />
#print "able to round to closest"<br />
for i in 0,1,2: finegridpoints[i] = new_gp[i]<br />
else:<br />
# darn .. have to round down.<br />
# Note that this can still fail a little bit .. it can only get you back down to the next multiple <= what was in<br />
# finegridpoints. So, if finegridpoints was exactly on a multiple, like (99,129,99), you'll get rounded down to<br />
# (99,127,99), which is still just a bit over the default max of 1200000. I think that's ok. It's the rounding error<br />
# from int(factor*finegridpoints ..) above, but it'll never be a huge error. If we needed to, we could easily fix this.<br />
#<br />
#print "rounding down more"<br />
for i in 0,1,2:<br />
#print finegridpoints[i],divmod(finegridpoints[i] - 1,32),<br />
finegridpoints[i] = divmod(finegridpoints[i] - 1,32)[0]*32 + 1<br />
print "New grid dimensions are",finegridpoints<br />
print " APBS Tools: coarse grid: (%5.3f,%5.3f,%5.3f)"%tuple(coarsedim)<br />
self.grid_coarse_x.setvalue(coarsedim[0])<br />
self.grid_coarse_y.setvalue(coarsedim[1])<br />
self.grid_coarse_z.setvalue(coarsedim[2])<br />
print " APBS Tools: fine grid: (%5.3f,%5.3f,%5.3f)"%tuple(finedim)<br />
self.grid_fine_x.setvalue(finedim[0])<br />
self.grid_fine_y.setvalue(finedim[1])<br />
self.grid_fine_z.setvalue(finedim[2])<br />
print " APBS Tools: center: (%5.3f,%5.3f,%5.3f)"%tuple(center)<br />
self.grid_center_x.setvalue(center[0])<br />
self.grid_center_y.setvalue(center[1])<br />
self.grid_center_z.setvalue(center[2])<br />
print " APBS Tools: fine grid points (%d,%d,%d)"%tuple(finegridpoints)<br />
self.grid_points_x.setvalue(finegridpoints[0])<br />
self.grid_points_y.setvalue(finegridpoints[1])<br />
self.grid_points_z.setvalue(finegridpoints[2])<br />
<br />
def fixColumns(self,sel):<br />
"""<br />
Make sure that everything fits into the correct columns.<br />
This means doing some rounding. It also means getting rid of<br />
chain, occupancy and b-factor information.<br />
"""<br />
#pymol.cmd.alter_state(1,'all','(x,y,z)=(int(x*1000)/1000.0, int(y*1000)/1000.0, int(z*1000)/1000.0)')<br />
#pymol.cmd.alter_state(1,'all','(x,y,z)=float("%.2f"%x),float("%.2f"%y),float("%.2f"%z)')<br />
pymol.cmd.alter_state(1,'all','(x,y,z)=float("%.3f"%x),float("%.3f"%y),float("%.3f"%z)')<br />
pymol.cmd.alter(sel,'chain=""')<br />
pymol.cmd.alter(sel,'b=0')<br />
pymol.cmd.alter(sel,'q=0')<br />
<br />
def cleanupGeneratedPdbOrPqrFile(self,filename):<br />
"""<br />
More cleanup on PQR files.<br />
<br />
pdb2pqr will happily write out a file where the coordinate<br />
columns overlap if you have -100.something as one of the<br />
coordinates, like<br />
<br />
90.350 97.230-100.010<br />
<br />
and so will PyMOL. We can't just assume that it's 0-1<br />
because pdb2pqr will debump things and write them out with<br />
3 digits post-decimal. Bleh.<br />
"""<br />
f = file(filename,'r')<br />
txt = f.read()<br />
f.close()<br />
f = file(filename,'w')<br />
# APBS accepts whitespace-delimited columns<br />
# it doesn't care about non-coord lines, so there's not need to be careful about<br />
# where we replace dashes.<br />
txt = txt.replace('-',' -')<br />
f.write(txt)<br />
f.close()<br />
<br />
def getUnassignedAtomsFromPqr(self,fname):<br />
"""<br />
Here is a comment from Todd Dolinsky via email:<br />
<br />
There's a couple of different errors which can be printed out via REMARK 5 lines; a good sample is:<br />
<br />
REMARK 1 PQR file generated by PDB2PQR (Version 1.2.0)<br />
REMARK 1<br />
REMARK 1 Forcefield Used: charmm<br />
REMARK 1<br />
REMARK 1 pKas calculated by propka and assigned using pH 7.00<br />
REMARK 1<br />
REMARK 5 WARNING: Propka determined the following residues to be<br />
REMARK 5 in a protonation state not supported by the<br />
REMARK 5 charmm forcefield!<br />
REMARK 5 All were reset to their standard pH 7.0 state.<br />
REMARK 5 <br />
REMARK 5 CYS 61 2 (negative)<br />
REMARK 5 CYS 79 2 (negative)<br />
REMARK 5 <br />
REMARK 5 WARNING: Unable to debump ALA 1 19<br />
REMARK 5 WARNING: Unable to debump MET 1 151<br />
REMARK 5 WARNING: Unable to debump PRO 1 258<br />
REMARK 5 WARNING: Unable to debump GLY 2 8<br />
REMARK 5 WARNING: Unable to debump THR 3 118<br />
REMARK 5<br />
REMARK 5 WARNING: PDB2PQR was unable to assign charges<br />
REMARK 5 to the following atoms (omitted below):<br />
REMARK 5 6657 O1 in TRS 900<br />
REMARK 5 6658 C2 in TRS 900<br />
REMARK 5 6659 C3 in TRS 900<br />
REMARK 5 6660 C4 in TRS 900<br />
REMARK 5 6661 O5 in TRS 900<br />
REMARK 5 6662 C6 in TRS 900<br />
REMARK 5 6663 O7 in TRS 900<br />
REMARK 5 6664 N8 in TRS 900<br />
REMARK 5<br />
REMARK 6 Total charge on this protein: -1.0000 e<br />
REMARK 6<br />
<br />
If all you care about is the atom number, you can probably regexp match on the 'in' field, something like<br />
<br />
>>> re.compile('REMARK 5 *(\d)* \w* in').findall(text) # Text contains PQR output string<br />
['6657', '6658', '6659', '6660', '6661', '6662', '6663', '6664']<br />
<br />
Or you can grab any other useful information - I'd say that using a regular expression like this would be the best option to ensure you don't get false positives. <br />
"""<br />
f = file(fname)<br />
unassigned = re.compile('REMARK 5 *(\d+) \w* in').findall(f.read()) # Text contains PQR output string<br />
f.close()<br />
return '+'.join(unassigned)<br />
<br />
<br />
def generateApbsInputFile(self):<br />
if self.checkInput(silent=False):<br />
#<br />
# set up our variables<br />
#<br />
pqr_filename = self.getPqrFilename()<br />
<br />
grid_points = [int(getattr(self,'grid_points_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
cglen = [float(getattr(self,'grid_coarse_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
fglen = [float(getattr(self,'grid_fine_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
cent = [float(getattr(self,'grid_center_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
<br />
apbs_mode = self.apbs_mode.getvalue()<br />
if apbs_mode == 'Nonlinear Poisson-Boltzmann Equation':<br />
apbs_mode = 'npbe'<br />
else:<br />
apbs_mode = 'lpbe'<br />
<br />
bcflmap = {'Zero': 'zero',<br />
'Single DH sphere': 'sdh',<br />
'Multiple DH spheres': 'mdh',<br />
#'Focusing': 'focus',<br />
}<br />
bcfl = bcflmap[self.bcfl.getvalue()]<br />
<br />
chgmmap = {'Linear':'spl0',<br />
'Cubic B-splines':'spl2',<br />
'Quintic B-splines':'spl4',<br />
}<br />
chgm = chgmmap[self.chgm.getvalue()]<br />
<br />
srfmmap = {'Mol surf for epsilon; inflated VdW for kappa, no smoothing':'mol',<br />
'Same, but with harmonic average smoothing':'smol',<br />
'Cubic spline':'spl2',<br />
'Similar to cubic spline, but with 7th order polynomial':'spl4',}<br />
<br />
srfm = srfmmap[self.srfm.getvalue()]<br />
<br />
dx_filename = self.pymol_generated_dx_filename.getvalue()<br />
if dx_filename.endswith('.dx'):<br />
dx_filename = dx_filename[:-3]<br />
apbs_input_text = getApbsInputFile(pqr_filename,<br />
grid_points,<br />
cglen,<br />
fglen,<br />
cent,<br />
apbs_mode,<br />
bcfl,<br />
float(self.ion_plus_one_conc.getvalue()), float(self.ion_plus_one_rad.getvalue()),<br />
float(self.ion_minus_one_conc.getvalue()), float(self.ion_minus_one_rad.getvalue()),<br />
float(self.ion_plus_two_conc.getvalue()), float(self.ion_plus_two_rad.getvalue()),<br />
float(self.ion_minus_two_conc.getvalue()), float(self.ion_minus_two_rad.getvalue()),<br />
float(self.interior_dielectric.getvalue()), float(self.solvent_dielectric.getvalue()),<br />
chgm,<br />
srfm,<br />
float(self.solvent_radius.getvalue()),<br />
float(self.system_temp.getvalue()),<br />
float(self.sdens.getvalue()),<br />
dx_filename,<br />
)<br />
if DEBUG:<br />
print "GOT THE APBS INPUT FILE"<br />
<br />
#<br />
# write out the input text<br />
#<br />
try:<br />
f = file(self.pymol_generated_in_filename.getvalue(),'w')<br />
f.write(apbs_input_text)<br />
f.close()<br />
except IOError:<br />
print "ERROR: Got the input file from APBS, but failed when trying to write to %s" % self.pymol_generated_in_filename.getvalue()<br />
return True<br />
else:<br />
self.checkInput()<br />
return False<br />
<br />
def checkInput(self,silent=False):<br />
"""If silent is True, we'll just return a True/False value<br />
"""<br />
if not silent:<br />
def show_error(message):<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = message,<br />
)<br />
junk = error_dialog.activate()<br />
else:<br />
def show_error(message):<br />
pass<br />
<br />
#<br />
# First, check to make sure we have valid locations for apbs and psize<br />
#<br />
if not self.binary.valid():<br />
show_error('Please set the APBS binary location')<br />
return False<br />
#<br />
# If the path to psize is not correct, that's fine .. we'll<br />
# do the calculations ourself.<br />
#<br />
<br />
#if not self.psize.valid():<br />
# show_error("Please set APBS's psize location")<br />
# return False<br />
<br />
#<br />
# Now check the temporary filenames<br />
#<br />
if self.radiobuttons.getvalue() != 'Use another PQR':<br />
if not self.pymol_generated_pqr_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated PQR file')<br />
return False<br />
elif not self.pqr_to_use.valid():<br />
show_error('Please select a valid pqr file or tell\nPyMOL to generate one')<br />
return False<br />
if not self.pymol_generated_pdb_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated PDB file')<br />
return False<br />
if not self.pymol_generated_dx_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated DX file')<br />
return False<br />
if not self.pymol_generated_in_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated APBS input file')<br />
return False<br />
if not self.map.getvalue():<br />
show_error('Please choose a name for the generated map.')<br />
return False<br />
<br />
<br />
#<br />
# Now, the ions<br />
#<br />
for sign in 'plus minus'.split():<br />
for value in 'one two'.split():<br />
for parm in 'conc rad'.split():<br />
if not getattr(self,'ion_%s_%s_%s'%(sign,value,parm)).valid():<br />
show_error('Please correct Ion concentrations and radii')<br />
return False<br />
#<br />
# Now the grid<br />
#<br />
for grid_type in 'coarse fine points center'.split():<br />
for coord in 'x y z'.split():<br />
if not getattr(self,'grid_%s_%s'%(grid_type,coord)).valid():<br />
show_error('Please correct grid dimensions\nby clicking on the "Set grid" button')<br />
return False<br />
<br />
#<br />
# Now other easy things<br />
#<br />
for (message, thing) in (('solvent dielectric',self.solvent_dielectric),<br />
('protein dielectric',self.interior_dielectric),<br />
('solvent radius',self.solvent_radius),<br />
('system temperature',self.system_temp),<br />
('sdens',self.sdens),<br />
):<br />
if not thing.valid():<br />
show_error('Please correct %s'%message)<br />
return False<br />
<br />
return True<br />
<br />
<br />
def generatePdb2pqrPqrFile(self,silent=False):<br />
"""use pdb2pqr to generate a pqr file<br />
"""<br />
if not silent:<br />
def show_error(message):<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = message,<br />
)<br />
junk = error_dialog.activate()<br />
else:<br />
def show_error(message):<br />
pass<br />
<br />
#<br />
# First, generate a PDB file<br />
#<br />
pdb_filename = self.pymol_generated_pdb_filename.getvalue()<br />
try:<br />
f = file(pdb_filename,'w')<br />
f.close()<br />
except:<br />
show_error('Please set a temporary PDB file location that you have permission to edit')<br />
return False<br />
# copied from WLD code<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
self.fixColumns(sel)<br />
pymol.cmd.save(pdb_filename,sel)<br />
self.cleanupGeneratedPdbOrPqrFile(pdb_filename)<br />
<br />
#<br />
# Now, generate a PQR file<br />
#<br />
## command_line = '%s %s %s %s'%(self.pdb2pqr.getvalue(),<br />
## self.pdb2pqr_options.getvalue(),<br />
## pdb_filename,<br />
## self.pymol_generated_pqr_filename.getvalue(),<br />
## )<br />
## print "RAN",command_line<br />
## result = os.system(command_line)<br />
#<br />
# We have to be a little cute about args, because pdb2pqr_options could have several options in it.<br />
args = '%s %s %s' %(self.pdb2pqr_options.getvalue(),<br />
pdb_filename,<br />
self.pymol_generated_pqr_filename.getvalue(),<br />
) <br />
(retval,progout) = run(self.pdb2pqr.getvalue(),args)<br />
<br />
<br />
if retval != 0:<br />
show_error('Could not run pdb2pqr: %s %s\n\n%s'%(self.pdb2pqr.getvalue(),<br />
args,<br />
progout)<br />
)<br />
return False<br />
self.cleanupGeneratedPdbOrPqrFile(self.pymol_generated_pqr_filename.getvalue())<br />
unassigned_atoms = self.getUnassignedAtomsFromPqr(self.pymol_generated_pqr_filename.getvalue())<br />
if unassigned_atoms:<br />
pymol.cmd.select('unassigned','ID %s'%unassigned_atoms)<br />
message_text = "Unable to assign parameters for the %s atoms in selection 'unassigned'.\nPlease either remove these unassigned atoms and re-start the calculation\nor fix their parameters in the generated PQR file and run the calculation\nusing the modified PQR file (select 'Use another PQR' in 'Main')."%len(unassigned_atoms.split('+'))<br />
print "Unassigned atom IDs",unassigned_atoms<br />
show_error(message_text)<br />
return False<br />
return True<br />
<br />
<br />
def generatePymolPqrFile(self):<br />
"""generate a pqr file from pymol<br />
<br />
This will also call through to champ to set the Hydrogens and charges<br />
if it needs to. If it does that, it may change the value self.selection<br />
to take the new Hydrogens into account.<br />
<br />
To make it worse, APBS seems to freak out when there are chain ids. So,<br />
this gets rid of the chain ids.<br />
<br />
"""<br />
# CHAMP will break in many cases if retain_order is set. So,<br />
# we unset it here and reset it later. Note that it's fine to<br />
# reset it before things are written out.<br />
ret_order = pymol.cmd.get('retain_order')<br />
pymol.cmd.set('retain_order',0)<br />
<br />
# WLD<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
<br />
pqr_filename = self.getPqrFilename()<br />
try:<br />
f = file(pqr_filename,'w')<br />
f.close()<br />
except:<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "Could not write PQR file.\nPlease check that temporary PQR filename is valid.",<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
<br />
# PyMOL + champ == pqr<br />
from chempy.champ import assign<br />
if self.radiobuttons.getvalue() == 'Use PyMOL generated PQR and PyMOL generated Hydrogens and termini':<br />
pymol.cmd.remove('hydro and %s'%sel)<br />
assign.missing_c_termini(sel)<br />
assign.formal_charges(sel)<br />
pymol.cmd.h_add(sel)<br />
# WLD (code now unnecessary)<br />
# new_hydros = '(hydro and neighbor %s)'%sel<br />
# sel = '%s or %s' % (sel,new_hydros)<br />
assign.amber99(sel)<br />
pymol.cmd.set('retain_order',ret_order)<br />
<br />
# WLD (code now unnecessary)<br />
# if not self.selection.getvalue() in '(all) all'.split():<br />
# self.selection.setvalue(sel)<br />
<br />
#<br />
# Get rid of chain information<br />
#<br />
# WLD -- PyMOL now does this automatically with PQR files <br />
# pymol.cmd.alter(sel,'chain = ""')<br />
self.fixColumns(sel)<br />
pymol.cmd.save(pqr_filename,sel)<br />
self.cleanupGeneratedPdbOrPqrFile(pqr_filename)<br />
missed_count = pymol.cmd.count_atoms("("+sel+") and flag 23")<br />
if missed_count > 0:<br />
pymol.cmd.select("unassigned","("+sel+") and flag 23")<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "Unable to assign parameters for the %s atoms in selection 'unassigned'.\nPlease either remove these unassigned atoms and re-start the calculation\nor fix their parameters in the generated PQR file and run the calculation\nusing the modified PQR file (select 'Use another PQR' in 'Main')."%missed_count,<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
return True<br />
<br />
<br />
############################################################<br />
############################################################<br />
############################################################<br />
## ##<br />
## PmwExtensions ##<br />
## ##<br />
############################################################<br />
############################################################<br />
############################################################<br />
<br />
"""<br />
This contains all of the visualization groups that we'll use for our<br />
PMW interface.<br />
"""<br />
<br />
#<br />
# Generically useful PMW extensions<br />
<br />
import os,fnmatch,time<br />
import Tkinter,Pmw<br />
#Pmw.setversion("0.8.5")<br />
<br />
#<br />
# The classes PmwFileDialog and PmwExistingFileDialog and the _errorpop function<br />
# are taken from the Pmw contrib directory. The attribution given in that file<br />
# is:<br />
################################################################################<br />
# Filename dialogs using Pmw<br />
#<br />
# (C) Rob W.W. Hooft, Nonius BV, 1998<br />
#<br />
# Modifications:<br />
#<br />
# J. Willem M. Nissink, Cambridge Crystallographic Data Centre, 8/2002<br />
# Added optional information pane at top of dialog; if option<br />
# 'info' is specified, the text given will be shown (in blue).<br />
# Modified example to show both file and directory-type dialog<br />
#<br />
# No Guarantees. Distribute Freely. <br />
# Please send bug-fixes/patches/features to <r.hooft@euromail.com><br />
#<br />
################################################################################<br />
<br />
def _errorpop(master,text):<br />
d=Pmw.MessageDialog(master,<br />
title="Error", <br />
message_text=text,<br />
buttons=("OK",))<br />
d.component('message').pack(ipadx=15,ipady=15)<br />
d.activate()<br />
d.destroy()<br />
<br />
class PmwFileDialog(Pmw.Dialog):<br />
"""File Dialog using Pmw"""<br />
def __init__(self, parent = None, **kw):<br />
# Define the megawidget options.<br />
optiondefs = (<br />
('filter', '*', self.newfilter),<br />
('directory', os.getcwd(), self.newdir),<br />
('filename', '', self.newfilename),<br />
('historylen',10, None),<br />
('command', None, None),<br />
('info', None, None),<br />
)<br />
self.defineoptions(kw, optiondefs)<br />
# Initialise base class (after defining options).<br />
Pmw.Dialog.__init__(self, parent)<br />
<br />
self.withdraw()<br />
<br />
# Create the components.<br />
interior = self.interior()<br />
<br />
if self['info'] is not None:<br />
rowoffset=1<br />
dn = self.infotxt()<br />
dn.grid(row=0,column=0,columnspan=2,padx=3,pady=3)<br />
else:<br />
rowoffset=0<br />
<br />
dn = self.mkdn()<br />
dn.grid(row=0+rowoffset,column=0,columnspan=2,padx=3,pady=3)<br />
del dn<br />
<br />
# Create the directory list component.<br />
dnb = self.mkdnb()<br />
dnb.grid(row=1+rowoffset,column=0,sticky='news',padx=3,pady=3)<br />
del dnb<br />
<br />
# Create the filename list component.<br />
fnb = self.mkfnb()<br />
fnb.grid(row=1+rowoffset,column=1,sticky='news',padx=3,pady=3)<br />
del fnb<br />
<br />
# Create the filter entry<br />
ft = self.mkft()<br />
ft.grid(row=2+rowoffset,column=0,columnspan=2,padx=3,pady=3)<br />
del ft<br />
<br />
# Create the filename entry<br />
fn = self.mkfn()<br />
fn.grid(row=3+rowoffset,column=0,columnspan=2,padx=3,pady=3)<br />
fn.bind('<Return>',self.okbutton)<br />
del fn<br />
<br />
# Buttonbox already exists<br />
bb=self.component('buttonbox')<br />
bb.add('OK',command=self.okbutton)<br />
bb.add('Cancel',command=self.cancelbutton)<br />
del bb<br />
<br />
Pmw.alignlabels([self.component('filename'),<br />
self.component('filter'),<br />
self.component('dirname')])<br />
<br />
def infotxt(self):<br />
""" Make information block component at the top """<br />
return self.createcomponent(<br />
'infobox',<br />
(), None,<br />
Tkinter.Label, (self.interior(),),<br />
width=51,<br />
relief='groove',<br />
foreground='darkblue',<br />
justify='left',<br />
text=self['info']<br />
)<br />
<br />
def mkdn(self):<br />
"""Make directory name component"""<br />
return self.createcomponent(<br />
'dirname',<br />
(), None,<br />
Pmw.ComboBox, (self.interior(),),<br />
entryfield_value=self['directory'],<br />
entryfield_entry_width=40,<br />
entryfield_validate=self.dirvalidate,<br />
selectioncommand=self.setdir,<br />
labelpos='w',<br />
label_text='Directory:')<br />
<br />
def mkdnb(self):<br />
"""Make directory name box"""<br />
return self.createcomponent(<br />
'dirnamebox',<br />
(), None,<br />
Pmw.ScrolledListBox, (self.interior(),),<br />
label_text='directories',<br />
labelpos='n',<br />
hscrollmode='none',<br />
dblclickcommand=self.selectdir)<br />
<br />
def mkft(self):<br />
"""Make filter"""<br />
return self.createcomponent(<br />
'filter',<br />
(), None,<br />
Pmw.ComboBox, (self.interior(),),<br />
entryfield_value=self['filter'],<br />
entryfield_entry_width=40,<br />
selectioncommand=self.setfilter,<br />
labelpos='w',<br />
label_text='Filter:')<br />
<br />
def mkfnb(self):<br />
"""Make filename list box"""<br />
return self.createcomponent(<br />
'filenamebox',<br />
(), None,<br />
Pmw.ScrolledListBox, (self.interior(),),<br />
label_text='files',<br />
labelpos='n',<br />
hscrollmode='none',<br />
selectioncommand=self.singleselectfile,<br />
dblclickcommand=self.selectfile)<br />
<br />
def mkfn(self):<br />
"""Make file name entry"""<br />
return self.createcomponent(<br />
'filename',<br />
(), None,<br />
Pmw.ComboBox, (self.interior(),),<br />
entryfield_value=self['filename'],<br />
entryfield_entry_width=40,<br />
entryfield_validate=self.filevalidate,<br />
selectioncommand=self.setfilename,<br />
labelpos='w',<br />
label_text='Filename:')<br />
<br />
def dirvalidate(self,string):<br />
if os.path.isdir(string):<br />
return Pmw.OK<br />
else:<br />
return Pmw.PARTIAL<br />
<br />
def filevalidate(self,string):<br />
if string=='':<br />
return Pmw.PARTIAL<br />
elif os.path.isfile(string):<br />
return Pmw.OK<br />
elif os.path.exists(string):<br />
return Pmw.PARTIAL<br />
else:<br />
return Pmw.OK<br />
<br />
def okbutton(self):<br />
"""OK action: user thinks he has input valid data and wants to<br />
proceed. This is also called by <Return> in the filename entry"""<br />
fn=self.component('filename').get()<br />
self.setfilename(fn)<br />
if self.validate(fn):<br />
self.canceled=0<br />
self.deactivate()<br />
<br />
def cancelbutton(self):<br />
"""Cancel the operation"""<br />
self.canceled=1<br />
self.deactivate()<br />
<br />
def tidy(self,w,v):<br />
"""Insert text v into the entry and at the top of the list of <br />
the combobox w, remove duplicates"""<br />
if not v:<br />
return<br />
entry=w.component('entry')<br />
entry.delete(0,'end')<br />
entry.insert(0,v)<br />
list=w.component('scrolledlist')<br />
list.insert(0,v)<br />
index=1<br />
while index<list.index('end'):<br />
k=list.get(index)<br />
if k==v or index>self['historylen']:<br />
list.delete(index)<br />
else:<br />
index=index+1<br />
w.checkentry()<br />
<br />
def setfilename(self,value):<br />
if not value:<br />
return<br />
value=os.path.join(self['directory'],value)<br />
dir,fil=os.path.split(value)<br />
self.configure(directory=dir,filename=value)<br />
<br />
c=self['command']<br />
if callable(c):<br />
c()<br />
<br />
def newfilename(self):<br />
"""Make sure a newly set filename makes it into the combobox list"""<br />
self.tidy(self.component('filename'),self['filename'])<br />
<br />
def setfilter(self,value):<br />
self.configure(filter=value)<br />
<br />
def newfilter(self):<br />
"""Make sure a newly set filter makes it into the combobox list"""<br />
self.tidy(self.component('filter'),self['filter'])<br />
self.fillit()<br />
<br />
def setdir(self,value):<br />
self.configure(directory=value)<br />
<br />
def newdir(self):<br />
"""Make sure a newly set dirname makes it into the combobox list"""<br />
self.tidy(self.component('dirname'),self['directory'])<br />
self.fillit()<br />
<br />
def singleselectfile(self):<br />
"""Single click in file listbox. Move file to "filename" combobox"""<br />
cs=self.component('filenamebox').curselection()<br />
if cs!=():<br />
value=self.component('filenamebox').get(cs)<br />
self.setfilename(value)<br />
<br />
def selectfile(self):<br />
"""Take the selected file from the filename, normalize it, and OK"""<br />
self.singleselectfile()<br />
value=self.component('filename').get()<br />
self.setfilename(value)<br />
if value:<br />
self.okbutton()<br />
<br />
def selectdir(self):<br />
"""Take selected directory from the dirnamebox into the dirname"""<br />
cs=self.component('dirnamebox').curselection()<br />
if cs!=():<br />
value=self.component('dirnamebox').get(cs)<br />
dir=self['directory']<br />
if not dir:<br />
dir=os.getcwd()<br />
if value:<br />
if value=='..':<br />
dir=os.path.split(dir)[0]<br />
else:<br />
dir=os.path.join(dir,value)<br />
self.configure(directory=dir)<br />
self.fillit()<br />
<br />
def askfilename(self,directory=None,filter=None):<br />
"""The actual client function. Activates the dialog, and<br />
returns only after a valid filename has been entered <br />
(return value is that filename) or when canceled (return <br />
value is None)"""<br />
if directory!=None:<br />
self.configure(directory=directory)<br />
if filter!=None:<br />
self.configure(filter=filter)<br />
self.fillit()<br />
self.canceled=1 # Needed for when user kills dialog window<br />
self.activate()<br />
if self.canceled:<br />
return None<br />
else:<br />
return self.component('filename').get()<br />
<br />
lastdir=""<br />
lastfilter=None<br />
lasttime=0<br />
def fillit(self):<br />
"""Get the directory list and show it in the two listboxes"""<br />
# Do not run unnecesarily<br />
if self.lastdir==self['directory'] and self.lastfilter==self['filter'] and self.lasttime>os.stat(self.lastdir)[8]:<br />
return<br />
self.lastdir=self['directory']<br />
self.lastfilter=self['filter']<br />
self.lasttime=time.time()<br />
dir=self['directory']<br />
if not dir:<br />
dir=os.getcwd()<br />
dirs=['..']<br />
files=[]<br />
try:<br />
fl=os.listdir(dir)<br />
fl.sort()<br />
except os.error,arg:<br />
if arg[0] in (2,20):<br />
return<br />
raise<br />
for f in fl:<br />
if os.path.isdir(os.path.join(dir,f)):<br />
dirs.append(f)<br />
else:<br />
filter=self['filter']<br />
if not filter:<br />
filter='*'<br />
if fnmatch.fnmatch(f,filter):<br />
files.append(f)<br />
self.component('filenamebox').setlist(files)<br />
self.component('dirnamebox').setlist(dirs)<br />
<br />
def validate(self,filename):<br />
"""Validation function. Should return 1 if the filename is valid, <br />
0 if invalid. May pop up dialogs to tell user why. Especially <br />
suited to subclasses: i.e. only return 1 if the file does/doesn't <br />
exist"""<br />
return 1<br />
<br />
<br />
class PmwExistingFileDialog(PmwFileDialog):<br />
def filevalidate(self,string):<br />
if os.path.isfile(string):<br />
return Pmw.OK<br />
else:<br />
return Pmw.PARTIAL<br />
<br />
def validate(self,filename):<br />
if os.path.isfile(filename):<br />
return 1<br />
elif os.path.exists(filename):<br />
_errorpop(self.interior(),"This is not a plain file")<br />
return 0<br />
else:<br />
_errorpop(self.interior(),"Please select an existing file")<br />
return 0<br />
<br />
class FileDialogButtonClassFactory:<br />
def get(fn,filter='*'):<br />
"""This returns a FileDialogButton class that will<br />
call the specified function with the resulting file.<br />
"""<br />
class FileDialogButton(Tkinter.Button):<br />
# This is just an ordinary button with special colors.<br />
<br />
def __init__(self, master=None, cnf={}, **kw):<br />
'''when we get a file, we call fn(filename)'''<br />
self.fn = fn<br />
self.__toggle = 0<br />
apply(Tkinter.Button.__init__, (self, master, cnf), kw)<br />
self.configure(command=self.set)<br />
def set(self):<br />
fd = PmwFileDialog(self.master,filter=filter)<br />
fd.title('Please choose a file')<br />
n=fd.askfilename()<br />
if n is not None:<br />
self.fn(n)<br />
return FileDialogButton<br />
get = staticmethod(get)<br />
<br />
############################################################<br />
############################################################<br />
############################################################<br />
## ##<br />
## PmwGroups ##<br />
## ##<br />
############################################################<br />
############################################################<br />
############################################################<br />
class VisualizationGroup(Pmw.Group):<br />
def __init__(self,*args,**kwargs):<br />
my_options = 'visgroup_num'.split()<br />
for option in my_options:<br />
# use these options as attributes of this class<br />
# and remove them from the kwargs dict before<br />
# passing on to Pmw.Group.__init__().<br />
setattr(self,option,kwargs.pop(option))<br />
kwargs['tag_text'] = kwargs['tag_text'] + ' (%s)'%self.visgroup_num<br />
Pmw.Group.__init__(self,*args,**kwargs)<br />
self.refresh()<br />
self.show_ms = False<br />
self.show_pi = False<br />
self.show_ni = False<br />
def refresh(self):<br />
things_to_kill = 'error_label update_buttonbox mm_group ms_group pi_group ni_group'.split()<br />
for thing in things_to_kill:<br />
try:<br />
getattr(self,thing).destroy()<br />
#print "destroyed",thing<br />
except AttributeError:<br />
#print "couldn't destroy",thing<br />
<br />
# note: this attributeerror will also hit if getattr(self,thing) misses.<br />
# another note: both halves of the if/else make an update_buttonbox.<br />
# if you rename the one in the top half to something else, you'll cause nasty Pmw errors.<br />
pass<br />
if [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'] and [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule']:<br />
self.mm_group = Pmw.Group(self.interior(),tag_text = 'Maps and Molecules')<br />
self.map = Pmw.OptionMenu(self.mm_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Map',<br />
items = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'],<br />
)<br />
self.map.pack(padx=4,side=LEFT)<br />
<br />
self.molecule = Pmw.OptionMenu(self.mm_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Molecule',<br />
items = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule'],<br />
)<br />
self.molecule.pack(padx=4,side=LEFT)<br />
self.update_buttonbox = Pmw.ButtonBox(self.mm_group.interior(), padx=0)<br />
self.update_buttonbox.pack(side=LEFT)<br />
self.update_buttonbox.add('Update',command=self.refresh)<br />
self.mm_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=TOP)<br />
<br />
self.ms_group = Pmw.Group(self.interior(),tag_text='Molecular Surface')<br />
self.ms_buttonbox = Pmw.ButtonBox(self.ms_group.interior(), padx=0)<br />
self.ms_buttonbox.pack()<br />
self.ms_buttonbox.add('Show',command=self.showMolSurface)<br />
self.ms_buttonbox.add('Hide',command=self.hideMolSurface)<br />
self.ms_buttonbox.add('Update',command=self.updateMolSurface)<br />
self.ms_buttonbox.alignbuttons()<br />
self.surface_solvent = IntVar()<br />
self.surface_solvent.set(APBSTools2.defaults['surface_solvent'])<br />
self.sol_checkbutton = Checkbutton(self.ms_group.interior(),<br />
text = "Solvent accessible surface",<br />
variable = self.surface_solvent)<br />
self.sol_checkbutton.pack() <br />
self.potential_at_sas = IntVar()<br />
self.potential_at_sas.set(APBSTools2.defaults['potential_at_sas'])<br />
self.pot_checkbutton = Checkbutton(self.ms_group.interior(),<br />
text = "Color by potential on sol. acc. surf.",<br />
variable = self.potential_at_sas)<br />
self.pot_checkbutton.pack()<br />
self.mol_surf_low = Pmw.Counter(self.ms_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Low',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = -1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real'},<br />
)<br />
self.mol_surf_middle = Pmw.Counter(self.ms_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Middle',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = 0,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real'}<br />
)<br />
self.mol_surf_high = Pmw.Counter(self.ms_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'High',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = 1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real'}<br />
)<br />
bars = (self.mol_surf_low,self.mol_surf_middle,self.mol_surf_high)<br />
Pmw.alignlabels(bars)<br />
for bar in bars: bar.pack(side=LEFT)<br />
self.ms_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=LEFT)<br />
<br />
self.pi_group = Pmw.Group(self.interior(),tag_text='Positive Isosurface')<br />
self.pi_buttonbox = Pmw.ButtonBox(self.pi_group.interior(), padx=0)<br />
self.pi_buttonbox.pack()<br />
self.pi_buttonbox.add('Show',command=self.showPosSurface)<br />
self.pi_buttonbox.add('Hide',command=self.hidePosSurface)<br />
self.pi_buttonbox.add('Update',command=self.updatePosSurface)<br />
self.pi_buttonbox.alignbuttons()<br />
self.pos_surf_val = Pmw.Counter(self.pi_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Contour (kT/e)',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = 1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real', 'min':0}<br />
)<br />
self.pos_surf_val.pack(side=LEFT)<br />
self.pi_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=LEFT)<br />
<br />
self.ni_group = Pmw.Group(self.interior(),tag_text='Negative Isosurface')<br />
self.ni_buttonbox = Pmw.ButtonBox(self.ni_group.interior(), padx=0)<br />
self.ni_buttonbox.pack()<br />
self.ni_buttonbox.add('Show',command=self.showNegSurface)<br />
self.ni_buttonbox.add('Hide',command=self.hideNegSurface)<br />
self.ni_buttonbox.add('Update',command=self.updateNegSurface)<br />
self.ni_buttonbox.alignbuttons()<br />
self.neg_surf_val = Pmw.Counter(self.ni_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Contour (kT/e)',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = -1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real', 'max':0}<br />
)<br />
self.neg_surf_val.pack(side=LEFT)<br />
self.ni_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=LEFT)<br />
<br />
else:<br />
self.error_label = Tkinter.Label(self.interior(),<br />
pady = 10,<br />
justify=LEFT,<br />
text = '''You must have at least a molecule and a map loaded.<br />
If you have a molecule and a map loaded, please click "Update"''',<br />
)<br />
self.error_label.pack()<br />
self.update_buttonbox = Pmw.ButtonBox(self.interior(), padx=0)<br />
self.update_buttonbox.pack()<br />
self.update_buttonbox.add('Update',command=self.refresh)<br />
<br />
def showMolSurface(self):<br />
self.updateMolSurface()<br />
<br />
def hideMolSurface(self):<br />
pymol.cmd.hide('surface',self.molecule.getvalue())<br />
<br />
def getRampName(self):<br />
#return 'e_lvl'<br />
idx = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule'].index(self.molecule.getvalue())<br />
return '_'.join(('e_lvl',str(idx),str(self.visgroup_num)))<br />
<br />
def getIsoPosName(self):<br />
idx = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'].index(self.map.getvalue())<br />
return '_'.join(('iso_pos',str(idx),str(self.visgroup_num)))<br />
<br />
def getIsoNegName(self):<br />
idx = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'].index(self.map.getvalue())<br />
return '_'.join(('iso_neg',str(idx),str(self.visgroup_num)))<br />
<br />
def updateMolSurface(self):<br />
molecule_name = self.molecule.getvalue()<br />
ramp_name = self.getRampName()<br />
map_name = self.map.getvalue()<br />
low = float(self.mol_surf_low.getvalue())<br />
mid = float(self.mol_surf_middle.getvalue())<br />
high = float(self.mol_surf_high.getvalue())<br />
range = [low,mid,high]<br />
print " APBS Tools: range is",range<br />
pymol.cmd.delete(ramp_name)<br />
pymol.cmd.ramp_new(ramp_name,map_name,range)<br />
pymol.cmd.set('surface_color',ramp_name,molecule_name)<br />
if self.surface_solvent.get()==1:<br />
pymol.cmd.set('surface_solvent',1,molecule_name)<br />
pymol.cmd.set('surface_ramp_above_mode',0,molecule_name)<br />
else:<br />
pymol.cmd.set('surface_solvent',0,molecule_name)<br />
pymol.cmd.set('surface_ramp_above_mode',self.potential_at_sas.get(),molecule_name)<br />
pymol.cmd.show('surface',molecule_name)<br />
pymol.cmd.refresh()<br />
pymol.cmd.recolor(molecule_name)<br />
<br />
def showPosSurface(self):<br />
self.updatePosSurface()<br />
def hidePosSurface(self):<br />
pymol.cmd.hide('everything',self.getIsoPosName())<br />
def updatePosSurface(self):<br />
pymol.cmd.delete(self.getIsoPosName())<br />
pymol.cmd.isosurface(self.getIsoPosName(),self.map.getvalue(),float(self.pos_surf_val.getvalue()))<br />
pymol.cmd.color('blue',self.getIsoPosName())<br />
pymol.cmd.show('everything',self.getIsoPosName())<br />
def showNegSurface(self):<br />
self.updateNegSurface()<br />
def hideNegSurface(self):<br />
pymol.cmd.hide('everything',self.getIsoNegName())<br />
def updateNegSurface(self):<br />
pymol.cmd.delete(self.getIsoNegName())<br />
pymol.cmd.isosurface(self.getIsoNegName(),self.map.getvalue(),float(self.neg_surf_val.getvalue()))<br />
pymol.cmd.color('red',self.getIsoNegName())<br />
pymol.cmd.show('everything',self.getIsoNegName())<br />
<br />
<br />
</source><br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3160User:Mglerner2010-01-28T20:12:24Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= Check out a new pre-release version of the PyMOL-APBS plugin! =<br />
<br />
== New Features ==<br />
<br />
I've been working with Jason Vertrees on a new version of the PyMOL-APBS plugin and it's now ready for pre-release. There are three big advantages of the new version:<br />
<br />
1. It's been tested modern OS X, Windows and Linux systems and fixes several long-standing bugs.<br />
2. It allows you to call through to PDB2PQR directly.<br />
3. It has two visualization panels to aid in showing multiple potential surfaces at once.<br />
<br />
I've also upped the default maximum allowed memory since typical users have bigger and faster computers these days.<br />
<br />
A slightly longer list of changes is included below. <br />
<br />
== How to get it ==<br />
<br />
There are two ways to get the new plugin<br />
<br />
1. If you have subversion installed,<br />
<br />
<source lang="bash"><br />
svn co https://pymolapbsplugin.svn.sourceforge.net/svnroot/pymolapbsplugin/trunk/pymolapbsplugin<br />
</source><br />
<br />
2. Copy the text directly from http://pymolwiki.org/index.php/User:Mglerner and put it in a file called apbsplugin.py<br />
<br />
Once you have the plugin, you can install it via PyMOL's plugin installer: Plugin --> Manage Plugins --> Install<br />
<br />
Note that the plugin will be installed as "APBS Tools2" so that you can continue to use your old version.<br />
<br />
== Longer feature list ==<br />
<br />
* The ability to call through directly to PDB2PQR<br />
* More modern apbs input files<br />
* Two visualization panels. It's often quite useful to look at two different electrostatic potentials at once. It's also quite useful to look at electrostatic potentials mapped onto two different surfaces at once. Multiple visualization panels makes this a snap: just set up one surface on panel 1 and another surface on panel 2.<br />
* Fixes several bugs that caused crashes on both OS X and Linux systems<br />
* Increased maximum allowed memory<br />
* Switch from os.system to subprocess for running external programs<br />
* Deals with paths on Windows properly<br />
* Gives better diagnostic information so that PyMOL/APBS developers can find bugs more easily<br />
* Lots of internal code cleanup<br />
<br />
== Plugin code ==<br />
<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
<br />
# TODO:<br />
# - provide diff for pdb2pqr freemol<br />
# - use remove_alt to count alternate atom locations and warn the user<br />
#<br />
# - Note to users that they should remove freemol's pymol.exe on OS X.<br />
<br />
### (all) and resn glu and resi 154+157<br />
### flag ignore, atom-selection, clear<br />
<br />
# APBS TOOLS Copyright Notice<br />
# ============================<br />
#<br />
# The APBS TOOLS source code is copyrighted, but you can freely use and<br />
# copy it as long as you don't change or remove any of the copyright<br />
# notices.<br />
#<br />
# ----------------------------------------------------------------------<br />
# APBS TOOLS is Copyright (C) 2009 by Michael G. Lerner<br />
#<br />
# All Rights Reserved<br />
#<br />
# Permission to use, copy, modify, distribute, and distribute modified<br />
# versions of this software and its documentation for any purpose and<br />
# without fee is hereby granted, provided that the above copyright<br />
# notice appear in all copies and that both the copyright notice and<br />
# this permission notice appear in supporting documentation, and that<br />
# the name of Michael G. Lerner not be used in advertising or publicity<br />
# pertaining to distribution of the software without specific, written<br />
# prior permission.<br />
#<br />
# MICHAEL G. LERNER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS<br />
# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND<br />
# FITNESS. IN NO EVENT SHALL MICHAEL G. LERNER BE LIABLE FOR ANY<br />
# SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER<br />
# RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF<br />
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN<br />
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.<br />
# ----------------------------------------------------------------------<br />
<br />
"""<br />
<br />
A NOTE TO USERS:<br />
<br />
You can change the default locations for the APBS and PDB2PQR binaries<br />
as well as the default temporary file directory below. If you set them<br />
in this file, they will be preserved each time you load up the<br />
plugin. Scroll down to the section entitled "Global config variables"<br />
(no quotes) below.<br />
<br />
A NOTE TO OTHER DEVELOPERS:<br />
<br />
I understand that I'm giving this code away for Free, and that there's<br />
not a ton of great sample PyMOL plugin code out there, so you're<br />
certainly encouraged to use this as a template. However, please<br />
acknowledge me in some way if you do (somewhere in the comments if you<br />
only use a little bit of code or something more if you use a lot).<br />
<br />
Thanks.<br />
<br />
-Michael<br />
<br />
Features under consideration:<br />
<br />
- Use 'acc' to calculate solvent-accessible surface areas. We'll use<br />
the PyMOL 'standard' method and store this data as B-factors.<br />
- Show the field lines. Relevant code from menu.py:<br />
<br />
def map_gradient(self_cmd, sele):<br />
return [[ 2, 'Gradient:', '' ],<br />
[ 1, 'default' , 'cmd.gradient("'+sele+'_grad","'+sele+'");cmd.ramp_new("'+sele+<br />
'_grad_ramp","'+sele+'");cmd.color("'+sele+'_grad_ramp","'+sele+'_grad");' ]<br />
]<br />
<br />
Known hacks:<br />
<br />
<br />
1. (code in execute() )There's a bug in the version of APBS shipped<br />
with Ubuntu 9.10 (version 1.1.0) that causes the name to become<br />
foo-PE0.dx instead of foo.dx. This would normally only occur in<br />
mg-para calcs or MPI versions of apbs. It's clearly bug-possible,<br />
but we will check for foo-PE0 if we can't find foo.dx.<br />
<br />
2. We look for dylib errors in the APBS executable that's shipped with<br />
freemol on OS X. Code in get_default()'s verify().<br />
<br />
"""<br />
from __future__ import division<br />
from __future__ import generators<br />
<br />
global DEBUG<br />
DEBUG = 1<br />
<br />
APBS_DEFAULT=True<br />
<br />
import os,math,re<br />
import string<br />
import Tkinter<br />
from Tkinter import *<br />
import Pmw<br />
import distutils.spawn # used for find_executable<br />
import traceback<br />
import pymol<br />
<br />
#<br />
# Global config variables<br />
#<br />
# To change the default locations, change these to something like<br />
# APBS_BINARY_LOCATION = '/opt/bin/apbs'<br />
#<br />
APBS_BINARY_LOCATION = None<br />
APBS_PSIZE_LOCATION = None<br />
APBS_PDB2PQR_LOCATION = None<br />
TEMPORARY_FILE_DIR = None<br />
<br />
apbs_plea = ("IMPORTANT REQUEST: If you have not already done so, please register\n"<br />
"your use of the open-source Adaptive Poisson-Boltzmann Solver (APBS) at\n"<br />
"-> http://agave.wustl.edu/apbs/download\n"<br />
"Such proof of usage is vital in securing funding for APBS development!\n")<br />
<br />
pdb2pqr_plea = ("IMPORTANT REQUEST: If you have not already done so, please register\n"<br />
"your use of the open-source PDB2PQR at\n"<br />
"-> http://www.poissonboltzmann.org/pdb2pqr/d\n"<br />
"Such proof of usage is vital in securing funding for PDB2PQR development!\n")<br />
global apbs_message, pdb2pqr_message<br />
apbs_message = """You must have APBS installed on your system."""<br />
pdb2pqr_message = """PDB2PQR can be used to generate .PQR files."""<br />
<br />
def get_default_location(name):<br />
"""<br />
Given the name of an APBS-related binary, look in<br />
* pymol path,<br />
* freemol path,<br />
* user defined places,<br />
* the system path,<br />
* Known other paths (/usr/local/bin and /opt/local/bin)<br />
for the parameter, name.<br />
<br />
Some programs are verified with additional tests. In particular,<br />
some versions of PyMOL ship with a broken apbs.exe, so we verify<br />
that it can be run.<br />
<br />
PARAMS<br />
name, (string) the basename of the file we're looking for<br />
EXAMPLE<br />
get_default_location("apbs.exe")<br />
RETURNS<br />
(string) path/to/file on success or "" on failure<br />
NOTES<br />
For any program name <foo>.exe we will also search for<br />
<foo>. We'll search for the .exe version first. We do not<br />
automatically check for .exe versions of programs when .exe is<br />
not specified.<br />
"""<br />
def verify(name,f):<br />
if name in 'apbs.exe apbs'.split():<br />
# You'd think we could just check the return code, but<br />
# APBS doesn't return zero on success. Instead, it returns<br />
# things like 3328. It seems to return 5 or -5 in this<br />
# particular failure case, but I'm not sure we can depend<br />
# on that always.<br />
(retcode,prog_out) = run(f,'--version')<br />
if 'dyld: Library not loaded' in prog_out:<br />
print "Skipping",f,"because it appears to be broken (dyld)"<br />
return False<br />
return True<br />
searchDirs = []<br />
if "FREEMOL" in os.environ:<br />
searchDirs.append(os.environ["FREEMOL"])<br />
if "PYMOL_PATH" in os.environ:<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "ext", "bin"))<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "freemol", "bin"))<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "freemol", "share", "apbs"))<br />
searchDirs.append(os.path.join(os.environ["PYMOL_PATH"], "freemol", "share", "pdb2pqr"))<br />
for x in (APBS_BINARY_LOCATION, APBS_PSIZE_LOCATION, APBS_PDB2PQR_LOCATION):<br />
if x != None and x != "":<br />
searchDirs.append(x)<br />
if name=="temp":<br />
searchDirs = []<br />
if TEMPORARY_FILE_DIR != None and TEMPORARY_FILE_DIR != "":<br />
searchDirs.append(TEMPORARY_FILE_DIR)<br />
searchDirs.append("/tmp")<br />
searchDirs.append(".")<br />
<br />
searchDirs.extend(string.split(os.environ["PATH"], ":"))<br />
searchDirs.append(os.path.join("/usr", "local", "bin"))<br />
searchDirs.append(os.path.join("/opt", "local", "bin"))<br />
<br />
print "Search dirs",searchDirs<br />
<br />
if DEBUG:<br />
print "get_default_location will search the following: ", searchDirs<br />
for d in searchDirs:<br />
if name=="temp":<br />
f = d # just search for the directory<br />
else:<br />
f = os.path.join( d, name ) # make path/name.py<br />
print "trying",f<br />
if os.path.exists(f) and verify(name,f):<br />
return f<br />
elif name.endswith('.exe'):<br />
f = os.path.join( d, name[:-4] ) # make path/name.py<br />
if os.path.exists(f) and verify(name,f):<br />
return f<br />
<br />
print "Could not find default location for file: %s" % name<br />
return ""<br />
<br />
def __init__(self):<br />
"""<br />
Init PyMOL, by adding APBSTools to the GUI under Plugins<br />
<br />
Creates the APBS widget/notebook. Once the event is received,<br />
we create a new instance of APBSTools2 which is a Pmw, which upon<br />
creation shows itself.<br />
"""<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Launch APBS Tools2',<br />
label='APBS Tools2...',<br />
command = lambda s=self: APBSTools2(s))<br />
<br />
def run(prog,args):<br />
'''<br />
wrapper to handle spaces on windows.<br />
prog is the full path to the program.<br />
args is a string that we will split up for you.<br />
or a tuple. or a list. your call.<br />
<br />
return value is (retval,prog_out)<br />
<br />
e.g.<br />
<br />
(retval,prog_out) = run("/bin/ls","-al /tmp/myusername")<br />
'''<br />
import subprocess,tempfile<br />
<br />
if type(args) == type(''):<br />
args = tuple(args.split())<br />
elif type(args) in (type([]),type(())):<br />
args = tuple(args)<br />
args = (prog,) + args<br />
<br />
try:<br />
output_file = tempfile.TemporaryFile(mode="w+") # <-- shouldn't this point to the temp dir<br />
except IOError:<br />
print "Error opening output_file when trying to run the APBS command."<br />
<br />
print "Running",args<br />
retcode = subprocess.call(args,stdout=output_file.fileno(),stderr=subprocess.STDOUT)<br />
output_file.seek(0)<br />
#prog_out = output_file.read()<br />
prog_out = ''.join(output_file.readlines())<br />
output_file.close() #windows doesn't do this automatically<br />
if DEBUG:<br />
print "Results were:"<br />
print "Return value:",retcode<br />
print "Output:"<br />
print prog_out<br />
return (retcode,prog_out)<br />
<br />
class util:<br />
"""<br />
A quick collection of utility functions.<br />
"""<br />
#@staticmethod<br />
def getMolecules():<br />
"""returns all molecules that PyMOL knows about"""<br />
return [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule']<br />
getMolecules = staticmethod(getMolecules)<br />
#@staticmethod<br />
def getMaps():<br />
"""returns all maps that PyMOL knows about"""<br />
return [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map']<br />
getMaps = staticmethod(getMaps)<br />
#def hasAlt(sel):<br />
# """returns true if non-standard locations (rotamers) are present for this selection"""<br />
# return cmd.count_atoms(sel + " and not alt ''")!=0<br />
#hasAlt = staticmethod(hasAlt)<br />
<br />
util = util()<br />
<br />
##############################################################################<br />
##############################################################################<br />
### ###<br />
### ApbsInterface ###<br />
### ###<br />
##############################################################################<br />
##############################################################################<br />
<br />
def getApbsInputFile(pqr_filename,<br />
grid_points,<br />
cglen,<br />
fglen,<br />
cent,<br />
apbs_mode,<br />
bcfl,<br />
ion_plus_one_conc,ion_plus_one_rad,<br />
ion_minus_one_conc,ion_minus_one_rad,<br />
ion_plus_two_conc,ion_plus_two_rad,<br />
ion_minus_two_conc,ion_minus_two_rad,<br />
interior_dielectric, solvent_dielectric,<br />
chgm,<br />
srfm,<br />
solvent_radius,<br />
system_temp,<br />
sdens,<br />
dx_filename,<br />
):<br />
print "Getting APBS input"<br />
#print "system_temp",system_temp,type(system_temp)<br />
#print "sdens",sdens,type(sdens)<br />
#<br />
# How shall we set up the grid? We'll use cglen, fglen, cgcent, fgcent<br />
# and dime.<br />
# This allows people to automate things (e.g. "Alanine scanning")<br />
#<br />
<br />
#<br />
# New template using mg-auto<br />
# See http://agave.wustl.edu/apbs/doc/api/html/#mg-auto<br />
#<br />
<br />
apbs_template = """#<br />
# Note that most of the comments here were taken from sample<br />
# input files that came with APBS. You can find APBS at<br />
# http://agave.wustl.edu/apbs/<br />
# Note that APBS is GPL'd code.<br />
#<br />
read<br />
mol pqr %s # read molecule 1<br />
end<br />
elec<br />
mg-auto<br />
dime %d %d %d # number of find grid points<br />
# calculated by psize.py<br />
cglen %f %f %f # coarse mesh lengths (A)<br />
fglen %f %f %f # fine mesh lengths (A)<br />
# calculated by psize.py<br />
cgcent %f %f %f # (could also give (x,y,z) form psize.py) #known center<br />
fgcent %f %f %f # (could also give (x,y,z) form psize.py) #known center<br />
%s # solve the full nonlinear PBE with npbe<br />
#lpbe # solve the linear PBE with lpbe<br />
bcfl %s # Boundary condition flag<br />
# 0 => Zero<br />
# 1 => Single DH sphere<br />
# 2 => Multiple DH spheres<br />
# 4 => Focusing<br />
#<br />
#ion 1 0.000 2.0 # Counterion declaration:<br />
ion charge 1 conc %f radius %f # Counterion declaration:<br />
ion charge -1 conc %f radius %f # ion <charge> <conc (M)> <radius><br />
ion charge 2 conc %f radius %f # ion <charge> <conc (M)> <radius><br />
ion charge -2 conc %f radius %f # ion <charge> <conc (M)> <radius><br />
pdie %f # Solute dielectric<br />
sdie %f # Solvent dielectric<br />
chgm %s # Charge disc method<br />
# 0 is linear splines<br />
# 1 is cubic b-splines<br />
mol 1 # which molecule to use<br />
srfm smol # Surface calculation method<br />
# 0 => Mol surface for epsilon;<br />
# inflated VdW for kappa; no<br />
# smoothing<br />
# 1 => As 0 with harmoinc average<br />
# smoothing<br />
# 2 => Cubic spline <br />
srad %f # Solvent radius (1.4 for water)<br />
swin 0.3 # Surface cubic spline window .. default 0.3<br />
temp %f # System temperature (298.15 default)<br />
sdens %f # Specify the number of grid points per square-angstrom to use in Vacc object. Ignored when srad is 0.0 (see srad) or srfm is spl2 (see srfm). There is a direct correlation between the value used for the Vacc sphere density, the accuracy of the Vacc object, and the APBS calculation time. APBS default value is 10.0.<br />
#gamma 0.105 # Surface tension parameter for apolar forces (in kJ/mol/A^2)<br />
# only used for force calculations, so we don't care, but<br />
# it *used to be* always required, and 0.105 is the default<br />
calcenergy no # Energy I/O to stdout<br />
# 0 => don't write out energy<br />
# 1 => write out total energy<br />
# 2 => write out total energy and all<br />
# components<br />
calcforce no # Atomic forces I/O (to stdout)<br />
# 0 => don't write out forces<br />
# 1 => write out net forces on molecule<br />
# 2 => write out atom-level forces<br />
write pot dx %s # What to write .. this says write the potential in dx<br />
# format to a file.<br />
end<br />
quit<br />
<br />
"""<br />
return apbs_template % (pqr_filename,<br />
grid_points[0], grid_points[1], grid_points[2],<br />
cglen[0],cglen[1],cglen[2],<br />
fglen[0],fglen[1],fglen[2],<br />
cent[0],cent[1],cent[2],<br />
cent[0],cent[1],cent[2],<br />
apbs_mode,<br />
bcfl,<br />
ion_plus_one_conc,ion_plus_one_rad,<br />
ion_minus_one_conc,ion_minus_one_rad,<br />
ion_plus_two_conc,ion_plus_two_rad,<br />
ion_minus_two_conc,ion_minus_two_rad,<br />
interior_dielectric, solvent_dielectric,<br />
chgm,<br />
solvent_radius,<br />
system_temp,<br />
sdens,<br />
dx_filename,<br />
)<br />
<br />
<br />
<br />
##############################################################################<br />
##############################################################################<br />
### ###<br />
### PluginCode ###<br />
### ###<br />
##############################################################################<br />
##############################################################################<br />
<br />
<br />
<br />
class APBSTools2:<br />
# The current goal is to factor all of the APBS-specific code into<br />
# an ApbsInterface class. The functions defined here before<br />
# __init__, as well as the functions defined on the various<br />
# Panels/Panes, will call through to self.ApbsInterface.<br />
def setPqrFile(self,name):<br />
print " APBS Tools: set pqr file to",name<br />
self.pqr_to_use.setvalue(name)<br />
self.radiobuttons.setvalue('Use another PQR')<br />
def getPqrFilename(self):<br />
if self.radiobuttons.getvalue() != 'Use another PQR':<br />
return self.pymol_generated_pqr_filename.getvalue()<br />
else:<br />
return self.pqr_to_use.getvalue()<br />
def setPsizeLocation(self,value):<br />
self.psize.setvalue(value)<br />
def setBinaryLocation(self,value):<br />
self.binary.setvalue(value)<br />
def setPdb2pqrLocation(self,value):<br />
self.pdb2pqr.setvalue(value)<br />
<br />
def setPymolGeneratedPqrFilename(self,value):<br />
self.pymol_generated_pqr_filename.setvalue(value)<br />
def setPymolGeneratedPdbFilename(self,value):<br />
self.pymol_generated_pdb_filename.setvalue(value)<br />
def setPymolGeneratedDxFilename(self,value):<br />
self.pymol_generated_dx_filename.setvalue(value)<br />
def setPymolGeneratedInFilename(self,value):<br />
self.pymol_generated_in_filename.setvalue(value)<br />
<br />
<br />
def getPymolGeneratedPqrFilename(self):<br />
return self.pymol_generated_pqr_filename.getvalue()<br />
def getPymolGeneratedPdbFilename(self):<br />
return self.pymol_generated_pdb_filename.getvalue()<br />
def getPymolGeneratedDxFilename(self):<br />
return self.pymol_generated_dx_filename.getvalue()<br />
def getPymolGeneratedInFilename(self):<br />
return self.pymol_generated_in_filename.getvalue()<br />
defaults = {<br />
"interior_dielectric" : 2.0,<br />
"solvent_dielectric" : 78.0,<br />
"solvent_radius" : 1.4,<br />
"system_temp" : 310.0,<br />
"apbs_mode" : 'Linearized Poisson-Boltzmann Equation',<br />
"ion_plus_one_conc" : 0.15,<br />
"ion_plus_one_rad" : 2.0,<br />
"ion_plus_two_conc" : 0.0,<br />
"ion_plus_two_rad" : 2.0,<br />
"ion_minus_one_conc" : 0.15,<br />
"ion_minus_one_rad" : 1.8,<br />
"ion_minus_two_conc" : 0.0,<br />
"ion_minus_two_rad" : 2.0,<br />
#"max_mem_allowed" : 400,<br />
"max_mem_allowed" : 1500,<br />
"potential_at_sas" : 0,<br />
"surface_solvent" : 1,<br />
"show_surface_for_scanning" : 1,<br />
#"grid_buffer" : 0,<br />
#"grid_buffer" : 20,<br />
"bcfl" : 'Single DH sphere', # Boundary condition flag for APBS<br />
"sdens": 10.0, # Specify the number of grid points per<br />
# square-angstrom to use in Vacc<br />
# object. Ignored when srad is 0.0 (see srad)<br />
# or srfm is spl2 (see srfm). There is a direct<br />
# correlation between the value used for the<br />
# Vacc sphere density, the accuracy of the Vacc<br />
# object, and the APBS calculation time. APBS<br />
# default value is 10.0.<br />
"chgm" : 'Cubic B-splines', # Charge disc method for APBS<br />
}<br />
<br />
def __init__(self,app):<br />
self.parent = app.root<br />
<br />
# Create the dialog.<br />
self.dialog = Pmw.Dialog(self.parent,<br />
buttons = ('Register APBS Use', 'Register PDB2PQR Use', 'Set grid', 'Run APBS', 'Exit APBS tools'),<br />
title = 'PyMOL APBS Tools',<br />
command = self.execute)<br />
self.dialog.withdraw()<br />
Pmw.setbusycursorattributes(self.dialog.component('hull'))<br />
<br />
w = Tkinter.Label(self.dialog.interior(),<br />
text = 'PyMOL APBS Tools\nMichael G. Lerner, Heather A. Carlson, 2009 - http://pymolwiki.org/index.php/APBS\n(incorporates modifications by Warren L. DeLano)',<br />
background = 'black',<br />
foreground = 'white',<br />
#pady = 20,<br />
)<br />
w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)<br />
<br />
self.notebook = Pmw.NoteBook(self.dialog.interior())<br />
self.notebook.pack(fill='both',expand=1,padx=10,pady=10)<br />
<br />
# Set up the Main page<br />
page = self.notebook.add('Main')<br />
group = Pmw.Group(page,tag_text='Main options')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.selection = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Selection to use: ',<br />
value='(polymer)',<br />
)<br />
self.map = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='What to call the resulting map: ',<br />
value='apbs_map',<br />
)<br />
self.radiobuttons = Pmw.RadioSelect(group.interior(),<br />
buttontype = 'radiobutton',<br />
orient = 'vertical',<br />
labelpos = 'w',<br />
)<br />
for text in ('Use PyMOL generated PQR and existing Hydrogens and termini',<br />
'Use PyMOL generated PQR and PyMOL generated Hydrogens and termini',<br />
'Use another PQR',<br />
'Use PDB2PQR',):<br />
self.radiobuttons.add(text)<br />
self.radiobuttons.setvalue('Use PyMOL generated PQR and PyMOL generated Hydrogens and termini')<br />
<br />
self.pdb2pqr_options = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='pdb2pqr command line options: ',<br />
value='--ff=AMBER',<br />
)<br />
self.pqr_to_use = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPqrFile,'*.pqr'),<br />
label_text='\tChoose Externally Generated PQR:',<br />
)<br />
<br />
<br />
<br />
for entry in (self.selection,self.map,self.radiobuttons,self.pdb2pqr_options,self.pqr_to_use):<br />
#for entry in (self.selection,self.map,self.radiobuttons,):<br />
entry.pack(fill='x',padx=4,pady=1) # vertical<br />
<br />
<br />
# Set up the main "Calculation" page<br />
page = self.notebook.add('Configuration')<br />
<br />
group = Pmw.Group(page,tag_text='Dielectric Constants')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column=0, row=0)<br />
self.interior_dielectric = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Protein Dielectric:',<br />
value = str(APBSTools2.defaults['interior_dielectric']),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
self.solvent_dielectric = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Solvent Dielectric:',<br />
value = str(APBSTools2.defaults['solvent_dielectric']),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
entries = (self.interior_dielectric,self.solvent_dielectric)<br />
for entry in entries:<br />
#entry.pack(side='left',fill='both',expand=1,padx=4) # side-by-side<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
group = Pmw.Group(page,tag_text='Other')<br />
group.pack(fill='both',expand=1, padx=4, pady=5)<br />
group.grid(column=1, row=1,columnspan=4)<br />
self.max_mem_allowed = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Maximum Memory Allowed (MB):',<br />
value = str(APBSTools2.defaults['max_mem_allowed']),<br />
validate = {'validator' : 'real',<br />
'min':1,}<br />
)<br />
self.apbs_mode = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'APBS Mode',<br />
items = ('Nonlinear Poisson-Boltzmann Equation','Linearized Poisson-Boltzmann Equation',),<br />
initialitem = APBSTools2.defaults['apbs_mode'],<br />
)<br />
self.apbs_mode.pack(fill='x',expand=1,padx=4)<br />
#self.apbs_mode.grid(column=0,row=0,columnspan=3)<br />
self.solvent_radius = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Solvent Radius:',<br />
validate = {'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['solvent_radius']),<br />
)<br />
self.system_temp = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'System Temperature:',<br />
validate = {'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['system_temp']),<br />
)<br />
self.sdens = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Vacc sphere density (grid points/A^2)',<br />
validate = {'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['sdens']),<br />
)<br />
self.bcfl = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Boundary Condition',<br />
items = ('Zero','Single DH sphere','Multiple DH spheres',), #'Focusing',),<br />
initialitem = APBSTools2.defaults['bcfl'],<br />
)<br />
self.chgm = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Charge disc method',<br />
items = ('Linear','Cubic B-splines','Quintic B-splines',),<br />
initialitem = APBSTools2.defaults['chgm'],<br />
)<br />
self.srfm = Pmw.OptionMenu(group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Surface Calculation Method',<br />
items = ('Mol surf for epsilon; inflated VdW for kappa, no smoothing','Same, but with harmonic average smoothing','Cubic spline','Similar to cubic spline, but with 7th order polynomial'),<br />
initialitem = 'Same, but with harmonic average smoothing',<br />
)<br />
#for entry in (self.apbs_mode,self.system_temp,self.solvent_radius,):<br />
for entry in (self.max_mem_allowed,self.solvent_radius,self.system_temp,self.sdens,self.apbs_mode,self.bcfl,self.chgm,self.srfm):<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
<br />
<br />
group = Pmw.Group(page,tag_text='Ions')<br />
group.pack(fill='both',expand=1, padx=4, pady=5)<br />
group.grid(column=0, row=1, )<br />
self.ion_plus_one_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (+1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_one_conc']),<br />
)<br />
self.ion_plus_one_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (+1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_one_rad']),<br />
)<br />
self.ion_minus_one_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (-1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_one_conc']),<br />
)<br />
self.ion_minus_one_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (-1):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_one_rad']),<br />
)<br />
self.ion_plus_two_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (+2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_two_conc']),<br />
)<br />
self.ion_plus_two_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (+2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_plus_two_rad']),<br />
)<br />
self.ion_minus_two_conc = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Concentration (M) (-2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_two_conc']),<br />
)<br />
self.ion_minus_two_rad = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Ion Radius (-2):',<br />
validate={'validator':'real','min':0},<br />
value = str(APBSTools2.defaults['ion_minus_two_rad']),<br />
)<br />
entries = (self.ion_plus_one_conc,self.ion_plus_one_rad,<br />
self.ion_minus_one_conc,self.ion_minus_one_rad,<br />
self.ion_plus_two_conc,self.ion_plus_two_rad,<br />
self.ion_minus_two_conc,self.ion_minus_two_rad,<br />
)<br />
for entry in entries:<br />
entry.pack(fill='x',expand=1,padx=4)<br />
<br />
group = Pmw.Group(page,tag_text = 'Coarse Mesh Length')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 1, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_coarse_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'real','min':0},<br />
value = -1,<br />
entry_width=15,<br />
)<br />
)<br />
getattr(self,'grid_coarse_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
<br />
group = Pmw.Group(page,tag_text = 'Fine Mesh Length')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 2, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_fine_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'real','min':0},<br />
value = -1,<br />
entry_width=15,<br />
)<br />
)<br />
getattr(self,'grid_fine_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
<br />
group = Pmw.Group(page,tag_text = 'Grid Center')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 3, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_center_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'real'},<br />
value = 0,<br />
entry_width=10,<br />
)<br />
)<br />
getattr(self,'grid_center_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
group = Pmw.Group(page,tag_text = 'Grid Points')<br />
group.pack(fill = 'both', expand = 1, padx = 4, pady = 5)<br />
group.grid(column = 4, row = 0)<br />
for coord in 'x y z'.split():<br />
setattr(self,'grid_points_%s'%coord,Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text=coord,<br />
validate={'validator':'integer','min':0},<br />
value = -1,<br />
entry_width=8,<br />
)<br />
)<br />
getattr(self,'grid_points_%s'%coord).pack(fill='x', expand=1, padx=4, pady=1)<br />
<br />
<br />
page.grid_rowconfigure(2,weight=1)<br />
page.grid_columnconfigure(5,weight=1)<br />
page = self.notebook.add('Program Locations')<br />
group = Pmw.Group(page,tag_text='Locations')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
def quickFileValidation(s):<br />
if s == '': return Pmw.PARTIAL<br />
elif os.path.isfile(s): return Pmw.OK<br />
elif os.path.exists(s): return Pmw.PARTIAL<br />
else: return Pmw.PARTIAL<br />
def quickFileDirValidation(s):<br />
'''<br />
assumes s ends in filename<br />
'''<br />
if os.path.exists(s) and not os.path.isfile(s):<br />
return Pmw.PARTIAL<br />
if os.path.isdir(os.path.split(s)[0]):<br />
return Pmw.OK<br />
return Pmw.PARTIAL<br />
self.binary = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setBinaryLocation),<br />
validate = {'validator':quickFileValidation,},<br />
value = get_default_location('apbs.exe'),<br />
label_text = 'APBS binary location:',<br />
)<br />
self.binary.pack(fill = 'x', padx = 20, pady = 10)<br />
self.psize = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPsizeLocation),<br />
validate = {'validator':quickFileValidation,},<br />
#value = '/usr/local/apbs-0.3.1/tools/manip/psize.py',<br />
value = get_default_location('psize.py'),<br />
label_text = 'APBS psize.py location:',<br />
)<br />
self.psize.pack(fill = 'x', padx = 20, pady = 10)<br />
self.pdb2pqr = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPdb2pqrLocation),<br />
validate = {'validator':quickFileValidation,},<br />
value = get_default_location('pdb2pqr.py'),<br />
label_text = 'pdb2pqr location:',<br />
)<br />
self.pdb2pqr.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
label = Tkinter.Label(group.interior(),<br />
pady = 10,<br />
justify=LEFT,<br />
text = """<br />
The PyMOL APBS tools can calculate proper grid dimensions and spacing (we attempt to make<br />
the fine mesh spacing 0.5A or finer, but we will make it coarser if forced to by the<br />
Maximum Grid Points setting in the configuration pane). If you wish to use APBS's psize.py<br />
to set up the grid, make sure that the path is set correctly above.<br />
<br />
PyMOL can generate PQR files using standard protein residues and AMBER charges. If you<br />
wish to use PDB2PQR instead, make sure that it is installed and that the path is set<br />
correctly above.<br />
<br />
If PyMOL does not automatically find apbs, psize.py, or pdb2pqr, you may set the environment<br />
variables APBS_BINARY, APBS_PSIZE and APBS_PDB2PQR to point to them respectively.<br />
""",<br />
)<br />
label.pack()<br />
<br />
<br />
page = self.notebook.add('Temp File Locations')<br />
group = Pmw.Group(page,tag_text='Locations')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.pymol_generated_pqr_filename = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedPqrFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
label_text = 'Temporary PQR file: ',<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.pqr'),<br />
)<br />
self.pymol_generated_pqr_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
self.pymol_generated_pdb_filename = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedPdbFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
label_text = 'Temporary PDB file: ',<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.pdb'),<br />
)<br />
self.pymol_generated_pdb_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
self.pymol_generated_dx_filename = Pmw.EntryField(group.interior(),<br />
labelpos = 'w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedDxFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
label_text = 'Temporary DX file: ',<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.dx'),<br />
)<br />
self.pymol_generated_dx_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
<br />
<br />
self.pymol_generated_in_filename = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_pyclass = FileDialogButtonClassFactory.get(self.setPymolGeneratedInFilename),<br />
validate = {'validator':quickFileDirValidation,},<br />
value = os.path.join(get_default_location('temp'),'pymol-generated.in'),<br />
label_text = 'APBS input file:')<br />
self.pymol_generated_in_filename.pack(fill = 'x', padx = 20, pady = 10)<br />
label = Tkinter.Label(group.interior(),<br />
pady = 10,<br />
justify=LEFT,<br />
text = """You can automatically set the default location of temporary files<br />
by setting the environment variable TEMP.<br />
""",<br />
)<br />
label.pack()<br />
# Create the visualization pages<br />
page = self.notebook.add('Visualization (1)')<br />
group = VisualizationGroup(page,tag_text='Visualization',visgroup_num=1)<br />
self.visualization_group_1 = group<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
<br />
page = self.notebook.add('Visualization (2)')<br />
group = VisualizationGroup(page,tag_text='Visualization',visgroup_num=2)<br />
self.visualization_group_2 = group<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
<br />
# Create a couple of other empty pages<br />
page = self.notebook.add('About')<br />
group = Pmw.Group(page, tag_text='About PyMOL APBS Tools')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
text = """This plugin integrates PyMOL (http://PyMOL.org/) with APBS (http://www.poissonboltzmann.org/apbs/).<br />
<br />
Documentation may be found at<br />
http://pymolwiki.org/index.php/APBS<br />
and<br />
http://apbs.wustl.edu/MediaWiki/index.php/APBS_electrostatics_in_PyMOL<br />
<br />
It requires APBS version >= 0.5.0.<br />
<br />
In the simplest case,<br />
<br />
1) Load a structure into PyMOL.<br />
2) Start this plugin.<br />
3) Make sure that the path to the APBS binary is correct on the "Program Locations" tab.<br />
4) Click the "Set grid" button to set up the grid.<br />
5) Click the "Run APBS" button.<br />
<br />
Many thanks to<br />
- Warren DeLano and Jason Vertrees for everything involving PyMOL<br />
- Nathan Baker, Todd Dolinsky and David Gohara for everything involving APBS<br />
- William G. Scott for help with several APBS+PyMOL issues and documentation<br />
<br />
Created by Michael Lerner (http://pymolwiki.org/index.php/User:Mglerner) mglerner@gmail.com<br />
Carlson Group, University of Michigan (http://www.umich.edu/~carlsonh/)<br />
<br />
Please contact the author and cite this plugin if you use it in a publication.<br />
<br />
Citation for this plugin:<br />
MG Lerner and HA Carlson. APBS plugin for PyMOL, 2006,<br />
University of Michigan, Ann Arbor.<br />
<br />
Citation for PyMOL may be found here:<br />
http://pymol.sourceforge.net/faq.html#CITE<br />
<br />
Citation for APBS:<br />
Baker NA, Sept D, Joseph S, Holst MJ, McCammon JA. Electrostatics of<br />
nanosystems: application to microtubules and the ribosome. Proc.<br />
Natl. Acad. Sci. USA 98, 10037-10041 2001.<br />
<br />
Citation for PDB2PQR:<br />
Dolinsky TJ, Nielsen JE, McCammon JA, Baker NA.<br />
PDB2PQR: an automated pipeline for the setup, execution,<br />
and analysis of Poisson-Boltzmann electrostatics calculations.<br />
Nucleic Acids Research 32 W665-W667 (2004).<br />
"""<br />
#<br />
# Add this as text in a scrollable pane.<br />
# Code based on Caver plugin<br />
# http://loschmidt.chemi.muni.cz/caver/index.php<br />
#<br />
interior_frame=Frame(group.interior())<br />
bar=Scrollbar(interior_frame,)<br />
text_holder=Text(interior_frame,yscrollcommand=bar.set,background="#ddddff",font="Times 14")<br />
bar.config(command=text_holder.yview)<br />
text_holder.insert(END,text)<br />
text_holder.pack(side=LEFT,expand="yes",fill="both")<br />
bar.pack(side=LEFT,expand="yes",fill="y")<br />
interior_frame.pack(expand="yes",fill="both")<br />
<br />
self.notebook.setnaturalsize()<br />
self.showAppModal()<br />
<br />
def showAppModal(self):<br />
#self.dialog.activate() #geometry = 'centerscreenfirst',globalMode = 'nograb')<br />
self.dialog.show()<br />
def execute(self, result, refocus=True):<br />
if result == 'Register APBS Use':<br />
import webbrowser<br />
webbrowser.open("http://agave.wustl.edu/apbs/download")<br />
elif result == 'Register PDB2PQR Use':<br />
import webbrowser<br />
webbrowser.open("http://www.poissonboltzmann.org/pdb2pqr/d/downloads")<br />
elif result == 'Run APBS':<br />
good = self.generateApbsInputFile()<br />
if not good:<br />
if DEBUG:<br />
print "ERROR: Something went wrong trying to generate the APBS input file."<br />
return False<br />
if self.radiobuttons.getvalue() == 'Use another PQR':<br />
pass<br />
elif self.radiobuttons.getvalue() == 'Use PDB2PQR':<br />
if DEBUG: print "GENERATING PQR FILE via PDB2PQR"<br />
good = self.generatePdb2pqrPqrFile()<br />
if not good:<br />
if DEBUG:<br />
print "Could not generate PDB2PQR file. generatePdb2pqrPqrFile failed."<br />
return False<br />
if DEBUG: print "GENERATED"<br />
else: # it's one of the pymol-generated options<br />
if DEBUG: print "GENERATING PQR FILE via PyMOL"<br />
good = self.generatePymolPqrFile()<br />
if not good:<br />
if DEBUG:<br />
print "Could not generate the PyMOL-basd PQR file. generatePyMOLPqrFile failed."<br />
return False<br />
if DEBUG: print "GENERATED"<br />
if os.path.exists(self.pymol_generated_dx_filename.getvalue()):<br />
try:<br />
os.unlink(self.pymol_generated_dx_filename.getvalue())<br />
except:<br />
traceback.print_exc()<br />
pass<br />
#command = "%s %s" % (self.binary.getvalue(),self.pymol_generated_in_filename.getvalue())<br />
#os.system(command)<br />
<br />
#<br />
# NOTE: if there are spaces in the directory name that contains pymol_generated_in_filename,<br />
# our run command will want to split it up into several arguments if we pass it as a<br />
# string. So, we pass it as a tuple.<br />
#<br />
(retval,progout) = run(self.binary.getvalue(),(self.pymol_generated_in_filename.getvalue(),))<br />
if refocus:<br />
#<br />
# There's a bug in the version of APBS shipped with<br />
# Ubuntu 9.10 (version 1.1.0) that causes the name to<br />
# become foo-PE0.dx instead of foo.dx. This would<br />
# normally only occur in mg-para calcs or MPI versions<br />
# of apbs. It's clearly bug-possible, but we will<br />
# check for foo-PE0 if we can't find foo.dx.<br />
#<br />
fname = self.pymol_generated_dx_filename.getvalue()<br />
if not os.path.isfile(fname):<br />
print "Could not find",fname,"so searching for",<br />
fname = '-PE0'.join(os.path.splitext(fname))<br />
print fname<br />
pymol.cmd.load(fname)<br />
self.visualization_group_1.refresh()<br />
self.visualization_group_2.refresh()<br />
self.notebook.tab('Visualization (1)').focus_set()<br />
self.notebook.selectpage('Visualization (1)')<br />
elif result == 'Set grid':<br />
self.runPsize()<br />
else:<br />
#<br />
# Doing it this way takes care of clicking on the x in the top of the<br />
# window, which as result set to None.<br />
#<br />
global APBS_BINARY_LOCATION, APBS_PSIZE_LOCATION<br />
APBS_BINARY_LOCATION = self.binary.getvalue()<br />
APBS_PSIZE_LOCATION = self.psize.getvalue()<br />
self.quit()<br />
def quit(self):<br />
self.dialog.destroy() # stops CPU hogging, perhaps fixes Ubuntu bug MGL<br />
<br />
def runPsize(self):<br />
class NoPsize(Exception):<br />
pass<br />
class NoPDB(Exception):<br />
pass<br />
try:<br />
if not self.psize.valid():<br />
raise NoPsize<br />
pqr_filename = self.pymol_generated_pqr_filename.getvalue()<br />
try:<br />
f = file(pqr_filename,'w')<br />
f.close()<br />
except:<br />
raise NoPDB<br />
#<br />
# Do some magic to load the psize module<br />
#<br />
import imp<br />
f,fname,description = imp.find_module('psize',[os.path.split(self.psize.getvalue())[0]])<br />
psize = imp.load_module('psize',f,fname,description)<br />
# WLD<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
<br />
if pymol.cmd.count_atoms( self.selection.getvalue() + " and not alt ''")!=0:<br />
print "WARNING: You have alternate locations for some of your atoms!"<br />
pymol.cmd.save(pqr_filename,sel)<br />
f.close()<br />
size = psize.Psize()<br />
size.setConstant('gmemceil',int(self.max_mem_allowed.getvalue()))<br />
size.runPsize(pqr_filename)<br />
coarsedim = size.getCoarseGridDims() # cglen<br />
finedim = size.getFineGridDims() # fglen<br />
# could use procgrid for multiprocessors<br />
finegridpoints = size.getFineGridPoints() # dime<br />
center = size.getCenter() # cgcent and fgcent<br />
print "APBS's psize.py was used to calculated grid dimensions"<br />
except (NoPsize,ImportError):<br />
print "This plugin was used to calculated grid dimensions"<br />
#<br />
# First, we need to get the dimensions of the molecule<br />
#<br />
# WLD<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
model = pymol.cmd.get_model(sel)<br />
mins = [None,None,None]<br />
maxs = [None,None,None]<br />
for a in model.atom:<br />
for i in (0,1,2):<br />
if mins[i] is None or a.coord[i] < mins[i]:<br />
mins[i] = a.coord[i]<br />
if maxs[i] is None or a.coord[i] > maxs[i]:<br />
maxs[i] = a.coord[i]<br />
if None in mins or None in maxs:<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "No atoms were in your selection",<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
<br />
box_length = [maxs[i] - mins[i] for i in range(3)]<br />
center = [(maxs[i] + mins[i])/2.0 for i in range(3)]<br />
#<br />
# psize expands the molecular dimensions by CFAC (which defaults<br />
# to 1.7) for the coarse grid<br />
#<br />
CFAC = 1.7<br />
coarsedim = [length*CFAC for length in box_length]<br />
<br />
#<br />
# psize also does something strange .. it adds a buffer FADD to<br />
# the box lengths to get the fine lengths. you'd think it'd also<br />
# have FFAC or CADD, but we'll mimic it here. it also has the<br />
# requirement that the fine grid lengths must be <= the corase<br />
# grid lengths. FADD defaults to 20.<br />
#<br />
FADD = 20<br />
finedim = [min(coarsedim[i],box_length[i] + FADD) for i in range(3)]<br />
<br />
#<br />
# And now the hard part .. setting up the grid points.<br />
# From the APBS manual at http://agave.wustl.edu/apbs/doc/html/user-guide/x594.html#dime<br />
# we have the formula<br />
# n = c*2^(l+1) + 1<br />
# where l is the number of levels in the MG hierarchy. The typical<br />
# number of levels is 4.<br />
#<br />
nlev = 4<br />
mult_fac = 2**(nlev + 1) # this will typically be 2^5==32<br />
# and c must be a non-zero integer<br />
<br />
# If we didn't have to be c*mult_fac + 1, this is what our grid points<br />
# would look like (we use the ceiling to be on the safe side .. it never<br />
# hurts to do too much.<br />
SPACE = 0.5 # default desired spacing = 0.5A<br />
#desired_points = [int(math.ceil(flen / SPACE)) for flen in finedim] # as integers<br />
desired_points = [flen / SPACE for flen in finedim] # as floats .. use int(math.ceil(..)) later<br />
<br />
# Now we set up our cs, taking into account mult_fac<br />
# (we use the ceiling to be on the safe side .. it never hurts to do<br />
# too much.)<br />
cs = [int(math.ceil(dp/mult_fac)) for dp in desired_points]<br />
<br />
finegridpoints = [mult_fac * c + 1 for c in cs]<br />
<br />
print "cs",cs<br />
print "finedim",finedim<br />
print "nlev",nlev<br />
print "mult_fac",mult_fac<br />
print "finegridpoints",finegridpoints<br />
<br />
except NoPDB:<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "Please set a temporary PDB file location",<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
<br />
if (finegridpoints[0]>0) and (finegridpoints[1]>0) and (finegridpoints[2]>0):<br />
max_mem_allowed = float(self.max_mem_allowed.getvalue())<br />
def memofgrid(finegridpoints):<br />
return 200. * float(finegridpoints[0] * finegridpoints[1] * finegridpoints[2]) / 1024. / 1024<br />
def gridofmem(mem):<br />
return mem * 1024. * 1024. / 200.<br />
max_grid_points = gridofmem(max_mem_allowed)<br />
print "Estimated memory usage",memofgrid(finegridpoints),'MB out of maximum allowed',max_mem_allowed<br />
if memofgrid(finegridpoints) > max_mem_allowed:<br />
print "Maximum memory usage exceeded. Old grid dimensions were",finegridpoints<br />
product = float(finegridpoints[0] * finegridpoints[1] * finegridpoints[2])<br />
factor = pow(max_grid_points/product,0.333333333)<br />
finegridpoints[0] = (int(factor*finegridpoints[0]/2))*2+1<br />
finegridpoints[1] = (int(factor*finegridpoints[1]/2))*2+1<br />
finegridpoints[2] = (int(factor*finegridpoints[2]/2))*2+1<br />
print "Fine grid points rounded down from",finegridpoints<br />
#<br />
# Now we have to make sure that this still fits the equation n = c*2^(l+1) + 1. Here, we'll<br />
# just assume nlev == 4, which means that we need to be (some constant times 32) + 1.<br />
#<br />
# This can be annoying if, e.g., you're trying to set [99, 123, 99] .. it'll get rounded to [99, 127, 99].<br />
# First, I'll try to round to the nearest 32*c+1. If that doesn't work, I'll just round down.<br />
#<br />
new_gp = [0,0,0]<br />
for i in 0,1,2:<br />
dm = divmod(finegridpoints[i] - 1,32)<br />
if dm[1]>16:<br />
new_gp[i] = (dm[0]+1)*32+1<br />
else:<br />
new_gp[i] = (dm[0])*32+1<br />
new_prod = new_gp[0]*new_gp[1]*new_gp[2]<br />
#print "tried new_prod",new_prod,"max_grid_points",max_grid_points,"small enough?",new_prod <= max_grid_points<br />
if new_prod <= max_grid_points:<br />
#print "able to round to closest"<br />
for i in 0,1,2: finegridpoints[i] = new_gp[i]<br />
else:<br />
# darn .. have to round down.<br />
# Note that this can still fail a little bit .. it can only get you back down to the next multiple <= what was in<br />
# finegridpoints. So, if finegridpoints was exactly on a multiple, like (99,129,99), you'll get rounded down to<br />
# (99,127,99), which is still just a bit over the default max of 1200000. I think that's ok. It's the rounding error<br />
# from int(factor*finegridpoints ..) above, but it'll never be a huge error. If we needed to, we could easily fix this.<br />
#<br />
#print "rounding down more"<br />
for i in 0,1,2:<br />
#print finegridpoints[i],divmod(finegridpoints[i] - 1,32),<br />
finegridpoints[i] = divmod(finegridpoints[i] - 1,32)[0]*32 + 1<br />
print "New grid dimensions are",finegridpoints<br />
print " APBS Tools: coarse grid: (%5.3f,%5.3f,%5.3f)"%tuple(coarsedim)<br />
self.grid_coarse_x.setvalue(coarsedim[0])<br />
self.grid_coarse_y.setvalue(coarsedim[1])<br />
self.grid_coarse_z.setvalue(coarsedim[2])<br />
print " APBS Tools: fine grid: (%5.3f,%5.3f,%5.3f)"%tuple(finedim)<br />
self.grid_fine_x.setvalue(finedim[0])<br />
self.grid_fine_y.setvalue(finedim[1])<br />
self.grid_fine_z.setvalue(finedim[2])<br />
print " APBS Tools: center: (%5.3f,%5.3f,%5.3f)"%tuple(center)<br />
self.grid_center_x.setvalue(center[0])<br />
self.grid_center_y.setvalue(center[1])<br />
self.grid_center_z.setvalue(center[2])<br />
print " APBS Tools: fine grid points (%d,%d,%d)"%tuple(finegridpoints)<br />
self.grid_points_x.setvalue(finegridpoints[0])<br />
self.grid_points_y.setvalue(finegridpoints[1])<br />
self.grid_points_z.setvalue(finegridpoints[2])<br />
<br />
def fixColumns(self,sel):<br />
"""<br />
Make sure that everything fits into the correct columns.<br />
This means doing some rounding. It also means getting rid of<br />
chain, occupancy and b-factor information.<br />
"""<br />
#pymol.cmd.alter_state(1,'all','(x,y,z)=(int(x*1000)/1000.0, int(y*1000)/1000.0, int(z*1000)/1000.0)')<br />
#pymol.cmd.alter_state(1,'all','(x,y,z)=float("%.2f"%x),float("%.2f"%y),float("%.2f"%z)')<br />
pymol.cmd.alter_state(1,'all','(x,y,z)=float("%.3f"%x),float("%.3f"%y),float("%.3f"%z)')<br />
pymol.cmd.alter(sel,'chain=""')<br />
pymol.cmd.alter(sel,'b=0')<br />
pymol.cmd.alter(sel,'q=0')<br />
<br />
def cleanupGeneratedPdbOrPqrFile(self,filename):<br />
"""<br />
More cleanup on PQR files.<br />
<br />
pdb2pqr will happily write out a file where the coordinate<br />
columns overlap if you have -100.something as one of the<br />
coordinates, like<br />
<br />
90.350 97.230-100.010<br />
<br />
and so will PyMOL. We can't just assume that it's 0-1<br />
because pdb2pqr will debump things and write them out with<br />
3 digits post-decimal. Bleh.<br />
"""<br />
f = file(filename,'r')<br />
txt = f.read()<br />
f.close()<br />
f = file(filename,'w')<br />
# APBS accepts whitespace-delimited columns<br />
# it doesn't care about non-coord lines, so there's not need to be careful about<br />
# where we replace dashes.<br />
txt = txt.replace('-',' -')<br />
f.write(txt)<br />
f.close()<br />
<br />
def getUnassignedAtomsFromPqr(self,fname):<br />
"""<br />
Here is a comment from Todd Dolinsky via email:<br />
<br />
There's a couple of different errors which can be printed out via REMARK 5 lines; a good sample is:<br />
<br />
REMARK 1 PQR file generated by PDB2PQR (Version 1.2.0)<br />
REMARK 1<br />
REMARK 1 Forcefield Used: charmm<br />
REMARK 1<br />
REMARK 1 pKas calculated by propka and assigned using pH 7.00<br />
REMARK 1<br />
REMARK 5 WARNING: Propka determined the following residues to be<br />
REMARK 5 in a protonation state not supported by the<br />
REMARK 5 charmm forcefield!<br />
REMARK 5 All were reset to their standard pH 7.0 state.<br />
REMARK 5 <br />
REMARK 5 CYS 61 2 (negative)<br />
REMARK 5 CYS 79 2 (negative)<br />
REMARK 5 <br />
REMARK 5 WARNING: Unable to debump ALA 1 19<br />
REMARK 5 WARNING: Unable to debump MET 1 151<br />
REMARK 5 WARNING: Unable to debump PRO 1 258<br />
REMARK 5 WARNING: Unable to debump GLY 2 8<br />
REMARK 5 WARNING: Unable to debump THR 3 118<br />
REMARK 5<br />
REMARK 5 WARNING: PDB2PQR was unable to assign charges<br />
REMARK 5 to the following atoms (omitted below):<br />
REMARK 5 6657 O1 in TRS 900<br />
REMARK 5 6658 C2 in TRS 900<br />
REMARK 5 6659 C3 in TRS 900<br />
REMARK 5 6660 C4 in TRS 900<br />
REMARK 5 6661 O5 in TRS 900<br />
REMARK 5 6662 C6 in TRS 900<br />
REMARK 5 6663 O7 in TRS 900<br />
REMARK 5 6664 N8 in TRS 900<br />
REMARK 5<br />
REMARK 6 Total charge on this protein: -1.0000 e<br />
REMARK 6<br />
<br />
If all you care about is the atom number, you can probably regexp match on the 'in' field, something like<br />
<br />
>>> re.compile('REMARK 5 *(\d)* \w* in').findall(text) # Text contains PQR output string<br />
['6657', '6658', '6659', '6660', '6661', '6662', '6663', '6664']<br />
<br />
Or you can grab any other useful information - I'd say that using a regular expression like this would be the best option to ensure you don't get false positives. <br />
"""<br />
f = file(fname)<br />
unassigned = re.compile('REMARK 5 *(\d+) \w* in').findall(f.read()) # Text contains PQR output string<br />
f.close()<br />
return '+'.join(unassigned)<br />
<br />
<br />
def generateApbsInputFile(self):<br />
if self.checkInput(silent=False):<br />
#<br />
# set up our variables<br />
#<br />
pqr_filename = self.getPqrFilename()<br />
<br />
grid_points = [int(getattr(self,'grid_points_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
cglen = [float(getattr(self,'grid_coarse_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
fglen = [float(getattr(self,'grid_fine_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
cent = [float(getattr(self,'grid_center_%s'%i).getvalue()) for i in 'x y z'.split()]<br />
<br />
apbs_mode = self.apbs_mode.getvalue()<br />
if apbs_mode == 'Nonlinear Poisson-Boltzmann Equation':<br />
apbs_mode = 'npbe'<br />
else:<br />
apbs_mode = 'lpbe'<br />
<br />
bcflmap = {'Zero': 'zero',<br />
'Single DH sphere': 'sdh',<br />
'Multiple DH spheres': 'mdh',<br />
#'Focusing': 'focus',<br />
}<br />
bcfl = bcflmap[self.bcfl.getvalue()]<br />
<br />
chgmmap = {'Linear':'spl0',<br />
'Cubic B-splines':'spl2',<br />
'Quintic B-splines':'spl4',<br />
}<br />
chgm = chgmmap[self.chgm.getvalue()]<br />
<br />
srfmmap = {'Mol surf for epsilon; inflated VdW for kappa, no smoothing':'mol',<br />
'Same, but with harmonic average smoothing':'smol',<br />
'Cubic spline':'spl2',<br />
'Similar to cubic spline, but with 7th order polynomial':'spl4',}<br />
<br />
srfm = srfmmap[self.srfm.getvalue()]<br />
<br />
dx_filename = self.pymol_generated_dx_filename.getvalue()<br />
if dx_filename.endswith('.dx'):<br />
dx_filename = dx_filename[:-3]<br />
apbs_input_text = getApbsInputFile(pqr_filename,<br />
grid_points,<br />
cglen,<br />
fglen,<br />
cent,<br />
apbs_mode,<br />
bcfl,<br />
float(self.ion_plus_one_conc.getvalue()), float(self.ion_plus_one_rad.getvalue()),<br />
float(self.ion_minus_one_conc.getvalue()), float(self.ion_minus_one_rad.getvalue()),<br />
float(self.ion_plus_two_conc.getvalue()), float(self.ion_plus_two_rad.getvalue()),<br />
float(self.ion_minus_two_conc.getvalue()), float(self.ion_minus_two_rad.getvalue()),<br />
float(self.interior_dielectric.getvalue()), float(self.solvent_dielectric.getvalue()),<br />
chgm,<br />
srfm,<br />
float(self.solvent_radius.getvalue()),<br />
float(self.system_temp.getvalue()),<br />
float(self.sdens.getvalue()),<br />
dx_filename,<br />
)<br />
if DEBUG:<br />
print "GOT THE APBS INPUT FILE"<br />
<br />
#<br />
# write out the input text<br />
#<br />
try:<br />
f = file(self.pymol_generated_in_filename.getvalue(),'w')<br />
f.write(apbs_input_text)<br />
f.close()<br />
except IOError:<br />
print "ERROR: Got the input file from APBS, but failed when trying to write to %s" % self.pymol_generated_in_filename.getvalue()<br />
return True<br />
else:<br />
self.checkInput()<br />
return False<br />
<br />
def checkInput(self,silent=False):<br />
"""If silent is True, we'll just return a True/False value<br />
"""<br />
if not silent:<br />
def show_error(message):<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = message,<br />
)<br />
junk = error_dialog.activate()<br />
else:<br />
def show_error(message):<br />
pass<br />
<br />
#<br />
# First, check to make sure we have valid locations for apbs and psize<br />
#<br />
if not self.binary.valid():<br />
show_error('Please set the APBS binary location')<br />
return False<br />
#<br />
# If the path to psize is not correct, that's fine .. we'll<br />
# do the calculations ourself.<br />
#<br />
<br />
#if not self.psize.valid():<br />
# show_error("Please set APBS's psize location")<br />
# return False<br />
<br />
#<br />
# Now check the temporary filenames<br />
#<br />
if self.radiobuttons.getvalue() != 'Use another PQR':<br />
if not self.pymol_generated_pqr_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated PQR file')<br />
return False<br />
elif not self.pqr_to_use.valid():<br />
show_error('Please select a valid pqr file or tell\nPyMOL to generate one')<br />
return False<br />
if not self.pymol_generated_pdb_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated PDB file')<br />
return False<br />
if not self.pymol_generated_dx_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated DX file')<br />
return False<br />
if not self.pymol_generated_in_filename.getvalue():<br />
show_error('Please choose a name for the PyMOL\ngenerated APBS input file')<br />
return False<br />
if not self.map.getvalue():<br />
show_error('Please choose a name for the generated map.')<br />
return False<br />
<br />
<br />
#<br />
# Now, the ions<br />
#<br />
for sign in 'plus minus'.split():<br />
for value in 'one two'.split():<br />
for parm in 'conc rad'.split():<br />
if not getattr(self,'ion_%s_%s_%s'%(sign,value,parm)).valid():<br />
show_error('Please correct Ion concentrations and radii')<br />
return False<br />
#<br />
# Now the grid<br />
#<br />
for grid_type in 'coarse fine points center'.split():<br />
for coord in 'x y z'.split():<br />
if not getattr(self,'grid_%s_%s'%(grid_type,coord)).valid():<br />
show_error('Please correct grid dimensions\nby clicking on the "Set grid" button')<br />
return False<br />
<br />
#<br />
# Now other easy things<br />
#<br />
for (message, thing) in (('solvent dielectric',self.solvent_dielectric),<br />
('protein dielectric',self.interior_dielectric),<br />
('solvent radius',self.solvent_radius),<br />
('system temperature',self.system_temp),<br />
('sdens',self.sdens),<br />
):<br />
if not thing.valid():<br />
show_error('Please correct %s'%message)<br />
return False<br />
<br />
return True<br />
<br />
<br />
def generatePdb2pqrPqrFile(self,silent=False):<br />
"""use pdb2pqr to generate a pqr file<br />
"""<br />
if not silent:<br />
def show_error(message):<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = message,<br />
)<br />
junk = error_dialog.activate()<br />
else:<br />
def show_error(message):<br />
pass<br />
<br />
#<br />
# First, generate a PDB file<br />
#<br />
pdb_filename = self.pymol_generated_pdb_filename.getvalue()<br />
try:<br />
f = file(pdb_filename,'w')<br />
f.close()<br />
except:<br />
show_error('Please set a temporary PDB file location that you have permission to edit')<br />
return False<br />
# copied from WLD code<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
self.fixColumns(sel)<br />
pymol.cmd.save(pdb_filename,sel)<br />
self.cleanupGeneratedPdbOrPqrFile(pdb_filename)<br />
<br />
#<br />
# Now, generate a PQR file<br />
#<br />
## command_line = '%s %s %s %s'%(self.pdb2pqr.getvalue(),<br />
## self.pdb2pqr_options.getvalue(),<br />
## pdb_filename,<br />
## self.pymol_generated_pqr_filename.getvalue(),<br />
## )<br />
## print "RAN",command_line<br />
## result = os.system(command_line)<br />
#<br />
# We have to be a little cute about args, because pdb2pqr_options could have several options in it.<br />
args = '%s %s %s' %(self.pdb2pqr_options.getvalue(),<br />
pdb_filename,<br />
self.pymol_generated_pqr_filename.getvalue(),<br />
) <br />
(retval,progout) = run(self.pdb2pqr.getvalue(),args)<br />
<br />
<br />
if retval != 0:<br />
show_error('Could not run pdb2pqr: %s %s\n\n%s'%(self.pdb2pqr.getvalue(),<br />
args,<br />
progout)<br />
)<br />
return False<br />
self.cleanupGeneratedPdbOrPqrFile(self.pymol_generated_pqr_filename.getvalue())<br />
unassigned_atoms = self.getUnassignedAtomsFromPqr(self.pymol_generated_pqr_filename.getvalue())<br />
if unassigned_atoms:<br />
pymol.cmd.select('unassigned','ID %s'%unassigned_atoms)<br />
message_text = "Unable to assign parameters for the %s atoms in selection 'unassigned'.\nPlease either remove these unassigned atoms and re-start the calculation\nor fix their parameters in the generated PQR file and run the calculation\nusing the modified PQR file (select 'Use another PQR' in 'Main')."%len(unassigned_atoms.split('+'))<br />
print "Unassigned atom IDs",unassigned_atoms<br />
show_error(message_text)<br />
return False<br />
return True<br />
<br />
<br />
def generatePymolPqrFile(self):<br />
"""generate a pqr file from pymol<br />
<br />
This will also call through to champ to set the Hydrogens and charges<br />
if it needs to. If it does that, it may change the value self.selection<br />
to take the new Hydrogens into account.<br />
<br />
To make it worse, APBS seems to freak out when there are chain ids. So,<br />
this gets rid of the chain ids.<br />
<br />
"""<br />
# CHAMP will break in many cases if retain_order is set. So,<br />
# we unset it here and reset it later. Note that it's fine to<br />
# reset it before things are written out.<br />
ret_order = pymol.cmd.get('retain_order')<br />
pymol.cmd.set('retain_order',0)<br />
<br />
# WLD<br />
sel = "((%s) or (neighbor (%s) and hydro))"%(<br />
self.selection.getvalue(), self.selection.getvalue())<br />
<br />
pqr_filename = self.getPqrFilename()<br />
try:<br />
f = file(pqr_filename,'w')<br />
f.close()<br />
except:<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "Could not write PQR file.\nPlease check that temporary PQR filename is valid.",<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
<br />
# PyMOL + champ == pqr<br />
from chempy.champ import assign<br />
if self.radiobuttons.getvalue() == 'Use PyMOL generated PQR and PyMOL generated Hydrogens and termini':<br />
pymol.cmd.remove('hydro and %s'%sel)<br />
assign.missing_c_termini(sel)<br />
assign.formal_charges(sel)<br />
pymol.cmd.h_add(sel)<br />
# WLD (code now unnecessary)<br />
# new_hydros = '(hydro and neighbor %s)'%sel<br />
# sel = '%s or %s' % (sel,new_hydros)<br />
assign.amber99(sel)<br />
pymol.cmd.set('retain_order',ret_order)<br />
<br />
# WLD (code now unnecessary)<br />
# if not self.selection.getvalue() in '(all) all'.split():<br />
# self.selection.setvalue(sel)<br />
<br />
#<br />
# Get rid of chain information<br />
#<br />
# WLD -- PyMOL now does this automatically with PQR files <br />
# pymol.cmd.alter(sel,'chain = ""')<br />
self.fixColumns(sel)<br />
pymol.cmd.save(pqr_filename,sel)<br />
self.cleanupGeneratedPdbOrPqrFile(pqr_filename)<br />
missed_count = pymol.cmd.count_atoms("("+sel+") and flag 23")<br />
if missed_count > 0:<br />
pymol.cmd.select("unassigned","("+sel+") and flag 23")<br />
error_dialog = Pmw.MessageDialog(self.parent,<br />
title = 'Error',<br />
message_text = "Unable to assign parameters for the %s atoms in selection 'unassigned'.\nPlease either remove these unassigned atoms and re-start the calculation\nor fix their parameters in the generated PQR file and run the calculation\nusing the modified PQR file (select 'Use another PQR' in 'Main')."%missed_count,<br />
)<br />
junk = error_dialog.activate()<br />
return False<br />
return True<br />
<br />
<br />
############################################################<br />
############################################################<br />
############################################################<br />
## ##<br />
## PmwExtensions ##<br />
## ##<br />
############################################################<br />
############################################################<br />
############################################################<br />
<br />
"""<br />
This contains all of the visualization groups that we'll use for our<br />
PMW interface.<br />
"""<br />
<br />
#<br />
# Generically useful PMW extensions<br />
<br />
import os,fnmatch,time<br />
import Tkinter,Pmw<br />
#Pmw.setversion("0.8.5")<br />
<br />
#<br />
# The classes PmwFileDialog and PmwExistingFileDialog and the _errorpop function<br />
# are taken from the Pmw contrib directory. The attribution given in that file<br />
# is:<br />
################################################################################<br />
# Filename dialogs using Pmw<br />
#<br />
# (C) Rob W.W. Hooft, Nonius BV, 1998<br />
#<br />
# Modifications:<br />
#<br />
# J. Willem M. Nissink, Cambridge Crystallographic Data Centre, 8/2002<br />
# Added optional information pane at top of dialog; if option<br />
# 'info' is specified, the text given will be shown (in blue).<br />
# Modified example to show both file and directory-type dialog<br />
#<br />
# No Guarantees. Distribute Freely. <br />
# Please send bug-fixes/patches/features to <r.hooft@euromail.com><br />
#<br />
################################################################################<br />
<br />
def _errorpop(master,text):<br />
d=Pmw.MessageDialog(master,<br />
title="Error", <br />
message_text=text,<br />
buttons=("OK",))<br />
d.component('message').pack(ipadx=15,ipady=15)<br />
d.activate()<br />
d.destroy()<br />
<br />
class PmwFileDialog(Pmw.Dialog):<br />
"""File Dialog using Pmw"""<br />
def __init__(self, parent = None, **kw):<br />
# Define the megawidget options.<br />
optiondefs = (<br />
('filter', '*', self.newfilter),<br />
('directory', os.getcwd(), self.newdir),<br />
('filename', '', self.newfilename),<br />
('historylen',10, None),<br />
('command', None, None),<br />
('info', None, None),<br />
)<br />
self.defineoptions(kw, optiondefs)<br />
# Initialise base class (after defining options).<br />
Pmw.Dialog.__init__(self, parent)<br />
<br />
self.withdraw()<br />
<br />
# Create the components.<br />
interior = self.interior()<br />
<br />
if self['info'] is not None:<br />
rowoffset=1<br />
dn = self.infotxt()<br />
dn.grid(row=0,column=0,columnspan=2,padx=3,pady=3)<br />
else:<br />
rowoffset=0<br />
<br />
dn = self.mkdn()<br />
dn.grid(row=0+rowoffset,column=0,columnspan=2,padx=3,pady=3)<br />
del dn<br />
<br />
# Create the directory list component.<br />
dnb = self.mkdnb()<br />
dnb.grid(row=1+rowoffset,column=0,sticky='news',padx=3,pady=3)<br />
del dnb<br />
<br />
# Create the filename list component.<br />
fnb = self.mkfnb()<br />
fnb.grid(row=1+rowoffset,column=1,sticky='news',padx=3,pady=3)<br />
del fnb<br />
<br />
# Create the filter entry<br />
ft = self.mkft()<br />
ft.grid(row=2+rowoffset,column=0,columnspan=2,padx=3,pady=3)<br />
del ft<br />
<br />
# Create the filename entry<br />
fn = self.mkfn()<br />
fn.grid(row=3+rowoffset,column=0,columnspan=2,padx=3,pady=3)<br />
fn.bind('<Return>',self.okbutton)<br />
del fn<br />
<br />
# Buttonbox already exists<br />
bb=self.component('buttonbox')<br />
bb.add('OK',command=self.okbutton)<br />
bb.add('Cancel',command=self.cancelbutton)<br />
del bb<br />
<br />
Pmw.alignlabels([self.component('filename'),<br />
self.component('filter'),<br />
self.component('dirname')])<br />
<br />
def infotxt(self):<br />
""" Make information block component at the top """<br />
return self.createcomponent(<br />
'infobox',<br />
(), None,<br />
Tkinter.Label, (self.interior(),),<br />
width=51,<br />
relief='groove',<br />
foreground='darkblue',<br />
justify='left',<br />
text=self['info']<br />
)<br />
<br />
def mkdn(self):<br />
"""Make directory name component"""<br />
return self.createcomponent(<br />
'dirname',<br />
(), None,<br />
Pmw.ComboBox, (self.interior(),),<br />
entryfield_value=self['directory'],<br />
entryfield_entry_width=40,<br />
entryfield_validate=self.dirvalidate,<br />
selectioncommand=self.setdir,<br />
labelpos='w',<br />
label_text='Directory:')<br />
<br />
def mkdnb(self):<br />
"""Make directory name box"""<br />
return self.createcomponent(<br />
'dirnamebox',<br />
(), None,<br />
Pmw.ScrolledListBox, (self.interior(),),<br />
label_text='directories',<br />
labelpos='n',<br />
hscrollmode='none',<br />
dblclickcommand=self.selectdir)<br />
<br />
def mkft(self):<br />
"""Make filter"""<br />
return self.createcomponent(<br />
'filter',<br />
(), None,<br />
Pmw.ComboBox, (self.interior(),),<br />
entryfield_value=self['filter'],<br />
entryfield_entry_width=40,<br />
selectioncommand=self.setfilter,<br />
labelpos='w',<br />
label_text='Filter:')<br />
<br />
def mkfnb(self):<br />
"""Make filename list box"""<br />
return self.createcomponent(<br />
'filenamebox',<br />
(), None,<br />
Pmw.ScrolledListBox, (self.interior(),),<br />
label_text='files',<br />
labelpos='n',<br />
hscrollmode='none',<br />
selectioncommand=self.singleselectfile,<br />
dblclickcommand=self.selectfile)<br />
<br />
def mkfn(self):<br />
"""Make file name entry"""<br />
return self.createcomponent(<br />
'filename',<br />
(), None,<br />
Pmw.ComboBox, (self.interior(),),<br />
entryfield_value=self['filename'],<br />
entryfield_entry_width=40,<br />
entryfield_validate=self.filevalidate,<br />
selectioncommand=self.setfilename,<br />
labelpos='w',<br />
label_text='Filename:')<br />
<br />
def dirvalidate(self,string):<br />
if os.path.isdir(string):<br />
return Pmw.OK<br />
else:<br />
return Pmw.PARTIAL<br />
<br />
def filevalidate(self,string):<br />
if string=='':<br />
return Pmw.PARTIAL<br />
elif os.path.isfile(string):<br />
return Pmw.OK<br />
elif os.path.exists(string):<br />
return Pmw.PARTIAL<br />
else:<br />
return Pmw.OK<br />
<br />
def okbutton(self):<br />
"""OK action: user thinks he has input valid data and wants to<br />
proceed. This is also called by <Return> in the filename entry"""<br />
fn=self.component('filename').get()<br />
self.setfilename(fn)<br />
if self.validate(fn):<br />
self.canceled=0<br />
self.deactivate()<br />
<br />
def cancelbutton(self):<br />
"""Cancel the operation"""<br />
self.canceled=1<br />
self.deactivate()<br />
<br />
def tidy(self,w,v):<br />
"""Insert text v into the entry and at the top of the list of <br />
the combobox w, remove duplicates"""<br />
if not v:<br />
return<br />
entry=w.component('entry')<br />
entry.delete(0,'end')<br />
entry.insert(0,v)<br />
list=w.component('scrolledlist')<br />
list.insert(0,v)<br />
index=1<br />
while index<list.index('end'):<br />
k=list.get(index)<br />
if k==v or index>self['historylen']:<br />
list.delete(index)<br />
else:<br />
index=index+1<br />
w.checkentry()<br />
<br />
def setfilename(self,value):<br />
if not value:<br />
return<br />
value=os.path.join(self['directory'],value)<br />
dir,fil=os.path.split(value)<br />
self.configure(directory=dir,filename=value)<br />
<br />
c=self['command']<br />
if callable(c):<br />
c()<br />
<br />
def newfilename(self):<br />
"""Make sure a newly set filename makes it into the combobox list"""<br />
self.tidy(self.component('filename'),self['filename'])<br />
<br />
def setfilter(self,value):<br />
self.configure(filter=value)<br />
<br />
def newfilter(self):<br />
"""Make sure a newly set filter makes it into the combobox list"""<br />
self.tidy(self.component('filter'),self['filter'])<br />
self.fillit()<br />
<br />
def setdir(self,value):<br />
self.configure(directory=value)<br />
<br />
def newdir(self):<br />
"""Make sure a newly set dirname makes it into the combobox list"""<br />
self.tidy(self.component('dirname'),self['directory'])<br />
self.fillit()<br />
<br />
def singleselectfile(self):<br />
"""Single click in file listbox. Move file to "filename" combobox"""<br />
cs=self.component('filenamebox').curselection()<br />
if cs!=():<br />
value=self.component('filenamebox').get(cs)<br />
self.setfilename(value)<br />
<br />
def selectfile(self):<br />
"""Take the selected file from the filename, normalize it, and OK"""<br />
self.singleselectfile()<br />
value=self.component('filename').get()<br />
self.setfilename(value)<br />
if value:<br />
self.okbutton()<br />
<br />
def selectdir(self):<br />
"""Take selected directory from the dirnamebox into the dirname"""<br />
cs=self.component('dirnamebox').curselection()<br />
if cs!=():<br />
value=self.component('dirnamebox').get(cs)<br />
dir=self['directory']<br />
if not dir:<br />
dir=os.getcwd()<br />
if value:<br />
if value=='..':<br />
dir=os.path.split(dir)[0]<br />
else:<br />
dir=os.path.join(dir,value)<br />
self.configure(directory=dir)<br />
self.fillit()<br />
<br />
def askfilename(self,directory=None,filter=None):<br />
"""The actual client function. Activates the dialog, and<br />
returns only after a valid filename has been entered <br />
(return value is that filename) or when canceled (return <br />
value is None)"""<br />
if directory!=None:<br />
self.configure(directory=directory)<br />
if filter!=None:<br />
self.configure(filter=filter)<br />
self.fillit()<br />
self.canceled=1 # Needed for when user kills dialog window<br />
self.activate()<br />
if self.canceled:<br />
return None<br />
else:<br />
return self.component('filename').get()<br />
<br />
lastdir=""<br />
lastfilter=None<br />
lasttime=0<br />
def fillit(self):<br />
"""Get the directory list and show it in the two listboxes"""<br />
# Do not run unnecesarily<br />
if self.lastdir==self['directory'] and self.lastfilter==self['filter'] and self.lasttime>os.stat(self.lastdir)[8]:<br />
return<br />
self.lastdir=self['directory']<br />
self.lastfilter=self['filter']<br />
self.lasttime=time.time()<br />
dir=self['directory']<br />
if not dir:<br />
dir=os.getcwd()<br />
dirs=['..']<br />
files=[]<br />
try:<br />
fl=os.listdir(dir)<br />
fl.sort()<br />
except os.error,arg:<br />
if arg[0] in (2,20):<br />
return<br />
raise<br />
for f in fl:<br />
if os.path.isdir(os.path.join(dir,f)):<br />
dirs.append(f)<br />
else:<br />
filter=self['filter']<br />
if not filter:<br />
filter='*'<br />
if fnmatch.fnmatch(f,filter):<br />
files.append(f)<br />
self.component('filenamebox').setlist(files)<br />
self.component('dirnamebox').setlist(dirs)<br />
<br />
def validate(self,filename):<br />
"""Validation function. Should return 1 if the filename is valid, <br />
0 if invalid. May pop up dialogs to tell user why. Especially <br />
suited to subclasses: i.e. only return 1 if the file does/doesn't <br />
exist"""<br />
return 1<br />
<br />
<br />
class PmwExistingFileDialog(PmwFileDialog):<br />
def filevalidate(self,string):<br />
if os.path.isfile(string):<br />
return Pmw.OK<br />
else:<br />
return Pmw.PARTIAL<br />
<br />
def validate(self,filename):<br />
if os.path.isfile(filename):<br />
return 1<br />
elif os.path.exists(filename):<br />
_errorpop(self.interior(),"This is not a plain file")<br />
return 0<br />
else:<br />
_errorpop(self.interior(),"Please select an existing file")<br />
return 0<br />
<br />
class FileDialogButtonClassFactory:<br />
def get(fn,filter='*'):<br />
"""This returns a FileDialogButton class that will<br />
call the specified function with the resulting file.<br />
"""<br />
class FileDialogButton(Tkinter.Button):<br />
# This is just an ordinary button with special colors.<br />
<br />
def __init__(self, master=None, cnf={}, **kw):<br />
'''when we get a file, we call fn(filename)'''<br />
self.fn = fn<br />
self.__toggle = 0<br />
apply(Tkinter.Button.__init__, (self, master, cnf), kw)<br />
self.configure(command=self.set)<br />
def set(self):<br />
fd = PmwFileDialog(self.master,filter=filter)<br />
fd.title('Please choose a file')<br />
n=fd.askfilename()<br />
if n is not None:<br />
self.fn(n)<br />
return FileDialogButton<br />
get = staticmethod(get)<br />
<br />
############################################################<br />
############################################################<br />
############################################################<br />
## ##<br />
## PmwGroups ##<br />
## ##<br />
############################################################<br />
############################################################<br />
############################################################<br />
class VisualizationGroup(Pmw.Group):<br />
def __init__(self,*args,**kwargs):<br />
my_options = 'visgroup_num'.split()<br />
for option in my_options:<br />
# use these options as attributes of this class<br />
# and remove them from the kwargs dict before<br />
# passing on to Pmw.Group.__init__().<br />
setattr(self,option,kwargs.pop(option))<br />
kwargs['tag_text'] = kwargs['tag_text'] + ' (%s)'%self.visgroup_num<br />
Pmw.Group.__init__(self,*args,**kwargs)<br />
self.refresh()<br />
self.show_ms = False<br />
self.show_pi = False<br />
self.show_ni = False<br />
def refresh(self):<br />
things_to_kill = 'error_label update_buttonbox mm_group ms_group pi_group ni_group'.split()<br />
for thing in things_to_kill:<br />
try:<br />
getattr(self,thing).destroy()<br />
#print "destroyed",thing<br />
except AttributeError:<br />
#print "couldn't destroy",thing<br />
<br />
# note: this attributeerror will also hit if getattr(self,thing) misses.<br />
# another note: both halves of the if/else make an update_buttonbox.<br />
# if you rename the one in the top half to something else, you'll cause nasty Pmw errors.<br />
pass<br />
if [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'] and [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule']:<br />
self.mm_group = Pmw.Group(self.interior(),tag_text = 'Maps and Molecules')<br />
self.map = Pmw.OptionMenu(self.mm_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Map',<br />
items = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'],<br />
)<br />
self.map.pack(padx=4,side=LEFT)<br />
<br />
self.molecule = Pmw.OptionMenu(self.mm_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Molecule',<br />
items = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule'],<br />
)<br />
self.molecule.pack(padx=4,side=LEFT)<br />
self.update_buttonbox = Pmw.ButtonBox(self.mm_group.interior(), padx=0)<br />
self.update_buttonbox.pack(side=LEFT)<br />
self.update_buttonbox.add('Update',command=self.refresh)<br />
self.mm_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=TOP)<br />
<br />
self.ms_group = Pmw.Group(self.interior(),tag_text='Molecular Surface')<br />
self.ms_buttonbox = Pmw.ButtonBox(self.ms_group.interior(), padx=0)<br />
self.ms_buttonbox.pack()<br />
self.ms_buttonbox.add('Show',command=self.showMolSurface)<br />
self.ms_buttonbox.add('Hide',command=self.hideMolSurface)<br />
self.ms_buttonbox.add('Update',command=self.updateMolSurface)<br />
self.ms_buttonbox.alignbuttons()<br />
self.surface_solvent = IntVar()<br />
self.surface_solvent.set(APBSTools2.defaults['surface_solvent'])<br />
self.sol_checkbutton = Checkbutton(self.ms_group.interior(),<br />
text = "Solvent accessible surface",<br />
variable = self.surface_solvent)<br />
self.sol_checkbutton.pack() <br />
self.potential_at_sas = IntVar()<br />
self.potential_at_sas.set(APBSTools2.defaults['potential_at_sas'])<br />
self.pot_checkbutton = Checkbutton(self.ms_group.interior(),<br />
text = "Color by potential on sol. acc. surf.",<br />
variable = self.potential_at_sas)<br />
self.pot_checkbutton.pack()<br />
self.mol_surf_low = Pmw.Counter(self.ms_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Low',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = -1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real'},<br />
)<br />
self.mol_surf_middle = Pmw.Counter(self.ms_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Middle',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = 0,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real'}<br />
)<br />
self.mol_surf_high = Pmw.Counter(self.ms_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'High',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = 1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real'}<br />
)<br />
bars = (self.mol_surf_low,self.mol_surf_middle,self.mol_surf_high)<br />
Pmw.alignlabels(bars)<br />
for bar in bars: bar.pack(side=LEFT)<br />
self.ms_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=LEFT)<br />
<br />
self.pi_group = Pmw.Group(self.interior(),tag_text='Positive Isosurface')<br />
self.pi_buttonbox = Pmw.ButtonBox(self.pi_group.interior(), padx=0)<br />
self.pi_buttonbox.pack()<br />
self.pi_buttonbox.add('Show',command=self.showPosSurface)<br />
self.pi_buttonbox.add('Hide',command=self.hidePosSurface)<br />
self.pi_buttonbox.add('Update',command=self.updatePosSurface)<br />
self.pi_buttonbox.alignbuttons()<br />
self.pos_surf_val = Pmw.Counter(self.pi_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Contour (kT/e)',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = 1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real', 'min':0}<br />
)<br />
self.pos_surf_val.pack(side=LEFT)<br />
self.pi_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=LEFT)<br />
<br />
self.ni_group = Pmw.Group(self.interior(),tag_text='Negative Isosurface')<br />
self.ni_buttonbox = Pmw.ButtonBox(self.ni_group.interior(), padx=0)<br />
self.ni_buttonbox.pack()<br />
self.ni_buttonbox.add('Show',command=self.showNegSurface)<br />
self.ni_buttonbox.add('Hide',command=self.hideNegSurface)<br />
self.ni_buttonbox.add('Update',command=self.updateNegSurface)<br />
self.ni_buttonbox.alignbuttons()<br />
self.neg_surf_val = Pmw.Counter(self.ni_group.interior(),<br />
labelpos = 'w',<br />
label_text = 'Contour (kT/e)',<br />
orient = 'vertical',<br />
entry_width = 4,<br />
entryfield_value = -1,<br />
datatype = 'real',<br />
entryfield_validate = {'validator' : 'real', 'max':0}<br />
)<br />
self.neg_surf_val.pack(side=LEFT)<br />
self.ni_group.pack(fill = 'both', expand = 1, padx = 4, pady = 5, side=LEFT)<br />
<br />
else:<br />
self.error_label = Tkinter.Label(self.interior(),<br />
pady = 10,<br />
justify=LEFT,<br />
text = '''You must have at least a molecule and a map loaded.<br />
If you have a molecule and a map loaded, please click "Update"''',<br />
)<br />
self.error_label.pack()<br />
self.update_buttonbox = Pmw.ButtonBox(self.interior(), padx=0)<br />
self.update_buttonbox.pack()<br />
self.update_buttonbox.add('Update',command=self.refresh)<br />
<br />
def showMolSurface(self):<br />
self.updateMolSurface()<br />
<br />
def hideMolSurface(self):<br />
pymol.cmd.hide('surface',self.molecule.getvalue())<br />
<br />
def getRampName(self):<br />
#return 'e_lvl'<br />
idx = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:molecule'].index(self.molecule.getvalue())<br />
return '_'.join(('e_lvl',str(idx),str(self.visgroup_num)))<br />
<br />
def getIsoPosName(self):<br />
idx = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'].index(self.map.getvalue())<br />
return '_'.join(('iso_pos',str(idx),str(self.visgroup_num)))<br />
<br />
def getIsoNegName(self):<br />
idx = [i for i in pymol.cmd.get_names() if pymol.cmd.get_type(i)=='object:map'].index(self.map.getvalue())<br />
return '_'.join(('iso_neg',str(idx),str(self.visgroup_num)))<br />
<br />
def updateMolSurface(self):<br />
molecule_name = self.molecule.getvalue()<br />
ramp_name = self.getRampName()<br />
map_name = self.map.getvalue()<br />
low = float(self.mol_surf_low.getvalue())<br />
mid = float(self.mol_surf_middle.getvalue())<br />
high = float(self.mol_surf_high.getvalue())<br />
range = [low,mid,high]<br />
print " APBS Tools: range is",range<br />
pymol.cmd.delete(ramp_name)<br />
pymol.cmd.ramp_new(ramp_name,map_name,range)<br />
pymol.cmd.set('surface_color',ramp_name,molecule_name)<br />
if self.surface_solvent.get()==1:<br />
pymol.cmd.set('surface_solvent',1,molecule_name)<br />
pymol.cmd.set('surface_ramp_above_mode',0,molecule_name)<br />
else:<br />
pymol.cmd.set('surface_solvent',0,molecule_name)<br />
pymol.cmd.set('surface_ramp_above_mode',self.potential_at_sas.get(),molecule_name)<br />
pymol.cmd.show('surface',molecule_name)<br />
pymol.cmd.refresh()<br />
pymol.cmd.recolor(molecule_name)<br />
<br />
def showPosSurface(self):<br />
self.updatePosSurface()<br />
def hidePosSurface(self):<br />
pymol.cmd.hide('everything',self.getIsoPosName())<br />
def updatePosSurface(self):<br />
pymol.cmd.delete(self.getIsoPosName())<br />
pymol.cmd.isosurface(self.getIsoPosName(),self.map.getvalue(),float(self.pos_surf_val.getvalue()))<br />
pymol.cmd.color('blue',self.getIsoPosName())<br />
pymol.cmd.show('everything',self.getIsoPosName())<br />
def showNegSurface(self):<br />
self.updateNegSurface()<br />
def hideNegSurface(self):<br />
pymol.cmd.hide('everything',self.getIsoNegName())<br />
def updateNegSurface(self):<br />
pymol.cmd.delete(self.getIsoNegName())<br />
pymol.cmd.isosurface(self.getIsoNegName(),self.map.getvalue(),float(self.neg_surf_val.getvalue()))<br />
pymol.cmd.color('red',self.getIsoNegName())<br />
pymol.cmd.show('everything',self.getIsoNegName())<br />
<br />
<br />
</source><br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=Ideas&diff=11839Ideas2010-01-27T20:36:00Z<p>Mglerner: </p>
<hr />
<div>=== Ideas for PyMOL Development ===<br />
<br />
This page was originally developed for the 2008 Google Summer of Code competition, but seeing as PyMOL wasn't selected, this page can instead serve as a resource for ongoing PyMOL development efforts.<br />
<br />
== Where to Start ==<br />
<br />
Always start with Python and only delve down into the C code when absolutely necessary. Although PyMOL is mostly a C-based application, much of the that code is opaque, fragile, and unforgiving. Although C code refactoring is an important project goal, such work may not be ideal since once mistake could potentially to destabilize the entire platform. <br />
<br />
Fortunately, the Python interpreter and the PyMOL command and selection languages make it possible to extend PyMOL safely and quickly. Even when performance is critical, Python should be the interface between external C, C++, and Java code and PyMOL's internal C data structures.<br />
<br />
== Choosing a Topic ==<br />
<br />
The best open-source code is usually written by an end-users attempting to meet their own pressing needs. So if you have already have a specific need which relates to PyMOL, then we strongly encourage you to follow up on that first!<br />
<br />
If you are looking for ideas, then try to seek out enhancements and/or integrations that will impact the largest potential user base. For example, imagine what new things might be useful to virtually all medicinal chemists, all structural biologists, all movie-makers, all paper-writers, and so forth.<br />
<br />
The ideas below are organized by category. Right now, integration with other open-source projects seems like the approach most likely to yield significant benefit, so those ideas are first.<br />
<br />
== Integration Ideas (Linking Out to Useful Open-Source Tools) ==<br />
<br />
In most cases, depending on the need, integration can be accomplished through standalone Python scripts, through new PyMOL commands, through PyMOL Wizards, or via Tkinter plugins.<br />
<br />
* APBS (electrostatics calculations): Improve the existing plugin. Michael Lerner is currently leading this effort. See [[APBS]]<br />
:: yea ([[User:Inchoate|Tree]] [[User:Jedgold|Jedgold]]"[[User:Vcpmartin|Vcpmartin]]") / nay (0)<br />
:: Feel free to mention specific plugin enhancements you'd like! [[User:Mglerner|Michael Lerner]]<br />
* RDKit (cheminformatics, depiction, UFF cleanup, etc.): Lots of potential here, however C++ coding may be necessary for more advanced integration tasks. [http://www.rdkit.org RDKit home]<br />
:: yea ([[User:Markvanraaij|Markvanraaij]]) / nay (0)<br />
* GIMP (image manipulation): Streamline & document the process of exporting images from PyMOL into GIMP and preparing them for submission to scientific Journals.<br />
:: yea (0) / nay (0)<br />
* Jmol (publishing visualizations inside of web pages): Liason between PyMOL & Jmol projects to develop a shared molecular visualization data model compatible with both applications.<br />
:: yea (0) / nay ([[User:Cowsandmilk|Cowsandmilk]])<br />
* Firefox (plugin): Develop an PyMOL plugin compatible with Firefox.<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* MMTK (molecular mechanics -- Python/flexible): Develop the ability to round-trip molecular systems from PyMOL, into MMTK, and back.<br />
:: yea (0) / nay (0)<br />
* GROMACS (molecular mechanics -- C/fast) - Maybe some ideas can be shared with this guy. [http://www.kde-apps.org/content/show.php/Gromacs+GUI+?content=47665 Gromacs GUI]<br />
:: yea ([[User:Jedgold|Jedgold]] [[User:Mglerner|Michael Lerner]]) / nay (0)<br />
* OpenOffice (escape Microsoft hegemony): Develop an PyMOL plugin.<br />
:: yea (0) / nay (0)<br />
* IPython integration (interactive shell): a robust alternative to the PyMOL command line?<br />
:: yea ([[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
* R (statistics): PyMOL a 3D viewer environment for visualizating & manipulating large statistical data sets?<br />
:: yea (0) / nay (0)<br />
<br />
Are there other key open-source packages we might specifically target for integration with PyMOL, either through GSoC or beyond?<br />
<br />
== High-Level Enhancement Ideas (Mostly Python-oriented) ==<br />
<br />
* Work on [[#More Ideas (Please add your own!)| MolViz]]<br />
:: yea (0) / nay (0)<br />
* Develop new plugins which automate routine tasks.<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* Improve the Python API documentation.<br />
:: yea ([[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
* Flesh out the new "from pymol2 import PyMOL" instance-based PyMOL API.<br />
:: yea (0) / nay (0)<br />
* Develop alternate Tkinter "skins" (for custom OEM-like applications).<br />
:: yea (0) / nay (0)<br />
* Develop a Tkinter/TOGL widget which holds a PyMOL viewer instance.<br />
:: yea (0) / nay (0)<br />
* Develop a PyQt widget which holds a PyMOL viewer instance.<br />
:: yea ([[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
* Create a plugin-manager GUI in the style of Firefox, Rythmbox, Gedit, Eclipse. A GUI where it is easy to turn off/on plugins, configure them and see help-contents for them. Maybe also some way to paste a url to install a new Plugin.<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* Add a plugin for a GUI window with the same functionality as the "Control Panel" window in SwissPDB Viewer.<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* Extend and modify the PyMOL command language so as to be compatible with existing RasMol and/or Jmol scripts.<br />
:: yea (0) / nay ([[User:Cowsandmilk|Cowsandmilk]])<br />
* Enhance the Mutagenesis Wizard in order to support Nucleic acids and/or Sugars.<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Better tab completion for commands<br />
:: yea ([[User:Cowsandmilk|Cowsandmilk]]) /nay(0)<br />
<br />
== Low-Level Enhancement Ideas (Mostly C-oriented) ==<br />
<br />
* Enable editing of displayed sequence alignments.<br />
:: yea ([[User:Jedgold|Jedgold]], [[User:Aschreyer|Aschreyer]], [[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
::: Would this then feed back to the structural alignment? [[User:Jedgold|Jedgold]]<br />
* Add multi-line textual annotations<br />
:: yea (0) / nay (0)<br />
* Support additional annotation object including: arrow, lines, and blobs.<br />
:: yea ([[User:Aschreyer|Aschreyer]], [[User:Vvostri|Vvostri]]) / nay (0)<br />
* Add display of secondary structure into the sequence viewer.<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Enable per-object Z clipping (especially in the ray tracer)<br />
:: yea ([[User:Gregori|Gregori]], [[User:Xevi|Xevi]], [[User:Johnm|Johnm]]) / nay (0)<br />
::: I would go a step further with fully customizable selection-based clipping planes (XYZ, color and transparency) ([[User:Gregori|Gregori]])<br />
* Highlight H-bonds, salt bridges, Pi-stacking, Pi-cations, etc.<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Build in a simple forcefield and energy minimizer suitable for use with Mutagenesis.<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Incorporate a suite of standard NMR visualizations (restraint violations, per-residue RMS, etc.)<br />
:: yea ([[User:Vvostri|Vvostri]]"[[User:Vcpmartin|Vcpmartin]]") / nay (0)<br />
* Enumeration and display of low-energy conformers.<br />
:: yea ([[User:Jedgold|Jedgold]]) / nay (0)<br />
::: This could be done by integrating RDKit, I think. [[User:Aschreyer|Aschreyer]]<br />
* Automated structure grafting (poor-man's homology modeling).<br />
:: yea (0) / nay ([[User:Jedgold|Jedgold]], [[User:Cowsandmilk|Cowsandmilk]])<br />
::: Perhaps a plugin to Modeller instead? ([[User:Jedgold|Jedgold]], [[User:Lucajovine|Luca Jovine]])<br />
* Import of alignment files.<br />
:: yea ([[User:Jedgold|Jedgold]], [[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Implement IMD (Interactive Molecular Dynamics) Interface, see http://www.ks.uiuc.edu/Research/vmd/imd/<br />
:: yea (0) / nay (0)<br />
* Add buttons for '''Set ChainID''' and '''Renumber Residues From...''' to Edit menu or Actions (wrapper around Alter command)<br />
:: yea ([[User:Sheehanj|Sheehanj]]) / nay (0)<br />
<br />
== Difficult C-level Code Refactoring Ideas ==<br />
<br />
* Assemble a test suite which thoroughly exercises the existing code (a prerequisite to major refactoring).<br />
:: yea ([[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
* Catch & handle memory-allocation failures gracefully (instead of crashing).<br />
:: yea ([[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
* Replace PyMOL's memory management & custom containers with a simple runtime object model.<br />
:: yea (0) / nay (0)<br />
* Separate the View and the Controllers from the Model so that they can all run asynchronously (on multiple cores).<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* Enable generalized undo of changes made to the Model.<br />
:: yea ([[User:Vvostri|Vvostri]]"[[User:Vcpmartin|Vcpmartin]], [[User:Lucajovine|Luca Jovine]]", [[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
* Clean up the internal matrix handling code.<br />
:: yea ([[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
<br />
== Ideas Involving Proprietary APIs ==<br />
<br />
Since these involve closed-source APIs and infrastructure, they aren't suitable for open-source development efforts. However, such requests are noted here for the sake of complete coverage.<br />
<br />
* Create a Windows port with "native" look & feel. <- Could this be done in PyQT or PyGTK?. Then it would look "native", but be cross-platform and not proprietary.<br />
:: yea (0) / nay (0)<br />
* Integrate directly via Mathematica via MathLink.<br />
:: yea (0) / nay ([[User:Aschreyer|Aschreyer]])<br />
* Further enhance JyMOL (Java-JNI/wrapped PyMOL)<br />
:: yea ([[User:Inchoate|Tree]], [[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
* Integrate with Matlab.<br />
:: yea (0) / nay ([[User:Aschreyer|Aschreyer]])<br />
* Quicklook Plugin on the Mac<br />
:: yea ([[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
<br />
== Ideas for Plugin Developers ==<br />
<br />
The range of things that PyMOL plugins can do has grown by leaps and bounds over the last several years. It may be time for some new infrastructure to facilitate plugin development.<br />
<br />
* Plugins that span multiple files. This means 1. the ability to have them 2. the ability for users to easily install them.<br />
:: yea (1) / nay (0) ([[User:Mglerner|Michael Lerner]])<br />
* Config files that persist between sessions. This would be useful for things like remembering the locations of external programs, etc., without requiring the user to modify their .pymolrc.<br />
:: yea (1) / nay (0) ([[User:Mglerner|Michael Lerner]])<br />
<br />
== More Ideas (Please add your own!) ==<br />
* [http://molviz.cs.toronto.edu/molviz MolViz] is a project to incorporate head tracking input into [http://pymol.sourceforge.net/ PyMol]. This is accomplished through a [[ImmersiveViz]] script written in Python to control the molecule's position using the existing [http://www.pymolwiki.org/index.php/Category:Commands PyMol API]. Related projects would include:<br />
** Improving the existing [[ImmersiveViz]] PyMol plugin for more precise control of the environment.<br />
** Developing new input drivers for the Wiimote form of control. This would require some bluetooth hacking.<br />
** Implementing some other forms of input for head tracking, such as fisheye head tracking, IR webcam tracking, etc (refer to the end of this [[http://www.youtube.com/watch?v=ncShaY4VSac video]] for a better description).<br />
:: yea (0) / nay (0)<br />
* Provide a 2D chemical depiction of the current 3D view.<br />
:: yea ([[User:Aschreyer|Aschreyer]], [[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
::: RDKit?<br />
* Spreadsheet view with additional information (e.g. IC50's).<br />
:: yea ([[User:Aschreyer|Aschreyer]]) / nay ([[User:Cowsandmilk|Cowsandmilk]])<br />
* Create additional documentation, screen casts, & tutorials.<br />
:: yea ([[User:Markvanraaij|Markvanraaij]]) / nay (0)<br />
* Export 3D PDF images.<br />
:: yea ([[User:Vvostri|Vvostri]], [[User:Lucajovine|Luca Jovine]]) / nay ([[User:Cowsandmilk|Cowsandmilk]])<br />
* <strike>Add extra "Single Word Selectors" like "nucleic", "protein", "water", "ions", "backbone" (for nucleic acids or proteins), "mainchain", "sidechain"</strike><br />
:: yea (0) / nay (0)<br />
* Add functionality that allows you to select atoms based on their location (i.e. select (x_coordinate < 10) and (z_coordinate > 0))<br />
:: yea (0) / nay (0)<br />
* set pdb_mirror option to use PDB mirrors other than RCSB for fetching structures (PDBe, PDBj); the EBI mirror is much faster from Europe for example.<br />
:: yea ([[User:Aschreyer|Aschreyer]]) / nay (0)<br />
* have the ability to link the TK console to the viewer so that users don't have to constantly alt+tab between what they want<br />
:: yea (0) / nay (0)<br />
* have the ability to disable typing in the viewer and automatically type in the TK console (I like being able to cut/paste/home/end)<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* I see a lot of "can pymol do this" threads - any ideas of a good UI for a page of "things PyMOL can do?"<br />
:: yea (0) / nay (0)<br />
* make an option where I can turn on a coordinate grid - perhaps an object that is a cuboid grid around any object in the view so I can still alter how it's rendered?<br />
:: yea (0) / nay (0)<br />
* iPhone / Nexus One app(s)<br />
:: yea (0) / nay (0)<br />
* single-color bonds between nonidentical or any spherical atoms colored specifically<br />
:: yea (0) / nay (0)<br />
* double bonds as two parallel cylinders<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* export scenes as [http://www.khronos.org/webgl/ WebGL] / Could make mobile apps, presentation plugins obsolete<br />
:: yea ([[User:Aschreyer|Aschreyer]], [[User:Cowsandmilk|Cowsandmilk]]) / nay (0)<br />
* export images in vector format<br />
:: yea ([[User:Vvostri|Vvostri]], [[User:Lucajovine|Luca Jovine]], [[User:Aschreyer|Aschreyer]]) / nay (0)<br />
* Keynote plugin<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Electron density contour sliders<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Automatic electron density map generation from PDB mmcif files or user-supplied MTZ files<br />
:: yea ([[User:Lucajovine|Luca Jovine]], [[User:Aschreyer|Aschreyer]], [[User:Johnm|Johnm]]) / nay (0)<br />
* Display of crystallographic symmetry and NCS axes, with possibility of showing symbols indicating what kind of axes they are<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Automatic symmetry expansion to show overall crystal packing; automatic generation of scenes showing crystal packing interface details<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)</div>Mglernerhttps://wiki.pymol.org/index.php?title=Ideas&diff=11830Ideas2010-01-22T04:49:25Z<p>Mglerner: /* Integration Ideas (Linking Out to Useful Open-Source Tools) */</p>
<hr />
<div>=== Ideas for PyMOL Development ===<br />
<br />
This page was originally developed for the 2008 Google Summer of Code competition, but seeing as PyMOL wasn't selected, this page can instead serve as a resource for ongoing PyMOL development efforts.<br />
<br />
== Where to Start ==<br />
<br />
Always start with Python and only delve down into the C code when absolutely necessary. Although PyMOL is mostly a C-based application, much of the that code is opaque, fragile, and unforgiving. Although C code refactoring is an important project goal, such work may not be ideal since once mistake could potentially to destabilize the entire platform. <br />
<br />
Fortunately, the Python interpreter and the PyMOL command and selection languages make it possible to extend PyMOL safely and quickly. Even when performance is critical, Python should be the interface between external C, C++, and Java code and PyMOL's internal C data structures.<br />
<br />
== Choosing a Topic ==<br />
<br />
The best open-source code is usually written by an end-users attempting to meet their own pressing needs. So if you have already have a specific need which relates to PyMOL, then we strongly encourage you to follow up on that first!<br />
<br />
If you are looking for ideas, then try to seek out enhancements and/or integrations that will impact the largest potential user base. For example, imagine what new things might be useful to virtually all medicinal chemists, all structural biologists, all movie-makers, all paper-writers, and so forth.<br />
<br />
The ideas below are organized by category. Right now, integration with other open-source projects seems like the approach most likely to yield significant benefit, so those ideas are first.<br />
<br />
== Integration Ideas (Linking Out to Useful Open-Source Tools) ==<br />
<br />
In most cases, depending on the need, integration can be accomplished through standalone Python scripts, through new PyMOL commands, through PyMOL Wizards, or via Tkinter plugins.<br />
<br />
* APBS (electrostatics calculations): Improve the existing plugin. Michael Lerner is currently leading this effort. See [[APBS]]<br />
:: yea ([[User:Inchoate|Tree]] [[User:Jedgold|Jedgold]]"[[User:Vcpmartin|Vcpmartin]]") / nay (0)<br />
* RDKit (cheminformatics, depiction, UFF cleanup, etc.): Lots of potential here, however C++ coding may be necessary for more advanced integration tasks. [http://www.rdkit.org RDKit home]<br />
:: yea ([[User:Markvanraaij|Markvanraaij]]) / nay (0)<br />
* GIMP (image manipulation): Streamline & document the process of exporting images from PyMOL into GIMP and preparing them for submission to scientific Journals.<br />
:: yea (0) / nay (0)<br />
* Jmol (publishing visualizations inside of web pages): Liason between PyMOL & Jmol projects to develop a shared molecular visualization data model compatible with both applications.<br />
:: yea (0) / nay (0)<br />
* Firefox (plugin): Develop an PyMOL plugin compatible with Firefox.<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* MMTK (molecular mechanics -- Python/flexible): Develop the ability to round-trip molecular systems from PyMOL, into MMTK, and back.<br />
:: yea (0) / nay (0)<br />
* GROMACS (molecular mechanics -- C/fast) - Maybe some ideas can be shared with this guy. [http://www.kde-apps.org/content/show.php/Gromacs+GUI+?content=47665 Gromacs GUI]<br />
:: yea ([[User:Jedgold|Jedgold]] [[User:Mglerner|Michael Lerner]]) / nay (0)<br />
* OpenOffice (escape Microsoft hegemony): Develop an PyMOL plugin.<br />
:: yea (0) / nay (0)<br />
* IPython integration (interactive shell): a robust alternative to the PyMOL command line?<br />
:: yea (0) / nay (0)<br />
* R (statistics): PyMOL a 3D viewer environment for visualizating & manipulating large statistical data sets?<br />
<br />
Are there other key open-source packages we might specifically target for integration with PyMOL, either through GSoC or beyond?<br />
<br />
== High-Level Enhancement Ideas (Mostly Python-oriented) ==<br />
<br />
* Work on [[#More Ideas (Please add your own!)| MolViz]]<br />
:: yea (0) / nay (0)<br />
* Develop new plugins which automate routine tasks.<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* Improve the Python API documentation.<br />
:: yea (0) / nay (0)<br />
* Flesh out the new "from pymol2 import PyMOL" instance-based PyMOL API.<br />
:: yea (0) / nay (0)<br />
* Develop alternate Tkinter "skins" (for custom OEM-like applications).<br />
:: yea (0) / nay (0)<br />
* Develop a Tkinter/TOGL widget which holds a PyMOL viewer instance.<br />
:: yea (0) / nay (0)<br />
* Develop a PyQt widget which holds a PyMOL viewer instance.<br />
:: yea (0) / nay (0)<br />
* Create a plugin-manager GUI in the style of Firefox, Rythmbox, Gedit, Eclipse. A GUI where it is easy to turn off/on plugins, configure them and see help-contents for them. Maybe also some way to paste a url to install a new Plugin.<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* Add a plugin for a GUI window with the same functionality as the "Control Panel" window in SwissPDB Viewer.<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* Extend and modify the PyMOL command language so as to be compatible with existing RasMol and/or Jmol scripts.<br />
:: yea (0) / nay (0)<br />
* Enhance the Mutagenesis Wizard in order to support Nucleic acids and/or Sugars.<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
<br />
== Low-Level Enhancement Ideas (Mostly C-oriented) ==<br />
<br />
* Enable editing of displayed sequence alignments.<br />
:: yea ([[User:Jedgold|Jedgold]], [[User:Aschreyer|Aschreyer]], [[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
::: Would this then feed back to the structural alignment? [[User:Jedgold|Jedgold]]<br />
* Add multi-line textual annotations<br />
:: yea (0) / nay (0)<br />
* Support additional annotation object including: arrow, lines, and blobs.<br />
:: yea ([[User:Aschreyer|Aschreyer]], [[User:Vvostri|Vvostri]]) / nay (0)<br />
* Add display of secondary structure into the sequence viewer.<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Enable per-object Z clipping (especially in the ray tracer)<br />
:: yea ([[User:Gregori|Gregori]]) / nay (0)<br />
::: I would go a step further with fully customizable selection-based clipping planes (XYZ, color and transparency) ([[User:Gregori|Gregori]])<br />
* Highlight H-bonds, salt bridges, Pi-stacking, Pi-cations, etc.<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Build in a simple forcefield and energy minimizer suitable for use with Mutagenesis.<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Incorporate a suite of standard NMR visualizations (restraint violations, per-residue RMS, etc.)<br />
:: yea ([[User:Vvostri|Vvostri]]"[[User:Vcpmartin|Vcpmartin]]") / nay (0)<br />
* Enumeration and display of low-energy conformers.<br />
:: yea ([[User:Jedgold|Jedgold]]) / nay (0)<br />
::: This could be done by integrating RDKit, I think. [[User:Aschreyer|Aschreyer]]<br />
* Automated structure grafting (poor-man's homology modeling).<br />
:: yea (0) / nay ([[User:Jedgold|Jedgold]])<br />
::: Perhaps a plugin to Modeller instead? ([[User:Jedgold|Jedgold]], [[User:Lucajovine|Luca Jovine]])<br />
* Import of alignment files.<br />
:: yea ([[User:Jedgold|Jedgold]], [[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Implement IMD (Interactive Molecular Dynamics) Interface, see http://www.ks.uiuc.edu/Research/vmd/imd/<br />
:: yea (0) / nay (0)<br />
* Add buttons for '''Set ChainID''' and '''Renumber Residues From...''' to Edit menu or Actions (wrapper around Alter command)<br />
:: yea ([[User:Sheehanj|Sheehanj]]) / nay (0)<br />
<br />
== Difficult C-level Code Refactoring Ideas ==<br />
<br />
* Assemble a test suite which thoroughly exercises the existing code (a prerequisite to major refactoring).<br />
:: yea (0) / nay (0)<br />
* Catch & handle memory-allocation failures gracefully (instead of crashing).<br />
:: yea (0) / nay (0)<br />
* Replace PyMOL's memory management & custom containers with a simple runtime object model.<br />
:: yea (0) / nay (0)<br />
* Separate the View and the Controllers from the Model so that they can all run asynchronously (on multiple cores).<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* Enable generalized undo of changes made to the Model.<br />
:: yea ([[User:Vvostri|Vvostri]]"[[User:Vcpmartin|Vcpmartin]], [[User:Lucajovine|Luca Jovine]]") / nay (0)<br />
* Clean up the internal matrix handling code.<br />
:: yea (0) / nay (0)<br />
<br />
== Ideas Involving Proprietary APIs ==<br />
<br />
Since these involve closed-source APIs and infrastructure, they aren't suitable for open-source development efforts. However, such requests are noted here for the sake of complete coverage.<br />
<br />
* Create a Windows port with "native" look & feel. <- Could this be done in PyQT or PyGTK?. Then it would look "native", but be cross-platform and not proprietary.<br />
:: yea (0) / nay (0)<br />
* Integrate directly via Mathematica via MathLink.<br />
:: yea (0) / nay ([[User:Aschreyer|Aschreyer]])<br />
* Further enhance JyMOL (Java-JNI/wrapped PyMOL)<br />
:: yea ([[User:Inchoate|Tree]]) / nay (0)<br />
* Integrate with Matlab.<br />
:: yea (0) / nay ([[User:Aschreyer|Aschreyer]])<br />
<br />
== More Ideas (Please add your own!) ==<br />
* [http://molviz.cs.toronto.edu/molviz MolViz] is a project to incorporate head tracking input into [http://pymol.sourceforge.net/ PyMol]. This is accomplished through a [[ImmersiveViz]] script written in Python to control the molecule's position using the existing [http://www.pymolwiki.org/index.php/Category:Commands PyMol API]. Related projects would include:<br />
** Improving the existing [[ImmersiveViz]] PyMol plugin for more precise control of the environment.<br />
** Developing new input drivers for the Wiimote form of control. This would require some bluetooth hacking.<br />
** Implementing some other forms of input for head tracking, such as fisheye head tracking, IR webcam tracking, etc (refer to the end of this [[http://www.youtube.com/watch?v=ncShaY4VSac video]] for a better description).<br />
:: yea (0) / nay (0)<br />
* Provide a 2D chemical depiction of the current 3D view.<br />
:: yea ([[User:Aschreyer|Aschreyer]]) / nay (0)<br />
::: RDKit?<br />
* Spreadsheet view with additional information (e.g. IC50's).<br />
:: yea ([[User:Aschreyer|Aschreyer]]) / nay (0)<br />
* Create additional documentation, screen casts, & tutorials.<br />
:: yea ([[User:Markvanraaij|Markvanraaij]]) / nay (0)<br />
* Export 3D PDF images.<br />
:: yea ([[User:Vvostri|Vvostri]], [[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* <strike>Add extra "Single Word Selectors" like "nucleic", "protein", "water", "ions", "backbone" (for nucleic acids or proteins), "mainchain", "sidechain"</strike><br />
:: yea (0) / nay (0)<br />
* Add functionality that allows you to select atoms based on their location (i.e. select (x_coordinate < 10) and (z_coordinate > 0))<br />
:: yea (0) / nay (0)<br />
* set pdb_mirror option to use PDB mirrors other than RCSB for fetching structures (PDBe, PDBj); the EBI mirror is much faster from Europe for example.<br />
:: yea ([[User:Aschreyer|Aschreyer]]) / nay (0)<br />
* have the ability to link the TK console to the viewer so that users don't have to constantly alt+tab between what they want<br />
:: yea (0) / nay (0)<br />
* have the ability to disable typing in the viewer and automatically type in the TK console (I like being able to cut/paste/home/end)<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* I see a lot of "can pymol do this" threads - any ideas of a good UI for a page of "things PyMOL can do?"<br />
:: yea (0) / nay (0)<br />
* make an option where I can turn on a coordinate grid - perhaps an object that is a cuboid grid around any object in the view so I can still alter how it's rendered?<br />
:: yea (0) / nay (0)<br />
* iPhone / Nexus One app(s)<br />
:: yea (0) / nay (0)<br />
* single-color bonds between nonidentical or any spherical atoms colored specifically<br />
:: yea (0) / nay (0)<br />
* double bonds as two parallel cylinders<br />
:: yea ([[User:Vvostri|Vvostri]]) / nay (0)<br />
* export scenes as [http://www.khronos.org/webgl/ WebGL] / Could make mobile apps, presentation plugins obsolete<br />
:: yea ([[User:Aschreyer|Aschreyer]]) / nay (0)<br />
* export images in vector format<br />
:: yea ([[User:Vvostri|Vvostri]], [[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Keynote plugin<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Electron density contour sliders<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Automatic electron density map generation from PDB mmcif files or user-supplied MTZ files<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Display of crystallographic symmetry and NCS axes, with possibility of showing symbols indicating what kind of axes they are<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)<br />
* Automatic symmetry expansion to show overall crystal packing; automatic generation of scenes showing crystal packing interface details<br />
:: yea ([[User:Lucajovine|Luca Jovine]]) / nay (0)</div>Mglernerhttps://wiki.pymol.org/index.php?title=Rendering_plugin&diff=9421Rendering plugin2010-01-22T02:04:11Z<p>Mglerner: </p>
<hr />
<div>==Description==<br />
Here is a small plugin to render images with a given DPI.<br />
<br />
The "Ray" button raytraces, and the "Draw" button just draws the image without raytracing (a fast way to see that the height/width look good).<br />
<br />
It warns you not to have the plugin window on top of your main PyMOL window when you click "Ray". That doesn't seem to be necessary anymore, at least on my MacBook Pro.<br />
<br />
The functionality is also available as a script (see my .pymolrc [[User:Mglerner|here]]).<br />
<br />
Here's the imperial version. The metric version follows.<br />
<br />
To install, save the script as e.g. rendering.py or rendering_metric.py and install via PyMOL's Plugin --> Manage Plugins --> Install menu.<br />
<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
# Plugin contributed by Michael Lerner (mglerner@gmail.com)<br />
<br />
import Tkinter<br />
import Pmw<br />
<br />
try:<br />
import pymol<br />
REAL_PYMOL = True<br />
except ImportError:<br />
REAL_PYMOL = False<br />
class pymol:<br />
class cmd:<br />
def ray(*args):<br />
print "ray",args<br />
def png(*args,**kwargs):<br />
print "png",args,kwargs<br />
def draw(*args,**kwargs):<br />
print "draw",args,kwargs<br />
ray = staticmethod(ray)<br />
png = staticmethod(png)<br />
draw = staticmethod(draw)<br />
<br />
def __init__(self):<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Launch Rendering Plugin',<br />
label='Rendering...',<br />
command = lambda s=self: RenderPlugin(s))<br />
class RenderPlugin:<br />
<br />
def __init__(self,app):<br />
self.parent = app.root<br />
self.dialog = Pmw.Dialog(self.parent,<br />
buttons = ('Ray','Draw','Exit'),<br />
title = 'PyMOL Rendering Plugin',<br />
command = self.execute)<br />
self.dialog.withdraw()<br />
Pmw.setbusycursorattributes(self.dialog.component('hull'))<br />
<br />
w = Tkinter.Label(self.dialog.interior(),<br />
text = 'PyMOL Rendering Plugin\nMichael Lerner, 2006 - www.umich.edu/~mlerner/PyMOL\nNOTE: make sure this window is not on top of the PyMOL window.',<br />
background = 'black',<br />
foreground = 'white',<br />
)<br />
w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)<br />
<br />
self.notebook = Pmw.NoteBook(self.dialog.interior())<br />
self.notebook.pack(fill='both',expand=1,padx=10,pady=10)<br />
<br />
# Set up the Main page<br />
page = self.notebook.add('Main')<br />
group = Pmw.Group(page,tag_text='Main options')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.filename = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Filename',<br />
value='picture.png',<br />
)<br />
self.height = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Height (inches):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
<br />
<br />
self.width = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Width (inches):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
self.dpi = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'DPI:',<br />
value = str(300),<br />
validate = {'validator' : 'integer',<br />
'min':0,}<br />
)<br />
entries = (self.height,self.width,self.filename,self.dpi)<br />
for entry in entries:<br />
#entry.pack(side='left',fill='both',expand=1,padx=4) # side-by-side<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
self.notebook.setnaturalsize()<br />
self.showAppModal()<br />
<br />
def showAppModal(self):<br />
#self.dialog.activate(geometry = 'centerscreenalways', globalMode = 'nograb')<br />
self.dialog.show()<br />
#self.dialog.activate(geometry = 'centerscreenalways')<br />
<br />
def execute(self, result):<br />
if result == 'Ray':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
pymol.cmd.ray(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
elif result == 'Draw':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
pymol.cmd.draw(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
else:<br />
#<br />
# Doing it this way takes care of clicking on the x in the top of the<br />
# window, which as result set to None.<br />
#<br />
if __name__ == '__main__':<br />
#<br />
# dies with traceback, but who cares<br />
#<br />
self.parent.destroy()<br />
else:<br />
self.dialog.withdraw()<br />
<br />
<br />
# Create demo in root window for testing.<br />
if __name__ == '__main__':<br />
class App:<br />
def my_show(self,*args,**kwargs):<br />
pass<br />
app = App()<br />
app.root = Tkinter.Tk()<br />
Pmw.initialise(app.root)<br />
app.root.title('Some Title')<br />
<br />
widget = RenderPlugin(app)<br />
exitButton = Tkinter.Button(app.root, text = 'Exit', command = app.root.destroy)<br />
exitButton.pack()<br />
app.root.mainloop()<br />
</source><br />
<br />
<br />
And here's the metric version<br />
<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
# Plugin contributed by Michael Lerner (mglerner@gmail.com)<br />
<br />
import Tkinter<br />
import Pmw<br />
<br />
try:<br />
import pymol<br />
REAL_PYMOL = True<br />
except ImportError:<br />
REAL_PYMOL = False<br />
class pymol:<br />
class cmd:<br />
def ray(*args):<br />
print "ray",args<br />
def png(*args,**kwargs):<br />
print "png",args,kwargs<br />
def draw(*args,**kwargs):<br />
print "draw",args,kwargs<br />
ray = staticmethod(ray)<br />
png = staticmethod(png)<br />
draw = staticmethod(draw)<br />
<br />
def __init__(self):<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Launch Metric Rendering Plugin',<br />
label='Metric Rendering...',<br />
command = lambda s=self: RenderPlugin(s))<br />
class RenderPlugin:<br />
<br />
def __init__(self,app):<br />
self.parent = app.root<br />
self.dialog = Pmw.Dialog(self.parent,<br />
buttons = ('Ray','Draw','Exit'),<br />
title = 'PyMOL Rendering Plugin',<br />
command = self.execute)<br />
self.dialog.withdraw()<br />
Pmw.setbusycursorattributes(self.dialog.component('hull'))<br />
<br />
w = Tkinter.Label(self.dialog.interior(),<br />
text = 'PyMOL Rendering Plugin\nMichael Lerner, 2006 - www.umich.edu/~mlerner/PyMOL\nNOTE: make sure this window is not on top of the PyMOL window.',<br />
background = 'black',<br />
foreground = 'white',<br />
)<br />
w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)<br />
<br />
self.notebook = Pmw.NoteBook(self.dialog.interior())<br />
self.notebook.pack(fill='both',expand=1,padx=10,pady=10)<br />
<br />
# Set up the Main page<br />
page = self.notebook.add('Main')<br />
group = Pmw.Group(page,tag_text='Main options')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.filename = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Filename',<br />
value='picture.png',<br />
)<br />
self.height = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Height (cm):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
<br />
<br />
self.width = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Width (cm):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
self.dpi = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'DPI:',<br />
value = str(300),<br />
validate = {'validator' : 'integer',<br />
'min':0,}<br />
)<br />
entries = (self.height,self.width,self.filename,self.dpi)<br />
for entry in entries:<br />
#entry.pack(side='left',fill='both',expand=1,padx=4) # side-by-side<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
self.notebook.setnaturalsize()<br />
self.showAppModal()<br />
<br />
def showAppModal(self):<br />
#self.dialog.activate(geometry = 'centerscreenalways', globalMode = 'nograb')<br />
self.dialog.show()<br />
#self.dialog.activate(geometry = 'centerscreenalways')<br />
<br />
def execute(self, result):<br />
in_per_cm = 0.393700787<br />
if result == 'Ray':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
h,w = in_per_cm*h,in_per_cm*w<br />
pymol.cmd.ray(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
elif result == 'Draw':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
h,w = in_per_cm*h,in_per_cm*w<br />
pymol.cmd.draw(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
else:<br />
#<br />
# Doing it this way takes care of clicking on the x in the top of the<br />
# window, which as result set to None.<br />
#<br />
if __name__ == '__main__':<br />
#<br />
# dies with traceback, but who cares<br />
#<br />
self.parent.destroy()<br />
else:<br />
self.dialog.withdraw()<br />
<br />
<br />
# Create demo in root window for testing.<br />
if __name__ == '__main__':<br />
class App:<br />
def my_show(self,*args,**kwargs):<br />
pass<br />
app = App()<br />
app.root = Tkinter.Tk()<br />
Pmw.initialise(app.root)<br />
app.root.title('Some Title')<br />
<br />
widget = RenderPlugin(app)<br />
exitButton = Tkinter.Button(app.root, text = 'Exit', command = app.root.destroy)<br />
exitButton.pack()<br />
app.root.mainloop()<br />
</source><br />
<br />
[[Category:Plugins]] [[Category:Coloring]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=Rendering_plugin&diff=9420Rendering plugin2010-01-22T02:02:45Z<p>Mglerner: </p>
<hr />
<div>==Description==<br />
Here is a small plugin to render images with a given DPI.<br />
<br />
The "Ray" button raytraces, and the "Draw" button just draws the image without raytracing (a fast way to see that the height/width look good).<br />
<br />
It warns you not to have the plugin window on top of your main PyMOL window when you click "Ray". That doesn't seem to be necessary anymore, at least on my MacBook Pro.<br />
<br />
The functionality is also available as a script (see my .pymolrc [[User:Mglerner|here]]).<br />
<br />
Here's the imperial version. The metric version follows.<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
# Plugin contributed by Michael Lerner (mglerner@gmail.com)<br />
<br />
import Tkinter<br />
import Pmw<br />
<br />
try:<br />
import pymol<br />
REAL_PYMOL = True<br />
except ImportError:<br />
REAL_PYMOL = False<br />
class pymol:<br />
class cmd:<br />
def ray(*args):<br />
print "ray",args<br />
def png(*args,**kwargs):<br />
print "png",args,kwargs<br />
def draw(*args,**kwargs):<br />
print "draw",args,kwargs<br />
ray = staticmethod(ray)<br />
png = staticmethod(png)<br />
draw = staticmethod(draw)<br />
<br />
def __init__(self):<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Launch Rendering Plugin',<br />
label='Rendering...',<br />
command = lambda s=self: RenderPlugin(s))<br />
class RenderPlugin:<br />
<br />
def __init__(self,app):<br />
self.parent = app.root<br />
self.dialog = Pmw.Dialog(self.parent,<br />
buttons = ('Ray','Draw','Exit'),<br />
title = 'PyMOL Rendering Plugin',<br />
command = self.execute)<br />
self.dialog.withdraw()<br />
Pmw.setbusycursorattributes(self.dialog.component('hull'))<br />
<br />
w = Tkinter.Label(self.dialog.interior(),<br />
text = 'PyMOL Rendering Plugin\nMichael Lerner, 2006 - www.umich.edu/~mlerner/PyMOL\nNOTE: make sure this window is not on top of the PyMOL window.',<br />
background = 'black',<br />
foreground = 'white',<br />
)<br />
w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)<br />
<br />
self.notebook = Pmw.NoteBook(self.dialog.interior())<br />
self.notebook.pack(fill='both',expand=1,padx=10,pady=10)<br />
<br />
# Set up the Main page<br />
page = self.notebook.add('Main')<br />
group = Pmw.Group(page,tag_text='Main options')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.filename = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Filename',<br />
value='picture.png',<br />
)<br />
self.height = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Height (inches):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
<br />
<br />
self.width = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Width (inches):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
self.dpi = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'DPI:',<br />
value = str(300),<br />
validate = {'validator' : 'integer',<br />
'min':0,}<br />
)<br />
entries = (self.height,self.width,self.filename,self.dpi)<br />
for entry in entries:<br />
#entry.pack(side='left',fill='both',expand=1,padx=4) # side-by-side<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
self.notebook.setnaturalsize()<br />
self.showAppModal()<br />
<br />
def showAppModal(self):<br />
#self.dialog.activate(geometry = 'centerscreenalways', globalMode = 'nograb')<br />
self.dialog.show()<br />
#self.dialog.activate(geometry = 'centerscreenalways')<br />
<br />
def execute(self, result):<br />
if result == 'Ray':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
pymol.cmd.ray(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
elif result == 'Draw':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
pymol.cmd.draw(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
else:<br />
#<br />
# Doing it this way takes care of clicking on the x in the top of the<br />
# window, which as result set to None.<br />
#<br />
if __name__ == '__main__':<br />
#<br />
# dies with traceback, but who cares<br />
#<br />
self.parent.destroy()<br />
else:<br />
self.dialog.withdraw()<br />
<br />
<br />
# Create demo in root window for testing.<br />
if __name__ == '__main__':<br />
class App:<br />
def my_show(self,*args,**kwargs):<br />
pass<br />
app = App()<br />
app.root = Tkinter.Tk()<br />
Pmw.initialise(app.root)<br />
app.root.title('Some Title')<br />
<br />
widget = RenderPlugin(app)<br />
exitButton = Tkinter.Button(app.root, text = 'Exit', command = app.root.destroy)<br />
exitButton.pack()<br />
app.root.mainloop()<br />
</source><br />
<br />
<br />
And here's the metric version<br />
<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
# Plugin contributed by Michael Lerner (mglerner@gmail.com)<br />
<br />
import Tkinter<br />
import Pmw<br />
<br />
try:<br />
import pymol<br />
REAL_PYMOL = True<br />
except ImportError:<br />
REAL_PYMOL = False<br />
class pymol:<br />
class cmd:<br />
def ray(*args):<br />
print "ray",args<br />
def png(*args,**kwargs):<br />
print "png",args,kwargs<br />
def draw(*args,**kwargs):<br />
print "draw",args,kwargs<br />
ray = staticmethod(ray)<br />
png = staticmethod(png)<br />
draw = staticmethod(draw)<br />
<br />
def __init__(self):<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Launch Metric Rendering Plugin',<br />
label='Metric Rendering...',<br />
command = lambda s=self: RenderPlugin(s))<br />
class RenderPlugin:<br />
<br />
def __init__(self,app):<br />
self.parent = app.root<br />
self.dialog = Pmw.Dialog(self.parent,<br />
buttons = ('Ray','Draw','Exit'),<br />
title = 'PyMOL Rendering Plugin',<br />
command = self.execute)<br />
self.dialog.withdraw()<br />
Pmw.setbusycursorattributes(self.dialog.component('hull'))<br />
<br />
w = Tkinter.Label(self.dialog.interior(),<br />
text = 'PyMOL Rendering Plugin\nMichael Lerner, 2006 - www.umich.edu/~mlerner/PyMOL\nNOTE: make sure this window is not on top of the PyMOL window.',<br />
background = 'black',<br />
foreground = 'white',<br />
)<br />
w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)<br />
<br />
self.notebook = Pmw.NoteBook(self.dialog.interior())<br />
self.notebook.pack(fill='both',expand=1,padx=10,pady=10)<br />
<br />
# Set up the Main page<br />
page = self.notebook.add('Main')<br />
group = Pmw.Group(page,tag_text='Main options')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.filename = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Filename',<br />
value='picture.png',<br />
)<br />
self.height = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Height (cm):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
<br />
<br />
self.width = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Width (cm):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
self.dpi = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'DPI:',<br />
value = str(300),<br />
validate = {'validator' : 'integer',<br />
'min':0,}<br />
)<br />
entries = (self.height,self.width,self.filename,self.dpi)<br />
for entry in entries:<br />
#entry.pack(side='left',fill='both',expand=1,padx=4) # side-by-side<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
self.notebook.setnaturalsize()<br />
self.showAppModal()<br />
<br />
def showAppModal(self):<br />
#self.dialog.activate(geometry = 'centerscreenalways', globalMode = 'nograb')<br />
self.dialog.show()<br />
#self.dialog.activate(geometry = 'centerscreenalways')<br />
<br />
def execute(self, result):<br />
in_per_cm = 0.393700787<br />
if result == 'Ray':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
h,w = in_per_cm*h,in_per_cm*w<br />
pymol.cmd.ray(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
elif result == 'Draw':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
h,w = in_per_cm*h,in_per_cm*w<br />
pymol.cmd.draw(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
else:<br />
#<br />
# Doing it this way takes care of clicking on the x in the top of the<br />
# window, which as result set to None.<br />
#<br />
if __name__ == '__main__':<br />
#<br />
# dies with traceback, but who cares<br />
#<br />
self.parent.destroy()<br />
else:<br />
self.dialog.withdraw()<br />
<br />
<br />
# Create demo in root window for testing.<br />
if __name__ == '__main__':<br />
class App:<br />
def my_show(self,*args,**kwargs):<br />
pass<br />
app = App()<br />
app.root = Tkinter.Tk()<br />
Pmw.initialise(app.root)<br />
app.root.title('Some Title')<br />
<br />
widget = RenderPlugin(app)<br />
exitButton = Tkinter.Button(app.root, text = 'Exit', command = app.root.destroy)<br />
exitButton.pack()<br />
app.root.mainloop()<br />
</source><br />
<br />
[[Category:Plugins]] [[Category:Coloring]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=Rendering_plugin&diff=9419Rendering plugin2010-01-22T02:01:57Z<p>Mglerner: Created page with '==Description== Here is a small plugin to render images with a given DPI. The "Ray" button raytraces, and the "Draw" button just draws the image without raytracing (a fast way t…'</p>
<hr />
<div>==Description==<br />
Here is a small plugin to render images with a given DPI.<br />
<br />
The "Ray" button raytraces, and the "Draw" button just draws the image without raytracing (a fast way to see that the height/width look good).<br />
<br />
It warns you not to have the plugin window on top of your main PyMOL window when you click "Ray". That doesn't seem to be necessary anymore, at least on my MacBook Pro.<br />
<br />
The functionality is also available as a script (see my .pymolrc [[User:Mglerner|here]]).<br />
<br />
Here's the imperial version. The metric version follows.<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
# Plugin contributed by Michael Lerner (mglerner@gmail.com)<br />
<br />
import Tkinter<br />
import Pmw<br />
<br />
try:<br />
import pymol<br />
REAL_PYMOL = True<br />
except ImportError:<br />
REAL_PYMOL = False<br />
class pymol:<br />
class cmd:<br />
def ray(*args):<br />
print "ray",args<br />
def png(*args,**kwargs):<br />
print "png",args,kwargs<br />
def draw(*args,**kwargs):<br />
print "draw",args,kwargs<br />
ray = staticmethod(ray)<br />
png = staticmethod(png)<br />
draw = staticmethod(draw)<br />
<br />
def __init__(self):<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Launch Rendering Plugin',<br />
label='Rendering...',<br />
command = lambda s=self: RenderPlugin(s))<br />
class RenderPlugin:<br />
<br />
def __init__(self,app):<br />
self.parent = app.root<br />
self.dialog = Pmw.Dialog(self.parent,<br />
buttons = ('Ray','Draw','Exit'),<br />
title = 'PyMOL Rendering Plugin',<br />
command = self.execute)<br />
self.dialog.withdraw()<br />
Pmw.setbusycursorattributes(self.dialog.component('hull'))<br />
<br />
w = Tkinter.Label(self.dialog.interior(),<br />
text = 'PyMOL Rendering Plugin\nMichael Lerner, 2006 - www.umich.edu/~mlerner/PyMOL\nNOTE: make sure this window is not on top of the PyMOL window.',<br />
background = 'black',<br />
foreground = 'white',<br />
)<br />
w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)<br />
<br />
self.notebook = Pmw.NoteBook(self.dialog.interior())<br />
self.notebook.pack(fill='both',expand=1,padx=10,pady=10)<br />
<br />
# Set up the Main page<br />
page = self.notebook.add('Main')<br />
group = Pmw.Group(page,tag_text='Main options')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.filename = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Filename',<br />
value='picture.png',<br />
)<br />
self.height = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Height (inches):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
<br />
<br />
self.width = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Width (inches):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
self.dpi = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'DPI:',<br />
value = str(300),<br />
validate = {'validator' : 'integer',<br />
'min':0,}<br />
)<br />
entries = (self.height,self.width,self.filename,self.dpi)<br />
for entry in entries:<br />
#entry.pack(side='left',fill='both',expand=1,padx=4) # side-by-side<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
self.notebook.setnaturalsize()<br />
self.showAppModal()<br />
<br />
def showAppModal(self):<br />
#self.dialog.activate(geometry = 'centerscreenalways', globalMode = 'nograb')<br />
self.dialog.show()<br />
#self.dialog.activate(geometry = 'centerscreenalways')<br />
<br />
def execute(self, result):<br />
if result == 'Ray':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
pymol.cmd.ray(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
elif result == 'Draw':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
pymol.cmd.draw(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
else:<br />
#<br />
# Doing it this way takes care of clicking on the x in the top of the<br />
# window, which as result set to None.<br />
#<br />
if __name__ == '__main__':<br />
#<br />
# dies with traceback, but who cares<br />
#<br />
self.parent.destroy()<br />
else:<br />
self.dialog.withdraw()<br />
<br />
<br />
# Create demo in root window for testing.<br />
if __name__ == '__main__':<br />
class App:<br />
def my_show(self,*args,**kwargs):<br />
pass<br />
app = App()<br />
app.root = Tkinter.Tk()<br />
Pmw.initialise(app.root)<br />
app.root.title('Some Title')<br />
<br />
widget = RenderPlugin(app)<br />
exitButton = Tkinter.Button(app.root, text = 'Exit', command = app.root.destroy)<br />
exitButton.pack()<br />
app.root.mainloop()<br />
</source><br />
<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
# Plugin contributed by Michael Lerner (mglerner@gmail.com)<br />
<br />
import Tkinter<br />
import Pmw<br />
<br />
try:<br />
import pymol<br />
REAL_PYMOL = True<br />
except ImportError:<br />
REAL_PYMOL = False<br />
class pymol:<br />
class cmd:<br />
def ray(*args):<br />
print "ray",args<br />
def png(*args,**kwargs):<br />
print "png",args,kwargs<br />
def draw(*args,**kwargs):<br />
print "draw",args,kwargs<br />
ray = staticmethod(ray)<br />
png = staticmethod(png)<br />
draw = staticmethod(draw)<br />
<br />
def __init__(self):<br />
self.menuBar.addmenuitem('Plugin', 'command',<br />
'Launch Metric Rendering Plugin',<br />
label='Metric Rendering...',<br />
command = lambda s=self: RenderPlugin(s))<br />
class RenderPlugin:<br />
<br />
def __init__(self,app):<br />
self.parent = app.root<br />
self.dialog = Pmw.Dialog(self.parent,<br />
buttons = ('Ray','Draw','Exit'),<br />
title = 'PyMOL Rendering Plugin',<br />
command = self.execute)<br />
self.dialog.withdraw()<br />
Pmw.setbusycursorattributes(self.dialog.component('hull'))<br />
<br />
w = Tkinter.Label(self.dialog.interior(),<br />
text = 'PyMOL Rendering Plugin\nMichael Lerner, 2006 - www.umich.edu/~mlerner/PyMOL\nNOTE: make sure this window is not on top of the PyMOL window.',<br />
background = 'black',<br />
foreground = 'white',<br />
)<br />
w.pack(expand = 1, fill = 'both', padx = 4, pady = 4)<br />
<br />
self.notebook = Pmw.NoteBook(self.dialog.interior())<br />
self.notebook.pack(fill='both',expand=1,padx=10,pady=10)<br />
<br />
# Set up the Main page<br />
page = self.notebook.add('Main')<br />
group = Pmw.Group(page,tag_text='Main options')<br />
group.pack(fill = 'both', expand = 1, padx = 10, pady = 5)<br />
self.filename = Pmw.EntryField(group.interior(),<br />
labelpos='w',<br />
label_text='Filename',<br />
value='picture.png',<br />
)<br />
self.height = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Height (cm):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
<br />
<br />
self.width = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'Width (cm):',<br />
value = str(4.0),<br />
validate = {'validator' : 'real',<br />
'min':0,}<br />
)<br />
self.dpi = Pmw.EntryField(group.interior(),labelpos='w',<br />
label_text = 'DPI:',<br />
value = str(300),<br />
validate = {'validator' : 'integer',<br />
'min':0,}<br />
)<br />
entries = (self.height,self.width,self.filename,self.dpi)<br />
for entry in entries:<br />
#entry.pack(side='left',fill='both',expand=1,padx=4) # side-by-side<br />
entry.pack(fill='x',expand=1,padx=4,pady=1) # vertical<br />
self.notebook.setnaturalsize()<br />
self.showAppModal()<br />
<br />
def showAppModal(self):<br />
#self.dialog.activate(geometry = 'centerscreenalways', globalMode = 'nograb')<br />
self.dialog.show()<br />
#self.dialog.activate(geometry = 'centerscreenalways')<br />
<br />
def execute(self, result):<br />
in_per_cm = 0.393700787<br />
if result == 'Ray':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
h,w = in_per_cm*h,in_per_cm*w<br />
pymol.cmd.ray(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
elif result == 'Draw':<br />
h = int(float(self.height.getvalue()) * int(self.dpi.getvalue()))<br />
w = int(float(self.width.getvalue()) * int(self.dpi.getvalue()))<br />
h,w = in_per_cm*h,in_per_cm*w<br />
pymol.cmd.draw(w,h)<br />
pymol.cmd.png(self.filename.getvalue(), dpi=int(self.dpi.getvalue()))<br />
else:<br />
#<br />
# Doing it this way takes care of clicking on the x in the top of the<br />
# window, which as result set to None.<br />
#<br />
if __name__ == '__main__':<br />
#<br />
# dies with traceback, but who cares<br />
#<br />
self.parent.destroy()<br />
else:<br />
self.dialog.withdraw()<br />
<br />
<br />
# Create demo in root window for testing.<br />
if __name__ == '__main__':<br />
class App:<br />
def my_show(self,*args,**kwargs):<br />
pass<br />
app = App()<br />
app.root = Tkinter.Tk()<br />
Pmw.initialise(app.root)<br />
app.root.title('Some Title')<br />
<br />
widget = RenderPlugin(app)<br />
exitButton = Tkinter.Button(app.root, text = 'Exit', command = app.root.destroy)<br />
exitButton.pack()<br />
app.root.mainloop()<br />
</source><br />
<br />
[[Category:Plugins]] [[Category:Coloring]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3159User:Mglerner2010-01-22T01:55:01Z<p>Mglerner: /* My ~/.pymolrc runs this .py script */</p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: units = 'in'<br />
elif 'cm' in x: units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3158User:Mglerner2010-01-22T01:53:33Z<p>Mglerner: /* My ~/.pymolrc runs this .py script */</p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
<br />
def rayy(width=-1,height=-1,units='in',dpi=-1,**kwargs):<br />
"""<br />
Slightly better version of the ray command.<br />
You can specify width and height in the units of your choice, e.g.<br />
<br />
rayy 3,2,units=in,dpi=300<br />
rayy 3in,2in<br />
rayy 1in, 2 cm, dpi=600<br />
<br />
Extra keyword arguments get passed on to the normal ray command.<br />
<br />
Units can be 'in' or 'cm'.<br />
<br />
For backwards compatibility, the conversion to dpi (or dots per<br />
centimeter) is only performed when dpi is specified.<br />
"""<br />
if type(dpi) in [type('')]: dpi = int(dpi)<br />
in_per_cm = 0.393700787<br />
def todots(x,units,dpi):<br />
if type(x) in [type('')]:<br />
x = x.lower()<br />
if 'in' in x: <br />
units = 'in'<br />
elif 'cm' in x: <br />
units = 'cm'<br />
x = float(x.replace(units,'').strip())<br />
if (dpi == -1):<br />
return x<br />
if units == 'cm': x = x * in_per_cm<br />
elif units == 'in': pass<br />
else: raise ValueError('Unknown units (%s)'%units)<br />
print '%s%s at %sdpi'%(x,units,dpi)<br />
return int(x * dpi)<br />
# How do we get current width/height of viewport? MainSceneGetSize perhaps<br />
# But it doesn't matter, as PyMOL will autoscale internally for us when given -1.<br />
try:<br />
width,height = todots(width,units,dpi),todots(height,units,dpi)<br />
except ValueError:<br />
print "Unknown units"<br />
return<br />
print 'width',width,'height',height<br />
cmd.ray(width=width,height=height,**kwargs)<br />
cmd.extend('rayy',rayy)<br />
<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=APBS&diff=4143APBS2009-12-01T20:12:51Z<p>Mglerner: </p>
<hr />
<div>== Introduction ==<br />
[[Image:Rna_surface_apbs.png|thumb|APBS-generated electrostatic surface displayed in PyMOL]]<br />
[http://apbs.sourceforge.net APBS], the Adaptive Poisson-Boltzmann Solver, is a [http://www.oreilly.com/openbook/freedom/ freely] available macromolecular electrostatics calculation program released under the [http://www.gnu.org/copyleft/gpl.html GPL]. It is a cost-effective but uncompromised alternative to [http://trantor.bioc.columbia.edu/grasp/ GRASP], and it can be used within pymol. Pymol can display the results of the calculations as an electrostatic potential molecular surface.<br />
<br />
PyMol currently supports the '''APBS plugin''' written by Michael Lerner. This plugin makes it possible to run APBS from within PyMOL, and then display the results as a color-coded electrostatic surface (units <math>K_bT/e_c</math>) in the molecular display window (as with the image to the right). See [http://apbs.wustl.edu/MediaWiki/index.php/APBS_electrostatics_in_PyMOL the APBS wiki] for more details, including instructions on how to download, install and use the plugin.<br />
<br />
'''Nucleic acids may prove problematic for the apbs plugin.''' If so, use the [http://pdb2pqr.sourceforge.net/ pdb2pqr] command-line tool to create a pqr file manually, instead of using the plugin to generate it. Then direct the APBS GUI on the [http://www-personal.umich.edu/~mlerner/PyMOL/images/main.png main menu] to read the pqr file you '''externally generated.'''<br />
<br />
==Required Dependencies==<br />
[http://apbs.sourceforge.net APBS] and its dependencies like [http://pdb2pqr.sourceforge.net pdb2pqr] and [http://scicomp.ucsd.edu/~mholst/codes/maloc/ maloc] are [http://www.oreilly.com/openbook/freedom/ freely] available under the [http://www.gnu.org/copyleft/gpl.html GPL]. The author of the software however [http://agave.wustl.edu/apbs/download/ asks that users register] with him to aid him in obtaining grant funding.<br />
<br />
----<br />
===Installing the Dependencies on OS X===<br />
#First, [http://agave.wustl.edu/apbs/download/ register] your use of the software. This will keep everyone happy.<br />
#Second, if you don't already have the [http://fink.sourceforge.net fink package management system], now is a good time to get it. Here is a [http://xanana.ucsc.edu/~wgscott/xtal/wiki/index.php/Quick_Start quick-start set of instructions] for getting X-windows, compilers, and fink all installed. <br />
#Once you are up and going, [http://xanana.ucsc.edu/~wgscott/xtal/wiki/index.php/How_to_Activate_the_Unstable_Branch activate the unstable branch in fink], and then issue the commands<br />
<source lang="bash"><br />
fink self-update<br />
fink install apbs<br />
</source><br />
or if you want to use the multi-processor version, issue<br />
<source lang="bash"><br />
fink self-update<br />
fink install apbs-mpi-openmpi<br />
</source><br />
Then install the X-windows based version of pymol using the command<br />
<source lang="bash"><br />
fink install pymol-py25<br />
</source><br />
Note that the fink version of pymol '''already has''' the latest version of the APBS plugin. You are set to go!<br />
<br />
Further details, as well as screen shots, are given [http://www.pymolwiki.org/index.php/MAC_Install#Install_APBS_and_friends_with_fink elsewhere in this wiki].<br />
<br />
===Installing the Dependencies on Linux===<br />
<br />
====From Scratch====<br />
Note that this tutorial assumes you're using the bash shell and have root privileges<br />
<OL><LI><br />
Obtain APBS and MALOC from...<br><br />
APBS = http://apbs.sourceforge.net (currently 0.4)<br><br />
MALOC = http://www.fetk.org/codes/maloc/index.html#download (currently 0.1-2)<BR><br />
<LI>Set up some environment variables & directories (temporary for building)<br />
<source lang="bash"><br />
$ export FETK_SRC=/<building directory>/temp_apbs<br />
$ export FETK_PREFIX=/usr/local/apbs-0.4.0 (or wherever you want it to live)<br />
$ export FETK_INCLUDE=${FETK_PREFIX}/include<br />
$ export FETK_LIBRARY=${FETK_PREFIX}/lib<br />
$ mkdir -p ${FETK_SRC} ${FETK_INCLUDE} ${FETK_LIBRARY}<br />
</source></LI><br />
<LI>Unpack the source packages<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}<br />
$ gzip -dc maloc-0.1-2.tar.gz | tar xvf -<br />
$ gzip -dc apbs-0.4.0.tar.gz | tar xvf -<br />
</source><br />
</LI><br />
<LI>Compile MALOC<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}/maloc<br />
$ ./configure --prefix=${FETK_PREFIX}</source><br />
If everything went well, then<br />
<source lang="bash"><br />
$ make; make install</source></LI><br />
<LI>Go get a coffee. Compilation/installation takes about 15 minutes on a 3GHz computer with 1GB of RAM.</LI><br />
<LI>Now on to compiling APBS itself<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}/apbs-0.4.0<br />
$ ./configure --prefix=${FETK_PREFIX}</source><br />
If all goes well:<br />
<source lang="bash"><br />
$ make all; make install</source></LI><br />
<LI>No time for coffee. Takes about 5 minutes on that fast computer.</LI><br />
<LI> There will now be an APBS binary at<br />
<source lang="bash">/usr/local/apbs-0.4.0/bin/i686-intel-linux/apbs</source></LI><br />
<LI> Make appropriate links<br />
<source lang="bash"><br />
$ ln -s /usr/local/apbs-0.4.0/bin/i686-intel-linux/apbs /usr/local/bin/apbs<br />
</source></LI><br />
<LI> Get rid of /<building directory dir>/temp_apbs<br />
<LI> Open PyMOL and make sure that the APBS plugin points to /usr/local/bin/apbs<br />
<LI> Rock and or Roll.<br />
</OL><br />
<br />
====Pre-Packaged====<br />
=====RPMs=====<br />
<br />
A variety of RPMs are available from the [http://sourceforge.net/project/showfiles.php?group_id=148472&package_id=163734&release_id=378273 APBS downloads website]. Again, please [http://agave.wustl.edu/apbs/download/ register] your use of the software if you have not yet done so.<br />
<br />
=====Debian packages=====<br />
<br />
For ubuntu and other debian linux distributions, probably the simplest thing is to download a promising looking rpm, convert it with the program [http://kitenet.net/programs/alien/ alien], and then install the [http://xanana.ucsc.edu/linux newly generated debian package] with the command<br />
<source lang="bash"><br />
sudo dpkg -i apbs*.deb<br />
</source><br />
<br />
=====Gentoo=====<br />
<br />
You have to install apbs and pdb2pqr. Both are masked via keywords atm. Type as root:<br />
<source lang="bash"><br />
echo sci-chemistry/pdb2pqr >> /etc/portage/package.keywords<br />
echo sci-chemistry/apbs >> /etc/portage/package.keywords<br />
emerge -av sci-chemistry/apbs sci-chemistry/pdb2pqr<br />
</source><br />
<br />
== Troubleshooting ==<br />
* If the B-factor is <math>\geq 100,</math> then APBS doesn't properly read in the PDB file and thus outputs garbage (or dies). To fix this, set all b factors to be less than 100. <source lang="python">alter all, b=min(b,99.9)</source> The problem stems from how to parse a PDB file. The PDB file originally was written when most people used FORTRAN programs, and so the file format was specified by columns, not by the more modern comma separated value format we tend to prefer today. For the latest on the PDB format see the [http://www.wwpdb.org/docs.html new PDB format docs].<br />
* APBS has problems, sometimes, in reading atoms with alternate conformations. You can remove the alternate locations with a simple script [[removeAlt]].<br />
* ObjectMapLoadDXFile-Error: as of this writing (9-23-2008) a known problem exists, and the Baker lab is working on it. It is typically caused by the use of directories with spaces in their names under Windows.<br />
<br />
== Problems with the bundled version of APBS ==<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
=== Leopard and Snow Leopard (10.5 and 10.6) ===<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
=== Tiger (10.4) ===<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
<br />
==Further contributions and edits are needed.==<br />
<br />
[[Category:Electrostatics]]<br />
[[Category:Biochemical_Properties]]<br />
[[Category:Plugins]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3157User:Mglerner2009-12-01T20:11:17Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. <br />
<br />
== Leopard and Snow Leopard (10.5 and 10.6) ==<br />
There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
<source lang="bash"><br />
bunzip2 libgfortran.3.dylib.gz2<br />
mv libgfortran.3.dylib /usr/local/lib<br />
</source><br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
<source lang="bash"><br />
ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib<br />
</source><br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
== Tiger (10.4) ==<br />
You'll need to install APBS yourself via MacPorts or via fink. Fink instructions may be found on the [[APBS]] page. Installation via MacPorts requires first installing MacPorts from [http://www.macports.org/] and then typing<br />
<br />
<source lang="bash"><br />
sudo port install apbs<br />
</source><br />
<br />
from the command line. This process could easily take several hours on an older machine, as MacPorts will recompile gcc, gfortran, and several other packages along the way.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=APBS&diff=4142APBS2009-12-01T16:26:07Z<p>Mglerner: </p>
<hr />
<div>== Introduction ==<br />
[[Image:Rna_surface_apbs.png|thumb|APBS-generated electrostatic surface displayed in PyMOL]]<br />
[http://apbs.sourceforge.net APBS], the Adaptive Poisson-Boltzmann Solver, is a [http://www.oreilly.com/openbook/freedom/ freely] available macromolecular electrostatics calculation program released under the [http://www.gnu.org/copyleft/gpl.html GPL]. It is a cost-effective but uncompromised alternative to [http://trantor.bioc.columbia.edu/grasp/ GRASP], and it can be used within pymol. Pymol can display the results of the calculations as an electrostatic potential molecular surface.<br />
<br />
PyMol currently supports the '''APBS plugin''' written by Michael Lerner. This plugin makes it possible to run APBS from within PyMOL, and then display the results as a color-coded electrostatic surface (units <math>K_bT/e_c</math>) in the molecular display window (as with the image to the right). See [http://apbs.wustl.edu/MediaWiki/index.php/APBS_electrostatics_in_PyMOL the APBS wiki] for more details, including instructions on how to download, install and use the plugin.<br />
<br />
'''Nucleic acids may prove problematic for the apbs plugin.''' If so, use the [http://pdb2pqr.sourceforge.net/ pdb2pqr] command-line tool to create a pqr file manually, instead of using the plugin to generate it. Then direct the APBS GUI on the [http://www-personal.umich.edu/~mlerner/PyMOL/images/main.png main menu] to read the pqr file you '''externally generated.'''<br />
<br />
==Required Dependencies==<br />
[http://apbs.sourceforge.net APBS] and its dependencies like [http://pdb2pqr.sourceforge.net pdb2pqr] and [http://scicomp.ucsd.edu/~mholst/codes/maloc/ maloc] are [http://www.oreilly.com/openbook/freedom/ freely] available under the [http://www.gnu.org/copyleft/gpl.html GPL]. The author of the software however [http://agave.wustl.edu/apbs/download/ asks that users register] with him to aid him in obtaining grant funding.<br />
<br />
----<br />
===Installing the Dependencies on OS X===<br />
#First, [http://agave.wustl.edu/apbs/download/ register] your use of the software. This will keep everyone happy.<br />
#Second, if you don't already have the [http://fink.sourceforge.net fink package management system], now is a good time to get it. Here is a [http://xanana.ucsc.edu/~wgscott/xtal/wiki/index.php/Quick_Start quick-start set of instructions] for getting X-windows, compilers, and fink all installed. <br />
#Once you are up and going, [http://xanana.ucsc.edu/~wgscott/xtal/wiki/index.php/How_to_Activate_the_Unstable_Branch activate the unstable branch in fink], and then issue the commands<br />
<source lang="bash"><br />
fink self-update<br />
fink install apbs<br />
</source><br />
or if you want to use the multi-processor version, issue<br />
<source lang="bash"><br />
fink self-update<br />
fink install apbs-mpi-openmpi<br />
</source><br />
Then install the X-windows based version of pymol using the command<br />
<source lang="bash"><br />
fink install pymol-py25<br />
</source><br />
Note that the fink version of pymol '''already has''' the latest version of the APBS plugin. You are set to go!<br />
<br />
Further details, as well as screen shots, are given [http://www.pymolwiki.org/index.php/MAC_Install#Install_APBS_and_friends_with_fink elsewhere in this wiki].<br />
<br />
===Installing the Dependencies on Linux===<br />
<br />
====From Scratch====<br />
Note that this tutorial assumes you're using the bash shell and have root privileges<br />
<OL><LI><br />
Obtain APBS and MALOC from...<br><br />
APBS = http://apbs.sourceforge.net (currently 0.4)<br><br />
MALOC = http://www.fetk.org/codes/maloc/index.html#download (currently 0.1-2)<BR><br />
<LI>Set up some environment variables & directories (temporary for building)<br />
<source lang="bash"><br />
$ export FETK_SRC=/<building directory>/temp_apbs<br />
$ export FETK_PREFIX=/usr/local/apbs-0.4.0 (or wherever you want it to live)<br />
$ export FETK_INCLUDE=${FETK_PREFIX}/include<br />
$ export FETK_LIBRARY=${FETK_PREFIX}/lib<br />
$ mkdir -p ${FETK_SRC} ${FETK_INCLUDE} ${FETK_LIBRARY}<br />
</source></LI><br />
<LI>Unpack the source packages<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}<br />
$ gzip -dc maloc-0.1-2.tar.gz | tar xvf -<br />
$ gzip -dc apbs-0.4.0.tar.gz | tar xvf -<br />
</source><br />
</LI><br />
<LI>Compile MALOC<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}/maloc<br />
$ ./configure --prefix=${FETK_PREFIX}</source><br />
If everything went well, then<br />
<source lang="bash"><br />
$ make; make install</source></LI><br />
<LI>Go get a coffee. Compilation/installation takes about 15 minutes on a 3GHz computer with 1GB of RAM.</LI><br />
<LI>Now on to compiling APBS itself<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}/apbs-0.4.0<br />
$ ./configure --prefix=${FETK_PREFIX}</source><br />
If all goes well:<br />
<source lang="bash"><br />
$ make all; make install</source></LI><br />
<LI>No time for coffee. Takes about 5 minutes on that fast computer.</LI><br />
<LI> There will now be an APBS binary at<br />
<source lang="bash">/usr/local/apbs-0.4.0/bin/i686-intel-linux/apbs</source></LI><br />
<LI> Make appropriate links<br />
<source lang="bash"><br />
$ ln -s /usr/local/apbs-0.4.0/bin/i686-intel-linux/apbs /usr/local/bin/apbs<br />
</source></LI><br />
<LI> Get rid of /<building directory dir>/temp_apbs<br />
<LI> Open PyMOL and make sure that the APBS plugin points to /usr/local/bin/apbs<br />
<LI> Rock and or Roll.<br />
</OL><br />
<br />
====Pre-Packaged====<br />
=====RPMs=====<br />
<br />
A variety of RPMs are available from the [http://sourceforge.net/project/showfiles.php?group_id=148472&package_id=163734&release_id=378273 APBS downloads website]. Again, please [http://agave.wustl.edu/apbs/download/ register] your use of the software if you have not yet done so.<br />
<br />
=====Debian packages=====<br />
<br />
For ubuntu and other debian linux distributions, probably the simplest thing is to download a promising looking rpm, convert it with the program [http://kitenet.net/programs/alien/ alien], and then install the [http://xanana.ucsc.edu/linux newly generated debian package] with the command<br />
<source lang="bash"><br />
sudo dpkg -i apbs*.deb<br />
</source><br />
<br />
=====Gentoo=====<br />
<br />
You have to install apbs and pdb2pqr. Both are masked via keywords atm. Type as root:<br />
<source lang="bash"><br />
echo sci-chemistry/pdb2pqr >> /etc/portage/package.keywords<br />
echo sci-chemistry/apbs >> /etc/portage/package.keywords<br />
emerge -av sci-chemistry/apbs sci-chemistry/pdb2pqr<br />
</source><br />
<br />
== Troubleshooting ==<br />
* If the B-factor is <math>\geq 100,</math> then APBS doesn't properly read in the PDB file and thus outputs garbage (or dies). To fix this, set all b factors to be less than 100. <source lang="python">alter all, b=min(b,99.9)</source> The problem stems from how to parse a PDB file. The PDB file originally was written when most people used FORTRAN programs, and so the file format was specified by columns, not by the more modern comma separated value format we tend to prefer today. For the latest on the PDB format see the [http://www.wwpdb.org/docs.html new PDB format docs].<br />
* APBS has problems, sometimes, in reading atoms with alternate conformations. You can remove the alternate locations with a simple script [[removeAlt]].<br />
* ObjectMapLoadDXFile-Error: as of this writing (9-23-2008) a known problem exists, and the Baker lab is working on it. It is typically caused by the use of directories with spaces in their names under Windows.<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
<br />
==Further contributions and edits are needed.==<br />
<br />
[[Category:Electrostatics]]<br />
[[Category:Biochemical_Properties]]<br />
[[Category:Plugins]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=User_talk:Mglerner&diff=10745User talk:Mglerner2009-12-01T16:20:54Z<p>Mglerner: </p>
<hr />
<div>Michael,<br />
<br />
Check out [[Fetch_Path]] for a cool setting. I don't use [[load]] much now b/c of this.<br />
<br />
[[User:Inchoate|Tree]] 15:54, 1 December 2009 (UTC)<br />
: cool!--[[User:Mglerner|-michael]] 16:20, 1 December 2009 (UTC)</div>Mglernerhttps://wiki.pymol.org/index.php?title=User_talk:Mglerner&diff=10744User talk:Mglerner2009-12-01T16:20:32Z<p>Mglerner: </p>
<hr />
<div>Michael,<br />
<br />
Check out [[Fetch_Path]] for a cool setting. I don't use [[load]] much now b/c of this.<br />
<br />
[[User:Inchoate|Tree]] 15:54, 1 December 2009 (UTC)<br />
: cool! Now if only I could make the signature button here do something other than --[[User:Mglerner|-michael]] 16:20, 1 December 2009 (UTC)</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3156User:Mglerner2009-12-01T15:43:15Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2 for OS X. There are three fairly easy ways to resolve it<br />
<br />
1. Download and install the most recent (post Dec. 1 2009) version of APBS from [http://www.poissonboltzmann.org/apbs/downloads]. Then copy the apbs binary into the freemol directory (mv it to /Applications/PyMOLX11Hybrid.app/pymol/freemol/bin/apbs.exe, overwriting the version that comes installed with PyMOL).<br />
<br />
2. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
3. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3155User:Mglerner2009-11-30T20:03:43Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2. There are two fairly easy ways to resolve it<br />
<br />
1. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
2. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
The version of libgfortran above is covered by the GNU General Public License (GPL). A copy of the GPL may be found at [http://www.gnu.org/licenses/licenses.html], and the source may be obtained from MacPorts ([http://www.macports.org/]).<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3154User:Mglerner2009-11-30T19:55:06Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= APBS Plugin FAQ =<br />
<br />
There is an issue with the freemol version of APBS shipped with PyMOL 1.2r2. There are two fairly easy ways to resolve it<br />
<br />
1. Download [[File:Libgfortran.3.dylib.bz2]], unzip it ("bunzip2 libgfortran.3.dylib.gz2") and move it to /usr/local/lib ("mv libgfortran.3.dylib /usr/local/lib" ... on some machines, you may need "sudo mv libgfortran.3.dylib /usr/local/lib").<br />
<br />
2. Use macports to install gcc 4.4.2 and link the appropriate library ("ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib" ... on some machines, you may need "sudo ln -s /opt/local/lib/gcc44/libgfortran.3.dylib /usr/local/lib/libgfortran.3.dylib").<br />
<br />
If you're curious, the problem is that APBS is dynamically linked, but Apple does not provide FORTRAN libraries.<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=File:Libgfortran.3.dylib.bz2&diff=2368File:Libgfortran.3.dylib.bz22009-11-30T19:45:20Z<p>Mglerner: libgfortran.3.dylib, required for freemol's APBS.</p>
<hr />
<div>libgfortran.3.dylib, required for freemol's APBS.</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3153User:Mglerner2009-11-17T20:31:35Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3152User:Mglerner2009-11-17T20:31:14Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= My open-source toolchain =<br />
<br />
* PyMOL (visualization, system setup, etc)<br />
* Python (all scripting/automation tasks)<br />
* numpy (efficient numerical library)<br />
* scipy (including traits for simple GUIs)<br />
* matplotlib (2D plotting)<br />
* GROMACS (simulations)<br />
<br />
I also make significant use of CHARMM and Amber. I used to be a heavy Linux supporter, but OS X has all of its advantages without the burden of system administration. If only it had a decent package management system.<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
</source><br />
<br />
= To Do =<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3151User:Mglerner2009-11-17T20:05:29Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
</source><br />
<br />
== To Do ==<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner|mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=APBS&diff=4141APBS2009-11-17T19:55:54Z<p>Mglerner: </p>
<hr />
<div>== Introduction ==<br />
[[Image:Rna_surface_apbs.png|thumb|APBS-generated electrostatic surface displayed in PyMOL]]<br />
[http://apbs.sourceforge.net APBS], the Adaptive Poisson-Boltzmann Solver, is a [http://www.oreilly.com/openbook/freedom/ freely] available macromolecular electrostatics calculation program released under the [http://www.gnu.org/copyleft/gpl.html GPL]. It is a cost-effective but uncompromised alternative to [http://trantor.bioc.columbia.edu/grasp/ GRASP], and it can be used within pymol. Pymol can display the results of the calculations as an electrostatic potential molecular surface.<br />
<br />
PyMol currently supports the '''APBS plugin''' written by Michael Lerner. This plugin makes it possible to run APBS from within PyMOL, and then display the results as a color-coded electrostatic surface (units <math>K_bT/e_c</math>) in the molecular display window (as with the image to the right). See [http://apbs.wustl.edu/MediaWiki/index.php/APBS_electrostatics_in_PyMOL the APBS wiki] for more details, including instructions on how to download, install and use the plugin.<br />
<br />
'''Nucleic acids may prove problematic for the apbs plugin.''' If so, use the [http://pdb2pqr.sourceforge.net/ pdb2pqr] command-line tool to create a pqr file manually, instead of using the plugin to generate it. Then direct the APBS GUI on the [http://www-personal.umich.edu/~mlerner/PyMOL/images/main.png main menu] to read the pqr file you '''externally generated.'''<br />
<br />
==Required Dependencies==<br />
[http://apbs.sourceforge.net APBS] and its dependencies like [http://pdb2pqr.sourceforge.net pdb2pqr] and [http://scicomp.ucsd.edu/~mholst/codes/maloc/ maloc] are [http://www.oreilly.com/openbook/freedom/ freely] available under the [http://www.gnu.org/copyleft/gpl.html GPL]. The author of the software however [http://agave.wustl.edu/apbs/download/ asks that users register] with him to aid him in obtaining grant funding.<br />
<br />
----<br />
===Installing the Dependencies on OS X===<br />
#First, [http://agave.wustl.edu/apbs/download/ register] your use of the software. This will keep everyone happy.<br />
#Second, if you don't already have the [http://fink.sourceforge.net fink package management system], now is a good time to get it. Here is a [http://xanana.ucsc.edu/~wgscott/xtal/wiki/index.php/Quick_Start quick-start set of instructions] for getting X-windows, compilers, and fink all installed. <br />
#Once you are up and going, [http://xanana.ucsc.edu/~wgscott/xtal/wiki/index.php/How_to_Activate_the_Unstable_Branch activate the unstable branch in fink], and then issue the commands<br />
<source lang="bash"><br />
fink self-update<br />
fink install apbs<br />
</source><br />
or if you want to use the multi-processor version, issue<br />
<source lang="bash"><br />
fink self-update<br />
fink install apbs-mpi-openmpi<br />
</source><br />
Then install the X-windows based version of pymol using the command<br />
<source lang="bash"><br />
fink install pymol-py25<br />
</source><br />
Note that the fink version of pymol '''already has''' the latest version of the APBS plugin. You are set to go!<br />
<br />
Further details, as well as screen shots, are given [http://www.pymolwiki.org/index.php/MAC_Install#Install_APBS_and_friends_with_fink elsewhere in this wiki].<br />
<br />
===Installing the Dependencies on Linux===<br />
<br />
====From Scratch====<br />
Note that this tutorial assumes you're using the bash shell and have root privileges<br />
<OL><LI><br />
Obtain APBS and MALOC from...<br><br />
APBS = http://apbs.sourceforge.net (currently 0.4)<br><br />
MALOC = http://www.fetk.org/codes/maloc/index.html#download (currently 0.1-2)<BR><br />
<LI>Set up some environment variables & directories (temporary for building)<br />
<source lang="bash"><br />
$ export FETK_SRC=/<building directory>/temp_apbs<br />
$ export FETK_PREFIX=/usr/local/apbs-0.4.0 (or wherever you want it to live)<br />
$ export FETK_INCLUDE=${FETK_PREFIX}/include<br />
$ export FETK_LIBRARY=${FETK_PREFIX}/lib<br />
$ mkdir -p ${FETK_SRC} ${FETK_INCLUDE} ${FETK_LIBRARY}<br />
</source></LI><br />
<LI>Unpack the source packages<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}<br />
$ gzip -dc maloc-0.1-2.tar.gz | tar xvf -<br />
$ gzip -dc apbs-0.4.0.tar.gz | tar xvf -<br />
</source><br />
</LI><br />
<LI>Compile MALOC<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}/maloc<br />
$ ./configure --prefix=${FETK_PREFIX}</source><br />
If everything went well, then<br />
<source lang="bash"><br />
$ make; make install</source></LI><br />
<LI>Go get a coffee. Compilation/installation takes about 15 minutes on a 3GHz computer with 1GB of RAM.</LI><br />
<LI>Now on to compiling APBS itself<br />
<source lang="bash"><br />
$ cd ${FETK_SRC}/apbs-0.4.0<br />
$ ./configure --prefix=${FETK_PREFIX}</source><br />
If all goes well:<br />
<source lang="bash"><br />
$ make all; make install</source></LI><br />
<LI>No time for coffee. Takes about 5 minutes on that fast computer.</LI><br />
<LI> There will now be an APBS binary at<br />
<source lang="bash">/usr/local/apbs-0.4.0/bin/i686-intel-linux/apbs</source></LI><br />
<LI> Make appropriate links<br />
<source lang="bash"><br />
$ ln -s /usr/local/apbs-0.4.0/bin/i686-intel-linux/apbs /usr/local/bin/apbs<br />
</source></LI><br />
<LI> Get rid of /<building directory dir>/temp_apbs<br />
<LI> Open PyMOL and make sure that the APBS plugin points to /usr/local/bin/apbs<br />
<LI> Rock and or Roll.<br />
</OL><br />
<br />
====Pre-Packaged====<br />
=====RPMs=====<br />
<br />
A variety of RPMs are available from the [http://sourceforge.net/project/showfiles.php?group_id=148472&package_id=163734&release_id=378273 APBS downloads website]. Again, please [http://agave.wustl.edu/apbs/download/ register] your use of the software if you have not yet done so.<br />
<br />
=====Debian packages=====<br />
<br />
For ubuntu and other debian linux distributions, probably the simplest thing is to download a promising looking rpm, convert it with the program [http://kitenet.net/programs/alien/ alien], and then install the [http://xanana.ucsc.edu/linux newly generated debian package] with the command<br />
<source lang="bash"><br />
sudo dpkg -i apbs*.deb<br />
</source><br />
<br />
=====Gentoo=====<br />
<br />
You have to install apbs and pdb2pqr. Both are masked via keywords atm. Type as root:<br />
<source lang="bash"><br />
echo sci-chemistry/pdb2pqr >> /etc/portage/package.keywords<br />
echo sci-chemistry/apbs >> /etc/portage/package.keywords<br />
emerge -av sci-chemistry/apbs sci-chemistry/pdb2pqr<br />
</source><br />
<br />
== Troubleshooting ==<br />
* If the B-factor is <math>\geq 100,</math> then APBS doesn't properly read in the PDB file and thus outputs garbage (or dies). To fix this, set all b factors to be less than 100. <source lang="python">alter all, b=min(b,99.9)</source> The problem stems from how to parse a PDB file. The PDB file originally was written when most people used FORTRAN programs, and so the file format was specified by columns, not by the more modern comma separated value format we tend to prefer today. For the latest on the PDB format see the [http://www.wwpdb.org/docs.html new PDB format docs].<br />
* APBS has problems, sometimes, in reading atoms with alternate conformations. You can remove the alternate locations with a simple script [[removeAlt]].<br />
* ObjectMapLoadDXFile-Error: as of this writing (9-23-2008) a known problem exists, and the Baker lab is working on it. It is typically caused by the use of directories with spaces in their names under Windows.<br />
<br />
==Further contributions and edits are needed.==<br />
<br />
[[Category:Electrostatics]]<br />
[[Category:Biochemical_Properties]]</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3150User:Mglerner2009-11-17T19:50:35Z<p>Mglerner: </p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
</source><br />
<br />
== To Do ==<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner]] Tue Nov 17 14:46:42 EST 2009</div>Mglernerhttps://wiki.pymol.org/index.php?title=User:Mglerner&diff=3149User:Mglerner2009-11-17T19:49:18Z<p>Mglerner: Created page with 'My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's l…'</p>
<hr />
<div>My name is Michael Lerner. I'm currently an IRTA postdoctoral fellow at NIH in the NHLBI's Laboratory of Computational Biology. Before that, I was a member of Heather Carlson's lab at the University of Michigan.<br />
<br />
I wrote the PyMOL/APBS plugin.<br />
<br />
-- '''Michael G. Lerner, PhD <br/><br />
''m dot g dot lerner (_at-) gmail dot com''<br />
<br />
= My ~/.pymolrc runs this .py script=<br />
<source lang="python"><br />
#!/usr/bin/env python<br />
from pymol import cmd,stored<br />
cmd.set('pdb_retain_ids',1)<br />
cmd.set('retain_order',1)<br />
import os<br />
def gro(fnm,name=None):<br />
os.system("/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm)<br />
print "Just did","/usr/local/bin/editconf -f %s -o /tmp/tmp.pdb" % fnm<br />
if name is None:<br />
name = fnm[:-4]<br />
cmd.load("/tmp/tmp.pdb",name)<br />
cmd.extend("gro",gro)<br />
<br />
def splitseq(seq,size):<br />
""" Split up seq in pieces of size """<br />
return [seq[i:i+size] for i in range(0, len(seq), size)]<br />
<br />
def getIDsInSel(sel, sorted=True, reversed=False):<br />
"""<br />
PARAMETERS<br />
sel,<br />
The selection, object or group to iterate over<br />
sorted (boolean),<br />
Should the list be sorted?<br />
reversed (boolean)<br />
Should the list be reversed before returned? (Combined<br />
with the above, you can return a decreasing-sorted list<br />
of names<br />
<br />
RETURNS<br />
list[] of strings, representing the object IDs desired.<br />
<br />
CREDITS<br />
This is a very slightly modified version of getNamesInSel <br />
from http://pymolwiki.org/index.php/GetNamesInSel<br />
"""<br />
stored.tempNames = set()<br />
cmd.iterate(sel, "stored.tempNames.add(ID)")<br />
rList = list(stored.tempNames)<br />
<br />
# if you want the list reversed or sorted,<br />
# uncomment the following lines<br />
if sorted:<br />
rList.sort()<br />
if reversed:<br />
rList.reverse()<br />
return rList<br />
<br />
cmd.extend("getIDsInSel", getIDsInSel)<br />
def togrp(selname,fname):<br />
'''Make a GROMACS index group from a selection'''<br />
f = file(fname,'w')<br />
f.write('[ %s ]\n'%selname)<br />
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <br />
#7267 7268 7269 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 <br />
idxs = getIDsInSel(selname)<br />
for g in splitseq(idxs,15):<br />
line = ' '.join(['%4s'%i for i in g])<br />
line = line + '\n'<br />
f.write(line)<br />
f.write('\n')<br />
f.close()<br />
cmd.extend('togrp',togrp)<br />
</source><br />
<br />
== To Do ==<br />
* Update the PyMOL/APBS plugin page<br />
<br />
<br />
[[User:Mglerner] Tue Nov 17 14:46:42 EST 2009</div>Mglerner