def get_band_center(form): c = Composition(str(form)) prod = 1.0 for el, amt in c.get_el_amt_dict().iteritems(): prod = prod * (Element(el).X ** amt) return -prod ** (1 / sum(c.get_el_amt_dict().values()))
def _parse_criteria(self, criteria): """ Internal method to perform mapping of criteria to proper mongo queries using aliases, as well as some useful sanitization. For example, string formulas such as "Fe2O3" are auto-converted to proper mongo queries of {"Fe":2, "O":3}. If 'criteria' is None, returns an empty dict. Putting this logic here simplifies callers and allows subclasses to insert something even when there are no criteria. """ if criteria is None: return dict() parsed_crit = dict() for k, v in self.defaults.items(): if k not in criteria: parsed_crit[self.aliases.get(k, k)] = v for key, crit in list(criteria.items()): if key in ["normalized_formula", "reduced_cell_formula"]: comp = Composition(crit) parsed_crit["pretty_formula"] = comp.reduced_formula elif key == "unit_cell_formula": comp = Composition(crit) crit = comp.as_dict() for el, amt in crit.items(): parsed_crit["{}.{}".format(self.aliases[key], el)] = amt parsed_crit["nelements"] = len(crit) parsed_crit['pretty_formula'] = comp.reduced_formula elif key in ["$or", "$and"]: parsed_crit[key] = [self._parse_criteria(m) for m in crit] else: parsed_crit[self.aliases.get(key, key)] = crit return parsed_crit
def __init__(self, lit_file=DEFAULT_LIT_FILE): self.line_data = {} # (line no.) -> {"formula_pretty", "tag1", "tag2", "tag3"} if not os.path.exists(lit_file): raise ValueError("Cannot find lit file: {}".format(lit_file)) with open(lit_file) as f: line_no = 1 tag1 = "" # most recent level-1 tag tag2 = "" # most recent level-2 tag tag3 = "" # most recent level-3 tag for line in f: line = line.strip() if line.startswith("###"): tag3 = line[3:] elif line.startswith("##"): tag2 = line[2:] tag3 = "" elif line.startswith("#"): tag1 = line[1:] tag2 = "" tag3 = "" elif line: c = Composition(line) self.line_data[line_no] = \ {"formula_pretty": c.get_reduced_formula_and_factor()[0], "tag1": tag1, "tag2": tag2, "tag3": tag3} line_no += 1
def get_hhi(self, comp_or_form): """ Gets the reserve and production HHI for a compound. Args: comp_or_form (Composition or String): A Composition or String formula Returns: A tuple representing the (HHI_production, HHI_reserve) """ try: if not isinstance(comp_or_form, Composition): comp_or_form = Composition(comp_or_form) hhi_p = 0 hhi_r = 0 for e in comp_or_form.elements: percent = comp_or_form.get_wt_fraction(e) dp, dr = self._get_hhi_el(e) hhi_p += dp * percent hhi_r += dr * percent return hhi_p, hhi_r except: return (None, None)
def get_composition_from_string(comp_str): """validate and return composition from string `comp_str`.""" from pymatgen import Composition, Element comp = Composition(comp_str) for element in comp.elements: Element(element) formula = comp.get_integer_formula_and_factor()[0] comp = Composition(formula) return ''.join([ '{}{}'.format(key, int(value) if value > 1 else '') for key, value in comp.as_dict().items() ])
def snl_to_wf_phonon(snl, parameters=None): fws = [] connections = {} parameters = parameters if parameters else {} snl_priority = parameters.get('priority', 1) priority = snl_priority * 2 # once we start a job, keep going! f = Composition.from_formula(snl.structure.composition.reduced_formula).alphabetical_formula # add the SNL to the SNL DB and figure out duplicate group tasks = [AddSNLTask()] spec = {'task_type': 'Add to SNL database', 'snl': snl.to_dict, '_queueadapter': QA_DB, '_priority': snl_priority} if 'snlgroup_id' in parameters and isinstance(snl, MPStructureNL): spec['force_mpsnl'] = snl.to_dict spec['force_snlgroup_id'] = parameters['snlgroup_id'] del spec['snl'] fws.append(FireWork(tasks, spec, name=get_slug(f + '--' + spec['task_type']), fw_id=0)) connections[0] = [1] # run GGA structure optimization for force convergence spec = snl_to_wf._snl_to_spec(snl) spec = update_spec_force_convergence(spec) spec['run_tags'].append("origin") spec['_priority'] = priority spec['_queueadapter'] = QA_VASP spec['task_type'] = "Vasp force convergence" tasks = [VaspWriterTask(), get_custodian_task(spec)] fws.append(FireWork(tasks, spec, name=get_slug(f + '--' + spec['task_type']), fw_id=1)) # insert into DB - GGA structure optimization spec = {'task_type': 'VASP db insertion', '_priority': priority, '_allow_fizzled_parents': True, '_queueadapter': QA_DB} fws.append( FireWork([VaspToDBTask()], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=2)) connections[1] = [2] spec = {'task_type': 'Setup Deformed Struct Task', '_priority': priority, '_queueadapter': QA_CONTROL} fws.append( FireWork([SetupDeformedStructTask()], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=3)) connections[2] = [3] wf_meta = get_meta_from_structure(snl.structure) wf_meta['run_version'] = 'May 2013 (1)' if '_materialsproject' in snl.data and 'submission_id' in snl.data['_materialsproject']: wf_meta['submission_id'] = snl.data['_materialsproject']['submission_id'] return Workflow(fws, connections, name=Composition.from_formula( snl.structure.composition.reduced_formula).alphabetical_formula, metadata=wf_meta)
def test_get_atoms(self): if not aio.ase_loaded: raise SkipTest("ASE not present. Skipping...") p = Poscar.from_file(os.path.join(test_dir, 'POSCAR')) structure = p.structure atoms = aio.AseAtomsAdaptor.get_atoms(structure) ase_composition = Composition.from_formula(atoms.get_name()) self.assertEqual(ase_composition, structure.composition)
def test_init(self): filepath = os.path.join(test_dir, 'POSCAR') poscar = Poscar.from_file(filepath) comp = poscar.structure.composition self.assertEqual(comp, Composition.from_formula("Fe4P4O16")) #Vasp 4 type with symbols at the end. poscar_string = """Test1 1.0 3.840198 0.000000 0.000000 1.920099 3.325710 0.000000 0.000000 -2.217138 3.135509 1 1 direct 0.000000 0.000000 0.000000 Si 0.750000 0.500000 0.750000 F""" poscar = Poscar.from_string(poscar_string) self.assertEqual(poscar.structure.composition, Composition.from_formula("SiF")) #Vasp 4 tyle file with default names, i.e. no element symbol found. poscar_string = """Test2 1.0 3.840198 0.000000 0.000000 1.920099 3.325710 0.000000 0.000000 -2.217138 3.135509 1 1 direct 0.000000 0.000000 0.000000 0.750000 0.500000 0.750000""" poscar = Poscar.from_string(poscar_string) self.assertEqual(poscar.structure.composition, Composition.from_formula("HHe")) #Vasp 4 tyle file with default names, i.e. no element symbol found. poscar_string = """Test3 1.0 3.840198 0.000000 0.000000 1.920099 3.325710 0.000000 0.000000 -2.217138 3.135509 1 1 Selective dynamics direct 0.000000 0.000000 0.000000 T T T Si 0.750000 0.500000 0.750000 F F F O""" poscar = Poscar.from_string(poscar_string) self.assertEqual(poscar.selective_dynamics, [[True, True, True], [False, False, False]]) self.selective_poscar = poscar
def snl_to_wf(snl, do_bandstructure=True): # TODO: clean this up once we're out of testing mode # TODO: add WF metadata fws = [] connections = {} # add the SNL to the SNL DB and figure out duplicate group tasks = [AddSNLTask()] spec = {'task_type': 'Add to SNL database', 'snl': snl.to_dict} fws.append(FireWork(tasks, spec, name=spec['task_type'], fw_id=0)) connections[0] = 1 # run GGA structure optimization spec = _snl_to_spec(snl, enforce_gga=True) tasks = [VaspWriterTask(), _get_custodian_task(spec)] fws.append(FireWork(tasks, spec, name=spec['task_type'], fw_id=1)) # insert into DB - GGA structure optimization spec = {'task_type': 'VASP db insertion', '_priority': 2, '_allow_fizzled_parents': True} spec.update(_get_metadata(snl)) fws.append(FireWork([VaspToDBTask()], spec, name=spec['task_type'], fw_id=2)) connections[1] = 2 if do_bandstructure: spec = {'task_type': 'Controller: add Electronic Structure'} spec.update(_get_metadata(snl)) fws.append( FireWork([AddEStructureTask()], spec, name=spec['task_type'], fw_id=3)) connections[2] = 3 # determine if GGA+U FW is needed incar = MPVaspInputSet().get_incar(snl.structure).to_dict if 'LDAU' in incar and incar['LDAU']: spec = {'task_type': 'GGA+U optimize structure (2x)', '_dupefinder': DupeFinderVasp().to_dict()} spec.update(_get_metadata(snl)) fws.append(FireWork( [VaspCopyTask({'extension': '.relax2'}), SetupGGAUTask(), _get_custodian_task(spec)], spec, name=spec['task_type'], fw_id=10)) connections[2].append(10) spec = {'task_type': 'VASP db insertion', '_allow_fizzled_parents': True} spec.update(_get_metadata(snl)) fws.append( FireWork([VaspToDBTask()], spec, name=spec['task_type'], fw_id=11)) connections[10] = 11 if do_bandstructure: spec = {'task_type': 'Controller: add Electronic Structure'} spec.update(_get_metadata(snl)) fws.append(FireWork([AddEStructureTask()], spec, name=spec['task_type'], fw_id=12)) connections[11] = 12 return Workflow(fws, connections, name=Composition.from_formula(snl.structure.composition.reduced_formula).alphabetical_formula)
def test_calculate_energy(self): reactants = [Composition("MgO"), Composition("Al2O3")] products = [Composition("MgAl2O4")] energies = { Composition("MgO"): -0.1, Composition("Al2O3"): -0.2, Composition("MgAl2O4"): -0.5 } rxn = Reaction(reactants, products) self.assertEqual(str(rxn), "1.000 MgO + 1.000 Al2O3 -> 1.000 MgAl2O4") self.assertEqual(rxn.normalized_repr, "MgO + Al2O3 -> MgAl2O4") self.assertAlmostEquals(rxn.calculate_energy(energies), -0.2, 5)
def test_remove_spectator_species(self): rxn = BalancedReaction( { Composition("Li"): 4, Composition("O2"): 1, Composition('Na'): 1 }, { Composition("Li2O"): 2, Composition('Na'): 1 }) self.assertTrue(Composition('Na') not in rxn.all_comp)
def task_dict_to_wf(task_dict, launchpad): fw_id = launchpad.get_new_fw_id() l_id = launchpad.get_new_launch_id() spec = {'task_type': task_dict['task_type'], 'run_tags': task_dict['run_tags'], 'vaspinputset_name': None, 'vasp': None, 'mpsnl': task_dict['snl'], 'snlgroup_id': task_dict['snlgroup_id']} tasks = [DummyLegacyTask()] launch_dir = task_dict['dir_name_full'] stored_data = {'error_list': []} update_spec = {'prev_vasp_dir': task_dict['dir_name'], 'prev_task_type': spec['task_type'], 'mpsnl': spec['mpsnl'], 'snlgroup_id': spec['snlgroup_id'], 'run_tags': spec['run_tags']} fwaction = FWAction(stored_data=stored_data, update_spec=update_spec) if task_dict['completed_at']: complete_date = datetime.datetime.strptime(task_dict['completed_at'], "%Y-%m-%d %H:%M:%S") state_history = [{"created_on": complete_date, 'state': 'COMPLETED'}] else: state_history = [] launches = [Launch('COMPLETED', launch_dir, fworker=None, host=None, ip=None, action=fwaction, state_history=state_history, launch_id=l_id, fw_id=fw_id)] f = Composition.from_formula(task_dict['pretty_formula']).alphabetical_formula fw = FireWork(tasks, spec, name=get_slug(f + '--' + spec['task_type']), launches=launches, state='COMPLETED', created_on=None, fw_id=fw_id) wf_meta = get_meta_from_structure(Structure.from_dict(task_dict['snl'])) wf_meta['run_version'] = 'preproduction (0)' wf = Workflow.from_FireWork(fw, name=f, metadata=wf_meta) launchpad.add_wf(wf, reassign_all=False) launchpad._upsert_launch(launches[0]) print 'ADDED', fw_id # return fw_id return fw_id
def synth_score_from_formula(self, formula): """ Takes input in form of an unreduced crystal composition and returns the synthesizability score for the same. Args: formula (str): For example: 'Ba2Yb2Al4Si2N10O4' Returns: synth_scores (list): Synthesizability scores (between 0 and 1) of given sample. """ # Updating the criteria updated_input = {"full_formula": formula} # Extracting the composition comp = Composition(formula) # Extracting the MP-IDs mp_id = self._get_mp_id(updated_input) # If Input given is invalid if len(mp_id) == 0: return "No such compound exists in Materials Project Database" # Checking if it already exists in pre-trained model fblock, mp_id, synth_score, df_input = self._check_if_already_exists( comp, updated_input) # If found in pre-trained models, report synth_scores if df_input.shape[0] == 0: if len(synth_score) != 0: logging.info("The synthesizability scores are %s", synth_score) return synth_score # Else, train the model and report scores else: df_extracted = self._extract_features(df_input) input_ids, df = self._append_data(df_extracted, fblock) score = self._do_pulearner(input_ids, df) synth_score.append(score) logging.info("The synthesizability scores are %s", synth_score) return synth_score
def testName(self): entry_Li = ComputedEntry("Li", -1.90753119) with open(os.path.join(test_dir, "LiTiO2_batt.json"), "r") as f: entries_LTO = json.load(f, cls=MontyDecoder) ie_LTO = InsertionElectrode.from_entries(entries_LTO, entry_Li) with open(os.path.join(test_dir, "FeF3_batt.json"), "r") as fid: entries = json.load(fid, cls=MontyDecoder) ce_FF = ConversionElectrode.from_composition_and_entries( Composition("FeF3"), entries ) plotter = VoltageProfilePlotter(xaxis="frac_x") plotter.add_electrode(ie_LTO, "LTO insertion") plotter.add_electrode(ce_FF, "FeF3 conversion") self.assertIsNotNone(plotter.get_plot_data(ie_LTO)) self.assertIsNotNone(plotter.get_plot_data(ce_FF))
def get_polymorphs(f_str, pda): """get_polymorphs Gets all the polymorphs with a chemical composition within the cutoff. :param f_str: Chemical composition we're interested in. :param pda: A PDAnalyzer for the appropriate phase diagram. :return: A list of entries within the cutoff. """ comp = Composition(f_str).reduced_composition relevant_polymorphs = [] for e in pda._pd.all_entries: if e.composition.reduced_composition == comp: ehull = pda.get_decomp_and_e_above_hull(e)[1] anion = [el for el in e.composition.as_dict() if el in anions][0] if ehull < ehull_cut[anion]: form_e = pda._pd.get_form_energy_per_atom(e) e.data["formation_energy_per_atom"] = form_e relevant_polymorphs.append(e) return relevant_polymorphs
def scrape_comp(row): # reformulate the doped site by electronegativity order of elements for a better web scraping,and remove '0's & parantheses. e.g. Pb(Ti0.50Zr0.50)O3 --> PbZr0.5Ti0.5O3 site_list = re.split( r'[()]', row.StructuredFormula ) # get what's inside parantheses and others separately doped_site = max( site_list, key=len) # get doped site re.sub(r"(?<=\d)0+", "", d) site_rearranged = '(' + re.sub( r"(?<=\d)0+", "", Composition(doped_site).formula.replace(' ', '') ) + ')' # arrange elements in electronegative order, remove '0' and club with () site_list[site_list.index( doped_site)] = site_rearranged # replace with processed site compound = str(''.join(site_list)) # print (compound) result = self.search(compound) return compound, result
def get_meta_from_structure(structure): if isinstance(structure, TransformedStructure): structure = structure.final_structure comp = structure.composition elsyms = sorted(set([e.symbol for e in comp.elements])) meta = {'nsites': structure.num_sites, 'elements': elsyms, 'nelements': len(elsyms), 'formula': comp.formula, 'formula_pretty': comp.reduced_formula, 'formula_reduced_abc': Composition(comp.reduced_formula) .alphabetical_formula, 'formula_anonymous': comp.anonymized_formula, 'chemsys': '-'.join(elsyms), 'is_ordered': structure.is_ordered, 'is_valid': structure.is_valid()} return meta
def __init__(self, mpid, cmpd_dict): """Initializing the feature finder. Sets up a FeatureFinder based on a dict from the hydrate finder. Args: mpid (str): The MP ID of the dry compound in question. cmpd_dict (dict): A dictionary output from the hydrate finder. """ comp = Composition(cmpd_dict['formula']).as_dict() self.comp = comp self.num_atoms = sum([comp[ele] for ele in comp]) self.mpid = mpid with MPRester() as mpr: struct = mpr.get_structure_by_material_id(self.mpid) self.struct = struct
def convert_mpworks_to_atomate(mpworks_doc, update_mpworks=True): """ Function to convert an mpworks document into an atomate document, uses schema above and a few custom cases Args: mpworks_doc (dict): mpworks task document update_mpworks (bool): flag to indicate that mpworks schema should be updated to final MPWorks version """ if update_mpworks: update_mpworks_schema(mpworks_doc) atomate_doc = {} for key_mpworks, key_atomate in settings['task_conversion_keys'].items(): val = get(mpworks_doc, key_mpworks) set_(atomate_doc, key_atomate, val) # Task type atomate_doc["task_label"] = settings['task_label_conversions'].get( mpworks_doc["task_type"]) # calculations atomate_doc["calcs_reversed"] = mpworks_doc["calculations"][::-1] # anonymous formula comp = Composition(atomate_doc['composition_reduced']) atomate_doc["formula_anonymous"] = comp.anonymized_formula # deformation matrix and original_task_id if "deformation_matrix" in mpworks_doc: # Transpose this b/c of old bug, should verify in doc processing defo = mpworks_doc["deformation_matrix"] if isinstance(defo, str): defo = convert_string_deformation_to_list(defo) defo = np.transpose(defo).tolist() set_(atomate_doc, "transmuter.transformations", ["DeformStructureTransformation"]) set_(atomate_doc, "transmuter.transformation_params", [{ "deformation": defo }]) return atomate_doc
def test_hse_structure_opt(default_dict): default_dict.update({ "xc": Xc.hse, "composition": Composition("UO2"), "symbol_list": ["U", "O"], "potcar": Potcar(["U", "O"]), "exchange_ratio": 0.5, "set_hubbard_u": True }) generator = IncarSettingsGenerator(**default_dict) # for k, v in generator.incar_settings.items(): # print(f'\"{k}\": {v}, ') expected = { "ALGO": "Damped", "PREC": "Normal", "LREAL": False, "EDIFF": 1e-07, "ENCUT": 520.0, "LASPH": True, "NELM": 100, "ISIF": 3, "IBRION": 2, "EDIFFG": -0.005, "NSW": 50, "ISMEAR": 0, "SIGMA": 0.1, "LWAVE": True, "LCHARG": False, "LORBIT": 10, "LHFCALC": True, "PRECFOCK": "Fast", "TIME": 0.4, "AEXX": 0.5, "HFSCREEN": 0.208, "LDAU": True, "LDAUTYPE": 2, "LMAXMIX": 6, "LDAUPRINT": 1, "LDAUU": [5, 0], "LDAUL": [3, -1], "KPAR": 1, } assert generator.incar_settings == expected
def setUp(self): self.formulas = ["LiCoO2", "FeF3", "MnO2"] self.conversion_eletrodes = {} for f in self.formulas: with open( os.path.join(PymatgenTest.TEST_FILES_DIR, f + "_batt.json"), "r") as fid: entries = json.load(fid, cls=MontyDecoder) if f in ["LiCoO2", "FeF3"]: working_ion = "Li" elif f in ["MnO2"]: working_ion = "Mg" c = ConversionElectrode.from_composition_and_entries( Composition(f), entries, working_ion_symbol=working_ion) self.conversion_eletrodes[f] = { "working_ion": working_ion, "CE": c } self.expected_properties = { "LiCoO2": { "average_voltage": 2.26940307125, "capacity_grav": 903.19752911225669, "capacity_vol": 2903.35804724, "specific_energy": 2049.7192465127678, "energy_density": 6588.8896693479574, }, "FeF3": { "average_voltage": 3.06179925889, "capacity_grav": 601.54508701578118, "capacity_vol": 2132.2069115142394, "specific_energy": 1841.8103016131706, "energy_density": 6528.38954147, }, "MnO2": { "average_voltage": 1.7127027687901726, "capacity_grav": 790.9142070034802, "capacity_vol": 3543.202003526853, "specific_energy": 1354.6009522103434, "energy_density": 6068.451881823329, }, }
def screen_formulas(candidates: Iterable[str]) -> Iterable[str]: """[Filters unique chemical compositions] Arguments: candidates {Iterable[str]} -- [List of chemical formula candidates] Returns: Iterable[str] -- [Filtered list of candidates] """ try: formulas = [] for formula in candidates: comp = Composition(formula) if comp.reduced_formula not in formulas: formulas.append(comp.reduced_formula) return formulas except Exception as exc: print('-- Could not filter candidates --') raise (exc)
def get_magpie_descriptor(comp, descriptor_name): """ Get descriptor data for elements in a compound from the Magpie data repository. Args: comp: (str) compound composition, eg: "NaCl" descriptor_name: name of Magpie descriptor needed. Find the entire list at https://bitbucket.org/wolverton/magpie/src/6ecf8d3b79e03e06ef55c141c350a08fbc8da849/Lookup%20Data/?at=master Returns: (list) of descriptor values for each element in the composition """ magpiedata_lst = [] magpiedata = collections.namedtuple( 'magpiedata', 'element propname propvalue propunit amt') available_props = [] for datafile in os.listdir('data/magpie_elementdata'): available_props.append(datafile.replace('.table', '')) if descriptor_name not in available_props: raise ValueError( "This descriptor is not available from the Magpie repository. Choose from {}" .format(available_props)) el_amt = Composition(comp).get_el_amt_dict() unit = None with open('data/magpie_elementdata/README.txt', 'r') as readme_file: readme_file_line = readme_file.readlines() for lineno, line in enumerate(readme_file_line, 1): if descriptor_name + '.table' in line: if 'Units: ' in readme_file_line[lineno + 1]: unit = readme_file_line[lineno + 1].split(':')[1].strip('\n') with open('data/magpie_elementdata/' + descriptor_name + '.table', 'r') as descp_file: lines = descp_file.readlines() for el in el_amt: atomic_no = Element(el).Z magpiedata_lst.append( magpiedata(element=el, propname=descriptor_name, propvalue=float(lines[atomic_no - 1]), propunit=unit, amt=el_amt[el])) return magpiedata_lst
def featurize(self, compositions: Iterable[str], log_every_n: int = 1000) -> np.ndarray: """Calculate features for crystal compositions. Parameters ---------- compositions: Iterable[str] Iterable sequence of composition strings, e.g. "MoS2". log_every_n: int, default 1000 Logging messages reported every `log_every_n` samples. Returns ------- features: np.ndarray A numpy array containing a featurized representation of `compositions`. """ # Convert iterables to list compositions = list(compositions) try: from pymatgen import Composition except ModuleNotFoundError: raise ValueError("This class requires pymatgen to be installed.") features = [] for idx, composition in enumerate(compositions): if idx % log_every_n == 0: logger.info("Featurizing datapoint %i" % idx) try: c = Composition(composition) features.append(self._featurize(c)) except: logger.warning( "Failed to featurize datapoint %i. Appending empty array" % idx) features.append(np.array([])) features = np.asarray(features) return features
def test_column_attr(self): """ Test that the autofeaturizer object correctly takes in composition_col, structure_col, bandstruct_col, and dos_col, and checks that fit_and_transform() works correctly with the attributes. """ # Modification of test_featurize_composition with AutoFeaturizer parameter target = "K_VRH" df = copy.copy(self.test_df[['composition', target]].iloc[:self.limit]) af = AutoFeaturizer(composition_col="composition", preset="best", ignore_errors=False) df = af.fit_transform(df, target) self.assertEqual(df["LUMO_element"].iloc[0], "Nb") self.assertTrue("composition" not in df.columns) df = self.test_df[["composition", target]].iloc[:self.limit] df["composition"] = [Composition(s) for s in df["composition"]] af = AutoFeaturizer(composition_col="composition", preset="best") df = af.fit_transform(df, target) self.assertEqual(df["LUMO_element"].iloc[0], "Nb") self.assertTrue("composition" not in df.columns) # Modification of test_featurize_structure with AutoFeaturizer parameter target = "K_VRH" df = copy.copy(self.test_df[['structure', target]].iloc[:self.limit]) af = AutoFeaturizer(structure_col="structure", preset="fast") df = af.fit_transform(df, target) self.assertTrue("vpa" in df.columns) self.assertTrue("HOMO_character" in df.columns) self.assertTrue("composition" not in df.columns) self.assertTrue("structure" not in df.columns) df = copy.copy(self.test_df[['structure', target]].iloc[:self.limit]) df["structure"] = [s.as_dict() for s in df["structure"]] af = AutoFeaturizer(structure_col="structure", preset="fast") df = af.fit_transform(df, target) self.assertTrue("vpa" in df.columns) self.assertTrue("HOMO_character" in df.columns) self.assertTrue("composition" not in df.columns) self.assertTrue("structure" not in df.columns)
def test_from_string(self): rxn = BalancedReaction({ Composition("Li"): 4, Composition("O2"): 1 }, {Composition("Li2O"): 2}) self.assertEqual(rxn, BalancedReaction.from_string("4 Li + O2 -> 2Li2O")) rxn = BalancedReaction({Composition("Li(NiO2)3"): 1}, { Composition("O2"): 0.5, Composition("Li(NiO2)2"): 1, Composition("NiO"): 1 }) self.assertEqual( rxn, BalancedReaction.from_string( "1.000 Li(NiO2)3 -> 0.500 O2 + 1.000 Li(NiO2)2 + 1.000 NiO"))
def get_entries(self, chemsys): """ Get all entries in a chemsys from materials Args: chemsys(str): a chemical system represented by string elements seperated by a dash (-) Returns: set(ComputedEntry): a set of entries for this system """ self.logger.info("Getting entries for: {}".format(chemsys)) new_q = dict(self.query) new_q["chemsys"] = {"$in": list(chemsys_permutations(chemsys))} fields = [ "structure", self.materials.key, "thermo.energy_per_atom", "composition", "calc_settings" ] data = list(self.materials.query(fields, new_q)) all_entries = [] for d in data: comp = Composition(d["composition"]) entry = ComputedEntry( comp, d["thermo"]["energy_per_atom"] * comp.num_atoms, 0.0, parameters=d["calc_settings"], entry_id=d[self.materials.key], data={ "oxide_type": oxide_type(Structure.from_dict(d["structure"])) }) all_entries.append(entry) self.logger.info("Total entries in {} : {}".format( chemsys, len(all_entries))) return all_entries
def get_chemsys(formula_or_structure, seperator='-'): """ Gets a sorted, character-delimited set of elements, e.g. Fe-Ni-O or O-Ti Args: formula_or_structure (str, Structure): formula or structure for which to get chemical system separator (str): separator for the chemsys elements Returns: (str): separated """ if isinstance(formula_or_structure, Structure): formula = formula_or_structure.composition.reduced_formula else: formula = formula_or_structure elements = [str(el) for el in Composition(formula)] return seperator.join(sorted(elements))
def get_atomic_lists_and_numbers(compositions): # get atom number atom_lists = np.empty(118, dtype=object) atoms_duplicated = [] atomic_numbers_duplicated = [] for line in compositions: if line == 'nan': line = 'NaN' atom_list = Composition(line[0]) #atom_list = Composition(line) for element in atom_list: atomic_numbers_duplicated.append(element.Z - 1) atom_lists[element.Z - 1] = element.symbol # reduce duplicate atomic_numbers = np.array(list(set(atomic_numbers_duplicated))) atomic_numbers = np.sort(atomic_numbers, axis=0) return atom_lists, atomic_numbers
def test_prediction(self): sp = SubstitutionPredictor(threshold = 8e-3) result = sp.list_prediction(['Na+', 'Cl-'], to_this_composition = True)[5] cprob = sp.p.cond_prob_list(result['substitutions'].keys(), result['substitutions'].values()) self.assertAlmostEqual(result['probability'], cprob) self.assertEqual(set(result['substitutions'].values()), set(['Na+', 'Cl-'])) result = sp.list_prediction(['Na+', 'Cl-'], to_this_composition = False)[5] cprob = sp.p.cond_prob_list(result['substitutions'].keys(), result['substitutions'].values()) self.assertAlmostEqual(result['probability'], cprob) self.assertNotEqual(set(result['substitutions'].values()), set(['Na+', 'Cl-'])) c = Composition({'Ag2+' : 1, 'Cl-' : 2}) result = sp.composition_prediction(c, to_this_composition = True)[2] self.assertEqual(set(result['substitutions'].values()), set(c.elements)) result = sp.composition_prediction(c, to_this_composition = False)[2] self.assertEqual(set(result['substitutions'].keys()), set(c.elements))
def test_featurize_composition(self): """ Test automatic featurization while only considering formula/composition. """ target = "K_VRH" # When compositions are strings df = copy.copy(self.test_df[["composition", target]].iloc[: self.limit]) af = AutoFeaturizer(preset="express") df = af.fit_transform(df, target) self.assertAlmostEqual(df["MagpieData minimum Number"].iloc[2], 14.0) self.assertTrue("composition" not in df.columns) # When compositions are Composition objects df = self.test_df[["composition", target]].iloc[: self.limit] df["composition"] = [Composition(s) for s in df["composition"]] af = AutoFeaturizer(preset="express") df = af.fit_transform(df, target) self.assertAlmostEqual(df["MagpieData minimum Number"].iloc[2], 14.0) self.assertTrue("composition" not in df.columns)
def test_energy_window(mocker): mock_bs = mocker.MagicMock() mock_bs.efermi = 0 mock_bs.is_metal.return_value = True stub_vasprun = mocker.MagicMock() stub_vasprun.final_structure.composition = Composition("MgO2") stub_vasprun.get_band_structure.return_value = mock_bs energy = { "1": [ np.array([[-0.2, -0.1, -0.3, -0.1], [-0.2, -0.1, -0.3, 0.1], [1.2, 1.3, 1.1, 1.2]]) ] } distances = [[0.0, 1.0]] labels = ["A", "GAMMA"] label_distances = [0.0, 1.0] plot_data = { "energy": energy, "distances": distances, "vbm": None, "cbm": None } mock_bsp = mocker.patch("vise.analyzer.vasp.plot_band.BSPlotter", auto_spec=True) mock_bsp.return_value.bs_plot_data.return_value = plot_data mock_bsp.return_value.get_ticks_old.return_value = { "label": labels, "distance": distances[0] } plot_info = BandPlotInfoFromVasp(stub_vasprun, "KPOINTS", energy_window=[0.0, 1.0 ]).make_band_plot_info() assert (plot_info.band_info_set[0].band_energies == [[[[ -0.2, -0.1, -0.3, 0.1 ]]]])
def compute_grav_cap(comp, wi, remove=True): """compute_grav_cap Computes the gravimetric capacity of a composition. :param comp: Composition dictionary object. :param wi: String which is the symbol of the working ion. :param remove: Are we removing? If not, we're inserting. :return: Gravimetric capacity in mAh/g. """ c = comp.as_dict() weight = comp.weight wi_charge = mobile_ion_charges[wi] if remove: num_wi = max_removal(c) else: num_wi = max_insertion(c, wi) wi_comp = Composition(wi) weight += wi_comp.weight * num_wi print num_wi, wi_charge cap = num_wi * wi_charge * ELECTRON_TO_AMPERE_HOURS grav_cap = cap / (weight / 1000) return grav_cap
def get_meta_from_structure(structure): # TODO: this won't work for molecules meta = {} meta['nsites'] = len(structure.sites) meta['elements'] = list(set([el.symbol for el in structure.composition.elements])) meta['nelements'] = len(meta['elements']) meta['formula'] = structure.composition.formula meta['formula_red'] = structure.composition.reduced_formula meta['formula_abc_red'] = Composition.from_formula(structure.composition.reduced_formula).alphabetical_formula meta['composition_dict'] = structure.composition.to_dict meta['anonymized_formula'] = structure.composition.anonymized_formula meta['chemsystem'] = '-'.join(sorted(list(set([e.symbol for e in structure.composition.elements])))) # the complex logic set/list is to prevent duplicates if there are multiple oxidation states meta['is_ordered'] = structure.is_ordered #promixity warning: meta['proximity_warning'] = False for (s1, s2) in itertools.combinations(structure._sites, 2): if s1.distance(s2) < Structure.DISTANCE_TOLERANCE: meta['proximity_warning'] = True return meta
def test_to_from_dict(self): rct = { Composition('K2SO4'): 3, Composition('Na2S'): 1, Composition('Li'): 24 } prod = { Composition('KNaS'): 2, Composition('K2S'): 2, Composition('Li2O'): 12 } rxn = BalancedReaction(rct, prod) d = rxn.as_dict() new_rxn = BalancedReaction.from_dict(d) for comp in new_rxn.all_comp: self.assertEqual(new_rxn.get_coeff(comp), rxn.get_coeff(comp))
def create_df(): newcoll = db['abc3'] newcoll.drop() x = 0 for doc in db['pauling_file_min_tags'].find().batch_size(75): x += 1 if x % 1000 == 0: print x if doc['metadata']['_structure']['anonymized_formula'] == 'ABC3' and doc['is_ht'] in [True,False] \ and 'TiO3' in doc['metadata']['_structure']['reduced_cell_formula']: newcoll.insert(doc) cursor = newcoll.find() df = pd.DataFrame(list(cursor)) for i, row in df.iterrows(): df.set_value(i, 'reduced_cell_formula', row['metadata']['_structure']['reduced_cell_formula']) try: df.set_value( i, 'space_group', int(row['metadata']['_Springer']['geninfo']['Space Group'])) except: df.set_value(i, 'space_group', None) try: df.set_value( i, 'density', float(row['metadata']['_Springer']['geninfo'] ['Density'].split()[2])) except IndexError as e: df.set_value(i, 'density', None) structure = Structure.from_dict(row['structure']) num_density = (structure.num_sites / structure.volume) no_of_atoms = Composition(structure.composition).num_atoms num_vol = (structure.volume / no_of_atoms) df.set_value(i, 'number_density', num_density) df.set_value(i, 'number_volume', num_vol) if row['metadata']['_structure']['is_ordered']: df.set_value(i, 'is_ordered', 1) else: df.set_value(i, 'is_ordered', 0) df.to_pickle('abc3.pkl')
def test_vasp_band_plotter(is_metal, expected_band_edge, mocker): mock_bs = mocker.MagicMock() mock_bs.efermi = 10 mock_bs.is_metal.return_value = is_metal stub_vasprun = mocker.MagicMock() stub_vasprun.final_structure.composition = Composition("MgO2") stub_vasprun.get_band_structure.return_value = mock_bs energy = {"1": [np.array([[0.1], [0.2], [0.3]])]} distances = [np.array([0.0, 0.1, 0.2])] labels = ["A", "$A_0$", "GAMMA"] label_distances = [0.0, 0.1, 0.2] plot_data = { "energy": energy, "distances": distances, "vbm": [[0, -100]], "cbm": [[1, 100], [2, 100]] } mock_bsp = mocker.patch("vise.analyzer.vasp.plot_band.BSPlotter", auto_spec=True) mock_bsp.return_value.bs_plot_data.return_value = plot_data mock_bsp.return_value.get_ticks_old.return_value = { "label": labels, "distance": [0.0, 0.1, 0.2] } plot_info = BandPlotInfoFromVasp(stub_vasprun, "KPOINTS").make_band_plot_info() expected_x_ticks = XTicks(labels=["A", "${\\rm A}_0$", "Γ"], distances=label_distances) assert plot_info.band_info_set[0].band_energies == [[[[0.1], [0.2], [0.3]]]] assert plot_info.band_info_set[0].band_edge == expected_band_edge assert plot_info.distances_by_branch == [[0.0, 0.1, 0.2]] assert plot_info.x_ticks == expected_x_ticks assert plot_info.title == "MgO$_{2}$"
def get_random_structure(): print("input the formula of structure like this: ") print("(Fe3O4)4") print("or input the formula and spacegroup like this ") print("Si4O8 20") wait_sep() in_str="" while in_str=="": in_str=input().strip().split() if len(in_str)==1: spgRange=[1,230] tag=False elif len(in_str)==2: spgRange=[int(in_str[1]),int(in_str[1])+1] tag=True else: print("unknow format") os._exit() comp=Composition(in_str[0]) elem=[el.symbol for el in comp] num_atom=[int(comp[el]) for el in elem] i=124456 scale=1.5 while True: random.seed(i) spg=np.random.randint(spgRange[0],spgRange[1]) print("try space group %s"%(spg)) i+=1 rc=random_crystal(spg,elem, num_atom, scale) pmg_structure=rc.prim_struct if pmg_structure is not None: print("Generate random structure with spg: %d natom: %d"%(spg, len(pmg_structure))) print(pmg_structure) pmg_structure.to('poscar','random_spg_'+str(spg)+'.vasp') return if tag: print("Failed to generate structure with spg: %d"%(spg)) return
def get_meta_from_structure(structure): """ Used by `structure_to_mock_job`, to "fill out" a job document. :param structure: pymatgen structure object :return: (dict) structure metadata """ comp = structure.composition elsyms = sorted(set([e.symbol for e in comp.elements])) meta = { 'nsites': len(structure), 'elements': elsyms, 'nelements': len(elsyms), 'formula': comp.formula, 'reduced_cell_formula': comp.reduced_formula, 'reduced_cell_formula_abc': Composition(comp.reduced_formula).alphabetical_formula, 'anonymized_formula': comp.anonymized_formula, 'chemsystem': '-'.join(elsyms), 'is_ordered': structure.is_ordered, 'is_valid': structure.is_valid(tol=0.50) } return meta
def snl_to_wf_ggau(snl): # TODO: add WF meta fws = [] connections = {} # add the root FW (GGA+U) spec = _snl_to_spec(snl, enforce_gga=False) tasks = [VaspWriterTask(), _get_custodian_task(spec)] fws.append(FireWork(tasks, spec, fw_id=1)) # add GGA insertion to DB spec = {'task_type': 'VASP db insertion', '_priority': 2, '_category': 'VASP'} spec.update(_get_metadata(snl)) fws.append(FireWork([VaspToDBTask()], spec, fw_id=2)) connections[1] = 2 mpvis = MPVaspInputSet() spec['vaspinputset_name'] = mpvis.__class__.__name__ return Workflow(fws, connections, name=Composition.from_formula(snl.structure.composition.reduced_formula).alphabetical_formula)
def test_init(self): filepath = os.path.join(test_dir, 'input/23221-ZDsSsJoEW14.res') res = Res.from_file(filepath) comp = res.structure.composition self.assertEqual(comp, Composition.from_formula("C194H60")) #print res res_string = """TITL CELL 1.0 1.0 1.0 1.0 90.0 90.0 90.0 LATT -1 SFAC Si F Si 1 0.000000 0.000000 0.000000 1.0 F 2 0.750000 0.500000 0.750000 1.0""" res = Res.from_string(res_string) self.assertEqual(res.structure.composition, Composition("SiF")) self.assertEquals(res.structure.num_sites, 2) #print res struct = Structure(Lattice.orthorhombic(2.5, 3.5, 7.0), ['Na', 'Cl'], [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]]) res = Res(struct) res_string = str(res) lines = res_string.splitlines() self.assertEqual(lines[1], "CELL 1.0 2.5 3.5 7.0 90.0 90.0 90.0")
def test_to_from_dict(self): d = self.vinput.to_dict vinput = VaspInput.from_dict(d) comp = vinput["POSCAR"].structure.composition self.assertEqual(comp, Composition.from_formula("Fe4P4O16"))
def snl_to_wf(snl, parameters=None): fws = [] connections = {} parameters = parameters if parameters else {} snl_priority = parameters.get('priority', 1) priority = snl_priority * 2 # once we start a job, keep going! f = Composition.from_formula(snl.structure.composition.reduced_formula).alphabetical_formula # add the SNL to the SNL DB and figure out duplicate group tasks = [AddSNLTask()] spec = {'task_type': 'Add to SNL database', 'snl': snl.to_dict, '_queueadapter': QA_DB, '_priority': snl_priority} if 'snlgroup_id' in parameters and isinstance(snl, MPStructureNL): spec['force_mpsnl'] = snl.to_dict spec['force_snlgroup_id'] = parameters['snlgroup_id'] del spec['snl'] fws.append(FireWork(tasks, spec, name=get_slug(f + '--' + spec['task_type']), fw_id=0)) connections[0] = [1] # run GGA structure optimization spec = _snl_to_spec(snl, enforce_gga=True) spec['_priority'] = priority spec['_queueadapter'] = QA_VASP tasks = [VaspWriterTask(), get_custodian_task(spec)] fws.append(FireWork(tasks, spec, name=get_slug(f + '--' + spec['task_type']), fw_id=1)) # insert into DB - GGA structure optimization spec = {'task_type': 'VASP db insertion', '_priority': priority, '_allow_fizzled_parents': True, '_queueadapter': QA_DB} fws.append( FireWork([VaspToDBTask()], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=2)) connections[1] = [2] if not parameters.get('skip_bandstructure', False): spec = {'task_type': 'Controller: add Electronic Structure v2', '_priority': priority, '_queueadapter': QA_CONTROL} fws.append( FireWork([AddEStructureTask()], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=3)) connections[2] = [3] # determine if GGA+U FW is needed incar = MPVaspInputSet().get_incar(snl.structure).to_dict if 'LDAU' in incar and incar['LDAU']: spec = _snl_to_spec(snl, enforce_gga=False) del spec['vasp'] # we are stealing all VASP params and such from previous run spec['_priority'] = priority spec['_queueadapter'] = QA_VASP fws.append(FireWork( [VaspCopyTask(), SetupGGAUTask(), get_custodian_task(spec)], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=10)) connections[2].append(10) spec = {'task_type': 'VASP db insertion', '_queueadapter': QA_DB, '_allow_fizzled_parents': True, '_priority': priority} fws.append( FireWork([VaspToDBTask()], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=11)) connections[10] = [11] if not parameters.get('skip_bandstructure', False): spec = {'task_type': 'Controller: add Electronic Structure v2', '_priority': priority, '_queueadapter': QA_CONTROL} fws.append( FireWork([AddEStructureTask()], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=12)) connections[11] = [12] wf_meta = get_meta_from_structure(snl.structure) wf_meta['run_version'] = 'May 2013 (1)' if '_materialsproject' in snl.data and 'submission_id' in snl.data['_materialsproject']: wf_meta['submission_id'] = snl.data['_materialsproject']['submission_id'] return Workflow(fws, connections, name=Composition.from_formula( snl.structure.composition.reduced_formula).alphabetical_formula, metadata=wf_meta)
if x % 1000 == 0: print x if (doc['metadata']['_Springer']['geninfo']['Refined Formula']).replace(u'\u2013', '-') != '-': form = doc['metadata']['_Springer']['geninfo']['Refined Formula'] else: form = doc['metadata']['_Springer']['geninfo']['Alphabetic Formula'] form = form.replace('[', '') form = form.replace(']', '') try: redform = Composition(form).reduced_formula except: print 'Could not parse composition for key:{} with composition:{}'.format(doc['key'], form) y += 1 continue alphaform_comp = Composition(redform).alphabetical_formula alphaform_frac = Composition(alphaform_comp).fractional_composition structure_comp = doc['metadata']['_structure']['reduced_cell_formula_abc'] structure_frac = Composition(structure_comp).fractional_composition if alphaform_frac != structure_frac and not alphaform_frac.almost_equals(structure_frac, 0.15): for document in db['pauling_file'].find({'key': doc['key']}): try: struct_lst = CifParser.from_string(document['cif_string']).get_structures() except: pass if len(struct_lst) > 1: matched = False for struct in struct_lst[1:]: another_frac = Composition(struct.composition).fractional_composition if alphaform_frac == another_frac or alphaform_frac.almost_equals(another_frac, 0.15): matched = True # '''
def run_task(self, fw_spec): print 'sleeping 10s for Mongo' time.sleep(10) print 'done sleeping' print 'the gap is {}, the cutoff is {}'.format(fw_spec['analysis']['bandgap'], self.gap_cutoff) if fw_spec['analysis']['bandgap'] >= self.gap_cutoff: print 'Adding more runs...' type_name = 'GGA+U' if 'GGA+U' in fw_spec['prev_task_type'] else 'GGA' snl = StructureNL.from_dict(fw_spec['mpsnl']) f = Composition.from_formula(snl.structure.composition.reduced_formula).alphabetical_formula fws = [] connections = {} priority = fw_spec['_priority'] # run GGA static spec = fw_spec # pass all the items from the current spec to the new # one spec.update({'task_type': '{} static'.format(type_name), '_queueadapter': QA_VASP, '_dupefinder': DupeFinderVasp().to_dict(), '_priority': priority}) fws.append( FireWork( [VaspCopyTask({'use_CONTCAR': True}), SetupStaticRunTask(), get_custodian_task(spec)], spec, name=get_slug(f+'--'+spec['task_type']), fw_id=-10)) # insert into DB - GGA static spec = {'task_type': 'VASP db insertion', '_queueadapter': QA_DB, '_allow_fizzled_parents': True, '_priority': priority} fws.append( FireWork([VaspToDBTask()], spec, name=get_slug(f+'--'+spec['task_type']), fw_id=-9)) connections[-10] = -9 # run GGA Uniform spec = {'task_type': '{} Uniform'.format(type_name), '_queueadapter': QA_VASP, '_dupefinder': DupeFinderVasp().to_dict(), '_priority': priority} fws.append(FireWork( [VaspCopyTask({'use_CONTCAR': False}), SetupNonSCFTask({'mode': 'uniform'}), get_custodian_task(spec)], spec, name=get_slug(f+'--'+spec['task_type']), fw_id=-8)) connections[-9] = -8 # insert into DB - GGA Uniform spec = {'task_type': 'VASP db insertion', '_queueadapter': QA_DB, '_allow_fizzled_parents': True, '_priority': priority} fws.append( FireWork([VaspToDBTask({'parse_uniform': True})], spec, name=get_slug(f+'--'+spec['task_type']), fw_id=-7)) connections[-8] = -7 # run GGA Band structure spec = {'task_type': '{} band structure'.format(type_name), '_queueadapter': QA_VASP, '_dupefinder': DupeFinderVasp().to_dict(), '_priority': priority} fws.append(FireWork([VaspCopyTask({'use_CONTCAR': False}), SetupNonSCFTask({'mode': 'line'}), get_custodian_task(spec)], spec, name=get_slug(f+'--'+spec['task_type']), fw_id=-6)) connections[-7] = -6 # insert into DB - GGA Band structure spec = {'task_type': 'VASP db insertion', '_queueadapter': QA_DB, '_allow_fizzled_parents': True, '_priority': priority} fws.append(FireWork([VaspToDBTask({})], spec, name=get_slug(f+'--'+spec['task_type']), fw_id=-5)) connections[-6] = -5 wf = Workflow(fws, connections) print 'Done adding more runs...' return FWAction(additions=wf) return FWAction()
vector = zeros((MAX_Z)) for element in composition: fraction = composition.get_atomic_fraction(element) vector[element.Z - 1] = fraction return(vector) # Extract materials and band gaps into lists, and construct naive feature set materials = [] bandgaps = [] naiveFeatures = [] MAX_Z = 100 # maximum length of vector to hold naive feature set for line in trainFile: split = str.split(line, ',') material = Composition(split[0]) materials.append(material) #store chemical formulas naiveFeatures.append(naiveVectorize(material)) #create features from chemical formula bandgaps.append(float(split[1])) #store numerical values of band gaps ############################################################################################################## # Establish baseline accuracy by "guessing the average" of the band gap set # A good model should never do worse. baselineError = mean(abs(mean(bandgaps) - bandgaps)) print("The MAE of always guessing the average band gap is: " + str(round(baselineError, 3)) + " eV") ############################################################################################################## #alpha is a tuning parameter affecting how regression deals with collinear inputs linear = linear_model.Ridge(alpha = 0.5)
def run_task(self, fw_spec): if '_fizzled_parents' in fw_spec and not 'prev_vasp_dir' in fw_spec: prev_dir = get_loc(fw_spec['_fizzled_parents'][0]['launches'][0]['launch_dir']) update_spec = {} # add this later when creating new FW fizzled_parent = True parse_dos = False else: prev_dir = get_loc(fw_spec['prev_vasp_dir']) update_spec = {'prev_vasp_dir': prev_dir, 'prev_task_type': fw_spec['prev_task_type'], 'run_tags': fw_spec['run_tags'], 'parameters': fw_spec.get('parameters')} fizzled_parent = False parse_dos = 'Uniform' in fw_spec['prev_task_type'] if 'run_tags' in fw_spec: self.additional_fields['run_tags'] = fw_spec['run_tags'] else: self.additional_fields['run_tags'] = fw_spec['_fizzled_parents'][0]['spec']['run_tags'] if MOVE_TO_GARDEN_DEV: prev_dir = move_to_garden(prev_dir, prod=False) elif MOVE_TO_GARDEN_PROD: prev_dir = move_to_garden(prev_dir, prod=True) # get the directory containing the db file db_dir = os.environ['DB_LOC'] db_path = os.path.join(db_dir, 'tasks_db.json') logging.basicConfig(level=logging.INFO) logger = logging.getLogger('MPVaspDrone') logger.setLevel(logging.INFO) sh = logging.StreamHandler(stream=sys.stdout) sh.setLevel(getattr(logging, 'INFO')) logger.addHandler(sh) with open(db_path) as f: db_creds = json.load(f) drone = MPVaspDrone( host=db_creds['host'], port=db_creds['port'], database=db_creds['database'], user=db_creds['admin_user'], password=db_creds['admin_password'], collection=db_creds['collection'], parse_dos=parse_dos, additional_fields=self.additional_fields, update_duplicates=self.update_duplicates) t_id, d = drone.assimilate(prev_dir, launches_coll=LaunchPad.auto_load().launches) mpsnl = d['snl_final'] if 'snl_final' in d else d['snl'] snlgroup_id = d['snlgroup_id_final'] if 'snlgroup_id_final' in d else d['snlgroup_id'] update_spec.update({'mpsnl': mpsnl, 'snlgroup_id': snlgroup_id}) print 'ENTERED task id:', t_id stored_data = {'task_id': t_id} if d['state'] == 'successful': update_spec['analysis'] = d['analysis'] update_spec['output'] = d['output'] return FWAction(stored_data=stored_data, update_spec=update_spec) # not successful - first test to see if UnconvergedHandler is needed if not fizzled_parent: unconverged_tag = 'unconverged_handler--{}'.format(fw_spec['prev_task_type']) output_dir = last_relax(os.path.join(prev_dir, 'vasprun.xml')) ueh = UnconvergedErrorHandler(output_filename=output_dir) if ueh.check() and unconverged_tag not in fw_spec['run_tags']: print 'Unconverged run! Creating dynamic FW...' spec = {'prev_vasp_dir': prev_dir, 'prev_task_type': fw_spec['task_type'], 'mpsnl': mpsnl, 'snlgroup_id': snlgroup_id, 'task_type': fw_spec['prev_task_type'], 'run_tags': list(fw_spec['run_tags']), 'parameters': fw_spec.get('parameters'), '_dupefinder': DupeFinderVasp().to_dict(), '_priority': fw_spec['_priority']} snl = StructureNL.from_dict(spec['mpsnl']) spec['run_tags'].append(unconverged_tag) spec['_queueadapter'] = QA_VASP fws = [] connections = {} f = Composition.from_formula( snl.structure.composition.reduced_formula).alphabetical_formula fws.append(FireWork( [VaspCopyTask({'files': ['INCAR', 'KPOINTS', 'POSCAR', 'POTCAR', 'CONTCAR'], 'use_CONTCAR': False}), SetupUnconvergedHandlerTask(), get_custodian_task(spec)], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=-2)) spec = {'task_type': 'VASP db insertion', '_allow_fizzled_parents': True, '_priority': fw_spec['_priority'], '_queueadapter': QA_DB, 'run_tags': list(fw_spec['run_tags'])} spec['run_tags'].append(unconverged_tag) fws.append( FireWork([VaspToDBTask()], spec, name=get_slug(f + '--' + spec['task_type']), fw_id=-1)) connections[-2] = -1 wf = Workflow(fws, connections) return FWAction(detours=wf) # not successful and not due to convergence problem - FIZZLE raise ValueError("DB insertion successful, but don't know how to fix this FireWork! Can't continue with workflow...")