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

tools/python/vgrid/mergedx.py

00001 #!/usr/bin/python2 -O
00002 
00003 """
00004     mergedx.py - Python script for merging dx files
00005 
00006     Written by Todd Dolinsky (todd@ccb.wustl.edu)
00007     Washington University in St. Louis
00008 """
00009 
00010 __date__ = "January 2005"
00011 __author__ = "Todd Dolinsky"
00012 
00013 VSMALL = 1.0e-9
00014 OUT = "mergedgrid.dx"
00015 HEADER = "\n\n\
00016     ----------------------------------------------------------------------\n\
00017     Adaptive Poisson-Boltzmann Solver (APBS)\n\
00018     Version 1.3 (November 2009)\n\
00019     \n\
00020     Nathan A. Baker (baker@biochem.wustl.edu)\n\
00021     Dept. of Biochemistry and Molecular Biophysics\n\
00022     Center for Computational Biology\n\
00023     Washington University in St. Louis\n\
00024     Additional contributing authors listed in the code documentation.\n\n\
00025     Copyright (c) 2002-2010. Washington University in St. Louis\n\
00026     All Rights Reserved.\n\n\
00027     Portions copyright (c) 1999-2002.  University of California.\n\
00028     Portions copyright (c) 1995.  Michael Holst.\n\n\
00029     Permission to use, copy, modify, and distribute this software and its\n\
00030     documentation for educational, research, and not-for-profit purposes,\n\
00031     without fee and without a signed licensing agreement, is hereby granted,\n\
00032     provided that the above copyright notice, this paragraph and the\n\
00033     following two paragraphs appear in all copies, modifications, and\n\
00034     distributions.\n\n\
00035     IN NO EVENT SHALL THE AUTHORS BE LIABLE TO ANY PARTY FOR DIRECT,\n\
00036     INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST\n\
00037     PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,\n\
00038     EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH\n\
00039     DAMAGE.\n\n\
00040     THE AUTHORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT\n\
00041     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A\n\
00042     PARTICULAR PURPOSE.  THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF\n\
00043     ANY, PROVIDED HEREUNDER IS PROVIDED \"AS IS\".  THE AUTHORS HAVE NO\n\
00044     OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR\n\
00045     MODIFICATIONS.\n\
00046     ----------------------------------------------------------------------\n\
00047     \n\n"
00048     
00049 import string
00050 import sys
00051 import getopt
00052 from vgrid import *
00053         
00054 def IJK(nx, ny, nz, i, j, k):
00055     """
00056         Translate a three dimensional point to
00057         a one dimensional list
00058 
00059         Parameters
00060             nx:    No. of total gridpoints in x direction (int)
00061             ny:    No. of total gridpoints in y direction (int)
00062             nz:    No. of total gridpoints in z direction (int)
00063             i:     Specific gridpoint in x direction (int)
00064             j:     Specific gridpoint in y direction (int)
00065             k:     Specific gridpoint in z direction (int)
00066             
00067         Returns
00068             value: The one dimensional value matching the
00069                    three dimensional point
00070     """
00071     value = (k*nx*ny + j*nx + i)
00072     return value
00073 
00074 def createGrid(inputpath, root):
00075     """
00076         Create the merged grid by use of an APBS input file and
00077         the multiple dx files.
00078 
00079         Parameters
00080             inputpath: The path to the APBS input file (string)
00081             root:      The root of the name of the multiple dx files,
00082                        to be completed with <int>.dx (string)
00083         Returns
00084             mygrid:    The merged grid object (Vgrid)
00085     """
00086     
00087     # Initialize some variables
00088     
00089     myaccess = []
00090     ofrac = [0,0,0]
00091     pdime = [0,0,0]
00092     dime =  [0,0,0]
00093     fglen = [0,0,0]
00094     glob =  [0,0,0]
00095     mygrid = None
00096     mydata = None
00097 
00098     # Parse the input file for useful information
00099 
00100     inputfile = open(inputpath)
00101     while 1:
00102         line = inputfile.readline()
00103         if line == "": break
00104         words = string.split(line)
00105         if len(words) == 0: continue
00106         if words[0] == "ofrac":
00107             ofrac[0] = float(words[1])
00108             ofrac[1] = float(words[1])
00109             ofrac[2] = float(words[1])
00110         elif words[0] == "pdime":
00111             pdime[0] = int(words[1])
00112             pdime[1] = int(words[2])
00113             pdime[2] = int(words[3])
00114         elif words[0] == "dime":
00115             dime[0] = int(words[1])
00116             dime[1] = int(words[2])
00117             dime[2] = int(words[3])
00118         elif words[0] == "fglen":
00119             fglen[0] = float(words[1])
00120             fglen[1] = float(words[2])
00121             fglen[2] = float(words[3])
00122 
00123     inputfile.close()
00124     
00125     if pdime[0] == 1: ofrac[0] = 0
00126     if pdime[1] == 1: ofrac[1] = 0
00127     if pdime[2] == 1: ofrac[2] = 0
00128     
00129     glob[0] = pdime[0]*int(round(dime[0]/(1 + 2*ofrac[0])))
00130     glob[1] = pdime[1]*int(round(dime[1]/(1 + 2*ofrac[1])))
00131     glob[2] = pdime[2]*int(round(dime[2]/(1 + 2*ofrac[2])))
00132      
00133     size = pdime[0] * pdime[1] * pdime[2]
00134 
00135     myxmin = None
00136     myymin = None
00137     myzmin = None
00138     myhx = None
00139     myhy = None
00140     myhz = None
00141     mydata = []
00142     
00143     # Read each dx file
00144 
00145     for i in range(size):
00146         mins = []
00147         for j in range(3): mins.append(None)
00148         kp = int(i/(pdime[0]*pdime[1]))
00149         jp = int((i - kp*pdime[0]*pdime[1])/pdime[0])
00150         ip = i - kp*pdime[0]*pdime[1] - jp*pdime[0]
00151         mins[0] = ip*glob[0]/pdime[0]
00152         mins[1] = jp*glob[1]/pdime[1]
00153         mins[2] = kp*glob[2]/pdime[2]
00154 
00155                 
00156         filename = "%s%i.dx" % (root, i)
00157         try:
00158             file = open(filename)
00159             file.close()
00160         except IOError:
00161             print "Unable to find file %s!" % filename
00162             sys.exit()
00163 
00164         data = []
00165         grid = Vgrid_ctor(0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, data)
00166 
00167         print "Reading dx file %s..." % filename
00168         Vgrid_readDX(grid, "FILE", "ASC", "", filename)
00169         grid.xmax = grid.xmin + grid.hx*(grid.nx - 1)
00170         grid.ymax = grid.ymin + grid.hy*(grid.ny - 1)
00171         grid.zmax = grid.zmin + grid.hzed*(grid.nz - 1)
00172         
00173         print "\tGrid dimensions: %i %i %i" % (grid.nx, grid.ny, grid.nz)
00174         print "\tGrid spacing: %.5f %.5f %.5f" % (grid.hx, grid.hy, grid.hzed)
00175         print "\tGrid lower corner: %.2f %.2f %.2f" % (grid.xmin, grid.ymin, grid.zmin)
00176         print "\tGrid upper corner: %.2f %.2f %.2f" % (grid.xmax, grid.ymax, grid.zmax)
00177         print "\tGlobal Gridpoint Minima: %i %i %i\n" % (mins[0], mins[1], mins[2])
00178 
00179         # If this is the first processor, initialize the merged grid
00180 
00181         if i == 0: # Initialize merged grid
00182             myhx = fglen[0]/(glob[0] - 1)
00183             myhy = fglen[1]/(glob[1] - 1)
00184             myhzed = fglen[2]/(glob[2] - 1)
00185             myxmin = grid.xmin
00186             myymin = grid.ymin
00187             myzmin = grid.zmin         
00188             for j in range(glob[0]*glob[1]*glob[2]):
00189                 mydata.append(0.0)
00190                 myaccess.append(0)
00191 
00192         # If this processor is the last in a given direction, do a sanity check
00193 
00194         if ip == (pdime[0] - 1):
00195             if glob[0] != (mins[0] + grid.nx):
00196                 print "Error occurred - This grid does not line up globally!"
00197                 print "Global x-dim gridpoint size:   %i" % glob[0]
00198                 print "This grid's maximum gridpoint: %i" % (mins[0] + grid.nx)
00199                 sys.exit()
00200         if jp == (pdime[1] - 1):
00201             if glob[1] != (mins[1] + grid.ny):
00202                 print "Error occurred - This grid does not line up globally!"
00203                 print "Global x-dim gridpoint size:   %i" % glob[1]
00204                 print "This grid's maximum gridpoint: %i" % (mins[1] + grid.ny)
00205                 sys.exit()
00206         if kp == (pdime[2] - 1):
00207             if glob[2] != (mins[2] + grid.nz):
00208                 print "Error occurred - This grid does not line up globally!"
00209                 print "Global x-dim gridpoint size:   %i" % glob[2]
00210                 print "This grid's maximum gridpoint: %i" % (mins[2] + grid.nz)
00211                 sys.exit()
00212            
00213         # Now add this grid to the merged grid
00214    
00215         for x in range(grid.nx):
00216             ival = grid.xmin + x*grid.hx
00217             for y in range(grid.ny):
00218                 jval = grid.ymin + y*grid.hy
00219                 for z in range(grid.nz):
00220                     kval = grid.zmin + z*grid.hzed
00221                     inval = 0.0
00222                     pt = [ival, jval, kval]
00223                     ret, value = Vgrid_value(grid, pt, inval)
00224                     if ret:
00225                         location = IJK(glob[0], glob[1], glob[2], (x+mins[0]), (y+mins[1]), (z+mins[2]))
00226                         myaccess[location] += 1
00227                         mydata[location] = value
00228                     else:
00229                         print ival, jval, kval
00230                         print "Could not find gridpoint %i %i %i in grid %s!" % (x,y,z, filename)
00231                         sys.exit()
00232 
00233         # Delete this grid object
00234 
00235         delete_vgrid(grid)
00236 
00237     # Make sure all values of the grid were accessed
00238 
00239     print "Ensuring all grid points were merged..."
00240     for i in range(glob[0]):
00241         for j in range(glob[1]):
00242             for k in range(glob[2]):
00243                 location = IJK(glob[0], glob[1], glob[2], i, j, k)
00244                 if myaccess[location] == 0:
00245                     print "Error: Found unaccessed gridpoint at %i %i %i!" % (i,j,k)
00246                     sys.exit()
00247                 elif myaccess[location] > 1: #Pt. on multiple grids: Error!                    
00248                     print "Error: Multiple grids attempted to access gridpoint %i %i %i in the global grid!" % (i,j,k)
00249                     sys.exit()
00250 
00251                 
00252     # Make the grid
00253     
00254     mygrid = Vgrid_ctor(glob[0], glob[1], glob[2], myhx, myhy, myhzed,
00255                         myxmin, myymin, myzmin, mydata)
00256 
00257     return mygrid
00258                 
00259 def resampleGrid(grid, nx, ny, nz):
00260     """
00261         Resample the grid to a smaller (less-defined) resolution
00262 
00263         Parameters
00264             grid:   The merged grid (Vgrid)
00265             nx:     The number of gridpoints in the x dir (int)
00266             nx:     The number of gridpoints in the x dir (int)
00267             nx:     The number of gridpoints in the x dir (int)
00268 
00269         Retrurns
00270             newgrid: The resampleed merged grid (Vgrid)
00271     """
00272 
00273     print "Resampling the grid..."
00274     
00275     # Ensure that the new grid size is smaller than the old grid size
00276     
00277     if (nx > grid.nx or ny > grid.ny or nz > grid.nz):
00278         print "Error: User specified grid size (%i %i %i) is larger than " % (nx, ny, nz)
00279         print "merged grid size (%i %i %i)!" % (grid.nx, grid.ny, grid.nz)
00280         sys.exit()
00281 
00282     # Get new grid spacing, and create initialized grid
00283     
00284     xmin = grid.xmin
00285     ymin = grid.ymin
00286     zmin = grid.zmin  
00287     xmax = grid.xmin + grid.hx*(grid.nx - 1)
00288     ymax = grid.ymin + grid.hy*(grid.ny - 1)
00289     zmax = grid.zmin + grid.hzed*(grid.nz - 1)
00290     hxnew = (xmax - xmin)/(nx - 1)
00291     hynew = (ymax - ymin)/(ny - 1)
00292     hznew = (zmax - zmin)/(nz - 1)
00293     mydata = []
00294     for i in range(nx*ny*nz): mydata.append(0.0)
00295     
00296     # Populate the new grid
00297 
00298     for x in range(nx):
00299         ival = xmin + x*hxnew
00300         for y in range(ny):
00301             jval = ymin + y*hynew
00302             for z in range(nz):
00303                 kval = zmin + z*hznew
00304                 pt = [ival, jval, kval]
00305                 inval = 0.0
00306                 ret, value = Vgrid_value(grid, pt, inval)
00307                 if ret:
00308                     location = IJK(nx, ny, nz, x,y,z)
00309                     if (value < VSMALL and value > 0): value = 0.0
00310                     mydata[location] = value
00311                 else:
00312                     print "Could not find gridpoint %i %i %i in grid %s!" % (x,y,z, filename)
00313                     sys.exit()
00314 
00315     # Delete the old grid
00316     delete_vgrid(grid)
00317 
00318     # Make the new grid
00319     newgrid = Vgrid_ctor(nx, ny, nz, hxnew, hynew, hznew,
00320                          xmin, ymin, zmin, mydata)
00321     return newgrid
00322 
00323 def printGrid(mygrid, outpath):
00324     """
00325         Print the merged grid using the Vgrid_writeDX command
00326 
00327         Parameters
00328             mygrid:  The merged grid (Vgrid)
00329             outpath: The output path for the new .dx file (string)
00330     """
00331     print "Writing output to %s..." % outpath
00332     title = "Merged Grid from mergedx.py"
00333     Vgrid_writeDX(mygrid, "FILE", "ASC", "", outpath,title, null_array());
00334    
00335 def usage():
00336     """
00337         Print usage information
00338     """
00339     str = "%s" % HEADER
00340     str = str + "mergedx.py\n"
00341     str = str + "\n"
00342     str = str + "This module merges multiple dx files generated from parallel\n"
00343     str = str + "APBS runs into one merged dx file. Users may also resample the\n"
00344     str = str + "grid size if desired.  Default output is written to mergedgrid.dx\n"
00345     str = str + "\n"
00346     str = str + "Usage: mergedx.py [options] <input-file> <dx-stem>\n"
00347     str = str + "\n"
00348     str = str + "    Required Arguments:\n"
00349     str = str + "        <input-file>   : The path to an APBS input file used to\n"
00350     str = str + "                         generate the dx file.  If the APBS run was\n"
00351     str = str + "                         asynchronous, any of the input files may be used\n"
00352     str = str + "        <dx-stem>      : The stem of the dx filenames.  This script will\n"
00353     str = str + "                         add the digit and the .dx extension -  note that\n"
00354     str = str + "                         the dx files MUST be trailed by the form *.dx\n"
00355     str = str + "\n"
00356     str = str + "                         Example: given dx files 2PHKB-PE0.dx and 2PHKB-PE1.dx,\n"
00357     str = str + "                                  the stem would be 2PHKB-PE\n"
00358     str = str + "\n"
00359     str = str + "   Optional Arguments:\n"
00360     str = str + "        --help   (-h)  : Display the usage information\n"
00361     str = str + "        --out=<outpath>: Save merged dx file into filename <outpath>\n"
00362     str = str + "        --nx=<xsize>   : Resample to the <xsize> gridpoints in the x direction\n"
00363     str = str + "        --ny=<ysize>   : Resample to the <ysize> gridpoints in the z direction\n"
00364     str = str + "        --nz=<zsize>   : Resample to the <zsize> gridpoints in the z direction\n"
00365     str = str + "                         Note: If resampling, nx, ny, and nz all must be specified.\n"
00366     str = str + "\n"
00367     sys.stderr.write(str)
00368     sys.exit()
00369     
00370 def main():
00371     """
00372         The main driver for the mergedx script
00373     """
00374     shortOptlist = "h"
00375     longOptlist = ["help","out=","nx=","ny=","nz="]
00376     try: opts, args = getopt.getopt(sys.argv[1:], shortOptlist, longOptlist)
00377     except getopt.GetoptError, details:
00378         sys.stderr.write("GetoptError:  %s\n" % details)
00379         usage()
00380   
00381     outpath = OUT
00382     nx = None
00383     ny = None
00384     nz = None
00385     resample = 0
00386     for o,a in opts:
00387         if o in ("-h","--help"):
00388             usage()
00389             sys.exit()
00390         elif o == "--out":
00391             outpath = a
00392         elif o == "--nx":
00393             nx = int(a)
00394         elif o == "--ny":
00395             ny = int(a)
00396         elif o == "--nz":
00397             nz = int(a)
00398  
00399     if (nx != None and ny != None and nz != None):
00400         resample = 1
00401     elif (nx == None and ny == None and nz == None):
00402         pass
00403     else:
00404         print "\nYou must enter either none or all values for nx, ny, and nz!"
00405         usage()
00406         sys.exit()
00407             
00408     argid = 1
00409     if outpath != OUT: argid += 1
00410     if resample == 1: argid += 3
00411 
00412     try:
00413         inputpath = sys.argv[argid]
00414         root = sys.argv[argid + 1]
00415     except IndexError:
00416         print "\nImproper number of arguments!"
00417         usage()
00418         sys.exit()
00419         
00420     startVio()
00421 
00422     mygrid = createGrid(inputpath, root)
00423     if resample:
00424         mygrid = resampleGrid(mygrid,nx,ny,nz)
00425     printGrid(mygrid, outpath)
00426 
00427     # If we're outputting back to stdout, delete the grid
00428     delete_vgrid(mygrid)
00429     
00430 if __name__ == "__main__": main()

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