def check_monomer(monomer, ff_file): """ Check whether monomer has proper number of branching points :str monomer: :str ff_file: :bool : object """ try: f = bgf.BgfFile(monomer) except IOError: return False branch = 0 head = 0 for atom in f.a: atom.rNo = 0 # this residue number will be the key to distinguish body and the new block if atom.chain == "B": branch += 1 if atom.chain == "H": head += 1 if branch != 1: raise ValueError('More than two branch atoms inside ' + str(monomer)) return False if head != 1: raise ValueError('More than two head atoms inside ' + str(monomer)) return False mass = bgftools.getMass(f, ff_file) f.saveBGF(monomer) return mass
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 main(primary, secondary, tertiary, ratio, mw, suffix, ff, n_requested_gen, isForce, silent, isPreserveCharge=False): """ generate polymer by slow addition method :str primary: primary monomer BGF location :str secondary: secondary monomer BGF location :str tertiary: tertiary monomer BGF location :list ratio: primary, secondary, tertiary amines ratio :float mw: desired molecular weight :str suffix: used to make a log filename and generated structure filename :str ff: force field file :n_requested_gen: requested number of polymer generation :bool silent: :bool isPreserveCharge: input: - primary, secondary, tertiary BGF file marked with branching point B and head H - the amine ratio - the target molecular weight remarks: - connect B and H - hydrogens attached on H or B will be automatically removed with respect to their role. - iteration will go on until we spend all designated monomers. writes an output: an n-oligomer BGF file """ ### 0. initialize # log: for different format for levels, see this: http://stackoverflow.com/questions/28635679/python-logging-different-formatters-for-the-same-log-file log = logging.getLogger(__name__) log.propagate = 0 logging.basicConfig(level=logging.DEBUG) formatter_file = logging.Formatter( "[%(asctime)s] [%(levelname)s] %(message)s", "%Y-%m-%d %H:%M:%S") formatter_debug = logging.Formatter("[%(levelname)s] %(message)s", "%Y-%m-%d %H:%M:%S") if not silent: streamhandler = logging.StreamHandler(sys.stdout) streamhandler.setFormatter(formatter_debug) streamhandler.setLevel(logging.INFO) log.addHandler(streamhandler) filehandler = logging.FileHandler(suffix + ".log") filehandler.setFormatter(formatter_file) filehandler.setLevel(logging.DEBUG) log.addHandler(filehandler) log.info( "***** Welcome to Hyperbranched Polymer Generator by Slow Addition Method *****" ) log.info(str(sys.argv)) # load primary, secondary, tertiary amines primary_mass = check_monomer(primary, ff) secondary_mass = check_monomer(secondary, ff) tertiary_mass = check_monomer(tertiary, ff) if not primary_mass or not secondary_mass or not tertiary_mass: log.error("Error found on reading monomers: Exiting.") sys.exit(0) # parameters for LAMMPS #mpi_command = os.environ["MPI"] #lammps_parallel_command = mpi_command + " " + lammps_command # parallel not supported yet lammps_command = os.environ["EXEC"] curr_dir = os.path.abspath(".") temp_dir = curr_dir + ("/scratch/") if not os.path.isdir(temp_dir): os.makedirs(temp_dir) shutil.copy(primary, temp_dir) shutil.copy(secondary, temp_dir) shutil.copy(tertiary, temp_dir) os.chdir(temp_dir) # determine numbers of required amine blocks from requested Mw ratio = np.array(ratio) log.info("Requested ratio: " + str(ratio)) masses = np.array([primary_mass, secondary_mass, tertiary_mass]) log.info("Calculated monomer mass (T/L/D): " + str(masses)) blocks = np.ceil(mw * ratio / masses) log.info("Calculated required monomer blocks (T/L/D): " + str(blocks)) estimated_mw = np.sum(masses * blocks) log.info("Estimated hyperbranched polymer molecular weight: " + str(estimated_mw)) monomers = [primary, secondary, tertiary] blocks = list(blocks) blocks = [int(i) for i in blocks] log.debug(str(blocks)) log.info("The script will generate " + str(n_requested_gen) + " polymers.") n_generation = 0 n_trial = 0 branch_pt_profile = [] while n_generation < n_requested_gen: n_trial += 1 # make a pool # 0 = primary, 1 = secondary, 2 = tertiary pool = [] for index, i in enumerate(blocks): log.debug("index, i: " + str(index) + " " + str(i)) for j in range(i): pool.append(index) # the first block should not be primary(terminal) log.info("<<< Trial " + str(n_trial) + " >>>") log.info("Shuffling monomer blocks..") random.shuffle(pool) while pool[-1] == 0: log.debug("pool: " + str(pool)) log.info("\tResuffle..") random.shuffle(pool) log.debug("pool: " + str(pool)) # pick the initial block n_addition = 1 init_block = pool.pop( ) # random pick: the last item of the shuffled list will be chosen for the first pick. body = bgf.BgfFile(monomers[init_block]) # the first monomer for atom in body.a: atom.rNo = n_addition # mark branches = refresh_branch(body) branch_pt_profile.append([n_addition, len(branches)]) log.info("*** iteration " + str(n_addition) + " ***") log.debug("init block: " + str(monomers[init_block])) is_generation_success = False tester = 0 # addition iteration #while tester == 0: while len(pool) > 0: # tester ###### tester = 1 # counter n_addition += 1 log.info("*** iteration " + str(n_addition) + " ***") ### find(update) branching points of the body branches = refresh_branch(body) branch_pt_profile.append([n_addition, len(branches)]) log.debug("aNo for Possible branches: " + str(branches)) if len(branches) == 0: log.warn( "No possible branching points. Failed to generate a polymer. Retrying.." ) os.system("rm in* dat* *trj *pbs *log") is_generation_success = False break ### if trials too many then quit the script. if not isForce and n_trial >= 3 * n_requested_gen: log.error( "The generator does not seem to generate proper structures. Quit." ) # branch point print output = "*** number of branching points ***" for i in branch_pt_profile: output += i[0] + '\t' + i[1] + '\n' log.debug(output) sys.exit(0) if n_trial > 1000 and n_generation == 0: log.error( "No single proper structure though many attemption. Quit.") # branch point print output = "*** number of branching points ***" for i in branch_pt_profile: output += str(i[0]) + '\t' + str(i[1]) + '\n' log.debug(output) sys.exit(0) ### randomly pick a branch point random.shuffle(branches) branch_pt_body = branches.pop() log.debug("Selected branch point aNo: " + str(branch_pt_body)) ### randomly pick a block (pop) random.shuffle(pool) monomer_type = pool.pop() monomer = bgf.BgfFile(monomers[monomer_type]) for atom in monomer.a: atom.rNo = n_addition # mark log.debug("Selected block: " + str(monomer_type)) ### pick an atom from the branch atom of the body to make a bond branch_atom = body.getAtom(branch_pt_body) log.debug(str(branch_atom)) bonding_candidate_body = [] for ano in branch_atom.CONECT: atom = body.getAtom(ano) if "H_" in atom.ffType or "H" in atom.aName: bonding_candidate_body.append(ano) #log.debug(str(bonding_candidate_body)) bonding_candidate_body = random.choice(bonding_candidate_body) bonding_candidate_body_atom = body.getAtom(bonding_candidate_body) log.debug(str(bonding_candidate_body)) log.debug(str(bonding_candidate_body_atom)) ### translate a block (x, y, z) = (bonding_candidate_body_atom.x, bonding_candidate_body_atom.y, bonding_candidate_body_atom.z) log.debug("script will translate the block by -" + str((x, y, z))) for atom in monomer.a: atom.x += x atom.y += y atom.z += z ### merge body = body.merge(monomer) body.renumber() #log.debug(str(body)) ### pick an atom from the head atom of a monomer head_atom_ano = 0 for atom in body.a: if "H" in atom.chain and atom.rNo == n_addition: head_atom_ano = atom.aNo head_atom = body.getAtom(head_atom_ano) #log.debug(str(head_atom)) bonding_candidate_monomer = [] for ano in head_atom.CONECT: atom = body.getAtom(ano) if "H" in atom.ffType and "H" in atom.aName: bonding_candidate_monomer.append(ano) #log.debug(str(bonding_candidate_monomer)) bonding_candidate_monomer = random.choice( bonding_candidate_monomer) bonding_candidate_monomer_atom = body.getAtom( bonding_candidate_monomer) #log.debug(str(bonding_candidate_monomer)) #log.debug(str(bonding_candidate_monomer_atom)) ### connect head(C) to tail(N) # branch_atom -- bonding_candidate_body ---- bonding_candidate_monomer -- head_atom # connect #log.debug("Connecting " + str(branch_atom.aNo) + " and " + str(head_atom.aNo)) branch_atom.connect(head_atom) head_atom.connect(branch_atom) #log.debug(str(body)) # charge branch_atom.charge += bonding_candidate_body_atom.charge head_atom.charge += bonding_candidate_monomer_atom.charge # remove delatoms = [ body.a2i[bonding_candidate_body], body.a2i[bonding_candidate_monomer] ] body.delAtoms(delatoms) body.renumber() #log.debug(str(body)) # translate _ = bgftools.getCom(body, ff) for atom in body.a: atom.x -= _[0] atom.y -= _[1] atom.z -= _[2] # refresh branches = refresh_branch(body) branch_pt_profile.append([n_addition, len(branches)]) #log.debug(str(branches)) # save temp_suffix = "_polymer_" + str(n_addition) temp_file = temp_suffix + ".bgf" # ex) _polymer_1.bgf body.CRYSTX = [50.0, 50.0, 50.0, 90.0, 90.0, 90.0] body.PERIOD = "111" body.AXES = "ZYX" body.SGNAME = "P 1 1 1" body.CELLS = [-1, 1, -1, 1, -1, 1] body.saveBGF(temp_file) # Minimization on LAMMPS createLammpsInput = "~tpascal/scripts/createLammpsInput.pl" + " -b " + temp_file + " -f " + ff + " -s " + temp_suffix + " -o 'no shake' -t min " + " > /dev/null" os.system(createLammpsInput) in_file = "in." + temp_suffix data_file = "data." + temp_suffix # LAMMPS input patch #os.system("sed -i 's/' " + in_file) os.system("sed -i 's/dielectric 1/dielectric 72/' " + in_file) os.system( "sed -i 's/kspace_style pppm 0.0001/kspace_style none/' " + in_file) os.system( "sed -i 's/boundary p p p/boundary s s s/' " + in_file) os.system( "sed -i 's/lj\/charmm\/coul\/long\/opt 7.5 8.50000/lj\/cut\/coul\/debye 0.142 10/' " + in_file) # LAMMPS data patch os.system( "sed -i 's/0.000000 50.000000/-50.000000 50.000000/' " + data_file) os.system("sed -i 's/0 # X/0 0 # X/' " + data_file) os.system("sed -i 's/Impropers//' " + data_file) t1 = time.time() runLammps = lammps_command + " -in in." + temp_suffix + " -log " + temp_suffix + ".log " + "-screen none" log.debug("Running " + runLammps) os.system(runLammps) t2 = time.time() log.debug("Elapsed time for minimization: " + str(t2 - t1) + " sec") # update coordinates trj_file = temp_suffix + ".min.lammpstrj" LAMMPS_trj2bgf.getLAMMPSTrajectory(temp_file, trj_file, temp_file, -1, False, True) body = bgf.BgfFile(temp_file) # end of a block addition is_generation_success = True # generation success if is_generation_success: n_generation += 1 # amine group check _ = bgftools.getAmineGroupInfo(body) if _ == blocks: body.REMARK.append( "Polymer generated with number of requested blocks.") else: log.warn( "Requested monomer block does not match with the generated polymer." ) break # charge check charge = 0.0 for atom in body.a: charge += atom.charge if abs(charge) >= 0.00001: log.warn("Charge is not neutral: " + str(charge)) # save the structure filename = suffix + "_" + str(n_generation) + ".bgf" body.DESCRP = "Polymer generated using " + os.path.basename( sys.argv[0] ) + " by " + os.environ["USER"] + " on " + time.asctime( time.gmtime()) body.REMARK.insert( 0, "Dendritic(tertiary) monomer with " + os.path.abspath(tertiary)) body.REMARK.insert( 0, "Linear(secondary) monomer with " + os.path.abspath(secondary)) body.REMARK.insert( 0, "Terminal(primary) monomer with " + os.path.abspath(primary)) body.saveBGF(filename) shutil.copy(filename, curr_dir) log.info("\tSaving the structure to the filename " + filename) # wiener index idx = calculate_wiener_index(body) log.info("Wiener index: " + str(idx)) body.REMARK.append("Requested Mw: " + str(mw)) body.REMARK.append("Actual mass:" + str(bgftools.getMass(body, ff))) body.REMARK.append("Wiener index: " + str(idx)) log.info(str(n_generation) + " structure generated.") log.info("Number of trials: " + str(n_trial)) # branch point print output = "*** number of branching points ***" for i in branch_pt_profile: output += i[0] + '\t' + i[1] + '\n' output += '\n' log.debug(output)
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 get_mass(bgf_file, ff_file=''): mybgf = bgf.BgfFile(bgf_file) return bt.getMass(mybgf, ff_file=ff_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 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
#!/home/noische/python import sys import os import bgf import bgftools import dreiding usage = "getMass.py bgffile fffile" if len(sys.argv) < 2: print(usage) sys.exit(0) bgf_file = sys.argv[1] ff_file = sys.argv[2] myBGF = bgf.BgfFile(bgf_file) Mw = bgftools.getMass(myBGF, ff_file) print(bgf_file + " mass: " + str(Mw))
Info) Residues: 1630 Info) Waters: 1629 Info) Segments: 1 Info) Fragments: 1630 Protein: 0 Nucleic: 0 """ usage = """ BGF_info.py bgf_file ff_file Prints information on BGF file. (mass, n_atoms, ff_types, ...) """ if len(sys.argv) < 3: print(usage) sys.exit(0) bgf_file = sys.argv[1] ff_file = sys.argv[2] mybgf = bgf.BgfFile(bgf_file) mw = bgftools.getMass(mybgf, ff_file) # molecular weight n_atoms = len(mybgf.a) # n_atoms d_fftypes = set() for atom in mybgf.a: d_fftypes.add(atom.ffType) print("Molecule mass: %f" % mw) print("Number of molecules: %f" % n_atoms) print("FF types in the molecule: %s" % str(list(d_fftypes)))
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 main(bgf_file, out_file, ff_file="", n=0, density=0.9, r=1.0): n_total_trial = 0 # if molecule numbers are not specified, create the box with the existing molecules in the BGF file. # if molecule numbers specified, copy the molecules in the box as many as the number specified. if n: import copy mybgf = bgf.BgfFile() id = 0 for i in tqdm.tqdm(range(int(n)), desc="Cloaning molecules", ncols=120): id += 1 mybgf2 = bgf.BgfFile(bgf_file) for i in mybgf2.a: i.rNo = id mybgf = mybgf.merge(mybgf2) else: mybgf = bgf.BgfFile(bgf_file) # calculate cubic size mass = bt.getMass(mybgf, ff_file=ff_file) target_density = density volume = mass / target_density / 6.022 * 10 cell_x = math.pow(volume, 1.0 / 3) print("The script will generate a cubic with dimensions %f^3" % cell_x) mybgf.CRYSTX = [cell_x, cell_x, cell_x, 90.0, 90.0, 90.0] # get com redefined_coords = [] molecules = bt.getMoleculeList(mybgf) for mol in tqdm.tqdm(molecules, ncols=120): #for index, mol in enumerate(molecules): n_trial = 0 while True: n_trial += 1 n_total_trial += 1 cx, cy, cz = bt.getCom(mybgf, ff_file=ff_file, aNo_list=mol) new_pos = [random.uniform(0, cell_x) for i in range(3)] new_rot = [random.uniform(0, 2 * math.pi) for i in range(3)] U = mathtools.rotate_matrix(new_rot[0], new_rot[1], new_rot[2]) # check the room before lying mol_coords = [] for ano in sorted(mol): atom = mybgf.getAtom(ano) x = atom.x y = atom.y z = atom.z x -= cx y -= cy z -= cz # rotate v = np.matrix([x, y, z]).T Uv = U * v x = float(Uv[0]) y = float(Uv[1]) z = float(Uv[2]) # move CM to new position x += new_pos[0] y += new_pos[1] z += new_pos[2] mol_coords.append([x, y, z]) # only successful trials can quit the while loop if query_safe_coords(redefined_coords, mol_coords, r=r): for index, ano in enumerate(sorted(mol)): atom = mybgf.getAtom(ano) atom.x = mol_coords[index][0] atom.y = mol_coords[index][1] atom.z = mol_coords[index][2] redefined_coords += mol_coords break else: # fail if too many trials performed if n_trial > 1000: print( "Failed to find a suitable coordinates to insert a molecule %s" % mol) sys.exit(0) # check print("Checking bad contacts..") t = scipy.spatial.KDTree(redefined_coords) d = t.query_pairs(r) if not d: print("There are no bad contacts with distance < %.2f" % r) else: print("Looks there're %d bad contacts" % len(d)) # save mybgf.saveBGF(out_file) print("File saved to %s" % out_file) print("\n** Stats **") print("Total generated coordinates: %d" % n_total_trial) print("Number of last trials: %d" % n_trial) print("Done.")
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