def adjust_interior_water(self, n_water): if not self._water_position_determined: nu.warn("You have to run determine_water_position() first.") return if not n_water: nu.warn( "You must specify the number of water molecules inside the Nanotube." ) return self.bgfmodel = bgftools.renumberMolecules(self.bgfmodel, 0, False) waters = set() for atom in self.bgfmodel.a: if atom.chain == 'I': waters.add(atom.rNo) waters = list(waters) print("\tFound %d interior water molecules." % len(waters)) if len(waters) < n_water: nu.warn("Too few solvent molecules to choose %d molecules." % n_water) return rNos = random.sample(waters, n_water) print("%d water molecules are randomly chosen. Others are removed." % n_water) delist = [] for atom in self.bgfmodel.a: if atom.chain == 'I' and not atom.rNo in rNos: delist.append(self.bgfmodel.a2i[atom.aNo]) delist.sort() self.bgfmodel.delAtoms(delist, False) self.bgfmodel.renumber() self.bgfmodel = bgftools.renumberMolecules(self.bgfmodel, 0, False) self.update()
def determine_water_position(self, *args): print("Marking water molecules whether internal or external..") if self.isRadiusCalc == False: nu.warn("Nanotube radius not calculated.") return 0 tempBGF = bgf.BgfFile() tempBGF = bgftools.make_periodic(tempBGF, self.pbc) self.make_pbc(self.pbc, self.bgfmodel.CRYSTX) # copy Nanotube atoms for atom in self.NTatoms + self.otheratoms: atom2 = copy.deepcopy(atom) tempBGF.addAtom(atom2) tempBGF.renumber() # mark rNames to Oxygen atoms n_oxygen_inside = 0 n_oxygen_outside = 0 for atom in self.WATatoms: if "H" in atom.ffType: continue xyz = np.array([atom.x, atom.y, atom.z]) r = np.sqrt( ((xyz * self.axis - self.center * self.axis)**2).sum(axis=-1)) h = (xyz * self.axismask).sum() if r < self.radius: # inside O atom.chain = "I" n_oxygen_inside += 1 else: # outside O atom.chain = "O" n_oxygen_outside += 1 print("Interior oxygens: " + str(n_oxygen_inside) + ", exterior oxygens: " + str(n_oxygen_outside)) self.n_inside_water = n_oxygen_inside self.n_outside_water = n_oxygen_outside # write water molecules chain = ["I", "O"] for cname in chain: print("Passing " + cname) for atom in self.WATatoms: if cname in atom.chain and "O" in atom.ffType: tempBGF.addAtom(atom) # l_Hatoms = atom.CONECT for index, ano in enumerate(l_Hatoms): atom2 = self.bgfmodel.getAtom(ano) atom2.chain = cname tempBGF.addAtom(atom2) # self.bgfmodel = tempBGF self.bgfmodel.renumber() self.bgfmodel = bgftools.renumberMolecules(self.bgfmodel, 0, False) self.update() print( "Water molecules are identified into interior(I) and exterior(O).") if len(args) == 0: nu.warn( "Residue name and coords for water molecules are modified.") elif len(args) == 1: print("Modified BGF file is saved to " + str(args[0])) self.bgfmodel.saveBGF(args[0]) self._water_position_determined = True
def renumberResNum(bgf_file, out_file, silent=True): bgftools.renumberMolecules(bgf_file, out_file, False)
if len(sys.argv) < 3: print(usage) sys.exit(0) mybgf = bgf.BgfFile(sys.argv[1]) out_file = sys.argv[2] selection = sys.argv[3] n_del = int(sys.argv[4]) resid = set() for atom in mybgf.a: if eval(selection): resid.add(atom.rNo) resid = list(resid) if len(resid) < n_del: nu.die("Not enough molecules to choose %d molecules to delete." % n_del) rnos = random.sample(resid, n_del) delist = [] for atom in mybgf.a: if atom.rNo in rnos: delist.append(mybgf.a2i[atom.aNo]) mybgf.delAtoms(delist) mybgf.renumber() mybgf.saveBGF(out_file) bt.renumberMolecules(out_file, out_file)
for atom in newBGF.a: atom.aTag = 0 # change into ATOM atom.rName = "WAT" if "O" in atom.ffType: atom.aName = "O" atom.ffType = water_O_ffType l_Hatoms = atom.CONECT for index, ano2 in enumerate(l_Hatoms): atom2 = newBGF.getAtom(ano2) atom2.aName = "H" + str(index + 1) atom2.ffType = water_H_ffType # merge myBGF and newBGF myBGF = myBGF.merge(newBGF, True) myBGF.renumber() # save myBGF = bgftools.renumberMolecules(myBGF, 0) myBGF.renumber() try: bgf_file = sys.argv[2] except: myBGF.saveBGF(sys.argv[1].split(".bgf")[0] + "_mod.bgf") else: myBGF.saveBGF(bgf_file) ### end
mybgf, 'atom.z', selection="'S_3a' in atom.ffType and atom.rNo == 2") avg_s3b_z2 = bt.atoms_average( mybgf, 'atom.z', selection="'S_3b' in atom.ffType and atom.rNo == 2") # prepare water box solvent = bgf.BgfFile('/home/noische/scripts/dat/WAT/spc_box.bgf') solvent = bt.stress_cell(solvent, str(1 / math.pow(1.7, 0.3333))) solvent.saveBGF('_solvent.bgf') addsolv_reg_cmd = "/qcfs/noische/scripts/BGF_addSolvent_region.py -b _temp.bgf -f %s -o _temp.bgf -m '0 0 %f' -M '%f %f %f' -n %d -t _solvent.bgf -v I" % ( ff_file, avg_s3a_z1 + 1.5, result.CRYSTX[0], result.CRYSTX[1], avg_s3b_z2 - 1.0, n_wat) print("** Adding confined water..") print(addsolv_reg_cmd) os.system(addsolv_reg_cmd) bt.renumberMolecules('_temp.bgf', '_temp.bgf') if len(sys.argv) == 8: os.system("mv _temp.bgf %s" % out_file) sys.exit(0) # add water outside mos2: bottom addsolv_reg_cmd = "/qcfs/noische/scripts/BGF_addSolvent_region.py -b _temp.bgf -f %s -o _temp.bgf -M '%f %f %f' -v O" % ( ff_file, result.CRYSTX[0], result.CRYSTX[1], avg_s3b_z1 - 0.5) print("** Adding bottom water..") print(addsolv_reg_cmd) os.system(addsolv_reg_cmd) bt.renumberMolecules('_temp.bgf', '_temp.bgf') # add water outside mos2: top addsolv_reg_cmd = "/qcfs/noische/scripts/BGF_addSolvent_region.py -b _temp.bgf -f %s -m '0 0 %f' -o %s -v O" % (
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