• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

tools/python/runGB.py

00001 """ Python APBS Generalized Born Implementation
00002 
00003     This module uses APBS to parameterize the effective Born radii of the
00004     Generalized Born electrostatic model and calculate the electrostatic
00005     solvation energy.
00006 
00007     Justin Xiang (jxiang@ccb.wustl.edu)
00008     Todd Dolinsky (todd@ccb.wustl.edu)
00009     Nathan Baker (baker@biochem.wustl.edu)
00010     Washington University in St. Louis
00011 
00012            APBS -- Adaptive Poisson-Boltzmann Solver
00013 
00014              Nathan A. Baker (baker@biochem.wustl.edu)
00015              Dept. Biochemistry and Molecular Biophysics
00016              Center for Computational Biology
00017              Washington University in St. Louis
00018 
00019              Additional contributing authors listed in the code documentation.
00020 
00021            Copyright (c) 2002-2010, Washington University in St. Louis.
00022            Portions Copyright (c) 2002-2010.  Nathan A. Baker
00023            Portions Copyright (c) 1999-2002.  The Regents of the University of California.
00024            Portions Copyright (c) 1995.  Michael Holst
00025 
00026            All rights reserved.
00027 
00028            Redistribution and use in source and binary forms, with or without
00029            modification, are permitted provided that the following conditions are met: 
00030 
00031            * Redistributions of source code must retain the above copyright notice, this
00032            list of conditions and the following disclaimer.  
00033 
00034            * Redistributions in binary form must reproduce the above copyright notice,
00035            this list of conditions and the following disclaimer in the documentation
00036            and/or other materials provided with the distribution.
00037 
00038            * Neither the name of Washington University in St. Louis nor the names of its
00039            contributors may be used to endorse or promote products derived from this
00040            software without specific prior written permission.
00041 
00042            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00043            "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00044            LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00045            A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00046            CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00047            EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00048            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00049            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00050            LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00051            NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00052            SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00053 """ 
00054 
00055 from apbslib import *
00056 import sys, time, getopt
00057 import string
00058 import math
00059 from sys import stdout, stderr
00060 from math import sqrt, pow, exp, pi
00061 
00062 __author__ = "Justin Xiang, Todd Dolinsky, Nathan Baker, Yong Huang"
00063 __date__ = "September 2009"
00064 
00065 Python_kb = 1.3806581e-23
00066 Python_Na = 6.0221367e+23
00067 Python_e0 = 8.85419e-12
00068 Python_C = 1.602117e-19
00069 NOSH_MAXMOL = 20
00070 NOSH_MAXCALC = 20
00071 
00072 class APBSError(Exception):
00073     """ APBSError class
00074 
00075         The APBSError class inherits off the Exception module and returns
00076         a string defining the nature of the error. 
00077     """
00078     
00079     def __init__(self, value):
00080         """
00081             Initialize with error message
00082 
00083             Parameters
00084                 value:  Error Message (string)
00085         """
00086         self.value = value
00087         
00088     def __str__(self):
00089         """
00090             Return the error message
00091         """
00092         return `self.value`
00093 
00094 def getHeader():
00095     """ Get header information about APBS
00096         Returns (header)
00097             header: Information about APBS
00098     """
00099 
00100     """ Get header information about APBS
00101         Returns (header)
00102             header: Information about APBS
00103     """
00104 
00105     header = "\n\n\
00106     ----------------------------------------------------------------------\n\
00107     Adaptive Poisson-Boltzmann Solver (APBS)\n\
00108     Version 1.3\n\
00109     \n\
00110     APBS -- Adaptive Poisson-Boltzmann Solver\n\
00111     \n\
00112     Nathan A. Baker (baker@biochem.wustl.edu)\n\
00113     Dept. Biochemistry and Molecular Biophysics\n\
00114     Center for Computational Biology\n\
00115     Washington University in St. Louis\n\
00116     \n\
00117     Additional contributing authors listed in the code documentation.\n\
00118     \n\
00119     Copyright (c) 2002-2010, Washington University in St. Louis.\n\
00120     Portions Copyright (c) 2002-2010.  Nathan A. Baker\n\
00121     Portions Copyright (c) 1999-2002.  The Regents of the University of California.\n\
00122     Portions Copyright (c) 1995.  Michael Holst\n\
00123     \n\
00124     All rights reserved.\n\
00125     \n\
00126     Redistribution and use in source and binary forms, with or without\n\
00127     modification, are permitted provided that the following conditions are met:\n\
00128     \n\
00129     * Redistributions of source code must retain the above copyright notice, this\n\
00130       list of conditions and the following disclaimer.\n\
00131     \n\
00132     * Redistributions in binary form must reproduce the above copyright notice,\n\
00133       this list of conditions and the following disclaimer in the documentation\n\
00134       and/or other materials provided with the distribution.\n\
00135     \n\
00136     * Neither the name of Washington University in St. Louis nor the names of its\n\
00137       contributors may be used to endorse or promote products derived from this\n\
00138       software without specific prior written permission.\n\
00139     \n\
00140     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\
00141     \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n\
00142     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n\
00143     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n\
00144     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n\
00145     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n\
00146     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n\
00147     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n\
00148     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n\
00149     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n\
00150     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\
00151     ----------------------------------------------------------------------\n\
00152     \n\n"
00153     return header
00154 
00155 def getUsage():
00156     """ Get usage information about running APBS via Python
00157         Returns (usage)
00158             usage: Text about running APBS via Python
00159     """
00160     
00161     usage = "\n\n\
00162     ----------------------------------------------------------------------\n\
00163     This driver program calculates electrostatic solvation energy with\n\
00164     Poission-Boltzmann parameterized Generailized Born model. \n\
00165     It is invoked as:\n\n\
00166       python runGB.py -i apbs.in\n\n\
00167     Optional arguments:\n\
00168       -o <output_parameter>     specifies path to output GB parameter file\n\
00169                                 (default: GB-parameters)\n\
00170                                 this parameter file is compatible with\n\
00171                                 readGB.py module\n\
00172       -m <output_matrix>        specifies path to output GB energy matrix\n\
00173       -h or --help              prints this help text\n\n\
00174     Special input file requirements:\n\
00175     This program can only calculate solvation energy for 1 molecule. Also,\n\
00176     it is assumed that the first molecule read in from the input file is\n\
00177     the target molecule. Additional molecules can be included only for\n\
00178     other purposes, such as centering etc. The elec statments specifies\n\
00179     the conditions for computing self energies during the parameterization\n\
00180     step. \n\
00181     ----------------------------------------------------------------------\n\n"
00182 
00183     return usage
00184 
00185 def main():
00186     """ Main driver for testing.  Runs APBS on given input file """
00187     
00188     # Initialize the MALOC library
00189     startVio()
00190 
00191     # Initialize variables, arrays
00192     com = Vcom_ctor(1)
00193     rank = Vcom_rank(com)
00194     size = Vcom_size(com)
00195     mgparm = MGparm()
00196     pbeparm = PBEparm()
00197     mem = Vmem_ctor("Main")
00198     pbe = new_pbelist(NOSH_MAXMOL)
00199     pmg = new_pmglist(NOSH_MAXMOL)
00200     pmgp = new_pmgplist(NOSH_MAXMOL)
00201     realCenter = double_array(3)
00202     totEnergy = []
00203     nforce = int_array(NOSH_MAXCALC)
00204     atomforce = new_atomforcelist(NOSH_MAXCALC)
00205     sdie = 0
00206     
00207     # Start the main timer
00208     
00209     main_timer_start = time.clock()
00210 
00211     # Check invocation
00212     
00213     stdout.write(getHeader())
00214     try:
00215         opts, args = getopt.getopt(sys.argv[1:], "hi:o:m:", ["help"])
00216     except getopt.GetoptError:
00217         stdout.write("problem with input format\n")
00218         stdout.write(getUsage())
00219         sys.exit("Incorrect usage!\n")
00220 
00221     output_param = "GB-parameters.dat"
00222     output_matrix = ""
00223     for o, a in opts:
00224         if o in ("-h", "--help"):
00225             stdout.write("Printing help text...\n")
00226             stdout.write(getUsage())
00227             sys.exit()
00228         if o == "-i":
00229             input_file = a
00230         if o == "-o":
00231             output_param = a
00232         if o == "-m":
00233             output_matrix = a
00234 
00235     # Parse the input file
00236     
00237     nosh = NOsh_ctor(rank, size)
00238     try: input_file
00239     except:
00240         stdout.write("input file not initiated - check input\n")
00241         stdout.write(getUsage())
00242         sys.exit("Incorrect usage!\n")
00243     stdout.write("Parsing input file %s...\n" % input_file)
00244     if NOsh_parseInputFile(nosh, input_file) != 1:
00245         stderr.write("main:  Error while parsing input file.\n")
00246         raise APBSError, "Error while parsing input file!"
00247 
00248     # Load the molecules using loadMolecules routine
00249 
00250     alist = new_valist(NOSH_MAXMOL)
00251     
00252     if loadMolecules(nosh,None,alist) != 1:
00253         stderr.write("main:  Error while loading molecules. \n")
00254         raise APBSError, "Error while loading molecules!"    
00255 
00256     # Setup reference lists
00257 
00258     numAtoms = get_Valist(alist,0).number
00259     stdout.write("Number of atoms loaded: %d\n" % numAtoms)
00260     reflist = []
00261     radlist = []
00262     position = [0 for i in range(numAtoms)]
00263     for iatom in xrange(numAtoms):
00264         reflist.append(Vatom_getCharge(Valist_getAtom(get_Valist(alist, 0), iatom)))
00265         radlist.append(Vatom_getRadius(Valist_getAtom(get_Valist(alist, 0), iatom)))
00266         position[iatom] = getAtomPosition(Valist_getAtom(get_Valist(alist, 0), iatom))
00267 
00268     # Setup calculations
00269 
00270     if NOsh_setupElecCalc(nosh, alist)!=1:
00271         stderr.write("main: Error while setting up calculations. \n")
00272         raise APBSError, "Error while setting up calculations. \n"
00273         
00274     # Initialize the energy arrays
00275     
00276     for i in xrange(nosh.ncalc): totEnergy.append(0.0)
00277     selfEnergy = []
00278 
00279     # Load the dielectric maps (will be reused)
00280     
00281     dielXMap = new_gridlist(NOSH_MAXMOL)
00282     dielYMap = new_gridlist(NOSH_MAXMOL)
00283     dielZMap = new_gridlist(NOSH_MAXMOL)
00284     if loadDielMaps(nosh, dielXMap, dielYMap, dielZMap) != 1:
00285         stderr.write("Error reading dielectric maps!\n")
00286         raise APBSError, "Error reading dielectric maps!"
00287     
00288     kappaMap = new_gridlist(NOSH_MAXMOL)
00289     if loadKappaMaps(nosh, kappaMap) != 1:
00290         stderr.write("Error reading kappa maps!\n")
00291         raise APBSError, "Error reading kappa maps!"
00292     
00293     # Turn off charges
00294 
00295     for iatom in range(numAtoms):
00296         Vatom_setCharge(Valist_getAtom(get_Valist(alist, 0), iatom),0.0)
00297 
00298     stdout.write("-----------------------------\n")
00299     for iatom in range(numAtoms):
00300 
00301         # Turn on/off charge sequentially
00302 
00303         if iatom == 0:
00304             refCharge = reflist[iatom]
00305             Vatom_setCharge(Valist_getAtom(get_Valist(alist, 0), iatom),refCharge)
00306         else:
00307             refCharge = reflist[iatom]
00308             Vatom_setCharge(Valist_getAtom(get_Valist(alist, 0), iatom),refCharge)
00309             Vatom_setCharge(Valist_getAtom(get_Valist(alist, 0), iatom-1),0.0)
00310         
00311         # Load other necessary maps
00312     
00313         chargeMap = new_gridlist(NOSH_MAXMOL)
00314         if loadChargeMaps(nosh, chargeMap) != 1:
00315             stderr.write("Error reading charge maps!\n")
00316             raise APBSError, "Error reading charge maps!"
00317 
00318         # Do the calculations
00319            stdout.write("Parameterizaing atom %d with %d PBE calculations\n" % ((iatom+1), nosh.ncalc))
00320         percentage = iatom*100*numAtoms**-1
00321         stdout.write("Roughly %f%% complete\n" % percentage)
00322 
00323         energylist = [0.0 for i in range(nosh.ncalc)]
00324         energymatrix = []
00325         
00326         for icalc in xrange(nosh.ncalc):
00327             stdout.write("Details of calculation %d:\n" % (icalc+1))
00328             calc = NOsh_getCalc(nosh, icalc)
00329             mgparm = calc.mgparm
00330             pbeparm = calc.pbeparm
00331 
00332             if ((sdie == 0) & (pbeparm.sdie != 1)):
00333                 sdie = pbeparm.sdie
00334             
00335             if calc.calctype != 0:
00336                 stderr.write("main:  Only multigrid calculations supported!\n")
00337                 raise APBSError, "Only multigrid calculations supported!"
00338             
00339             # Routine initMG
00340            
00341             if initMG(icalc, nosh, mgparm, pbeparm, realCenter, pbe, 
00342                       alist, dielXMap, dielYMap, dielZMap, kappaMap, chargeMap, 
00343                       pmgp, pmg) != 1:
00344                 stderr.write("Error setting up MG calculation!\n")
00345                 raise APBSError, "Error setting up MG calculation!"
00346       
00347             # Solve the problem : Routine solveMG
00348            
00349             thispmg = get_Vpmg(pmg,icalc)
00350 
00351             if solveMG(nosh, thispmg, mgparm.type) != 1:
00352                 stderr.write("Error solving PDE! \n")
00353                 raise APBSError, "Error Solving PDE!"
00354 
00355             # Set partition information : Routine setPartMG
00356 
00357             if setPartMG(nosh, mgparm, thispmg) != 1:
00358                 stderr.write("Error setting partition info!\n")
00359                 raise APBSError, "Error setting partition info!"
00360             
00361             # Get the energies - the energy for this calculation
00362             # (calculation number icalc) will be stored in the totEnergy array
00363             
00364             ret, totEnergy[icalc] = energyMG(nosh, icalc, thispmg, 0,
00365                                              totEnergy[icalc], 0.0, 0.0, 0.0)
00366 
00367             energies = getEnergies(thispmg, get_Valist(alist, 0))
00368             energylist[icalc] = 0.5*energies[iatom] # remove self interaction
00369 
00370             stdout.write("\n")
00371             
00372         for iprint in range(nosh.nprint):
00373             selfEnergy.append(returnEnergy(com, nosh, energylist, iprint))
00374             
00375         stdout.write("Self energy value: %.6E kJ/mol for atom %d\n" % (selfEnergy[-1], (iatom+1)))
00376         stdout.write("-----------------------------\n")
00377         # Clean up APBS structures for next iteration
00378         
00379         killEnergy()
00380         killMG(nosh, pbe, pmgp, pmg)
00381         killChargeMaps(nosh, chargeMap)
00382 
00383     # Clean up dielectirc map after parameterization
00384     
00385     killKappaMaps(nosh, kappaMap)
00386     killDielMaps(nosh, dielXMap, dielYMap, dielZMap)
00387 
00388     # SI unit conversion
00389     
00390     for i in xrange(numAtoms):
00391         reflist[i]=reflist[i]*Python_C
00392     
00393     # Obtain Born radii from self energies
00394     
00395     bradlist = []
00396     dij2 = [[0.0 for i in range(numAtoms)] for j in range(numAtoms)]
00397     fGB = [[0.0 for i in range(numAtoms)] for j in range(numAtoms)]
00398     for i in xrange(numAtoms):
00399         brad = -pow(reflist[i],2)*(1-1/sdie)*0.5*Python_Na/(4.0*pi*Python_e0*selfEnergy[i]*1e3)
00400         bradlist.append(brad)
00401 
00402     FILE = open(output_param, "w")
00403     FILE.write(str(sdie)+"\n")
00404     FILE.write("radii\tenergy\n")
00405     parameters = zip(bradlist, selfEnergy)
00406     for i in parameters:
00407         print >> FILE, "\t".join(map(str,i))
00408     FILE.close()
00409     stdout.write("GB parameters ouput in %s\n" % output_param)
00410     stdout.write("(1st column, Born radii; 2nd column, self energy)\n")
00411 
00412     for i in xrange(numAtoms):
00413         for j in xrange(i+1):
00414             
00415             for coord in xrange(3):
00416                 dij2[i][j] = dij2[i][j] + pow((position[i][coord]-position[j][coord])*1e-10,2)
00417 
00418             d = dij2[i][j]
00419             bradi = bradlist[i]
00420             bradj = bradlist[j]
00421             fGB[i][j] = sqrt(d+bradi*bradj*exp(-d/(4.0*bradi*bradj)))
00422     
00423     # Calculate energy
00424     
00425     Gpol = 0.0
00426     for i in xrange(numAtoms):
00427         for j in xrange(numAtoms):
00428             if j <= i:
00429                 Gpol = Gpol + reflist[i]*reflist[j]/fGB[i][j]
00430             else:
00431                 Gpol = Gpol + reflist[i]*reflist[j]/fGB[j][i]
00432     
00433     Gpol = -Gpol*(1-1/sdie)*0.5*1e-3*Python_Na/(4.0*pi*Python_e0)
00434     
00435     # Print result
00436     
00437     stdout.write("\nGB Energy: %.10E kJ/mol\n" % Gpol)
00438 
00439     # Record data
00440     
00441     if output_matrix != "":
00442         FILE = open(output_matrix, "w")
00443         term = 0.0
00444         for i in range(numAtoms):
00445             for j in range(numAtoms):
00446                 if j<=i:
00447                     term = reflist[i]*reflist[j]/fGB[i][j]
00448                     term = -term*(1-1/sdie)*0.5*1e-3*Python_Na/(4*pi*Python_e0)
00449                     FILE.write(str(term)+"\t")
00450                 else:
00451                     term = reflist[i]*reflist[j]/fGB[j][i]
00452                     term = -term*(1-1/sdie)*0.5*1e-3*Python_Na/(4*pi*Python_e0)
00453                     FILE.write(str(term)+"\t")
00454             FILE.write("\n")
00455         FILE.close()
00456         stdout.write("Energy matrix ouput in %s\n" % output_matrix)
00457 
00458     # Clean up for program exit
00459     
00460     killMolecules(nosh, alist)
00461     
00462     delete_Nosh(nosh)
00463         
00464     # Clean up Python structures
00465         
00466     delete_double_array(realCenter)
00467     delete_int_array(nforce)
00468     delete_atomforcelist(atomforce)
00469     delete_valist(alist)
00470     delete_gridlist(dielXMap)
00471     delete_gridlist(dielYMap)
00472     delete_gridlist(dielZMap)
00473     delete_gridlist(kappaMap)
00474     delete_gridlist(chargeMap)
00475     delete_pmglist(pmg)
00476     delete_pmgplist(pmgp)
00477     delete_pbelist(pbe)
00478     
00479     
00480     # Clean up MALOC structures
00481     delete_Com(com)
00482     delete_Mem(mem)
00483     stdout.write("\n")
00484     stdout.write("Thanks for using APBS!\n\n")
00485 
00486     # Stop the main timer
00487     main_timer_stop = time.clock()
00488     stdout.write("Total execution time:  %1.6e sec\n" % (main_timer_stop - main_timer_start))
00489 
00490  
00491 if __name__ == "__main__": main()

Generated on Wed Oct 20 2010 11:12:21 for APBS by  doxygen 1.7.2