Esempio n. 1
0
def add_ions(neutral=True, conc=0, pname='NA', nname='CL'):
    if (not neutral) and (conc == 0):
        utils.update("add_ions", "no ions will be added...")
        return

    if neutral:
        utils.update("add_ions", "will add ions ({}/{}) to neutralize the system...".format(pname, nname))

    if conc > 0:
        utils.update("add_ions", "will add ions ({}/{}) for target concentration = {} mmol/ml...".format(pname, nname, conc))

    # Generate IONS.mdp (just a dummy required).
    os.system('touch IONS.mdp')

    # Add ion topology to topol.top.
    topol.add_mol("{0}.ff/ions.itp".format(universe.get('d_modelFF')), "Include ion topology")

    # Run gmx grompp and genion.
    utils.update("add_ions", "running gmx grompp and genion to add ions...")

    os.system("gmx grompp -f IONS.mdp -c {0} -p topol.top -o IONS.tpr >> builder.log 2>&1".format(universe.get('d_nameList')[-1]))

    if neutral:
        os.system("gmx genion -s IONS.tpr -o {0}_ION.pdb -p topol.top -pname {1} -nname {2} -conc {3} -neutral >> builder.log 2>&1 << EOF\nSOL\nEOF".format(universe.get('d_pdbName'), pname, nname, conc))
    else:
        os.system("gmx genion -s IONS.tpr -o {0}_ION.pdb -p topol.top -pname {1} -nname {2} -conc {3} >> builder.log 2>&1 << EOF\nSOL\nEOF".format(universe.get('d_pdbName'), pname, nname, conc))

    # To update d_residues.
    load("{0}_ION.pdb".format(universe.get('d_pdbName')))

    # To update d_nameList.
    utils.add_to_nameList("{0}_ION.pdb".format(universe.get('d_pdbName')))
Esempio n. 2
0
def write(name):
    with open(name, 'w') as file:
        if universe.has('d_title'):
            file.write("TITLE {0}\n".format(universe.get('d_title')))

        if universe.has('d_box'):
            file.write("CRYST1{0}\n".format(universe.get('d_box')))

        file.write("MODEL {:8d}\n".format(universe.get('d_model')))

        atomNumber = 1
        for residue in universe.get('d_residues'):
            for idx in range(0, len(residue.d_atoms)):
                file.write(
                    "{:6s}{:5d} {:^4s}{:1s}{:4s}{:1s}{:4d}{:1s}   {:8.3f}{:8.3f}{:8.3f}\n"
                    .format('ATOM', atomNumber, residue.d_atoms[idx],
                            residue.d_ali[idx], residue.d_resname,
                            residue.d_chain, residue.d_resid, '',
                            residue.d_x[idx], residue.d_y[idx],
                            residue.d_z[idx]))
                atomNumber += 1

        file.write("TER\nENDMDL\n")

    utils.add_to_nameList(name)
Esempio n. 3
0
def energy_minimize():
    gen_mdp('EM')

    utils.update("energy_minimize",
                 "running gmx grompp and mdrun for energy minimization...")

    os.system(
        "gmx grompp -f EM.mdp -c {0} -p topol.top -o EM.tpr -r {0} >> builder.log 2>&1"
        .format(universe.get('d_nameList')[-1]))
    os.system("gmx mdrun -deffnm EM -c EM.pdb >> builder.log 2>&1")

    utils.add_to_nameList("EM.pdb")
Esempio n. 4
0
def energy_pcouple():
    gen_mdp('NPT')

    utils.update("energy_pcouple",
                 "running gmx grompp and mdrun for pressure coupling...")

    os.system(
        "gmx grompp -f NPT.mdp -c {0} -p topol.top -o NPT.tpr -r {0} >> builder.log 2>&1"
        .format(universe.get('d_nameList')[-1]))
    os.system("gmx mdrun -deffnm NPT -c NPT.pdb >> builder.log 2>&1")

    utils.add_to_nameList("NPT.pdb")
Esempio n. 5
0
def add_water():
    utils.update("add_water", "running gmx solvate...")
    
    os.system("gmx solvate -cp {0} -o {1}_SOL.pdb >> builder.log 2>&1".format(universe.get('d_nameList')[-1], universe.get('d_pdbName')))

    # To update d_residues.
    load("{0}_SOL.pdb".format(universe.get('d_pdbName')))

    # To update topol.top.
    topol.add_mol("{0}.ff/{1}.itp".format(universe.get('d_modelFF'), universe.get('d_modelWater')), "Include water topology", "SOL", countRes('SOL'))

    # To update d_nameList.
    utils.add_to_nameList("{0}_SOL.pdb".format(universe.get('d_pdbName')))
Esempio n. 6
0
def energy_tcouple():
    gen_mdp('NVT')

    utils.update("energy_tcouple",
                 "running gmx grompp and mdrun for temperature coupling...")

    os.system(
        "gmx grompp -f NVT.mdp -c {0} -p topol.top -o NVT.tpr -r {0} >> builder.log 2>&1"
        .format(universe.get('d_nameList')[-1]))
    os.system(
        "gmx mdrun -deffnm NVT -c {0}_NVT.pdb >> builder.log 2>&1".format(
            universe.get('d_pdbName')))

    utils.add_to_nameList("{0}_NVT.pdb".format(universe.get('d_pdbName')))
Esempio n. 7
0
def add_box(d_boxMargin, d_boxType='cubic'):
    utils.update("add_box", "adding box using gmx editconf (boxMargin = {0}, boxType = {1})...".format(d_boxMargin, d_boxType))

    os.system("gmx editconf -f {0} -o {1}_BOX.pdb -d {2} -bt {3} >> builder.log 2>&1".format(universe.get('d_nameList')[-1], universe.get('d_pdbName'), d_boxMargin, d_boxType))

    # To set d_boxMargin and d_boxType.
    universe.add('d_boxMargin', d_boxMargin)
    universe.add('d_boxType', d_boxType)

    # To update d_box.
    load("{0}_BOX.pdb".format(universe.get('d_pdbName')))

    # To update d_nameList.
    utils.add_to_nameList("{0}_BOX.pdb".format(universe.get('d_pdbName')))
Esempio n. 8
0
def add_buffer(ph_bufpdbName, ph_bufitpName, ph_bufMargin=2.0, ph_bufnmol=-1, attempts=100000):
    if not (universe.get('ph_constantpH') and universe.get('ph_restrainpH')):
        utils.update("add_buffer", "either ph_constantpH or ph_restrainpH is False --> skipping...")
        return

    # If user doesn't specified the amount, use #BUF = #ACID.
    if (ph_bufnmol == -1):
        ph_bufnmol = countRes('ASP') + countRes('GLU')

    utils.update("add_buffer", "will attempt to add {0} buffer molecule(s)...".format(ph_bufnmol))

    # RUN GROMACS INSERT-MOLECULES COMMAND
    os.system("touch vdwradii.dat") # we need this dummy file for this to work.

    os.system("gmx insert-molecules -f {0} -o {1}_BUF.pdb -ci {2} -nmol {3} -scale 1.0 -radius {4} -try {5} >> builder.log 2>&1".format(
        universe.get('d_nameList')[-1],
        universe.get('d_pdbName'),
        ph_bufpdbName,
        ph_bufnmol,
        0.5 * ph_bufMargin,
        int(attempts / ph_bufnmol)))

    os.remove("vdwradii.dat") # clean dummy file.

    # To update d_residues.
    load("{0}_BUF.pdb".format(universe.get('d_pdbName')))    

    # Give user a warning if there wasn't enough space.
    actual = countRes('BUF')
    if actual < ph_bufnmol:
        utils.update("add_buffer", "warning: only {0}/{1} requested buffer molecules inserted after {2} attempts,".format(actual, ph_bufnmol, attempts))
        utils.update("add_buffer", "warning: try decreasing ph_bufMargin (={0}nm) or increasing d_boxMargin (={1}nm)...".format(ph_bufMargin, universe.get('d_boxMargin')))
    else:
        utils.update("add_buffer", "succesfully added {0} buffer molecule(s)...".format(actual))

    # To add buffer topology to topol.top.
    utils.update("add_buffer", "updating topology...")
    os.system("cp {} .".format(ph_bufitpName))
    topol.add_mol(os.path.basename(ph_bufitpName), "Include buffer topology", 'BUF', actual)

    # Set some parameters in the universe.
    universe.add('ph_bufpdbName', ph_bufpdbName)
    universe.add('ph_bufitpName', ph_bufitpName)
    universe.add('ph_bufMargin', ph_bufMargin)
    universe.add('ph_bufnmol', actual)

    # To update d_nameList.
    utils.add_to_nameList("{0}_BUF.pdb".format(universe.get('d_pdbName')))
Esempio n. 9
0
def generate(d_modelFF, d_modelWater, d_terministring="", d_customitp=""):
    # Internal helper function.
    def rebuild_topol():
        # If we have only one chain, gromacs will put everything in topol.top.
        # If we have more than one chain, gromacs will do it for us.
        if (len(universe.get('d_chain')) <= 1):
            readingProtein = False
            
            file = open("topol_Protein_chain_A.itp", 'w')

            for line in open("topol.top").readlines():
                if (not readingProtein and line == "[ moleculetype ]\n"):
                    readingProtein = True
            
                if (readingProtein and line == "; Include water topology\n"):
                    readingProtein = False

                if (readingProtein):
                    file.write(line)
    
            file.close()
    
        with open('topol.top', 'w') as file:
            file.write("; Include forcefield parameters\n")
            file.write("#include \"{0}.ff/forcefield.itp\"\n\n".format(universe.get('d_modelFF')))

            file.write("; Include protein topology\n")
            for letter in universe.get('d_chain'):
                file.write("#include \"topol_Protein_chain_{0}.itp\"\n".format(letter))
            file.write('\n')

            file.write('[ system ]\n')
            file.write('{0}\n\n'.format(universe.get('d_pdbName')))

            file.write('[ molecules ]\n')
            file.write('; Compounts \t\t #mols\n')
            for letter in universe.get('d_chain'):
                file.write("Protein_chain_{0}\t\t1\n".format(letter))

    # ADD RELEVANT PARAMETERS TO UNIVERSE ######################################
    universe.add('d_modelFF', d_modelFF)
    universe.add('d_modelWater', d_modelWater)
    universe.add('d_terministring', d_terministring)

    # USER UPDATE STUFF ########################################################
    countACID = protein.countRes("ASP") + protein.countRes("GLU")

    # If constant-pH is on,
    if universe.get('ph_constantpH'):
        utils.update("generate", 'constant-pH is turned on...')
        
        # and we have at least one protonatable reside,
        if countACID > 0:
            utils.update("generate", "detected {} acidic residue(s):".format(countACID))

            for letter in universe.get('d_chain'):
                count = 1

                for residue in universe.get('d_residues'):
                    if residue.d_chain == letter:
                        count += 1

                        if residue.d_resname in ['ASP', 'GLU']:
                            utils.update("generate", "{:3s}-{:<4d} in chain {}".format(residue.d_resname, count, letter))

            utils.update("generate", "(setting protonation state to true (option 1) for all of these)")

        else:
            utils.update("generate", "no acidic residues detected, constant-pH is turned off...")
            universe.add('ph_constantpH', False)
            universe.add('ph_restrainpH', False)

    else:
        utils.update("generate", 'constant-pH is turned off...')
        universe.add('ph_restrainpH', False) # If ph_constantpH is False then this is also False.

    utils.update("generate", "using the {} force field with the {} water model...".format(d_modelFF, d_modelWater))

    # CREATE EOFSTRING FOR PDB2GMX COMMAND #####################################

    # Here we create EOFstring to circumvent pd2gmx prompting for user input.
    xstr = "<< EOF"
    # The for-loop sets the protonation state of all GLUs and ASPs to 1
    # (True) if ph_constantpH is True, and to 0 (False) if ph_constantpH is False.
    for chain in universe.get('d_chain'):
        for residue in universe.get('d_residues'):
            if residue.d_resname in ['ASP', 'GLU'] and residue.d_chain == chain:
                xstr += "\n{:d}".format(universe.get('ph_constantpH'))
        
        # Furthermore, if the user specified a two-letter string for the termini,
        # add those to the EOFstring as well:
        if (d_terministring != ""):
            xstr += "\n{}".format(d_terministring[0])
            xstr += "\n{}".format(d_terministring[1])
    # End EOFstring:
    xstr += "\nEOF"
    # print(xstr) # Debug

    # UPDATE USER ABOUT WHAT WE DO WITH THE TERMINI ############################

    if (d_terministring != ""):
        utils.update("generate", "Using options {} for termini...".format(d_terministring))
    else:
        utils.update("generate", "No termini specified, using gmx default (00 = NH3+ and COO-)...")
    
    utils.update("generate", "running pdb2gmx to create {}_PR2.pdb and topol.top...".format(universe.get('d_pdbName')))

    # RUN ACTUAL PDB2GMX COMMAND ###############################################

    if (d_terministring != ""):
        os.system("gmx pdb2gmx -f {0} -o {1}_PR2.pdb -asp -glu -ignh -ff {2} -water {3} -ter >> builder.log 2>&1 {4}".format(universe.get('d_nameList')[-1], universe.get('d_pdbName'), d_modelFF, d_modelWater, xstr))
    else:
        os.system("gmx pdb2gmx -f {0} -o {1}_PR2.pdb -asp -glu -ignh -ff {2} -water {3} >> builder.log 2>&1 {4}".format(universe.get('d_nameList')[-1], universe.get('d_pdbName'), d_modelFF, d_modelWater, xstr))

    # Rebuild topology.
    rebuild_topol()

    # Use custom topol_Protein_chain_A.itp (this is a temporary fix for charmm36-mar2019-m4)
    if (d_customitp != ""):
        utils.update("generate", "Overwriting topol_Protein_chain_A.itp generated by pdb2gmx with {}...".format(d_customitp))
        os.system("cp {} .".format(d_customitp))

    # To update d_residues.
    protein.load("{0}_PR2.pdb".format(universe.get('d_pdbName')))

    # To update d_nameList.
    utils.add_to_nameList("{0}_PR2.pdb".format(universe.get('d_pdbName')))
Esempio n. 10
0
def add_buffer(ph_bufpdbName="",
               ph_bufitpName="",
               ph_bufqqA=[1],
               ph_bufqqB=[0],
               ph_bufMargin=2.5,
               attempts=100000):
    # This function writes a dummy .pdb containing the default buffer (ion).
    def writeDefaultPDB():
        with open("defaultBuffer.pdb", 'w') as file:
            file.write("TITLE     BUFFER PARTICLE\n")
            file.write("MODEL        1\n")
            file.write(
                "ATOM      1  NA  BUF     1     110.896   2.872  68.855  1.00  0.00            \n"
            )
            file.write("TER\n")
            file.write("ENDMDL\n")

    # This function writes the topology for the default buffer (ion).
    # Note: charge should not be 0 because then some interactions are not generated???
    # Update: this was fixed by Berk in e2c2340.
    def writeDefaultITP():
        with open("defaultBuffer.itp", 'w') as file:
            file.write("[ moleculetype ]\n")
            file.write("; molname	nrexcl\n")
            file.write("BUF		1\n\n")
            file.write("[ atoms ]\n")
            file.write(
                "; id	at type		res nr	residu name at name  cg nr	charge	 \n")
            file.write("1		SOD			1		   BUF			NA		   1		0	 \n\n")
            file.write("#ifdef POSRES_BUF\n")
            file.write("; Position restraint for each buffer ion\n")
            file.write("[ position_restraints ]\n")
            file.write(";  i funct       fcx        fcy        fcz\n")
            file.write("   1    1       1000       1000       1000\n")
            file.write("#endif\n")

    # Skip this whole step if we don't need it.
    if not (universe.get('ph_constantpH')
            and universe.get('ph_QQleveling') in [1, 2]):
        utils.update(
            "add_buffer",
            "either ph_constantpH is False or ph_QQleveling = 0 --> skipping..."
        )
        return

    # Make sure that the sum of the charges in state A and B are correct.
    if (sum(ph_bufqqA) != 1 or sum(ph_bufqqB) != 0):
        utils.warning(
            "add_buffer",
            "buffer charges incorrectly specified! sums must be 1 and 0")
        universe.get('ph_bufqqA')
        universe.get('ph_bufqqB')

    # Determine whether we use the default or a custom buffer.
    useDefault = False
    if (ph_bufpdbName == "" and ph_bufitpName == ""):
        utils.update("add_buffer", "using default (built-in) buffer...")
        useDefault = True
    elif (ph_bufpdbName == "" and ph_bufitpName != ""):
        utils.warning(
            "add_buffer",
            "ph_bufitpName not specified, resorting to default buffer!")
        useDefault = True
    elif (ph_bufpdbName != "" and ph_bufitpName == ""):
        utils.warning(
            "add_buffer",
            "ph_bufpdbName not specified, resorting to default buffer!")
        useDefault = True
    else:
        utils.update("add_buffer", "using custom buffer...")

    if (useDefault):
        # Check to make sure that the charges for the default buffer are correct.
        if (ph_bufqqA != [1] or ph_bufqqB != [0]):
            utils.warning(
                "add_buffer",
                "buffer charges incorrectly specified for default buffer!")
            universe.get('ph_bufqqA')
            universe.get('ph_bufqqB')

        # Generate the files for the default buffer and update data members.
        writeDefaultPDB()
        ph_bufpdbName = "defaultBuffer.pdb"
        writeDefaultITP()
        ph_bufitpName = "defaultBuffer.itp"

    # Get the number of buffer molecules we need.
    ph_bufnmol = 0
    for lambdaType in universe.get('ph_lambdaTypes'):
        ph_bufnmol += countRes(lambdaType.d_resname)

    utils.update(
        "add_buffer",
        "will attempt to add {0} buffer molecule(s)...".format(ph_bufnmol))

    # RUN GROMACS INSERT-MOLECULES COMMAND
    os.system(
        "touch vdwradii.dat")  # we need this dummy file for this to work.

    os.system(
        "gmx insert-molecules -f {0} -o {1}_BUF.pdb -ci {2} -nmol {3} -scale 1.0 -radius {4} -try {5} >> builder.log 2>&1"
        .format(
            universe.get('d_nameList')[-1], universe.get('d_pdbName'),
            ph_bufpdbName, ph_bufnmol, 0.5 * ph_bufMargin,
            int(attempts / ph_bufnmol)))

    os.remove("vdwradii.dat")  # clean dummy file.

    # To update d_residues.
    load("{0}_BUF.pdb".format(universe.get('d_pdbName')))

    # Give user a warning if there wasn't enough space.
    actual = countRes('BUF')
    if actual < ph_bufnmol:
        utils.warning(
            "add_buffer",
            "only {0}/{1} requested buffer molecules inserted after {2} attempts,"
            .format(actual, ph_bufnmol, attempts))
        utils.warning(
            "add_buffer",
            "try decreasing ph_bufMargin (={0}nm) or increasing d_boxMargin (={1}nm)..."
            .format(ph_bufMargin, universe.get('d_boxMargin')))
    else:
        utils.update(
            "add_buffer",
            "succesfully added {0} buffer molecule(s)...".format(actual))

    # To add buffer topology to topol.top.
    utils.update("add_buffer", "updating topology...")

    if (useDefault):
        os.remove("defaultBuffer.pdb")  # Remove dummy .pdb file.
    else:
        os.system("cp {} .".format(ph_bufitpName))  # Copy to working dir.

    topol.add_mol(os.path.basename(ph_bufitpName), "Include buffer topology",
                  'BUF', actual)

    # Set some parameters in the universe.
    universe.add('ph_bufpdbName', ph_bufpdbName)
    universe.add('ph_bufitpName', ph_bufitpName)
    universe.add('ph_bufqqA', ph_bufqqA)
    universe.add('ph_bufqqB', ph_bufqqB)
    universe.add('ph_bufMargin', ph_bufMargin)
    universe.add('ph_bufnmol', actual)

    # To update d_nameList.
    utils.add_to_nameList("{0}_BUF.pdb".format(universe.get('d_pdbName')))