"""helper function to strip extention of filename""" base = os.path.basename(fp) fn, ext = os.path.splitext(base) return fn ####### configure pymatgen XRD calculator ##### calculate_params = {} wavelength = 0.5 tth_range = np.arange(0, 90, 0.1) std_q = theta2q(tth_range, wavelength) # instantiate calculators xrd_cal = XRDCalculator() xrd_cal.wavelength = wavelength xrd_cal.TWO_THETA_TOL = 10**-2 calculate_params.update({'xrd_wavelength': xrd_cal.wavelength}) ####### PDF calculator instance ###### cal = PDFCalculator() ####### Bond distance calculator instance ###### bc = BondCalculator(rmax=bond_range) def map_learninglib(cif_fp, mode='bond_dst'): """function designed to build atomic distance list with parallel computation Parameters ----------
def learninglib_build(self, output_dir=None, pdfcal_cfg=None, rdf=True, xrd=False, Bisoequiv=0.1, rstep=None, DebyeCal=False, nosymmetry=False, tth_range=None, wavelength=0.5): """ method to build learning lib with diffpy based on path of cif library. Paramters of G(r) calculation are set via glbl.<attribute>. "PDFCal_config.txt" file with PDFCalculator configuration will also be output Parameters ---------- pdfcal_cfg : dict, optional configuration of PDF calculator, default is the one defined inside glbl class. rdf : bool, optional option to compute RDF or not. default to True, if not, compute pdf xrd : bool, optional option to compute XRD (which is slow). default to False. Bisoequiv : float, optional value of isotropic thermal parameter. default is 0.1. scientific equation: Biso = 8 (pi**2) Uiso rstep : float, optioanl space of PDF. default is pi/qmax. DebyeCal : bool, optional option to use Debye calculator. default is False. nosymmetry : bool, optional DEPRECATED for now. option to apply no symmetry. default is False. tth_range : ndarray, optional range of 2theta. default is [0:0.1:90] wavelength : float, optional wavelength in angstroms, default to 0.5 A which corresponds to Qmax ~= 17 """ # setup output dir timestr = _timestampstr(time.time()) if output_dir is None: tail = "LearningLib_{}".format(timestr) output_dir = os.path.join(os.getcwd(), tail) print('=== output dir would be {} ==='.format(output_dir)) self.output_dir = output_dir if tth_range is None: self.tth_range = np.arange(0, 90, 0.1) self.wavelength = wavelength self.std_q = theta2q(self.tth_range, self.wavelength) ####### configure pymatgen XRD calculator ##### # instantiate calculators xrd_cal = XRDCalculator() xrd_cal.wavelength = self.wavelength xrd_cal.TWO_THETA_TOL = 10**-2 self.calculate_params.update({'xrd_wavelength': xrd_cal.wavelength}) xrd_list = [] sg_list = [] # (a,b,c, alpha, beta, gamma, volume) structure_list_1 = [] # primative cell structure_list_2 = [] # ordinary cell # chemical element composition_list_1 = [] # primative cell composition_list_2 = [] # ordinary cell fail_list = [] ####### configure diffpy PDF calculator ###### if DebyeCal: cal = DebyePDFCalculator() self.calculator_type = 'Debye' cal = PDFCalculator() self.calculator = cal self.calculator_type = 'PDF' self.calculate_params.update({'calculator_type': self.calculator_type}) # setup calculator parameters if rstep is None: rstep = glbl.rstep self.rstep = rstep self.calculator.rstep = rstep # annoying fact self.calculate_params.update({'rstep':rstep}) if pdfcal_cfg is None: self.pdfcal_cfg = glbl.cfg self.calculate_params.update(self.pdfcal_cfg) # configure calculator for k,v in self.pdfcal_cfg.items(): setattr(self.calculator, k, v) # empty list to store results gr_list = [] rdf_list = [] print("====== INFO: calculation parameters:====\n{}" .format(self.calculate_params)) struc_df = pd.DataFrame() ############# loop through cifs ################# for cif in sorted(self.cif_list): _cif = os.path.join(self.input_dir, cif) try: # diffpy structure struc = loadStructure(_cif) struc.Bisoequiv = Bisoequiv ## calculate PDF/RDF with diffpy ## if nosymmetry: struc = nosymmetry(struc) cal.setStructure(struc) cal.eval() # pymatge structure struc_meta = CifParser(_cif) ## calculate XRD with pymatgen ## if xrd: xrd = xrd_cal.get_xrd_data(struc_meta\ .get_structures(False).pop()) _xrd = np.asarray(xrd)[:,:2] q, iq = _xrd.T interp_q = assign_nearest(self.std_q, q, iq) xrd_list.append(interp_q) else: pass ## test space group info ## _sg = struc_meta.get_structures(False).pop()\ .get_space_group_info() except: print("{} fail".format(_cif)) fail_list.append(cif) else: # no error for both pymatgen and diffpy gr_list.append(cal.pdf) rdf_list.append(cal.rdf) self.density_list.append(cal.slope) print('=== Finished evaluating PDF from structure {} ===' .format(cif)) ## update features ## flag = ['primitive', 'ordinary'] option = [True, False] compo_list = [composition_list_1, composition_list_2] struc_fields = ['a','b','c','alpha','beta','gamma', 'volume'] for f, op, compo in zip(flag, option, compo_list): rv_dict = {} struc = struc_meta.get_structures(op).pop() a, b, c = struc.lattice.abc aa, bb, cc = struc.lattice.angles volume = struc.volume for k, v in zip(struc_fields, [a, b, c, aa, bb, cc, volume]): rv_dict.update({"{}_{}".format(f, k) : v}) compo.append(struc.composition.as_dict()) struc_df = struc_df.append(rv_dict, ignore_index=True) # sg info, use the ordinary setup sg_list.append(struc.get_space_group_info()) print('=== Finished evaluating XRD from structure {} ===' .format(cif)) # finally, store crucial calculation results as attributes self.r_grid = cal.rgrid #4*pi * r^2 * rho(r) = R(r) -> RDF to density self.gr_array = np.asarray(gr_list)/4/np.pi/self.r_grid**2 self.rdf_array = np.asarray(gr_list) self.density_list = np.asarray(self.density_list) self.xrd_info = np.asarray(xrd_list) self.sg_list = sg_list # 1 -> primitive , 2 -> ordinary self.composition_list_1 = composition_list_1 self.composition_list_2 = composition_list_2 self.struc_df = struc_df self.fail_list = fail_list