Exemple #1
0
def mainCommand(argv):
    """
        Main driver for running program from the command line.
    """

    fieldNames = ('amber', 'charmm', 'parse', 'tyl06', 'peoepb', 'swanson')

    validForcefields = []
    validForcefields.extend(fieldNames)
    validForcefields.extend((x.upper() for x in fieldNames))

    description = 'This module takes a PDB file as input and performs ' +\
                  'optimizations before yielding a new PQR-style file in PQR_OUTPUT_PATH.\n' +\
                  'If PDB_PATH is an ID it will automatically be obtained from the PDB archive.'

    usage = 'Usage: %prog [options] PDB_PATH PQR_OUTPUT_PATH'

    parser = OptionParser(description=description,
                          usage=usage,
                          version='%prog (Version ' + __version__ + ')')

    group = OptionGroup(parser, "Manditory options",
                        "One of the following options must be used.")
    group.add_option('--ff',
                     dest='ff',
                     metavar='FIELD_NAME',
                     choices=validForcefields,
                     help='The forcefield to use - currently amber, ' +
                     'charmm, parse, tyl06, peoepb and swanson ' +
                     'are supported.')

    group.add_option(
        '--userff',
        dest='userff',
        metavar='USER_FIELD_FILE',
        help=
        'The user created forcefield file to use. Requires --usernames overrides --ff'
    )

    group.add_option(
        '--clean',
        dest='clean',
        action='store_true',
        default=False,
        help='Do no optimization, atom addition, or parameter assignment, ' +
        'just return the original PDB file in aligned format. ' +
        'Overrides --ff and --userff')
    parser.add_option_group(group)

    group = OptionGroup(parser, "General options")
    group.add_option('--nodebump',
                     dest='debump',
                     action='store_false',
                     default=True,
                     help='Do not perform the debumping operation')

    group.add_option('--noopt',
                     dest='opt',
                     action='store_false',
                     default=True,
                     help='Do not perform hydrogen optimization')

    group.add_option('--chain',
                     dest='chain',
                     action='store_true',
                     default=False,
                     help='Keep the chain ID in the output PQR file')

    group.add_option(
        '--assign-only',
        dest='assign_only',
        action='store_true',
        default=False,
        help=
        'Only assign charges and radii - do not add atoms, debump, or optimize.'
    )

    group.add_option(
        '--ffout',
        dest='ffout',
        metavar='FIELD_NAME',
        choices=validForcefields,
        help=
        'Instead of using the standard canonical naming scheme for residue and atom names, '
        + 'use the names from the given forcefield - currently amber, ' +
        'charmm, parse, tyl06, peoepb and swanson are supported.')

    group.add_option(
        '--usernames',
        dest='usernames',
        metavar='USER_NAME_FILE',
        help='The user created names file to use. Required if using --userff')

    group.add_option(
        '--apbs-input',
        dest='input',
        action='store_true',
        default=False,
        help=
        'Create a template APBS input file based on the generated PQR file.  Also creates a Python '
        + 'pickle for using these parameters in other programs.')

    group.add_option(
        '--ligand',
        dest='ligand',
        metavar='PATH',
        help=
        'Calculate the parameters for the ligand in mol2 format at the given path. '
        + 'Pdb2pka must be compiled.')

    group.add_option(
        '--whitespace',
        dest='whitespace',
        action='store_true',
        default=False,
        help=
        'Insert whitespaces between atom name and residue name, between x and y, and between y and z.'
    )

    group.add_option('--typemap',
                     dest='typemap',
                     action='store_true',
                     default=False,
                     help='Create Typemap output.')

    group.add_option(
        '--neutraln',
        dest='neutraln',
        action='store_true',
        default=False,
        help='Make the N-terminus of this protein neutral (default is charged). '
        'Requires PARSE force field.')

    group.add_option(
        '--neutralc',
        dest='neutralc',
        action='store_true',
        default=False,
        help='Make the C-terminus of this protein neutral (default is charged). '
        'Requires PARSE force field.')

    group.add_option('-v',
                     '--verbose',
                     dest='verbose',
                     action='store_true',
                     default=False,
                     help='Print information to stdout.')

    group.add_option(
        '--drop-water',
        dest='drop_water',
        action='store_true',
        default=False,
        help=
        'Drop waters before processing protein. Currently recognized and deleted are the following water types:  %s'
        % ', '.join(WAT.water_residue_names))

    group.add_option(
        '--include-header',
        dest='include_header',
        action='store_true',
        default=False,
        help='Include pdb header in pqr file. '
        'WARNING: The resulting PQR file will not work with APBS versions prior to 1.5'
    )
    parser.add_option_group(group)

    pka_group = OptionGroup(parser, "pH options")

    pka_group.add_option(
        '--ph-calc-method',
        dest='ph_calc_method',
        metavar='PH_METHOD',
        choices=('propka', 'pdb2pka'),
        help=
        'Method used to calculate ph values. If a pH calculation method is selected, for each'
        ' titratable residue pH values will be calculated and the residue potentially modified'
        ' after comparison with the pH value supplied by --with_ph\n'
        'propka - Use PROPKA to calculate pH values. Actual PROPKA results will be output to <output-path>.propka.\n'
        'pdb2pka - Use PDB2PKA to calculate pH values. Requires the use of the PARSE force field.'
        ' Warning: Larger residues can take a very long time to run using this method. EXPERIMENTAL!'
    )

    pka_group.add_option(
        '--with-ph',
        dest='ph',
        action='store',
        type='float',
        default=7.0,
        help=
        'pH values to use when applying the results of the selected pH calculation method.'
        ' Defaults to %default')

    parser.add_option_group(pka_group)

    pdb2pka_group = OptionGroup(parser, "PDB2PKA method options")

    pdb2pka_group.add_option(
        '--pdb2pka-out',
        dest='pdb2pka_out',
        action='store',
        default='pdb2pka_output',
        help='Output directory for PDB2PKA results. Defaults to %default')
    pdb2pka_group.add_option(
        '--pdb2pka-resume',
        dest='pdb2pka_resume',
        action="store_true",
        default=False,
        help='Resume run from state saved in output directory.')

    pdb2pka_group.add_option(
        '--pdie',
        dest='pdb2pka_pdie',
        default=8,
        type='int',
        help='Protein dielectric constant. Defaults to %default')
    pdb2pka_group.add_option(
        '--sdie',
        dest='pdb2pka_sdie',
        default=80,
        type='int',
        help='Solvent dielectric constant. Defaults to %default')

    #     pdb2pka_group.add_option('--maps', dest='maps', default=None, type='int',
    #                              help='<1 for using provided 3D maps; 2 for genereting new maps>')
    #     pdb2pka_group.add_option('--xdiel', dest='xdiel', default=None, type='str',
    #                              help='<xdiel maps>')
    #     pdb2pka_group.add_option('--ydiel', dest='ydiel', default=None, type='str',
    #                              help='<ydiel maps>')
    #     pdb2pka_group.add_option('--zdiel', dest='zdiel', default=None, type='str',
    #                              help='<zdiel maps>')
    #     pdb2pka_group.add_option('--kappa', dest='kappa', default=None, type='str',
    #                              help='<ion-accessibility map>')
    #     pdb2pka_group.add_option('--smooth', dest='sd', default=None, type='float',
    #                              help='<st.dev [A] of Gaussian smooting of 3D maps at the boundary, bandthwith=3 st.dev>')
    #
    # Cut off energy for calculating non-charged-charged interaction energies
    #
    pdb2pka_group.add_option(
        '--pairene',
        dest='pdb2pka_pairene',
        type='float',
        default=1.0,
        help=
        'Cutoff energy in kT for calculating non charged-charged interaction energies. Default: %default'
    )

    parser.add_option_group(pdb2pka_group)

    propka_group = OptionGroup(parser, "PROPKA method options")

    propka_group.add_option(
        "--propka-reference",
        dest="propka_reference",
        default="neutral",
        choices=('neutral', 'low-pH'),
        help=
        "Setting which reference to use for stability calculations. See PROPKA 3.0 documentation."
    )

    propka_group.add_option(
        '--propka-verbose',
        dest='propka_verbose',
        action='store_true',
        default=False,
        help='Print extra proPKA information to stdout. '
        'WARNING: This produces an incredible amount of output.')

    parser.add_option_group(propka_group)

    extensions.setupExtensionsOptions(parser)

    (options, args) = parser.parse_args(argv[1:])

    commandLine = ' '.join(argv[1:])

    if len(args) != 2:
        parser.error('Incorrect number (%d) of arguments!\nargs: %s' %
                     (len(args), args))

    if options.assign_only or options.clean:
        options.debump = options.optflag = False

    userfffile = None
    usernamesfile = None

    if not options.clean:
        if not options.usernames is None:
            try:
                usernamesfile = open(options.usernames, 'rU')
            except IOError:
                parser.error('Unable to open user names file %s' %
                             options.usernames)

        if not options.userff is None:
            try:
                userfffile = open(options.userff, 'rU')
            except IOError:
                parser.error('Unable to open user force field file %s' %
                             options.userff)

            if options.usernames is None:
                parser.error('--usernames must be specified if using --userff')

        else:
            if options.ff is None:
                parser.error(
                    'One of the manditory options was not specified.\n' +
                    'Please specify either --ff, --userff, or --clean')

            if getFFfile(options.ff) == '':
                parser.error(
                    'Unable to find parameter files for forcefield %s!' %
                    options.ff)

    if options.ph < 0.0 or options.ph > 14.0:
        parser.error(
            '%i is not a valid pH!  Please choose a pH between 0.0 and 14.0.' %
            options.pH)

    ph_calc_options = None
    if options.ph_calc_method == 'propka':
        ph_calc_options = utilities.createPropkaOptions(
            options.ph,
            verbose=options.propka_verbose,
            reference=options.propka_reference)

    if options.ph_calc_method == 'pdb2pka':
        if options.ff.lower() != 'parse':
            parser.error('PDB2PKA requires the PARSE force field.')
        ph_calc_options = {
            'output_dir': options.pdb2pka_out,
            'clean_output': not options.pdb2pka_resume,
            'pdie': options.pdb2pka_pdie,
            'sdie': options.pdb2pka_sdie,
            'pairene': options.pdb2pka_pairene
        }

    if options.ligand is not None:
        try:
            options.ligand = open(options.ligand, 'rU')
        except IOError:
            parser.error('Unable to find ligand file %s!' % options.ligand)

    if options.neutraln and (options.ff is None
                             or options.ff.lower() != 'parse'):
        parser.error('--neutraln option only works with PARSE forcefield!')

    if options.neutralc and (options.ff is None
                             or options.ff.lower() != 'parse'):
        parser.error('--neutralc option only works with PARSE forcefield!')

    text = """
--------------------------
PDB2PQR - a Python-based structural conversion utility
--------------------------
Please cite your use of PDB2PQR as:
  Dolinsky TJ, Nielsen JE, McCammon JA, Baker NA.
  PDB2PQR: an automated pipeline for the setup, execution,
  and analysis of Poisson-Boltzmann electrostatics calculations.
  Nucleic Acids Research 32 W665-W667 (2004).

"""
    sys.stdout.write(text)

    path = args[0]
    pdbFile = getPDBFile(path)
    pdblist, errlist = readPDB(pdbFile)

    if len(pdblist) == 0 and len(errlist) == 0:
        parser.error("Unable to find file %s!" % path)

    if len(errlist) != 0 and options.verbose:
        print "Warning: %s is a non-standard PDB file.\n" % path
        print errlist

    outpath = args[1]
    options.outname = outpath

    #In case no extensions were specified or no extensions exist.
    if not hasattr(options,
                   'active_extensions') or options.active_extensions is None:
        options.active_extensions = []

    #I see no point in hiding options from extensions.
    extensionOpts = options

    #TODO: The ideal would be to pass a file like object for the second
    # argument and add a third for names then
    # get rid of the userff and username arguments to this function.
    # This would also do away with the redundent checks and such in
    # the Forcefield constructor.
    try:
        header, lines, missedligands = runPDB2PQR(
            pdblist,
            options.ff,
            outname=options.outname,
            ph=options.ph,
            verbose=options.verbose,
            selectedExtensions=options.active_extensions,
            ph_calc_method=options.ph_calc_method,
            ph_calc_options=ph_calc_options,
            extensionOptions=extensionOpts,
            clean=options.clean,
            neutraln=options.neutraln,
            neutralc=options.neutralc,
            ligand=options.ligand,
            assign_only=options.assign_only,
            chain=options.chain,
            drop_water=options.drop_water,
            debump=options.debump,
            opt=options.opt,
            typemap=options.typemap,
            userff=userfffile,
            usernames=usernamesfile,
            ffout=options.ffout,
            commandLine=commandLine,
            include_old_header=options.include_header)
    except PDB2PQRError as er:
        print er
        sys.exit(2)

    # Print the PQR file
    outfile = open(outpath, "w")
    outfile.write(header)
    # Adding whitespaces if --whitespace is in the options
    for line in lines:
        if options.whitespace:
            if line[0:4] == 'ATOM':
                newline = line[0:6] + ' ' + line[6:16] + ' ' + line[
                    16:38] + ' ' + line[38:46] + ' ' + line[46:]
                outfile.write(newline)
            elif line[0:6] == 'HETATM':
                newline = line[0:6] + ' ' + line[6:16] + ' ' + line[
                    16:38] + ' ' + line[38:46] + ' ' + line[46:]
                outfile.write(newline)
        else:
            outfile.write(line)
    outfile.close()

    if options.input:
        from src import inputgen
        from src import psize
        method = "mg-auto"
        size = psize.Psize()
        size.parseInput(outpath)
        size.runPsize(outpath)
        async = 0  # No async files here!
        input = inputgen.Input(outpath, size, method, async, potdx=True)
        input.printInputFiles()
        input.dumpPickle()
        pickleToJSON(outpath)
Exemple #2
0
def mainCommand(argv):
    """
        Main driver for running program from the command line.
    """
    
    fieldNames = ('amber','charmm','parse', 'ty106','peopb','swanson')
    
    validForcefields = []
    validForcefields.extend(fieldNames)
    validForcefields.extend((x.upper() for x in fieldNames))
    
    description = 'This module takes a PDB file as input and performs ' +\
                  'optimizations before yielding a new PQR-style file in PQR_OUTPUT_PATH.\n' +\
                  'If PDB_PATH is an ID it will automatically be obtained from the PDB archive.'
                  
    usage = 'Usage: %prog [options] PDB_PATH PQR_OUTPUT_PATH'
    
    parser = OptionParser(description=description, usage=usage, version='%prog (Version ' + __version__ + ')')
    

    group = OptionGroup(parser,"Manditory options", "One of the following options must be used.")
    group.add_option('--ff', dest='ff', metavar='FIELD_NAME', choices=validForcefields,
                      help='The forcefield to use - currently amber, ' +
                           'charmm, parse, tyl06, peoepb and swanson ' +
                           'are supported.')
    
    group.add_option('--userff', dest='userff', metavar='USER_FIELD_FILE', 
                      help='The user created forcefield file to use. Requires --usernames overrides --ff')
    
    group.add_option('--clean', dest='clean', action='store_true', default=False,
                      help='Do no optimization, atom addition, or parameter assignment, ' +
                           'just return the original PDB file in aligned format. ' +
                           'Overrides --ff and --userff')
    parser.add_option_group(group)
    
    
    group = OptionGroup(parser,"General options")
    group.add_option('--nodebump', dest='debump', action='store_false', default=True,
                      help='Do not perform the debumping operation')
    
    group.add_option('--noopt', dest='opt', action='store_false', default=True,
                      help='Do not perform hydrogen optimization')
    
    group.add_option('--chain', dest='chain', action='store_true', default=False,
                      help='Keep the chain ID in the output PQR file')
    
    group.add_option('--assign-only', dest='assign_only', action='store_true', default=False,
                      help='Only assign charges and radii - do not add atoms, debump, or optimize.')
    
    group.add_option('--ffout', dest='ffout', metavar='FIELD_NAME',choices=validForcefields,
                      help='Instead of using the standard canonical naming scheme for residue and atom names, ' +
                           'use the names from the given forcefield - currently amber, ' +
                           'charmm, parse, tyl06, peoepb and swanson ' +
                           'are supported.')
    
    group.add_option('--usernames', dest='usernames', metavar='USER_NAME_FILE', 
                      help='The user created names file to use. Required if using --userff')
    
    group.add_option('--with-ph', dest='pH', action='store', type='float',
                      help='Use propka to calculate pKas and apply them to the molecule given the pH value. ' +
                           'Actual PropKa results will be output to <output-path>.propka.')
    
    group.add_option('--apbs-input', dest='input', action='store_true', default=False,
                      help='Create a template APBS input file based on the generated PQR file.  Also creates a Python ' +
                           'pickle for using these parameters in other programs.')
    
    group.add_option('--ligand', dest='ligand',  metavar='PATH',
                      help='Calculate the parameters for the ligand in mol2 format at the given path. ' + 
                           'Pdb2pka must be compiled.')
    
    group.add_option('--whitespace', dest='whitespace', action='store_true', default=False,
                      help='Insert whitespaces between atom name and residue name, between x and y, and between y and z.')   
    
    group.add_option('--typemap', dest='typemap', action='store_true', default=False,
                      help='Create Typemap output.')
    
    group.add_option('--neutraln', dest='neutraln', action='store_true', default=False,
                      help='Make the N-terminus of this protein neutral (default is charged). ' +
                           'Requires PARSE force field.')  
    
    group.add_option('--neutralc', dest='neutralc', action='store_true', default=False,
                      help='Make the C-terminus of this protein neutral (default is charged). ' +
                           'Requires PARSE force field.')  

    group.add_option('-v', '--verbose', dest='verbose', action='store_true', default=False,
                      help='Print information to stdout.')
    parser.add_option_group(group)
    
    extentionsGroup = extensions.setupExtensionsOptions(parser)
    
    (options, args) = parser.parse_args() 
    
    if len(args) != 2:
        parser.error('Incorrect number (%d) of arguments!\nargv: %s, args: %s' % (len(args),argv, args))   

    # Append Numeric/Numpy path to sys.path if the user specified a non-standard location during configuration
    sys.argv=argv
    package_path = PACKAGE_PATH
    if package_path != "":
        sys.path.extend(package_path.split(":"))
        
    if (not options.pH is None) and (options.pH < 0.0 or options.pH > 14.0):
        parser.error('%i is not a valid pH!  Please choose a pH between 0.0 and 14.0.' % options.pH)
        
    if options.assign_only or options.clean:
        options.debump = options.optflag = False
        
    userfffile = None
    usernamesfile = None
    
    if not options.clean:
        if not options.usernames is None:
            try:
                usernamesfile = open(options.usernames, 'rU')
            except IOError:
                parser.error('Unable to open user names file %s' % options.usernames)
                
        if not options.userff is None:
            try:
                userfffile = open(options.userff, 'rU')
            except IOError:
                parser.error('Unable to open user force field file %s' % options.userff)
            
            if options.usernames is None:
                parser.error('--usernames must be specified if using --userff')
            
        else:
            if options.ff is None:
                parser.error('One of the manditory options was not specified.\n' + 
                             'Please specify either --ff, --userff, or --clean')
        
            if getFFfile(options.ff) == '':
                parser.error('Unable to find parameter files for forcefield %s!' % options.ff)

    if not options.ligand is None:
        try:
            options.ligand = open(options.ligand, 'rU')
        except IOError:
            parser.error('Unable to find ligand file %s!' % options.ligand)

    if options.neutraln and (options.ff != 'parse' or not options.userff is None):
        parser.error('--neutraln option only works with PARSE forcefield!')
        
    if options.neutralc and (options.ff != 'parse' or not options.userff is None):
        parser.error('--neutralc option only works with PARSE forcefield!')

    text =  "\n--------------------------\n"
    text += "PDB2PQR - a Python-based structural conversion utility\n"
    text += "--------------------------\n"
    text += "Please cite your use of PDB2PQR as:\n"
    text += "  Dolinsky TJ, Nielsen JE, McCammon JA, Baker NA.\n"
    text += "  PDB2PQR: an automated pipeline for the setup, execution,\n"
    text += "  and analysis of Poisson-Boltzmann electrostatics calculations.\n"
    text += "  Nucleic Acids Research 32 W665-W667 (2004).\n\n"
    sys.stdout.write(text)
            
    path = args[0]
    file = getPDBFile(path)
    pdblist, errlist = readPDB(file)
    
    if len(pdblist) == 0 and len(errlist) == 0:
        #TODO: Why are we doing this?
#        try: 
#            os.remove(path)
#        except OSError: 
#            pass
        parser.error("Unable to find file %s!" % path)

    if len(errlist) != 0 and options.verbose:
        print "Warning: %s is a non-standard PDB file.\n" % path
        print errlist

    outpath = args[1]
    options.outname = outpath

    #In case no extensions were specified.
    if options.active_extentions is None:
        options.active_extentions = []
        
    #Filter out the options specifically for extentions.
    #Passed into runPDB2PQR, but not used by any extention yet.
    extentionOpts = ExtentionOptions()
    
    if extentionsGroup is not None:
        for opt in extentionsGroup.option_list:
            if opt.dest == 'active_extentions':
                continue
            setattr(extentionOpts, opt.dest, 
                    getattr(options, opt.dest))

    #TODO: The ideal would be to pass a file like object for the second
    # argument and get rid of the userff and username arguments to this function.
    # This would also do away with the redundent checks and such in 
    # the Forcefield constructor.
    header, lines, missedligands = runPDB2PQR(pdblist, 
                                              options.ff, 
                                              outname = options.outname,
                                              ph = options.pH,
                                              verbose = options.verbose,
                                              extentions = options.active_extentions,
                                              ententionOptions = extentionOpts,
                                              clean = options.clean,
                                              neutraln = options.neutraln,
                                              neutralc = options.neutralc,
                                              ligand = options.ligand,
                                              assign_only = options.assign_only,
                                              chain = options.chain,
                                              debump = options.debump,
                                              opt = options.opt,
                                              typemap = options.typemap,
                                              userff = userfffile,
                                              usernames = usernamesfile,
                                              ffout = options.ffout)
    
    # Print the PQR file
    outfile = open(outpath,"w")
    outfile.write(header)
    # Adding whitespaces if --whitespace is in the options
    for line in lines:
        if options.whitespace: 
            if line[0:4] == 'ATOM':
                newline = line[0:16] + ' ' + line[16:38] + ' ' + line[38:46] + ' ' + line[46:]
                outfile.write(newline)
            elif line[0:6] == 'HETATM':
                newline = line[0:16] + ' ' + line[16:38] + ' ' + line[38:46] + ' ' + line[46:]
                outfile.write(newline)
        else: 
            outfile.write(line)
    outfile.close()

    if options.input:
        from src import inputgen
        from src import psize
        method = "mg-auto"
        size = psize.Psize()
        size.parseInput(outpath)
        size.runPsize(outpath)
        async = 0 # No async files here!
        input = inputgen.Input(outpath, size, method, async)
        input.printInputFiles()
        input.dumpPickle()
Exemple #3
0
def mainCommand(argv):
    """
        Main driver for running program from the command line.
    """

    fieldNames = ('amber','charmm','parse', 'tyl06','peoepb','swanson')

    validForcefields = []
    validForcefields.extend(fieldNames)
    validForcefields.extend((x.upper() for x in fieldNames))

    description = 'This module takes a PDB file as input and performs ' +\
                  'optimizations before yielding a new PQR-style file in PQR_OUTPUT_PATH.\n' +\
                  'If PDB_PATH is an ID it will automatically be obtained from the PDB archive.'

    usage = 'Usage: %prog [options] PDB_PATH PQR_OUTPUT_PATH'

    parser = OptionParser(description=description, usage=usage, version='%prog (Version ' + __version__ + ')')


    group = OptionGroup(parser,"Manditory options", "One of the following options must be used.")
    group.add_option('--ff', dest='ff', metavar='FIELD_NAME', choices=validForcefields,
                      help='The forcefield to use - currently amber, ' +
                           'charmm, parse, tyl06, peoepb and swanson ' +
                           'are supported.')

    group.add_option('--userff', dest='userff', metavar='USER_FIELD_FILE',
                      help='The user created forcefield file to use. Requires --usernames overrides --ff')

    group.add_option('--clean', dest='clean', action='store_true', default=False,
                      help='Do no optimization, atom addition, or parameter assignment, ' +
                           'just return the original PDB file in aligned format. ' +
                           'Overrides --ff and --userff')
    parser.add_option_group(group)


    group = OptionGroup(parser,"General options")
    group.add_option('--nodebump', dest='debump', action='store_false', default=True,
                      help='Do not perform the debumping operation')

    group.add_option('--noopt', dest='opt', action='store_false', default=True,
                      help='Do not perform hydrogen optimization')

    group.add_option('--chain', dest='chain', action='store_true', default=False,
                      help='Keep the chain ID in the output PQR file')

    group.add_option('--assign-only', dest='assign_only', action='store_true', default=False,
                      help='Only assign charges and radii - do not add atoms, debump, or optimize.')

    group.add_option('--ffout', dest='ffout', metavar='FIELD_NAME',choices=validForcefields,
                      help='Instead of using the standard canonical naming scheme for residue and atom names, ' +
                           'use the names from the given forcefield - currently amber, ' +
                           'charmm, parse, tyl06, peoepb and swanson are supported.')

    group.add_option('--usernames', dest='usernames', metavar='USER_NAME_FILE',
                      help='The user created names file to use. Required if using --userff')

    group.add_option('--apbs-input', dest='input', action='store_true', default=False,
                      help='Create a template APBS input file based on the generated PQR file.  Also creates a Python ' +
                           'pickle for using these parameters in other programs.')

    group.add_option('--ligand', dest='ligand',  metavar='PATH',
                      help='Calculate the parameters for the ligand in mol2 format at the given path. ' +
                           'Pdb2pka must be compiled.')

    group.add_option('--whitespace', dest='whitespace', action='store_true', default=False,
                      help='Insert whitespaces between atom name and residue name, between x and y, and between y and z.')

    group.add_option('--typemap', dest='typemap', action='store_true', default=False,
                      help='Create Typemap output.')

    group.add_option('--neutraln', dest='neutraln', action='store_true', default=False,
                      help='Make the N-terminus of this protein neutral (default is charged). '
                           'Requires PARSE force field.')

    group.add_option('--neutralc', dest='neutralc', action='store_true', default=False,
                      help='Make the C-terminus of this protein neutral (default is charged). '
                           'Requires PARSE force field.')

    group.add_option('-v', '--verbose', dest='verbose', action='store_true', default=False,
                      help='Print information to stdout.')

    group.add_option('--drop-water', dest='drop_water', action='store_true', default=False,
                      help='Drop waters before processing protein. Currently recognized and deleted are the following water types:  %s' % ', '.join(WAT.water_residue_names))

    group.add_option('--include-header', dest='include_header', action='store_true', default=False,
                      help='Include pdb header in pqr file. '
                           'WARNING: The resulting PQR file will not work with APBS versions prior to 1.5')
    parser.add_option_group(group)

    pka_group = OptionGroup(parser,"pH options")

    pka_group.add_option('--ph-calc-method', dest='ph_calc_method', metavar='PH_METHOD', choices=('propka', 'propka31', 'pdb2pka'),
                      help='Method used to calculate ph values. If a pH calculation method is selected, for each'
                      ' titratable residue pH values will be calculated and the residue potentially modified'
                      ' after comparison with the pH value supplied by --with_ph\n'
                      'propka - Use PROPKA to calculate pH values. Actual PROPKA results will be output to <output-path>.propka.\n'
                      'propka31 - Use PROPKA 3.1 to calculate pH values. Actual PROPKA results will be output to <output-path>.propka.\n'
                      'pdb2pka - Use PDB2PKA to calculate pH values. Requires the use of the PARSE force field.'
                      ' Warning: Larger residues can take a very long time to run using this method. EXPERIMENTAL!')

    pka_group.add_option('--with-ph', dest='ph', action='store', type='float', default=7.0,
                      help='pH values to use when applying the results of the selected pH calculation method.'
                      ' Defaults to %default')

    parser.add_option_group(pka_group)

    pdb2pka_group = OptionGroup(parser,"PDB2PKA method options")

    pdb2pka_group.add_option('--pdb2pka-out', dest='pdb2pka_out', action='store', default='pdb2pka_output',
                             help='Output directory for PDB2PKA results. Defaults to %default')
    pdb2pka_group.add_option('--pdb2pka-resume', dest='pdb2pka_resume', action="store_true", default=False,
                             help='Resume run from state saved in output directory.')

    pdb2pka_group.add_option('--pdie', dest='pdb2pka_pdie', default=8,type='int',
                             help='Protein dielectric constant. Defaults to %default')
    pdb2pka_group.add_option('--sdie', dest='pdb2pka_sdie', default=80, type='int',
                             help='Solvent dielectric constant. Defaults to %default')

#     pdb2pka_group.add_option('--maps', dest='maps', default=None, type='int',
#                              help='<1 for using provided 3D maps; 2 for genereting new maps>')
#     pdb2pka_group.add_option('--xdiel', dest='xdiel', default=None, type='str',
#                              help='<xdiel maps>')
#     pdb2pka_group.add_option('--ydiel', dest='ydiel', default=None, type='str',
#                              help='<ydiel maps>')
#     pdb2pka_group.add_option('--zdiel', dest='zdiel', default=None, type='str',
#                              help='<zdiel maps>')
#     pdb2pka_group.add_option('--kappa', dest='kappa', default=None, type='str',
#                              help='<ion-accessibility map>')
#     pdb2pka_group.add_option('--smooth', dest='sd', default=None, type='float',
#                              help='<st.dev [A] of Gaussian smooting of 3D maps at the boundary, bandthwith=3 st.dev>')
    #
    # Cut off energy for calculating non-charged-charged interaction energies
    #
    pdb2pka_group.add_option('--pairene',dest='pdb2pka_pairene',type='float',default=1.0,
                      help='Cutoff energy in kT for calculating non charged-charged interaction energies. Default: %default')

    parser.add_option_group(pdb2pka_group)

    propka_group = OptionGroup(parser,"PROPKA method options")

    propka_group.add_option("--propka-reference", dest="propka_reference", default="neutral", choices=('neutral','low-pH'),
           help="Setting which reference to use for stability calculations. See PROPKA 3.0 documentation.")

    propka_group.add_option('--propka-verbose', dest='propka_verbose', action='store_true', default=False,
                      help='Print extra proPKA information to stdout. '
                           'WARNING: This produces an incredible amount of output.')

    parser.add_option_group(propka_group)


    extensions.setupExtensionsOptions(parser)

    (options, args) = parser.parse_args(argv[1:])

    commandLine = ' '.join(argv[1:])

    if len(args) != 2:
        parser.error('Incorrect number (%d) of arguments!\nargs: %s' % (len(args), args))

    if options.assign_only or options.clean:
        options.debump = options.optflag = False

    userfffile = None
    usernamesfile = None

    if not options.clean:
        if not options.usernames is None:
            try:
                usernamesfile = open(options.usernames, 'rU')
            except IOError:
                parser.error('Unable to open user names file %s' % options.usernames)

        if not options.userff is None:
            try:
                userfffile = open(options.userff, 'rU')
            except IOError:
                parser.error('Unable to open user force field file %s' % options.userff)

            if options.usernames is None:
                parser.error('--usernames must be specified if using --userff')

        else:
            if options.ff is None:
                parser.error('One of the manditory options was not specified.\n' +
                             'Please specify either --ff, --userff, or --clean')

            if getFFfile(options.ff) == '':
                parser.error('Unable to find parameter files for forcefield %s!' % options.ff)

    if options.ph < 0.0 or options.ph > 14.0:
        parser.error('%i is not a valid pH!  Please choose a pH between 0.0 and 14.0.' % options.pH)

    ph_calc_options = None
    if options.ph_calc_method == 'propka':
        ph_calc_options = utilities.createPropkaOptions(options.ph,
                                                   verbose=options.propka_verbose,
                                                   reference=options.propka_reference)
    elif options.ph_calc_method == 'propka31':
        import propka.lib
        ph_calc_options, _ = propka.lib.loadOptions('--quiet')
    elif options.ph_calc_method == 'pdb2pka':
        if options.ff.lower() != 'parse':
            parser.error('PDB2PKA requires the PARSE force field.')
        ph_calc_options = {'output_dir': options.pdb2pka_out,
                          'clean_output': not options.pdb2pka_resume,
                          'pdie': options.pdb2pka_pdie,
                          'sdie': options.pdb2pka_sdie,
                          'pairene': options.pdb2pka_pairene}

    if options.ligand is not None:
        try:
            options.ligand = open(options.ligand, 'rU')
        except IOError:
            parser.error('Unable to find ligand file %s!' % options.ligand)

    if options.neutraln and (options.ff is None or options.ff.lower() != 'parse'):
        parser.error('--neutraln option only works with PARSE forcefield!')

    if options.neutralc and (options.ff is None or options.ff.lower() != 'parse'):
        parser.error('--neutralc option only works with PARSE forcefield!')

    text =  """
--------------------------
PDB2PQR - a Python-based structural conversion utility
--------------------------
Please cite your use of PDB2PQR as:
  Dolinsky TJ, Nielsen JE, McCammon JA, Baker NA.
  PDB2PQR: an automated pipeline for the setup, execution,
  and analysis of Poisson-Boltzmann electrostatics calculations.
  Nucleic Acids Research 32 W665-W667 (2004).

"""
    sys.stdout.write(text)

    path = args[0]
    pdbFile = getPDBFile(path)
    pdblist, errlist = readPDB(pdbFile)

    if len(pdblist) == 0 and len(errlist) == 0:
        parser.error("Unable to find file %s!" % path)

    if len(errlist) != 0 and options.verbose:
        print("Warning: %s is a non-standard PDB file.\n" % path)
        print(errlist)

    outpath = args[1]
    options.outname = outpath

    #In case no extensions were specified or no extensions exist.
    if not hasattr(options, 'active_extensions' ) or options.active_extensions is None:
        options.active_extensions = []

    #I see no point in hiding options from extensions.
    extensionOpts = options

    #TODO: The ideal would be to pass a file like object for the second
    # argument and add a third for names then
    # get rid of the userff and username arguments to this function.
    # This would also do away with the redundent checks and such in
    # the Forcefield constructor.
    try:
        header, lines, missedligands, _ = runPDB2PQR(pdblist,
                                                  options.ff,
                                                  outname = options.outname,
                                                  ph = options.ph,
                                                  verbose = options.verbose,
                                                  selectedExtensions = options.active_extensions,
                                                  ph_calc_method = options.ph_calc_method,
                                                  ph_calc_options = ph_calc_options,
                                                  extensionOptions = extensionOpts,
                                                  clean = options.clean,
                                                  neutraln = options.neutraln,
                                                  neutralc = options.neutralc,
                                                  ligand = options.ligand,
                                                  assign_only = options.assign_only,
                                                  chain = options.chain,
                                                  drop_water = options.drop_water,
                                                  debump = options.debump,
                                                  opt = options.opt,
                                                  typemap = options.typemap,
                                                  userff = userfffile,
                                                  usernames = usernamesfile,
                                                  ffout = options.ffout,
                                                  commandLine = commandLine,
                                                  include_old_header = options.include_header)
    except PDB2PQRError as er:
        print(er)
        sys.exit(2)

    # Print the PQR file
    outfile = open(outpath,"w")
    outfile.write(header)
    # Adding whitespaces if --whitespace is in the options
    for line in lines:
        if options.whitespace:
            if line[0:4] == 'ATOM':
                newline = line[0:6] + ' ' + line[6:16] + ' ' + line[16:38] + ' ' + line[38:46] + ' ' + line[46:]
                outfile.write(newline)
            elif line[0:6] == 'HETATM':
                newline = line[0:6] + ' ' + line[6:16] + ' ' + line[16:38] + ' ' + line[38:46] + ' ' + line[46:]
                outfile.write(newline)
        else:
            outfile.write(line)
    outfile.close()

    if options.input:
        from src import inputgen
        from src import psize
        method = "mg-auto"
        size = psize.Psize()
        size.parseInput(outpath)
        size.runPsize(outpath)
        async = 0 # No async files here!
        input = inputgen.Input(outpath, size, method, async, potdx=True)
        input.printInputFiles()
        input.dumpPickle()