Beispiel #1
0
def assignWaterResidue(bgf_file, out_file, silent=True):

    mybgf = bgf.BgfFile(bgf_file)

    for atom in mybgf.a:
        for i in bgftools.is_water(mybgf, atom.aNo):
            mybgf.getAtom(i).rName = "WAT"

    mybgf.saveBGF(out_file)
Beispiel #2
0
def removebadcontacts(bgf_file, out_file, thresh, silent=True):

    if isinstance(bgf_file, bgf.BgfFile):
        myBGF = bgf_file
    else:
        if not silent:
            print(sys.argv[0] + ": Removing bad contacts from " + bgf_file +
                  " with distance threshold " + str(thresh) +
                  " A and saving to " + out_file + ".")
        myBGF = bgf.BgfFile(bgf_file)

    delete_list = []

    if not silent:
        print("removeBadContacts will remove water molecules within " +
              str(thresh) + " Angstrom from the solute.")
    for solute_aNo in bgftools.listSoluteAtoms(myBGF):
        solute = myBGF.getAtom(solute_aNo)
        for oxygen_aNo in bgftools.listOxygenAtoms(myBGF):
            water = bgftools.is_water(myBGF, oxygen_aNo)
            if water != [] or type(water) != NoneType:
                if len(water) == 3:  # if water is a water molecule,
                    # calculate the distance between solute atoms and the molecule
                    O = myBGF.getAtom(water[0])
                    H1 = myBGF.getAtom(water[1])
                    H2 = myBGF.getAtom(water[2])
                    dist_O_sol = bgf.distance(solute, O)
                    dist_H1_sol = bgf.distance(solute, H1)
                    dist_H2_sol = bgf.distance(solute, H2)
                    if dist_O_sol < thresh or dist_H1_sol < thresh or dist_H2_sol < thresh:
                        if oxygen_aNo not in delete_list:
                            delete_list.append(oxygen_aNo)
                            delete_list.sort()
                        ##if water not in delete_list:
                        ##delete_list.append(water)

    if delete_list != []:
        delete_list.reverse()  # reverse sort for delAtoms
        for oxygen_index in delete_list:
            bgftools.deleteWaterAtoms(myBGF, oxygen_index)
        myBGF.renumber()

        if not silent:
            print("removeBadContacts: " + str(len(delete_list)) +
                  " water molecules are removed.")
    else:
        if not silent:
            print(
                "There are no water molecules that corresponds to the criteria."
            )

    if isinstance(out_file, bgf.BgfFile):
        return myBGF
    else:
        myBGF.saveBGF(out_file)
        return 1
Beispiel #3
0
def addsolvent(bgf_file,
               solvent_bgf,
               size,
               margin,
               out_file,
               ff_file,
               silent=True):

    ### initialize
    water = False

    ### load the solute bgf file
    if not silent: print("Initializing..")
    myBGF = bgf.BgfFile(bgf_file)  # str

    #solventBGF = bgf.BgfFile("/home/noische/scripts/dat/WAT/f3c_box.bgf")	# F3C waterbox
    if not silent: print("Loading the solvent file " + solvent_bgf + " ..")
    solventBGF = bgf.BgfFile(solvent_bgf)

    ### Generate error when the solvent box is not periodic:
    if not solventBGF.PERIOD:
        nu.die(
            "addSolvent: The solvent file is not periodic. Use a box full of solvent."
        )

    ### Check the type of solvent
    if not silent:
        print("(the solvent box seems to be full of " +
              os.path.basename(solvent_file)[:-4] + " )")
    if "f3c" in solvent_bgf:
        water = True  # this flag is used to remove the bad contacts with the molecule.
    if "spc" in solvent_bgf:
        water = True  # this flag is used to remove the bad contacts with the molecule.
    if "tip" in solvent_bgf:
        water = True  # this flag is used to remove the bad contacts with the molecule.

    ### calculate the box size
    if not silent: print("Analyzing box information..")
    if len(myBGF.CRYSTX) > 2:
        strsize = [myBGF.CRYSTX[0], myBGF.CRYSTX[1], myBGF.CRYSTX[2]]
    else:
        box = bgf.getBGFSize(myBGF, 0)  # [xlo, xhi, ylo, yhi, zlo, zhi]
        strsize = [box[1] - box[0], box[3] - box[2], box[5] - box[4]]

    ###
    if size == "" and margin != "":
        strsize = [
            strsize[0] + 2 * margin[0], strsize[1] + 2 * margin[1],
            strsize[2] + 2 * margin[2]
        ]  # add margin on str size
    elif size != "" and margin == "":
        strsize = size

    waterboxsize = solventBGF.CRYSTX[:3]  # REMARK: This is a kind of constant.
    copyNumber = [0, 0, 0]
    for index, i in enumerate(copyNumber):
        copyNumber[index] = math.ceil(
            strsize[index] /
            waterboxsize[index])  # how many times to replicate the water box

    if not silent: print("Creating box information: " + str(strsize))

    ### replicate the solvent box
    bigboxBGF = bgftools.replicateCell(solventBGF, copyNumber, True)
    bigboxBGF.saveBGF("_replicate.bgf")
    if not silent:
        print("- Number of atoms in the created box: " + str(len(bigboxBGF.a)))

    ### trim the water box
    if water:
        if not silent:
            print("Generating water box.. Calculating water molecules")
        delatom = []
        delwater = []
        delwaterindex = []
        for atom in bigboxBGF.a:
            if atom.x > strsize[0] or atom.y > strsize[1] or atom.z > strsize[
                    2]:
                delatom.append(atom.aNo)
        for aNo in delatom:
            water_molecule = bgftools.is_water(bigboxBGF, aNo)
            if not water_molecule in delwater:
                delwater.append(water_molecule)
        delwater = nu.flatten(delwater)
        delwater = nu.removeRepeat(delwater)
        delwater.sort()
        delwater.reverse()
        for aNo in delwater:
            delwaterindex.append(bigboxBGF.getAtomIndex(aNo))
        del (delwater)
        if not silent: print("Generating water box.. Trimming")
        bigboxBGF.delAtoms(delwaterindex, False)
        bigboxBGF.renumber()
    elif not water:
        if not silent:
            print("Generating solvent box.. Extracting solvent molecules")
        delatom = []
        delsolvent = []
        delsolventindex = []
        for atom in bigboxBGF.a:
            if atom.x > strsize[0] or atom.y > strsize[1] or atom.z > strsize[
                    2]:
                delatom.append(atom.aNo)
        for aNo in delatom:
            molecule_list = []
            molecule = bgftools.getmolecule(bigboxBGF, bigboxBGF.getAtom(aNo),
                                            molecule_list)
            for number in molecule_list:
                if not number in delsolvent: delsolvent.append(number)
        delsolvent = nu.flatten(delsolvent)
        delsolvent = nu.removeRepeat(delsolvent)
        delsolvent.sort()
        delsolvent.reverse()
        for aNo in delsolvent:
            delsolventindex.append(bigboxBGF.getAtomIndex(aNo))
        if not silent: print("Generating solvent box.. Trimming")
        bigboxBGF.delAtoms(delsolventindex, False)
        bigboxBGF.renumber()

    ### merge two structure
    # REMARK: it is natural to have the periodic information of water box for the output BGF file.
    # REMARK: HETATOM should be located on the first of the BGF file. So use dummy for merging.
    if not silent: print("\nAdding trimmed solvent box to the structure..")
    bigboxcenter = [strsize[0] / 2, strsize[1] / 2, strsize[2] / 2]
    a, b, c = bgftools.getCom(myBGF, ff_file)
    bgf.moveBGF(myBGF, bigboxcenter[0] - a, bigboxcenter[1] - b,
                bigboxcenter[2] - c)

    ## remove bad contacts between solutes and solvents
    if not silent: print("Atom distance calculation for contacts..")
    delatom = []
    delsolvent = []
    delsolventindex = []
    for atom1 in myBGF.a:
        for atom2 in bigboxBGF.a:
            # if the distance between atom1 and atom2 is less than 2.8, add to a delete list
            dist_sq = (atom1.x - atom2.x)**2 + (atom1.y - atom2.y)**2 + (
                atom1.z - atom2.z)**2
            if dist_sq < 7.84:
                delatom.append(atom2.aNo)

    # delete bad atoms!
    if not silent: print("Removing bad contacts..")
    for aNo in delatom:
        molecule_list = []
        molecule = bgftools.getmolecule(bigboxBGF, bigboxBGF.getAtom(aNo),
                                        molecule_list)
        for number in molecule_list:
            if not number in delsolvent: delsolvent.append(number)
    delsolvent = nu.flatten(delsolvent)
    delsolvent = nu.removeRepeat(delsolvent)
    delsolvent.sort()
    delsolvent.reverse()
    for aNo in delsolvent:
        delsolventindex.append(bigboxBGF.getAtomIndex(aNo))
    bigboxBGF.delAtoms(delsolventindex, False)
    bigboxBGF.renumber()

    ## compute stats for adding solvents
    if not silent: print("\nComputing stats..")
    mol_list = bgftools.getMoleculeList(bigboxBGF)
    n_mol = len(mol_list)
    n_atom = len(nu.flatten(mol_list))
    if not silent:
        print(
            str(n_mol) + " molecules (" + str(n_atom) +
            " atoms) will be added.")

    ## merge
    bigboxBGF = myBGF.merge(bigboxBGF, True)
    if not silent: print("Total atoms in the file: " + str(len(bigboxBGF.a)))

    ## some paperworking for periodic box
    bigboxBGF.OTHER = solventBGF.OTHER
    bigboxBGF.PERIOD = solventBGF.PERIOD
    bigboxBGF.AXES = solventBGF.AXES
    bigboxBGF.SGNAME = solventBGF.SGNAME
    bigboxBGF.CRYSTX = solventBGF.CRYSTX
    bigboxBGF.CELLS = solventBGF.CELLS

    ## adjust the size of the box
    bigboxBGF.CRYSTX = [
        strsize[0], strsize[1], strsize[2], solventBGF.CRYSTX[3],
        solventBGF.CRYSTX[4], solventBGF.CRYSTX[5]
    ]
    """
	### remove bad contacts and save
	if water:
		if not silent: print("Removing bad contacts: distance criteria is 2.8 A")
		bigboxBGF = removebadcontacts(bigboxBGF, bigboxBGF, 2.8)

		### renumber residue numbers
		# RULE: all rNos for water molecules will be renumbered from 2. (for createLammpsInput.pl)
		if not silent: print("Renumbering water molecules..")
		max_rNo_in_hetatm = 0;
		oxygen_list = bgftools.listOxygenAtoms(bigboxBGF)
	
		### find the biggest rNo among HETATM
		for atom in bigboxBGF.a:
			if atom.aTag == 1:
				if max_rNo_in_hetatm < atom.rNo: max_rNo_in_hetatm = atom.rNo
	
		### update rNo in water molecules
		rNo_for_water = max_rNo_in_hetatm + 500;
		for aNo in oxygen_list:
			water_aNo = bgftools.is_water(bigboxBGF, aNo)	# get aNo in a water molecule by checking the oxygen atom
			if water_aNo != []:
				for atom_aNo in water_aNo:
					bigboxBGF.getAtom(atom_aNo).rNo = rNo_for_water
				rNo_for_water += 1
	"""

    ### record BGF remarks
    bigboxBGF.REMARK.insert(
        0, "Solvents added by " + os.path.basename(sys.argv[0]) + " by " +
        os.environ["USER"] + " on " + time.asctime(time.gmtime()))
    bigboxBGF.REMARK.insert(0, "Solvents: " + str(solvent_file))

    ### save BGF
    if not silent: print("Saving the file.. see " + str(out_file))
    bigboxBGF.saveBGF(out_file)

    return 1
def addsolvent(bgf_file,
               solvent_bgf,
               min,
               max,
               n_solvent,
               out_file,
               ff_file,
               margin,
               mark,
               silent=True):

    ### initialize
    water = False
    default_margin = 1.0
    x_margin = 0.0
    y_margin = 0.0
    z_margin = 0.0
    if "x" in margin.lower():
        x_margin = default_margin
    if "y" in margin.lower():
        y_margin = default_margin
    if "z" in margin.lower():
        z_margin = default_margin

    ### load the solute bgf file
    if not silent: print("Initializing..")
    myBGF = bgf.BgfFile(bgf_file)  # str
    myBGF.renumber()

    if not silent: print("Loading the solvent file " + solvent_bgf + " ..")
    solventBGF = bgf.BgfFile(solvent_bgf)

    ### Generate error when the solvent box is not periodic:
    if not solventBGF.PERIOD:
        nu.die(
            "addSolvent: The solvent file is not periodic. Use a box full of solvent."
        )

    ### Check the type of solvent
    if not silent:
        print("(the solvent box seems to be full of " +
              os.path.basename(solvent_file)[:-4] + " )")
    if "f3c" in solvent_bgf:
        water = True  # this flag is used to remove the bad contacts with the molecule.
    if "spc" in solvent_bgf:
        water = True  # this flag is used to remove the bad contacts with the molecule.
    if "tip" in solvent_bgf:
        water = True  # this flag is used to remove the bad contacts with the molecule.

    ### calculate the box size
    if not silent: print("Analyzing box information..")
    if not min:
        min = [0.0, 0.0, 0.0]
    if not max:
        max = myBGF.CRYSTX[:3]

    strsize = [
        max[0] - min[0] - x_margin, max[1] - min[1] - y_margin,
        max[2] - min[2] - z_margin
    ]

    waterboxsize = solventBGF.CRYSTX[:3]  # REMARK: This is a kind of constant.
    copyNumber = [0, 0, 0]
    for index, i in enumerate(copyNumber):
        copyNumber[index] = math.ceil(
            strsize[index] /
            waterboxsize[index])  # how many times to replicate the water box

    if not silent: print("Creating box information: " + str(strsize))

    ### replicate the solvent box
    if not silent: print("Creating box.. this may take some time.")
    bigboxBGF = bgftools.replicateCell(solventBGF, copyNumber, True)
    bigboxBGF.saveBGF("_replicate.bgf")
    if not silent:
        print("- Number of atoms in the created box: " + str(len(bigboxBGF.a)))
    delatom = []
    delsolvent = []
    delsolventindex = []
    delwater = []
    delwaterindex = []

    bigboxBGF = bgf.BgfFile("_replicate.bgf")
    bigboxBGF.renumber()

    ### trim the water box
    if water:
        if not silent:
            print("Generating water box.. Calculating water molecules")
        for atom in bigboxBGF.a:
            if atom.x > strsize[0] or atom.y > strsize[1] or atom.z > strsize[
                    2]:
                delatom.append(atom.aNo)
        for aNo in delatom:
            water_molecule = bgftools.is_water(bigboxBGF, aNo)
            if not water_molecule in delwater:
                delwater.append(water_molecule)
        delwater = nu.flatten(delwater)
        delwater = nu.removeRepeat(delwater)
        for aNo in delwater:
            delwaterindex.append(bigboxBGF.a2i[aNo])
        if not silent: print("Generating water box.. Trimming")
        bigboxBGF.delAtoms(delwaterindex, False)
        bigboxBGF.renumber()
    elif not water:
        if not silent:
            print("Generating solvent box.. Extracting solvent molecules")
        for atom in tqdm.tqdm(bigboxBGF.a, desc='Iterating', ncols=120):
            if atom.x > strsize[0] or atom.y > strsize[1] or atom.z > strsize[
                    2]:
                delatom.append(atom.aNo)

        molecule = bgftools.getMoleculeList(bigboxBGF)
        for aNo in tqdm.tqdm(delatom,
                             desc='Appending atoms to remove',
                             ncols=120):
            for i in molecule:
                if aNo in i:
                    delsolvent += i
                    break
        delsolvent = list(set(delsolvent))
        for aNo in delsolvent:
            delsolventindex.append(bigboxBGF.a2i[aNo])
        if not silent: print("Generating solvent box.. Trimming")
        delsolventindex.sort()
        #delsolventindex.reverse()
        bigboxBGF.delAtoms(delsolventindex, False)
        bigboxBGF.renumber()

    bigboxBGF.saveBGF("_temp.bgf")  ## debug

    ### remain n molecules and delete residues
    bigboxBGF = bgftools.renumberMolecules(bigboxBGF, 0, False)  # renumber rNo

    if n_solvent:
        residues = set()
        for atom in bigboxBGF.a:
            residues.add(atom.rNo)  # scan molecule rNo
        residues = list(residues)
        if not silent: print("Found %d water molecules." % len(residues))
        if len(residues) < n_solvent:
            nu.die("Too few solvent molecules to choose %d molecules." %
                   n_solvent)

        rNos = random.sample(residues, n_solvent)  # select n molecules
        if not silent: print("%d water molecules are chosen." % n_solvent)

        # delete molecules
        delist = []
        for atom in bigboxBGF.a:
            if not atom.rNo in rNos:
                delist.append(bigboxBGF.a2i[atom.aNo])  # if not chosen, delete
        delist.sort()
        bigboxBGF.delAtoms(delist, False)
        bigboxBGF.renumber()

        bigboxBGF = bgftools.renumberMolecules(bigboxBGF, 0, False)

    ### move the water box to min position
    for atom in bigboxBGF.a:
        atom.x += min[0] + x_margin / 2
        atom.y += min[1] + y_margin / 2
        atom.z += min[2] + z_margin / 2

    ### add mark to the solvents
    if mark:
        for atom in bigboxBGF.a:
            atom.chain = mark

    bigboxBGF.saveBGF('_temp.bgf')

    # REMARK: it is natural to have the periodic information of water box for the output BGF file.
    # REMARK: HETATOM should be located on the first of the BGF file. So use dummy for merging.
    ## compute stats for adding solvents
    if not silent: print("\nComputing stats..")
    mol_list = bgftools.getMoleculeList(bigboxBGF)
    n_mol = len(mol_list)
    n_atom = len(nu.flatten(mol_list))
    if not silent:
        print(
            str(n_mol) + " molecules (" + str(n_atom) +
            " atoms) will be added.")

    ## merge
    #bigboxBGF = myBGF.merge(bigboxBGF, True)
    myBGF = bgf.BgfFile(bgf_file)
    bigboxBGF = bgf.BgfFile("_temp.bgf")
    bigboxBGF2 = myBGF.merge(bigboxBGF)
    if not silent: print("Total atoms in the file: " + str(len(bigboxBGF.a)))

    ## some paperworking for periodic box
    bigboxBGF2.OTHER = myBGF.OTHER
    bigboxBGF2.PERIOD = myBGF.PERIOD
    bigboxBGF2.AXES = myBGF.AXES
    bigboxBGF2.SGNAME = myBGF.SGNAME
    bigboxBGF2.CRYSTX = myBGF.CRYSTX
    bigboxBGF2.CELLS = myBGF.CELLS

    ### record BGF remarks
    bigboxBGF2.REMARK.insert(
        0, "Solvents added by " + os.path.basename(sys.argv[0]) + " by " +
        os.environ["USER"] + " on " + time.asctime(time.gmtime()))
    bigboxBGF2.REMARK.insert(0, "Solvents: " + str(solvent_file))

    ### save BGF
    if not silent: print("Saving the file.. see " + str(out_file))
    bigboxBGF2.saveBGF(out_file)

    return 1