def gen_element(ele_name, key): assert (type(ele_name) == str) mpr = MPRester(key) data = mpr.query({ 'elements': [ele_name], 'nelements': 1 }, properties=[ "task_id", "pretty_formula", 'formula', "anonymous_formula", 'formation_energy_per_atom', 'energy_per_atom', 'structure' ]) for ii in data: work_path = make_path_mp(ii) os.makedirs(work_path, exist_ok=True) fposcar = os.path.join(work_path, 'POSCAR') fjson = os.path.join(work_path, 'data.json') ii['structure'].to('poscar', fposcar) ii['structure'].to('json', fjson) m = StructureMatcher() for ii in global_std_crystal.keys(): ss = gen_ele_std(ele_name, ii) find = False for jj in data: if m.fit(ss, jj['structure']): find = True break if find: work_path = make_path_mp(jj) with open(os.path.join(work_path, 'std-crys'), 'w') as fp: fp.write(ii + '\n')
def gen_alloy(eles, key): mpr = MPRester(key) data = mpr.query({ 'elements': { '$all': eles }, 'nelements': len(eles) }, properties=[ "task_id", "pretty_formula", 'formula', "anonymous_formula", 'formation_energy_per_atom', 'energy_per_atom', 'structure' ]) if len(data) == 0: return alloy_file = make_path_mp(data[0]) os.makedirs(alloy_file, exist_ok=True) alloy_file = os.path.join(alloy_file, '..') alloy_file = os.path.join(alloy_file, 'alloy') with open(alloy_file, 'w') as fp: None for ii in data: work_path = make_path_mp(ii) os.makedirs(work_path, exist_ok=True) fposcar = os.path.join(work_path, 'POSCAR') fjson = os.path.join(work_path, 'data.json') ii['structure'].to('poscar', fposcar) ii['structure'].to('json', fjson)
def do_query(args): m = MPRester() try: criteria = json.loads(args.criteria) except json.decoder.JSONDecodeError: criteria = args.criteria if args.structure: count = 0 for d in m.query(criteria, properties=["structure", "task_id"]): s = d["structure"] formula = re.sub(r"\s+", "", s.formula) if args.structure == "poscar": fname = "POSCAR.%s_%s" % (d["task_id"], formula) else: fname = "%s-%s.%s" % (d["task_id"], formula, args.structure) s.to(filename=fname) count += 1 print("%d structures written!" % count) elif args.entries: entries = m.get_entries(criteria) dumpfn(entries, args.entries) print("%d entries written to %s!" % (len(entries), args.entries)) else: props = ["e_above_hull", "spacegroup"] props += args.data entries = m.get_entries(criteria, property_data=props) t = [] headers = ["mp-id", "Formula", "Spacegroup", "E/atom (eV)", "E above hull (eV)"] + args.data for e in entries: row = [e.entry_id, e.composition.reduced_formula, e.data["spacegroup"]["symbol"], e.energy_per_atom, e.data["e_above_hull"]] row += [e.data[s] for s in args.data] t.append(row) t = sorted(t, key=lambda x: x[headers.index("E above hull (eV)")]) print(tabulate(t, headers=headers, tablefmt="pipe", floatfmt=".3f"))
class MaterialsProject(BaseDataSource): """ Query the Materials Project for Data. """ def __init__(self, api_key: str = None): """ Args: api_key (str or None): Materials Project API key. """ self.mpr = MPRester(api_key=api_key) def get(self, criteria: Union[str, Dict], properties: List[str]) -> pd.DataFrame: # type: ignore """ Args: criteria (str or dict): Criteria for query properties (list): Properties to be queried. Returns: pandas DataFrame """ data = self.mpr.query(criteria=criteria, properties=properties) return pd.DataFrame(data)
# create a ./data folder if it doesn't already exist if not path.isdir(data_dir): os.mkdir(data_dir) cif_folder = data_dir + prop + "_cifs/" csv_path = data_dir + prop + ".csv" api_key = sys.argv[1] m = MPRester(api_key=api_key) # skip radioactive elements and noble gases elements = ["H", "Li", "Be", "B", "C", "N", "O", "F", "Na", "Mg", "Al", "Si", "P", "S", "Cl", "K", "Ca", "Sc", "Ti", "V", "Cr", "Mn", "Fe", "Co", "Ni", "Cu", "Zn", "Ga", "Ge", "As", "Se", "Br", "Rb", "Sr", "Y", "Zr", "Nb", "Mo", "Tc", "Ru", "Rh", "Pd", "Ag", "Cd", "In", "Sn", "Sb", "Te", "I", "Cs", "Ba", "La", "Ce", "Pr", "Nd", "Pm", "Sm", "Eu", "Gd", "Tb", "Dy", "Ho", "Er", "Tm", "Yb", "Lu", "Hf", "Ta", "W", "Re", "Os", "Ir", "Pt", "Au", "Hg", "Tl", "Pb", "Bi"] # query for property data of stable, ordered materials data = m.query(criteria={"is_ordered":True, "e_above_hull":0}, properties=["full_formula",id,prop,"cif","elements"]) # convert to a dataframe df = pd.DataFrame.from_records(data) # drop out entries that have elements not in the list inds_to_drop = [] for row in df.iterrows(): if not set(row[1]["elements"]).intersection(set(elements))==set(row[1]["elements"]): inds_to_drop.append(row[0]) df = df.drop(inds_to_drop) # and save as CSV (without cifs or element lists) df = df.drop(["cif", "elements"], axis=1)
class MPResterTest(unittest.TestCase): def setUp(self): self.rester = MPRester() def test_get_data(self): props = ["energy", "energy_per_atom", "formation_energy_per_atom", "nsites", "unit_cell_formula", "pretty_formula", "is_hubbard", "elements", "nelements", "e_above_hull", "hubbards", "is_compatible", "task_ids", "density", "icsd_ids", "total_magnetization"] # unicode literals have been reintroduced in py>3.2 expected_vals = [-191.33812137, -6.833504334642858, -2.551358929370749, 28, {k: v for k, v in {'P': 4, 'Fe': 4, 'O': 16, 'Li': 4}.items()}, "LiFePO4", True, ['Li', 'O', 'P', 'Fe'], 4, 0.0, {k: v for k, v in {'Fe': 5.3, 'Li': 0.0, 'O': 0.0, 'P': 0.0}.items()}, True, [u'mp-601412', u'mp-19017', u'mp-796535', u'mp-797820', u'mp-540081', u'mp-797269'], 3.4662026991351147, [159107, 154117, 160776, 99860, 181272, 166815, 260571, 92198, 165000, 155580, 38209, 161479, 153699, 260569, 260570, 200155, 260572, 181341, 181342, 72545, 56291, 97764, 162282, 155635], 16.0002716] for (i, prop) in enumerate(props): if prop not in ['hubbards', 'unit_cell_formula', 'elements', 'icsd_ids', 'task_ids']: val = self.rester.get_data("mp-19017", prop=prop)[0][prop] self.assertAlmostEqual(expected_vals[i], val) elif prop in ["elements", "icsd_ids", "task_ids"]: self.assertEqual(set(expected_vals[i]), set(self.rester.get_data("mp-19017", prop=prop)[0][prop])) else: self.assertEqual(expected_vals[i], self.rester.get_data("mp-19017", prop=prop)[0][prop]) props = ['structure', 'initial_structure', 'final_structure', 'entry'] for prop in props: obj = self.rester.get_data("mp-19017", prop=prop)[0][prop] if prop.endswith("structure"): self.assertIsInstance(obj, Structure) elif prop == "entry": obj = self.rester.get_data("mp-19017", prop=prop)[0][prop] self.assertIsInstance(obj, ComputedEntry) #Test chemsys search data = self.rester.get_data('Fe-Li-O', prop='unit_cell_formula') self.assertTrue(len(data) > 1) elements = {Element("Li"), Element("Fe"), Element("O")} for d in data: self.assertTrue( set(Composition(d['unit_cell_formula']).elements).issubset( elements)) self.assertRaises(MPRestError, self.rester.get_data, "Fe2O3", "badmethod") def test_get_materials_id_from_task_id(self): self.assertEqual(self.rester.get_materials_id_from_task_id( "mp-540081"), "mp-19017") def test_get_materials_id_references(self): # nosetests pymatgen/matproj/tests/test_matproj.py:MPResterTest.test_get_materials_id_references m = MPRester() data = m.get_materials_id_references('mp-123') self.assertTrue(len(data) > 1000) def test_find_structure(self): # nosetests pymatgen/matproj/tests/test_matproj.py:MPResterTest.test_find_structure m = MPRester() ciffile = os.path.join(test_dir, 'Fe3O4.cif') data = m.find_structure(ciffile) self.assertTrue(len(data) > 1) s = CifParser(ciffile).get_structures()[0] data = m.find_structure(s) self.assertTrue(len(data) > 1) def test_get_entries_in_chemsys(self): syms = ["Li", "Fe", "O"] entries = self.rester.get_entries_in_chemsys(syms) elements = set([Element(sym) for sym in syms]) for e in entries: self.assertIsInstance(e, ComputedEntry) self.assertTrue(set(e.composition.elements).issubset(elements)) def test_get_structure_by_material_id(self): s1 = self.rester.get_structure_by_material_id("mp-1") self.assertEqual(s1.formula, "Cs1") def test_get_entry_by_material_id(self): e = self.rester.get_entry_by_material_id("mp-19017") self.assertIsInstance(e, ComputedEntry) self.assertTrue(e.composition.reduced_formula, "LiFePO4") def test_query(self): criteria = {'elements': {'$in': ['Li', 'Na', 'K'], '$all': ['O']}} props = ['pretty_formula', 'energy'] data = self.rester.query(criteria=criteria, properties=props) self.assertTrue(len(data) > 6) data = self.rester.query(criteria="*2O", properties=props) self.assertGreaterEqual(len(data), 52) self.assertIn("Li2O", (d["pretty_formula"] for d in data)) def test_get_exp_thermo_data(self): data = self.rester.get_exp_thermo_data("Fe2O3") self.assertTrue(len(data) > 0) for d in data: self.assertEqual(d.formula, "Fe2O3") def test_get_dos_by_id(self): dos = self.rester.get_dos_by_material_id("mp-2254") self.assertIsInstance(dos, CompleteDos) def test_get_bandstructure_by_material_id(self): bs = self.rester.get_bandstructure_by_material_id("mp-2254") self.assertIsInstance(bs, BandStructureSymmLine) def test_get_structures(self): structs = self.rester.get_structures("Mn3O4") self.assertTrue(len(structs) > 0) def test_get_entries(self): entries = self.rester.get_entries("TiO2") self.assertTrue(len(entries) > 1) for e in entries: self.assertEqual(e.composition.reduced_formula, "TiO2") entries = self.rester.get_entries("TiO2", inc_structure="final") self.assertTrue(len(entries) > 1) for e in entries: self.assertEqual(e.structure.composition.reduced_formula, "TiO2") # all_entries = self.rester.get_entries("Fe", compatible_only=False) # entries = self.rester.get_entries("Fe", compatible_only=True) # self.assertTrue(len(entries) < len(all_entries)) entries = self.rester.get_entries("Fe", compatible_only=True, property_data=["cif"]) self.assertIn("cif", entries[0].data) for e in self.rester.get_entries("CdO2", inc_structure=False): self.assertIsNotNone(e.data["oxide_type"]) def test_get_exp_entry(self): entry = self.rester.get_exp_entry("Fe2O3") self.assertEqual(entry.energy, -825.5) def test_submit_query_delete_snl(self): s = Structure([[5, 0, 0], [0, 5, 0], [0, 0, 5]], ["Fe"], [[0, 0, 0]]) # d = self.rester.submit_snl( # [s, s], remarks=["unittest"], # authors="Test User <*****@*****.**>") # self.assertEqual(len(d), 2) # data = self.rester.query_snl({"about.remarks": "unittest"}) # self.assertEqual(len(data), 2) # snlids = [d["_id"] for d in data] # self.rester.delete_snl(snlids) # data = self.rester.query_snl({"about.remarks": "unittest"}) # self.assertEqual(len(data), 0) def test_get_stability(self): entries = self.rester.get_entries_in_chemsys(["Fe", "O"]) modified_entries = [] for entry in entries: # Create modified entries with energies that are 0.01eV higher # than the corresponding entries. if entry.composition.reduced_formula == "Fe2O3": modified_entries.append( ComputedEntry(entry.composition, entry.uncorrected_energy + 0.01, parameters=entry.parameters, entry_id="mod_{}".format(entry.entry_id))) rest_ehulls = self.rester.get_stability(modified_entries) all_entries = entries + modified_entries compat = MaterialsProjectCompatibility() all_entries = compat.process_entries(all_entries) pd = PhaseDiagram(all_entries) a = PDAnalyzer(pd) for e in all_entries: if str(e.entry_id).startswith("mod"): for d in rest_ehulls: if d["entry_id"] == e.entry_id: data = d break self.assertAlmostEqual(a.get_e_above_hull(e), data["e_above_hull"]) def test_get_reaction(self): rxn = self.rester.get_reaction(["Li", "O"], ["Li2O"]) self.assertIn("Li2O", rxn["Experimental_references"]) def test_get_substrates(self): substrate_data = self.rester.get_substrates('mp-123', 5, [1, 0, 0]) substrates = [sub_dict['sub_id'] for sub_dict in substrate_data] self.assertIn("mp-2534", substrates) def test_parse_criteria(self): crit = MPRester.parse_criteria("mp-1234 Li-*") self.assertIn("Li-O", crit["$or"][1]["chemsys"]["$in"]) self.assertIn({"task_id": "mp-1234"}, crit["$or"]) crit = MPRester.parse_criteria("Li2*") self.assertIn("Li2O", crit["pretty_formula"]["$in"]) self.assertIn("Li2I", crit["pretty_formula"]["$in"]) self.assertIn("CsLi2", crit["pretty_formula"]["$in"]) crit = MPRester.parse_criteria("Li-*-*") self.assertIn("Li-Re-Ru", crit["chemsys"]["$in"]) self.assertNotIn("Li-Li", crit["chemsys"]["$in"]) comps = MPRester.parse_criteria("**O3")["pretty_formula"]["$in"] for c in comps: self.assertEqual(len(Composition(c)), 3, "Failed in %s" % c) chemsys = MPRester.parse_criteria("{Fe,Mn}-O")["chemsys"]["$in"] self.assertEqual(len(chemsys), 2) comps = MPRester.parse_criteria("{Fe,Mn,Co}O")["pretty_formula"]["$in"] self.assertEqual(len(comps), 3, comps) #Let's test some invalid symbols self.assertRaises(ValueError, MPRester.parse_criteria, "li-fe") self.assertRaises(ValueError, MPRester.parse_criteria, "LO2") crit = MPRester.parse_criteria("POPO2") self.assertIn("P2O3", crit["pretty_formula"]["$in"])
class MPResterTest(unittest.TestCase): def setUp(self): self.rester = MPRester() def test_get_data(self): props = ["energy", "energy_per_atom", "formation_energy_per_atom", "nsites", "unit_cell_formula", "pretty_formula", "is_hubbard", "elements", "nelements", "e_above_hull", "hubbards", "is_compatible", "task_ids", "density", "icsd_ids", "total_magnetization"] # unicode literals have been reintroduced in py>3.2 expected_vals = [-191.33812137, -6.833504334642858, -2.551358929370749, 28, {k: v for k, v in {'P': 4, 'Fe': 4, 'O': 16, 'Li': 4}.items()}, "LiFePO4", True, ['Li', 'O', 'P', 'Fe'], 4, 0.0, {k: v for k, v in {'Fe': 5.3, 'Li': 0.0, 'O': 0.0, 'P': 0.0}.items()}, True, [u'mp-601412', u'mp-19017', u'mp-796535', u'mp-797820', u'mp-540081', u'mp-797269'], 3.4662026991351147, [159107, 154117, 160776, 99860, 181272, 166815, 260571, 92198, 165000, 155580, 38209, 161479, 153699, 260569, 260570, 200155, 260572, 181341, 181342, 72545, 56291, 97764, 162282, 155635], 16.0002716] for (i, prop) in enumerate(props): if prop not in ['hubbards', 'unit_cell_formula', 'elements', 'icsd_ids', 'task_ids']: val = self.rester.get_data("mp-19017", prop=prop)[0][prop] self.assertAlmostEqual(expected_vals[i], val) elif prop in ["elements", "icsd_ids", "task_ids"]: self.assertEqual(set(expected_vals[i]), set(self.rester.get_data("mp-19017", prop=prop)[0][prop])) else: self.assertEqual(expected_vals[i], self.rester.get_data("mp-19017", prop=prop)[0][prop]) props = ['structure', 'initial_structure', 'final_structure', 'entry'] for prop in props: obj = self.rester.get_data("mp-19017", prop=prop)[0][prop] if prop.endswith("structure"): self.assertIsInstance(obj, Structure) elif prop == "entry": obj = self.rester.get_data("mp-19017", prop=prop)[0][prop] self.assertIsInstance(obj, ComputedEntry) #Test chemsys search data = self.rester.get_data('Fe-Li-O', prop='unit_cell_formula') self.assertTrue(len(data) > 1) elements = {Element("Li"), Element("Fe"), Element("O")} for d in data: self.assertTrue( set(Composition(d['unit_cell_formula']).elements).issubset( elements)) self.assertRaises(MPRestError, self.rester.get_data, "Fe2O3", "badmethod") def test_get_materials_id_from_task_id(self): self.assertEqual(self.rester.get_materials_id_from_task_id( "mp-540081"), "mp-19017") def test_get_materials_id_references(self): # nosetests pymatgen/matproj/tests/test_matproj.py:MPResterTest.test_get_materials_id_references m = MPRester() data = m.get_materials_id_references('mp-123') self.assertTrue(len(data) > 1000) def test_find_structure(self): # nosetests pymatgen/matproj/tests/test_matproj.py:MPResterTest.test_find_structure m = MPRester() ciffile = os.path.join(test_dir, 'Fe3O4.cif') data = m.find_structure(ciffile) self.assertTrue(len(data) > 1) s = CifParser(ciffile).get_structures()[0] data = m.find_structure(s) self.assertTrue(len(data) > 1) def test_get_entries_in_chemsys(self): syms = ["Li", "Fe", "O"] entries = self.rester.get_entries_in_chemsys(syms) elements = set([Element(sym) for sym in syms]) for e in entries: self.assertIsInstance(e, ComputedEntry) self.assertTrue(set(e.composition.elements).issubset(elements)) def test_get_structure_by_material_id(self): s1 = self.rester.get_structure_by_material_id("mp-1") self.assertEqual(s1.formula, "Cs1") def test_get_entry_by_material_id(self): e = self.rester.get_entry_by_material_id("mp-19017") self.assertIsInstance(e, ComputedEntry) self.assertTrue(e.composition.reduced_formula, "LiFePO4") def test_query(self): criteria = {'elements': {'$in': ['Li', 'Na', 'K'], '$all': ['O']}} props = ['pretty_formula', 'energy'] data = self.rester.query(criteria=criteria, properties=props) self.assertTrue(len(data) > 6) data = self.rester.query(criteria="*2O", properties=props) self.assertGreaterEqual(len(data), 52) self.assertIn("Li2O", (d["pretty_formula"] for d in data)) def test_get_exp_thermo_data(self): data = self.rester.get_exp_thermo_data("Fe2O3") self.assertTrue(len(data) > 0) for d in data: self.assertEqual(d.formula, "Fe2O3") def test_get_dos_by_id(self): dos = self.rester.get_dos_by_material_id("mp-2254") self.assertIsInstance(dos, CompleteDos) def test_get_bandstructure_by_material_id(self): bs = self.rester.get_bandstructure_by_material_id("mp-2254") self.assertIsInstance(bs, BandStructureSymmLine) def test_get_structures(self): structs = self.rester.get_structures("Mn3O4") self.assertTrue(len(structs) > 0) def test_get_entries(self): entries = self.rester.get_entries("TiO2") self.assertTrue(len(entries) > 1) for e in entries: self.assertEqual(e.composition.reduced_formula, "TiO2") entries = self.rester.get_entries("TiO2", inc_structure="final") self.assertTrue(len(entries) > 1) for e in entries: self.assertEqual(e.structure.composition.reduced_formula, "TiO2") # all_entries = self.rester.get_entries("Fe", compatible_only=False) # entries = self.rester.get_entries("Fe", compatible_only=True) # self.assertTrue(len(entries) < len(all_entries)) entries = self.rester.get_entries("Fe", compatible_only=True, property_data=["cif"]) self.assertIn("cif", entries[0].data) for e in self.rester.get_entries("CdO2", inc_structure=False): self.assertIsNotNone(e.data["oxide_type"]) def test_get_exp_entry(self): entry = self.rester.get_exp_entry("Fe2O3") self.assertEqual(entry.energy, -825.5) def test_submit_query_delete_snl(self): s = Structure([[5, 0, 0], [0, 5, 0], [0, 0, 5]], ["Fe"], [[0, 0, 0]]) # d = self.rester.submit_snl( # [s, s], remarks=["unittest"], # authors="Test User <*****@*****.**>") # self.assertEqual(len(d), 2) # data = self.rester.query_snl({"about.remarks": "unittest"}) # self.assertEqual(len(data), 2) # snlids = [d["_id"] for d in data] # self.rester.delete_snl(snlids) # data = self.rester.query_snl({"about.remarks": "unittest"}) # self.assertEqual(len(data), 0) def test_get_stability(self): entries = self.rester.get_entries_in_chemsys(["Fe", "O"]) modified_entries = [] for entry in entries: # Create modified entries with energies that are 0.01eV higher # than the corresponding entries. if entry.composition.reduced_formula == "Fe2O3": modified_entries.append( ComputedEntry(entry.composition, entry.uncorrected_energy + 0.01, parameters=entry.parameters, entry_id="mod_{}".format(entry.entry_id))) rest_ehulls = self.rester.get_stability(modified_entries) all_entries = entries + modified_entries compat = MaterialsProjectCompatibility() all_entries = compat.process_entries(all_entries) pd = PhaseDiagram(all_entries) for e in all_entries: if str(e.entry_id).startswith("mod"): for d in rest_ehulls: if d["entry_id"] == e.entry_id: data = d break self.assertAlmostEqual(pd.get_e_above_hull(e), data["e_above_hull"]) def test_get_reaction(self): rxn = self.rester.get_reaction(["Li", "O"], ["Li2O"]) self.assertIn("Li2O", rxn["Experimental_references"]) def test_get_substrates(self): substrate_data = self.rester.get_substrates('mp-123', 5, [1, 0, 0]) substrates = [sub_dict['sub_id'] for sub_dict in substrate_data] self.assertIn("mp-2534", substrates) def test_parse_criteria(self): crit = MPRester.parse_criteria("mp-1234 Li-*") self.assertIn("Li-O", crit["$or"][1]["chemsys"]["$in"]) self.assertIn({"task_id": "mp-1234"}, crit["$or"]) crit = MPRester.parse_criteria("Li2*") self.assertIn("Li2O", crit["pretty_formula"]["$in"]) self.assertIn("Li2I", crit["pretty_formula"]["$in"]) self.assertIn("CsLi2", crit["pretty_formula"]["$in"]) crit = MPRester.parse_criteria("Li-*-*") self.assertIn("Li-Re-Ru", crit["chemsys"]["$in"]) self.assertNotIn("Li-Li", crit["chemsys"]["$in"]) comps = MPRester.parse_criteria("**O3")["pretty_formula"]["$in"] for c in comps: self.assertEqual(len(Composition(c)), 3, "Failed in %s" % c) chemsys = MPRester.parse_criteria("{Fe,Mn}-O")["chemsys"]["$in"] self.assertEqual(len(chemsys), 2) comps = MPRester.parse_criteria("{Fe,Mn,Co}O")["pretty_formula"]["$in"] self.assertEqual(len(comps), 3, comps) #Let's test some invalid symbols self.assertRaises(ValueError, MPRester.parse_criteria, "li-fe") self.assertRaises(ValueError, MPRester.parse_criteria, "LO2") crit = MPRester.parse_criteria("POPO2") self.assertIn("P2O3", crit["pretty_formula"]["$in"])
def from_pymatgen_structure( structure=None, formula=None, space_grp=None, MP_key=None, conventional_standard_structure=True, ): """ Create a Crystal object from a pymatgen Structure object. If a Materials Project API key is installed, you may pass the Materials Project ID of a structure, which will be fetched through the MP API. For setup information see: https://pymatgen.org/usage.html#setting-the-pmg-mapi-key-in-the-config-file. Alternatively, Materials Porject API key can be pass as an argument through the function (MP_key). To get your API key, please visit Materials Project website and login/sign up using your email id. Once logged in, go to the dashboard to generate your own API key (https://materialsproject.org/dashboard). Note that pymatgen typically prefers to return primitive unit cells, which can be overridden by setting conventional_standard_structure=True. Args: structure: (pymatgen Structure or str), if specified as a string, it will be considered as a Materials Project ID of a structure, otherwise it will accept only pymatgen Structure object. if None, MP database will be queried using the specified formula and/or space groups for the available structure formula: (str), pretty formula to search in the MP database, (note that the forumlas in MP database are not always formatted in the conventional order. Please visit Materials Project website for information (https://materialsproject.org/) if None, structure argument must not be None space_grp: (int) space group number of the forumula provided to query MP database. If None, MP will search for all the available space groups for the formula provided and will consider the one with lowest unit cell volume, only specify when using formula to search MP database MP_key: (str) Materials Project API key conventional_standard_structure: (bool) if True, conventional standard unit cell will be returned instead of the primitive unit cell pymatgen returns """ import pymatgen as mg from pymatgen.ext.matproj import MPRester if structure is not None: if isinstance(structure, str): mpr = MPRester(MP_key) structure = mpr.get_structure_by_material_id(structure) assert isinstance(structure, mg.core.Structure ), "structure must be pymatgen Structure object" structure = (mg.symmetry.analyzer.SpacegroupAnalyzer( structure).get_conventional_standard_structure() if conventional_standard_structure else structure) else: mpr = MPRester(MP_key) if formula is None: raise Exception( "Atleast a formula needs to be provided to query from MP database!!" ) query = mpr.query( criteria={"pretty_formula": formula}, properties=["structure", "icsd_ids", "spacegroup"], ) if space_grp: query = [ query[i] for i in range(len(query)) if mg.symmetry.analyzer.SpacegroupAnalyzer( query[i]["structure"]).get_space_group_number() == space_grp ] selected = query[np.argmin([ query[i]["structure"].lattice.volume for i in range(len(query)) ])] structure = (mg.symmetry.analyzer.SpacegroupAnalyzer( selected["structure"]).get_conventional_standard_structure() if conventional_standard_structure else selected["structure"]) positions = structure.frac_coords #: fractional atomic coordinates cell = np.array([ structure.lattice.a, structure.lattice.b, structure.lattice.c, structure.lattice.alpha, structure.lattice.beta, structure.lattice.gamma, ]) numbers = np.array([s.species.elements[0].Z for s in structure]) return Crystal(positions, numbers, cell)
def fetch_materials_data(root_dir): # properties of interest properties = [ # ID "material_id", "icsd_id", "icsd_ids", # structure "cif", "spacegroup", "crystal_system", "volume", "nsites", # composition "unit_cell_formula", "pretty_formula", "elements", "nelements", # energy "energy", "energy_per_atom", "formation_energy_per_atom", "e_above_hull", # electronic property "band_gap", "is_hubbard", "hubbards", "is_compatible", # mechanical property "elasticity", "piezo", 'diel', # other property "density", "total_magnetization", # additional info "oxide_type", "warnings", "task_ids", "tags" ] # MaterialsProject API settings my_API_key = None # put your API key here if not my_API_key: print("please specify your Materials Project API key here") sys.exit() m = MPRester(api_key=my_API_key) # query all materials data query_all = m.query(criteria={}, properties=properties) MPdata_all = pd.DataFrame(entry.values() for entry in query_all) MPdata_all.columns = properties # write cif to file cif_dir = os.path.join(root_dir, "MP_cifs") if os.path.exists(cif_dir): _ = input("MPdata_all/MP_cifs dir already exists, press Enter to continue, Ctrl+C to terminate..") else: os.mkdir(cif_dir) for _, irow in MPdata_all[["material_id", "cif"]].iterrows(): cif_file = os.path.join(cif_dir, irow["material_id"] + ".cif") with open(cif_file, 'w') as f: f.write(irow["cif"]) MPdata_all = MPdata_all.drop(columns=["cif"]) # materials with calculated band structures query_band = m.query(criteria={"has": "bandstructure"}, properties=["material_id"]) band_filenames = [list(entry.values())[0] for entry in query_band] MPdata_all['has_band_structure'] = MPdata_all["material_id"].isin(band_filenames) # write properties to file out_file = os.path.join(root_dir, "MPdata_all.csv") MPdata_all.to_csv(out_file, sep=';', index=False, header=MPdata_all.columns, mode='w')
row.append(atom_r**3*10**(-7)) ElemData.append(row) Database=[] print("Element Data Collection Completion:--- %s seconds ---" % (time.time() - start_time)) f.write('Comp,MPID,target,AvgElectron,sTot,pTot,dTot,fTot,NAtom,AvgIonicRad,DevIonicRad,VolumeAverageMass,AverageMass,DevMass,RedMass,AvgENeg,DiffENeg,DevENeg,AvgDipole,DevDipole,DiffDipole,TotalVolume,totalAtoms,density,OmegaAvg,OmegaDev,OmegaMax,OmegaMin,eHull,formE,gap,symm,lattA,lattB,lattC,lattAlpha,lattBeta,lattGamma') f.write('\n') numberofanalyzed=0 for i in range(0,numMaterials): stabdata = m.query(criteria={'material_id':ID[i]}, properties=["pretty_formula","formation_energy_per_atom","band_gap","spacegroup.number",'volume', 'structure','density','e_above_hull','nsites']) symm=SymmGroupFinder(stabdata[0]['spacegroup.number']) gap = stabdata[0]['band_gap'] volume=stabdata[0]['volume'] formE=stabdata[0]['formation_energy_per_atom'] lattA=stabdata[0]['structure'].lattice.a lattB=stabdata[0]['structure'].lattice.b lattC=stabdata[0]['structure'].lattice.c lattAlpha=stabdata[0]['structure'].lattice.angles[0] lattBeta=stabdata[0]['structure'].lattice.angles[1] lattGamma=stabdata[0]['structure'].lattice.angles[2] density=stabdata[0]['density'] eHull=stabdata[0]['e_above_hull'] NAtom=stabdata[0]['nsites']
# import names input_filename = input("\nInput filename (CSV file only): ") names = data_handler.import_csv(input_filename) # create a folder to store cifs dir_name = input_filename.replace('.csv', '') os.mkdir(dir_name) print('\nDirectory "' + dir_name + '" is created. All CIF files will be stored in this folder. \n') # loop through all names entries = [] for name in tqdm(names): data_handler.try_url('https://www.materialsproject.org') results = m.query(name, properties=['material_id', 'spacegroup.number']) # query for result in results: material_id = result['material_id'] sgn = result['spacegroup.number'] if sgn != 1 and sgn != 2: # exclude triclinics structure = m.get_structure_by_material_id( material_id, conventional_unit_cell=True) symmetrized_structure = SpacegroupAnalyzer( structure).get_symmetrized_structure() entry = [name, sgn, material_id] entries.append(entry) CifWriter(symmetrized_structure, symprec=0.01).write_file(dir_name + '/' + name + '_' + str(sgn) + '_' + material_id + '.cif')
def to_cif(self): m = MPRester("iEe4KC8U9QBczglh") structure = m.query(self.id, ['initial_structure']) # 改变不同的晶体ID录入不同的数字 f = structure[0]['initial_structure'] f1 = str(f) + '\n' j_pv_lst = re.findall('abc\s\s\s:\s\s\s(.*?)\n', f1)[0] j1_pv_lst = j_pv_lst.split(' ') a = float(j1_pv_lst[0]) b = float(j1_pv_lst[1]) c = float(j1_pv_lst[2]) par_lst_matrix = [[a, 0, 0], [0, b, 0], [0, 0, c]] print(par_lst_matrix) # 物质种类(比如:Lu2 Al4) y1 = re.findall('Full\sFormula\s(.*?)\n', f1)[0] # y1_lst = y1.lstrip('(').rstrip(')') material = re.findall('Full\sFormula\s(.*?)\n', f1)[0].lstrip('(').rstrip(')') self.mat_name = material elements = material.split(' ') element_lst = [] num_lst = [] for element in elements: # 这个循环之后,得到原子与对应的原子数两个列表 letter_lst = list(element) num_lst.append(letter_lst[-1]) letter_lst.pop(-1) element1 = ''.join(letter_lst) element_lst.append(element1) par_lst_species = [] # 用于Cifwrite参数(species)的 for i in range(len(num_lst)): num = int(num_lst[i]) for j in range(num): par_lst_species.append(element_lst[i]) print(par_lst_species) # 每个原子的坐标 ord_lst = [] # 最终Cifwriter所需要的coords参数 ord_lst2 = [] # 储存的形式为 for element in element_lst: ord_lst1 = re.findall(element + '\s\s\s\s(.*?)\n', f1) for ord in ord_lst1: ord1 = ord.split(' ') while '' in ord1: ord1.remove('') ord_lst2.append(ord1) for ord in ord_lst2: ord1 = [] for string in ord: num = float(string) ord1.append(num) if len(ord1) == 3: ord2 = ord1 ord_lst.append(ord2) par_lst_coords = ord_lst print(par_lst_coords) # 构建Structure类 structure = Structure(par_lst_matrix, par_lst_species, par_lst_coords) slab = CifWriter( structure, write_magmoms=True ) # struct (Structure) – structure to write; symprec (float) – If not none, finds the symmetry of the structure and writes the cif with symmetry information. Passes symprec to the SpacegroupAnalyzer; write_magmoms (bool) – If True, will write magCIF file. Incompatible with symprec slab.write_file( r'C:\Users\wang1\Desktop\2D\download vasp\{}.cif'.format( self.mat_name))
'W': 7.17 } U_elements = list(U_dict.keys()) ############################################################################## entries = mpr.query(criteria={ "elements": { "$all": ["O"], "$in": TM_list }, "anonymous_formula": { "A": 1, "B": 1, "C": 3 }, "nelements": 3, "spacegroup.number": 221, "crystal_system": "cubic", "spacegroup.symbol": "Pm-3m" }, properties=[ "materials_id", "pretty_formula", "formation_energy_per_atom", "cif", "structure", "band_gap", "input.incar", "magnetic_type", "total_magnetization", "e_above_hull", "volume", "theoretical" ]) print("%d entries were found" % len(entries)) sorted_entries = sorted(entries, key=lambda e: e['e_above_hull']) # test_entries = sorted_entries[:10]
#define your search criteria criteria ={#"band_gap": {"$gt":0.1}, "spacegroup.number": {"$gt": 75}, "nelements": {"$in": [2, 3]}, "nsites": {"$lt": 60}, } #choose the properties which you are interested: properties = [ "material_id", "band_gap", "e_above_hull", "structure", "spacegroup.number", "composition_reduced", #"cif", ] entries = mpr.query(criteria=criteria, properties=properties) print("=============================Initial:", len(entries)) for i, entry in enumerate(entries): pmg = entry['structure'] eles = [ele.symbol for ele in pmg.composition.elements] for ele in eles: pmg0 = pmg.copy() todo = [e0 for e0 in eles if e0 != ele] pmg0.remove_species(todo) comp = pmg.composition.fractional_composition.get_atomic_fraction(ele) process(pmg0, entry['material_id'], entry['spacegroup.number'], pmg.composition, comp)
print("Loading Data ......") dataset = np.load('data/crystal_structures.npz') features = np.array(dataset['xrd'], np.float32) property = sys.argv[1] if property == "crystal_system": labels = np.array(dataset['crystal_system'], int) elif property == "space_group": labels = np.array(dataset['space_group'], int) - 1 # 0-index else: mps = np.array(dataset['mp']) m = MPRester("wdRVIWP0Sdc4Xp4pxQt") labels = [] for mp in mps: val = m.query(criteria={"task_id": mp}, properties=[property]) labels.append(val) labels = np.array(labels) print(features.shape) print(labels.shape, min(labels), max(labels), len(set(labels))) K = max(labels) + 1 features = features / np.amax(features, axis=1)[:, None] analyze(K) features, labels = shuffle(features, labels, random_state=0) print("Generating data_loader ......")
class MaterialsProjectImporter(DbImporter): """ Database importer for the Materials Project. """ _properties = 'structure' _supported_keywords = None def __init__(self, **kwargs): """ Instantiate the MaterialsProjectImporter by setting up the Materials API (MAPI) connection details. """ self.setup_db(**kwargs) def setup_db(self, **kwargs): """ Setup the required parameters to the REST API """ try: api_key = kwargs['api_key'] except KeyError: try: api_key = os.environ['PMG_MAPI_KEY'] except KeyError as exception: raise KeyError( 'API key not supplied and PMG_MAPI_KEY environment variable not set. Either pass it when ' 'initializing the class, or set the environment variable PMG_MAPI_KEY to your API key.' ) from exception api_key = None self._api_key = api_key self._verify_api_key() self._mpr = MPRester(self._api_key) def _verify_api_key(self): """ Verify the supplied API key by issuing a request to Materials Project. """ response = requests.get( 'https://www.materialsproject.org/rest/v1/api_check', headers={'X-API-KEY': self._api_key} ) response_content = response.json() # a dict if 'error' in response_content: raise RuntimeError(response_content['error']) if not response_content['valid_response']: raise RuntimeError('Materials Project did not give a valid response for the API key check.') if not response_content['api_key_valid']: raise RuntimeError('Your API key for Materials Project is not valid.') @property def api_key(self): """ Return the API key configured for the importer """ return self._api_key @property def properties(self): """ Return the properties that will be queried """ return self._properties def get_supported_keywords(self): """ Returns the list of all supported query keywords :return: list of strings """ return self._supported_keywords def query(self, **kwargs): """ Query the database with a given dictionary of query parameters for a given properties :param query: a dictionary with the query parameters :param properties: the properties to query """ try: query = kwargs['query'] except AttributeError: raise AttributeError( 'Make sure the supplied dictionary has `query` as a key. This ' 'should contain a dictionary with the right query needed.' ) try: properties = kwargs['properties'] except AttributeError: raise AttributeError('Make sure the supplied dictionary has `properties` as a key.') if not isinstance(query, dict): raise TypeError('The query argument should be a dictionary') if properties is None: properties = self._properties if properties != 'structure': raise ValueError(f'Unsupported properties: {properties}') results = [] properties_list = ['material_id', 'cif'] for entry in self._find(query, properties_list): results.append(entry) search_results = MaterialsProjectSearchResults(results, return_class=MaterialsProjectCifEntry) return search_results def _find(self, query, properties): """ Query the database with a given dictionary of query parameters :param query: a dictionary with the query parameters """ for entry in self._mpr.query(criteria=query, properties=properties): yield entry
def query_all_of_materials_project(): """ Query all of the materials project in single element queries. Combines all the queries and writes the output to a pickle file """ #Initialize the API query object API_key = 'mhaSG6L5b4HOQv2A' mp_rest = MPRester(API_key) #properties useful for project useful_properties = [ u'energy', u'band_gap', u'e_above_hull', u'elements', u'pretty_formula', u'formation_energy_per_atom', u'cif', u'density', u'material_id', u'nelements', u'energy_per_atom' ] #Other Possible Properties #Full description of each property at #https://materialsproject.org/docs/api#materials_.28calculated_materials_data.29 # ,u'is_compatible' # ,u'elasticity' # ,u'unit_cell_formula' # ,u'oxide_type' # ,u'hubbards' # ,u'task_ids' # ,u'nsites' # ,u'icsd_id' # ,u'tags' # ,u'volume' # ,u'total_magnetization' # ,u'is_hubbard' # ,u'spacegroup' # ,u'full_formula' #Divide the elements into groups of 1 to make small queries so PMG doesn't #get mad num_eles = len(chemical_symbols) divided = num_eles criteria_list = [{ 'elements': { '$all': chemical_symbols[x * num_eles / divided:num_eles * (x + 1) / divided] } } for x in range(divided)] #For each criteria query the materials project and append the output query_output = [] for criteria in criteria_list: print 'Querying Elements in Criteria : {0}'.format(criteria) query_output += mp_rest.query(criteria, useful_properties) #Need to remove any duplicate jobs (i.e. jobs with same material_id) unique_query_output = [] counted_mat_ids = [] for row in query_output: if not row['material_id'] in counted_mat_ids: unique_query_output.append(row) counted_mat_ids.append(row['material_id']) #Write the output to a pickle file project_folder = os.environ['CS230_Project_Folder'] with open(project_folder + '/data/raw_data/mat_proj_query.pickle', 'w') as file_curr: file_curr.write(pickle.dumps(new_output)) return unique_query_output
elif k==len(TempSegment)-1 and isfloat(TempSegment[k])==False: SeparatedName.append(TempSegment[k]) SeparatedName.append(str(multiplier)) return(SeparatedName) #test.cv is the compound list g=open('CompoundDescriptorsMP_exception.csv','w') f=open('CompoundDescriptorsMP.csv','w') ID=[] target=[] API_Key='pF2RrzEPyZmIsLST' m=MPRester(API_Key) MPID_DICT= m.query(criteria={}, properties=["task_id"]) numMaterials=len(MPID_DICT) print("Number Of Materials Analyzed:---%s---" % (numMaterials)) ''' Compounds=[] for i in range(0,len(ID)): stabdata = m.query(criteria={'material_id':ID[i]}, properties=["pretty_formula"]) Compounds.append(stabdata[0]['pretty_formula']) #print(Compounds) ''' print("API established") ElementList=np.genfromtxt('NameListFile.txt',dtype=None) Elements=[] for i in range(0,len(ElementList)): Elements.append(ElementList[i][1].decode("utf-8"))
class MPResterTest(unittest.TestCase): def setUp(self): self.rester = MPRester() warnings.simplefilter("ignore") def tearDown(self): warnings.resetwarnings() def test_get_all_materials_ids_doc(self): mids = self.rester.get_materials_ids("Al2O3") random.shuffle(mids) doc = self.rester.get_doc(mids.pop(0)) self.assertEqual(doc["pretty_formula"], "Al2O3") def test_get_data(self): props = ["energy", "energy_per_atom", "formation_energy_per_atom", "nsites", "unit_cell_formula", "pretty_formula", "is_hubbard", "elements", "nelements", "e_above_hull", "hubbards", "is_compatible", "task_ids", "density", "icsd_ids", "total_magnetization"] # unicode literals have been reintroduced in py>3.2 expected_vals = [-191.33812137, -6.833504334642858, -2.551358929370749, 28, {k: v for k, v in {'P': 4, 'Fe': 4, 'O': 16, 'Li': 4}.items()}, "LiFePO4", True, ['Li', 'O', 'P', 'Fe'], 4, 0.0, {k: v for k, v in {'Fe': 5.3, 'Li': 0.0, 'O': 0.0, 'P': 0.0}.items()}, True, [u'mp-601412', u'mp-19017', u'mp-796535', u'mp-797820', u'mp-540081', u'mp-797269'], 3.4662026991351147, [159107, 154117, 160776, 99860, 181272, 166815, 260571, 92198, 165000, 155580, 38209, 161479, 153699, 260569, 260570, 200155, 260572, 181341, 181342, 72545, 56291, 97764, 162282, 155635], 16.0002716] for (i, prop) in enumerate(props): if prop not in ['hubbards', 'unit_cell_formula', 'elements', 'icsd_ids', 'task_ids']: val = self.rester.get_data("mp-19017", prop=prop)[0][prop] self.assertAlmostEqual(expected_vals[i], val) elif prop in ["elements", "icsd_ids", "task_ids"]: self.assertEqual(set(expected_vals[i]), set(self.rester.get_data("mp-19017", prop=prop)[0][prop])) else: self.assertEqual(expected_vals[i], self.rester.get_data("mp-19017", prop=prop)[0][prop]) props = ['structure', 'initial_structure', 'final_structure', 'entry'] for prop in props: obj = self.rester.get_data("mp-19017", prop=prop)[0][prop] if prop.endswith("structure"): self.assertIsInstance(obj, Structure) elif prop == "entry": obj = self.rester.get_data("mp-19017", prop=prop)[0][prop] self.assertIsInstance(obj, ComputedEntry) #Test chemsys search data = self.rester.get_data('Fe-Li-O', prop='unit_cell_formula') self.assertTrue(len(data) > 1) elements = {Element("Li"), Element("Fe"), Element("O")} for d in data: self.assertTrue( set(Composition(d['unit_cell_formula']).elements).issubset( elements)) self.assertRaises(MPRestError, self.rester.get_data, "Fe2O3", "badmethod") def test_get_materials_id_from_task_id(self): self.assertEqual(self.rester.get_materials_id_from_task_id( "mp-540081"), "mp-19017") def test_get_materials_id_references(self): # nosetests pymatgen/matproj/tests/test_matproj.py:MPResterTest.test_get_materials_id_references m = MPRester() data = m.get_materials_id_references('mp-123') self.assertTrue(len(data) > 1000) def test_find_structure(self): # nosetests pymatgen/matproj/tests/test_matproj.py:MPResterTest.test_find_structure m = MPRester() ciffile = os.path.join(test_dir, 'Fe3O4.cif') data = m.find_structure(ciffile) self.assertTrue(len(data) > 1) s = CifParser(ciffile).get_structures()[0] data = m.find_structure(s) self.assertTrue(len(data) > 1) def test_get_entries_in_chemsys(self): syms = ["Li", "Fe", "O"] entries = self.rester.get_entries_in_chemsys(syms) elements = set([Element(sym) for sym in syms]) for e in entries: self.assertIsInstance(e, ComputedEntry) self.assertTrue(set(e.composition.elements).issubset(elements)) def test_get_structure_by_material_id(self): s1 = self.rester.get_structure_by_material_id("mp-1") self.assertEqual(s1.formula, "Cs1") def test_get_entry_by_material_id(self): e = self.rester.get_entry_by_material_id("mp-19017") self.assertIsInstance(e, ComputedEntry) self.assertTrue(e.composition.reduced_formula, "LiFePO4") def test_query(self): criteria = {'elements': {'$in': ['Li', 'Na', 'K'], '$all': ['O']}} props = ['pretty_formula', 'energy'] data = self.rester.query(criteria=criteria, properties=props) self.assertTrue(len(data) > 6) data = self.rester.query(criteria="*2O", properties=props) self.assertGreaterEqual(len(data), 52) self.assertIn("Li2O", (d["pretty_formula"] for d in data)) def test_get_exp_thermo_data(self): data = self.rester.get_exp_thermo_data("Fe2O3") self.assertTrue(len(data) > 0) for d in data: self.assertEqual(d.formula, "Fe2O3") def test_get_dos_by_id(self): dos = self.rester.get_dos_by_material_id("mp-2254") self.assertIsInstance(dos, CompleteDos) def test_get_bandstructure_by_material_id(self): bs = self.rester.get_bandstructure_by_material_id("mp-2254") self.assertIsInstance(bs, BandStructureSymmLine) bs_unif = self.rester.get_bandstructure_by_material_id( "mp-2254", line_mode=False) self.assertIsInstance(bs_unif, BandStructure) self.assertNotIsInstance(bs_unif, BandStructureSymmLine) def test_get_phonon_data_by_material_id(self): bs = self.rester.get_phonon_bandstructure_by_material_id("mp-661") self.assertIsInstance(bs, PhononBandStructureSymmLine) dos = self.rester.get_phonon_dos_by_material_id("mp-661") self.assertIsInstance(dos, CompletePhononDos) ddb_str = self.rester.get_phonon_ddb_by_material_id("mp-661") self.assertIsInstance(ddb_str, str) def test_get_structures(self): structs = self.rester.get_structures("Mn3O4") self.assertTrue(len(structs) > 0) def test_get_entries(self): entries = self.rester.get_entries("TiO2") self.assertTrue(len(entries) > 1) for e in entries: self.assertEqual(e.composition.reduced_formula, "TiO2") entries = self.rester.get_entries("TiO2", inc_structure=True) self.assertTrue(len(entries) > 1) for e in entries: self.assertEqual(e.structure.composition.reduced_formula, "TiO2") # all_entries = self.rester.get_entries("Fe", compatible_only=False) # entries = self.rester.get_entries("Fe", compatible_only=True) # self.assertTrue(len(entries) < len(all_entries)) entries = self.rester.get_entries("Fe", compatible_only=True, property_data=["cif"]) self.assertIn("cif", entries[0].data) for e in self.rester.get_entries("CdO2", inc_structure=False): self.assertIsNotNone(e.data["oxide_type"]) # test if it will retrieve the conventional unit cell of Ni entry = self.rester.get_entry_by_material_id( "mp-23", inc_structure=True, conventional_unit_cell=True) Ni = entry.structure self.assertEqual(Ni.lattice.a, Ni.lattice.b) self.assertEqual(Ni.lattice.a, Ni.lattice.c) self.assertEqual(Ni.lattice.alpha, 90) self.assertEqual(Ni.lattice.beta, 90) self.assertEqual(Ni.lattice.gamma, 90) # Ensure energy per atom is same primNi = self.rester.get_entry_by_material_id( "mp-23", inc_structure=True, conventional_unit_cell=False) self.assertEqual(primNi.energy_per_atom, entry.energy_per_atom) Ni = self.rester.get_structure_by_material_id( "mp-23", conventional_unit_cell=True) self.assertEqual(Ni.lattice.a, Ni.lattice.b) self.assertEqual(Ni.lattice.a, Ni.lattice.c) self.assertEqual(Ni.lattice.alpha, 90) self.assertEqual(Ni.lattice.beta, 90) self.assertEqual(Ni.lattice.gamma, 90) # Test case where convs are different from initial and final th = self.rester.get_structure_by_material_id( "mp-37", conventional_unit_cell=True) th_entry = self.rester.get_entry_by_material_id( "mp-37", inc_structure=True, conventional_unit_cell=True) th_entry_initial = self.rester.get_entry_by_material_id( "mp-37", inc_structure="initial", conventional_unit_cell=True) self.assertEqual(th, th_entry.structure) self.assertEqual(len(th_entry.structure), 4) self.assertEqual(len(th_entry_initial.structure), 2) def test_get_pourbaix_entries(self): pbx_entries = self.rester.get_pourbaix_entries(["Fe"]) for pbx_entry in pbx_entries: self.assertTrue(isinstance(pbx_entry, PourbaixEntry)) # Ensure entries are pourbaix compatible pbx = PourbaixDiagram(pbx_entries) # Try binary system pbx_entries = self.rester.get_pourbaix_entries(["Fe", "Cr"]) pbx = PourbaixDiagram(pbx_entries) # Test Zn-S, which has Na in reference solids pbx_entries = self.rester.get_pourbaix_entries(["Zn", "S"]) def test_get_exp_entry(self): entry = self.rester.get_exp_entry("Fe2O3") self.assertEqual(entry.energy, -825.5) def test_submit_query_delete_snl(self): s = Structure([[5, 0, 0], [0, 5, 0], [0, 0, 5]], ["Fe"], [[0, 0, 0]]) # d = self.rester.submit_snl( # [s, s], remarks=["unittest"], # authors="Test User <*****@*****.**>") # self.assertEqual(len(d), 2) # data = self.rester.query_snl({"about.remarks": "unittest"}) # self.assertEqual(len(data), 2) # snlids = [d["_id"] for d in data] # self.rester.delete_snl(snlids) # data = self.rester.query_snl({"about.remarks": "unittest"}) # self.assertEqual(len(data), 0) def test_get_stability(self): entries = self.rester.get_entries_in_chemsys(["Fe", "O"]) modified_entries = [] for entry in entries: # Create modified entries with energies that are 0.01eV higher # than the corresponding entries. if entry.composition.reduced_formula == "Fe2O3": modified_entries.append( ComputedEntry(entry.composition, entry.uncorrected_energy + 0.01, parameters=entry.parameters, entry_id="mod_{}".format(entry.entry_id))) rest_ehulls = self.rester.get_stability(modified_entries) all_entries = entries + modified_entries compat = MaterialsProjectCompatibility() all_entries = compat.process_entries(all_entries) pd = PhaseDiagram(all_entries) for e in all_entries: if str(e.entry_id).startswith("mod"): for d in rest_ehulls: if d["entry_id"] == e.entry_id: data = d break self.assertAlmostEqual(pd.get_e_above_hull(e), data["e_above_hull"]) def test_get_reaction(self): rxn = self.rester.get_reaction(["Li", "O"], ["Li2O"]) self.assertIn("Li2O", rxn["Experimental_references"]) def test_get_substrates(self): substrate_data = self.rester.get_substrates('mp-123', 5, [1, 0, 0]) substrates = [sub_dict['sub_id'] for sub_dict in substrate_data] self.assertIn("mp-2534", substrates) def test_get_surface_data(self): data = self.rester.get_surface_data("mp-126") # Pt self.assertIn("surfaces", data) surfaces = data["surfaces"] self.assertTrue(len(surfaces) > 0) surface = surfaces.pop() self.assertIn("miller_index", surface) self.assertIn("surface_energy", surface) self.assertIn("is_reconstructed", surface) data_inc = self.rester.get_surface_data("mp-126", inc_structures=True) self.assertIn("structure", data_inc["surfaces"][0]) def test_get_wulff_shape(self): ws = self.rester.get_wulff_shape("mp-126") self.assertTrue(isinstance(ws, WulffShape)) def test_get_interface_reactions(self): kinks = self.rester.get_interface_reactions("LiCoO2", "Li3PS4") self.assertTrue(len(kinks) > 0) kink = kinks[0] self.assertIn("energy", kink) self.assertIn("ratio", kink) self.assertIn("rxn", kink) self.assertTrue(isinstance(kink['rxn'], Reaction)) kinks_open_O = self.rester.get_interface_reactions( "LiCoO2", "Li3PS4", open_el="O", relative_mu=-1) self.assertTrue(len(kinks_open_O) > 0) with warnings.catch_warnings(record=True) as w: warnings.filterwarnings("always", message="The reactant.+") self.rester.get_interface_reactions("LiCoO2", "MnO3") self.assertTrue("The reactant" in str(w[-1].message)) def test_parse_criteria(self): crit = MPRester.parse_criteria("mp-1234 Li-*") self.assertIn("Li-O", crit["$or"][1]["chemsys"]["$in"]) self.assertIn({"task_id": "mp-1234"}, crit["$or"]) crit = MPRester.parse_criteria("Li2*") self.assertIn("Li2O", crit["pretty_formula"]["$in"]) self.assertIn("Li2I", crit["pretty_formula"]["$in"]) self.assertIn("CsLi2", crit["pretty_formula"]["$in"]) crit = MPRester.parse_criteria("Li-*-*") self.assertIn("Li-Re-Ru", crit["chemsys"]["$in"]) self.assertNotIn("Li-Li", crit["chemsys"]["$in"]) comps = MPRester.parse_criteria("**O3")["pretty_formula"]["$in"] for c in comps: self.assertEqual(len(Composition(c)), 3, "Failed in %s" % c) chemsys = MPRester.parse_criteria("{Fe,Mn}-O")["chemsys"]["$in"] self.assertEqual(len(chemsys), 2) comps = MPRester.parse_criteria("{Fe,Mn,Co}O")["pretty_formula"]["$in"] self.assertEqual(len(comps), 3, comps) #Let's test some invalid symbols self.assertRaises(ValueError, MPRester.parse_criteria, "li-fe") self.assertRaises(ValueError, MPRester.parse_criteria, "LO2") crit = MPRester.parse_criteria("POPO2") self.assertIn("P2O3", crit["pretty_formula"]["$in"])
from pymatgen.ext.matproj import MPRester # Change "<APIKEY>" to the API key obtained from MP. mpr = MPRester("<APIKEY>") data = mpr.query(criteria={"pretty_formula": "Al2O3"}, properties=["final_energy", "band_gap"]) print(data) import pandas as pd df = pd.DataFrame(data) # Convert to DataFrame
class MPResterTest(unittest.TestCase): def setUp(self): self.rester = MPRester() warnings.simplefilter("ignore") def tearDown(self): warnings.resetwarnings() def test_get_all_materials_ids_doc(self): mids = self.rester.get_materials_ids("Al2O3") random.shuffle(mids) doc = self.rester.get_doc(mids.pop(0)) self.assertEqual(doc["pretty_formula"], "Al2O3") def test_get_data(self): props = ["energy", "energy_per_atom", "formation_energy_per_atom", "nsites", "unit_cell_formula", "pretty_formula", "is_hubbard", "elements", "nelements", "e_above_hull", "hubbards", "is_compatible", "task_ids", "density", "icsd_ids", "total_magnetization"] # unicode literals have been reintroduced in py>3.2 expected_vals = [-191.3359011, -6.833425039285714, -2.5515769497278913, 28, {'P': 4, 'Fe': 4, 'O': 16, 'Li': 4}, "LiFePO4", True, ['Li', 'O', 'P', 'Fe'], 4, 0.0, {'Fe': 5.3, 'Li': 0.0, 'O': 0.0, 'P': 0.0}, True, {'mp-19017', 'mp-540081', 'mp-601412'}, 3.464840709092822, [159107, 154117, 160776, 99860, 181272, 166815, 260571, 92198, 165000, 155580, 38209, 161479, 153699, 260569, 260570, 200155, 260572, 181341, 181342, 72545, 56291, 97764, 162282, 155635], 15.9996841] for (i, prop) in enumerate(props): if prop not in ['hubbards', 'unit_cell_formula', 'elements', 'icsd_ids', 'task_ids']: val = self.rester.get_data("mp-19017", prop=prop)[0][prop] self.assertAlmostEqual(expected_vals[i], val, places=2) elif prop in ["elements", "icsd_ids", "task_ids"]: upstream_vals = set( self.rester.get_data("mp-19017", prop=prop)[0][prop]) self.assertLessEqual(set(expected_vals[i]), upstream_vals) else: self.assertEqual(expected_vals[i], self.rester.get_data("mp-19017", prop=prop)[0][prop]) props = ['structure', 'initial_structure', 'final_structure', 'entry'] for prop in props: obj = self.rester.get_data("mp-19017", prop=prop)[0][prop] if prop.endswith("structure"): self.assertIsInstance(obj, Structure) elif prop == "entry": obj = self.rester.get_data("mp-19017", prop=prop)[0][prop] self.assertIsInstance(obj, ComputedEntry) #Test chemsys search data = self.rester.get_data('Fe-Li-O', prop='unit_cell_formula') self.assertTrue(len(data) > 1) elements = {Element("Li"), Element("Fe"), Element("O")} for d in data: self.assertTrue( set(Composition(d['unit_cell_formula']).elements).issubset( elements)) self.assertRaises(MPRestError, self.rester.get_data, "Fe2O3", "badmethod") def test_get_data(self): # Test getting supported properties self.assertNotEqual(self.rester.get_task_data("mp-30"), []) # Test aliasing data = self.rester.get_task_data("mp-30", "energy") self.assertAlmostEqual(data[0]["energy"], -4.09929227, places=2) def test_get_materials_id_from_task_id(self): self.assertEqual(self.rester.get_materials_id_from_task_id( "mp-540081"), "mp-19017") def test_get_materials_id_references(self): # nosetests pymatgen/matproj/tests/test_matproj.py:MPResterTest.test_get_materials_id_references m = MPRester() data = m.get_materials_id_references('mp-123') self.assertTrue(len(data) > 1000) def test_find_structure(self): # nosetests pymatgen/matproj/tests/test_matproj.py:MPResterTest.test_find_structure m = MPRester() ciffile = os.path.join(test_dir, 'Fe3O4.cif') data = m.find_structure(ciffile) self.assertTrue(len(data) > 1) s = CifParser(ciffile).get_structures()[0] data = m.find_structure(s) self.assertTrue(len(data) > 1) def test_get_entries_in_chemsys(self): syms = ["Li", "Fe", "O"] entries = self.rester.get_entries_in_chemsys(syms) elements = set([Element(sym) for sym in syms]) for e in entries: self.assertIsInstance(e, ComputedEntry) self.assertTrue(set(e.composition.elements).issubset(elements)) def test_get_structure_by_material_id(self): s1 = self.rester.get_structure_by_material_id("mp-1") self.assertEqual(s1.formula, "Cs1") def test_get_entry_by_material_id(self): e = self.rester.get_entry_by_material_id("mp-19017") self.assertIsInstance(e, ComputedEntry) self.assertTrue(e.composition.reduced_formula, "LiFePO4") def test_query(self): criteria = {'elements': {'$in': ['Li', 'Na', 'K'], '$all': ['O']}} props = ['pretty_formula', 'energy'] data = self.rester.query(criteria=criteria, properties=props) self.assertTrue(len(data) > 6) data = self.rester.query(criteria="*2O", properties=props) self.assertGreaterEqual(len(data), 52) self.assertIn("Li2O", (d["pretty_formula"] for d in data)) def test_get_exp_thermo_data(self): data = self.rester.get_exp_thermo_data("Fe2O3") self.assertTrue(len(data) > 0) for d in data: self.assertEqual(d.formula, "Fe2O3") def test_get_dos_by_id(self): dos = self.rester.get_dos_by_material_id("mp-2254") self.assertIsInstance(dos, CompleteDos) def test_get_bandstructure_by_material_id(self): bs = self.rester.get_bandstructure_by_material_id("mp-2254") self.assertIsInstance(bs, BandStructureSymmLine) bs_unif = self.rester.get_bandstructure_by_material_id( "mp-2254", line_mode=False) self.assertIsInstance(bs_unif, BandStructure) self.assertNotIsInstance(bs_unif, BandStructureSymmLine) def test_get_phonon_data_by_material_id(self): bs = self.rester.get_phonon_bandstructure_by_material_id("mp-661") self.assertIsInstance(bs, PhononBandStructureSymmLine) dos = self.rester.get_phonon_dos_by_material_id("mp-661") self.assertIsInstance(dos, CompletePhononDos) ddb_str = self.rester.get_phonon_ddb_by_material_id("mp-661") self.assertIsInstance(ddb_str, str) def test_get_structures(self): structs = self.rester.get_structures("Mn3O4") self.assertTrue(len(structs) > 0) def test_get_entries(self): entries = self.rester.get_entries("TiO2") self.assertTrue(len(entries) > 1) for e in entries: self.assertEqual(e.composition.reduced_formula, "TiO2") entries = self.rester.get_entries("TiO2", inc_structure=True) self.assertTrue(len(entries) > 1) for e in entries: self.assertEqual(e.structure.composition.reduced_formula, "TiO2") # all_entries = self.rester.get_entries("Fe", compatible_only=False) # entries = self.rester.get_entries("Fe", compatible_only=True) # self.assertTrue(len(entries) < len(all_entries)) entries = self.rester.get_entries("Fe", compatible_only=True, property_data=["cif"]) self.assertIn("cif", entries[0].data) for e in self.rester.get_entries("CdO2", inc_structure=False): self.assertIsNotNone(e.data["oxide_type"]) # test if it will retrieve the conventional unit cell of Ni entry = self.rester.get_entry_by_material_id( "mp-23", inc_structure=True, conventional_unit_cell=True) Ni = entry.structure self.assertEqual(Ni.lattice.a, Ni.lattice.b) self.assertEqual(Ni.lattice.a, Ni.lattice.c) self.assertEqual(Ni.lattice.alpha, 90) self.assertEqual(Ni.lattice.beta, 90) self.assertEqual(Ni.lattice.gamma, 90) # Ensure energy per atom is same primNi = self.rester.get_entry_by_material_id( "mp-23", inc_structure=True, conventional_unit_cell=False) self.assertEqual(primNi.energy_per_atom, entry.energy_per_atom) Ni = self.rester.get_structure_by_material_id( "mp-23", conventional_unit_cell=True) self.assertEqual(Ni.lattice.a, Ni.lattice.b) self.assertEqual(Ni.lattice.a, Ni.lattice.c) self.assertEqual(Ni.lattice.alpha, 90) self.assertEqual(Ni.lattice.beta, 90) self.assertEqual(Ni.lattice.gamma, 90) # Test case where convs are different from initial and final th = self.rester.get_structure_by_material_id( "mp-37", conventional_unit_cell=True) th_entry = self.rester.get_entry_by_material_id( "mp-37", inc_structure=True, conventional_unit_cell=True) th_entry_initial = self.rester.get_entry_by_material_id( "mp-37", inc_structure="initial", conventional_unit_cell=True) self.assertEqual(th, th_entry.structure) self.assertEqual(len(th_entry.structure), 4) self.assertEqual(len(th_entry_initial.structure), 2) # Test if the polymorphs of Fe are properly sorted # by e_above_hull when sort_by_e_above_hull=True Fe_entries = self.rester.get_entries("Fe", sort_by_e_above_hull=True) self.assertEqual(Fe_entries[0].data["e_above_hull"], 0) def test_get_pourbaix_entries(self): pbx_entries = self.rester.get_pourbaix_entries(["Fe"]) for pbx_entry in pbx_entries: self.assertTrue(isinstance(pbx_entry, PourbaixEntry)) # Ensure entries are pourbaix compatible pbx = PourbaixDiagram(pbx_entries) # Try binary system pbx_entries = self.rester.get_pourbaix_entries(["Fe", "Cr"]) pbx = PourbaixDiagram(pbx_entries) # TODO: Shyue Ping: I do not understand this test. You seem to # be grabbing Zn-S system, but I don't see proper test for anything, # including Na ref. This test also takes a long time. # Test Zn-S, which has Na in reference solids # pbx_entries = self.rester.get_pourbaix_entries(["Zn", "S"]) def test_get_exp_entry(self): entry = self.rester.get_exp_entry("Fe2O3") self.assertEqual(entry.energy, -825.5) def test_submit_query_delete_snl(self): s = Structure([[5, 0, 0], [0, 5, 0], [0, 0, 5]], ["Fe"], [[0, 0, 0]]) # d = self.rester.submit_snl( # [s, s], remarks=["unittest"], # authors="Test User <*****@*****.**>") # self.assertEqual(len(d), 2) # data = self.rester.query_snl({"about.remarks": "unittest"}) # self.assertEqual(len(data), 2) # snlids = [d["_id"] for d in data] # self.rester.delete_snl(snlids) # data = self.rester.query_snl({"about.remarks": "unittest"}) # self.assertEqual(len(data), 0) def test_get_stability(self): entries = self.rester.get_entries_in_chemsys(["Fe", "O"]) modified_entries = [] for entry in entries: # Create modified entries with energies that are 0.01eV higher # than the corresponding entries. if entry.composition.reduced_formula == "Fe2O3": modified_entries.append( ComputedEntry(entry.composition, entry.uncorrected_energy + 0.01, parameters=entry.parameters, entry_id="mod_{}".format(entry.entry_id))) rest_ehulls = self.rester.get_stability(modified_entries) all_entries = entries + modified_entries compat = MaterialsProjectCompatibility() all_entries = compat.process_entries(all_entries) pd = PhaseDiagram(all_entries) for e in all_entries: if str(e.entry_id).startswith("mod"): for d in rest_ehulls: if d["entry_id"] == e.entry_id: data = d break self.assertAlmostEqual(pd.get_e_above_hull(e), data["e_above_hull"]) def test_get_reaction(self): rxn = self.rester.get_reaction(["Li", "O"], ["Li2O"]) self.assertIn("Li2O", rxn["Experimental_references"]) def test_get_substrates(self): substrate_data = self.rester.get_substrates('mp-123', 5, [1, 0, 0]) substrates = [sub_dict['sub_id'] for sub_dict in substrate_data] self.assertIn("mp-2534", substrates) def test_get_surface_data(self): data = self.rester.get_surface_data("mp-126") # Pt self.assertIn("surfaces", data) surfaces = data["surfaces"] self.assertTrue(len(surfaces) > 0) surface = surfaces.pop() self.assertIn("miller_index", surface) self.assertIn("surface_energy", surface) self.assertIn("is_reconstructed", surface) data_inc = self.rester.get_surface_data("mp-126", inc_structures=True) self.assertIn("structure", data_inc["surfaces"][0]) def test_get_wulff_shape(self): ws = self.rester.get_wulff_shape("mp-126") self.assertTrue(isinstance(ws, WulffShape)) def test_get_cohesive_energy(self): ecoh = self.rester.get_cohesive_energy("mp-13") self.assertTrue(ecoh, 5.04543279) def test_get_interface_reactions(self): kinks = self.rester.get_interface_reactions("LiCoO2", "Li3PS4") self.assertTrue(len(kinks) > 0) kink = kinks[0] self.assertIn("energy", kink) self.assertIn("ratio", kink) self.assertIn("rxn", kink) self.assertTrue(isinstance(kink['rxn'], Reaction)) kinks_open_O = self.rester.get_interface_reactions( "LiCoO2", "Li3PS4", open_el="O", relative_mu=-1) self.assertTrue(len(kinks_open_O) > 0) with warnings.catch_warnings(record=True) as w: warnings.filterwarnings("always", message="The reactant.+") self.rester.get_interface_reactions("LiCoO2", "MnO9") self.assertTrue("The reactant" in str(w[-1].message)) def test_parse_criteria(self): crit = MPRester.parse_criteria("mp-1234 Li-*") self.assertIn("Li-O", crit["$or"][1]["chemsys"]["$in"]) self.assertIn({"task_id": "mp-1234"}, crit["$or"]) crit = MPRester.parse_criteria("Li2*") self.assertIn("Li2O", crit["pretty_formula"]["$in"]) self.assertIn("Li2I", crit["pretty_formula"]["$in"]) self.assertIn("CsLi2", crit["pretty_formula"]["$in"]) crit = MPRester.parse_criteria("Li-*-*") self.assertIn("Li-Re-Ru", crit["chemsys"]["$in"]) self.assertNotIn("Li-Li", crit["chemsys"]["$in"]) comps = MPRester.parse_criteria("**O3")["pretty_formula"]["$in"] for c in comps: self.assertEqual(len(Composition(c)), 3, "Failed in %s" % c) chemsys = MPRester.parse_criteria("{Fe,Mn}-O")["chemsys"]["$in"] self.assertEqual(len(chemsys), 2) comps = MPRester.parse_criteria("{Fe,Mn,Co}O")["pretty_formula"]["$in"] self.assertEqual(len(comps), 3, comps) #Let's test some invalid symbols self.assertRaises(ValueError, MPRester.parse_criteria, "li-fe") self.assertRaises(ValueError, MPRester.parse_criteria, "LO2") crit = MPRester.parse_criteria("POPO2") self.assertIn("P2O3", crit["pretty_formula"]["$in"])
# %% perovskites["volume"] = perovskites.structure.apply( lambda struct: struct.volume) perovskites.hist(column="volume", bins=50, log=True) # %% mpr = MPRester() perovskites["likely_mp_ids"] = perovskites.structure.progress_apply( mpr.find_structure) # %% mp_ids = perovskites.likely_mp_ids.explode().value_counts().index.to_list() es_above_hull = mpr.query({"material_id": {"$in": mp_ids}}, ["e_above_hull"]) # %% ax = perovskites.likely_mp_ids.apply(len).value_counts().plot(kind="bar", log=True) annotate_bar_heights() plt.savefig("likely_mp_ids_lens.pdf") # %% perovskites[["sg_symbol", "sg_number"]] = perovskites.progress_apply( lambda row: row.structure.get_space_group_info(), axis=1, result_type="expand") perovskites["crystal_system"] = perovskites.structure.progress_apply( lambda struct: SpacegroupAnalyzer(struct).get_crystal_system())