def update_mass(ff_file, silent=True): for i in ff_file: # no need to read the ff_file again. if i in loaded_ff: continue # read if not silent: print("Updating atom mass with %s" % i) FF = dreiding.loadFF(i) atominfo = dreiding.loadAtomTypes(FF) for key in atominfo.keys(): atom_mass[key] = atominfo[key]['MASS'] loaded_ff.append(i)
def countWater(bgf_file, trj_file, n_step, watercopy, ff_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) global out_file if out_file == "": out_file = "countWater5.profile" print("The result will be recorded to the file " + out_file + " ...") ftemp = open(out_file, 'w') ftemp.write(str(sys.argv) + "\n") ftemp.write("t" + '\t' + "n_O" + '\t' + "r_CNT" + '\t' + "std_r" + '\t' + "min_x" + '\t' + "max_x" + '\t' + "min_y" + '\t' + "max_y" + '\t' + "min_z" + '\t' + "max_z" + '\t' + "l_NT" + '\t' + "replNum" + '\t' + "copyNum" + '\t' + "n_WAT" + '\t' + "remark" + '\n') curr_dir = os.path.abspath(".") temp_dir = curr_dir + "/countWAT5/" print(temp_dir) 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 first " + str(n_step) + " timesteps.") ### read mass from ff_file atominfo = dict() 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) ### extract aNos of CNT in the BGF file aNo_CNT = [] aNo_WAT_O = [] aNo_WAT_all = [] mass_CNT = [] for atom in myBGF.a: # Carbons in CNT or atoms in BNNT if "NT" in atom.rName: aNo_CNT.append(atom.aNo) 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.") mass_CNT.append(aMass) # 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 myBGF = bgf.BgfFile(bgf_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(' ') 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:] # load atom coordinates from chunk 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]) ### convert atom coordinates to lists CNT = [] WATER = [] for atom in myBGF.a: if "NT" in atom.rName: CNT.append([atom.x, atom.y, atom.z]) if "WAT" in atom.rName and "O" in atom.ffType: WATER.append([atom.x, atom.y, atom.z]) CNT = np.array(CNT) n_CNT = len(CNT) # CNT coordinates WATER = np.array(WATER) # Water coordinates WATERONLY = np.copy(WATER) boxsize = np.array(boxsize) ### 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 "all atoms in BGF": move COM of CNT as origin Mx, My, Mz = np.average(CNT, axis=0, weights=mass_CNT) # CoM of CNT COM = np.array([[Mx, My, Mz]]) CNT = CNT - COM + boxsize / 2.0 # move WATER = WATER - COM + boxsize / 2.0 ### apply PBC WATER = np.mod(WATER, boxsize) ### save coordinates to BGF before rotation myBGF2 = bgf.BgfFile() for index, i in enumerate(CNT): newatom = bgf.BgfAtom() newatom.x, newatom.y, newatom.z = i newatom.aNo = index newatom.aName = 'C' + str(index) newatom.rName = 'CNT' newatom.ffType = 'C_' newatom.chain = 'A' newatom.rNo = 1 myBGF2.addAtom(newatom) for index, i in enumerate(WATER): newatom = bgf.BgfAtom() newatom.x, newatom.y, newatom.z = i newatom.aNo = index + n_CNT newatom.aName = 'O' newatom.rName = 'WAT' newatom.ffType = 'OW' newatom.chain = 'O' newatom.rNo = 100 myBGF2.addAtom(newatom) myBGF2.REMARK.append('TIMESTEP ' + str(timestep)) myBGF2.PERIOD = "111" myBGF2.AXES = "ZYX" myBGF2.SGNAME = "P 1 1 1" myBGF2.CELLS = [-1, 1, -1, 1, -1, 1] myBGF2.CRYSTX = [boxsize[0], boxsize[1], boxsize[2], 90.0, 90.0, 90.0] myBGF2.saveBGF(temp_dir + bgf_file.split(".bgf")[0] + "." + str(timestep) + ".bgf") ### move CM of CNT to origin CNT = CNT - boxsize / 2.0 WATER = WATER - boxsize / 2.0 ### how the CNT is lying across the periodic box? for atom in CNT: min_x_CNT, min_y_CNT, min_z_CNT = CNT.min(axis=0) max_x_CNT, max_y_CNT, max_z_CNT = CNT.max(axis=0) margin = 5.0 ### copy water molecules max_x_axis = int(round((max_x_CNT + margin) / boxsize[0])) min_x_axis = int(round((min_x_CNT - margin) / boxsize[0])) max_y_axis = int(round((max_y_CNT + margin) / boxsize[1])) min_y_axis = int(round((min_y_CNT - margin) / boxsize[1])) max_z_axis = int(round((max_z_CNT + margin) / boxsize[2])) min_z_axis = int(round((min_z_CNT - margin) / boxsize[2])) replNum = (min_x_axis, max_x_axis, min_y_axis, max_y_axis, min_z_axis, max_z_axis) copyNum = 0 remark = "" if watercopy: for x in range(min_x_axis, max_x_axis + 1): remark += "x: " if x != 0: WATER2 = np.copy(WATERONLY) dx = np.array([[boxsize[0] * x, 0, 0]]) WATER2 = WATER2 + dx WATER = np.concatenate((WATER, WATER2)) copyNum += 1 remark += str(x) + " " for y in range(min_y_axis, max_y_axis + 1): remark += "y: " if y != 0: WATER2 = np.copy(WATERONLY) dy = np.array([[0, boxsize[1] * y, 0]]) WATER2 = WATER2 + dy WATER = np.concatenate((WATER, WATER2)) copyNum += 1 remark += str(y) + " " for z in range(min_z_axis, max_z_axis + 1): remark += "z: " if z != 0: WATER2 = np.copy(WATERONLY) dz = np.array([[0, 0, boxsize[2] * z]]) WATER2 = WATER2 + dz WATER = np.concatenate((WATER, WATER2)) copyNum += 1 remark += str(z) + " " ''' ### WATER distribution check x_axis = np.linspace(WATER[:,0].min(), WATER[:,0].max(), 10) y_axis = np.linspace(WATER[:,1].min(), WATER[:,1].max(), 10) z_axis = np.linspace(WATER[:,2].min(), WATER[:,2].max(), 10) x_hist, _ = np.histogram(WATER[:,0], x_axis, normed=True) y_hist, _ = np.histogram(WATER[:,1], y_axis, normed=True) z_hist, _ = np.histogram(WATER[:,2], z_axis, normed=True) remark += " xdist: " for i in x_hist: remark += "{0:6.3f}".format(i) remark += " ydist: " for i in y_hist: remark += "{0:6.3f}".format(i) remark += " zdist: " for i in z_hist: remark += "{0:6.3f}".format(i) ''' ### MI of CNT calculation for atom in CNT: Ixx += (atom[1]**2 + atom[2]**2) / N_CNT Iyy += (atom[0]**2 + atom[2]**2) / N_CNT Izz += (atom[0]**2 + atom[1]**2) / N_CNT Ixy -= (atom[0] * atom[1]) / N_CNT Ixz -= (atom[0] * atom[2]) / N_CNT Iyz -= (atom[1] * atom[2]) / N_CNT I = np.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]]) # the moment of inertia tensor eigval, eigvec = np.linalg.eig( I) # eigval[0] is the minimum among the values. U = np.matrix(eigvec) Ut = U.T ### box rotation for atom in CNT: v = np.matrix([atom[0], atom[1], atom[2]]).T Uv = Ut * v atom[0] = float(Uv[2]) atom[1] = float(Uv[1]) atom[2] = float(Uv[0]) # CNT rotation for atom in WATER: v = np.matrix([atom[0], atom[1], atom[2]]).T Uv = Ut * v atom[0] = float(Uv[2]) atom[1] = float(Uv[1]) atom[2] = float(Uv[0]) # water rotation ### save coordinates to BGF after rotation myBGF2 = bgf.BgfFile() for index, i in enumerate(CNT): newatom = bgf.BgfAtom() newatom.x, newatom.y, newatom.z = i newatom.aNo = index newatom.aName = 'C' + str(index) newatom.rName = 'CNT' newatom.ffType = 'C_' newatom.chain = 'A' newatom.rNo = 1 myBGF2.addAtom(newatom) for index, i in enumerate(WATER): newatom = bgf.BgfAtom() newatom.x, newatom.y, newatom.z = i newatom.aNo = index + n_CNT newatom.aName = 'O' newatom.rName = 'WAT' newatom.ffType = 'OW' newatom.chain = 'O' newatom.rNo = 100 myBGF2.addAtom(newatom) myBGF2.REMARK.append('TIMESTEP ' + str(timestep)) myBGF2.PERIOD = "111" myBGF2.AXES = "ZYX" myBGF2.SGNAME = "P 1 1 1" myBGF2.CELLS = [-1, 1, -1, 1, -1, 1] myBGF2.CRYSTX = [boxsize[0], boxsize[1], boxsize[2], 90.0, 90.0, 90.0] myBGF2.saveBGF(temp_dir + bgf_file.split(".bgf")[0] + "." + str(timestep) + ".rot.bgf") ### CNT height _, _, min_z_CNT = CNT.min(axis=0) _, _, max_z_CNT = CNT.max(axis=0) height_CNT = max_z_CNT - min_z_CNT ### CNT radius x_CNT, y_CNT, z_CNT = np.mean(CNT, axis=0) x_std_CNT, y_std_CNT, z_std_CNT = np.std(CNT, axis=0) if x_std_CNT > 1.0 or y_std_CNT > 1.0: remark += "" ### radius of CNT l_r_CNT = [] for atom in CNT: l_r_CNT.append( math.sqrt((atom[0] - x_CNT)**2 + (atom[1] - y_CNT)**2)) r_CNT = np.mean(l_r_CNT) std_r_CNT = np.std(l_r_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 < r_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 WAT_in_CNT = [] for atom in WATER: dist_sq = (atom[0] - x_CNT)**2 + (atom[1] - y_CNT)**2 if min_z_CNT + margin <= atom[2] and atom[ 2] <= max_z_CNT - margin and dist_sq < r_CNT**2: WAT_in_CNT.append(atom) n_WAT_in_CNT = len(WAT_in_CNT) ''' ### WATER bad contact check: copy-failure-proof: NEED CORRECTION WAT1 = []; WAT2 = []; for index1, i in enumerate(WAT_in_CNT): for j in WATER[index1:]: WAT1.append(i); WAT2.append(j); WAT1 = np.array(WAT1); WAT2 = np.array(WAT2) min_dists = np.min(np.dstack(((WAT1 - WAT2) % boxsize, (WAT2 - WAT1) % boxsize)), axis = 2) dists = np.sqrt(np.sum(min_dists ** 2, axis = 1)) for d in dists: if d > 0 and d < 1.0: remark += "Bad contacts" + str(d) continue; ''' d = "{0:8.3f}" e = "{0:6.1f}" output = "{0:<10}".format(timestep) + str( n_WAT_in_CNT ) + ' | ' + d.format(r_CNT) + d.format(std_r_CNT) + ' | ' + e.format( boxsize[0] ) + e.format(boxsize[1]) + e.format(boxsize[2]) + ' | ' + e.format( min_x_CNT) + e.format(max_x_CNT) + e.format(min_y_CNT) + e.format( max_y_CNT) + e.format(min_z_CNT) + e.format( max_z_CNT) + ' | ' + e.format(height_CNT) + ' | ' + str( replNum) + '\t' + str(copyNum) + '\t' + str( len(WATER)) + '\t' + str(remark) + '\n' ftemp.write(output) 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 " + out_file + " ..Done.") return 1
bgfFile = value elif option in ('-f', '--forcefield'): ffFile = value elif option in ('-s', '--suffix'): suffix = value elif option in (''): print usage sys.exit(0) ##### Initialize output = "" if suffix == "": suffix = "lammps" ##### Open a new data file myBGF = BgfFile(bgfFile) forcefield = dreiding.loadFF(ffFile) ##### Description of the file output += "Created by lammps.py\n" output += "\n" ##### the number of atoms output += "{0:8d}".format(len(myBGF.a)) + " atoms" + "\n" ##### the number of bonds output += "{0:8d}".format(len(getAtomBondsID(myBGF))) + " bonds" + "\n" ##### the number of angles output += "{0:8d}".format(len( getAtomAnglePairsID(myBGF))) + " angles" + "\n"
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 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 densityProfile(bgf_file, trj_file, ff_file, pickle_file, out_file, 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 atominfo = dict() # atom data extracted from ff_file result = dict() axis = 2 # 1: x-axis, 2: y-axis, 3: z-axis ### open files myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myTRJ.seek(0) myPickle = open(pickle_file) f_debug = open("debug.dat", 'w') if not silent: print("Pickling..") Dipole = pickle.load(myPickle) # dipole data ### 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 + " " dict_residue[i] = [] if not silent: print("Found " + str(len(residue)) + " residues in BGF file: " + str(output)) residue = list(residue) #residue.append('TOTAL') n_residue = len(residue) # number of residues (including total) ### bookkeep residue numbers for each residue molecules = bgftools.getMoleculeList(myBGF) dict_rNo2rName = dict() 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) dict_rNo2rName[atom.rNo] = atomresname #print(dict_residue) #print(dict_rNo2rName) ### 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 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(' ') ######## if timestep < avg_timestep: continue if timestep % 10000 != 0: 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 ### ### find bin ## CAUTION: only for NVT 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), interval) #print("Bins....:") #print(bins) ### find CM of every molecule res_z = [] residues = [] 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 m = bgftools.getMass(myBGF, molecule, ff_file) # molecule mass cm = [0, 0, 0] # center of mass coord = [0, 0, 0] # atom x, y, z residues.append(residue_no) # store residue numbers of molecules 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 res_z.append([residue_no, cm[2]]) ### binning according to z-axis bin_resno = [] for index, bin in enumerate(bins): temp_resno = [] for i in res_z: try: if bin < i[1] and bins[index + 1] > i[1]: temp_resno.append(i[0]) except: continue bin_resno.append([bin, temp_resno]) ### refinement for residues bin_avg = [] for r in residue: temp_per_r = [] for b in bin_resno: temp_bin_res = [] for i in b[1]: if dict_rNo2rName[i] == r: temp_bin_res.append(i) temp_per_r.append([b[0], temp_bin_res]) bin_avg.append([r, temp_per_r]) ### average #result = []; result_t = dict() for rdata in bin_avg: temp_per_r = [] for b in rdata[1]: temp_bin_res = [] avg_mag = 0 avg_angle_cos = 0 for i in b[1]: avg_mag += Dipole[timestep][rdata[0]]['ABSMU'][i] mu = Dipole[timestep][rdata[0]]['MU'][i] # angle btwn z-axis and mu angle_cos = mu[2] / math.sqrt(mu[0]**2 + mu[1]**2 + mu[2]**2) f_debug.write( str(timestep) + '\t' + str(mu) + '\t' + str(Dipole[timestep][rdata[0]]['ABSMU'][i]) + '\t' + str(angle_cos) + '\n') avg_angle_cos += angle_cos if not len(b[1]) == 0: avg_mag /= len(b[1]) if not len(b[1]) == 0: avg_angle_cos /= len(b[1]) temp_per_r.append([b[0], avg_angle_cos, avg_mag]) #result.append(temp_per_r) result_t[rdata[0]] = temp_per_r result[timestep] = result_t ### end of loop: check elapsed time t2 = time.time() # time mark elapsed_time = t2 - t1 ### write pickle o = open(out_file + ".pickle", 'w') pickle.dump(result, o) ### return print('') return 1