def run(mybgf, t, chunk, sel=""): """ This function performs the calculation. Output: - int t: timestep - list result: found hbonds - bgf.BgfFile mybgf: BgfFile with update coordinates - string sel: a selection """ mybgf = update_coord(chunk, mybgf, mytrj.pbc[t], scaled=yes_scale) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, fragments=atom_frags, ff_file=ff_file, silent=True) if not sel: sel = calculate_sel_kwac(mybgf) # for Kwac's confined water molecules in MoS2 nanoslit elif sel == "all": sel = "" # for water if sel: sel_O_atoms = [atom.aNo for atom in mybgf.a if eval(sel) and 'O' in atom.ffType] else: sel_O_atoms = [atom.aNo for atom in mybgf.a if 'O' in atom.ffType] result = hbonds(mybgf, selection=sel) if verbose: mybgf.saveBGF(str(t) + ".bgf") return t, sel_O_atoms, result
def run_hb(mybgf, t, chunk): mybgf = update_coord(chunk, mybgf, mytrj.pbc[t], scaled=yes_scale) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, fragments=atom_frags, ff_file=ff_file, silent=True) ''' #sel = "atom.chain == 'I'" # for test # find inwater boundary for selection swr = 3.270615945/2 gwr = 3.057430885/2 margin = 5.0 gwa_y = bt.atoms_average(mybgf, 'atom.y', selection="'GWA' in atom.rName") gwb_y = bt.atoms_average(mybgf, 'atom.y', selection="'GWB' in atom.rName") if type == "gra": avg_z1 = bt.atoms_average(mybgf, 'atom.z', selection="'C_R' in atom.ffType and 'GRA' in atom.rName") # gra bottom avg_z2 = bt.atoms_average(mybgf, 'atom.z', selection="'C_R' in atom.ffType and 'GRB' in atom.rName") # gra top actual_distance = avg_z2 - avg_z1 elif type == "mos": avg_s3a_z2 = bt.atoms_average(mybgf, 'atom.z', selection="'S_3a' in atom.ffType and atom.rNo == 2") # mos2 top avg_s3b_z1 = bt.atoms_average(mybgf, 'atom.z', selection="'S_3b' in atom.ffType and atom.rNo == 1") # mos2 bottom actual_distance = avg_s3a_z2 - avg_s3b_z1 inwater_x = mybgf.CRYSTX[0] inwater_y = gwb_y - gwa_y + 2 * gwr - 2 * margin inwater_z = actual_distance - 2 * swr sel = "atom.y > {gwa_y} + {margin} and atom.y < {gwb_y} - {margin}".format(**vars()) ''' sel = "" hb = calc_hbonds(mybgf, selection=sel) return t, hb
def analyze(bgf_file, trj_file, ff_file='', out_file=''): '''analyze something within a timestep in a series of lammps trajectory. ''' # variables # inner functions def get_line(file): with open(file, 'r') as f: for line in f: yield line # 1. Load BGF mybgf = bgf.BgfFile(bgf_file) N_BGF_ATOMS = len(mybgf.a) # 2. Read LAMMPS Trajectory #timesteps, N_HEADER, N_ATOMS = lt.getTrjInfo(trj_file) mytrj = lt.lammpstrj(trj_file) timesteps = mytrj.load() N_HEADER = mytrj.nheader N_ATOMS = mytrj.natoms[0] N_BUFFER = N_HEADER + N_ATOMS if N_BGF_ATOMS != N_ATOMS: nu.die( "Number of atoms in trajectory file does not match with BGF file.") # 3. Determine dump style dump_keywords = mytrj.dumpstyle yes_scale = False if 'xs' in dump_keywords: yes_scale = True # 4. Update coordinates from the snapshot dump = get_line(trj_file) for t in tqdm.tqdm(timesteps, ncols=120, desc="Analyzing"): chunk = [next(dump) for i in range(N_BUFFER)] t = int(chunk[1]) mybgf.CRYSTX = mytrj.pbc[t] + [90.0, 90.0, 90.0] coords = chunk[9:] for c in coords: c = c.split(' ') atom = mybgf.getAtom(int(c[0])) if yes_scale: atom.x = float(c[2]) * pbc[0] atom.y = float(c[3]) * pbc[1] atom.z = float(c[4]) * pbc[2] else: atom.x = float(c[2]) atom.y = float(c[3]) atom.z = float(c[4]) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, ff_file=ff_file, silent=True)
def run(system, t, coords, sel=""): """ This function performs the analysis. Input: - bgf.BgfFile mybgf - int t: a timestep written in LAMMPS trjectory - list chunk: list of atom coordinates in LAMMPS trajectory - str sel: a string to evaluate for selecting atoms Output: - int t: timestep - list result: found hbonds """ assert isinstance(system, bgf.BgfFile), "Wrong object: should be an instance of bgf.BgfFile class." assert isinstance(t, int), "Timestep should be int." assert isinstance(coords, list), "coords should be a list." # update the coordinates from trj to the BGF object system = update_coord(coords, system, mytrj.pbc[t], scaled=yes_scale) # wrap the coordinates into the pbc cell system = bt.periodicMoleculeSort(system, system.CRYSTX, fragments=atom_frags, ff_file=ff_file, silent=True) selected_atoms = [atom for atom in system.a if eval(sel)] # do analysis here out = [] # list to save results # ... # something something something # ... # # blah blah blah # ... # save each trajectory as BGF file if verbose mode activated. if verbose: system.saveBGF(str(t) + ".bgf") return t, out
def run(mybgf, t, chunk, sel=""): """ This function performs the calculation. Output: - int t: timestep - list result: found hbonds - bgf.BgfFile mybgf: BgfFile with update coordinates - string sel: a selection """ mybgf = update_coord(chunk, mybgf, mytrj.pbc[t], scaled=yes_scale) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, fragments=atom_frags, ff_file=ff_file, silent=True) result = hbonds(mybgf, selection=sel) if verbose: mybgf.saveBGF(str(t) + ".bgf") return t, result
def countWaterCNT(bgf_file, trj_file, silent=False): # init timestep = 0 l_timestep = [] myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myDAT = open(bgf_file[:-4] + ".count.dat", "w") myDAT.write("Time\tHeight\tRadius\tNumber\n") # extract aNos of CNT in the BGF file aNo_CNT = [] aNo_MtOH_C = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) # Carbons in MeOH if "MET" in atom.rName and "C" in atom.aName: aNo_MtOH_C.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # for every shot in the trajectory file update BGF and manipulate myDUMP = dump.dump(trj_file, 0) # sequential reading while 1: aNo_MtOH_C_in_CNT = copy.deepcopy(aNo_MtOH_C) # initialize for the moment of inertia and the center of mass calculation U = 0 Ut = 0 Uv = 0 Ixx = 0 Ixy = 0 Ixz = 0 Iyx = 0 Iyy = 0 Iyz = 0 Izx = 0 Izy = 0 Izz = 0 Mx = 0 My = 0 Mz = 0 time = myDUMP.next() sys.stdout.write('\r' + "Reading timestep.. " + str(time)) sys.stdout.flush() #print("Timestep: " + str(time)) if time == -1: break nu.shutup() myDUMP.sort() nu.say() l_timestep = myDUMP.time() # timesteps are 'appended' incrementally atoms = myDUMP.viz(len(l_timestep) - 1)[ 2] # atom coordinate info: id,type,x,y,z for each atom as 2d array box = myDUMP.viz(len(l_timestep) - 1)[1] # [xlo, ylo, zlo, xhi, yhi, zhi] box = [float(i) for i in box] boxsize = [box[3] - box[0], box[4] - box[1], box[5] - box[1]] # simbox size myBGF.CRYSTX = [ boxsize[0], boxsize[1], boxsize[2], myBGF.CRYSTX[3], myBGF.CRYSTX[4], myBGF.CRYSTX[5] ] #print("l_atoms " + str(len(atoms))) # update the coordinates in the bgf file for atom in atoms: bgfatom = myBGF.getAtom(atom[0]) bgfatom.x = float(atom[2]) bgfatom.y = float(atom[3]) bgfatom.z = float(atom[4]) """ # com of CNT for atom in myBGF.a: if "CNT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT """ myBGF = bgftools.periodicMoleculeSort(myBGF) #print(Mx, My, Mz) # transpose for "all atoms in BGF" for atom in myBGF.a: atom.x -= Mx atom.y -= My atom.z -= Mz # calculate the moment of inertia (MI) and the center of mass (COM) of CNT from "myBGF" for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) Ixx += (atom.y**2 + atom.z**2) / N_CNT Iyy += (atom.x**2 + atom.z**2) / N_CNT Izz += (atom.x**2 + atom.y**2) / N_CNT Ixy -= (atom.x * atom.y) / N_CNT Ixz -= (atom.x * atom.z) / N_CNT Iyz -= (atom.y * atom.z) / N_CNT # the moment of inertia tensor I = numpy.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]]) # eigenvalue & eigenvector calculation eigval, eigvec = numpy.linalg.eig( I) # eigval[0] is the minimum among the values. # rearrange the U vector U = numpy.matrix(eigvec) Ut = U.T # "myBGF" transform for atom in myBGF.a: v = numpy.matrix([atom.x, atom.y, atom.z]).T Uv = Ut * v atom.x = float(Uv[0]) atom.y = float(Uv[1]) atom.z = float(Uv[2]) # com of CNT Mx = 0 My = 0 Mz = 0 for atom in myBGF.a: if "CNT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT #print(Mx, My, Mz) # transpose for "all atoms in BGF" for atom in myBGF.a: atom.x -= Mx atom.y -= My atom.z -= Mz """ ### THIS PART (UPDATING LAMMPSTRJ) DOES NOT WORK ### myDUMP.aselect.all(time) # all atoms should be selected to be changed myDUMP.tselect.one(time) coordx = []; coordy = []; coordz = [] for atom in myBGF.a: coordx.append(atom.x) coordy.append(atom.y) coordz.append(atom.z) myDUMP.setv("xu", coordx) myDUMP.setv("yu", coordy) myDUMP.setv("zu", coordz) """ """ ### CHECKING ORIGIN by adding an atom at (0, 0, 0) and is okay. 110914 inkim origin = bgf.BgfAtom() origin.aTag = 0 origin.aName = "ORIG" origin.ffType = "Ar" origin.chain = "A" origin.x = 0.0 origin.y = 0.0 origin.z = 0.0 origin.rName = "ORG" myBGF.addAtom(origin) """ # for CNT atoms, calculate some properties min_x_CNT = 0.0 max_x_CNT = 0.0 radius_CNT = 0.0 height_CNT = 0.0 for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) # minimum and maximum x coord of CNT: this will be the height of CNT if atom.x < min_x_CNT: min_x_CNT = atom.x if atom.x > max_x_CNT: max_x_CNT = atom.x radius_CNT += math.sqrt(atom.y**2 + atom.z**2) # average radius of CNT radius_CNT = radius_CNT / N_CNT height_CNT = max_x_CNT - min_x_CNT # determine whether C in MtOH is in the CNT Cylinder for aNo in aNo_MtOH_C: atom = myBGF.getAtom(aNo) dist = math.sqrt(atom.y**2 + atom.z**2) if atom.x > min_x_CNT \ and atom.x < max_x_CNT \ and dist < radius_CNT: pass else: aNo_MtOH_C_in_CNT.remove(aNo) #print("Height of CNT: " + str(height_CNT) + " " + str(min_x_CNT) + " " + str(max_x_CNT)) #print("Average radius of CNT: " + str(radius_CNT)) #print("Average number of methanols in CNT: " + str(len(aNo_MtOH_C_in_CNT))) myDAT.write(str(time) + "\t") myDAT.write(str("{0:<8.3f}".format(height_CNT))) myDAT.write(str("{0:<8.3f}".format(radius_CNT))) myDAT.write(str(len(aNo_MtOH_C_in_CNT)) + "\n") # write output myBGF.saveBGF(bgf_file[:-4] + "." + str(time) + ".bgf") #myDUMP.write(trj_file.split(".")[0] + "_mod." + trj_file.split(".")[1]) print('') return 1
def getVelocity(bgf_file, trj_file, n_step, silent=False): # const PI = math.pi vdw_r_C = 1.7 # init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock l_data = [] # stores vz l_avg_radius_CNT = [] myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) ftemp = open("countWater42.profile", 'w') ftemp.write(str(sys.argv) + "\n") curr_dir = os.path.abspath(".") temp_dir = curr_dir + "/CountWAT42/" if not os.path.isdir(temp_dir): os.makedirs(temp_dir) # how many steps to go? n_timestep = len(lt.getTrjInfo(trj_file)) if n_step == 0: n_step = n_timestep print(" ..The trajectory contains " + str(n_timestep) + " timesteps.") print("The script will proceed for the last " + str(n_step) + " timesteps.") # extract aNos of CNT in the BGF file aNo_CNT = [] aNo_WAT_O = [] aNo_WAT_all = [] for atom in myBGF.a: # Carbons in CNT or atoms in BNNT if "NT" in atom.rName: aNo_CNT.append(atom.aNo) # Oxygen in water if "WAT" in atom.rName and "O" in atom.aName: aNo_WAT_O.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # check if there exists water properly if len(aNo_WAT_O) == 0: nu.die("No water molecules in the BGF file.") if len(aNo_CNT) == 0: nu.die("No CNT molecules in the BGF file.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 while 1: ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_step - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() if processed_step == n_step: break ### Read try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = 'unwrapped' # assume that "dump 1 all custom 100 ${sname}${rtemp}K.nvt.lammps id type xu yu zu vx vy vz" in lammps input # actual coordinate coordinfo = chunk[9:] # modified for fast treatment for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) atom.vx = float(atomcoord[5]) atom.vy = float(atomcoord[6]) atom.vz = float(atomcoord[7]) if myBGF.CRYSTX != []: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] else: nu.warn("Crystal information error: is this file not periodic?") for i in range(0, 3): myBGF.CRYSTX.append(boxsize[i]) ### myBGF update complete! ### ### align CNT to z axis # initialize for the moment of inertia and the center of mass calculation U = 0 Ut = 0 Uv = 0 Ixx = 0 Ixy = 0 Ixz = 0 Iyx = 0 Iyy = 0 Iyz = 0 Izx = 0 Izy = 0 Izz = 0 Mx = 0 My = 0 Mz = 0 # set COM of CNT as origin Mx = 0 My = 0 Mz = 0 # Center of mass of CNT for atom in myBGF.a: if "NT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT for atom in myBGF.a: atom.x -= Mx # move atom.y -= My atom.z -= Mz # calculate the moment of inertia (MI) and the center of mass (COM) of CNT from "myBGF" for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) Ixx += (atom.y**2 + atom.z**2) / N_CNT Iyy += (atom.x**2 + atom.z**2) / N_CNT Izz += (atom.x**2 + atom.y**2) / N_CNT Ixy -= (atom.x * atom.y) / N_CNT Ixz -= (atom.x * atom.z) / N_CNT Iyz -= (atom.y * atom.z) / N_CNT # the moment of inertia tensor I = np.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]]) # eigenvalue & eigenvector calculation eigval, eigvec = np.linalg.eig( I) # eigval[0] is the minimum among the values. # rearrange the U vector U = np.matrix(eigvec) Ut = U.T # "myBGF" rotation for atom in myBGF.a: v = np.matrix([atom.x, atom.y, atom.z]).T Uv = Ut * v atom.x = float(Uv[2]) atom.y = float(Uv[1]) atom.z = float(Uv[0]) #dimension = np.matrix(boxsize).T #boxsize_prime = np.array(np.dot(Ut, dimension).T) boxsize_prime = np.transpose( np.dot(Ut, np.transpose(np.array(boxsize)))) # new pbc from jackjack5 print(boxsize) print(boxsize_prime) # move atoms to box center for atom in myBGF.a: atom.x -= boxsize_prime[0] / 2 atom.y -= boxsize_prime[1] / 2 atom.z -= boxsize_prime[2] / 2 myBGF.saveBGF(temp_dir + bgf_file.split(".bgf")[0] + "." + str(timestep) + ".beforepbc.bgf") myBGF = bgftools.periodicMoleculeSort(myBGF, 0, myBGF.CRYSTX) myBGF.saveBGF(temp_dir + bgf_file.split(".bgf")[0] + "." + str(timestep) + ".bgf") # for CNT atoms, calculate some properties min_x_CNT = 1000.0 max_x_CNT = -1000.0 radius_CNT = 0.0 height_CNT = 0.0 min_y_CNT = 1000.0 max_y_CNT = -1000.0 min_z_CNT = 1000.0 max_z_CNT = -1000.0 l_radius_CNT = [] l_x_CNT = [] l_y_CNT = [] for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) # center of CNT l_x_CNT.append(atom.x) l_y_CNT.append(atom.y) # height if atom.z < min_z_CNT: min_z_CNT = atom.z if atom.z > max_z_CNT: max_z_CNT = atom.z x_CNT, a = nu.meanstdv(l_x_CNT) y_CNT, a = nu.meanstdv(l_y_CNT) z_diff = max_z_CNT - min_z_CNT height_CNT = z_diff # radius of CNT for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) l_radius_CNT.append( math.sqrt((atom.x - x_CNT)**2 + (atom.y - y_CNT)**2)) radius_CNT, a = nu.meanstdv(l_radius_CNT) l_avg_radius_CNT.append(radius_CNT) ### get water molecules in CNT # inside the CNT := min_z_CNT <= z <= max_z_CNT and (x - (x_diff/2))**2 + (y - (y_diff/2))**2 < radius_CNT**2 # aNo_WAT_O_atoms: molecules which O atom is within CNT # we don't need to calculate H atoms. Let's consider only O atoms margin = 0.0 # water molecules far from the margin will be only considered aNo_WAT_O_in_CNT = [] for aNo in aNo_WAT_O: atom = myBGF.getAtom(aNo) dist_sq = (atom.x - x_CNT)**2 + (atom.y - y_CNT)**2 if "WAT" in atom.rName and "O" in atom.ffType and min_z_CNT + margin <= atom.z and atom.z <= max_z_CNT - margin and dist_sq < radius_CNT**2: aNo_WAT_O_in_CNT.append(aNo) else: pass ### record number of water molecules in CNT #l_data.append([timestep, len(aNo_WAT_O_in_CNT), radius_CNT, z_diff]) #output = str(timestep) + '\t' + str(len(aNo_WAT_O_in_CNT)) + '\t' + str(radius_CNT) + '\t' + str(z_diff) + '\n' output = str(timestep) + '\t' + str( len(aNo_WAT_O_in_CNT)) + '\t' + str(radius_CNT) + '\t' + str( min_z_CNT) + '\t' + str(max_z_CNT) + '\t' + str( z_diff) + '\t' + str(height_CNT) + '\t' + str( len(aNo_CNT)) + '\n' # debug ftemp.write(output) #sys.stdout.write('Done ') sys.stdout.flush() t2 = time.time() # time mark elapsed_time = t2 - t1 processed_step += 1 print('') ftemp.close() print( "numbers of water molecules are written in countWater.profile ..Done.") return 1
def densityProfile(bgf_file, trj_file, out_file, interval, avg_timestep, direction='z', ff_file='', silent=False): nu.warn( "LAMMPS trajectory with NPT simulations will give you the wrong result." ) ### init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock vector = [0, 0, 1] # the axis of interest. in the acetone-water case, z direction. atominfo = bgftools.atom_mass # atom data extracted from ff_file result = dict() axis = 0 # 1: x-axis, 2: y-axis, 3: z-axis ### direction if "x" in direction: axis = 0 elif "y" in direction: axis = 1 elif "z" in direction: axis = 2 else: nu.die("Error on reading direction.") ### open files myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) f_out_file = open(out_file + ".dat", 'w') f_avg_out_file = open(out_file + ".average.dat", 'w') f_pickle = open(out_file + ".pickle", 'w') f_avg_pickle = open(out_file + ".average.pickle", 'w') ### read residues from bgf_file:: residue is replaced by ffTypes residue = set() # kind of residues in BGF file dict_residue = dict() # stores residue numbers per each residue. RES1: [1, 2, ..], RES2: [6, 7, ..] for i in myBGF.a: rname = string.strip(i.ffType) residue.add(rname) output = "" for i in residue: output += i + " " if not silent: print("Found " + str(len(residue)) + " residues in BGF file: " + str(output)) residue = list(residue) residue.append('TOTAL') for index, i in enumerate(residue): dict_residue[i] = index n_residue = len(residue) # number of residues (including total) if ff_file: bgftools.update_mass(ff_file) ### read trajectory file # how many steps to go? #l_timestep = lt.getTrjInfo(trj_file) #mytrj = trj.lammpstrj(trj_file) mytrj = Trj(trj_file) l_timestep = mytrj.load() n_timestep = len(l_timestep) if not silent: print("\nThe trajectory contains %d timesteps." % n_timestep) # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 while 1: try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) l_timestep.append(timestep) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_timestep - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Elapsed time for the previous step: " + "{0:4.1f}".format(elapsed_time) + " seconds, Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds = " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() processed_step += 1 ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn( "No image information no the trajectory file. Will be treated as unwrapped." ) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float( atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float( atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float( atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, myBGF.CRYSTX, silent=True) ### DONE for updating trj on BGF file ### ### Do whatever I want: density profile ### upper and lower bound min = -3.0 max = boxsize[axis] + 3.0 ### make a bin bin = np.arange(math.floor(min), math.ceil(max), interval) ### for every atoms, get atom coordinate and its type positions = [] # atom positions. [ res1, res2, ..., total ] masses = [] # used for a weight for histogram. [ res1, res2, ..., total ] hist = [] bin_edges = [] for i in range(n_residue): positions.append([]) masses.append([]) hist.append([]) bin_edges.append([]) for atom in myBGF.a: coord = [atom.x, atom.y, atom.z] # total positions[-1].append(coord[axis]) masses[-1].append(atominfo[atom.ffType]) # residues positions[dict_residue[atom.ffType.strip()]].append(coord[axis]) masses[dict_residue[atom.ffType.strip()]].append( atominfo[atom.ffType]) ### calculate volume area = 0 if axis == 0: area = boxsize[1] * boxsize[2] elif axis == 1: area = boxsize[0] * boxsize[2] elif axis == 2: area = boxsize[0] * boxsize[1] vol = area * interval ### histogram for i in range(n_residue): hist[i], bin_edges[i] = np.histogram(positions[i], bins=bin, weights=masses[i]) hist[i] = hist[i] / 6.022 / vol * 10 # density ### store temp = dict() for i in range(n_residue): temp2 = dict() temp2['HIST'] = hist[i] temp2['BIN_EDGES'] = bin_edges[i] temp[residue[i]] = temp2 result[timestep] = temp ### end of loop: check elapsed time t2 = time.time() # time mark elapsed_time = t2 - t1 ### calculate average values if not silent: print("\nAveraging the last %d timesteps.." % avg_timestep) avg_timesteps = l_timestep[-avg_timestep:] avg_hist = [] avg_bin_edges = [] for i in range(n_residue): avg_hist.append( np.zeros(len(result[l_timestep[-avg_timestep]]['TOTAL']['HIST']))) #avg_bin_edges.append(np.zeros(len(result[-avg_timestep]['TOTAL']['BIN_EDGES']))); for t in avg_timesteps: for r in result[t]: avg_hist[dict_residue[r]] += result[t][r]['HIST'] for i in range(n_residue): avg_hist[i] /= len(avg_timesteps) # normalize temp_avg = dict() # residue --- HIST, BIN_EDGES for i in residue: temp2 = dict() temp2['HIST'] = avg_hist[dict_residue[i]] temp2['BIN_EDGES'] = bin_edges[0] temp_avg[i] = temp2 ### write up a average data to file output = str(avg_timestep) + "\n" for r in temp_avg: output += str(r) + "\n" for index, i in enumerate(temp_avg[r]['HIST']): output += str( temp_avg[r]['BIN_EDGES'][index]) + "\t" + str(i) + "\n" output += "\n" f_avg_out_file.write(output) ### write up a whole data to file output = "" tkey = result.keys() tkey.sort() for t in tkey: output += str(t) + "\n" rkey = result[t].keys() rkey.sort() for r in rkey: output += str(r) + "\n" for index, i in enumerate(result[t][r]['HIST']): output += str( result[t][r]['BIN_EDGES'][index]) + "\t" + str(i) + "\n" output += "\n" output += "\n" f_out_file.write(output) ### write up a pickle object if not silent: print("Writing pickle object..") pickle.dump(result, f_pickle) f_pickle.close() pickle.dump(temp, f_avg_pickle) f_avg_pickle.close() ### return print('') return 1
def myfunction(bgf_file, trj_file, n_step, out_file, silent=False): # const PI = math.pi vdw_r_C = 1.7 # init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock # environments myBGF = bgf.BgfFile(bgf_file) # load BGF myTRJ = open(trj_file) # load LAMMPS trj myTRJ.seek(0) out_file = "myfunction.dat" f_out_file = open(out_file, 'w') # data will be recorded here f_out_file.write(str(sys.argv) + "\n") curr_dir = os.path.abspath(".") temp_dir = curr_dir + "/data/" if not os.path.isdir(temp_dir): os.makedirs(temp_dir) print("* Current directory: " + curr_dir) print("* Temp directory: " + temp_dir) # variables pass # scan LAMMPS trj to count how many shots in the file n_timestep = len(lt.getTrjInfo(trj_file)) if n_step == 0: n_step = n_timestep print(" ..The trajectory contains " + str(n_timestep) + " timesteps.") print("The script will proceed for the last " + str(n_step) + " timesteps.") # prepare something with BGF file for atom in myBGF.a: # do something pass ### Read trajectory file header while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # initial trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # launch LAMMPS trj file dumpatom = get_line(trj_file) ### loop over trj and do the analysis processed_step = 0 # counter t1 = t2 = 0 elapsed_time = 0 # timer: calculate ETA while 1: # Show progress t1 = time.time() remaining_time = elapsed_time * (n_step - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() # stop analysis if requested n_step reached if processed_step == n_step: break # Read a shot from the trj file try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = 'unwrapped' # assume that "dump 1 all custom 100 ${sname}${rtemp}K.nvt.lammps id type xu yu zu vx vy vz" in lammps input # actual coordinate coordinfo = chunk[9:] # modified for fast treatment for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) atom.vx = float(atomcoord[5]) atom.vy = float(atomcoord[6]) atom.vz = float(atomcoord[7]) if myBGF.CRYSTX != []: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] else: nu.warn("Crystal information error: is this file not periodic?") for i in range(0, 3): myBGF.CRYSTX.append(boxsize[i]) # pbc wrap if required myBGF = bgftools.periodicMoleculeSort(myBGF, 0, myBGF.CRYSTX) ### do some analysis """ asdflkjhasdlkfjadslkfjasdlkvjbaldskjfha;lsiefhja;lsejkfblnkdsjvb """ ### record data output = str(timestep) + '\t' + str(123) + '\n' f_out_file.write(output) ### update timer sys.stdout.flush() t2 = time.time() # time mark elapsed_time = t2 - t1 processed_step += 1 print('') f_out_file.close() print("numbers of water molecules are written in " + out_file + " ..Done.") return 1
def getVelocity(bgf_file, trj_file, n_step, silent=False): # const PI = math.pi vdw_r_C = 1.7 # init timestep = 0; l_timestep = []; line = []; n_header = 0; t1 = 0; t2 = 0; # clock interval = 0.1; l_data = []; # stores vz l_avg_radius_CNT = []; myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) # how many steps to go? wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read() n_timestep = int(wc_trj_file.split()[0]); print("The trajectory contains " + str(n_timestep) + " timesteps.") # extract aNos of CNT in the BGF file aNo_CNT = [] aNo_WAT_O = [] aNo_WAT_all = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) # Oxygen in water if "WAT" in atom.rName and "O" in atom.aName: aNo_WAT_O.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # check if there exists water properly if len(aNo_WAT_O) == 0: nu.die("No water molecules in the BGF file.") if len(aNo_CNT) == 0: nu.die("No CNT molecules in the BGF file.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break; # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1]] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0; t1 = t2 = 0; elapsed_time = 0; while 1: ### Show progress sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) ) sys.stdout.flush() ### Read try: chunk = [next(dumpatom) for i in range(natoms+n_header)] except StopIteration: break; timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1]]; boxsize = [float(i) for i in boxsize]; boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') if timestep != n_step: continue; ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die("Number of atoms in trajectory file does not match with BGF file.") mode = 'unwrapped' # assume that "dump 1 all custom 100 ${sname}${rtemp}K.nvt.lammps id type xu yu zu vx vy vz" in lammps input # actual coordinate coordinfo = chunk[9:] # modified for fast treatment for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) atom.vx = float(atomcoord[5]) atom.vy = float(atomcoord[6]) atom.vz = float(atomcoord[7]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass; #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0, True) ### myBGF update complete! ### #aNo_WAT_O_in_CNT = copy.deepcopy(aNo_WAT_O) ### align CNT to z axis # initialize for the moment of inertia and the center of mass calculation U = 0; Ut = 0; Uv = 0; Ixx = 0; Ixy = 0; Ixz = 0; Iyx = 0; Iyy = 0; Iyz = 0; Izx = 0; Izy = 0; Izz = 0; Mx = 0; My = 0; Mz = 0; # transpose for "all atoms in BGF": move COM of CNT as origin # com of CNT Mx = 0; My = 0; Mz = 0; for atom in myBGF.a: if "CNT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT # move for atom in myBGF.a: atom.x -= Mx atom.y -= My atom.z -= Mz # calculate the moment of inertia (MI) and the center of mass (COM) of CNT from "myBGF" for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) Ixx += (atom.y**2 + atom.z**2) / N_CNT Iyy += (atom.x**2 + atom.z**2) / N_CNT Izz += (atom.x**2 + atom.y**2) / N_CNT Ixy -= (atom.x * atom.y) / N_CNT Ixz -= (atom.x * atom.z) / N_CNT Iyz -= (atom.y * atom.z) / N_CNT # the moment of inertia tensor I = np.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]]) # eigenvalue & eigenvector calculation eigval, eigvec = np.linalg.eig(I) # eigval[0] is the minimum among the values. # rearrange the U vector U = np.matrix(eigvec) Ut = U.T # "myBGF" rotation for atom in myBGF.a: v = np.matrix([atom.x, atom.y, atom.z]).T Uv = Ut * v atom.x = float(Uv[1]) atom.y = float(Uv[2]) atom.z = float(Uv[0]) # for CNT atoms, calculate some properties min_x_CNT = 1000.0; max_x_CNT = -1000.0; radius_CNT = 0.0; height_CNT = 0.0; temp = []; min_y_CNT = 1000.0; max_y_CNT = -1000.0; min_z_CNT = 1000.0; max_z_CNT = -1000.0; CNT_orientation = ""; l_radius_CNT = []; l_x_CNT = []; l_y_CNT = []; for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) # center of CNT l_x_CNT.append(atom.x) l_y_CNT.append(atom.y) # height if atom.z < min_z_CNT: min_z_CNT = atom.z if atom.z > max_z_CNT: max_z_CNT = atom.z x_CNT, a = nu.meanstdv(l_x_CNT) y_CNT, a = nu.meanstdv(l_y_CNT) z_diff = max_z_CNT - min_z_CNT # radius of CNT for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) l_radius_CNT.append( math.sqrt( (atom.x - x_CNT)**2 + (atom.y - y_CNT)**2 )) radius_CNT, a = nu.meanstdv(l_radius_CNT) l_avg_radius_CNT.append(radius_CNT) ### get water molecules in CNT # inside the CNT := min_z_CNT <= z <= max_z_CNT and (x - (x_diff/2))**2 + (y - (y_diff/2))**2 < radius_CNT**2 # aNo_WAT_O_atoms: molecules which O atom is within CNT # we don't need to calculate H atoms. Let's consider only O atoms margin = 0.0; # water molecules far from the margin will be only considered aNo_WAT_O_in_CNT = [] aNo_WAT_O_not_in_CNT = [] myBGF2 = copy.deepcopy(myBGF) # delete graphenes for atom in myBGF2.a: if "GRA" in atom.rName: aNo_WAT_O_not_in_CNT.append(myBGF.a2i[atom.aNo]) # delete water molecules for aNo in aNo_WAT_O: atom = myBGF.getAtom(aNo) dist_sq = (atom.x - x_CNT)**2 + (atom.y - y_CNT)**2 if "WAT" in atom.rName and "O" in atom.ffType and min_z_CNT + margin <= atom.z and atom.z <= max_z_CNT - margin and dist_sq < radius_CNT**2: aNo_WAT_O_in_CNT.append(aNo) else: delete_list = []; dummy = bgftools.getmolecule(myBGF, myBGF.getAtom(aNo), delete_list) for i in delete_list: aNo_WAT_O_not_in_CNT.append(myBGF.a2i[i]) myBGF2.delAtoms(aNo_WAT_O_not_in_CNT) myBGF2.renumber() myBGF2.saveBGF(bgf_file[:-4] + "." + str(timestep) + "." + str(len(aNo_WAT_O_in_CNT)) + ".bgf") sys.stdout.write('Done ') sys.stdout.flush() print(len(aNo_WAT_O_in_CNT)) processed_step += 1; print('') return 1
def getHBond(bgf_file, trj_file, selection='', silent=False): # init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock hbond_dat = dict() d_crit = 3.5 a_crit = 30.0 myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) myPickle_file = bgf_file[:-4] + ".hbond.pickle" myDAT = open(bgf_file[:-4] + ".hbond.count.dat", "w") myDAT.write(str(sys.argv) + "\n") # how many steps to go? wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read() n_timestep = int(wc_trj_file.split()[0]) print("The trajectory contains " + str(n_timestep) + " timesteps.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 while 1: ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_timestep - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() ### Read try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn( "No image information no the trajectory file. Will be treated as unwrapped." ) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float( atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float( atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float( atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") pbc = myBGF.CRYSTX[:3] # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, myBGF.CRYSTX, silent=True) ### myBGF update complete! ### # get donor and acceptor # donors: O in ACT A = [] D = [] for atom in myBGF.a: if selection: if "O" in atom.ffType and eval(selection): A.append(atom) if "O" in atom.ffType and eval(selection): D.append(atom) else: if "O" in atom.ffType: A.append(atom) if "O" in atom.ffType: D.append(atom) if not len(A) or not len(D): nu.die( "There are no atoms which can make H_bond (especially O atoms)!" ) ### find hydrogen bonds # for all pairs of OC-HW sys.stdout.write('Hbonds.. ') sys.stdout.flush() hbonds = [] donors = [] acceptors = [] hydrogens = [] angles = [] distances = [] for d_atom in D: d = np.array([d_atom.x, d_atom.y, d_atom.z]) for a_atom in A: a = np.array([a_atom.x, a_atom.y, a_atom.z]) dist = nu.dist(d, a) #dist = bgf.distance(d_atom, a_atom) if 0.001 < dist < d_crit: # check H angle for ano in d_atom.CONECT: h_atom = myBGF.getAtom(ano) h = np.array([h_atom.x, h_atom.y, h_atom.z]) u = h - d v = a - d theta = np.dot(u, v) / norm(u) / norm(v) theta = np.degrees(arccos(theta)) #theta = bgf.angle(h_atom, d_atom, a_atom, radians=False) if theta < a_crit: hbonds.append([d_atom.aNo, a_atom.aNo]) donors.append(d_atom.aNo) acceptors.append(a_atom.aNo) hydrogens.append(h_atom.aNo) distances.append(dist) angles.append(theta) #n_hbond += 1 #print("%s %s" % (d_atom.rNo, a_atom.rNo)) hbond_dat[timestep] = hbonds sys.stdout.write( 'Done ') sys.stdout.flush() print("") for i in zip(donors, acceptors, hydrogens, distances, angles): print i sys.exit(0) myDAT.write("%d %d\n" % (timestep, len(hbonds))) # write output #myBGF.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".bgf") #myBGF2.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".bgf") t2 = time.time() # time mark elapsed_time = t2 - t1 pickle_f = open(myPickle_file, 'w') pickle.dump(hbond_dat, pickle_f) print('') myDAT.close() return 1
def getHbond(bgf_file, trj_file, ff_file='', selection='', out_file=''): '''analyze something within a timestep in a series of lammps trajectory. ''' # variables result = dict() # inner functions def get_line(file): with open(file, 'r') as f: for line in f: yield line # 1. Load BGF mybgf = bgf.BgfFile(bgf_file) N_BGF_ATOMS = len(mybgf.a) atom_frags = bt.getMoleculeList(mybgf) # 2. Read LAMMPS Trajectory mytrj = lt.lammpstrj(trj_file) mytrj.load() timesteps = sorted(mytrj.timesteps) N_HEADER = mytrj.nheader N_ATOMS = mytrj.natoms[timesteps[0]] N_BUFFER = N_HEADER + N_ATOMS if N_BGF_ATOMS != N_ATOMS: nu.die( "Number of atoms in trajectory file does not match with BGF file.") # 3. Determine dump style dump_keywords = mytrj._dump_style yes_scale = False if 'xs' in dump_keywords: yes_scale = True # 4. Update coordinates from the snapshot dump = get_line(trj_file) for t in tqdm.tqdm(timesteps, ncols=120, desc="Analyzing HBonds"): chunk = [next(dump) for i in range(N_BUFFER)] mybgf = update_coord(chunk, mybgf, mytrj.pbc[t], scaled=yes_scale) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, fragments=atom_frags, ff_file=ff_file, silent=True) ### collect data def calc_hbonds(): # variables A = [] D = [] hbonds = [] d_crit = 3.5 a_crit = 30.0 for atom in mybgf.a: if selection: if "O" in atom.ffType and eval(selection): A.append(atom) if "O" in atom.ffType and eval(selection): D.append(atom) else: if "O" in atom.ffType: A.append(atom) if "O" in atom.ffType: D.append(atom) if not len(A) or not len(D): nu.die( "There are no atoms which can make H_bond (O atoms so far)!" ) # calculate hbonds for d_atom in D: d = np.array([d_atom.x, d_atom.y, d_atom.z]) # donor coord neigh_anos = bt.get_neighbors_aNo(A, d, r=d_crit, pbc=mytrj.pbc[t], k=6) donors = [d_atom.aNo] + d_atom.CONECT for ano in neigh_anos: a_atom = mybgf.getAtom(ano) a = np.array([a_atom.x, a_atom.y, a_atom.z]) # acceptor coord acceptors = [a_atom.aNo] + a_atom.CONECT for ano in d_atom.CONECT: h_atom = mybgf.getAtom(ano) h = np.array([h_atom.x, h_atom.y, h_atom.z]) u = h - d v = a - d theta = np.dot(u, v) / norm(u) / norm(v) theta = np.degrees(arccos(theta)) if theta < a_crit: # HBond exists dist = nu.pbc_dist(a, d, mytrj.pbc[t]) dist_ah = nu.pbc_dist(d, h, mytrj.pbc[t]) # E_vdw sigma_r = O_sigma / dist sigma_r_6 = sigma_r**6 sigma_r_12 = sigma_r**12 E_vdw = 4.0 * O_epsilon * (sigma_r_12 - sigma_r_6) # E_vdw in kcal/mol # E_coul E_coul = 0.0 for i, j in itertools.product(donors, acceptors): atom1 = mybgf.getAtom(i) atom2 = mybgf.getAtom(j) a1 = [atom1.x, atom1.y, atom1.z] a2 = [atom2.x, atom2.y, atom2.z] dist_ij = nu.pbc_dist(a1, a2, mytrj.pbc[t]) E_coul += 332.06371 * atom1.charge * atom2.charge / dist_ij # E_coul in kcal/mol # E_hbond E_hbond = E_coul + E_vdw # E_hbond = E_vdw + E_coul # update for v4 # angle between H-O-H plane and O..O vector H1 = mybgf.getAtom(d_atom.CONECT[0]) h1 = [H1.x, H1.y, H1.z] # H1 H2 = mybgf.getAtom(d_atom.CONECT[1]) h2 = [H2.x, H2.y, H2.z] # H2 p = d - h1 q = d - h2 n = np.cross( p, q) # normal vector of the H1-O-H2 plane m = a - d # O..O vector alpha = np.dot(n, m) / norm(n) / norm(m) alpha = np.degrees( arcsin(alpha) ) # angle between H-O-H plane and O..O vector #hbonds.append([d_atom.aNo, a_atom.aNo, d, a, dist, theta, [E_coul, E_vdw, E_hbond]]) # v2 #hbonds.append([d_atom.aNo, a_atom.aNo, d, a, dist, theta, [E_coul, E_vdw, E_hbond], dist_ah]) # v3 hbonds.append([ d_atom.aNo, a_atom.aNo, d, a, dist, theta, [E_coul, E_vdw, E_hbond], dist_ah, alpha ]) # v4 return hbonds hbonds = calc_hbonds() result[t] = hbonds #break; # tester # 5. Analyze if not out_file: out_file = trj_file + ".hbonds.v4" pickle_file = out_file + ".pickle" with open(pickle_file, 'wb') as f: pickle.dump(result, f, protocol=pickle.HIGHEST_PROTOCOL) print("Success to save the result to a pickle file %s" % pickle_file)
def trj2data(dat_file, trj_file, step, skipVelocity, silent=False): # init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) ### LAMMPS Data dat_atoms = [] if not silent: print("== Step 1. Loading LAMMPS Data") if not os.path.exists(dat_file): nu.die("Please check the LAMMPS data file.") f_dat_file = open(dat_file) temp = f_dat_file.read().split('\n') dat_atom_start = temp.index('Atoms') dat_atom_end = temp.index('Bonds') dat_atoms = temp[dat_atom_start + 1:dat_atom_end] f_dat_file.close() ### LAMMPS Trajectory # how many steps to go? if not silent: print("== Step 2. Loading LAMMPS Trajectory") n_timestep = len(lt.getTrjInfo(trj_file)) print("The trajectory contains " + str(n_timestep) + " timesteps.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 if not silent: print("== Step 3. Reading LAMMPS Trajectory") while 1: try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_timestep - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Elapsed time for the previous step: " + "{0:4.1f}".format(elapsed_time) + " seconds, Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds = " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() processed_step += 1 ### if step is specified, then save only for that step. if step != "": if timestep == step: pass else: continue else: pass ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' flagVelocity = False if 'vx' in keywords or 'vy' in keywords or 'vz' in keywords: flagVelocity = True # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn( "No image information no the trajectory file. Will be treated as unwrapped." ) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float( atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float( atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float( atomcoord[4]) if not skipVelocity: if flagVelocity == True: atom.vx = float(atomcoord[5]) atom.vy = float(atomcoord[6]) atom.vz = float(atomcoord[7]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0) #myBGF.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".trjupdated.bgf") ### myBGF update complete! ### ### update LAMMPS data file ### myDAT = open(dat_file) myNewDAT = open(dat_file + "." + str(timestep), 'w') linecount = 0 while 1: line = myDAT.readline() if not line: break if linecount == 0: output = line.strip( "\n") + " and updated with timestep " + str( timestep) + " in " + trj_file + "\n" linecount += 1 myNewDAT.write(output) continue if "xlo " in line: output = "\t" + " {0:>10.6f} {1:>10.6f}".format( 0.0, boxsize[0]) + " xlo xhi\n" myNewDAT.write(output) continue elif "ylo " in line: output = "\t" + " {0:>10.6f} {1:>10.6f}".format( 0.0, boxsize[1]) + " ylo yhi\n" myNewDAT.write(output) continue elif "zlo " in line: output = "\t" + " {0:>10.6f} {1:>10.6f}".format( 0.0, boxsize[2]) + " zlo zhi\n" myNewDAT.write(output) continue if not "Atoms" in line: myNewDAT.write(line) else: myNewDAT.write("Atoms\n\n") for i in dat_atoms: if len(i) == 0: continue parse = i.split() atomNo = int(parse[0]) molNo = int(parse[1]) atomTypeNo = int(parse[2]) atom = myBGF.getAtom(atomNo) if atom.aNo != atomNo or atom.rNo != molNo: nu.die( "BGF and data file mismatch. Please check both files." ) else: output = "{0:>8} {1:>8} {2:>8} {3:10.5f} {4:10.5f} {5:10.5f} {6:10.5f} {7:12.8f} {8:12.8f} {9:12.8f}".format( atom.aNo, atom.rNo, atomTypeNo, atom.charge, atom.x, atom.y, atom.z, atom.vx, atom.vy, atom.vz) + "\n" myNewDAT.write(output) # consume for i in range(len(dat_atoms)): line = myDAT.readline() myNewDAT.write("\n") t2 = time.time() # time mark elapsed_time = t2 - t1 print('') return 1
def countWaterCNT(bgf_file, trj_file, fixed, silent): # init timestep = 0; l_timestep = []; line = []; n_header = 0; output = ""; radius_CNTs = []; t1 = 0; t2 = 0; # clock radius_CNT = 0.0; myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) # how many steps to go? #wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read() #n_timestep = int(wc_trj_file.split()[0]); n_timestep = len(lt.getTrjInfo(trj_file)) print("The trajectory contains " + str(n_timestep) + " timesteps.") # extract aNos of CNT in the BGF file aNo_CNT = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break; # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1]] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0; t1 = t2 = 0; elapsed_time = 0; while 1: try: chunk = [next(dumpatom) for i in range(natoms+n_header)] except StopIteration: break; timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1]]; boxsize = [float(i) for i in boxsize]; boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### Show progress t1 = time.time(); remaining_time = elapsed_time * (n_timestep - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Elapsed time for the previous step: " + "{0:4.1f}".format(elapsed_time) + " seconds, Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds = " + "{0:4.1f} minutes".format(remaining_time/60) + ") " + str(radius_CNT)) sys.stdout.flush() processed_step += 1; ### if step is specified, then save only for that step. if step != 0: if timestep == step: pass; else: continue; else: pass; ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die("Number of atoms in trajectory file does not match with BGF file.") mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn("No image information no the trajectory file. Will be treated as unwrapped.") atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float(atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float(atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float(atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass; #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0) #myBGF.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".trjupdated.bgf") ### myBGF update complete! ### if not fixed: ### rotate cnt to x axis # initialize for the moment of inertia and the center of mass calculation U = 0; Ut = 0; Uv = 0; Ixx = 0; Ixy = 0; Ixz = 0; Iyx = 0; Iyy = 0; Iyz = 0; Izx = 0; Izy = 0; Izz = 0; Mx = 0; My = 0; Mz = 0; # transpose for "all atoms in BGF": move COM of CNT as origin # com of CNT Mx = 0; My = 0; Mz = 0; for atom in myBGF.a: if "CNT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT # move for atom in myBGF.a: atom.x -= Mx atom.y -= My atom.z -= Mz # calculate the moment of inertia (MI) and the center of mass (COM) of CNT from "myBGF" for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) Ixx += (atom.y**2 + atom.z**2) / N_CNT Iyy += (atom.x**2 + atom.z**2) / N_CNT Izz += (atom.x**2 + atom.y**2) / N_CNT Ixy -= (atom.x * atom.y) / N_CNT Ixz -= (atom.x * atom.z) / N_CNT Iyz -= (atom.y * atom.z) / N_CNT # the moment of inertia tensor I = numpy.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]]) # eigenvalue & eigenvector calculation eigval, eigvec = numpy.linalg.eig(I) # eigval[0] is the minimum among the values. # rearrange the U vector U = numpy.matrix(eigvec) Ut = U.T # "myBGF" rotation for atom in myBGF.a: v = numpy.matrix([atom.x, atom.y, atom.z]).T Uv = Ut * v atom.x = float(Uv[0]) atom.y = float(Uv[1]) atom.z = float(Uv[2]) # for CNT atoms, calculate some properties min_x_CNT = 0.0; max_x_CNT = 0.0; height_CNT = 0.0; aNo_MtOH_C_not_in_CNT = []; temp = []; min_y_CNT = 0.0; max_y_CNT = 0.0; min_z_CNT = 0.0; max_z_CNT = 0.0; CNT_orientation = ""; # check the orientation of CNT for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) # minimum and maximum x coord of CNT: this will be the height of CNT if atom.x < min_x_CNT: min_x_CNT = atom.x if atom.x > max_x_CNT: max_x_CNT = atom.x if atom.y < min_y_CNT: min_y_CNT = atom.y if atom.y > max_y_CNT: max_y_CNT = atom.y if atom.z < min_z_CNT: min_z_CNT = atom.z if atom.z > max_z_CNT: max_z_CNT = atom.z x_diff = max_x_CNT - min_x_CNT y_diff = max_y_CNT - min_y_CNT z_diff = max_z_CNT - min_z_CNT if x_diff > y_diff and x_diff > z_diff: # CNT is aligned along x axis height_CNT = x_diff CNT_orientation = "x" elif y_diff > x_diff and y_diff > z_diff: # CNT is aligned along y axis height_CNT = y_diff CNT_orientation = "y" elif z_diff > x_diff and z_diff > y_diff: # CNT is aligned along z axis height_CNT = z_diff CNT_orientation = "z" if CNT_orientation == "x": for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) radius_CNT += math.sqrt(atom.y**2 + atom.z**2) # average radius of CNT elif CNT_orientation == "y": for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) radius_CNT += math.sqrt(atom.x**2 + atom.z**2) # average radius of CNT elif CNT_orientation == "z": for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) radius_CNT += math.sqrt(atom.x**2 + atom.y**2) # average radius of CNT radius_CNT = radius_CNT / N_CNT radius_CNTs.append(radius_CNT) output += str(timestep) + '\t' + str(radius_CNT) + '\n' #if not silent: print(str(timestep) + '\t' + str(radius_CNT) + '\n') # write output #myBGF.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".bgf") #myBGF2.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".bgf") t2 = time.time() # time mark elapsed_time = t2 - t1; #print(output) m, s = nu.meanstdv(radius_CNTs) output += "average: " + '\t' + str(m) + '\t' + str(s) + '\n' print('') print(output) return 1
def getSlipLength(bgf_file, trj_file, ff_file, n_step, n_avg_step, silent=False): # const PI = math.pi vdw_r_C = 1.7 # init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock l_data = [] # stores [r vz] l_F_N = [] l_F_N_inner = [] l_F_N_outer = [] # stores sum of friction force l_result = [] l_avg_radius_CNT = [] n_avg_count = 0 n_avg_count_step = 0 myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) myPkl = open(trj_file + ".method2.pickle", 'w') myOut = open(trj_file + ".method2.avg_vz.out", 'w') myOut.write(str(n_avg_step) + " steps are averaged.\n") myOut.write("AVG_STARTING_STEP\tAVG_vz\tF_N\tF_N_outer\tF_N_inner\n") # how many steps to go? if not silent: print("== Step 1. Loading LAMMPS Trajectory") wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read() n_timestep = int(wc_trj_file.split()[0]) if n_step == 0: n_step = n_timestep print("The trajectory contains " + str(n_timestep) + " timesteps.") # extract aNos of CNT in the BGF file aNo_CNT = [] aNo_WAT_O = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) # Oxygen in water if "WAT" in atom.rName and "O" in atom.aName: aNo_WAT_O.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # check if there exists water properly if len(aNo_WAT_O) == 0: nu.die("No water molecules in the BGF file.") if len(aNo_CNT) == 0: nu.die("No CNT molecules in the BGF file.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip( 'ATOMS ') # assume ATOMS id type xu yu zu vx vy vz fx fy fz # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 while 1: ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_step - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() if processed_step == n_step: break ### Read try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) l_timestep.append(timestep) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = 'unwrapped' # assume that "dump 1 all custom 100 ${sname}${rtemp}K.nvt.lammps id type xu yu zu vx vy vz fx fy fz" in lammps input # actual coordinate coordinfo = chunk[9:] # modified for fast treatment for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) atom.x = float(atomcoord[2]) # coord atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) atom.vx = float(atomcoord[5]) # vel atom.vy = float(atomcoord[6]) atom.vz = float(atomcoord[7]) if 'fx' in keywords: atom.fx = float(atomcoord[8]) # force atom.fy = float(atomcoord[9]) atom.fz = float(atomcoord[10]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0, True) ### myBGF update complete! ### # for CNT atoms, calculate some properties on CNT min_x_CNT = 0.0 max_x_CNT = 0.0 radius_CNT = 0.0 height_CNT = 0.0 aNo_WAT_O_not_in_CNT = [] temp = [] min_y_CNT = 0.0 max_y_CNT = 0.0 min_z_CNT = 0.0 max_z_CNT = 0.0 CNT_orientation = "" l_radius_CNT = [] l_x_CNT = [] l_y_CNT = [] for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) # center of CNT l_x_CNT.append(atom.x) l_y_CNT.append(atom.y) # height if atom.z < min_z_CNT: min_z_CNT = atom.z if atom.z > max_z_CNT: max_z_CNT = atom.z # center of CNT x_CNT, a = nu.meanstdv(l_x_CNT) y_CNT, a = nu.meanstdv(l_y_CNT) z_diff = max_z_CNT - min_z_CNT # radius of CNT for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) l_radius_CNT.append( math.sqrt((atom.x - x_CNT)**2 + (atom.y - y_CNT)**2)) radius_CNT, a = nu.meanstdv(l_radius_CNT) l_avg_radius_CNT.append(radius_CNT) ### get water molecules in CNT # inside the CNT := min_z_CNT <= z <= max_z_CNT and (x - (x_diff/2))**2 + (y - (y_diff/2))**2 < radius_CNT**2 margin = 0 # water molecules far from the margin will be only considered aNo_WAT_O_in_CNT = [] for aNo in aNo_WAT_O: atom = myBGF.getAtom(aNo) dist_sq = (atom.x - x_CNT)**2 + (atom.y - y_CNT)**2 if "WAT" in atom.rName and min_z_CNT + margin <= atom.z and atom.z <= max_z_CNT - margin and dist_sq < radius_CNT**2: aNo_WAT_O_in_CNT.append(aNo) else: pass ### find outer water layer and collect data aNo_WAT_outer = [] for aNo in aNo_WAT_O_in_CNT: atom = myBGF.getAtom(aNo) r = math.sqrt((atom.x - x_CNT)**2 + (atom.y - y_CNT)**2) # separate inner and outer water molecules # for (12, 12) outer is r >= 3 #if r >= 3: # 5 = 2 (depletion area) + 3 (outer shell) if radius_CNT - r <= 5: aNo_WAT_outer.append(aNo) #l_data.append(atom.vz*10**5) # outer water velocity = v_slip, original velocity unit: A/fs = 10^5 m/s # calculate z-directional velocity of water molecules vcm = sum vi mi / sum mi atom = myBGF.getAtom(aNo_WAT_outer[0]) mass_O = bgftools.getMass(myBGF, [aNo_WAT_outer[0]], ff_file) atom = myBGF.getAtom(atom.CONECT[0]) mass_H = bgftools.getMass(myBGF, [atom.aNo], ff_file) mass_H2O = mass_O + 2 * mass_H # H2O mass for aNo in aNo_WAT_outer: atom = myBGF.getAtom(aNo) # oxygen #vcmx = atom.vx * mass_O #vcmy = atom.vy * mass_O vcmz = atom.vz * mass_O for ano in atom.CONECT: atom2 = myBGF.getAtom(ano) #vcmx += atom.vx * mass_O #vcmy += atom.vy * mass_O vcmz += atom.vz * mass_H #vcmx /= mass_H2O #vcmy /= mass_H2O vcmz /= mass_H2O l_data.append(vcmz * 10**5) # calculate sum of forces on carbon atoms of CNT F_N = 0.0 F_N_outer = 0.0 F_N_inner = 0.0 for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) x, y = (atom.x - x_CNT, atom.y - y_CNT) theta = 0 if y >= 0: theta = math.acos(x / (math.sqrt(x**2 + y**2))) else: theta = -math.acos(x / (math.sqrt(x**2 + y**2))) F_N += atom.fy * math.cos(theta) + atom.fx * math.sin(theta) #F_N += abs(atom.fx * math.cos(theta) + atom.fy * math.sin(theta)) l_F_N.append(F_N) # timestep mark for starting average if n_avg_count == 0: n_avg_count_step = timestep n_avg_count += 1 # "Job's Done" counter # if the time comes.. average! if n_avg_count == n_avg_step: a = analyzeData(l_data) # average vz l_result.append( [timestep, a] ) # note the the timestep here is not the timestep that the average started. t, s = nu.meanstdv(l_F_N) # average force on CNT myOut.write( str(n_avg_count_step) + "\t" + str(a) + "\t" + str(t) + "\n") # reset l_data = [] n_avg_count = 0 l_F_N = [] sys.stdout.write( 'Done ') sys.stdout.flush() # ending for timestep treatment t2 = time.time() # time mark elapsed_time = t2 - t1 processed_step += 1 # write output pkl.dump(l_result, myPkl) print('') return 1
def getHbond(bgf_file, trj_file, ff_file='', selection='', out_file=''): '''analyze something within a timestep in a series of lammps trajectory. ''' # variables result = dict() # inner functions def get_line(file): with open(file, 'r') as f: for line in f: yield line # 1. Load BGF mybgf = bgf.BgfFile(bgf_file) N_BGF_ATOMS = len(mybgf.a) # 2. Read LAMMPS Trajectory #timesteps, N_HEADER, N_ATOMS = lt.getTrjInfo(trj_file) mytrj = lt.lammpstrj(trj_file) timesteps = mytrj.load() N_HEADER = mytrj.nheader N_ATOMS = mytrj.natoms[timesteps[0]] N_BUFFER = N_HEADER + N_ATOMS if N_BGF_ATOMS != N_ATOMS: nu.die( "Number of atoms in trajectory file does not match with BGF file.") # 3. Determine dump style dump_keywords = mytrj.dumpstyle yes_scale = False if 'xs' in dump_keywords: yes_scale = True # 4. Update coordinates from the snapshot dump = get_line(trj_file) for t in tqdm.tqdm(timesteps, ncols=120, desc="Analyzing HBonds"): chunk = [next(dump) for i in range(N_BUFFER)] mybgf.CRYSTX = mytrj.pbc[t] + [90.0, 90.0, 90.0] coords = chunk[9:] for c in coords: c = c.split(' ') atom = mybgf.getAtom(int(c[0])) if yes_scale: atom.x = float(c[2]) * pbc[0] atom.y = float(c[3]) * pbc[1] atom.z = float(c[4]) * pbc[2] else: atom.x = float(c[2]) atom.y = float(c[3]) atom.z = float(c[4]) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, ff_file=ff_file, silent=True) ### collect data def calc_hbonds(): # variables A = [] D = [] hbonds = [] d_crit = 3.5 a_crit = 30.0 for atom in mybgf.a: if selection: if "O" in atom.ffType and eval(selection): A.append(atom) if "O" in atom.ffType and eval(selection): D.append(atom) else: if "O" in atom.ffType: A.append(atom) if "O" in atom.ffType: D.append(atom) if not len(A) or not len(D): nu.die( "There are no atoms which can make H_bond (O atoms so far)!" ) # calculate hbonds for d_atom in D: d = np.array([d_atom.x, d_atom.y, d_atom.z]) # donor coord neigh_anos = bt.get_neighbors_aNo(A, d, r=d_crit, pbc=mytrj.pbc[t], k=6) donors = [d_atom.aNo] + d_atom.CONECT for ano in neigh_anos: a_atom = mybgf.getAtom(ano) a = np.array([a_atom.x, a_atom.y, a_atom.z]) # acceptor coord acceptors = [a_atom.aNo] + a_atom.CONECT for ano in d_atom.CONECT: h_atom = mybgf.getAtom(ano) h = np.array([h_atom.x, h_atom.y, h_atom.z]) u = h - d v = a - d theta = np.dot(u, v) / norm(u) / norm(v) theta = np.degrees(arccos(theta)) if theta < a_crit: dist = nu.pbc_dist(a, d, mytrj.pbc[t]) dist_dh = nu.pbc_dist(d, h, mytrj.pbc[t]) # E_vdw sigma_r = O_sigma / dist sigma_r_6 = sigma_r**6 sigma_r_12 = sigma_r**12 E_vdw = 4.0 * O_epsilon * (sigma_r_12 - sigma_r_6) # Evdw in kcal/mol # E_coul E_coul = 0.0 for i, j in itertools.product(donors, acceptors): atom1 = mybgf.getAtom(i) atom2 = mybgf.getAtom(j) a1 = [atom1.x, atom1.y, atom1.z] a2 = [atom2.x, atom2.y, atom2.z] dist_ij = nu.pbc_dist(a1, a2, mytrj.pbc[t]) E_coul += 332.06371 * atom1.charge * atom2.charge / dist_ij #E_coul /= 2.0 E_hbond = E_coul + E_vdw # E_hbond = E_vdw + E_coul #print("e_coul: %f, e_coul2: %f, E_coul: %f, E_vdw: %f, E_hbond: %f, O-O dist: %f, O-H dist: %f" % (e_coul, e_coul2, E_coul, E_vdw, E_hbond, dist, dist_a_dh)) #print("E_coul: %f, E_vdw: %f, E_hbond: %f, O-O dist: %f" % (E_coul, E_vdw, E_hbond, dist)) #hbonds.append([d_atom.aNo, a_atom.aNo, d, a, dist, theta, [E_coul, E_vdw, E_hbond]]) hbonds.append([ d_atom.aNo, a_atom.aNo, d, a, dist, theta, [E_coul, E_vdw, E_hbond], dist_dh ]) return hbonds hbonds = calc_hbonds() result[t] = hbonds #break; # tester # 5. Analyze if not out_file: out_file = trj_file + ".hbonds.v2" pickle_file = out_file + ".pickle" with open(pickle_file, 'wb') as f: pickle.dump(result, f, protocol=pickle.HIGHEST_PROTOCOL) print("Success to save the result to a pickle file %s" % pickle_file) '''
def getHbond(bgf_file, trj_file, ff_file='', selection='', out_file='', nsamples=0): '''analyze something within a timestep in a series of lammps trajectory. ''' # variables result = dict() # inner functions def get_line(file): with open(file, 'r') as f: for line in f: yield line # 1. Load BGF mybgf = bgf.BgfFile(bgf_file) N_BGF_ATOMS = len(mybgf.a) # 2. Read LAMMPS Trajectory #timesteps, N_HEADER, N_ATOMS = lt.getTrjInfo(trj_file) mytrj = lt.lammpstrj(trj_file) timesteps = mytrj.load() if nsamples: requested_timesteps = timesteps[-nsamples:] else: requested_timesteps = timesteps N_HEADER = mytrj.nheader N_ATOMS = mytrj.natoms[timesteps[0]] N_BUFFER = N_HEADER + N_ATOMS if N_BGF_ATOMS != N_ATOMS: nu.die( "Number of atoms in trajectory file does not match with BGF file.") A = [] D = [] if not selection: for atom in mybgf.a: if "O" in atom.ffType: A.append(atom) if "O" in atom.ffType: D.append(atom) # 3. Determine dump style dump_keywords = mytrj.dumpstyle # 4. Update coordinates from the snapshot dump = get_line(trj_file) for t in tqdm.tqdm(timesteps, ncols=120, desc="Analyzing HBonds"): chunk = [next(dump) for i in range(N_BUFFER)] t = int(chunk[1]) if not t in requested_timesteps: continue mybgf.CRYSTX = mytrj.pbc[t] + [90.0, 90.0, 90.0] coords = chunk[9:] for c in coords: c = c.split(' ') atom = mybgf.getAtom(int(c[0])) atom.x = float(c[2]) atom.y = float(c[3]) atom.z = float(c[4]) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, ff_file=ff_file, silent=True) ### collect data def calc_hbonds(): hbonds = [] d_crit = 3.6 if selection: for atom in mybgf.a: if "O" in atom.ffType and eval(selection): A.append(atom) if "O" in atom.ffType and eval(selection): D.append(atom) # calculate hbonds for d_atom in D: d = np.array([d_atom.x, d_atom.y, d_atom.z]) # donor coord neigh_anos = bt.get_neighbors_aNo(A, d, r=d_crit, pbc=mytrj.pbc[t], k=6) for ano in neigh_anos: a_atom = mybgf.getAtom(ano) a = np.array([a_atom.x, a_atom.y, a_atom.z]) # acceptor coord dist = nu.pbc_dist(a, d, mytrj.pbc[t]) if dist > 2.0: for ano in d_atom.CONECT: h_atom = mybgf.getAtom(ano) h = np.array([h_atom.x, h_atom.y, h_atom.z]) u = h - d v = a - d theta = np.dot(u, v) / norm(u) / norm(v) #theta = np.degrees(arccos(theta)) if -0.17364817766693034885171662676931 < theta < 1.0: hbonds.append([dist, np.degrees(theta)]) return hbonds hbonds = calc_hbonds() result[t] = hbonds #break; # tester # 5. Analyze if not out_file: out_file = trj_file + ".hbonds_pmf" pickle_file = out_file + ".pickle" with open(pickle_file, 'wb') as f: pickle.dump(result, f, protocol=pickle.HIGHEST_PROTOCOL) print("Success to save the result to a pickle file %s" % pickle_file)
def count_layer(bgf_file, trj_file, ff_file='', out_file='', prefix=''): '''measures confined density of graphene interlayer ''' # variables result = dict() r_vdw_C = 3.38383824 / 2 # inner functions def get_line(file): with open(file, 'r') as f: for line in f: yield line # 1. Load BGF mybgf = bgf.BgfFile(bgf_file) N_BGF_ATOMS = len(mybgf.a) # 2. Read LAMMPS Trajectory mytrj = lt.lammpstrj(trj_file) timesteps = mytrj.load() N_HEADER = mytrj.nheader N_ATOMS = mytrj.natoms[0] N_BUFFER = N_HEADER + N_ATOMS if N_BGF_ATOMS != N_ATOMS: nu.die( "Number of atoms in trajectory file does not match with BGF file.") # 3. Determine dump style dump_keywords = mytrj.dumpstyle yes_scale = False if 'xs' in dump_keywords: yes_scale = True # Mass wat_ano = [] for atom in mybgf.a: if atom.chain == "I": wat_ano.append(atom.aNo) mass = bt.getMass(mybgf, wat_ano, ff_file=ff_file) # 4. Update coordinates from the snapshot dump = get_line(trj_file) for t in tqdm.tqdm(timesteps, ncols=120, desc="Counting Atoms"): chunk = [next(dump) for i in range(N_BUFFER)] t = int(chunk[1]) mybgf.CRYSTX = mytrj.pbc[t] + [90.0, 90.0, 90.0] coords = chunk[9:] for c in coords: c = c.split(' ') atom = mybgf.getAtom(int(c[0])) if yes_scale: atom.x = float(c[2]) * pbc[0] atom.y = float(c[3]) * pbc[1] atom.z = float(c[4]) * pbc[2] else: atom.x = float(c[2]) atom.y = float(c[3]) atom.z = float(c[4]) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, ff_file=ff_file, silent=True) ### collect data def density(): # variables density = dict() # height avg_gra_z1 = bt.atoms_average( mybgf, 'atom.z', selection="'C_2G' in atom.ffType and atom.rNo == 1") avg_gra_z2 = bt.atoms_average( mybgf, 'atom.z', selection="'C_2G' in atom.ffType and atom.rNo == 2") dist = avg_gra_z2 - avg_gra_z1 eff_dist = avg_gra_z2 - avg_gra_z1 - 2 * r_vdw_C # volume x = mytrj.pbc[t][0] y = mytrj.pbc[t][1] volume = x * y * dist eff_volume = x * y * eff_dist # density density = mass / 6.022 / volume * 10 eff_density = mass / 6.022 / eff_volume * 10 return [ x, y, dist, mass, volume, eff_volume, eff_dist, density, eff_density ] density = density() result[t] = density # 5. Analyze timesteps = sorted(result.keys()) with open(prefix + '.trj.density.dat', 'w') as f: output = "#x\ty\tdist\tmass\tvolume\teff_volume\teff_dist\tdensity\teff_density\n" for t in timesteps: output += "%d " % t output += " ".join("%8.3f" % float(i) for i in result[t]) f.write(output)
def hard_work(mybgf, chunk): mybgf = update_coord(chunk, mybgf, mytrj.pbc[t], scaled=yes_scale) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, fragments=atom_frags, ff_file=ff_file, silent=True) ''' # find inwater boundary swr = 3.270615945/2 gwr = 3.057430885/2 margin = 5.0 gwa_y = bt.atoms_average(mybgf, 'atom.y', selection="'GWA' in atom.rName") gwb_y = bt.atoms_average(mybgf, 'atom.y', selection="'GWB' in atom.rName") if type == "gra": avg_z1 = bt.atoms_average(mybgf, 'atom.z', selection="'C_R' in atom.ffType and 'GRA' in atom.rName") # gra bottom avg_z2 = bt.atoms_average(mybgf, 'atom.z', selection="'C_R' in atom.ffType and 'GRB' in atom.rName") # gra top actual_distance = avg_z2 - avg_z1 elif type == "mos": avg_s3a_z2 = bt.atoms_average(mybgf, 'atom.z', selection="'S_3a' in atom.ffType and atom.rNo == 2") # mos2 top avg_s3b_z1 = bt.atoms_average(mybgf, 'atom.z', selection="'S_3b' in atom.ffType and atom.rNo == 1") # mos2 bottom actual_distance = avg_s3a_z2 - avg_s3b_z1 inwater_x = pbc[0] inwater_y = gwb_y - gwa_y + 2 * gwr - 2 * margin inwater_z = actual_distance - 2 * swr selection = "atom.y > {gwa_y} + {margin} and atom.y < {gwb_y} - {margin}".format(**vars()) ''' ### collect data def calc_hbonds(): # variables A = [] D = [] hbonds = [] d_crit = 3.5 a_crit = 30.0 for atom in mybgf.a: if selection: if "O" in atom.ffType and eval(selection): A.append(atom) if "O" in atom.ffType and eval(selection): D.append(atom) else: if "O" in atom.ffType: A.append(atom) if "O" in atom.ffType: D.append(atom) if not len(A) or not len(D): nu.die( "There are no atoms which can make H_bond (O atoms so far)!" ) # calculate hbonds for d_atom in D: d = np.array([d_atom.x, d_atom.y, d_atom.z]) # donor coord neigh_anos = bt.get_neighbors_aNo(A, d, r=d_crit, pbc=mytrj.pbc[t], k=6) donors = [d_atom.aNo] + d_atom.CONECT for ano in neigh_anos: a_atom = mybgf.getAtom(ano) a = np.array([a_atom.x, a_atom.y, a_atom.z]) # acceptor coord acceptors = [a_atom.aNo] + a_atom.CONECT for ano in d_atom.CONECT: h_atom = mybgf.getAtom(ano) h = np.array([h_atom.x, h_atom.y, h_atom.z]) u = h - d v = a - d theta = np.dot(u, v) / norm(u) / norm(v) theta = np.degrees(arccos(theta)) if theta < a_crit: # HBond exists dist = nu.pbc_dist(a, d, mytrj.pbc[t]) dist_ah = nu.pbc_dist(d, h, mytrj.pbc[t]) # E_vdw sigma_r = O_sigma / dist sigma_r_6 = sigma_r**6 sigma_r_12 = sigma_r**12 E_vdw = 4.0 * O_epsilon * (sigma_r_12 - sigma_r_6) # E_vdw in kcal/mol # E_coul E_coul = 0.0 for i, j in itertools.product( donors, acceptors): atom1 = mybgf.getAtom(i) atom2 = mybgf.getAtom(j) a1 = [atom1.x, atom1.y, atom1.z] a2 = [atom2.x, atom2.y, atom2.z] dist_ij = nu.pbc_dist(a1, a2, mytrj.pbc[t]) E_coul += 332.06371 * atom1.charge * atom2.charge / dist_ij # E_coul in kcal/mol # E_hbond E_hbond = E_coul + E_vdw # E_hbond = E_vdw + E_coul # update for v4 # angle between H-O-H plane and O..O vector H1 = mybgf.getAtom(d_atom.CONECT[0]) h1 = [H1.x, H1.y, H1.z] # H1 H2 = mybgf.getAtom(d_atom.CONECT[1]) h2 = [H2.x, H2.y, H2.z] # H2 p = d - h1 q = d - h2 n = np.cross( p, q) # normal vector of the H1-O-H2 plane m = a - d # O..O vector alpha = np.dot(n, m) / norm(n) / norm(m) alpha = np.degrees( arcsin(alpha) ) # angle between H-O-H plane and O..O vector hbonds.append([ d_atom.aNo, a_atom.aNo, d, a, dist, theta, [E_coul, E_vdw, E_hbond], dist_ah, alpha ]) # v4 return hbonds hb = calc_hbonds() return hb
def densityProfile(bgf_file, trj_file, ff_file, out_file, direction, cnt_direction, interval, avg_timestep, silent=False): nu.warn( "LAMMPS trajectory with NPT simulations will give you the wrong result." ) ### init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock vector = [0, 0, 1] # the axis of interest. in the acetone-water case, z direction. atominfo = dict() # atom data extracted from ff_file result = dict() axis = 0 # 1: x-axis, 2: y-axis, 3: z-axis ### direction if "x" in direction: axis = 0 elif "y" in direction: axis = 1 elif "z" in direction: axis = 2 else: nu.die("Error on reading direction.") ### CNT direction if "x" in cnt_direction: cnt_direction = 0 elif "y" in cnt_direction: cnt_direction = 1 elif "z" in cnt_direction: cnt_direction = 2 else: nu.die("Error on reading CNT direction.") ### open files myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) f_out_file = open(out_file + ".dat", 'w') f_avg_out_file = open(out_file + ".average.dat", 'w') f_pickle = open(out_file + ".pickle", 'w') f_avg_pickle = open(out_file + ".average.pickle", 'w') ### read residues from bgf_file residue = set() # kind of residues in BGF file dict_residue = dict() # stores residue numbers per each residue. RES1: [1, 2, ..], RES2: [6, 7, ..] for i in myBGF.a: rname = string.strip(i.rName) residue.add(rname) output = "" for i in residue: output += i + " " if not silent: print("Found " + str(len(residue)) + " residues in BGF file: " + str(output)) residue = list(residue) residue.append('TOTAL') for index, i in enumerate(residue): dict_residue[i] = index n_residue = len(residue) # number of residues (including total) ### if no CNT the die if "CNT" not in residue: nu.die( "It seems that the BGF file does not contain any CNT atoms. Exiting." ) ### extract aNos of CNT in the BGF file aNo_CNT = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) ### read mass from ff_file try: parse = ff_file.split(" ") except: nu.die( "Error occurred when reading the force field file.. Check your " + str(ff_file)) else: if not silent: print("Found " + str(len(parse)) + " Cerius2 Force Fields.") for i in parse: FF = dreiding.loadFF(i) temp_atominfo = dreiding.loadAtomTypes(FF) atominfo.update(temp_atominfo) ### read trajectory file # how many steps to go? n_timestep = len(lt.getTrjInfo(trj_file)) if not silent: print("The trajectory contains " + str(n_timestep) + " timesteps.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = line[8].strip('ATOMS ') initial_boxsize = copy.deepcopy(boxsize) # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 while 1: try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) l_timestep.append(timestep) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### if the box size changes, then stop (only takes NVT trajectory) for i in range(3): if abs(initial_boxsize[i] - boxsize[i]) > 0.1: nu.die( "Simulation box change detected in the trajectory file. NVT trajectory is required to continue." ) ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_timestep - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Elapsed time for the previous step: " + "{0:4.1f}".format(elapsed_time) + " seconds, Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds = " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() processed_step += 1 ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn( "No image information no the trajectory file. Will be treated as unwrapped." ) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float( atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float( atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float( atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0) ### DONE for updating trj on BGF file ### ### Do whatever I want: density profile ### find the CNT center radius_CNT = 0 cntx = cnty = cntz = 0 natoms_CNT = len(aNo_CNT) for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) cntx += atom.x cnty += atom.y cntz += atom.z cntx /= natoms_CNT cnty /= natoms_CNT cntz = natoms_CNT ### make a bin diagonal_length = 0.0 box_height = boxsize[cnt_direction] radial_bin_length = 0.0 x_length = boxsize[0] / 2 y_length = boxsize[1] / 2 z_length = boxsize[2] / 2 if cnt_direction == 0: diagonal_length = math.sqrt(boxsize[1]**2 + boxsize[2]**2) / 2 radial_bin_length = min(diagonal_length, y_length, z_length) elif cnt_direction == 1: diagonal_length = math.sqrt(boxsize[0]**2 + boxsize[2]**2) / 2 radial_bin_length = min(diagonal_length, x_length, z_length) elif cnt_direction == 2: diagonal_length = math.sqrt(boxsize[0]**2 + boxsize[1]**2) / 2 radial_bin_length = min(diagonal_length, y_length, z_length) # choose the shortest length among diagonal and half size of the box length #radial_bin_length = min(diagonal_length, boxsize[0]/2, boxsize[1]/2, boxsize[2]/2) bin = np.arange(0.0, math.ceil(radial_bin_length), interval) ### for every atoms, get atom coordinate and its type positions = [] # atom positions. [ res1, res2, ..., total ] masses = [] # used for a weight for histogram. [ res1, res2, ..., total ] hist = [] bin_edges = [] for i in range(n_residue): positions.append([]) masses.append([]) hist.append([]) bin_edges.append([]) for atom in myBGF.a: coord = [atom.x, atom.y, atom.z] dist = 0 # calculate radial distance from CNT center to atom if cnt_direction == 0: dist = math.sqrt((atom.y - cnty)**2 + (atom.z - cntz)**2) elif cnt_direction == 1: dist = math.sqrt((atom.x - cntx)**2 + (atom.z - cntz)**2) elif cnt_direction == 2: dist = math.sqrt((atom.x - cntx)**2 + (atom.y - cnty)**2) # total positions[-1].append(dist) masses[-1].append(atominfo[atom.ffType]['MASS']) # residues positions[dict_residue[atom.rName.strip()]].append(dist) masses[dict_residue[atom.rName.strip()]].append( atominfo[atom.ffType]['MASS']) ### histogram for i in range(n_residue): hist[i], bin_edges[i] = np.histogram(positions[i], bins=bin, weights=masses[i]) ### divide by volume for density vol = [] for j in range(len(hist[0])): vol.append(math.pi * (bin_edges[0][j + 1]**2 - bin_edges[0][j]**2) * box_height) for i in range(n_residue): hist[i] = hist[i] / 6.022 / vol * 10.0 # density ### store temp = dict() for i in range(n_residue): temp2 = dict() temp2['HIST'] = hist[i] temp2['BIN_EDGES'] = bin_edges[i] temp[residue[i]] = temp2 result[timestep] = temp ### end of loop: check elapsed time t2 = time.time() # time mark elapsed_time = t2 - t1 ### calculate average values if not silent: print("\nAveraging the last " + str(avg_timestep) + " timesteps..") avg_timesteps = l_timestep[-avg_timestep:] avg_hist = [] avg_bin_edges = [] for i in range(n_residue): avg_hist.append( np.zeros(len(result[l_timestep[-avg_timestep]]['TOTAL']['HIST']))) #avg_bin_edges.append(np.zeros(len(result[-avg_timestep]['TOTAL']['BIN_EDGES']))); for t in avg_timesteps: for r in result[t]: avg_hist[dict_residue[r]] += result[t][r]['HIST'] for i in range(n_residue): avg_hist[i] /= len(avg_timesteps) # normalize temp_avg = dict() # residue --- HIST, BIN_EDGES for i in residue: temp2 = dict() temp2['HIST'] = avg_hist[dict_residue[i]] temp2['BIN_EDGES'] = bin_edges[0] temp_avg[i] = temp2 ### write up a average data to file output = str(avg_timestep) + "\n" for r in temp_avg: output += str(r) + "\n" for index, i in enumerate(temp_avg[r]['HIST']): output += str( temp_avg[r]['BIN_EDGES'][index]) + "\t" + str(i) + "\n" output += "\n" f_avg_out_file.write(output) ### write up a whole data to file output = "" tkey = result.keys() tkey.sort() for t in tkey: output += str(t) + "\n" rkey = result[t].keys() rkey.sort() for r in rkey: output += str(r) + "\n" for index, i in enumerate(result[t][r]['HIST']): output += str( result[t][r]['BIN_EDGES'][index]) + "\t" + str(i) + "\n" output += "\n" output += "\n" f_out_file.write(output) ### write up a pickle object if not silent: print("Writing pickle object..") pickle.dump(result, f_pickle) f_pickle.close() pickle.dump(temp, f_avg_pickle) f_avg_pickle.close() ### return print('') return 1
def getVelocity(bgf_file, trj_file, n_step, silent=False): # const PI = math.pi vdw_r_C = 1.7 # init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock l_data = [] # stores vz l_avg_radius_CNT = [] myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) # how many steps to go? n_timestep = len(lt.getTrjInfo(trj_file)) if n_step == 0: n_step = n_timestep print("The trajectory contains " + str(n_timestep) + " timesteps.") print("The script will proceed for the last " + str(n_step) + " timesteps.") # extract aNos of CNT in the BGF file aNo_CNT = [] aNo_WAT_O = [] aNo_WAT_all = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) # Oxygen in water if "WAT" in atom.rName and "O" in atom.aName: aNo_WAT_O.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # check if there exists water properly if len(aNo_WAT_O) == 0: nu.die("No water molecules in the BGF file.") if len(aNo_CNT) == 0: nu.die("No CNT molecules in the BGF file.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 while 1: ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_step - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() if processed_step == n_step: break ### Read try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = 'unwrapped' # assume that "dump 1 all custom 100 ${sname}${rtemp}K.nvt.lammps id type xu yu zu vx vy vz" in lammps input # actual coordinate coordinfo = chunk[9:] del (chunk) # modified for fast treatment for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) atom.vx = float(atomcoord[5]) atom.vy = float(atomcoord[6]) atom.vz = float(atomcoord[7]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0, True) ### myBGF update complete! ### #aNo_WAT_O_in_CNT = copy.deepcopy(aNo_WAT_O) # for CNT atoms, calculate some properties min_x_CNT = 1000.0 max_x_CNT = -1000.0 radius_CNT = 0.0 height_CNT = 0.0 temp = [] min_y_CNT = 1000.0 max_y_CNT = -1000.0 min_z_CNT = 1000.0 max_z_CNT = -1000.0 CNT_orientation = "" l_radius_CNT = [] l_x_CNT = [] l_y_CNT = [] for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) # center of CNT l_x_CNT.append(atom.x) l_y_CNT.append(atom.y) # height if atom.z < min_z_CNT: min_z_CNT = atom.z if atom.z > max_z_CNT: max_z_CNT = atom.z x_CNT, a = nu.meanstdv(l_x_CNT) y_CNT, a = nu.meanstdv(l_y_CNT) z_diff = max_z_CNT - min_z_CNT # radius of CNT for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) l_radius_CNT.append( math.sqrt((atom.x - x_CNT)**2 + (atom.y - y_CNT)**2)) radius_CNT, a = nu.meanstdv(l_radius_CNT) l_avg_radius_CNT.append(radius_CNT) ### get water molecules in CNT # inside the CNT := min_z_CNT <= z <= max_z_CNT and (x - (x_diff/2))**2 + (y - (y_diff/2))**2 < radius_CNT**2 # aNo_WAT_O_atoms: molecules which O atom is within CNT # we don't need to calculate H atoms. Let's consider only O atoms margin = 0.0 # water molecules far from the margin will be only considered aNo_WAT_O_in_CNT = [] for aNo in aNo_WAT_O: atom = myBGF.getAtom(aNo) dist_sq = (atom.x - x_CNT)**2 + (atom.y - y_CNT)**2 if "WAT" in atom.rName and "O" in atom.ffType and min_z_CNT + margin <= atom.z and atom.z <= max_z_CNT - margin and dist_sq < radius_CNT**2: aNo_WAT_O_in_CNT.append(aNo) else: pass ### record number of water molecules in CNT l_data.append([timestep, len(aNo_WAT_O_in_CNT), radius_CNT, z_diff]) #sys.stdout.write('Done ') #sys.stdout.flush() t2 = time.time() # time mark elapsed_time = t2 - t1 processed_step += 1 print('') ftemp = open("countWater.profile", 'w') ftemp.write(str(sys.argv)) for i in l_data: output = str(i[0]) + '\t' + str(i[1]) + '\t' + str(i[2]) + '\t' + str( i[3]) + '\n' ftemp.write(output) ftemp.close() print( "numbers of water molecules are written in countWater.profile ..Done.") return 1
def countWaterCNT(bgf_file, trj_file, ff_file, n_step, do_hbonds, silent=False): # const PI = math.pi vdw_r_C = 1.7 # init timestep = 0; l_timestep = []; line = []; n_header = 0; t1 = 0; t2 = 0; # clock myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) myDAT = open(bgf_file[:-4] + ".calcDensity.count.dat", "w") myDAT2 = open(bgf_file[:-4] + ".calcDensity.hbond.dat", "w") myDAT3 = open(bgf_file[:-4] + ".calcDensity.configuration.dat", "w") myDAT.write(str(sys.argv) + "\n") myDAT.write("Time\tmin_X\tmax_X\tHeight\tRadius\tNumber\tVolume\tEff_volume\tExact_mass\tMass\tExact_den\tMtOH_den\tExact_eff_den\tMtOH_eff_den\tn_hbond\n") # how many steps to go? wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read() n_timestep = int(wc_trj_file.split()[0]); if n_step == 0: n_step = n_timestep; print("The trajectory contains " + str(n_timestep) + " timesteps.") print("The script will proceed for the last " + str(n_step) + " timesteps.") # extract aNos of CNT in the BGF file aNo_CNT = [] aNo_MtOH_C = [] aNo_MtOH_all = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) # Carbons in MeOH if "MET" in atom.rName and "C" in atom.aName: aNo_MtOH_C.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # check if there exists MtOH properly if len(aNo_MtOH_C) == 0: nu.die("No MtOH molecules in the BGF file.") if len(aNo_CNT) == 0: nu.die("No CNT molecules in the BGF file.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break; # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1]] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0; t1 = t2 = 0; elapsed_time = 0; while 1: ### Show progress t1 = time.time(); remaining_time = elapsed_time * (n_step - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time/60) + ")") sys.stdout.flush() processed_step += 1; if processed_step == n_step: break; aNo_MtOH_C_atoms = [] aNo_atoms_in_CNT = [] ### Read try: chunk = [next(dumpatom) for i in range(natoms+n_header)] except StopIteration: break; timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1]]; boxsize = [float(i) for i in boxsize]; boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die("Number of atoms in trajectory file does not match with BGF file.") mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn("No image information no the trajectory file. Will be treated as unwrapped.") atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float(atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float(atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float(atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass; #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0, True) ### myBGF update complete! ### aNo_MtOH_C_in_CNT = copy.deepcopy(aNo_MtOH_C) ### Realign whole system to x axis sys.stdout.write(' Realigning.. ') sys.stdout.flush() # initialize for the moment of inertia and the center of mass calculation U = 0; Ut = 0; Uv = 0; Ixx = 0; Ixy = 0; Ixz = 0; Iyx = 0; Iyy = 0; Iyz = 0; Izx = 0; Izy = 0; Izz = 0; Mx = 0; My = 0; Mz = 0; # transpose for "all atoms in BGF": move COM of CNT as origin # com of CNT Mx = 0; My = 0; Mz = 0; for atom in myBGF.a: if "CNT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT # move for atom in myBGF.a: atom.x -= Mx atom.y -= My atom.z -= Mz # calculate the moment of inertia (MI) and the center of mass (COM) of CNT from "myBGF" for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) Ixx += (atom.y**2 + atom.z**2) / N_CNT Iyy += (atom.x**2 + atom.z**2) / N_CNT Izz += (atom.x**2 + atom.y**2) / N_CNT Ixy -= (atom.x * atom.y) / N_CNT Ixz -= (atom.x * atom.z) / N_CNT Iyz -= (atom.y * atom.z) / N_CNT # the moment of inertia tensor I = numpy.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]]) # eigenvalue & eigenvector calculation eigval, eigvec = numpy.linalg.eig(I) # eigval[0] is the minimum among the values. # rearrange the U vector U = numpy.matrix(eigvec) Ut = U.T # "myBGF" rotation for atom in myBGF.a: v = numpy.matrix([atom.x, atom.y, atom.z]).T Uv = Ut * v atom.x = float(Uv[0]) atom.y = float(Uv[1]) atom.z = float(Uv[2]) # for CNT atoms, calculate some properties min_x_CNT = 0.0; max_x_CNT = 0.0; radius_CNT = 0.0; height_CNT = 0.0; aNo_MtOH_C_not_in_CNT = []; temp = []; min_y_CNT = 0.0; max_y_CNT = 0.0; min_z_CNT = 0.0; max_z_CNT = 0.0; CNT_orientation = ""; # check the orientation of CNT for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) # minimum and maximum x coord of CNT: this will be the height of CNT if atom.x < min_x_CNT: min_x_CNT = atom.x if atom.x > max_x_CNT: max_x_CNT = atom.x if atom.y < min_y_CNT: min_y_CNT = atom.y if atom.y > max_y_CNT: max_y_CNT = atom.y if atom.z < min_z_CNT: min_z_CNT = atom.z if atom.z > max_z_CNT: max_z_CNT = atom.z x_diff = max_x_CNT - min_x_CNT y_diff = max_y_CNT - min_y_CNT z_diff = max_z_CNT - min_z_CNT if x_diff > y_diff and x_diff > z_diff: # CNT is aligned along x axis height_CNT = x_diff CNT_orientation = "x" elif y_diff > x_diff and y_diff > z_diff: # CNT is aligned along y axis height_CNT = y_diff CNT_orientation = "y" elif z_diff > x_diff and z_diff > y_diff: # CNT is aligned along z axis height_CNT = z_diff CNT_orientation = "z" if CNT_orientation == "x": for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) radius_CNT += math.sqrt(atom.y**2 + atom.z**2) # average radius of CNT elif CNT_orientation == "y": for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) radius_CNT += math.sqrt(atom.x**2 + atom.z**2) # average radius of CNT elif CNT_orientation == "z": for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) radius_CNT += math.sqrt(atom.x**2 + atom.y**2) # average radius of CNT radius_CNT = radius_CNT / N_CNT ### Rotate y or z to x axis Tyx = numpy.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]]) Tzx = numpy.array([[0, 0, -1], [0, 1, 0], [1, 0, 0]]) if CNT_orientation == "y": for atom in myBGF.a: u = numpy.matrix([atom.x, atom.y, atom.z]).T Tu = Tyx*u atom.x = float(Tu[0]) atom.y = float(Tu[1]) atom.z = float(Tu[2]) min_x_CNT = min_y_CNT; max_x_CNT = max_y_CNT; elif CNT_orientation == "z": for atom in myBGF.a: u = numpy.matrix([atom.x, atom.y, atom.z]).T Tu = Tzx*u atom.x = float(Tu[0]) atom.y = float(Tu[1]) atom.z = float(Tu[2]) min_x_CNT = min_z_CNT; max_x_CNT = max_z_CNT; ### get MtOHs in CNT sys.stdout.write('Density.. ') sys.stdout.flush() # 1. aNo_atoms_in_CNT: exact atoms within CNT for atom in myBGF.a: ano = atom.aNo dist = math.sqrt(atom.y**2 + atom.z**2) if not "CNT" in atom.rName and atom.x > min_x_CNT and atom.x < max_x_CNT and dist < radius_CNT: # inside aNo_atoms_in_CNT.append(ano) else: # outside pass; # 2. aNo_MtOH_C_atoms: molecules which C atom is within CNT for aNo in aNo_MtOH_C: atom = myBGF.getAtom(aNo) dist = math.sqrt(atom.y**2 + atom.z**2) if atom.x > min_x_CNT and atom.x < max_x_CNT and dist < radius_CNT: # inside of the CNT pass; else: """ # delete atoms delete_list = []; dummy = bgftools.getmolecule(myBGF, myBGF.getAtom(aNo), delete_list) for i in delete_list: aNo_MtOH_C_not_in_CNT.append(myBGF.a2i[i]) """ # outside of the CNT aNo_MtOH_C_in_CNT.remove(aNo) for aNo in aNo_MtOH_C_in_CNT: anos = []; dummy = bgftools.getmolecule(myBGF, myBGF.getAtom(aNo), anos) for i in anos: aNo_MtOH_C_atoms.append(i) # calculate volume of CNT # radius: average radius - can't be applied in bent CNTs # height: maximum height of CNT # volume: radius**2 + height volume = (radius_CNT**2) * height_CNT * PI eff_volume = (radius_CNT - vdw_r_C)**2 * height_CNT * PI # calculate mass in CNT MtOH_exact_mass = bgftools.getMass(myBGF, aNo_atoms_in_CNT, ff_file) MtOH_MtOH_C_mass = bgftools.getMass(myBGF, aNo_MtOH_C_atoms, ff_file) # calculate density: mass / 6.022 / vol * 10 vol_exact_density = MtOH_exact_mass / 6.022 / volume * 10; vol_MtOH_density = MtOH_MtOH_C_mass / 6.022 / volume * 10; # calculate effective density ( radius - r_vdw ) eff_vol_exact_density = MtOH_exact_mass / 6.022 / eff_volume * 10; eff_vol_MtOH_density = MtOH_MtOH_C_mass / 6.022 / eff_volume * 10; ### Check MET status output = ""; MeOH_align = []; # find O in MET: MeOH_align = [C.x, O.x] for ano in aNo_MtOH_C_in_CNT: atom = myBGF.getAtom(ano) for i in atom.CONECT: atom2 = myBGF.getAtom(i) if "O" in atom2.ffType: MeOH_align.append([atom.x, atom2.x]) MeOH_align.sort(key=sortkey) # print MET align status for i in MeOH_align: if i[0] > i[1]: # C-O: 1 output += "1 " else: # O-C: 0 output += "0 " # n_hbond n_hbond = 0; """ # how many 10 or 01 (hydrogen bonds) in output? count += output.count("1 0") count += output.count("0 1") """ hbond_C_pairs = ""; hbond_OH_pairs = []; if do_hbonds: ### find hydrogen bonds ### criteria: r(O..O) <= 3.5, r(O..HO) <= 2.6, A(HO-O..O) <= 30' (ref: Haughney et al., JPC 1987) ### acceptor donor donor acceptor # for all pairs of MtOH molecules sys.stdout.write('Hbonds.. ') sys.stdout.flush() C_pairs = itertools.permutations(aNo_MtOH_C_in_CNT, 2) # count how many iterations on the permutations: #c_perm = 0; #for i in C_pairs: # c_perm += 1; #print(str(len(aNo_MtOH_C_in_CNT)) + " " + str(c_perm)) for p in C_pairs: (ano1, ano2) = p # Donor part # get C1 C1 = myBGF.getAtom(ano1) # get O1 for i in C1.CONECT: temp_atom = myBGF.getAtom(i) if "O" in temp_atom.ffType[0]: O1 = temp_atom # get H1 for i in O1.CONECT: temp_atom = myBGF.getAtom(i) if "H" in temp_atom.ffType[0]: H1 = temp_atom # Acceptor part # get C2 C2 = myBGF.getAtom(ano2) # get O2 for i in C2.CONECT: temp_atom = myBGF.getAtom(i) if "O" in temp_atom.ffType[0]: O2 = temp_atom # get H2 for i in O2.CONECT: temp_atom = myBGF.getAtom(i) if "H" in temp_atom.ffType[0]: H2 = temp_atom """ # H1 and O2 should be inside the CNT dist = math.sqrt(H1.y**2 + H1.z**2) if H1.x > min_x_CNT and H1.x < max_x_CNT and dist < radius_CNT: continue; dist = math.sqrt(O2.y**2 + O2.z**2) if O2.x > min_x_CNT and O2.x < max_x_CNT and dist < radius_CNT: continue; """ ## determine hbond # calculate r(O1..O2) crit_1 = bgf.distance(O1, O2); # calculate r(O1..H2) crit_2 = bgf.distance(O2, H1); # calculate A(O1-H2..O2) crit_3 = bgf.angle(H1, O1, O2); #if crit_1 <= 3.5 and crit_2 <= 2.6 and crit_3 <= 30: if crit_1 <= 3.5 and crit_3 <= 30: # Hbond!! n_hbond += 1; OH_pair = [O2.aNo, H1.aNo]; hbond_OH_pairs.append(OH_pair) #hbond_C_pairs += str(ano1) + "-" + str(ano2) + "\t" else: continue; hbond_pairs = hbond_OH_pairs #temp = nu.removeRepeat(hbond_OH_pairs) #hbond_pairs = nu.removeReverse(temp) sys.stdout.write('Done ') sys.stdout.flush() myDAT.write(str(timestep) + "\t") myDAT.write(str("{0:<8.3f}".format(min_x_CNT)) + "\t") myDAT.write(str("{0:<8.3f}".format(max_x_CNT)) + "\t") myDAT.write(str("{0:<8.3f}".format(height_CNT)) + "\t") myDAT.write(str("{0:<8.3f}".format(radius_CNT)) + "\t") myDAT.write(str(len(aNo_MtOH_C_in_CNT)) + "\t") myDAT.write(str("{0:<8.3f}".format(volume)) + "\t") myDAT.write(str("{0:<8.3f}".format(eff_volume)) + "\t") myDAT.write(str("{0:<8.3f}".format(MtOH_exact_mass)) + "\t") myDAT.write(str("{0:<8.3f}".format(MtOH_MtOH_C_mass)) + "\t") myDAT.write(str("{0:<8.3f}".format(vol_exact_density)) + "\t") myDAT.write(str("{0:<8.3f}".format(vol_MtOH_density)) + "\t") myDAT.write(str("{0:<8.3f}".format(eff_vol_exact_density)) + "\t") myDAT.write(str("{0:<8.3f}".format(eff_vol_MtOH_density) + "\t")) myDAT.write(str(len(hbond_pairs)) + "\n") myDAT2.write(str(hbond_pairs) + "\n") myDAT3.write(str(output) + "\n") #myDAT.write(str(aNo_MtOH_C_in_CNT) + "\n") # write output #myBGF.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".bgf") #myBGF2.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".bgf") t2 = time.time() # time mark elapsed_time = t2 - t1; print('') myDAT.close() myDAT2.close() return 1
def countWaterCNT(bgf_file, trj_file, d_crit=3.5, selection='', nsample=0, silent=False): ### init # constants deg_109p47 = math.radians(109.47) # variables timestep = 0 l_timestep = [] line = [] n_header = 0 avg_angles = [] avg_diheds = [] bin = np.arange(0.0, 181.0, 1.0) t1 = 0 t2 = 0 # clock myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) myDAT = open(bgf_file[:-4] + ".AOP.dat", "w") myDAT.write("#timestep\tAOP\tF4\n") # how many steps to go? #mytrj = lt.lammpstrj(trj_file) mytrj = Trj(trj_file) l_timestep = mytrj.load() n_timestep = len(l_timestep) l_timestep.sort() requested_timesteps = l_timestep[-nsample:] print( "Using neighboring water distance criteria %4.1f A (should be consistent with the coordination number)" % d_crit) print("The trajectory contains " + str(n_timestep) + " timesteps.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 while 1: ### Show progress t1 = time.time() remaining_time = elapsed_time * (len(requested_timesteps) - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() ### Read try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') if not timestep in requested_timesteps: continue ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn( "No image information no the trajectory file. Will be treated as unwrapped." ) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float( atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float( atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float( atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, myBGF.CRYSTX, silent=True) ### myBGF update complete! ### # get water OW O = [] anos_O = [] for atom in myBGF.a: if selection: if "O" in atom.ffType and eval(selection): O.append(atom) anos_O.append(atom.aNo) else: if "O" in atom.ffType: O.append(atom) anos_O.append(atom.aNo) if not len(O): nu.die("There are no O atoms which satisfies %s!" % selection) ### calculate AOP and F4 sys.stdout.write('AOP..... ') sys.stdout.flush() coords = [] anos = [] for atom in O: coords.append([atom.x, atom.y, atom.z]) anos.append(atom.aNo) pbc = np.array(myBGF.CRYSTX[:3]) coords = np.array(coords) tree = pkdtree.PeriodicKDTree( pbc, coords) # KDtree for distance calculation # analyze local water structures for a timestep n_neighbors = [] angles = [] diheds = [] for atom in O: # local variables # find neighbors neighbors = [] # list of O atoms near centerO centerO = np.array([atom.x, atom.y, atom.z]) d, ndx = tree.query(centerO, k=6) index = np.where((d >= 1e-4) & (d <= d_crit)) # discard self for i in ndx[index]: neighbors.append(myBGF.getAtom(anos[i])) # calculate O1-O-O2 angle for i, j in itertools.combinations(neighbors, 2): if not "O" in i.ffType or not "O" in j.ffType: nu.die("Wrong atom found.") x = [i.x, i.y, i.z] y = [j.x, j.y, j.z] pbc_dist = nu.pbc_dist(x, y, pbc) dist = nu.dist(x, y) if abs(pbc_dist - dist) > 0.1: continue # discard atoms over pbc boundaries # angle angle = nu.angle(x, centerO, y, radians=False) angles.append(angle) n_neighbors.append( len(neighbors)) # number of neighboring water molecules # calculate dihedral for i in neighbors: # find aNos of H located farthest among all combinations hO_anos = atom.CONECT hi_anos = i.CONECT max_dist_pair = [] max_dist = 0.0 for k, l in itertools.product(hO_anos, hi_anos): h1 = myBGF.getAtom(k) # H atom connected with atom h2 = myBGF.getAtom(l) # H atom connected with i dist = bgf.distance(h1, h2) if dist > max_dist: max_dist = dist max_dist_pair = [ h1, h2 ] # now we have two H atoms in maximum distance connected with atom and i # dihedral angle phi = bgf.dihedral(max_dist_pair[0], atom, i, max_dist_pair[1], radians=False) diheds.append(phi) hist_angle, _ = np.histogram(angles, bins=bin, normed=True) hist_dihed, _ = np.histogram(diheds, bins=bin, normed=True) avg_angles.append(hist_angle) avg_diheds.append(hist_dihed) sys.stdout.write( 'Done ') sys.stdout.flush() # write output processed_step += 1 t2 = time.time() # time mark elapsed_time = t2 - t1 avg_angles = np.mean(np.array(avg_angles), axis=0) avg_diheds = np.mean(np.array(avg_diheds), axis=0) #print(avg_diheds) myDAT.write("#angles population\n") for index, i in enumerate(avg_angles): myDAT.write("%8.2f %8.5f\n" % (_[index], avg_angles[index])) myDAT.write("\n\n") myDAT.write("#diheds population\n") for index, i in enumerate(avg_diheds): myDAT.write("%8.2f %8.5f\n" % (_[index], avg_diheds[index])) myDAT.close() print('') return 1
def dipole(bgf_file, trj_file, ff_file, out_file, avg_timestep, silent=False): ### init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock vector = [0, 0, 1] # the axis of interest. in the acetone-water case, z direction. atominfo = dict() # atom data extracted from ff_file result = dict() axis = 2 # for orientational distribution of dipole moments. 1: x-axis, 2: y-axis, 3: z-axis ### unit conversion for debye elementary_q = 1.602176487e-19 # elementary charge in C debye_conv = 3.33564e-30 # 1 Debye in C*m k = elementary_q * 1e-10 / debye_conv ### open files myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) myOUT = open(out_file + ".dat", 'w') #myOUT2 = open(out_file + ".angle.dat", 'w') myRESULT = open(out_file + ".pickle", 'w') myRESULT2 = open(out_file + ".histo.pickle", 'w') ### read residues from bgf_file residueNames = set() # kind of residues in BGF file residueNumbers = set() dict_residue = dict() # stores residue numbers per each residue. RES1: [1, 2, ..], RES2: [6, 7, ..] for i in myBGF.a: rname = string.strip(i.rName) residueNames.add(rname) rno = i.rNo residueNumbers.add(rno) temp = "" for i in residueNames: temp += i + " " dict_residue[i] = [] if not silent: print("Found " + str(len(residueNames)) + " residues in BGF file: " + str(temp)) ### bookkeep residue numbers for each residue molecules = bgftools.getMoleculeList(myBGF) for molecule in molecules: # get an atom atom = myBGF.getAtom(molecule[0]) atomresname = string.strip(atom.rName) atomresno = atom.rNo # check if all molecule has same residue name and numbers for ano in molecule: atom2 = myBGF.getAtom(ano) temp_rno = atom2.rNo temp_rname = string.strip(atom2.rName) if temp_rno != atomresno or temp_rname != atomresname: nu.die( "Different residue name or residue number in a same molecule: " + str(atom2.aNo)) # record resid for resnames dict_residue[atomresname].append(atom.rNo) ### read mass from ff_file try: parse = ff_file.split(" ") except: nu.die( "Error occurred when reading the force field file.. Check your " + str(ff_file)) else: if not silent: print("Found " + str(len(parse)) + " Cerius2 Force Fields.") for i in parse: FF = dreiding.loadFF(i) temp_atominfo = dreiding.loadAtomTypes(FF) atominfo.update(temp_atominfo) ### read trajectory file # how many steps to go? wc_trj_file = popen("grep -A 1 TIMESTEP " + trj_file).read() wc_trj_file = wc_trj_file.split() l_timestep = [] for i in wc_trj_file: if "ITEM" in i or "TIME" in i or "--" in i: pass else: l_timestep.append(i) l_timestep = [int(i) for i in l_timestep] l_timestep.sort() n_timestep = len(l_timestep) if not silent: print("The trajectory contains " + str(n_timestep) + " timesteps.") l_requested_timesteps = l_timestep[-avg_timestep:] # requested timesteps if not silent: print("Only requested the last " + str(avg_timestep) + " timesteps. ") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 while 1: try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) if not timestep in l_requested_timesteps: continue #l_timestep.append(timestep) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### Show progress t1 = time.time() remaining_time = elapsed_time * (len(l_requested_timesteps) - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Elapsed time for the previous step: " + "{0:4.1f}".format(elapsed_time) + " seconds, Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds = " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() processed_step += 1 ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn( "No image information no the trajectory file. Will be treated as unwrapped." ) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float( atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float( atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float( atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0) ### DONE for updating trj on BGF file ### ### Now Dipole Moment Calculation # list of all molecules in BGF dipole_moments = dict() abs_dipole_moments = dict() angles = dict() temp_dict = dict() output_dipole = str(timestep) + "\t" output_abs_dipole = str(timestep) + "\t" output_angle = str(timestep) + "\t" ### find bin for orientational distribution of dipole moment min = 100000 max = -100000 for atom in myBGF.a: coord = [atom.x, atom.y, atom.z] if coord[axis] < min: min = coord[axis] if coord[axis] > max: max = coord[axis] if boxsize[axis] > max: max = boxsize[axis] if 0 < min: min = 0 bins = np.arange(math.floor(min), math.ceil(max), 1.0) binned_rNo = dict() for r in residueNames: binned_rNo[r] = [[] for b in bins] # space for binned residue numbers (= molecules) binned_mu = copy.deepcopy(binned_rNo) ### For every molecule for molecule in molecules: n_atom = len(molecule) # number of atoms in the molecule residue_no = myBGF.getAtom(molecule[0]).rNo # residue number of the molecule residue_name = myBGF.getAtom(molecule[0]).rName # residue name of the molecule m = bgftools.getMass(myBGF, molecule, ff_file) # molecule mass cm = [0, 0, 0] # center of mass mu = [0, 0, 0] # dipole moment coord = [0, 0, 0] # atom x, y, z for aNo in molecule: atom = myBGF.getAtom(aNo) coord = [atom.x, atom.y, atom.z] # error if residue numbers are different if atom.rNo != residue_no: nu.die( "Residue numbers in a same molecule are not consistent. Please check your BGF file." ) # error if mass is unreadable ffType = string.strip(atom.ffType) try: aMass = atominfo[ffType]['MASS'] except: nu.die("Cannot read the atom type " + str(atom.ffType) + " in the data file.") # calculate CM for index, i in enumerate(coord): cm[index] += i * aMass cm = [i / m for i in cm] # center of mass #print(str(residue_no) + '\t' + str(cm)) # REMARK: it seems to be okay without this process. """ # translate the molecule to CM for aNo in molecule: atom = myBGF.getAtom(aNo) atom.x -= cm[0] atom.y -= cm[1] atom.z -= cm[2] """ # calculate dipole moment sum(qi * di) mu_i = [] for aNo in molecule: atom = myBGF.getAtom(aNo) coord = [atom.x, atom.y, atom.z] mu_i.append([i * atom.charge * k for i in coord]) # sum up mu = [0, 0, 0] for i in mu_i: mu[0] += i[0] mu[1] += i[1] mu[2] += i[2] # for acetone case #len_mu = math.sqrt(dot(mu, mu)) #len_vector = math.sqrt(dot(vector, vector)) len_mu = math.sqrt(dot(mu, mu)) len_vector = 1.0 #angle = dot(mu, vector) / ( len_mu * len_vector ) angle = mu[2] / (len_mu * len_vector) # for ACETONE case # results dipole_moments[residue_no] = mu abs_dipole_moments[residue_no] = len_mu angles[residue_no] = angle ### Orientational distribution of dipole moments # binning according to molecule's CM and store to binned_rNo for index, bin in enumerate(bins): try: if bin < cm[axis] and bins[index + 1] > cm[axis]: binned_rNo[residue_name][index].append(residue_no) except: continue # binning is perfect so far! residueNumbers = list(residueNumbers) residueNames = list(residueNames) residueNumbers.sort() temp_dict = dict() temp_dict2 = dict() temp_dict2['MU'] = dipole_moments temp_dict2['ABSMU'] = abs_dipole_moments temp_dict2['ANGLES'] = angles temp_dict['TOTAL'] = temp_dict2 ### paperworks per residue for resname in residueNames: temp_dict2 = dict() res_dipole_moments = dict() res_abs_dipole_moments = dict() res_angles = dict() # load residue numbers per residue type resnumbers = dict_residue[resname] for rno in resnumbers: res_dipole_moments[rno] = dipole_moments[rno] res_abs_dipole_moments[rno] = abs_dipole_moments[rno] res_angles[rno] = angles[rno] temp_dict2['MU'] = res_dipole_moments temp_dict2['ABSMU'] = res_abs_dipole_moments temp_dict2['ANGLES'] = res_angles temp_dict2['BIN'] = bins # for analyze #temp_dict2['RNO_DISTR'] = binned_rNo[resname] temp_dict2['DISTR_ANGLES'] = binned_mu[resname] temp_dict2['DISTR_ABSMU'] = binned_mu[resname] # write dipole moments for index, item in enumerate(binned_rNo[resname]): if len(item) == 0: continue for i in item: temp_dict2['DISTR_ANGLES'][index].append( temp_dict2['ANGLES'][i]) #temp_dict2['DISTR_ABSMU'][index].append(temp_dict2['ABSMU'][i]) temp_dict[resname] = temp_dict2 # result: timestep - residue - MU, ANGLES, NATOMS result[timestep] = temp_dict t2 = time.time() # time mark elapsed_time = t2 - t1 ### Averaging orientational distribution of dipole moments over timesteps #del temp_dict1 del temp_dict2 temp_dict1 = dict() # angles with keys: bin temp_dict2 = dict() # |mu| with keys: bin # append for r in residueNames: temp_dict1[r] = dict() temp_dict2[r] = dict() for t in l_requested_timesteps: for index, b in enumerate(result[t][r]['BIN']): if not temp_dict1[r].has_key(b): temp_dict1[r][b] = [] if not temp_dict2[r].has_key(b): temp_dict2[r][b] = [] # append averaged values avg, std = meanstdv(result[t][r]['DISTR_ANGLES'][index]) temp_dict1[r][b].append(avg) for i in result[t][r]['DISTR_ANGLES'][index]: temp_dict2[r][b].append(i) #for i in result[t][r]['DISTR_ABSMU'][index]: # temp_dict2[b].append(i) # average avg_angles = dict() avg_absmu = dict() avg_angles_stdev = dict() avg_absmu_stdev = dict() for r in residueNames: avg_angles[r] = dict() avg_absmu[r] = dict() avg_angles_stdev[r] = dict() avg_absmu_stdev[r] = dict() temp = temp_dict1[r].keys() temp.sort() for i in temp: avg_angles[r][i], avg_angles_stdev[r][i] = meanstdv( temp_dict1[r][i]) avg_absmu[r][i], avg_absmu_stdev[r][i] = meanstdv(temp_dict2[r][i]) # print for average print("") print("Averaged " + str(avg_timestep) + " timesteps out of " + str(n_timestep)) for r in residueNames: print(r) for i in temp: #print(str(i) + '\t' + str(temp_dict1[i])) print( str(i) + '\t' + str(avg_angles[r][i]) + '\t' + str(avg_angles_stdev[r][i])) print("") # save for debug output = "" for r in residueNames: for i in temp: output += str(i) + '\t' + str(temp_dict1[r][i]) + '\n' myOUT.write(output) myOUT.close() # save the pickle object pkl.dump(result, myRESULT) myRESULT.close() pkl.dump(temp_dict2, myRESULT2) myRESULT2.close() print('') return 1
def getHbond(bgf_file, trj_file, ff_file='', selection='', out_file='', n=0): '''analyze something within a timestep in a series of lammps trajectory. ''' # variables result = dict() # inner functions def get_line(file): with open(file, 'r') as f: for line in f: yield line # 1. Load BGF mybgf = bgf.BgfFile(bgf_file) N_BGF_ATOMS = len(mybgf.a) atom_frags = bt.getMoleculeList(mybgf) # 2. Read LAMMPS Trajectory mytrj = lt.lammpstrj(trj_file) timesteps = mytrj.load() N_HEADER = mytrj.nheader N_ATOMS = mytrj.natoms[timesteps[0]] N_BUFFER = N_HEADER + N_ATOMS if N_BGF_ATOMS != N_ATOMS: nu.die( "Number of atoms in trajectory file does not match with BGF file.") # 3. Determine dump style dump_keywords = mytrj.dumpstyle yes_scale = False if 'xs' in dump_keywords: yes_scale = True # 4. Update coordinates from the snapshot dump = get_line(trj_file) requested_t = sorted(timesteps)[-n:] for t in tqdm.tqdm(timesteps, ncols=120, desc="Analyzing HBonds", miniters=1): chunk = [next(dump) for i in range(N_BUFFER)] if not t in requested_t: continue mybgf = update_coord(chunk, mybgf, mytrj.pbc[t], scaled=yes_scale) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, fragments=atom_frags, ff_file=ff_file, silent=True) ### collect data def calc_hbonds(): # variables A = [] D = [] hbond_angles = [] d_crit = 3.5 a_crit = 30.0 for atom in mybgf.a: if selection: if "O" in atom.ffType and eval(selection): A.append(atom) if "O" in atom.ffType and eval(selection): D.append(atom) else: if "O" in atom.ffType: A.append(atom) if "O" in atom.ffType: D.append(atom) if not len(A) or not len(D): nu.die( "There are no atoms which can make H_bond (O atoms so far)!" ) # calculate hbonds for d_atom in D: d = np.array([d_atom.x, d_atom.y, d_atom.z]) # donor coord neigh_anos = bt.get_neighbors_aNo(A, d, r=d_crit, k=6) neigh_hbonded_coord = [] for ano in neigh_anos: a_atom = mybgf.getAtom(ano) a = np.array([a_atom.x, a_atom.y, a_atom.z]) # acceptor coord if bt.is_hbonded(mybgf, d_atom, a_atom): neigh_hbonded_coord.append(a) for i, j in itertools.combinations(neigh_hbonded_coord, 2): angle = nu.angle(i, d, j, radians=False) hbond_angles.append(angle) return hbond_angles hbonds = calc_hbonds() result[t] = hbonds #break; # tester # 5. Analyze if not out_file: out_file = trj_file + ".hbonds.angles." pickle_file = out_file + ".pickle" with open(pickle_file, 'wb') as f: pickle.dump(result, f, protocol=pickle.HIGHEST_PROTOCOL) print("Success to save the result to a pickle file %s" % pickle_file)
def getHbond(bgf_file, trj_file, ff_file='', selection='', out_file=''): '''analyze something within a timestep in a series of lammps trajectory. ''' # variables result = dict() # inner functions def get_line(file): with open(file, 'r') as f: for line in f: yield line # 1. Load BGF mybgf = bgf.BgfFile(bgf_file) N_BGF_ATOMS = len(mybgf.a) # 2. Read LAMMPS Trajectory #timesteps, N_HEADER, N_ATOMS = lt.getTrjInfo(trj_file) mytrj = lt.lammpstrj(trj_file) timesteps = mytrj.load() N_HEADER = mytrj.nheader N_ATOMS = mytrj.natoms[timesteps[0]] N_BUFFER = N_HEADER + N_ATOMS if N_BGF_ATOMS != N_ATOMS: nu.die( "Number of atoms in trajectory file does not match with BGF file.") # 3. Determine dump style dump_keywords = mytrj.dumpstyle yes_scale = False if 'xs' in dump_keywords: yes_scale = True # 4. Update coordinates from the snapshot dump = get_line(trj_file) for t in tqdm.tqdm(timesteps, ncols=120, desc="Analyzing HBonds"): chunk = [next(dump) for i in range(N_BUFFER)] t = int(chunk[1]) mybgf.CRYSTX = mytrj.pbc[t] + [90.0, 90.0, 90.0] coords = chunk[9:] for c in coords: c = c.split(' ') atom = mybgf.getAtom(int(c[0])) if yes_scale: atom.x = float(c[2]) * pbc[0] atom.y = float(c[3]) * pbc[1] atom.z = float(c[4]) * pbc[2] else: atom.x = float(c[2]) atom.y = float(c[3]) atom.z = float(c[4]) mybgf = bt.periodicMoleculeSort(mybgf, mybgf.CRYSTX, ff_file=ff_file, silent=True) ### collect data def calc_hbonds(): # variables A = [] D = [] hbonds = [] d_crit = 3.5 a_crit = 30.0 for atom in mybgf.a: if selection: if "O" in atom.ffType and eval(selection): A.append(atom) if "O" in atom.ffType and eval(selection): D.append(atom) else: if "O" in atom.ffType: A.append(atom) if "O" in atom.ffType: D.append(atom) if not len(A) or not len(D): nu.die( "There are no atoms which can make H_bond (O atoms so far)!" ) # calculate hbonds for d_atom in D: d = np.array([d_atom.x, d_atom.y, d_atom.z]) neigh_anos = bt.get_neighbors_aNo(A, d, r=d_crit, pbc=mytrj.pbc[t]) for ano in neigh_anos: a_atom = mybgf.getAtom(ano) h = bt.is_hbonded2(mybgf, d_atom, a_atom) # returns hbonded H coord if len(h) != 0: a = np.array([a_atom.x, a_atom.y, a_atom.z]) dist = nu.pbc_dist(a, d, mytrj.pbc[t]) u = h - d v = a - d theta = np.dot(u, v) / norm(u) / norm(v) theta = np.degrees(arccos(theta)) hbonds.append( [d_atom.aNo, a_atom.aNo, d, a, dist, theta]) return hbonds hbonds = calc_hbonds() result[t] = hbonds #break; # tester # 5. Analyze if not out_file: out_file = trj_file + ".hbonds.new2" pickle_file = out_file + ".pickle" with open(pickle_file, 'wb') as f: pickle.dump(result, f, protocol=pickle.HIGHEST_PROTOCOL) print("Success to save the result to a pickle file %s" % pickle_file)
def countWaterCNT(bgf_file, trj_file, step, doSave, silent=False): # init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) myDAT = open(bgf_file[:-4] + ".count.dat", "w") myDAT.write("Time\tmin_X\tmax_X\tHeight\tRadius\tNumber\n") # how many steps to go? wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read() n_timestep = int(wc_trj_file.split()[0]) print("The trajectory contains " + str(n_timestep) + " timesteps.") # extract aNos of CNT in the BGF file aNo_CNT = [] aNo_MtOH_C = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) # Carbons in MeOH if "MET" in atom.rName and "C" in atom.aName: aNo_MtOH_C.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 while 1: try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_timestep - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Elapsed time for the previous step: " + "{0:4.1f}".format(elapsed_time) + " seconds, Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds = " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() processed_step += 1 ### if step is specified, then save only for that step. if step != 0: if timestep == step: pass else: continue else: pass ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn( "No image information no the trajectory file. Will be treated as unwrapped." ) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float( atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float( atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float( atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0) #myBGF.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".trjupdated.bgf") ### myBGF update complete! ### aNo_MtOH_C_in_CNT = copy.deepcopy(aNo_MtOH_C) # initialize for the moment of inertia and the center of mass calculation U = 0 Ut = 0 Uv = 0 Ixx = 0 Ixy = 0 Ixz = 0 Iyx = 0 Iyy = 0 Iyz = 0 Izx = 0 Izy = 0 Izz = 0 Mx = 0 My = 0 Mz = 0 # transpose for "all atoms in BGF": move COM of CNT as origin # com of CNT Mx = 0 My = 0 Mz = 0 for atom in myBGF.a: if "CNT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT # move for atom in myBGF.a: atom.x -= Mx atom.y -= My atom.z -= Mz # calculate the moment of inertia (MI) and the center of mass (COM) of CNT from "myBGF" for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) Ixx += (atom.y**2 + atom.z**2) / N_CNT Iyy += (atom.x**2 + atom.z**2) / N_CNT Izz += (atom.x**2 + atom.y**2) / N_CNT Ixy -= (atom.x * atom.y) / N_CNT Ixz -= (atom.x * atom.z) / N_CNT Iyz -= (atom.y * atom.z) / N_CNT # the moment of inertia tensor I = numpy.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]]) # eigenvalue & eigenvector calculation eigval, eigvec = numpy.linalg.eig( I) # eigval[0] is the minimum among the values. # rearrange the U vector U = numpy.matrix(eigvec) Ut = U.T # "myBGF" rotation for atom in myBGF.a: v = numpy.matrix([atom.x, atom.y, atom.z]).T Uv = Ut * v atom.x = float(Uv[0]) atom.y = float(Uv[1]) atom.z = float(Uv[2]) """ # com of CNT Mx = 0; My = 0; Mz = 0; for atom in myBGF.a: if "CNT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT # transpose for "all atoms in BGF": move COM of CNT as origin for atom in myBGF.a: atom.x -= Mx atom.y -= My atom.z -= Mz """ # for CNT atoms, calculate some properties min_x_CNT = 0.0 max_x_CNT = 0.0 radius_CNT = 0.0 height_CNT = 0.0 aNo_MtOH_C_not_in_CNT = [] temp = [] min_y_CNT = 0.0 max_y_CNT = 0.0 min_z_CNT = 0.0 max_z_CNT = 0.0 CNT_orientation = "" # check the orientation of CNT for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) # minimum and maximum x coord of CNT: this will be the height of CNT if atom.x < min_x_CNT: min_x_CNT = atom.x if atom.x > max_x_CNT: max_x_CNT = atom.x if atom.y < min_y_CNT: min_y_CNT = atom.y if atom.y > max_y_CNT: max_y_CNT = atom.y if atom.z < min_z_CNT: min_z_CNT = atom.z if atom.z > max_z_CNT: max_z_CNT = atom.z x_diff = max_x_CNT - min_x_CNT y_diff = max_y_CNT - min_y_CNT z_diff = max_z_CNT - min_z_CNT if x_diff > y_diff and x_diff > z_diff: # CNT is aligned along x axis height_CNT = x_diff CNT_orientation = "x" elif y_diff > x_diff and y_diff > z_diff: # CNT is aligned along y axis height_CNT = y_diff CNT_orientation = "y" elif z_diff > x_diff and z_diff > y_diff: # CNT is aligned along z axis height_CNT = z_diff CNT_orientation = "z" if CNT_orientation == "x": for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) radius_CNT += math.sqrt(atom.y**2 + atom.z**2) # average radius of CNT elif CNT_orientation == "y": for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) radius_CNT += math.sqrt(atom.x**2 + atom.z**2) # average radius of CNT elif CNT_orientation == "z": for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) radius_CNT += math.sqrt(atom.x**2 + atom.y**2) # average radius of CNT radius_CNT = radius_CNT / N_CNT # determine whether C in MtOH is in the CNT Cylinder if doSave: myBGF2 = copy.deepcopy(myBGF) for aNo in aNo_MtOH_C: atom = myBGF.getAtom(aNo) if CNT_orientation == "x": dist = math.sqrt(atom.y**2 + atom.z**2) if atom.x > min_x_CNT and atom.x < max_x_CNT and dist < radius_CNT: # inside of the CNT pass else: # delete atoms delete_list = [] dummy = bgftools.getmolecule(myBGF, myBGF.getAtom(aNo), delete_list) for i in delete_list: aNo_MtOH_C_not_in_CNT.append(myBGF.a2i[i]) # outside of the CNT aNo_MtOH_C_in_CNT.remove(aNo) elif CNT_orientation == "y": dist = math.sqrt(atom.x**2 + atom.z**2) if atom.y > min_y_CNT and atom.y < max_y_CNT and dist < radius_CNT: pass else: # delete atoms delete_list = [] dummy = bgftools.getmolecule(myBGF, myBGF.getAtom(aNo), delete_list) for i in delete_list: aNo_MtOH_C_not_in_CNT.append(myBGF.a2i[i]) # outside of the CNT aNo_MtOH_C_in_CNT.remove(aNo) elif CNT_orientation == "z": dist = math.sqrt(atom.x**2 + atom.y**2) if atom.z > min_z_CNT and atom.z < max_z_CNT and dist < radius_CNT: pass else: # delete atoms delete_list = [] dummy = bgftools.getmolecule(myBGF, myBGF.getAtom(aNo), delete_list) for i in delete_list: aNo_MtOH_C_not_in_CNT.append(myBGF.a2i[i]) # outside of the CNT aNo_MtOH_C_in_CNT.remove(aNo) myBGF2.delAtoms(aNo_MtOH_C_not_in_CNT) myBGF2.renumber() myDAT.write(str(timestep) + "\t") myDAT.write(str("{0:<8.3f}".format(min_x_CNT))) myDAT.write(str("{0:<8.3f}".format(max_x_CNT))) myDAT.write(str("{0:<8.3f}".format(min_y_CNT))) myDAT.write(str("{0:<8.3f}".format(max_y_CNT))) myDAT.write(str("{0:<8.3f}".format(min_z_CNT))) myDAT.write(str("{0:<8.3f}".format(max_z_CNT))) myDAT.write(str("{0:<8.3f}".format(height_CNT))) myDAT.write(str("{0:<8.3f}".format(radius_CNT))) myDAT.write(str(len(aNo_MtOH_C_in_CNT)) + "\n") #myDAT.write(str(aNo_MtOH_C_in_CNT) + "\n") # write output if doSave: myBGF2.saveBGF(bgf_file[:-4] + "." + str(timestep) + ".bgf") t2 = time.time() # time mark elapsed_time = t2 - t1 print('') return 1
def countWaterCNT(bgf_file, trj_file, out_file, silent=False): # const PI = math.pi vdw_r_C = 1.7 # init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) myNewTRJ = open(out_file, 'w') # how many steps to go? wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read() n_timestep = int(wc_trj_file.split()[0]) print("The trajectory contains " + str(n_timestep) + " timesteps.") # extract aNos of CNT in the BGF file aNo_CNT = [] aNo_MtOH_all = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # check if there exists MtOH properly if len(aNo_CNT) == 0: nu.die("No CNT molecules in the BGF file.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 d_atomtype = dict() # dict for writing atom types # check flag for atom informations: the first shot will be treated, and will be skipped after. firsttimeFlag = 0 while 1: ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_timestep - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() processed_step += 1 ### Read try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn( "No image information no the trajectory file. Will be treated as unwrapped." ) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float( atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float( atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float( atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") ### for the first shot, record atom types if firsttimeFlag == 0: d_atomtype[int(atomcoord[0])] = atomcoord[1] ### myBGF update complete! ### ### Realign whole system to x axis sys.stdout.write(' Realigning.. ') sys.stdout.flush() # initialize for the moment of inertia and the center of mass calculation U = 0 Ut = 0 Uv = 0 Ixx = 0 Ixy = 0 Ixz = 0 Iyx = 0 Iyy = 0 Iyz = 0 Izx = 0 Izy = 0 Izz = 0 Mx = 0 My = 0 Mz = 0 # transpose for "all atoms in BGF": move COM of CNT as origin # com of CNT Mx = 0 My = 0 Mz = 0 for atom in myBGF.a: if "CNT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT # move for atom in myBGF.a: atom.x += Mx atom.y += My atom.z += Mz # calculate the moment of inertia (MI) and the center of mass (COM) of CNT from "myBGF" for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) Ixx += (atom.y**2 + atom.z**2) / N_CNT Iyy += (atom.x**2 + atom.z**2) / N_CNT Izz += (atom.x**2 + atom.y**2) / N_CNT Ixy -= (atom.x * atom.y) / N_CNT Ixz -= (atom.x * atom.z) / N_CNT Iyz -= (atom.y * atom.z) / N_CNT # the moment of inertia tensor I = numpy.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]]) # eigenvalue & eigenvector calculation eigval, eigvec = numpy.linalg.eig( I) # eigval[0] is the minimum among the values. # rearrange the U vector U = numpy.matrix(eigvec) Ut = U.T # "myBGF" rotation for atom in myBGF.a: v = numpy.matrix([atom.x, atom.y, atom.z]).T Uv = Ut * v atom.x = float(Uv[0]) atom.y = float(Uv[1]) atom.z = float(Uv[2]) ### update crystx information: note that CNT is along x-axis. # is this right?? 20130619 if boxsize[0] > boxsize[1] and boxsize[0] > boxsize[2]: boxsize = [boxsize[0], boxsize[1], boxsize[2]] elif boxsize[1] > boxsize[0] and boxsize[1] > boxsize[2]: boxsize = [boxsize[1], boxsize[0], boxsize[2]] elif boxsize[2] > boxsize[0] and boxsize[2] > boxsize[1]: boxsize = [boxsize[2], boxsize[0], boxsize[1]] for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] # transpose to the center of box for atom in myBGF.a: atom.x += (boxsize[0] / 2) atom.y += (boxsize[1] / 2) atom.z += (boxsize[2] / 2) # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0) ### Write LAMMPS trjectory output = "ITEM: TIMESTEP\n" output += str(timestep) + "\n" output += "ITEM: NUMBER OF ATOMS\n" output += str(natom_bgf) + "\n" output += "ITEM: BOX BOUNDS pp pp pp\n" output += "0 " + str(boxsize[0]) + "\n" output += "0 " + str(boxsize[1]) + "\n" output += "0 " + str(boxsize[2]) + "\n" output += "ITEM: ATOMS id type xu yu zu\n" for atom in myBGF.a: output += str(atom.aNo) + " " + d_atomtype[atom.aNo] + " " + str( atom.x) + " " + str(atom.y) + " " + str(atom.z) + "\n" myNewTRJ.write(output) t2 = time.time() # time mark elapsed_time = t2 - t1 myNewTRJ.close() print('') return 1
def getSlipLength(bgf_file, trj_file, ff_file, interval, n_step, n_avg_step, silent=False): """ This calculates the profile of averaged velocity according to r. NOTE: This is different from averaged velocity profile according to r. """ # const PI = math.pi vdw_r_C = 1.7 # init timestep = 0 l_timestep = [] line = [] n_header = 0 output = "" t1 = 0 t2 = 0 # clock myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) myPkl = open( trj_file + ".profile.r_ave_vel-s" + str(n_step) + "k" + str(n_skip) + ".pickle", 'w') #f_dump = open(trj_file + ".profile.r_ave_vel.dump", 'w') #dump = ""; # how many steps to go? n_timestep = len(lt.getTrjInfo(trj_file, silent=False)) if n_step == 0: n_step = n_timestep if not silent: print("The trajectory contains " + str(n_timestep) + " timesteps.") # extract aNos of CNT in the BGF file aNo_CNT = [] aNo_WAT_O = [] aNo_WAT_all = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) # Oxygen in water if "WAT" in atom.rName and "O" in atom.aName: aNo_WAT_O.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # check if there exists water properly if len(aNo_WAT_O) == 0: nu.die("No water molecules in the BGF file.") if len(aNo_CNT) == 0: nu.die("No CNT molecules in the BGF file.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 # calculate radius_CNT avg_radius_CNT = 0.0 x_CNT = 0.0 y_CNT = 0.0 if not silent: print( "Calculating the average radius of CNT throughout the averaging steps" ) while 1: ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_step - processed_step) ### Read try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break # skip if necessary if processed_step <= n_skip: processed_step += 1 continue timestep = int(chunk[1]) l_timestep.append(timestep) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') sys.stdout.write('\r' + "Fetched timestep: " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file mode = 'unwrapped' # assume that "dump 1 all custom 100 ${sname}${rtemp}K.nvt.lammps id type xu yu zu vx vy vz" in lammps input # actual coordinate coordinfo = chunk[9:] # modified for fast treatment for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass # apply periodic condition #myBGF = bgftools.periodicMoleculeSort(myBGF, 0, True) ### myBGF update complete! ### # for CNT atoms, calculate some properties min_x_CNT = 0.0 max_x_CNT = 0.0 radius_CNT = 0.0 height_CNT = 0.0 aNo_WAT_O_not_in_CNT = [] temp = [] min_y_CNT = 0.0 max_y_CNT = 0.0 min_z_CNT = 0.0 max_z_CNT = 0.0 CNT_orientation = "" l_radius_CNT = [] l_x_CNT = [] l_y_CNT = [] for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) # center of CNT l_x_CNT.append(atom.x) l_y_CNT.append(atom.y) # height if atom.z < min_z_CNT: min_z_CNT = atom.z if atom.z > max_z_CNT: max_z_CNT = atom.z x_CNT, a = nu.meanstdv(l_x_CNT) y_CNT, a = nu.meanstdv(l_y_CNT) z_diff = max_z_CNT - min_z_CNT # radius of CNT for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) l_radius_CNT.append( math.sqrt((atom.x - x_CNT)**2 + (atom.y - y_CNT)**2)) radius_CNT, a = nu.meanstdv(l_radius_CNT) l_avg_radius_CNT.append(radius_CNT) if processed_step > 3: break avg_radius_CNT, s = nu.meanstdv(l_avg_radius_CNT) bins = np.arange(0.0, math.ceil(radius_CNT), interval) l_radial_vz_profile = np.zeros(len(bins) - 1) if not silent: print("\nAveraged CNT radius: " + str(avg_radius_CNT) + " A") if not silent: print("CNT center: " + str([x_CNT, y_CNT])) # calculate properties myTRJ.close() myTRJ = open(trj_file) myTRJ.seek(0) dumpatom = get_line(trj_file) processed_step = 0 r = [] vz = [] # data container while 1: data = dict() # stores [r vz] for a timestep ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_step - processed_step) ### Read try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break if processed_step <= n_skip: processed_step += 1 continue timestep = int(chunk[1]) l_timestep.append(timestep) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') sys.stdout.write('\r' + "Fetched timestep: " + str(timestep) + " (Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds, " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = 'unwrapped' # assume that "dump 1 all custom 100 ${sname}${rtemp}K.nvt.lammps id type xu yu zu vx vy vz" in lammps input # actual coordinate coordinfo = chunk[9:] # modified for fast treatment for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) atom.vx = float(atomcoord[5]) atom.vy = float(atomcoord[6]) atom.vz = float(atomcoord[7]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0, True) ### myBGF update complete! ### # calculate z-directional velocity of water molecules wrt r vcm = sum vi mi / sum mi atom = myBGF.getAtom(aNo_WAT_O[0]) mass_O = bgftools.getMass(myBGF, [aNo_WAT_O[0]], ff_file) atom = myBGF.getAtom(atom.CONECT[0]) mass_H = bgftools.getMass(myBGF, [atom.aNo], ff_file) mass_H2O = mass_O + 2 * mass_H # H2O mass for ano in aNo_WAT_O: atom = myBGF.getAtom(ano) # oxygen # com & velocity calculation cmx = atom.x * mass_O cmy = atom.y * mass_O vcmz = atom.vz * mass_O for ano2 in atom.CONECT: atom2 = myBGF.getAtom(ano2) cmx += atom2.x * mass_H cmy += atom2.y * mass_H vcmz += atom2.vz * mass_H cmx /= mass_H2O cmy /= mass_H2O vcmz /= mass_H2O dist = math.sqrt((x_CNT - cmx)**2 + (y_CNT - cmy)**2) r.append(dist) vz.append(vcmz * 10**5) # LAMMPS real unit conversion for velocity # timestep mark for starting average if l_avg_count == []: n_avg_count_step = timestep l_avg_count.append(timestep) # if the time has come.. average! if len(l_avg_count) == n_avg_step or processed_step == n_timestep - 1: if not silent: print(" Averaging invoked at timestep " + str(timestep) + " (" + str(len(l_avg_count)) + " points)") # binning vz = np.array(vz) sum_vz = np.ma.array(np.histogram(r, bins, weights=vz)[0]) sum_vz2 = np.ma.array(np.histogram(r, bins, weights=vz * vz)[0]) n_vz = np.ma.array(np.histogram(r, bins)[0]) #mask_n = ma.masked_values(n_vz, 0) mean = sum_vz / n_vz std = np.sqrt(sum_vz2 / n_vz - mean * mean) mean = np.ma.fix_invalid(mean, fill_value=0.0).data std = np.ma.fix_invalid(std, fill_value=0.0).data n_vz = np.ma.fix_invalid(n_vz, fill_value=0).data if len(mean) != len(bins) - 1 or len(std) != len(bins) - 1: nu.die("on numpy masked_array calculation!") l_result.append([l_avg_count, bins, n_vz, mean, std]) # reset r = [] vz = [] l_radial_vz_profile = np.zeros(len(bins) - 1) l_avg_count = [] t2 = time.time() # time mark elapsed_time = t2 - t1 processed_step += 1 #f_dump.write(dump) pkl.dump(l_result, myPkl) print('') return 1
def getHBond(bgf_file, trj_file, out_file, direction, interval, avg_timestep, silent=False): nu.warn( "LAMMPS trajectory with NPT simulations will give you the wrong result." ) ### init timestep = 0 l_timestep = [] line = [] n_header = 0 t1 = 0 t2 = 0 # clock vector = [0, 0, 1] # the axis of interest. in the acetone-water case, z direction. atominfo = dict() # atom data extracted from ff_file result = dict() axis = 0 # 1: x-axis, 2: y-axis, 3: z-axis ### direction if "x" in direction: axis = 0 elif "y" in direction: axis = 1 elif "z" in direction: axis = 2 else: nu.die("Error on reading direction.") ### open files myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) f_out_file = open(out_file + ".dat", 'w') f_avg_out_file = open(out_file + ".average.dat", 'w') f_pickle = open(out_file + ".pickle", 'w') f_avg_pickle = open(out_file + ".average.pickle", 'w') ### read residues from bgf_file residue = set() # kind of residues in BGF file dict_residue = dict() # stores residue numbers per each residue. RES1: [1, 2, ..], RES2: [6, 7, ..] for i in myBGF.a: rname = string.strip(i.rName) residue.add(rname) output = "" for i in residue: output += i + " " if not silent: print("Found " + str(len(residue)) + " residues in BGF file: " + str(output)) residue = list(residue) residue.append('TOTAL') for index, i in enumerate(residue): dict_residue[i] = index n_residue = len(residue) # number of residues (including total) ### read trajectory file # how many steps to go? wc_trj_file = popen("grep TIMESTEP " + trj_file + " | wc -l ").read() n_timestep = int(wc_trj_file.split()[0]) print("The trajectory contains " + str(n_timestep) + " timesteps.") # Find header of the trajectory file while 1: templine = myTRJ.readline() line.append(templine.strip('\n').strip('ITEM: ')) n_header += 1 if "ITEM: ATOMS" in templine: break # INITIAL trajectory information timestep = int(line[1]) natoms = int(line[3]) boxsize = [ line[5].split(' ')[0], line[5].split(' ')[1], line[6].split(' ')[0], line[6].split(' ')[1], line[7].split(' ')[0], line[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] keywords = line[8].strip('ATOMS ') # for every shot in the trajectory file update BGF and manipulate dumpatom = get_line(trj_file) processed_step = 0 t1 = t2 = 0 elapsed_time = 0 while 1: try: chunk = [next(dumpatom) for i in range(natoms + n_header)] except StopIteration: break timestep = int(chunk[1]) l_timestep.append(timestep) natoms = int(chunk[3]) boxsize = [ chunk[5].split(' ')[0], chunk[5].split(' ')[1], chunk[6].split(' ')[0], chunk[6].split(' ')[1], chunk[7].split(' ')[0], chunk[7].split(' ')[1] ] boxsize = [float(i) for i in boxsize] boxsize = [(boxsize[1] - boxsize[0]), (boxsize[3] - boxsize[2]), (boxsize[5] - boxsize[4])] keywords = chunk[8].split('ATOMS ')[1].strip('\n').split(' ') ### Show progress t1 = time.time() remaining_time = elapsed_time * (n_timestep - processed_step) sys.stdout.write('\r' + "Reading timestep.. " + str(timestep) + " (Elapsed time for the previous step: " + "{0:4.1f}".format(elapsed_time) + " seconds, Remaining time: " + "{0:4.1f}".format(remaining_time) + " seconds = " + "{0:4.1f} minutes".format(remaining_time / 60) + ")") sys.stdout.flush() processed_step += 1 ### update myBGF with trajectory information ### natom_bgf = len(myBGF.a) # number of atoms in BGF file if not natom_bgf == natoms: nu.die( "Number of atoms in trajectory file does not match with BGF file." ) mode = "" if 'xs' in keywords or 'ys' in keywords or 'zs' in keywords: mode = 'scaled' elif 'x' in keywords or 'y' in keywords or 'z' in keywords: mode = 'normal' elif 'xu' in keywords or 'yu' in keywords or 'zu' in keywords: mode = 'unwrapped' # actual coordinate coordinfo = chunk[9:] # assume that coordinfo is similar to ['id', 'type', 'xs', 'ys', 'zs', 'ix', 'iy', 'iz'] for atomline in coordinfo: atomcoord = atomline.split(' ') atom = myBGF.getAtom(int(atomcoord[0])) if mode == 'scaled': atom.x = float(atomcoord[2]) * boxsize[0] atom.y = float(atomcoord[3]) * boxsize[1] atom.z = float(atomcoord[4]) * boxsize[2] elif mode == 'unwrapped': atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) elif mode == 'normal': try: ix_index = keywords.index('ix') iy_index = keywords.index('iy') iz_index = keywords.index('iz') except ValueError: nu.warn( "No image information no the trajectory file. Will be treated as unwrapped." ) atom.x = float(atomcoord[2]) atom.y = float(atomcoord[3]) atom.z = float(atomcoord[4]) else: atom.x = (int(atomcoord[ix_index]) * boxsize[0]) + float( atomcoord[2]) atom.y = (int(atomcoord[iy_index]) * boxsize[1]) + float( atomcoord[3]) atom.z = (int(atomcoord[iz_index]) * boxsize[2]) + float( atomcoord[4]) try: for i in range(0, 3): myBGF.CRYSTX[i] = boxsize[i] except: pass #nu.warn("Crystal information error: is this file not periodic?") # apply periodic condition myBGF = bgftools.periodicMoleculeSort(myBGF, 0) ### DONE for updating trj on BGF file ### ### Do whatever I want: density profile ### list up O in ACT ### list up H in WAT ### for every pair, get hbond dist ### if it's less than 2.4A, then count++ ### return print('') return 1