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

bin/ApbsClient.py

00001 #!/usr/bin/python
00002 """
00003 Opal client for remote APBS execution.
00004 
00005 Written by Samir Unni, Dave Gohara, Nathan Baker, Yong Huang based on example code from Sriram Krishnan
00006 
00007 ----------------------------------------------------------------------
00008     APBS -- Adaptive Poisson-Boltzmann Solver
00009     Version 1.3
00010     
00011     Nathan A. Baker (baker@biochem.wustl.edu)
00012     Dept. Biochemistry and Molecular Biophysics
00013     Center for Computational Biology
00014     Washington University in St. Louis
00015     
00016     Additional contributing authors listed in the code documentation.
00017     
00018     Copyright (c) 2002-2010, Washington University in St. Louis.
00019     Portions Copyright (c) 2002-2010.  Nathan A. Baker
00020     Portions Copyright (c) 1999-2002.  The Regents of the University of California.
00021     Portions Copyright (c) 1995.  Michael Holst
00022     
00023     All rights reserved.
00024     
00025     Redistribution and use in source and binary forms, with or without
00026     modification, are permitted provided that the following conditions are met:
00027     
00028     * Redistributions of source code must retain the above copyright notice, this
00029     list of conditions and the following disclaimer.
00030     
00031     * Redistributions in binary form must reproduce the above copyright notice,
00032     this list of conditions and the following disclaimer in the documentation
00033     and/or other materials provided with the distribution.
00034     
00035     * Neither the name of Washington University in St. Louis nor the names of its
00036     contributors may be used to endorse or promote products derived from this
00037     software without specific prior written permission.
00038     
00039     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00040     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00041     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00042     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00043     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00044     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00045     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00046     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00047     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00048     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00049     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00050 ----------------------------------------------------------------------
00051     APBS uses FETK (the Finite Element ToolKit) to solve the
00052     Poisson-Boltzmann equation numerically.  FETK is a portable collection
00053     of finite element modeling class libraries developed by the Michael Holst
00054     research group and written in an object-oriented form of C.  FEtk is
00055     designed to solve general coupled systems of nonlinear partial differential
00056     equations using adaptive finite element methods, inexact Newton methods,
00057     and algebraic multilevel methods.  More information about FEtk may be found
00058     at <http://www.FEtk.ORG>.
00059 ----------------------------------------------------------------------
00060     APBS also uses Aqua to solve the Poisson-Boltzmann equation numerically.
00061     Aqua is a modified form of the Holst group PMG library <http://www.FEtk.ORG>
00062     which has been modified by Patrice Koehl
00063     <http://koehllab.genomecenter.ucdavis.edu/> for improved efficiency and
00064     memory usage when solving the Poisson-Boltzmann equation.
00065 ----------------------------------------------------------------------
00066     Please cite your use of APBS as:
00067     
00068     Baker NA, Sept D, Joseph S, Holst MJ, McCammon JA. Electrostatics of
00069     nanosystems: application to microtubules and the ribosome. Proc.
00070     Natl. Acad. Sci. USA 98, 10037-10041 2001.
00071 ----------------------------------------------------------------------
00072 """
00073 __date__  = "3 September 2009"
00074 __author__ = "Samir Unni, Dave Gohara, Nathan Baker, Yong Huang"
00075 __version__ = "1.3"
00076 
00077 import sys
00078 from sys import stdout, stderr
00079 import time
00080 import httplib, urllib
00081 import string
00082 import os, os.path
00083 import subprocess
00084 import getopt
00085 
00086 ########################################################################
00087 #### USERS SHOULD ADD THEIR OWN PATH TO THE APBS INSTALLATION HERE! ####
00088 # This path variable is only needed if you are installing a binary distribution of APBS.  It should point to
00089 # the location where APBS was installed; e.g., the directory that contains the APBS bin, include, lib, and
00090 # share sub-directories.  The following value is just an example and may not be appropriate for your system
00091 # depending on where you installed APBS:
00092 userPath = "/usr/local/apbs-1.3"
00093 ########################################################################
00094 
00095 #### Here are our help and credit messages
00096 creditString = __doc__
00097 helpString = "\n\n\
00098     This driver program calculates electrostatic potentials, energies, and forces\n\
00099     using both multigrid and finite element methods.  It is invoked as:\n\
00100     \n\
00101            ApbsClient.py [options] apbs.in\n\
00102     \n\
00103     where apbs.in is a formatted input file and [options] are:\n\
00104     \n\
00105     --output-file=<name>     Enables output logging to the path listed in <name>.\n\
00106     --output-format=<type>   Specifies format for logging.  Options for type are\n\
00107       either \"xml\" or \"flat\".   Uses flat-file format if --output-format is not used.\n\
00108     --help                   Display this help information.\n\
00109     \n\
00110     Options specific to the Opal web client are:\n\
00111     \n\
00112     --fetch=<output file location>\n\
00113                              Used to specify the location to which the files should be\n\
00114                              downloaded. Files are downloaded to current directory if\n\
00115                              <output file location> or the entire flag is omitted when\n\
00116                              expected.\n\
00117     --library-location=<directory>\n\
00118                              This path variable is only needed if you are using a binary\n\
00119                              distribution of APBS.  It should point to the location where\n\
00120                              APBS was installed; e.g., the directory that contains the APBS\n\
00121                              bin, include, lib, and share sub-directories.  The following\n\
00122                              value is just an example and may not be appropriate for your\n\
00123                              system, depending on where you installed APBS:\n\
00124                                --library-location=/usr/local/apbs-1.3\n\
00125                              Note that you can also edit this Python file to eliminate the\n\
00126                              need to specify this option.\n\
00127     --job-id=<job ID>        Specifies the job ID of the run for which results are to be\n\
00128                              downloaded. Expects the '--fetch' flag to be present as well.\n\
00129     --no-fetch               Disables fetching of files following (only) a blocked run.\n\
00130     --non-blocking           Disables blocking and outputs a URL at which the data can be\n\
00131                              retreived later.\n\
00132     --service-location=<URL> Specifies the location of the Opal server.  Defaults to\n\
00133                              http://kryptonite.nbcr.net/opal2/services/apbs-1.3\n\
00134     --local                  Perform a local APBS run using whatever APBS executable is\n\
00135                              available in the path \
00136 \n----------------------------------------------------------------------\n\
00137 \n"
00138 
00139 def processOptions():
00140            """ A function that transforms command line options into a dictionary for further processing.  However,
00141            presence of the -h or --help option causes the script to print help information and exit. """
00142            global helpString
00143            global service_url
00144            shortOptions = "h"
00145            longOptions = ["help", "local", "library-location=", "output-format=", "output-file=", "fetch=", "job-id=", "no-fetch", "non-blocking", "service-location="]
00146            opts, args = getopt.getopt(sys.argv[1:], shortOptions, longOptions)
00147            optionDict = {}
00148            for o, a in opts:
00149                       if o in ("-h", "--help"):
00150                                  stdout.write("%s\n" % helpString)
00151                                  sys.exit()
00152                       elif o == "--local":
00153                                  optionDict["local"] = True
00154                       elif o == "--output-format":
00155                                  if a in ("xml", "flat"):
00156                                             optionDict["output-format"] = a
00157                                  else:
00158                                             stderr.write("Invalid argument (%s) for --output-format!\n" % a)
00159                                             sys.exit(13)
00160                       elif o == "--output-file":
00161                                  optionDict["output-file"] = a
00162                       elif o == "--fetch":
00163                                  optionDict["fetch"] = a
00164                       elif o == "--job-id":
00165                                  optionDict["job-id"] = a
00166                       elif o == "--no-fetch":
00167                                  optionDict["no-fetch"] = True
00168                       elif o == "--non-blocking":
00169                                  optionDict["non-blocking"] = True
00170                       elif o == "--service-location":
00171                                  optionDict["service-location"] = a
00172                                  service_url = optionDict["service-location"]
00173                       elif o == "--library-location":
00174                                  optionDict["library-location"] = a
00175                       else:
00176                                  stderr.write("Ignoring unrecognized option %s.\n" % o)
00177            optionDict["args"] = args
00178            if not (optionDict.has_key("fetch") and optionDict.has_key("job-id")):
00179                       if (optionDict.has_key("fetch") or optionDict.has_key("job-id")):
00180                                  stderr.write("Error.  Please use both \"--fetch\" and \"--job-id\" flags together.\n")
00181                                  stderr.write("Ignoring these flags...\n")
00182            return optionDict
00183 
00184 #### Setup a list of paths to search for Opal-related modules ####
00185 sys.path.append(userPath)
00186 
00187 # This is the path determined by autoconf/automake
00188 configPath = "/home/bake113/lib/python2.6/site-packages"
00189 modPaths = [configPath, os.path.join(configPath, "ZSI")]
00190 sys.path = sys.path + modPaths
00191 
00192 # This is the current working directory
00193 sys.path.append(os.getcwd())
00194 
00195 # This is an attempt to decipher the path of this script if not in the current directory (and not in the path)
00196 myExecPath = sys.argv[0]
00197 pathSplit = os.path.split(myExecPath)
00198 libPath = os.path.join(pathSplit[0], "../lib/python2.5/site-packages")
00199 sys.path.append(os.path.abspath(libPath))
00200 
00201 # Now check to see if the user specified the APBS installation path on the command line
00202 if __name__ == "__main__":
00203            optDict = processOptions()
00204            if optDict.has_key("library-location"):
00205                       sys.path.append(optDict["library-location"])
00206 try:
00207            import ZSI
00208            from AppService_client import AppServiceLocator, AppServicePortTypeSoapBindingSOAP, getAppMetadataRequest, launchJobRequest, queryStatusRequest, getOutputsRequest, launchJobBlockingRequest, getOutputAsBase64ByNameRequest
00209            from AppService_types import ns0
00210            from ZSI.TC import String
00211 except ImportError, errstr:
00212            stderr.write("ImportError:  %s\n" % errstr)
00213            stderr.write("ApbsClient.py could not find the necessary Python libraries in any of the following locations:\n")
00214            for path in sys.path:
00215                       stderr.write("\t%s\n" % path)
00216            stderr.write("Please edit the ApbsClient.py file using your favorite text editor and add the location\n")
00217            stderr.write("of your APBS installation to the section of the ApbsClient.py file labeled\n")
00218            stderr.write("\"#### USERS SHOULD ADD THEIR OWN PATH TO THE APBS INSTALLATION HERE! ####\"\n")
00219            raise ImportError, errstr
00220 
00221 #### Autoconf the various URLs and version numbers needed for the remote server
00222 service_url = "http://kryptonite.nbcr.net/opal2/services/apbs-1.3"
00223 parallel_service_url = "http://oolite.calit2.optiputer.net/opal2/services/apbs-parallel-1.3"
00224 local_version = "1.3"
00225 maxmem = -1
00226 
00227 def enoughMemory(inputFileName):
00228     if(maxmem == -1):
00229         return True
00230 
00231     inputFile = file(inputFileName, 'r')
00232     for line in inputFile:
00233         line = line.strip()
00234         if(line[:4].lower()=='dime'):
00235             grid_dimensions = line.split()
00236     return ((int(grid_dimensions[1])*int(grid_dimensions[2])*int(grid_dimensions[3])*160/(1024*1024) < maxmem))
00237 
00238 def fetchResults(jobID,outputDirectory,outputFiles,fetchAll):
00239            """ Downloads files from Opal server (only if automatic downloading is enabled). """
00240            stdout.write("Downloading select results:\n")
00241            if outputDirectory != None:
00242                       stdout.write("\tOutput directory:  %s\n" % outputDirectory)
00243                       try:
00244                                  os.makedirs(outputDirectory)
00245                       except OSError:
00246                                  pass
00247                       os.chdir(outputDirectory)
00248     
00249            for file in outputFiles:
00250                       fileName = file._name
00251                       urllib.urlretrieve(file._url, fileName)
00252                       stdout.write("\tDownloading %s...\n" % fileName)
00253 
00254 def pollStatus(jobID,outputDirectory):
00255            """ Determines current status of run and executes fetching of results if the run is completed. """
00256            global service_url
00257            appServicePort = AppServiceLocator().getAppServicePort(service_url)
00258            status = appServicePort.queryStatus(queryStatusRequest(jobID))
00259            
00260            if status._code == 4:
00261                       stderr.write("Error!  The calculation failed!\n")
00262                       stderr.write("Message:  %s\n" % status._message)
00263                       sys.exit(13)
00264            elif status._code != 8:
00265                       stderr.write("Sorry, the calculation hasn't been completed yet. Please wait a short while and attempt to fetch the files again.\n")
00266                       sys.exit(13)
00267            else:
00268                       resp = appServicePort.getOutputs(getOutputsRequest(jobID))
00269                       fetchResults(jobID, outputDirectory, resp._outputFile, status._code==4)
00270 
00271 def initLocalVars():
00272            """ Initializes variables for local usage.  This should eventually be merged with processOptions """
00273            vars = {'typeOfRun' : 'local'}
00274            optionDict = processOptions()
00275            
00276            # Non-blocking parser
00277            if optionDict.has_key("no-fetch"):
00278                       vars['fetchFiles'] = False
00279            else:
00280                       vars["fetchFiles"] = True
00281            if optionDict.has_key("non-blocking"):
00282                       vars['blocking'] = False
00283            else:
00284                       vars["blocking"] = True
00285            # Samir:  I have no idea what fetchFileDescriptionLocation was supposed to do so I set it to None
00286            vars['fetchFileDescriptionLocation'] = None
00287            
00288            # Parses location to save to after a blocking run
00289            if optionDict.has_key("fetch") and vars["blocking"]:
00290                       vars["outputDirectory"] = optionDict["fetch"]
00291            else:
00292                       vars['outputDirectory'] = None
00293            
00294            # Parses custom service location
00295            if optionDict.has_key("service-location"):
00296                       vars["service_url"] = optionDict["service-location"]
00297 
00298            # parses filename to write to
00299            vars['outFile'] = False
00300            if optionDict.has_key("output-file"):
00301                       vars["argList"] = "--output-file=%s" % optionDict["output-file"]
00302                       vars["outFile"] = True
00303            if optionDict.has_key("output-format") and vars["outFile"]:
00304                       if not vars.has_key("argList"):
00305                                  vars["argList"] = ""
00306                       argString = "--output-format=%s" % optionDict["output-format"]
00307                       vars["argList"] = "%s %s" % (vars["argList"], argString)
00308                           
00309            return vars
00310 
00311 def initRemoteVars(argv):
00312            """ Initializes variables for remote usage """
00313            vars = {'typeOfRun':'remote'}
00314     
00315            # data will always be written to a file, and have the same main file name as the .in file, since that can't be specified through the web interface
00316            vars['outFileName'] = os.path.basename(argv[-1])
00317            for i in (1, len(vars['outFileName'])):
00318                       if(vars['outFileName'][-i]=="."):
00319                                  vars['outFileName']=vars['outFileName'][:-i]+".out"
00320                                  break
00321            return vars
00322 
00323 def displayResults(jobID):
00324            """ Displays URLs of resulting files, if they are not to be fetched automatically. """
00325            global service_url
00326            appServicePort = AppServiceLocator().getAppServicePort(service_url)
00327            resp = appServicePort.getOutputs(getOutputsRequest(jobID))
00328            
00329            # Retrieve a listing of all output files
00330            stdout.write("\tStandard Output:  %s\n" % resp._stdOut, "\n")
00331            stdout.write("\tStandard Error:  %s\n", resp._stdErr)
00332            if (resp._outputFile != None):
00333                       for i in range(0, resp._outputFile.__len__()):
00334                                  stdout.write("\t%s:  %s\n" % (resp._outputFile[i]._name, resp._outputFile[i]._url))
00335                       stdout.write("\tStandard Error:  %s\n" % resp._stdErr)
00336 
00337 def execApbs(vars=None, argv=None):
00338            """ Executes APBS and regulates checking of job status and retrieval of data if job is successfully completed. """
00339            if argv is None:
00340                       # i.e. if it is a local run
00341                       argv = sys.argv
00342                       webRun = False
00343            else:
00344                       webRun = True
00345                       custom_service_url = None
00346                       if vars != None:
00347                                  if vars.has_key('service_url'):
00348                                             custom_service_url = vars['service_url']
00349                       vars = initRemoteVars(argv)
00350                       if custom_service_url != None:
00351                                  vars['service_url'] = custom_service_url
00352            global service_url    
00353            #*argument parser
00354            # command-line arguments
00355            vars['inFile'] = argv[-1]
00356            
00357            # parses input file
00358            if(vars['inFile'].find("/")==-1):
00359                       directory=""
00360            else:
00361                       directory = os.path.dirname(vars['inFile'])+'/'
00362                       vars['inFile'] = os.path.basename(vars['inFile'])
00363                       
00364            nprocs = 1
00365            if not vars.has_key('service_url'):
00366                       # find out if it's sequential or parallel
00367                       tempFile = open(directory+vars['inFile'], 'r')
00368                       version_check_flag = True
00369                       for line in tempFile:
00370                                  # remove whitespace
00371                                  line=line.strip()
00372                                  if(line[:5]=='pdime'):
00373                                             dimension_array = line.split()
00374                                             nprocs = int(dimension_array[1])*int(dimension_array[2])*int(dimension_array[3])
00375                                             global parallel_service_url
00376                                             vars['service_url'] = parallel_service_url
00377                                             version_check_flag = False
00378                                  if(line[:5]=='async'):
00379                                             vars['service_url'] = service_url
00380                                             version_check_flag = True
00381                                             break
00382                       if version_check_flag:
00383                                  vars['service_url'] = service_url
00384                                  
00385                       tempFile.close()
00386            else:
00387                       version_check_flag = True     # Enable version checking for custom defined Opal service as well 
00388                       service_url = vars['service_url']
00389            # Retrieve a reference to the AppServicePort
00390            #*this is also from the path to the service
00391            appServicePort = AppServiceLocator().getAppServicePort(vars['service_url'])
00392            
00393            # Set up remote job launch
00394            req = launchJobRequest()
00395            # Checks version compatibility (but currently only works for sequential calculations)
00396            if version_check_flag:
00397                       opal_version = AppServicePortTypeSoapBindingSOAP(vars['service_url']).getAppMetadata(getAppMetadataRequest())._usage.split()[-1]
00398                       if opal_version != local_version:
00399                                  stderr.write("WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!\n")
00400                                  stderr.write("It appears that the remote server version of APBS (%s) does not match\nthe local version (%s)!\n" % (opal_version,local_version))
00401                                  stderr.write("Proceed at your own risk!!\n")
00402                                  stderr.write("WARNING! WARNING! WARNING! WARNING! WARNING! WARNING! WARNING!\n")
00403                                  if webRun:
00404                                             return False
00405            
00406            if(vars.has_key('argList')):
00407                       vars['argList'] = vars['argList'] + " " + vars['inFile']
00408            else:
00409                       vars['argList']=vars['inFile']
00410                       
00411            req._argList = vars['argList']
00412            req._numProcs = nprocs
00413            # append all input files in this manner - in this case we have two of them
00414            
00415            inputFiles = []
00416            #*this is where apbs.in is read in
00417            inputFiles.append(ns0.InputFileType_Def('inputFile'))
00418            #*this must be the same as req._argList is defined to be
00419            inputFiles[-1]._name = vars['inFile']
00420            tempFile = open(directory+vars['inFile'], 'r')
00421            inputFiles[-1]._contents = tempFile.read()
00422            tempFile.close()
00423     
00424            # this is where the rest of the files to read in are determined
00425            start = False
00426            tempFile = open(directory+vars['inFile'], 'r')
00427            for line in tempFile:
00428                       # remove whitespace
00429                       line=line.strip()
00430                       if(line=="end"):
00431                                  break
00432                       if(start and line.find("#")!=0):
00433                                  # eliminates lines with just comments
00434                                  # remove comment
00435                                  if(line.find("#")!=-1):
00436                                             line = line[:line.find("#")]
00437                                  # re-remove whitespace (left after comment removal)
00438                                  line=line.strip()
00439                                  # remove everything except file name
00440                                  count = -1
00441                                  while line[count]!=' ':
00442                                             count = count-1
00443                                  fileName=line[count+1:]
00444                                  inputFiles.append(ns0.InputFileType_Def('inputFile'))
00445                                  inputFiles[-1]._name=fileName
00446                                  tempFile2 = open(directory+fileName, "r")
00447                                  inputFiles[-1]._contents = tempFile2.read()
00448                                  tempFile2.close()
00449                       if(line=="read"):
00450                                  start = True
00451            
00452            tempFile.close()
00453            
00454            # req's inputFile variable is the array of input files created in the lines directly above
00455            req._inputFile = inputFiles
00456            
00457            if vars['typeOfRun']=='remote':
00458                       appServicePort.launchJob(req)
00459                       return [appServicePort, appServicePort.launchJob(req)]
00460            
00461            # Launch job, and retrieve job ID
00462            print "Launching remote APBS job"
00463            try:
00464                       resp = appServicePort.launchJob(req)
00465            except ZSI.FaultException, errstr:
00466                       stderr.write("Error! Failed to execute Opal job. Please send the entire output to the APBS development team.\n")
00467                       stderr.write("%s\n" % errstr.fault.AsSoap())
00468                       sys.exit(13)
00469            
00470            jobID = resp._jobID
00471            print "Received Job ID:", jobID
00472     
00473            status = resp._status
00474     
00475            if(vars['blocking']):
00476                       # Poll for job status
00477                       print "Polling job status"
00478                       while 1:
00479                                  # print current status
00480                                  stdout.write("Status:\n")
00481                                  stdout.write("\tCode:  %s\n" % status._code)
00482                                  stdout.write("\tMessage:  %s\n" % status._message)
00483                                  stdout.write("\tURL for all results:  %s\n" % status._baseURL)
00484                                  
00485                                  if (status._code == 8) or (status._code == 4) or (not vars['blocking']):
00486                                             # STATUS_DONE || STATUS_FAILED
00487                                             break
00488                                  
00489                                  # Sleep for 30 seconds
00490                                  stdout.write("Waiting 30 seconds...\n")
00491                                  time.sleep(30)
00492             
00493                                  # Query job status
00494                                  status = appServicePort.queryStatus(queryStatusRequest(jobID))
00495         
00496                       # Output
00497                       if vars['fetchFiles']:
00498                                  pollStatus(jobID, vars['outputDirectory'])
00499                       else:
00500                                  displayResults(jobID)
00501                                  
00502                                  
00503            else:
00504                       stdout.write("When the job is complete, the results can be retrieved at: \n")
00505                       stdout.write("\t%s\n" % status._baseURL)
00506                       stdout.write("If you want to use the APBS Opal client to download the results for you, the job ID is:\n")
00507                       stdout.write("\t%s\n" % jobID)
00508                       
00509 def main():
00510            """ Parses input, runs local jobs, and fetches files from previously completed calculations. """
00511            # __main__ output
00512            global helpString
00513            print creditString
00514            # Check for invocation with no arguments
00515            if len(sys.argv) == 1:
00516                       stderr.write("Error!  This program must be called with at least one option!\n")
00517                       stderr.write("%s\n" % helpString)
00518                       sys.exit()
00519 
00520            # Process the options
00521            optionDict = processOptions()
00522            if optionDict.has_key("help"):
00523                       stdout.write("%s\n" % helpString)
00524                       sys.exit()
00525 
00526            # Local run
00527            if optionDict.has_key("local"):
00528                       # Assemble an argument string to run as a sub-process
00529                       args = [] # must be returned
00530                       args.append('apbs')
00531                       if optionDict.has_key("output-file"):
00532                                  argString = "--output-file=%s" % optionDict["output-file"]
00533                                  args.append(argString)
00534                       if optionDict.has_key("output-format"):
00535                                  argString = "--output-format=%s" % optionDict["output-format"]
00536                                  args.append(argString)
00537                       if optionDict.has_key("args"):
00538                                  args = args + optionDict["args"]
00539                       if(not enoughMemory(optionDict["args"][-1])):
00540                                  # Add Opal error sending support
00541                                  print "Job will use too much memory to complete calculation"
00542                                  sys.exit()
00543                       stdout.write("Running:  %s...\n" % " ".join(args))
00544                       subprocess.call(args)
00545                       sys.exit()
00546 
00547            # Determines if this is a run to just fetch the files after a non-blocking calculation
00548            if optionDict.has_key("job-id"):
00549                       jobID = optionDict["job-id"]
00550                       outputDirectory = None
00551                       if optionDict.has_key("fetch"):
00552                                  outputDirectory = optionDict["fetch"]
00553                       pollStatus(jobID,outputDirectory)
00554                       sys.exit()
00555 
00556 
00557 
00558 # Run the main driver if we are invoked 
00559 if __name__ == "__main__":
00560            main()
00561            execApbs(vars=initLocalVars())

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