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

tools/python/readGB.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 import sys, time, getopt
00056 import string
00057 import math
00058 from sys import stdout, stderr
00059 from math import sqrt, pow, exp, pi
00060 
00061 __author__ = "Todd Dolinsky, Nathan Baker"
00062 __date__ = "July 2007"
00063 
00064 Python_kb = 1.3806581e-23
00065 Python_Na = 6.0221367e+23
00066 Python_e0 = 8.85419e-12
00067 Python_C = 1.602117e-19
00068 NOSH_MAXMOL = 20
00069 NOSH_MAXCALC = 20
00070 
00071 class APBSError(Exception):
00072     """ APBSError class
00073 
00074         The APBSError class inherits off the Exception module and returns
00075         a string defining the nature of the error. 
00076     """
00077     
00078     def __init__(self, value):
00079         """
00080             Initialize with error message
00081 
00082             Parameters
00083                 value:  Error Message (string)
00084         """
00085         self.value = value
00086         
00087     def __str__(self):
00088         """
00089             Return the error message
00090         """
00091         return `self.value`
00092 
00093 def getHeader():
00094     """ Get header information about APBS
00095         Returns (header)
00096             header: Information about APBS
00097     """
00098 
00099     header = "\n\n\
00100     ----------------------------------------------------------------------\n\
00101     Adaptive Poisson-Boltzmann Solver (APBS)\n\
00102     Version 1.3\n\
00103     \n\
00104     APBS -- Adaptive Poisson-Boltzmann Solver\n\
00105     \n\
00106     Nathan A. Baker (baker@biochem.wustl.edu)\n\
00107     Dept. Biochemistry and Molecular Biophysics\n\
00108     Center for Computational Biology\n\
00109     Washington University in St. Louis\n\
00110     \n\
00111     Additional contributing authors listed in the code documentation.\n\
00112     \n\
00113     Copyright (c) 2002-2010, Washington University in St. Louis.\n\
00114     Portions Copyright (c) 2002-2010.  Nathan A. Baker\n\
00115     Portions Copyright (c) 1999-2002.  The Regents of the University of California.\n\
00116     Portions Copyright (c) 1995.  Michael Holst\n\
00117     \n\
00118     All rights reserved.\n\
00119     \n\
00120     Redistribution and use in source and binary forms, with or without\n\
00121     modification, are permitted provided that the following conditions are met:\n\
00122     \n\
00123     * Redistributions of source code must retain the above copyright notice, this\n\
00124       list of conditions and the following disclaimer.\n\
00125     \n\
00126     * Redistributions in binary form must reproduce the above copyright notice,\n\
00127       this list of conditions and the following disclaimer in the documentation\n\
00128       and/or other materials provided with the distribution.\n\
00129     \n\
00130     * Neither the name of Washington University in St. Louis nor the names of its\n\
00131       contributors may be used to endorse or promote products derived from this\n\
00132       software without specific prior written permission.\n\
00133     \n\
00134     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\
00135     \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n\
00136     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n\
00137     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n\
00138     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n\
00139     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n\
00140     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n\
00141     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n\
00142     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n\
00143     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n\
00144     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\
00145     ----------------------------------------------------------------------\n\
00146     \n\n"
00147 
00148     return header
00149 
00150 def getUsage():
00151     """ Get usage information about running APBS via Python
00152         Returns (usage)
00153             usage: Text about running APBS via Python
00154     """
00155     
00156     usage = "\n\n\
00157     ----------------------------------------------------------------------\n\
00158     This driver program calculates electrostatic solvation energy from the\n\
00159     Generalized Born model based on a provided parameter file.\n\
00160     It is invoked as:\n\n\
00161       python readGB.py -p parameter_file -i structure.pqr\n\n\
00162     The parameter_file can be generated using runGB modules. It should\n\
00163     contain either, or both of the column fields: Effective Born radii and\n\
00164     self energy. The first line of the parameter_file should indicate the\n\
00165     value of solvent dielectric. The second line specifies what the column\n\
00166     fields are, by flagging 'radii' and/or 'energy'.\n\n\
00167     Optional arguments:\n\
00168       -o <output_parameter>     specifies path to output GB parameter file\n\
00169       -m <output_matrix>        specifies path to output GB energy matrix\n\
00170       -h or --help              prints this help text\n\
00171     ----------------------------------------------------------------------\n\n"
00172 
00173     return usage
00174 
00175 def main():
00176 
00177     main_timer_start = time.clock()
00178     
00179     sdie = 0.0
00180 
00181     # Method: 1 = from energy; 0 = from radii
00182     method = 0
00183     column = -1
00184     
00185     # Check invocation
00186     stdout.write(getHeader())
00187     try:
00188         opts, args = getopt.getopt(sys.argv[1:], "hp:i:o:m:", ["help"])
00189     except getopt.GetoptError:
00190         stdout.write("problem with input format\n")
00191         stdout.write(getUsage())
00192         sys.exit("Incorrect usage!\n")
00193         
00194     output_param = ""
00195     output_matrix = ""
00196     for o, a in opts:
00197         if o in ("-h", "--help"):
00198             stdout.write("Printing help text...\n")
00199             stdout.write(getUsage())
00200             sys.exit()
00201         if o == "-p":
00202             if a == "":
00203                 stdout.write("parameter file not specified\n")
00204                 stdout.write(getUsage())
00205                 sys.exit("Incorrect usage!\n")
00206             else:
00207                 param_file = a
00208         if o == "-i":
00209             if a == "":
00210                 stdout.write("input pqr file not specified\n")
00211                 stdout.write(getUsage())
00212                 sys.exit("Incorrect usage!\n")
00213             else:
00214                 pqr_file = a
00215         if o == "-o":
00216             output_param = a
00217         if o == "-m":
00218             output_matrix = a
00219 
00220     # Parse the input file
00221     try: param_file
00222     except:
00223         stdout.write("parameter file not initiated - check input\n")
00224         stdout.write(getUsage())
00225         sys.exit("Incorrect usage!\n")
00226     try: pqr_file
00227     except:
00228         stdout.write("input pqr file not initiated - check input\n")
00229         stdout.write(getUsage())
00230         sys.exit("Incorrect usage!\n")
00231     
00232     stdout.write("Parsing parameter file %s...\n" % param_file)
00233     energylist = []
00234     bradlist = []
00235     try: f = open(param_file, 'r')
00236     except IOError:
00237         stdout.write("cannot open parameter file specified\n")
00238         sys.exit("IOError!\n")
00239     index = 0
00240     for line in f:
00241         term = line.split()
00242         if index == 0:
00243             if term[0].isdigit:
00244                 sdie = float(term[0])
00245             else:
00246                 stderr.write("main: Parameter format error; First line should be sdie only")
00247                 raise APBSError, "Incorrect format!"
00248         elif index == 1:
00249             if len(term) == 1:
00250                 if term[0] == "energy":
00251                     method = 1
00252             elif len(term) == 2:
00253                 if term[0] == "radii":
00254                     column = 0
00255                 else:
00256                     column = 1
00257             else:
00258                 stderr.write("main: Parameter format error; Second line should be field flags")
00259                 raise APBSError, "Incorrect format!"
00260         else:
00261             if method == 1:
00262                 if term[column].isdigit:
00263                     energylist.append(float(term[column]))
00264             else:
00265                 if term[column].isdigit:
00266                     bradlist.append(float(term[column]))
00267         index = index + 1
00268     f.close()
00269     
00270     if method:
00271         numAtoms = len(energylist)
00272         stdout.write("Parsed energy for %d atoms.\n" % numAtoms)        
00273     else:
00274         numAtoms = len(bradlist)
00275         stdout.write("Parsed Born radii for %d atoms.\n" % numAtoms)
00276     
00277     stdout.write("Parsing PQR file %s...\n" % pqr_file)
00278     position = [[0.0 for i in range(3)] for j in range(numAtoms)]
00279     x = []
00280     y = []
00281     z = []
00282     chargelist = []
00283     try: f = open(pqr_file, 'r+')
00284     except IOError:
00285         stdout.write("cannot open input pqr file specified\n")
00286         sys.exit("IOError!\n")
00287     iatom = 0
00288     for line in f:
00289         param = line.split()
00290         if param[0] != "ATOM":
00291             continue
00292         if len(param) == 10:
00293             x.append(float(param[5]))
00294             y.append(float(param[6]))
00295             z.append(float(param[7]))
00296             chargelist.append(float(param[8])*Python_C)
00297             iatom=iatom+1
00298     f.close()
00299     if len(chargelist) != numAtoms:
00300         stderr.write("main: Number of atoms in energy list (%d) doest not match PQR list (%d)\n" %
00301                      (len(chargelist),numAtoms))
00302         raise APBSError, "Non-matching energy list and PQR file"
00303     for iatom in range(numAtoms):
00304         position[iatom][0]=x[iatom]
00305         position[iatom][1]=y[iatom]
00306         position[iatom][2]=z[iatom]
00307 
00308     stdout.write("Input files parsed...\n")
00309     
00310     # Obtain Born radii from self energies
00311     stdout.write("Starting energy calculations...\n")
00312     dij2 = [[0.0 for i in range(numAtoms)] for j in range(numAtoms)]
00313     fGB = [[0.0 for i in range(numAtoms)] for j in range(numAtoms)]
00314     if method:
00315         for i in xrange(numAtoms):
00316             brad = -pow(chargelist[i],2)*(1-1/sdie)*0.5*Python_Na/(4*pi*Python_e0*energylist[i]*1e3)
00317             bradlist.append(brad)
00318 
00319     if output_param != "":
00320         stdout.write("writing parameter file to %s\n" % output_param)
00321         FILE = open(output_param, "w")
00322         FILE.write(str(sdie)+"\n")
00323         if method:
00324             FILE.write("radii\tenergy\n")
00325             parameters = zip(bradlist, energylist)
00326             for i in parameters:
00327                 print >> FILE, "\t".join(map(str,i))
00328         else:
00329             FILE.write("radii\n")
00330             for i in bradlist:
00331                 FILE.write(str(i)+"\n")
00332         FILE.close()
00333     
00334     for i in xrange(numAtoms):
00335         for j in xrange(i+1):
00336             
00337             for coord in xrange(3):
00338                 dij2[i][j] = dij2[i][j] + pow((position[i][coord]-position[j][coord])*1e-10,2)
00339 
00340             d = dij2[i][j]
00341             bradi = bradlist[i]
00342             bradj = bradlist[j]
00343             if j==i:
00344                 fGB[i][j]=bradlist[i]
00345             else:
00346                 fGB[i][j] = sqrt(d+bradi*bradj*exp(-d/(4.0*bradi*bradj)))
00347     
00348     # Calculate energy
00349 
00350     Gpol = 0.0
00351     for i in xrange(numAtoms):
00352         for j in xrange(numAtoms):
00353             if j < i:
00354                 Gpol = Gpol + chargelist[i]*chargelist[j]/fGB[i][j]
00355             elif j > i:
00356                 Gpol = Gpol + chargelist[i]*chargelist[j]/fGB[j][i]
00357 
00358     for i in xrange(numAtoms):
00359         Gpol = Gpol + pow(chargelist[i],2)/bradlist[i]
00360     
00361     Gpol = -Gpol*(1-1/sdie)*0.5*1e-3*Python_Na/(4*pi*Python_e0)
00362     
00363     # Print result
00364     stdout.write("\nGB Energy: %.10E kJ/mol\n" % Gpol)
00365 
00366     # Record data
00367     if output_matrix != "":
00368         FILE = open(filename, 'w')
00369         term = 0.0
00370         for i in range(numAtoms):
00371             for j in range(numAtoms):
00372                 if j<=i:
00373                     term = chargelist[i]*chargelist[j]/fGB[i][j]
00374                     term = -term*(1-1/sdie)*0.5*1e-3*Python_Na/(4*pi*Python_e0)
00375                     FILE.write(str(term)+"\t")
00376                 else:
00377                     term = chargelist[i]*chargelist[j]/fGB[j][i]
00378                     term = -term*(1-1/sdie)*0.5*1e-3*Python_Na/(4*pi*Python_e0)
00379                     FILE.write(str(term)+"\t")
00380             FILE.write("\n")
00381         FILE.close()
00382         stdout.write("Energy matrix output in %s\n" % filename)
00383 
00384     stdout.write("\n")
00385     stdout.write("Thanks for using APBS!\n\n")
00386 
00387     # Stop the main timer
00388     main_timer_stop = time.clock()
00389     stdout.write("Total execution time:  %1.6e sec\n" % (main_timer_stop - main_timer_start))
00390 
00391  
00392 if __name__ == "__main__": main()

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