예제 #1
0
    def _solvent_amber_files(self,
                             lig1_name,
                             lig1_mol2,
                             lig1_frcmod,
                             prmtop_filename,
                             inpcrd_filename,
                             leaprc='leaprc.gaff'):

        logger = logging.getLogger(__name__)
        logger.setLevel(logging.DEBUG)
        handler = logging.FileHandler('tleap_solvent_phase.log')
        logger.addHandler(handler)

        #Get absolute paths for input/output
        lig1_mol2 = os.path.abspath(lig1_mol2)
        lig1_frcmod = os.path.abspath(lig1_frcmod)

        prmtop_filename = os.path.abspath(prmtop_filename)
        inpcrd_filename = os.path.abspath(inpcrd_filename)

        #Work in a temporary directory, on hard coded filenames, to avoid any issues AMBER may have with spaces and other special characters in filenames
        with mdtraj.utils.enter_temp_directory():
            shutil.copy(lig1_mol2, 'file.mol2')
            shutil.copy(lig1_frcmod, 'file.frcmod')

            tleap_input = f"""
            source oldff/leaprc.ff99SB
            source {leaprc}
            loadamberparams file.frcmod
            LIG = loadmol2 file.mol2
            check LIG
            solvateBox LIG TIP3PBOX 10.0
            addIons LIG Cl- 5
            addIons LIG K+ 5
            saveamberparm LIG out.prmtop out.inpcrd
            quit
            """

            file_handle = open('tleap_commands', 'w')
            file_handle.writelines(tleap_input)
            file_handle.close()

            cmd = f'tleap -f {file_handle.name}'
            output = getoutput(cmd)
            logger.debug(output)

            #Copy back target files
            shutil.copy('out.prmtop', prmtop_filename)
            shutil.copy('out.inpcrd', inpcrd_filename)

        logfile = os.path.abspath('tleap_solvent_phase.log')
        destination = os.path.abspath('data')
        shutil.move(logfile,
                    os.path.join(destination, os.path.basename(logfile)))

        return prmtop_filename, inpcrd_filename
예제 #2
0
def build_peptide_tleap(amino_acids):
    """
    Use tleap to generate a peptide topology
    and positions.

    Parameters
    ----------
    amino_acids : list of str
        List of amino acids and caps in three-letter names
        e.g. ['ACE', 'ALA', 'NME']

    Returns
    -------
    topology : simtk.openmm.app.Topology object
        Topology of the amino acid
    positions : [n, 3] array
        positions of atoms
    """
    aa_str = " ".join(amino_acids)
    filename = "".join(amino_acids)
    tleapstr = """
    source oldff/leaprc.ff99SBildn
    system = sequence {{ {amino_acid} }}
    saveamberparm system {filename}.prmtop {filename}.inpcrd
    """.format(amino_acid=aa_str, filename=filename)
    cwd = os.getcwd()
    temp_dir = tempfile.mkdtemp()
    os.chdir(temp_dir)
    tleap_file = open('tleap_commands', 'w')
    tleap_file.writelines(tleapstr)
    tleap_file.close()
    tleap_cmd_str = "tleap -f %s " % tleap_file.name

    #call tleap, log output to logger
    output = getoutput(tleap_cmd_str)
    logging.debug(output)

    prmtop = app.AmberPrmtopFile("{filename}.prmtop".format(filename=filename))
    inpcrd = app.AmberInpcrdFile("{filename}.inpcrd".format(filename=filename))
    topology = prmtop.topology
    positions = inpcrd.positions

    os.chdir(cwd)
    shutil.rmtree(temp_dir)
    return topology, positions
예제 #3
0
def build_peptide_tleap(amino_acids):
    """
    Use tleap to generate a peptide topology
    and positions.

    Parameters
    ----------
    amino_acids : list of str
        List of amino acids and caps in three-letter names
        e.g. ['ACE', 'ALA', 'NME']

    Returns
    -------
    topology : simtk.openmm.app.Topology object
        Topology of the amino acid
    positions : [n, 3] array
        positions of atoms
    """
    aa_str = " ".join(amino_acids)
    filename = "".join(amino_acids)
    tleapstr = """
    source oldff/leaprc.ff99SBildn
    system = sequence {{ {amino_acid} }}
    saveamberparm system {filename}.prmtop {filename}.inpcrd
    """.format(amino_acid=aa_str, filename=filename)
    cwd = os.getcwd()
    temp_dir = tempfile.mkdtemp()
    os.chdir(temp_dir)
    tleap_file = open('tleap_commands', 'w')
    tleap_file.writelines(tleapstr)
    tleap_file.close()
    tleap_cmd_str = "tleap -f %s " % tleap_file.name

    #call tleap, log output to logger
    output = getoutput(tleap_cmd_str)
    logging.debug(output)

    prmtop = app.AmberPrmtopFile("{filename}.prmtop".format(filename=filename))
    inpcrd = app.AmberInpcrdFile("{filename}.inpcrd".format(filename=filename))
    topology = prmtop.topology
    positions = inpcrd.positions

    os.chdir(cwd)
    shutil.rmtree(temp_dir)
    return topology, positions
예제 #4
0
def build_mixture_prmtop(mol2_filenames, frcmod_filenames, box_filename, prmtop_filename, inpcrd_filename, water_model = 'TIP3P'):
    """Create a prmtop and inpcrd from a collection of mol2 and frcmod files
    as well as a single box PDB.  We have used this for setting up
    simulations of neat liquids or binary mixtures.

    Parameters
    ----------
    mol2_filenames : list(str)
        Filenames of GAFF flavored mol2 files.  Each must contain exactly
        ONE ligand.
    frcmod_filenames : str
        Filename of input GAFF frcmod filenames.
    box_filename : str
        Filename of PDB containing an arbitrary box of the mol2 molecules.
    prmtop_filename : str
        output prmtop filename.  Should have suffix .prmtop
    inpcrd_filename : str
        output inpcrd filename.  Should have suffix .inpcrd
    water_model : str, optional. Default: "TIP3P"
        String specifying water model to be used IF water is present as a component of the mixture. Valid options are currently "TIP3P", "SPC", or None. If None is specified, flexible GAFF-water will be used as for any other solute (old behavior).

    Returns
    -------
    tleap_commands : str
        The string of commands piped to tleap for building the prmtop
        and inpcrd files.  This will *already* have been run, but the
        output can be useful for debugging or archival purposes. However,
        this will reflect temporary file names for both input and output
        file as these are used to avoid tleap filename restrictions.

    Notes
    -----
    This can be easily broken if there are missing, duplicated, or
    inconsistent ligand residue names in your box, mol2, and frcmod files.
    You can use mdtraj to edit the residue names with something like
    this: trj.top.residue(0).name = "L1"
    """

    # Check for one residue name per mol2 file and uniqueness between all mol2 files
    all_names = set()
    for filename in mol2_filenames:
        t = md.load(filename)
        names = set([r.name for r in t.top.residues])

        if len(names) != 1:
            raise(ValueError("Must have a SINGLE residue name in each mol2 file."))

        all_names = all_names.union(list(names))

    if len(all_names) != len(mol2_filenames):
        raise(ValueError("Must have UNIQUE residue names in each mol2 file."))
    if len(mol2_filenames) != len(frcmod_filenames):
        raise(ValueError("Must provide an equal number of frcmod and mol2 file names."))

    #Get number of files
    nfiles = len(mol2_filenames)

    #Check validity of water model options
    valid_water = ['TIP3P', 'SPC', None]
    if not water_model in valid_water:
        raise(ValueError("Must provide a valid water model."))

    #If we are requesting a different water model, check if there is water present
    if not water_model==None:
        parmed = import_("parmed")
        solventIsWater = []
        waterPresent = False
        for i in range(nfiles):
            mol = parmed.load_file( mol2_filenames[i] )
            #Check if it is water by checking GAFF atom names
            types = [ atom.type for atom in mol.atoms ]
            if 'oh' in types and types.count('ho')==2 and len(types)==3:
                solventIsWater.append(True)
                waterPresent = True
            else:
                solventIsWater.append(False)

        #In this case, if we have any water, we will now work on fewer .mol2 and .frcmod files and instead use the force field files for those. So, reduce nfiles and remove the files we don't need from the .mol2 and .frcmod filename lists
        #After doing so, go on to interpret the specified water model and compose the water model string needed for tleap
        if waterPresent:
            new_mol2_filenames = []
            new_frcmod_filenames = []
            water_mol2_filenames = []
            for i in range( nfiles ):
                if not solventIsWater[i]:
                    new_mol2_filenames.append( mol2_filenames[i] )
                    new_frcmod_filenames.append( frcmod_filenames[i] )
                else:
                    water_mol2_filenames.append( mol2_filenames[i] )
            nfiles = len(new_mol2_filenames)
            mol2_filenames = new_mol2_filenames
            frcmod_filenames = new_frcmod_filenames

            #Now interpret the specified water model and translate into AMBER nomenclature
            if water_model=='TIP3P':
                water_model = 'TP3'
            elif water_model =='SPC':
                water_model = 'SPC'
            else:
                raise(ValueError("Cannot translate specified water model into one of the available models."))


            #Compose string for loading specified water molecule
            water_string = '\n'
            water_names = [md.load(filename).top.residue(0).name for filename in water_mol2_filenames]
            for name in water_names:
                water_string += '%s = %s\n' % (name, water_model )
                #Also if not TIP3P, update to source correct frcmod file
                if water_model == 'SPC':
                    water_string += 'loadamberparams frcmod.spce\n'
                elif water_model =='TP3':
                    continue
                else:
                    raise(ValueError("Cannot identify water frcmod file to be loaded."))

            #Rename water atoms in box file to match what is expected by AMBER
            packmol = import_("openmoltools.packmol")
            packmol.rename_water_atoms(box_filename)
    else:
        waterPresent = False

    #Make temporary, hardcoded filenames for mol2 and frcmod input to avoid tleap filename restrictions
    tmp_mol2_filenames = [ 'in%d.mol2' % n for n in range(nfiles) ]
    tmp_frcmod_filenames = [ 'in%d.frcmod' % n for n in range(nfiles) ]

    #Make temporary, hardcoded filenames for output files to avoid tleap filename restrictions
    tmp_prmtop_filename = 'out.prmtop'
    tmp_inpcrd_filename = 'out.inpcrd'
    tmp_box_filename = 'tbox.pdb'

    #Build absolute paths of input files so we can use context and temporary directory
    infiles = mol2_filenames + frcmod_filenames + [box_filename]
    infiles = [ os.path.abspath(filenm) for filenm in infiles ]

    #Build absolute paths of output files so we can copy them back
    prmtop_filename = os.path.abspath( prmtop_filename )
    inpcrd_filename = os.path.abspath( inpcrd_filename )

    #Use temporary directory and do the setup
    with mdtraj.utils.enter_temp_directory():

        #Copy input files to temporary file names in target directory
        for (infile, outfile) in zip( infiles, tmp_mol2_filenames+tmp_frcmod_filenames+[tmp_box_filename] ):
            shutil.copy( infile, outfile)
            logger.debug('Copying input file %s to %s...\n' % (infile, outfile))


        all_names = [md.load(filename).top.residue(0).name for filename in tmp_mol2_filenames]

        mol2_section = "\n".join("%s = loadmol2 %s" % (all_names[k], filename) for k, filename in enumerate(tmp_mol2_filenames))
        #If non-GAFF water is present, load desired parameters for that water as well.
        if waterPresent:
            mol2_section += water_string
        amberparams_section = "\n".join("loadamberparams %s" % (filename) for k, filename in enumerate(tmp_frcmod_filenames))

        tleap_commands = TLEAP_TEMPLATE % dict(mol2_section=mol2_section, amberparams_section=amberparams_section, box_filename=tmp_box_filename, prmtop_filename=tmp_prmtop_filename, inpcrd_filename=tmp_inpcrd_filename)
        print(tleap_commands)

        file_handle = open('tleap_commands', 'w')
        file_handle.writelines(tleap_commands)
        file_handle.close()

        logger.debug('Running tleap in temporary directory.')
        cmd = "tleap -f %s " % file_handle.name
        logger.debug(cmd)

        output = getoutput(cmd)
        logger.debug(output)
        check_for_errors( output, other_errors = ['Improper number of arguments'], ignore_errors = ['unperturbed charge of the unit', 'ignoring the error'] )

        #Copy stuff back to right filenames
        for (tfile, finalfile) in zip( [tmp_prmtop_filename, tmp_inpcrd_filename], [prmtop_filename, inpcrd_filename] ):
            shutil.copy( tfile, finalfile)

    return tleap_commands
예제 #5
0
def run_tleap(molecule_name, gaff_mol2_filename, frcmod_filename, prmtop_filename=None, inpcrd_filename=None, log_debug_output=False):
    """Run AmberTools tleap to create simulation files for AMBER

    Parameters
    ----------
    molecule_name : str
        The name of the molecule
    gaff_mol2_filename : str
        GAFF format mol2 filename produced by antechamber
    frcmod_filename : str
        Amber frcmod file produced by prmchk
    prmtop_filename : str, optional, default=None
        Amber prmtop file produced by tleap, defaults to molecule_name
    inpcrd_filename : str, optional, default=None
        Amber inpcrd file produced by tleap, defaults to molecule_name
    log_debug_output : bool, optional, default=False
        If true, will send output of tleap to logger.

    Returns
    -------
    prmtop_filename : str
        Amber prmtop file produced by tleap
    inpcrd_filename : str
        Amber inpcrd file produced by tleap
    """
    if prmtop_filename is None:
        prmtop_filename = "%s.prmtop" % molecule_name
    if inpcrd_filename is None:
        inpcrd_filename = "%s.inpcrd" % molecule_name

    #Get absolute paths for input/output
    gaff_mol2_filename = os.path.abspath( gaff_mol2_filename )
    frcmod_filename = os.path.abspath( frcmod_filename )
    prmtop_filename = os.path.abspath( prmtop_filename )
    inpcrd_filename = os.path.abspath( inpcrd_filename )

    #Work in a temporary directory, on hard coded filenames, to avoid any issues AMBER may have with spaces and other special characters in filenames
    with mdtraj.utils.enter_temp_directory():
        shutil.copy( gaff_mol2_filename, 'file.mol2' )
        shutil.copy( frcmod_filename, 'file.frcmod' )

        tleap_input = """
    source oldff/leaprc.ff99SB
    source leaprc.gaff
    LIG = loadmol2 file.mol2
    check LIG
    loadamberparams file.frcmod
    saveamberparm LIG out.prmtop out.inpcrd
    quit

"""

        file_handle = open('tleap_commands', 'w')
        file_handle.writelines(tleap_input)
        file_handle.close()

        cmd = "tleap -f %s " % file_handle.name
        if log_debug_output: logger.debug(cmd)

        output = getoutput(cmd)
        if log_debug_output: logger.debug(output)

        check_for_errors( output, other_errors = ['Improper number of arguments'] )

        #Copy back target files
        shutil.copy( 'out.prmtop', prmtop_filename )
        shutil.copy( 'out.inpcrd', inpcrd_filename )

    return prmtop_filename, inpcrd_filename
예제 #6
0
def run_antechamber(molecule_name, input_filename, charge_method="bcc", net_charge=None, gaff_mol2_filename=None, frcmod_filename=None,
    input_format='mol2', resname=False, log_debug_output=False):
    """Run AmberTools antechamber and parmchk2 to create GAFF mol2 and frcmod files.

    Parameters
    ----------
    molecule_name : str
        Name of the molecule to be parameterized, will be used in output filenames.
    ligand_filename : str
        The molecule to be parameterized.  Must be tripos mol2 format.
    charge_method : str, optional
        If not None, the charge method string will be passed to Antechamber.
    net_charge : int, optional
        If not None, net charge of the molecule to be parameterized.
        If None, Antechamber sums up partial charges from the input file.
    gaff_mol2_filename : str, optional, default=None
        Name of GAFF mol2 filename to output.  If None, uses local directory
        and molecule_name
    frcmod_filename : str, optional, default=None
        Name of GAFF frcmod filename to output.  If None, uses local directory
        and molecule_name
    input_format : str, optional, default='mol2'
        Format specifier for input file to pass to antechamber.
    resname : bool, optional, default=False
        Set the residue name used within output files to molecule_name
    log_debug_output : bool, optional, default=False
        If true, will send output of tleap to logger.

    Returns
    -------
    gaff_mol2_filename : str
        GAFF format mol2 filename produced by antechamber
    frcmod_filename : str
        Amber frcmod file produced by prmchk
    """
    utils = import_("openmoltools.utils")
    ext = utils.parse_ligand_filename(input_filename)[1]

    if gaff_mol2_filename is None:
        gaff_mol2_filename = molecule_name + '.gaff.mol2'
    if frcmod_filename is None:
        frcmod_filename = molecule_name + '.frcmod'

    #Build absolute paths for input and output files
    gaff_mol2_filename = os.path.abspath( gaff_mol2_filename )
    frcmod_filename = os.path.abspath( frcmod_filename )
    input_filename = os.path.abspath( input_filename )

    def read_file_contents(filename):
        infile = open(filename, 'r')
        contents = infile.read()
        infile.close()
        return contents

    #Use temporary directory context to do this to avoid issues with spaces in filenames, etc.
    with mdtraj.utils.enter_temp_directory():
        local_input_filename = 'in.' + input_format
        shutil.copy( input_filename, local_input_filename )

        # Run antechamber.
        cmd = "antechamber -i %(local_input_filename)s -fi %(input_format)s -o out.mol2 -fo mol2 -s 2" % vars()
        if charge_method is not None:
            cmd += ' -c %s' % charge_method
        if net_charge is not None:
            cmd += ' -nc %d' % net_charge
        if resname:
            cmd += ' -rn %s' % molecule_name

        if log_debug_output: logger.debug(cmd)
        output = getoutput(cmd)
        if not os.path.exists('out.mol2'):
            msg  = "antechamber failed to produce output mol2 file\n"
            msg += "command: %s\n" % cmd
            msg += "output:\n"
            msg += 8 * "----------" + '\n'
            msg += output
            msg += 8 * "----------" + '\n'
            msg += "input mol2:\n"
            msg += 8 * "----------" + '\n'
            msg += read_file_contents(local_input_filename)
            msg += 8 * "----------" + '\n'
            raise Exception(msg)
        if log_debug_output: logger.debug(output)

        # Run parmchk.
        cmd = "parmchk2 -i out.mol2 -f mol2 -o out.frcmod"
        if log_debug_output: logger.debug(cmd)
        output = getoutput(cmd)
        if not os.path.exists('out.frcmod'):
            msg  = "parmchk2 failed to produce output frcmod file\n"
            msg += "command: %s\n" % cmd
            msg += "output:\n"
            msg += 8 * "----------" + '\n'
            msg += output
            msg += 8 * "----------" + '\n'
            msg += "input mol2:\n"
            msg += 8 * "----------" + '\n'
            msg += read_file_contents('out.mol2')
            msg += 8 * "----------" + '\n'
            raise Exception(msg)
        if log_debug_output: logger.debug(output)
        check_for_errors(output)

        #Copy back
        shutil.copy( 'out.mol2', gaff_mol2_filename )
        shutil.copy( 'out.frcmod', frcmod_filename )

    return gaff_mol2_filename, frcmod_filename
예제 #7
0
def do_solvate( top_filename, gro_filename, top_solv_filename, gro_solv_filename, box_dim, box_type, water_model, water_top, FF = 'amber99sb-ildn.ff' ):

    """ This function creates water solvated molecule coordinate files and its corresponding topology
        
        PARAMETERS:
            top_filename: str
                          Topology path/filename
            gro_filename: str
                          Coordinates path/filename
            top_solv_filename: str
                          Topology path/filename (solvated system)
            gro_solv_filename: str
                          Coordinates path/filename (solvated system)
            box_dim: float
                          cubic box dimension (nm); will be passed to GROMACS wiin .2f format
            box_type: str
                          box type (string passed to gmx solvate)
            water_model: str
                          Water model string to tell gmx solvate to use when solvating, i.e. "spc216"
            water_top: str
                          Water include file to ensure is present in topology file, i.e. "tip3p.itp"
            FF : str, optional, default = 'amber99sb-ildn.ff'
                          String specifying base force field directory for include files (i.e. 'amber99sb-ildn.ff').  

        NOTES:
        -----
        Primarily tested on 3 point water models. May need adjustment for other models.
"""

    #Setting up proper environment variables
    os.environ['GMX_MAXBACKUP'] = '-1' # Avoids unnecessary GROMACS backup files
    os.environ['GMX_NO_QUOTES'] = '1' # Supresses end-of-file quotes (gcq)

    #Get absolute paths for input/output
    top_filename = os.path.abspath( top_filename )
    gro_filename = os.path.abspath( gro_filename )
    top_solv_filename = os.path.abspath( top_solv_filename )
    gro_solv_filename = os.path.abspath( gro_solv_filename )

    with mdtraj.utils.enter_temp_directory(): #Work on hard coded filenames in temporary directory

        shutil.copy( gro_filename, 'in.gro' )
        shutil.copy( top_filename, 'out.top' )

        #string with the Gromacs 5.0.4 box generating commands
        cmdbox = 'gmx editconf -f in.gro -o out.gro -c -d %.2f -bt %s' % ( box_dim, box_type)
        output = getoutput(cmdbox)
        logger.debug(output)
        check_for_errors(output)

        #string with the Gromacs 5.0.4 solvation tool (it is not genbox anymore)
        cmdsolv = 'gmx solvate -cp out.gro -cs %s -o out.gro -p out.top' % (water_model)
        output = getoutput(cmdsolv)
        logger.debug(output)
        check_for_errors(output)

        #Insert Force Field specifications
        ensure_forcefield( 'out.top', 'out.top', FF = FF)

        #Insert line for water topology portion of the code
        try:
            file = open('out.top','r')
            text = file.readlines()
            file.close()
        except:
            raise NameError('The file out.top is missing' )

        #Insert water model
        wateritp = os.path.join(FF, water_top ) # e.g water_top = 'tip3p.itp'
        index = 0
        while '[ system ]' not in text[index]:
            index += 1
        text[index] = '#include "%s"\n\n' % wateritp + text[index]

        #Write the topology file
        try:
            file = open('out.top','w+')
            file.writelines( text )
            file.close()
        except:
            raise NameError('The file %s is missing' % 'out.top')

        #Check if file exist and is not empty;
        if os.stat( 'out.gro' ) == 0 or os.stat( 'out.top' ).st_size == 0:
            raise(ValueError("Solvent insertion failed"))

        #Copy back files
        shutil.copy( 'out.gro', gro_solv_filename )
        shutil.copy( 'out.top', top_solv_filename )

    return
예제 #8
0
def build_mixture_prmtop(mol2_filenames, frcmod_filenames, box_filename, prmtop_filename, inpcrd_filename, water_model = 'TIP3P'):
    """Create a prmtop and inpcrd from a collection of mol2 and frcmod files
    as well as a single box PDB.  We have used this for setting up
    simulations of neat liquids or binary mixtures.

    Parameters
    ----------
    mol2_filenames : list(str)
        Filenames of GAFF flavored mol2 files.  Each must contain exactly
        ONE ligand.
    frcmod_filenames : str
        Filename of input GAFF frcmod filenames.
    box_filename : str
        Filename of PDB containing an arbitrary box of the mol2 molecules.
    prmtop_filename : str
        output prmtop filename.  Should have suffix .prmtop
    inpcrd_filename : str
        output inpcrd filename.  Should have suffix .inpcrd
    water_model : str, optional. Default: "TIP3P"
        String specifying water model to be used IF water is present as a component of the mixture. Valid options are currently "TIP3P", "SPC", or None. If None is specified, flexible GAFF-water will be used as for any other solute (old behavior).

    Returns
    -------
    tleap_commands : str
        The string of commands piped to tleap for building the prmtop
        and inpcrd files.  This will *already* have been run, but the
        output can be useful for debugging or archival purposes. However,
        this will reflect temporary file names for both input and output
        file as these are used to avoid tleap filename restrictions.

    Notes
    -----
    This can be easily broken if there are missing, duplicated, or
    inconsistent ligand residue names in your box, mol2, and frcmod files.
    You can use mdtraj to edit the residue names with something like
    this: trj.top.residue(0).name = "L1"
    """

    # Check for one residue name per mol2 file and uniqueness between all mol2 files
    all_names = set()
    for filename in mol2_filenames:
        t = md.load(filename)
        names = set([r.name for r in t.top.residues])

        if len(names) != 1:
            raise(ValueError("Must have a SINGLE residue name in each mol2 file."))

        all_names = all_names.union(list(names))

    if len(all_names) != len(mol2_filenames):
        raise(ValueError("Must have UNIQUE residue names in each mol2 file."))
    if len(mol2_filenames) != len(frcmod_filenames):
        raise(ValueError("Must provide an equal number of frcmod and mol2 file names."))

    #Get number of files
    nfiles = len(mol2_filenames)

    #Check validity of water model options
    valid_water = ['TIP3P', 'SPC', None]
    if not water_model in valid_water:
        raise(ValueError("Must provide a valid water model."))

    #If we are requesting a different water model, check if there is water present
    if not water_model==None:
        parmed = import_("parmed")
        solventIsWater = []
        waterPresent = False
        for i in range(nfiles):
            mol = parmed.load_file( mol2_filenames[i] )
            #Check if it is water by checking GAFF atom names
            types = [ atom.type for atom in mol.atoms ]
            if 'oh' in types and types.count('ho')==2 and len(types)==3:
                solventIsWater.append(True)
                waterPresent = True
            else:
                solventIsWater.append(False)

        #In this case, if we have any water, we will now work on fewer .mol2 and .frcmod files and instead use the force field files for those. So, reduce nfiles and remove the files we don't need from the .mol2 and .frcmod filename lists
        #After doing so, go on to interpret the specified water model and compose the water model string needed for tleap
        if waterPresent:
            new_mol2_filenames = []
            new_frcmod_filenames = []
            water_mol2_filenames = []
            for i in range( nfiles ):
                if not solventIsWater[i]:
                    new_mol2_filenames.append( mol2_filenames[i] )
                    new_frcmod_filenames.append( frcmod_filenames[i] )
                else:
                    water_mol2_filenames.append( mol2_filenames[i] )
            nfiles = len(new_mol2_filenames)
            mol2_filenames = new_mol2_filenames
            frcmod_filenames = new_frcmod_filenames

            #Now interpret the specified water model and translate into AMBER nomenclature
            if water_model=='TIP3P':
                water_model = 'TP3'
            elif water_model =='SPC':
                water_model = 'SPC'
            else:
                raise(ValueError("Cannot translate specified water model into one of the available models."))


            #Compose string for loading specified water molecule
            water_string = '\n'
            water_names = [md.load(filename).top.residue(0).name for filename in water_mol2_filenames]
            for name in water_names:
                water_string += '%s = %s\n' % (name, water_model )
                #Also if not TIP3P, update to source correct frcmod file
                if water_model == 'SPC':
                    water_string += 'loadamberparams frcmod.spce\n'
                elif water_model =='TP3':
                    continue
                else:
                    raise(ValueError("Cannot identify water frcmod file to be loaded."))

            #Rename water atoms in box file to match what is expected by AMBER
            packmol = import_("openmoltools.packmol")
            packmol.rename_water_atoms(box_filename)
    else:
        waterPresent = False

    #Make temporary, hardcoded filenames for mol2 and frcmod input to avoid tleap filename restrictions
    tmp_mol2_filenames = [ 'in%d.mol2' % n for n in range(nfiles) ]
    tmp_frcmod_filenames = [ 'in%d.frcmod' % n for n in range(nfiles) ]

    #Make temporary, hardcoded filenames for output files to avoid tleap filename restrictions
    tmp_prmtop_filename = 'out.prmtop'
    tmp_inpcrd_filename = 'out.inpcrd'
    tmp_box_filename = 'tbox.pdb'

    #Build absolute paths of input files so we can use context and temporary directory
    infiles = mol2_filenames + frcmod_filenames + [box_filename]
    infiles = [ os.path.abspath(filenm) for filenm in infiles ]

    #Build absolute paths of output files so we can copy them back
    prmtop_filename = os.path.abspath( prmtop_filename )
    inpcrd_filename = os.path.abspath( inpcrd_filename )

    #Use temporary directory and do the setup
    with mdtraj.utils.enter_temp_directory():

        #Copy input files to temporary file names in target directory
        for (infile, outfile) in zip( infiles, tmp_mol2_filenames+tmp_frcmod_filenames+[tmp_box_filename] ):
            shutil.copy( infile, outfile)
            logger.debug('Copying input file %s to %s...\n' % (infile, outfile))


        all_names = [md.load(filename).top.residue(0).name for filename in tmp_mol2_filenames]

        mol2_section = "\n".join("%s = loadmol2 %s" % (all_names[k], filename) for k, filename in enumerate(tmp_mol2_filenames))
        #If non-GAFF water is present, load desired parameters for that water as well.
        if waterPresent:
            mol2_section += water_string
        amberparams_section = "\n".join("loadamberparams %s" % (filename) for k, filename in enumerate(tmp_frcmod_filenames))

        tleap_commands = TLEAP_TEMPLATE % dict(mol2_section=mol2_section, amberparams_section=amberparams_section, box_filename=tmp_box_filename, prmtop_filename=tmp_prmtop_filename, inpcrd_filename=tmp_inpcrd_filename)
        print(tleap_commands)

        file_handle = open('tleap_commands', 'w')
        file_handle.writelines(tleap_commands)
        file_handle.close()

        logger.debug('Running tleap in temporary directory.')
        cmd = "tleap -f %s " % file_handle.name
        logger.debug(cmd)

        output = getoutput(cmd)
        logger.debug(output)
        check_for_errors( output, other_errors = ['Improper number of arguments'], ignore_errors = ['unperturbed charge of the unit', 'ignoring the error'] )

        #Copy stuff back to right filenames
        for (tfile, finalfile) in zip( [tmp_prmtop_filename, tmp_inpcrd_filename], [prmtop_filename, inpcrd_filename] ):
            shutil.copy( tfile, finalfile)

    return tleap_commands
예제 #9
0
def run_tleap(molecule_name, gaff_mol2_filename, frcmod_filename, prmtop_filename=None, inpcrd_filename=None, log_debug_output=False):
    """Run AmberTools tleap to create simulation files for AMBER

    Parameters
    ----------
    molecule_name : str
        The name of the molecule
    gaff_mol2_filename : str
        GAFF format mol2 filename produced by antechamber
    frcmod_filename : str
        Amber frcmod file produced by prmchk
    prmtop_filename : str, optional, default=None
        Amber prmtop file produced by tleap, defaults to molecule_name
    inpcrd_filename : str, optional, default=None
        Amber inpcrd file produced by tleap, defaults to molecule_name
    log_debug_output : bool, optional, default=False
        If true, will send output of tleap to logger.

    Returns
    -------
    prmtop_filename : str
        Amber prmtop file produced by tleap
    inpcrd_filename : str
        Amber inpcrd file produced by tleap
    """
    if prmtop_filename is None:
        prmtop_filename = "%s.prmtop" % molecule_name
    if inpcrd_filename is None:
        inpcrd_filename = "%s.inpcrd" % molecule_name

    #Get absolute paths for input/output
    gaff_mol2_filename = os.path.abspath( gaff_mol2_filename )
    frcmod_filename = os.path.abspath( frcmod_filename )
    prmtop_filename = os.path.abspath( prmtop_filename )
    inpcrd_filename = os.path.abspath( inpcrd_filename )

    #Work in a temporary directory, on hard coded filenames, to avoid any issues AMBER may have with spaces and other special characters in filenames
    with mdtraj.utils.enter_temp_directory():
        shutil.copy( gaff_mol2_filename, 'file.mol2' )
        shutil.copy( frcmod_filename, 'file.frcmod' )

        tleap_input = """
    source oldff/leaprc.ff99SB
    source leaprc.gaff
    LIG = loadmol2 file.mol2
    check LIG
    loadamberparams file.frcmod
    saveamberparm LIG out.prmtop out.inpcrd
    quit

"""

        file_handle = open('tleap_commands', 'w')
        file_handle.writelines(tleap_input)
        file_handle.close()

        cmd = "tleap -f %s " % file_handle.name
        if log_debug_output: logger.debug(cmd)

        output = getoutput(cmd)
        if log_debug_output: logger.debug(output)

        check_for_errors( output, other_errors = ['Improper number of arguments'] )

        #Copy back target files
        shutil.copy( 'out.prmtop', prmtop_filename )
        shutil.copy( 'out.inpcrd', inpcrd_filename )

    return prmtop_filename, inpcrd_filename
예제 #10
0
def run_antechamber(molecule_name, input_filename, charge_method="bcc", net_charge=None, gaff_mol2_filename=None, frcmod_filename=None,
    input_format='mol2', resname=False, log_debug_output=False):
    """Run AmberTools antechamber and parmchk2 to create GAFF mol2 and frcmod files.

    Parameters
    ----------
    molecule_name : str
        Name of the molecule to be parameterized, will be used in output filenames.
    ligand_filename : str
        The molecule to be parameterized.  Must be tripos mol2 format.
    charge_method : str, optional
        If not None, the charge method string will be passed to Antechamber.
    net_charge : int, optional
        If not None, net charge of the molecule to be parameterized.
        If None, Antechamber sums up partial charges from the input file.
    gaff_mol2_filename : str, optional, default=None
        Name of GAFF mol2 filename to output.  If None, uses local directory
        and molecule_name
    frcmod_filename : str, optional, default=None
        Name of GAFF frcmod filename to output.  If None, uses local directory
        and molecule_name
    input_format : str, optional, default='mol2'
        Format specifier for input file to pass to antechamber.
    resname : bool, optional, default=False
        Set the residue name used within output files to molecule_name
    log_debug_output : bool, optional, default=False
        If true, will send output of tleap to logger.

    Returns
    -------
    gaff_mol2_filename : str
        GAFF format mol2 filename produced by antechamber
    frcmod_filename : str
        Amber frcmod file produced by prmchk
    """
    utils = import_("openmoltools.utils")
    ext = utils.parse_ligand_filename(input_filename)[1]

    if gaff_mol2_filename is None:
        gaff_mol2_filename = molecule_name + '.gaff.mol2'
    if frcmod_filename is None:
        frcmod_filename = molecule_name + '.frcmod'

    #Build absolute paths for input and output files
    gaff_mol2_filename = os.path.abspath( gaff_mol2_filename )
    frcmod_filename = os.path.abspath( frcmod_filename )
    input_filename = os.path.abspath( input_filename )

    def read_file_contents(filename):
        infile = open(filename, 'r')
        contents = infile.read()
        infile.close()
        return contents

    #Use temporary directory context to do this to avoid issues with spaces in filenames, etc.
    with mdtraj.utils.enter_temp_directory():
        local_input_filename = 'in.' + input_format
        shutil.copy( input_filename, local_input_filename )

        # Run antechamber.
        cmd = "antechamber -i %(local_input_filename)s -fi %(input_format)s -o out.mol2 -fo mol2 -s 2" % vars()
        if charge_method is not None:
            cmd += ' -c %s' % charge_method
        if net_charge is not None:
            cmd += ' -nc %d' % net_charge
        if resname:
            cmd += ' -rn %s' % molecule_name

        if log_debug_output: logger.debug(cmd)
        output = getoutput(cmd)
        if not os.path.exists('out.mol2'):
            msg  = "antechamber failed to produce output mol2 file\n"
            msg += "command: %s\n" % cmd
            msg += "output:\n"
            msg += 8 * "----------" + '\n'
            msg += output
            msg += 8 * "----------" + '\n'
            msg += "input mol2:\n"
            msg += 8 * "----------" + '\n'
            msg += read_file_contents(local_input_filename)
            msg += 8 * "----------" + '\n'
            raise Exception(msg)
        if log_debug_output: logger.debug(output)

        # Run parmchk.
        cmd = "parmchk2 -i out.mol2 -f mol2 -o out.frcmod"
        if log_debug_output: logger.debug(cmd)
        output = getoutput(cmd)
        if not os.path.exists('out.frcmod'):
            msg  = "parmchk2 failed to produce output frcmod file\n"
            msg += "command: %s\n" % cmd
            msg += "output:\n"
            msg += 8 * "----------" + '\n'
            msg += output
            msg += 8 * "----------" + '\n'
            msg += "input mol2:\n"
            msg += 8 * "----------" + '\n'
            msg += read_file_contents('out.mol2')
            msg += 8 * "----------" + '\n'
            raise Exception(msg)
        if log_debug_output: logger.debug(output)
        check_for_errors(output)

        #Copy back
        shutil.copy( 'out.mol2', gaff_mol2_filename )
        shutil.copy( 'out.frcmod', frcmod_filename )

    return gaff_mol2_filename, frcmod_filename
예제 #11
0
def build_mixture_prmtop(mol2_filenames, frcmod_filenames, box_filename,
                         prmtop_filename, inpcrd_filename):
    """Create a prmtop and inpcrd from a collection of mol2 and frcmod files as well as a single box PDB.  
    We have used this for setting up simulations of binary mixtures.
    - Original code by : Chodera Lab / Openmoltools project (https://github.com/choderalab/openmoltools)

    Parameters
    ----------
    mol2_filenames : list(str)
        Filenames of GAFF flavored mol2 files.  Each must contain exactly
        ONE ligand.
    frcmod_filenames : str
        Filename of input GAFF frcmod filenames.
    box_filename : str
        Filename of PDB containing an arbitrary box of the mol2 molecules.
    prmtop_filename : str
        output prmtop filename.  Should have suffix .prmtop
    inpcrd_filename : str
        output inpcrd filename.  Should have suffix .inpcrd
    water_model : str, optional. Default: "TIP3P"
        String specifying water model to be used IF water is present as a component of the mixture. Valid options are currently "TIP3P", "SPC", or None. If None is specified, flexible GAFF-water will be used as for any other solute (old behavior).
    Returns
    -------
    tleap_commands : str
        The string of commands piped to tleap for building the prmtop
        and inpcrd files.  This will *already* have been run, but the
        output can be useful for debugging or archival purposes. However,
        this will reflect temporary file names for both input and output
        file as these are used to avoid tleap filename restrictions.
    Notes
    -----
    This can be easily broken if there are missing, duplicated, or
    inconsistent ligand residue names in your box, mol2, and frcmod files.
    You can use mdtraj to edit the residue names with something like
    this: trj.top.residue(0).name = "L1"
    """

    # Check for one residue name per mol2 file and uniqueness between all mol2 files
    all_names = set()
    for filename in mol2_filenames:
        t = md.load(filename)
        names = set([r.name for r in t.top.residues])

        if len(names) != 1:
            raise (ValueError(
                "Must have a SINGLE residue name in each mol2 file."))

        all_names = all_names.union(list(names))

    if len(all_names) != len(mol2_filenames):
        raise (ValueError("Must have UNIQUE residue names in each mol2 file."))
    if len(mol2_filenames) != len(frcmod_filenames):
        raise (ValueError(
            "Must provide an equal number of frcmod and mol2 file names."))

    #Get number of files
    nfiles = len(mol2_filenames)

    #Build absolute paths of input files so we can use context and temporary directory
    infiles = mol2_filenames + frcmod_filenames + [box_filename]
    infiles = [os.path.abspath(filenm) for filenm in infiles]

    #Build absolute paths of output files so we can copy them back
    prmtop_filename = os.path.abspath(prmtop_filename)
    inpcrd_filename = os.path.abspath(inpcrd_filename)

    #Use temporary directory and do the setup
    with md.utils.enter_temp_directory():
        all_names = [
            md.load(filename).top.residue(0).name
            for filename in mol2_filenames
        ]

        mol2_section = "\n".join("%s = loadmol2 %s" % (all_names[k], filename)
                                 for k, filename in enumerate(mol2_filenames))

        amberparams_section = "\n".join(
            "loadamberparams %s" % (filename)
            for k, filename in enumerate(frcmod_filenames))

        tleap_commands = TLEAP_TEMPLATE % dict(
            mol2_section=mol2_section,
            amberparams_section=amberparams_section,
            box_filename=box_filename,
            prmtop_filename=prmtop_filename,
            inpcrd_filename=inpcrd_filename)
        print(tleap_commands)

        file_handle = open('tleap_commands', 'w')
        file_handle.writelines(tleap_commands)
        file_handle.close()

        logger.debug('Running tleap in temporary directory.')
        cmd = "tleap -f %s " % file_handle.name
        logger.debug(cmd)

        output = getoutput(cmd)
        logger.debug(output)

    return tleap_commands