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

tools/manip/inputgen.py

00001 """ inputgen class
00002 
00003     Create an APBS input file using psize data
00004 
00005     Written by Todd Dolinsky based on original sed script by Nathan Baker
00006 
00007         ----------------------------
00008 
00009     Version:  $Id: inputgen.py 1552 2010-02-10 17:46:27Z yhuang01 $
00010    
00011            APBS -- Adaptive Poisson-Boltzmann Solver
00012 
00013              Nathan A. Baker (baker@biochem.wustl.edu)
00014              Dept. Biochemistry and Molecular Biophysics
00015              Center for Computational Biology
00016              Washington University in St. Louis
00017 
00018              Additional contributing authors listed in the code documentation.
00019 
00020            Copyright (c) 2002-2010, Washington University in St. Louis.
00021            Portions Copyright (c) 2002-2010.  Nathan A. Baker
00022            Portions Copyright (c) 1999-2002.  The Regents of the University of California.
00023            Portions Copyright (c) 1995.  Michael Holst
00024 
00025            All rights reserved.
00026 
00027            Redistribution and use in source and binary forms, with or without
00028            modification, are permitted provided that the following conditions are met: 
00029 
00030            * Redistributions of source code must retain the above copyright notice, this
00031            list of conditions and the following disclaimer.  
00032 
00033            * Redistributions in binary form must reproduce the above copyright notice,
00034            this list of conditions and the following disclaimer in the documentation
00035            and/or other materials provided with the distribution.
00036 
00037            * Neither the name of Washington University in St. Louis nor the names of its
00038            contributors may be used to endorse or promote products derived from this
00039            software without specific prior written permission.
00040 
00041            THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00042            "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00043            LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00044            A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00045            CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00046            EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00047            PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00048            PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00049            LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00050            NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00051            SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00052 
00053 
00054     ----------------------------
00055 """
00056 
00057 # User - Definable Variables: Default values
00058 
00059 # cfac = 1.7                  # Factor by which to expand mol dims to
00060                               # get coarse grid dims
00061 # fadd = 20                   # Amount to add to mol dims to get fine
00062                               # grid dims
00063 # space = 0.50                # Desired fine mesh resolution
00064 # gmemfac = 200               # Number of bytes per grid point required 
00065                               # for sequential MG calculation 
00066 # gmemceil = 400              # Max MB allowed for sequential MG
00067                               # calculation.  Adjust this to force the
00068                               # script to perform faster calculations (which
00069                               # require more parallelism).
00070 # ofrac = 0.1                  # Overlap factor between mesh partitions
00071 # redfac = 0.25               # The maximum factor by which a domain
00072                               # dimension can be reduced during focusing
00073 
00074 import string, sys
00075 import psize
00076 import pickle
00077 
00078 class Elec:
00079     """
00080         An object for the ELEC section of an APBS input file
00081     """
00082     def __init__(self, pqrpath, size, method, asyncflag, istrng=0, potdx=0):
00083         """
00084             Initialize the variables that can be set in this object
00085             Users can modify any of these variables (that's why
00086             they're here!)
00087         """
00088 
00089         # If this is an async or parallel calc, we want to use
00090         # the per-grid dime rather than the global dime.
00091         
00092         self.dime = size.getFineGridPoints()
00093         gmem = 200.0 * self.dime[0] * self.dime[1] * self.dime[2] / 1024.0 / 1024.0
00094         if method == "": # method not named - use ceiling
00095             if gmem > size.getConstant("gmemceil"): method = "mg-para"
00096             else: method = "mg-auto"
00097 
00098         if method == "mg-para":
00099             self.dime = size.getSmallest()
00100 
00101         self.method = method
00102         self.istrng = istrng
00103         self.glen = size.getCoarseGridDims()
00104         self.cglen = size.getCoarseGridDims()
00105         self.fglen = size.getFineGridDims()
00106         self.pdime = size.getProcGrid()
00107         
00108         self.label = ""
00109         self.nlev = 4
00110         self.ofrac = 0.1
00111         self.async = 0
00112         self.asyncflag = asyncflag
00113         self.cgcent = "mol 1"
00114         self.fgcent = "mol 1"
00115         self.gcent = "mol 1"
00116         self.mol = 1
00117         self.lpbe = 1
00118         self.npbe = 0
00119         self.bcfl = "sdh"
00120         self.ion = [[-1,1.815],[1,1.875]] # Multiple ions possible
00121         self.pdie = 2.0
00122         self.sdie = 78.54
00123         self.srfm = "smol"
00124         self.chgm = "spl2"
00125         self.sdens = 10.0
00126         self.srad = 1.4
00127         self.swin = 0.3
00128         self.temp = 298.15
00129         self.gamma = 0.105
00130         self.calcenergy = "total"
00131         self.calcforce = "no"
00132         if potdx == 1:
00133             self.write = [["pot", "dx", pqrpath]]
00134         else:
00135             self.write = [["pot", "dx", "pot"]] # Multiple write statements possible
00136     
00137     def __str__(self):
00138         """
00139             Return the elec statement as a string. Check the method
00140             to see which keywords to use.
00141         """
00142         text = "elec %s\n" % self.label
00143         text += "    %s\n" % self.method
00144         text += "    dime %i %i %i\n" % (self.dime[0], self.dime[1], self.dime[2])
00145         if self.method == "mg-manual":
00146             text += "    nlev %i\n" % self.nlev
00147             text += "    glen %.3f %.3f %.3f\n" % (self.glen[0], self.glen[1], self.glen[2])
00148             text += "    gcent %s\n" % self.gcent
00149         elif self.method == "mg-auto":
00150             text += "    cglen %.4f %.4f %.4f\n" % (self.cglen[0], self.cglen[1], self.cglen[2])
00151             text += "    fglen %.4f %.4f %.4f\n" % (self.fglen[0], self.fglen[1], self.fglen[2])
00152             text += "    cgcent %s\n" % self.cgcent
00153             text += "    fgcent %s\n" % self.fgcent
00154         elif self.method == "mg-para":
00155             text += "    pdime %i %i %i\n" % (self.pdime[0], self.pdime[1], self.pdime[2])
00156             text += "    ofrac %.1f\n" % self.ofrac
00157             text += "    cglen %.4f %.4f %.4f\n" % (self.cglen[0], self.cglen[1], self.cglen[2])
00158             text += "    fglen %.4f %.4f %.4f\n" % (self.fglen[0], self.fglen[1], self.fglen[2])
00159             text += "    cgcent %s\n" % self.cgcent
00160             text += "    fgcent %s\n" % self.fgcent
00161             if self.asyncflag == 1:
00162                 text += "    async %i\n" % self.async
00163         text += "    mol %i\n" % self.mol
00164         if self.lpbe: text += "    lpbe\n"
00165         else: text += "    npbe\n"
00166         text += "    bcfl %s\n" % self.bcfl
00167         if self.istrng > 0:
00168             for ion in self.ion:
00169                 text += "    ion charge %.2f conc %.3f radius %.4f\n" % (ion[0], self.istrng, ion[1])               
00170         text += "    pdie %.4f\n" % self.pdie                
00171         text += "    sdie %.4f\n" % self.sdie                
00172         text += "    srfm %s\n" % self.srfm                   
00173         text += "    chgm %s\n" % self.chgm
00174         text += "    sdens %.2f\n" % self.sdens
00175         text += "    srad %.2f\n" % self.srad          
00176         text += "    swin %.2f\n" % self.swin         
00177         text += "    temp %.2f\n" % self.temp     
00178         text += "    calcenergy %s\n" % self.calcenergy
00179         text += "    calcforce %s\n" % self.calcforce
00180         for write in self.write:
00181             text += "    write %s %s %s\n" % (write[0], write[1], write[2])
00182         text += "end\n"
00183         return text
00184         
00185 class Input:
00186     """
00187         The input class.  Each input object is one APBS input file.
00188     """
00189 
00190     def __init__(self, pqrpath, size, method, asyncflag, istrng=0, potdx=0):
00191         """
00192             Initialize the input file class.  Each input file contains
00193             a PQR name, a list of elec objects, and a list of strings
00194             containing print statements.  For starters assume two
00195             ELEC statements are needed, one for the inhomgenous and
00196             the other for the homogenous dielectric calculations.
00197 
00198             Users can edit the elec statements and the print statements.
00199 
00200             This assumes you have already run psize, either by
00201                  size.runPsize(/path/to/pqr) or
00202 
00203                  size.parseString(string)
00204                  size.setAll()
00205 
00206             Parameters
00207                 pqrpath:   The path to the PQR file (string)
00208                 size:      The Psize object (psize)
00209                 method:    The method (para, auto, manual, async) to use
00210                 asyncflag: 1 if async is desired, 0 otherwise
00211         """ 
00212 
00213         self.pqrpath = pqrpath
00214         self.asyncflag = asyncflag
00215 
00216         # Initialize variables to default elec values
00217 
00218         elec1 = Elec(pqrpath, size, method, asyncflag, istrng, potdx)
00219         if potdx == 0:
00220             elec2 = Elec(pqrpath, size, method, asyncflag, istrng, potdx)
00221             setattr(elec2, "sdie", 2.0)
00222             setattr(elec2, "write", [])
00223         else:
00224             elec2 = ""
00225         self.elecs = [elec1, elec2]
00226      
00227         i = string.rfind(pqrpath, "/") + 1
00228         self.pqrname = pqrpath[i:]
00229 
00230         if potdx == 0:
00231             self.prints = ["print elecEnergy 2 - 1 end"]     
00232         else:
00233             self.prints = []
00234 
00235     def __str__(self):
00236         """
00237             Return the text of the input file
00238         """
00239         text  = "read\n"
00240         text += "    mol pqr %s\n" % self.pqrname
00241         text += "end\n"
00242         for elec in self.elecs:
00243             text += str(elec)            
00244         for prints in self.prints:
00245             text += prints
00246         text += "\nquit\n"
00247         return text
00248   
00249     def printInputFiles(self):
00250         """
00251             Make the input file(s) associated with this object
00252         """
00253         period = string.find(self.pqrpath,".")
00254         if self.asyncflag == 1:
00255             outname = self.pqrpath[0:period] + "-para.in"
00256 
00257             # Temporarily disable async flag
00258             for elec in self.elecs:
00259                 elec.asyncflag = 0
00260             file = open(outname, "w")
00261             file.write(str(self))
00262             file.close()
00263 
00264             # Now make the async files
00265             elec = self.elecs[0]
00266             
00267             nproc = elec.pdime[0] * elec.pdime[1] * elec.pdime[2]
00268             for i in range(int(nproc)):
00269                 outname = self.pqrpath[0:period] + "-PE%i.in" % i
00270                 for elec in self.elecs:
00271                     elec.asyncflag = 1
00272                     elec.async = i
00273                 file = open(outname, "w")
00274                 file.write(str(self))
00275                 file.close()
00276         
00277         else:
00278             if period > 0:
00279                 outname = self.pqrpath[0:period] + ".in"
00280             else:
00281                 outname = self.pqrpath + ".in"
00282             file = open(outname, "w")
00283             file.write(str(self))
00284             file.close()
00285 
00286     def dumpPickle(self):
00287         """
00288             Make a Python pickle associated with the APBS input parameters
00289         """
00290         period = string.find(self.pqrpath,".")
00291         if period > 0:
00292             outname = self.pqrpath[0:period] + "-input.p"
00293         else:
00294             outname = self.pqrpath + "-input.p"
00295         pfile = open(outname, "w")
00296         pickle.dump(self, pfile)
00297         pfile.close()
00298 
00299 def splitInput(filename):
00300     """
00301         Split the parallel input file into multiple async file names
00302 
00303         Parameters
00304             filename:  The path to the original parallel input
00305                        file (string)
00306     """
00307     nproc = 0
00308     file = open(filename, 'rU')
00309     text = ""
00310     while 1:
00311         line = file.readline()
00312         if line == "": break
00313         text += line
00314         line = string.strip(line)
00315         if line.startswith("pdime"): # Get # Procs
00316             words = string.split(line)
00317             nproc = int(words[1]) * int(words[2]) * int(words[3])
00318 
00319     if nproc == 0:
00320         sys.stderr.write("%s is not a valid APBS parallel input file!\n" % filename)
00321         sys.stderr.write("The inputgen script was unable to asynchronize this file!\n")
00322         sys.exit(2)
00323 
00324     period = string.find(filename,".")
00325     for i in range(nproc):
00326         outname = filename[0:period] + "-PE%i.in" % i
00327         outtext = string.replace(text, "mg-para\n","mg-para\n    async %i\n" % i)
00328         outfile = open(outname, "w")
00329         outfile.write(outtext)
00330         outfile.close()
00331           
00332 def usage():
00333     """
00334         Display the usage information for this script
00335     """
00336     size = psize.Psize()
00337     usage = "\n"
00338     usage = usage + "Use this script to generate new APBS input files or split an existing\n"
00339     usage = usage + "parallel input file into multiple async files.\n\n"
00340     usage = usage + "Usage: inputgen.py [opts] <filename>\n"
00341     usage = usage + "Optional Arguments:\n"
00342     usage = usage + "  --help               : Display this text\n"
00343     usage = usage + "  --split              : Split an existing parallel input file to multiple\n"
00344     usage = usage + "                         async input files.\n"
00345     usage = usage + "  --potdx              : Create an input to compute an electrostatic potential map.\n"
00346     usage = usage + "  --method=<value>     : Force output file to write a specific APBS ELEC\n"
00347     usage = usage + "                         method.  Options are para (parallel), auto\n"
00348     usage = usage + "                         (automatic), manual (manual), or async (asynchronous).\n"
00349     usage = usage + "                         solve.  async will result in multiple input files.\n"
00350     usage = usage + "  --cfac=<value>       : Factor by which to expand molecular dimensions to\n"
00351     usage = usage + "                         get coarse grid dimensions.\n"
00352     usage = usage + "                         [default = %g]\n" % size.getConstant("cfac")
00353     usage = usage + "  --fadd=<value>       : Amount to add to molecular dimensions to get fine\n"
00354     usage = usage + "                         grid dimensions.\n"
00355     usage = usage + "                         [default = %g]\n" % size.getConstant("fadd")
00356     usage = usage + "  --space=<value>      : Desired fine mesh resolution\n"
00357     usage = usage + "                         [default = %g]\n" % size.getConstant("space")
00358     usage = usage + "  --gmemfac=<value>    : Number of bytes per grid point required\n"
00359     usage = usage + "                         for sequential MG calculation\n"
00360     usage = usage + "                         [default = %g]\n" % size.getConstant("gmemfac")
00361     usage = usage + "  --gmemceil=<value>   : Max MB allowed for sequential MG\n"
00362     usage = usage + "                         calculation.  Adjust this to force the\n"
00363     usage = usage + "                         script to perform faster calculations (which\n"
00364     usage = usage + "                         require more parallelism).\n"
00365     usage = usage + "                         [default = %g]\n" % size.getConstant("gmemceil")
00366     usage = usage + "  --ofrac=<value>      : Overlap factor between mesh partitions\n"
00367     usage = usage + "                         [default = %g]\n" % size.getConstant("ofrac")
00368     usage = usage + "  --redfac=<value>     : The maximum factor by which a domain\n"
00369     usage = usage + "                         dimension can be reduced during focusing\n"
00370     usage = usage + "                         [default = %g]\n" % size.getConstant("redfac")
00371     usage = usage + "  --istrng=<value>     : Ionic strength (M). Na+ anc Cl- ions will be used\n"
00372     sys.stderr.write(usage)
00373     sys.exit(2)
00374 
00375 def main():
00376 
00377     import getopt
00378     filename = ""
00379     shortOptList = ""
00380     longOptList = ["help","split","potdx","method=","cfac=","space=","gmemceil=","gmemfac=","ofrac=","redfac=","istrng="]
00381 
00382     try:
00383         opts, args = getopt.getopt(sys.argv[1:], shortOptList, longOptList)
00384     except getopt.GetoptError, details:
00385         sys.stderr.write("Option error (%s)!\n" % details)
00386         usage()
00387         
00388     if len(args) != 1:
00389         sys.stderr.write("Invalid argument list!\n")
00390         usage()
00391     else:
00392         filename = args[0]
00393 
00394     method = ""
00395     size = psize.Psize()
00396     async = 0
00397     split = 0
00398     istrng = 0
00399     potdx = 0
00400     
00401     for o, a in opts:
00402         if o == "--help":
00403             usage()
00404         if o == "--split": split = 1
00405         if o == "--potdx": potdx = 1
00406         if o == "--method":
00407             if a == "para":
00408                 sys.stdout.write("Forcing a parallel calculation\n")
00409                 method = "mg-para"
00410             elif a == "auto":
00411                 sys.stdout.write("Forcing a sequential calculation\n")
00412                 method = "mg-auto"
00413             elif a == "async":
00414                 sys.stdout.write("Forcing an asynchronous calculation\n")
00415                 method = "mg-para"
00416                 async = 1
00417             elif a == "manual":
00418                 sys.stdout.write("Forcing a manual calculation\n")
00419                 method = "mg-manual"
00420             else:
00421                 sys.stdout.write("Incorrect method argument: %s\n" % a)
00422                 sys.stdout.write("Defaulting to memory dependent result\n")
00423         if o == "--cfac":
00424             size.setConstant("cfac", float(a))
00425         if o == "--space":
00426             size.setConstant("space", float(a))
00427         if o == "--gmemfac":
00428             size.setConstant("gmemfac", int(a))
00429         if o == "--gmemceil":
00430             size.setConstant("gmemceil",  int(a))
00431         if o == "--ofrac":
00432             size.setConstant("ofrac", float(a))
00433         if o == "--redfac":
00434             size.setConstant("redfac", float(a))
00435         if o == "--istrng":
00436             istrng = float(a)
00437 
00438     if split == 1:
00439         splitInput(filename)
00440     else:
00441         size.runPsize(filename)
00442         input = Input(filename, size, method, async, istrng, potdx)
00443         input.printInputFiles()
00444 
00445 if __name__ == "__main__": main()

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