def setUp(self): with open(os.path.join(test_dir, 'si_structure.json'), 'r') as sth: si_str = Structure.from_dict(json.load(sth)) with open(os.path.join(test_dir, 'si_bandstructure_line.json'), 'r') as bsh: si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh)) si_bs_line.structure = si_str with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'), 'r') as bsh: si_bs_uniform = BandStructure.from_dict(json.load(bsh)) si_bs_uniform.structure = si_str self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values()) self.df = pd.DataFrame({ 'bs_line': [si_bs_line], 'bs_uniform': [si_bs_uniform] }) with open(os.path.join(test_dir, 'VBr2_971787_bandstructure.json'), 'r') as bsh: vbr2_uniform = BandStructure.from_dict(json.load(bsh)) self.vbr2kpts = [ k.frac_coords for k in vbr2_uniform.labels_dict.values() ] self.vbr2kpts = [ [0.0, 0.0, 0.0], # \\Gamma [0.2, 0.0, 0.0], # between \\Gamma and M [0.5, 0.0, 0.0], # M [0.5, 0.0, 0.5] ] # L self.df2 = pd.DataFrame({'bs_line': [vbr2_uniform]})
def add_ebp(dir_entry): json_data = {} with open(dir_entry, 'r') as thefile: json_data = json.load(thefile) if 'ebp' in json_data: return bs = BandStructure.from_dict(json_data['bandstructure']) for i in range(bs.nb_bands): if min(bs.bands[1][i]) > bs.efermi: cbbottom = i vbtop = i-1 break vb_en = 0.0 cb_en = 0.0 for i in range(N_VB): vb_en += math.fsum(bs.bands[1][vbtop-i])/N_VB for i in range(N_CB): cb_en += math.fsum(bs.bands[1][cbbottom+i])/N_CB total_en = (vb_en + cb_en)/(2*len(bs.kpoints)) if not(bs.is_metal()): total_en -= (bs.get_vbm())['energy'] json_data['ebp'] = total_en else: print 'Warning, material is a metal! No VBM offset applied, no file written' if PRINT_DEBUG: print 'The branch point energy of ' + json_data['name'] + ' is ' + str(total_en) + ' eV' with open(dir_entry, 'w') as thefile: json.dump(json_data, thefile)
def from_dict(d): """ Construct VaspJob object from python dictionary. Returns ------- VaspJob object """ path = d['path'] inputs = VaspInput.from_dict(d['inputs']) job_settings = d['job_settings'] job_script_filename = d['job_script_filename'] name = d['name'] outputs = {} if d['outputs']: outputs[ 'ComputedStructureEntry'] = ComputedStructureEntry.from_dict( d['outputs']['ComputedStructureEntry']) vaspjob = VaspJob(path, inputs, job_settings, outputs, job_script_filename, name) vaspjob._band_structure = BandStructure.from_dict( d['band_structure']) if d['band_structure'] else None vaspjob._is_converged = d['is_converged'] if outputs: for k, v in vaspjob.computed_entry.data.items(): if k not in vaspjob._default_data_computed_entry: setattr(vaspjob, k, v) return vaspjob
def extract_bs(mat): bs = None # Process the bandstructure for information if "bs" in mat["bandstructure"]: bs_dict = mat["bandstructure"]["bs"] # Add in structure if not already there if "structure" not in bs_dict: bs_dict["structure"] = mat["structure"] # Add in High Symm K Path if not already there if len(bs_dict.get("labels_dict", {})) == 0: labels = get(mat, "inputs.nscf_line.kpoints.labels", None) kpts = get(mat, "inputs.nscf_line.kpoints.kpoints", None) if labels and kpts: labels_dict = dict(zip(labels, kpts)) labels_dict.pop(None, None) else: struc = Structure.from_dict(mat["structure"]) labels_dict = HighSymmKpath(struc)._kpath["kpoints"] bs_dict["labels_dict"] = labels_dict bs = BandStructureSymmLine.from_dict( BandStructure.from_dict(bs_dict).as_dict()) return bs
def setUp(self): with open(os.path.join(test_dir, 'si_structure.json'),'r') as sth: si_str = Structure.from_dict(json.load(sth)) with open(os.path.join(test_dir, 'si_bandstructure.json'),'r') as bsh: si_bs = BandStructure.from_dict(json.load(bsh)) si_bs.structure = si_str self.df = pd.DataFrame({'bs': [si_bs]})
def get_band_structure(self, task_id, line_mode=False): m_task = self.collection.find_one({"task_id": task_id}, {"calcs_reversed": 1}) fs_id = m_task['calcs_reversed'][0]['bandstructure_fs_id'] fs = gridfs.GridFS(self.db, 'bandstructure_fs') bs_json = zlib.decompress(fs.get(fs_id).read()) bs_dict = json.loads(bs_json) if line_mode: return BandStructureSymmLine.from_dict(bs_dict) else: return BandStructure.from_dict(bs_dict)
def get_band_structure(self, task_id): m_task = self.collection.find_one({"task_id": task_id}, {"calcs_reversed": 1}) fs_id = m_task['calcs_reversed'][0]['bandstructure_fs_id'] fs = gridfs.GridFS(self.db, 'bandstructure_fs') bs_json = zlib.decompress(fs.get(fs_id).read()) bs_dict = json.loads(bs_json.decode()) if bs_dict["@class"] == "BandStructure": return BandStructure.from_dict(bs_dict) elif bs_dict["@class"] == "BandStructureSymmLine": return BandStructureSymmLine.from_dict(bs_dict) else: raise ValueError("Unknown class for band structure! {}".format(bs_dict["@class"]))
def add_material(dir_entry, data_list): with open(dir_entry, 'r') as thefile: json_data = json.load(thefile) if 'ebp' not in json_data: print 'Skipped ' + json_data['name'] + ', no ebp' return bs = BandStructure.from_dict(json_data['bandstructure']) bandinfo = bs.get_band_gap() bandgap = CORRECTION_SLOPE*bandinfo["energy"]+CORRECTION_OFFSET ebp = EBP_CORRECTION*json_data['ebp'] if PRINT_DEBUG: print json_data['name'] + ' has vbm ' + str(-ebp) + " eV and cbm " + str(bandgap-ebp) + ' eV' data_list.append({'name': json_data['name'], 'vbm': -ebp, 'cbm': bandgap-ebp})
def setUp(self): with open(os.path.join(test_dir, 'si_structure.json'),'r') as sth: si_str = Structure.from_dict(json.load(sth)) with open(os.path.join(test_dir, 'si_bandstructure_line.json'),'r') as bsh: si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh)) si_bs_line.structure = si_str with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'),'r') as bsh: si_bs_uniform = BandStructure.from_dict(json.load(bsh)) si_bs_uniform.structure = si_str self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values()) self.df = pd.DataFrame({'bs_line': [si_bs_line], 'bs_uniform': [si_bs_uniform]}) with open(os.path.join(test_dir, 'VBr2_971787_bandstructure.json'), 'r') as bsh: vbr2_uniform = BandStructure.from_dict(json.load(bsh)) self.vbr2kpts = [k.frac_coords for k in vbr2_uniform.labels_dict.values()] self.vbr2kpts = [[0.0, 0.0, 0.0], # \\Gamma [0.2, 0.0, 0.0], # between \\Gamma and M [0.5, 0.0, 0.0], # M [0.5, 0.0, 0.5]] # L self.df2 = pd.DataFrame({'bs_line': [vbr2_uniform]})
def featurize(self, bs): """ Args: bs (pymatgen BandStructure or BandStructureSymmLine or their dict): The band structure to featurize() Returns ([float]): a list of band structure features. If not bs.structure, the features that require the structure will be returned as NaN. List of currently supported features: band_gap (eV): the difference between the CBM and VBM energy is_gap_direct (0.0|1.0): whether the band gap is direct or not direct_gap (eV): the minimum direct distance of the last valence band and the first conduction band {n,p}_ex{#}_en (eV): for example p_ex2_en is the absolute value of the energy of the second valence (p) band extremum w.r.t. VBM {n,p}_ex{#}_norm (float): e.g. n_ex1_norm is norm of the fractional coordinates of k-points of the 1st conduction (n) band extremum, i.e., the CBM """ if isinstance(bs, dict): bs = BandStructure.from_dict(bs) if bs.is_metal(): raise ValueError("Cannot featurize a metallic band structure!") # preparation cbm = bs.get_cbm() vbm = bs.get_vbm() band_gap = bs.get_band_gap() vbm_bidx, vbm_bspin = self.get_bindex_bspin(vbm, is_cbm=False) cbm_bidx, cbm_bspin = self.get_bindex_bspin(cbm, is_cbm=True) vbm_ens = np.array(bs.bands[vbm_bspin][vbm_bidx]) cbm_ens = np.array(bs.bands[cbm_bspin][cbm_bidx]) # featurize self.feat = [] self.feat.append(('band_gap', band_gap['energy'])) self.feat.append(('is_gap_direct', band_gap['direct'])) self.feat.append(('direct_gap', min(cbm_ens - vbm_ens))) self.feat.append( ('p_ex1_norm', norm(bs.kpoints[vbm['kpoint_index'][0]].frac_coords))) self.feat.append( ('n_ex1_norm', norm(bs.kpoints[cbm['kpoint_index'][0]].frac_coords))) return list(x[1] for x in self.feat)
def setUp(self): self.bz = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/transp/")) self.bz_bands = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/bands/")) self.bz_up = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/dos_up/"), dos_spin=1) self.bz_dw = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/dos_dw/"), dos_spin=-1) self.bz_fermi = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/fermi/")) with open(os.path.join(test_dir, "Cu2O_361_bandstructure.json"), "rt") as f: d = json.load(f) self.bs = BandStructure.from_dict(d) self.btr = BoltztrapRunner(self.bs, 1)
def setUp(self): with open(os.path.join(test_dir, 'si_structure.json'), 'r') as sth: si_str = Structure.from_dict(json.load(sth)) with open(os.path.join(test_dir, 'si_bandstructure_line.json'), 'r') as bsh: si_bs_line = BandStructureSymmLine.from_dict(json.load(bsh)) si_bs_line.structure = si_str with open(os.path.join(test_dir, 'si_bandstructure_uniform.json'), 'r') as bsh: si_bs_uniform = BandStructure.from_dict(json.load(bsh)) si_bs_uniform.structure = si_str self.si_kpts = list(HighSymmKpath(si_str).kpath['kpoints'].values()) self.df = pd.DataFrame({ 'bs_line': [si_bs_line], 'bs_uniform': [si_bs_uniform] })
def get_band_structure(self, task_id): """ Read the BS data into a PMG BandStructure or BandStructureSymmLine object Args: task_id(int or str): the task_id containing the data Returns: BandStructure or BandStructureSymmLine """ obj_dict = self.get_data_from_maggma_or_gridfs(task_id, key="bandstructure") if obj_dict["@class"] == "BandStructure": return BandStructure.from_dict(obj_dict) elif obj_dict["@class"] == "BandStructureSymmLine": return BandStructureSymmLine.from_dict(obj_dict) else: raise ValueError("Unknown class for band structure! {}".format( obj_dict["@class"]))
def add_material(dir_entry, data_list): with open(dir_entry, 'r') as thefile: json_data = json.load(thefile) if 'ebp' not in json_data: print 'Skipped ' + json_data['name'] + ', no ebp' return bs = BandStructure.from_dict(json_data['bandstructure']) bandinfo = bs.get_band_gap() bandgap = CORRECTION_SLOPE * bandinfo["energy"] + CORRECTION_OFFSET ebp = EBP_CORRECTION * json_data['ebp'] if PRINT_DEBUG: print json_data['name'] + ' has vbm ' + str( -ebp) + " eV and cbm " + str(bandgap - ebp) + ' eV' data_list.append({ 'name': json_data['name'], 'vbm': -ebp, 'cbm': bandgap - ebp })
def setUpClass(cls): cls.bz = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/transp/")) cls.bz_bands = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/bands/")) cls.bz_up = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/dos_up/"), dos_spin=1) cls.bz_dw = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/dos_dw/"), dos_spin=-1) cls.bz_fermi = BoltztrapAnalyzer.from_files( os.path.join(test_dir, "boltztrap/fermi/")) with open(os.path.join(test_dir, "Cu2O_361_bandstructure.json"), "rt") as f: d = json.load(f) cls.bs = BandStructure.from_dict(d) cls.btr = BoltztrapRunner(cls.bs, 1) warnings.simplefilter("ignore")
def dos_from_boltztrap(bs_dict, energy_grid=0.005, avoid_projections=False): """ Function to just interpolate a DOS from a bandstructure using BoltzTrap Args: bs_dict(dict): A MSONable dictionary for a bandstructure object energy_grid(float): the energy_grid spacing for the DOS in eV avoid_projections(bool): don't interpolate projections even if present """ bs = BandStructure.from_dict(bs_dict) st = bs.structure energy_grid = energy_grid * units.eV projections = True if bs.projections and not avoid_projections else False if bs.is_spin_polarized: data_up = BandstructureLoader(bs, st, spin=1) data_dn = BandstructureLoader(bs, st, spin=-1) min_bnd = min(data_up.ebands.min(), data_dn.ebands.min()) max_bnd = max(data_up.ebands.max(), data_dn.ebands.max()) data_up.set_upper_lower_bands(min_bnd, max_bnd) data_dn.set_upper_lower_bands(min_bnd, max_bnd) bztI_up = BztInterpolator(data_up, energy_range=np.inf, curvature=False) bztI_dn = BztInterpolator(data_dn, energy_range=np.inf, curvature=False) npts_mu = int((max_bnd - min_bnd) / energy_grid) dos_up = bztI_up.get_dos(partial_dos=projections, npts_mu=npts_mu) dos_dn = bztI_dn.get_dos(partial_dos=projections, npts_mu=npts_mu) cdos = merge_up_down_doses(dos_up, dos_dn) else: data = BandstructureLoader(bs, st) min_bnd = min(data.ebands.min(), data.ebands.min()) max_bnd = max(data.ebands.max(), data.ebands.max()) npts_mu = int((max_bnd - min_bnd) / energy_grid) bztI = BztInterpolator(data, energy_range=np.inf, curvature=False) cdos = bztI.get_dos(partial_dos=projections, npts_mu=npts_mu) return cdos.as_dict()
def get_interpolated_dos(self, mat): nelect = mat["calc_settings"]["nelect"] bs_dict = mat["bandstructure"]["uniform_bs"] bs_dict["structure"] = mat['structure'] bs = BandStructure.from_dict(bs_dict) if bs.is_spin_polarized: with ScratchDir("."): BoltztrapRunner(bs=bs, nelec=nelect, run_type="DOS", dos_type="TETRA", spin=1, timeout=60).run(path_dir=os.getcwd()) an_up = BoltztrapAnalyzer.from_files("boltztrap/", dos_spin=1) with ScratchDir("."): BoltztrapRunner(bs=bs, nelec=nelect, run_type="DOS", dos_type="TETRA", spin=-1, timeout=60).run(path_dir=os.getcwd()) an_dw = BoltztrapAnalyzer.from_files("boltztrap/", dos_spin=-1) cdos = an_up.get_complete_dos(bs.structure, an_dw) else: with ScratchDir("."): BoltztrapRunner(bs=bs, nelec=nelect, run_type="DOS", dos_type="TETRA", timeout=60).run(path_dir=os.getcwd()) an = BoltztrapAnalyzer.from_files("boltztrap/") cdos = an.get_complete_dos(bs.structure) return cdos
def build_bs(bs_dict, mat): bs_dict["structure"] = mat["structure"] # Add in High Symm K Path if not already there if len(bs_dict.get("labels_dict", {})) == 0: labels = get(mat, "inputs.nscf_line.kpoints.labels", None) kpts = get(mat, "inputs.nscf_line.kpoints.kpoints", None) if labels and kpts: labels_dict = dict(zip(labels, kpts)) labels_dict.pop(None, None) else: struc = Structure.from_dict(mat["structure"]) labels_dict = HighSymmKpath(struc)._kpath["kpoints"] bs_dict["labels_dict"] = labels_dict # This is somethign to do with BandStructureSymmLine's from dict being problematic bs = BandStructureSymmLine.from_dict( BandStructure.from_dict(bs_dict).as_dict()) return bs
def process_item(self, mat): """ Process the tasks and materials into just a list of materials Args: mat (dict): material document Returns: (dict): electronic_structure document """ self.logger.info("Processing: {}".format(mat[self.materials.key])) d = {self.electronic_structure.key: mat[ self.materials.key], "bandstructure": {}} bs = None dos = None interpolated_dos = None # Process the bandstructure for information if "bs" in mat["bandstructure"]: if "structure" not in mat["bandstructure"]["bs"]: mat["bandstructure"]["bs"]["structure"] = mat["structure"] if len(mat["bandstructure"]["bs"].get("labels_dict", {})) == 0: struc = Structure.from_dict(mat["structure"]) kpath = HighSymmKpath(struc)._kpath["kpoints"] mat["bandstructure"]["bs"]["labels_dict"] = kpath # Somethign is wrong with the as_dict / from_dict encoding in the two band structure objects so have to use this hodge podge serialization # TODO: Fix bandstructure objects in pymatgen bs = BandStructureSymmLine.from_dict( BandStructure.from_dict(mat["bandstructure"]["bs"]).as_dict()) d["bandstructure"]["band_gap"] = {"band_gap": bs.get_band_gap()["energy"], "direct_gap": bs.get_direct_band_gap(), "is_direct": bs.get_band_gap()["direct"], "transition": bs.get_band_gap()["transition"]} if self.small_plot: d["bandstructure"]["plot_small"] = get_small_plot(bs) if "dos" in mat["bandstructure"]: dos = CompleteDos.from_dict(mat["bandstructure"]["dos"]) if self.interpolate_dos and "uniform_bs" in mat["bandstructure"]: try: interpolated_dos = self.get_interpolated_dos(mat) except Exception: self.logger.warning("Boltztrap interpolation failed for {}. Continuing with regular DOS".format(mat[self.materials.key])) # Generate static images if self.static_images: try: ylim = None if bs: plotter = WebBSPlotter(bs) fig = plotter.get_plot() ylim = fig.ylim() # Used by DOS plot fig.close() d["bandstructure"]["bs_plot"] = image_from_plotter(plotter) if dos: plotter = WebDosVertPlotter() plotter.add_dos_dict(dos.get_element_dos()) if interpolated_dos: plotter.add_dos("Total DOS", interpolated_dos) d["bandstructure"]["dos_plot"] = image_from_plotter(plotter, ylim=ylim) d["bandstructure"]["dos_plot"] = image_from_plotter(plotter, ylim=ylim) except Exception: self.logger.warning( "Caught error in electronic structure plotting for {}: {}".format(mat[self.materials.key], traceback.format_exc())) return None return d
#N_CB = 2 #N_VB = 4 #filename = 'AlN_structure.json' #N_CB = 1 #N_VB = 2 #filename = 'zb-GaN_structure.json' N_CB = 1 N_VB = 2 filename = 'CdO_structure.json' with open(filename, 'r') as thefile: json_data = json.load(thefile) bs = BandStructure.from_dict(json_data['bandstructure']) for i in range(bs.nb_bands): if min(bs.bands[1][i]) > bs.efermi: cbbottom = i vbtop = i - 1 break vb_en = 0.0 cb_en = 0.0 for i in range(N_VB): vb_en += math.fsum(bs.bands[1][vbtop - i]) / N_VB for i in range(N_CB): cb_en += math.fsum(bs.bands[1][cbbottom + i]) / N_CB total_en = (vb_en + cb_en) / (2 * len(bs.kpoints)) if not (bs.is_metal()):
def run_task(self, fw_spec): # import here to prevent import errors in bigger MPCollab # get the band structure and nelect from files """ prev_dir = get_loc(fw_spec['prev_vasp_dir']) vasprun_loc = zpath(os.path.join(prev_dir, 'vasprun.xml')) kpoints_loc = zpath(os.path.join(prev_dir, 'KPOINTS')) vr = Vasprun(vasprun_loc) bs = vr.get_band_structure(kpoints_filename=kpoints_loc) """ filename = get_slug( 'JOB--' + fw_spec['mpsnl'].structure.composition.reduced_formula + '--' + fw_spec['task_type']) with open(filename, 'w+') as f: f.write('') # get the band structure and nelect from DB block_part = get_block_part(fw_spec['prev_vasp_dir']) db_dir = os.environ['DB_LOC'] assert isinstance(db_dir, object) db_path = os.path.join(db_dir, 'tasks_db.json') with open(db_path) as f: creds = json.load(f) connection = MongoClient(creds['host'], creds['port']) tdb = connection[creds['database']] tdb.authenticate(creds['admin_user'], creds['admin_password']) props = { "calculations": 1, "task_id": 1, "state": 1, "pseudo_potential": 1, "run_type": 1, "is_hubbard": 1, "hubbards": 1, "unit_cell_formula": 1 } m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: time.sleep( 60) # only thing to think of is wait for DB insertion(?) m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: raise ValueError( "Could not find task with dir_name: {}".format(block_part)) if m_task['state'] != 'successful': raise ValueError( "Cannot run Boltztrap; parent job unsuccessful") nelect = m_task['calculations'][0]['input']['parameters']['NELECT'] bs_id = m_task['calculations'][0]['band_structure_fs_id'] print bs_id, type(bs_id) fs = gridfs.GridFS(tdb, 'band_structure_fs') bs_dict = json.loads(fs.get(bs_id).read()) bs_dict['structure'] = m_task['calculations'][0]['output'][ 'crystal'] bs = BandStructure.from_dict(bs_dict) print("find previous run with block_part {}".format(block_part)) print 'Band Structure found:', bool(bs) print(bs.as_dict()) print("nelect: {}".format(nelect)) # run Boltztrap doping = [] for d in [1e16, 1e17, 1e18, 1e19, 1e20]: doping.extend([1 * d, 2.5 * d, 5 * d, 7.5 * d]) doping.append(1e21) runner = BoltztrapRunner(bs, nelect, doping=doping) dir = runner.run(path_dir=os.getcwd()) # put the data in the database bta = BoltztrapAnalyzer.from_files(dir) # 8/21/15 - Anubhav removed fs_id (also see line further below, ted['boltztrap_full_fs_id'] ...) # 8/21/15 - this is to save space in MongoDB, as well as non-use of full Boltztrap output (vs rerun) """ data = bta.as_dict() data.update(get_meta_from_structure(bs._structure)) data['snlgroup_id'] = fw_spec['snlgroup_id'] data['run_tags'] = fw_spec['run_tags'] data['snl'] = fw_spec['mpsnl'] data['dir_name_full'] = dir data['dir_name'] = get_block_part(dir) data['task_id'] = m_task['task_id'] del data['hall'] # remove because it is too large and not useful fs = gridfs.GridFS(tdb, "boltztrap_full_fs") btid = fs.put(json.dumps(jsanitize(data))) """ # now for the "sanitized" data ted = bta.as_dict() del ted['seebeck'] del ted['hall'] del ted['kappa'] del ted['cond'] # ted['boltztrap_full_fs_id'] = btid ted['snlgroup_id'] = fw_spec['snlgroup_id'] ted['run_tags'] = fw_spec['run_tags'] ted['snl'] = fw_spec['mpsnl'].as_dict() ted['dir_name_full'] = dir ted['dir_name'] = get_block_part(dir) ted['task_id'] = m_task['task_id'] ted['pf_doping'] = bta.get_power_factor(output='tensor', relaxation_time=self.TAU) ted['zt_doping'] = bta.get_zt(output='tensor', relaxation_time=self.TAU, kl=self.KAPPAL) ted['pf_eigs'] = self.get_eigs(ted, 'pf_doping') ted['pf_best'] = self.get_extreme(ted, 'pf_eigs') ted['pf_best_dope18'] = self.get_extreme(ted, 'pf_eigs', max_didx=3) ted['pf_best_dope19'] = self.get_extreme(ted, 'pf_eigs', max_didx=4) ted['zt_eigs'] = self.get_eigs(ted, 'zt_doping') ted['zt_best'] = self.get_extreme(ted, 'zt_eigs') ted['zt_best_dope18'] = self.get_extreme(ted, 'zt_eigs', max_didx=3) ted['zt_best_dope19'] = self.get_extreme(ted, 'zt_eigs', max_didx=4) ted['seebeck_eigs'] = self.get_eigs(ted, 'seebeck_doping') ted['seebeck_best'] = self.get_extreme(ted, 'seebeck_eigs') ted['seebeck_best_dope18'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=3) ted['seebeck_best_dope19'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=4) ted['cond_eigs'] = self.get_eigs(ted, 'cond_doping') ted['cond_best'] = self.get_extreme(ted, 'cond_eigs') ted['cond_best_dope18'] = self.get_extreme(ted, 'cond_eigs', max_didx=3) ted['cond_best_dope19'] = self.get_extreme(ted, 'cond_eigs', max_didx=4) ted['kappa_eigs'] = self.get_eigs(ted, 'kappa_doping') ted['kappa_best'] = self.get_extreme(ted, 'kappa_eigs', maximize=False) ted['kappa_best_dope18'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=3) ted['kappa_best_dope19'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=4) try: from mpcollab.thermoelectrics.boltztrap_TE import BoltzSPB bzspb = BoltzSPB(ted) maxpf_p = bzspb.get_maximum_power_factor( 'p', temperature=0, tau=1E-14, ZT=False, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxpf_n = bzspb.get_maximum_power_factor( 'n', temperature=0, tau=1E-14, ZT=False, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_p = bzspb.get_maximum_power_factor( 'p', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_n = bzspb.get_maximum_power_factor( 'n', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) ted['zt_best_finemesh'] = {'p': maxzt_p, 'n': maxzt_n} ted['pf_best_finemesh'] = {'p': maxpf_p, 'n': maxpf_n} except: import traceback traceback.print_exc() print 'COULD NOT GET FINE MESH DATA' # add is_compatible mpc = MaterialsProjectCompatibility("Advanced") try: func = m_task["pseudo_potential"]["functional"] labels = m_task["pseudo_potential"]["labels"] symbols = ["{} {}".format(func, label) for label in labels] parameters = { "run_type": m_task["run_type"], "is_hubbard": m_task["is_hubbard"], "hubbards": m_task["hubbards"], "potcar_symbols": symbols } entry = ComputedEntry(Composition(m_task["unit_cell_formula"]), 0.0, 0.0, parameters=parameters, entry_id=m_task["task_id"]) ted["is_compatible"] = bool(mpc.process_entry(entry)) except: traceback.print_exc() print 'ERROR in getting compatibility, task_id: {}'.format( m_task["task_id"]) ted["is_compatible"] = None tdb.boltztrap.insert(jsanitize(ted)) update_spec = { 'prev_vasp_dir': fw_spec['prev_vasp_dir'], 'boltztrap_dir': os.getcwd(), 'prev_task_type': fw_spec['task_type'], 'mpsnl': fw_spec['mpsnl'].as_dict(), 'snlgroup_id': fw_spec['snlgroup_id'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters') } return FWAction(update_spec=update_spec)
def featurize(self, bs): """ Args: bs (pymatgen BandStructure or BandStructureSymmLine or their dict): The band structure to featurize. To obtain all features, bs should include the structure attribute. Returns: ([float]): a list of band structure features. If not bs.structure, features that require the structure will be returned as NaN. List of currently supported features: band_gap (eV): the difference between the CBM and VBM energy is_gap_direct (0.0|1.0): whether the band gap is direct or not direct_gap (eV): the minimum direct distance of the last valence band and the first conduction band p_ex1_norm (float): k-space distance between Gamma point and k-point of VBM n_ex1_norm (float): k-space distance between Gamma point and k-point of CBM p_ex1_degen: degeneracy of VBM n_ex1_degen: degeneracy of CBM if kpoints is provided (e.g. for kpoints == [[0.0, 0.0, 0.0]]): n_0.0;0.0;0.0_en: (energy of the first conduction band at [0.0, 0.0, 0.0] - CBM energy) p_0.0;0.0;0.0_en: (energy of the last valence band at [0.0, 0.0, 0.0] - VBM energy) """ if isinstance(bs, dict): bs = BandStructure.from_dict(bs) if bs.is_metal(): raise ValueError("Cannot featurize a metallic band structure!") bs_kpts = [k.frac_coords for k in bs.kpoints] cvd = {'p': bs.get_vbm(), 'n': bs.get_cbm()} for itp, tp in enumerate(['p', 'n']): cvd[tp]['k'] = bs.kpoints[cvd[tp]['kpoint_index'][0]].frac_coords cvd[tp]['bidx'], cvd[tp]['sidx'] = \ self.get_bindex_bspin(cvd[tp], is_cbm=bool(itp)) cvd[tp]['Es'] = np.array(bs.bands[cvd[tp]['sidx']][cvd[tp]['bidx']]) band_gap = bs.get_band_gap() # featurize feat = OrderedDict() feat['band_gap'] = band_gap['energy'] feat['is_gap_direct'] = band_gap['direct'] feat['direct_gap'] = min(cvd['n']['Es'] - cvd['p']['Es']) for tp in ['p', 'n']: feat['{}_ex1_norm'.format(tp)] = norm(cvd[tp]['k']) if bs.structure: feat['{}_ex1_degen'.format(tp)] = bs.get_kpoint_degeneracy(cvd[tp]['k']) else: feat['{}_ex1_degen'.format(tp)] = float('NaN') if self.kpoints: obands = {'n': [], 'p': []} for spin in bs.bands: for band_idx in range(bs.nb_bands): if max(bs.bands[spin][band_idx]) < bs.efermi: obands['p'].append(bs.bands[spin][band_idx]) if min(bs.bands[spin][band_idx]) > bs.efermi: obands['n'].append(bs.bands[spin][band_idx]) bands = {tp: np.zeros((len(obands[tp]), len(self.kpoints))) for tp in ['p', 'n']} for tp in ['p', 'n']: for ib, ob in enumerate(obands[tp]): bands[tp][ib, :] = griddata(points=np.array(bs_kpts), values=np.array(ob) - cvd[tp]['energy'], xi=self.kpoints, method=self.find_method) for ik, k in enumerate(self.kpoints): sorted_band = np.sort(bands[tp][:, ik]) if tp == 'p': sorted_band = sorted_band[::-1] for ib in range(self.nbands): k_name = '{}_{};{};{}_en{}'.format(tp, k[0], k[1], k[2], ib+1) try: feat[k_name] = sorted_band[ib] except IndexError: feat[k_name] = float('NaN') return list(feat.values())
def run_task(self, fw_spec): # get the band structure and nelect from files """ prev_dir = get_loc(fw_spec['prev_vasp_dir']) vasprun_loc = zpath(os.path.join(prev_dir, 'vasprun.xml')) kpoints_loc = zpath(os.path.join(prev_dir, 'KPOINTS')) vr = Vasprun(vasprun_loc) bs = vr.get_band_structure(kpoints_filename=kpoints_loc) """ # get the band structure and nelect from DB block_part = get_block_part(fw_spec['prev_vasp_dir']) db_dir = os.environ['DB_LOC'] assert isinstance(db_dir, object) db_path = os.path.join(db_dir, 'tasks_db.json') with open(db_path) as f: creds = json.load(f) connection = MongoClient(creds['host'], creds['port']) tdb = connection[creds['database']] tdb.authenticate(creds['admin_user'], creds['admin_password']) m_task = tdb.tasks.find_one({"dir_name": block_part}, { "calculations": 1, "task_id": 1 }) nelect = m_task['calculations'][0]['input']['parameters']['NELECT'] bs_id = m_task['calculations'][0]['band_structure_fs_id'] print bs_id, type(bs_id) fs = gridfs.GridFS(tdb, 'band_structure_fs') bs_dict = json.loads(fs.get(bs_id).read()) bs_dict['structure'] = m_task['calculations'][0]['output'][ 'crystal'] bs = BandStructure.from_dict(bs_dict) print 'Band Structure found:', bool(bs) print nelect # run Boltztrap runner = BoltztrapRunner(bs, nelect) dir = runner.run(path_dir=os.getcwd()) # put the data in the database bta = BoltztrapAnalyzer.from_files(dir) data = bta.to_dict data.update(get_meta_from_structure(bs._structure)) data['snlgroup_id'] = fw_spec['snlgroup_id'] data['run_tags'] = fw_spec['run_tags'] data['snl'] = fw_spec['mpsnl'] data['dir_name_full'] = dir data['dir_name'] = get_block_part(dir) data['task_id'] = m_task['task_id'] data['hall'] = {} # remove because it is too large and not useful data['hall_doping'] = { } # remove because it is too large and not useful tdb.boltztrap.insert(clean_json(data)) update_spec = { 'prev_vasp_dir': fw_spec['prev_vasp_dir'], 'boltztrap_dir': os.getcwd(), 'prev_task_type': fw_spec['task_type'], 'mpsnl': fw_spec['mpsnl'], 'snlgroup_id': fw_spec['snlgroup_id'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters') } return FWAction(update_spec=update_spec)
#N_CB = 2 #N_VB = 4 #filename = 'AlN_structure.json' #N_CB = 1 #N_VB = 2 #filename = 'zb-GaN_structure.json' N_CB = 1 N_VB = 2 filename = 'CdO_structure.json' with open(filename, 'r') as thefile: json_data = json.load(thefile) bs = BandStructure.from_dict(json_data['bandstructure']) for i in range(bs.nb_bands): if min(bs.bands[1][i]) > bs.efermi: cbbottom = i vbtop = i-1 break vb_en = 0.0 cb_en = 0.0 for i in range(N_VB): vb_en += math.fsum(bs.bands[1][vbtop-i])/N_VB for i in range(N_CB): cb_en += math.fsum(bs.bands[1][cbbottom+i])/N_CB total_en = (vb_en + cb_en)/(2*len(bs.kpoints)) if not(bs.is_metal()):
def run_task(self, fw_spec): # import here to prevent import errors in bigger MPCollab # get the band structure and nelect from files """ prev_dir = get_loc(fw_spec['prev_vasp_dir']) vasprun_loc = zpath(os.path.join(prev_dir, 'vasprun.xml')) kpoints_loc = zpath(os.path.join(prev_dir, 'KPOINTS')) vr = Vasprun(vasprun_loc) bs = vr.get_band_structure(kpoints_filename=kpoints_loc) """ filename = get_slug( 'JOB--' + fw_spec['mpsnl'].structure.composition.reduced_formula + '--' + fw_spec['task_type']) with open(filename, 'w+') as f: f.write('') # get the band structure and nelect from DB block_part = get_block_part(fw_spec['prev_vasp_dir']) db_dir = os.environ['DB_LOC'] assert isinstance(db_dir, object) db_path = os.path.join(db_dir, 'tasks_db.json') with open(db_path) as f: creds = json.load(f) connection = MongoClient(creds['host'], creds['port']) tdb = connection[creds['database']] tdb.authenticate(creds['admin_user'], creds['admin_password']) props = {"calculations": 1, "task_id": 1, "state": 1, "pseudo_potential": 1, "run_type": 1, "is_hubbard": 1, "hubbards": 1, "unit_cell_formula": 1} m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: time.sleep(60) # only thing to think of is wait for DB insertion(?) m_task = tdb.tasks.find_one({"dir_name": block_part}, props) if not m_task: raise ValueError("Could not find task with dir_name: {}".format(block_part)) if m_task['state'] != 'successful': raise ValueError("Cannot run Boltztrap; parent job unsuccessful") nelect = m_task['calculations'][0]['input']['parameters']['NELECT'] bs_id = m_task['calculations'][0]['band_structure_fs_id'] print bs_id, type(bs_id) fs = gridfs.GridFS(tdb, 'band_structure_fs') bs_dict = json.loads(fs.get(bs_id).read()) bs_dict['structure'] = m_task['calculations'][0]['output']['crystal'] bs = BandStructure.from_dict(bs_dict) print 'Band Structure found:', bool(bs) print nelect # run Boltztrap runner = BoltztrapRunner(bs, nelect) dir = runner.run(path_dir=os.getcwd()) # put the data in the database bta = BoltztrapAnalyzer.from_files(dir) # 8/21/15 - Anubhav removed fs_id (also see line further below, ted['boltztrap_full_fs_id'] ...) # 8/21/15 - this is to save space in MongoDB, as well as non-use of full Boltztrap output (vs rerun) """ data = bta.as_dict() data.update(get_meta_from_structure(bs._structure)) data['snlgroup_id'] = fw_spec['snlgroup_id'] data['run_tags'] = fw_spec['run_tags'] data['snl'] = fw_spec['mpsnl'] data['dir_name_full'] = dir data['dir_name'] = get_block_part(dir) data['task_id'] = m_task['task_id'] del data['hall'] # remove because it is too large and not useful fs = gridfs.GridFS(tdb, "boltztrap_full_fs") btid = fs.put(json.dumps(jsanitize(data))) """ # now for the "sanitized" data ted = bta.as_dict() del ted['seebeck'] del ted['hall'] del ted['kappa'] del ted['cond'] # ted['boltztrap_full_fs_id'] = btid ted['snlgroup_id'] = fw_spec['snlgroup_id'] ted['run_tags'] = fw_spec['run_tags'] ted['snl'] = fw_spec['mpsnl'].as_dict() ted['dir_name_full'] = dir ted['dir_name'] = get_block_part(dir) ted['task_id'] = m_task['task_id'] ted['pf_doping'] = bta.get_power_factor(output='tensor', relaxation_time=self.TAU) ted['zt_doping'] = bta.get_zt(output='tensor', relaxation_time=self.TAU, kl=self.KAPPAL) ted['pf_eigs'] = self.get_eigs(ted, 'pf_doping') ted['pf_best'] = self.get_extreme(ted, 'pf_eigs') ted['pf_best_dope18'] = self.get_extreme(ted, 'pf_eigs', max_didx=3) ted['pf_best_dope19'] = self.get_extreme(ted, 'pf_eigs', max_didx=4) ted['zt_eigs'] = self.get_eigs(ted, 'zt_doping') ted['zt_best'] = self.get_extreme(ted, 'zt_eigs') ted['zt_best_dope18'] = self.get_extreme(ted, 'zt_eigs', max_didx=3) ted['zt_best_dope19'] = self.get_extreme(ted, 'zt_eigs', max_didx=4) ted['seebeck_eigs'] = self.get_eigs(ted, 'seebeck_doping') ted['seebeck_best'] = self.get_extreme(ted, 'seebeck_eigs') ted['seebeck_best_dope18'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=3) ted['seebeck_best_dope19'] = self.get_extreme(ted, 'seebeck_eigs', max_didx=4) ted['cond_eigs'] = self.get_eigs(ted, 'cond_doping') ted['cond_best'] = self.get_extreme(ted, 'cond_eigs') ted['cond_best_dope18'] = self.get_extreme(ted, 'cond_eigs', max_didx=3) ted['cond_best_dope19'] = self.get_extreme(ted, 'cond_eigs', max_didx=4) ted['kappa_eigs'] = self.get_eigs(ted, 'kappa_doping') ted['kappa_best'] = self.get_extreme(ted, 'kappa_eigs', maximize=False) ted['kappa_best_dope18'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=3) ted['kappa_best_dope19'] = self.get_extreme(ted, 'kappa_eigs', maximize=False, max_didx=4) try: from mpcollab.thermoelectrics.boltztrap_TE import BoltzSPB bzspb = BoltzSPB(ted) maxpf_p = bzspb.get_maximum_power_factor('p', temperature=0, tau=1E-14, ZT=False, kappal=0.5,\ otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxpf_n = bzspb.get_maximum_power_factor('n', temperature=0, tau=1E-14, ZT=False, kappal=0.5,\ otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_p = bzspb.get_maximum_power_factor('p', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) maxzt_n = bzspb.get_maximum_power_factor('n', temperature=0, tau=1E-14, ZT=True, kappal=0.5, otherprops=('get_seebeck_mu_eig', 'get_conductivity_mu_eig', \ 'get_thermal_conductivity_mu_eig', 'get_average_eff_mass_tensor_mu')) ted['zt_best_finemesh'] = {'p': maxzt_p, 'n': maxzt_n} ted['pf_best_finemesh'] = {'p': maxpf_p, 'n': maxpf_n} except: import traceback traceback.print_exc() print 'COULD NOT GET FINE MESH DATA' # add is_compatible mpc = MaterialsProjectCompatibility("Advanced") try: func = m_task["pseudo_potential"]["functional"] labels = m_task["pseudo_potential"]["labels"] symbols = ["{} {}".format(func, label) for label in labels] parameters = {"run_type": m_task["run_type"], "is_hubbard": m_task["is_hubbard"], "hubbards": m_task["hubbards"], "potcar_symbols": symbols} entry = ComputedEntry(Composition(m_task["unit_cell_formula"]), 0.0, 0.0, parameters=parameters, entry_id=m_task["task_id"]) ted["is_compatible"] = bool(mpc.process_entry(entry)) except: traceback.print_exc() print 'ERROR in getting compatibility, task_id: {}'.format(m_task["task_id"]) ted["is_compatible"] = None tdb.boltztrap.insert(jsanitize(ted)) update_spec = {'prev_vasp_dir': fw_spec['prev_vasp_dir'], 'boltztrap_dir': os.getcwd(), 'prev_task_type': fw_spec['task_type'], 'mpsnl': fw_spec['mpsnl'].as_dict(), 'snlgroup_id': fw_spec['snlgroup_id'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters')} return FWAction(update_spec=update_spec)
def run_task(self, fw_spec): # get the band structure and nelect from files """ prev_dir = get_loc(fw_spec['prev_vasp_dir']) vasprun_loc = zpath(os.path.join(prev_dir, 'vasprun.xml')) kpoints_loc = zpath(os.path.join(prev_dir, 'KPOINTS')) vr = Vasprun(vasprun_loc) bs = vr.get_band_structure(kpoints_filename=kpoints_loc) """ # get the band structure and nelect from DB block_part = get_block_part(fw_spec['prev_vasp_dir']) db_dir = os.environ['DB_LOC'] assert isinstance(db_dir, object) db_path = os.path.join(db_dir, 'tasks_db.json') with open(db_path) as f: creds = json.load(f) connection = MongoClient(creds['host'], creds['port']) tdb = connection[creds['database']] tdb.authenticate(creds['admin_user'], creds['admin_password']) m_task = tdb.tasks.find_one({"dir_name": block_part}, {"calculations": 1, "task_id": 1}) nelect = m_task['calculations'][0]['input']['parameters']['NELECT'] bs_id = m_task['calculations'][0]['band_structure_fs_id'] print bs_id, type(bs_id) fs = gridfs.GridFS(tdb, 'band_structure_fs') bs_dict = json.loads(fs.get(bs_id).read()) bs_dict['structure'] = m_task['calculations'][0]['output']['crystal'] bs = BandStructure.from_dict(bs_dict) print 'Band Structure found:', bool(bs) print nelect # run Boltztrap runner = BoltztrapRunner(bs, nelect) dir = runner.run(path_dir=os.getcwd()) # put the data in the database bta = BoltztrapAnalyzer.from_files(dir) data = bta.to_dict data.update(get_meta_from_structure(bs._structure)) data['snlgroup_id'] = fw_spec['snlgroup_id'] data['run_tags'] = fw_spec['run_tags'] data['snl'] = fw_spec['mpsnl'] data['dir_name_full'] = dir data['dir_name'] = get_block_part(dir) data['task_id'] = m_task['task_id'] data['hall'] = {} # remove because it is too large and not useful data['hall_doping'] = {} # remove because it is too large and not useful tdb.boltztrap.insert(clean_json(data)) update_spec = {'prev_vasp_dir': fw_spec['prev_vasp_dir'], 'boltztrap_dir': os.getcwd(), 'prev_task_type': fw_spec['task_type'], 'mpsnl': fw_spec['mpsnl'], 'snlgroup_id': fw_spec['snlgroup_id'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters')} return FWAction(update_spec=update_spec)
def featurize(self, bs): """ Args: bs (pymatgen BandStructure or BandStructureSymmLine or their dict): The band structure to featurize. To obtain all features, bs should include the structure attribute. Returns: ([float]): a list of band structure features. If not bs.structure, features that require the structure will be returned as NaN. List of currently supported features: band_gap (eV): the difference between the CBM and VBM energy is_gap_direct (0.0|1.0): whether the band gap is direct or not direct_gap (eV): the minimum direct distance of the last valence band and the first conduction band p_ex1_norm (float): k-space distance between Gamma point and k-point of VBM n_ex1_norm (float): k-space distance between Gamma point and k-point of CBM p_ex1_degen: degeneracy of VBM n_ex1_degen: degeneracy of CBM if kpoints is provided (e.g. for kpoints == [[0.0, 0.0, 0.0]]): n_0.0;0.0;0.0_en: (energy of the first conduction band at [0.0, 0.0, 0.0] - CBM energy) p_0.0;0.0;0.0_en: (energy of the last valence band at [0.0, 0.0, 0.0] - VBM energy) """ if isinstance(bs, dict): bs = BandStructure.from_dict(bs) if bs.is_metal(): raise ValueError("Cannot featurize a metallic band structure!") bs_kpts = [k.frac_coords for k in bs.kpoints] cvd = {'p': bs.get_vbm(), 'n': bs.get_cbm()} for itp, tp in enumerate(['p', 'n']): cvd[tp]['k'] = bs.kpoints[cvd[tp]['kpoint_index'][0]].frac_coords cvd[tp]['bidx'], cvd[tp]['sidx'] = \ self.get_bindex_bspin(cvd[tp], is_cbm=bool(itp)) cvd[tp]['Es'] = np.array( bs.bands[cvd[tp]['sidx']][cvd[tp]['bidx']]) band_gap = bs.get_band_gap() # featurize self.feat = {} self.feat['band_gap'] = band_gap['energy'] self.feat['is_gap_direct'] = band_gap['direct'] self.feat['direct_gap'] = min(cvd['n']['Es'] - cvd['p']['Es']) if self.kpoints: for tp in ['p', 'n']: fit = griddata(points=np.array(bs_kpts), values=cvd[tp]['Es'] - cvd[tp]['energy'], xi=self.kpoints, method=self.find_method) for ik, k in enumerate(self.kpoints): k_name = '{}_{};{};{}_en'.format(tp, k[0], k[1], k[2]) self.feat[k_name] = fit[ik] for tp in ['p', 'n']: self.feat['{}_ex1_norm'.format(tp)] = norm(cvd[tp]['k']) if bs.structure: self.feat['{}_ex1_degen'.format(tp)] = \ bs.get_kpoint_degeneracy(cvd[tp]['k']) else: self.feat['{}_ex1_degen'] = float('NaN') return list(self.feat.values())