def rdf(u, thresholds, n_bins, pair, block): '''Computes water radial distribution functions (RDF). Args: u: MDAnalysis Universe object containing trajectory. t: Thresholds specifying layer boundaries. n_bins: Number of bins for RDF. pair: Pair of elements to consider. block: Range of frames composing block. Returns: Radial distribution function. ''' atoms = list(pair) # Select appropriate atom groups within specified layers down = 'prop z > %s and prop z < %s' % (*thresholds[:2], ) up = 'prop z > %s and prop z < %s' % (*thresholds[2:], ) ag1 = u.select_atoms('name %s and ((%s) or (%s))' % (atoms[0], down, up), updating=True) ag2 = u.select_atoms('name %s' % atoms[1]) # Compute the RDF between ag1 and ag2 rdf = InterRDF(ag1, ag2, nbins=n_bins, range=(0, 6), verbose=True) rdf.run(start=block.start, stop=block.stop) return (rdf.results.bins, rdf.results.rdf)
def test_double_run(self): # running rdf twice should give the same result self._linear_water() s1, s2 = self._get_sels() rdf = InterRDF(s1, s2).run() rdf.run() assert_(len(rdf.count[rdf.count == 4]) == 2)
class SimpleRdfBench(object): """Benchmarks for MDAnalysis.analysis.rdf """ params = ([20, 75, 200], [[0, 5], [0, 15], [0, 20]]) param_names = ['nbins', 'range_val'] def setup(self, nbins, range_val): self.sel_str = 'name OW' self.u = MDAnalysis.Universe(TPR, XTC) try: self.sel = self.u.select_atoms(self.sel_str)[:200] except AttributeError: self.sel = self.u.selectAtoms(self.sel_str)[:200] # do not include initialization of the # InterRDF object in the benchmark itself self.rdf = InterRDF(g1=self.sel, g2=self.sel, nbins=nbins, range=range_val) def time_interrdf(self, nbins, range_val): """Benchmark a full trajectory parse by MDAnalysis.analysis.rdf.InterRDF """ self.rdf.run()
def test_exclusion(self): # should see two distances with 4 counts each self._linear_water() s1, s2 = self._get_sels() rdf = InterRDF(s1, s2, exclusion_block=(1, 2)) rdf.run() assert_(rdf.count.sum() == 4)
def test_count(self): # should see two distances with 4 counts each self._linear_water() s1, s2 = self._get_sels() rdf = InterRDF(s1, s2) rdf.run() assert_(len(rdf.count[rdf.count == 4]) == 2)
def test_count_sum(self): # OW vs HW # should see 8 comparisons in count self._linear_water() s1, s2 = self._get_sels() rdf = InterRDF(s1, s2) rdf.run() assert_(rdf.count.sum() == 8)
class SimpleRdfBench(object): """Benchmarks for MDAnalysis.analysis.rdf """ params = ([20,75,200], [[0,5], [0,15], [0,20]], [1, 100, 1000, 10000]) param_names = ['nbins', 'range_val', 'natoms'] def setup(self, nbins, range_val, natoms): self.sel_str = 'name OW' self.u = MDAnalysis.Universe(TPR, XTC) try: self.sel = self.u.select_atoms(self.sel_str)[:natoms] except AttributeError: self.sel = self.u.selectAtoms(self.sel_str)[:natoms] # do not include initialization of the # InterRDF object in the benchmark itself self.rdf = InterRDF(g1=self.sel, g2=self.sel, nbins=nbins, range=range_val) def time_interrdf(self, nbins, range_val): """Benchmark a full trajectory parse by MDAnalysis.analysis.rdf.InterRDF """ self.rdf.run()
u.atoms.write("system.pdb") print("===> The initial configuration has been written to system.pdb ") # # =========================================================" # Example #3: Calculate a radial distribution function " # =========================================================" # from MDAnalysis.analysis.rdf import InterRDF charged = u.select_atoms("prop charge > 0") rdf = InterRDF(charged, charged, nbins=7, range=(0, 10)) # This runs so far only over the single frame we have loaded. # Multiframe averaging must be done by hand rdf.run() # # =========================================================" # Example #4: Saving frames to a GROMACS's TRR trajectory # =========================================================" # from MDAnalysis.coordinates.TRR import TRRWriter W = TRRWriter("traj.trr", n_atoms=len(system.part)) for i in range(100): # integrate system.integrator.run(1) # replace last frame
def test_double_run(sels): # running rdf twice should give the same result s1, s2 = sels rdf = InterRDF(s1, s2).run() rdf.run() assert len(rdf.count[rdf.count == 4]) == 2
def compute_microstructure(molten_salt_system, ensemble, start, stop, step, nbins=500, rdf_flag=True, cn_flag=True, adf_flag=True): """ Description: compute microstructure info including radial distribution fuction(rdf), coordination number(cn) and angle distribution function(adf) using MDAnalysis module. adf is not completed Args: molten_salt_system: ensemble: start: stop: step: rdf_flag: cn_flag: adf_flag: Returns: return dicts according to setting """ global dir_molten_salt_system global dir_list # analysis elements and get cations and inions according cif file os.chdir(dir_molten_salt_system) cations_list, anions_list = [], [] with open(molten_salt_system+'.cif', 'r') as f_cif: flag = False atoms_list = [] for line in f_cif: if line.startswith(' _atom_type_oxidation_number'): flag = True continue if line.startswith('loop_'): flag = False continue if flag: tmp_tuple = tuple(list(filter(None, line.strip().split(' ')))) atoms_list.append(tmp_tuple) for i in range(len(atoms_list)): if float(atoms_list[i][1]) > 0: cations_list.append((re.findall(r"[A-Za-z]+", atoms_list[i][0])[0]).upper()) # transfered to uppercase because MDAnalysis can just identify capitalization elif float(atoms_list[i][1]) < 0: anions_list.append((re.findall(r"[A-Za-z]+", atoms_list[i][0])[0]).upper()) elements_list = cations_list+anions_list elements_count = len(elements_list) # determine # of pairs(used in rdf and cn) pairs_count = 0 for i in range(elements_count): for j in range(i, elements_count): pairs_count += 1 # radial_distribution_function_dense_dict, coordination_number_dense_dict= [{} for i in range(pairs_count)], [{} for i in range(pairs_count)] # 加密的 radial_distribution_function_dict, coordination_number_dict= [{} for i in range(pairs_count)], [{} for i in range(pairs_count)] # 原始的 for dirname in dir_list: os.chdir(os.path.join(dir_molten_salt_system, dirname)) deal_with_PDB(dirname, ensemble) # write MODEL and ENDMDL into xxx.pdb file and stored as traj.pdb universe = MDA.Universe('traj.pdb') # determine cutoff of rdf tmp_list = list(filter(None, os.popen('grep CRY '+dirname+'-'+ensemble+'.pdb').readlines()[-1].strip().split(' '))) equilibrium_lattice_constant_a = float(tmp_list[1]) equilibrium_lattice_constant_b = float(tmp_list[2]) equilibrium_lattice_constant_c = float(tmp_list[3]) equilibrium_lattice_constant_min = min(equilibrium_lattice_constant_a, equilibrium_lattice_constant_b, equilibrium_lattice_constant_c) cutoff = equilibrium_lattice_constant_min//2 # begin compute rdf and cn columns_count = -1 for i in range(elements_count): for j in range(i, elements_count): columns_count += 1 atomgroup1 = universe.select_atoms('name '+elements_list[i]) atomgroup2 = universe.select_atoms('name '+elements_list[j]) rdf = InterRDF(atomgroup1, atomgroup2, nbins=nbins, range=(0.0, cutoff)) rdf.run(start=start, stop=stop, step=step) # after run, rdf and count have been generated rdf.rdf[0] = 0 # 第一个数莫名奇妙的超级大,本该为0 # This part is discarded because of the limitation of 16MB for single file in mongodb ''' # 加密10倍的 # store rdf results into a dict # make curve smoother rdf_new = np.linspace(rdf.bins.min(), rdf.bins.max(), nbins*10) # 加密十倍, 画出来的图更光滑 rdf_smooth = spline(rdf.bins, rdf.rdf, rdf_new) # get rdf_rmax(first peak) and rdf_rmin(first peak valley) of rdf rdf_rmax_index = np.argmax(rdf_smooth) rdf_rmax = rdf_new[rdf_rmax_index] rdf_rmin_index = np.argmin(rdf_smooth[rdf_rmax_index:]) rdf_rmin = rdf_new[rdf_rmax_index:][rdf_rmin_index] radial_distribution_function_dense_dict[columns_count]['pair'] = elements_list[i]+'-'+elements_list[j] radial_distribution_function_dense_dict[columns_count][dirname] = {'rdf_rmax': rdf_rmax, 'rdf_rmin': rdf_rmin, 'rdf_value': Binary(pickle.dumps(np.vstack((rdf_new, rdf_smooth)), protocol=2))} # numpy必须转换成二进制才能存进pymongo # store cn results into a dict rdf_count = rdf.count.copy() rdf_count = rdf_count/(len(atomgroup1)*rdf.__dict__['n_frames']) # average cn = rdf_count.cumsum() # integrate # make curve smoother cn_smooth = spline(rdf.bins, cn, rdf_new) # get cn_rmin according to first peak valley in rdf cn_rmin = cn_smooth[rdf_rmax_index:][rdf_rmin_index] coordination_number_dense_dict[columns_count]['pair'] = elements_list[i]+'-'+elements_list[j] coordination_number_dense_dict[columns_count][dirname] = {'cn_rmin': cn_rmin, 'cn_value': Binary(pickle.dumps(np.vstack((rdf_new, cn_smooth)), protocol=2))} ''' # 原始的 # rdf radial_distribution_function_dict[columns_count]['pair'] = elements_list[i]+'-'+elements_list[j] radial_distribution_function_dict[columns_count][dirname] = Binary(pickle.dumps(np.vstack((rdf.bins, rdf.rdf)), protocol=2)) # cn rdf_count = rdf.count.copy() rdf_count = rdf_count/(len(atomgroup1)*rdf.__dict__['n_frames']) # average cn = rdf_count.cumsum() # integrate coordination_number_dict[columns_count]['pair'] = elements_list[i]+'-'+elements_list[j] coordination_number_dict[columns_count][dirname] = Binary(pickle.dumps(np.vstack((rdf.bins, cn)), protocol=2)) os.system('rm traj.pdb') os.chdir(dir_molten_salt_system) return radial_distribution_function_dict, coordination_number_dict
end = u.trajectory.n_frames # RDF analysis print("#------------------------------------------------------#") print("Start RDF analysis") os.system("mkdir RDF") os.system("cd RDF") ow = u.select_atoms("name OW") hw = u.select_atoms("name HW1 or name HW2") selcation = u.select_atoms("name %s" % (cation[0])) selanion = u.select_atoms("name %s" % (anion[0])) ow_ow = IRDF(ow, ow, nbins=100, exclusion_block=(1, 1)) rdf_ow_ow = ow_ow.run() print("ow ow rdf analysis done") ow_hw = IRDF(ow, hw, nbins=100) rdf_ow_hw = ow_hw.run() print("ow hw rdf analysis done") cation_ow = IRDF(selcation, ow, nbins=100) rdf_cation_ow = cation_ow.run() print("cation ow rdf analysis done") anion_ow = IRDF(selanion, ow, nbins=100) rdf_anion_ow = anion_ow.run() print("anion ow rdf analysis done") with open("rdf.txt", "w") as f: f.write("# RDF result for ow-ow,ow-hw,cation-ow,anion-ow\n") for i in range(len(ow_ow.bins)): f.write("%.3f %.3f %.3f %.3f %.3f \n"%(rdf_ow_ow.bins[i],\