Example #1
0
 def OnQuery(self, event):
     key='NdHi2bTnJ9WDS1sU'
     a=MPRester(key)
     formula=''
     for element, number in self.extracted_elements:
         if element.startswith('^'):
             element=element.split('}')[-1]
         formula+='%s%g'%(element, number)
     res=a.get_data(formula)
     if type(res) is not list:
         return
     if len(res)>1:
         # more then one structure available, ask for user input to select appropriate
         items=[]
         for i, ri in enumerate(res):
             cs=ri['spacegroup']['crystal_system']
             sgs=ri['spacegroup']['symbol']
             frm=ri['full_formula']
             v=ri['volume']
             dens=ri['density']
             items.append(
                 '%i: %s (%s) | UC Formula: %s\n     Density: %s g/cm³ | UC Volume: %s'%
                 (i+1, sgs, cs, frm, dens, v))
             if ri['tags'] is not None:
                 items[-1]+='\n     '+';'.join(ri['tags'][:3])
         dia=wx.SingleChoiceDialog(self,
                                   'Several entries have been found, please select appropriate:',
                                   'Select correct database entry',
                                   items)
         if not dia.ShowModal()==wx.ID_OK:
             return None
         res=res[dia.GetSelection()]
     else:
         res=res[0]
     return self.analyze_cif(res['cif'])
Example #2
0
class MPResterTest(PymatgenTest):
    _multiprocess_shared_ = True

    def setUp(self):
        self.rester = MPRester()
        warnings.simplefilter("ignore")

    def tearDown(self):
        warnings.simplefilter("default")
        self.rester.session.close()

    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_xas_data(self):
        # Test getting XAS data
        data = self.rester.get_xas_data("mp-19017", "Li")
        self.assertEqual("mp-19017,Li", data['mid_and_el'])
        self.assertAlmostEqual(data['spectrum']['x'][0], 55.178, places=2)
        self.assertAlmostEqual(data['spectrum']['y'][0], 0.0164634, places=2)
        
    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 = self.TEST_FILES_DIR / 'Fe3O4.cif'
        data = m.find_structure(str(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, chunk_size=0)
        self.assertTrue(len(data) > 6)
        data = self.rester.query(
            criteria="*2O", properties=props, chunk_size=0)
        self.assertGreaterEqual(len(data), 52)
        self.assertIn("Li2O", (d["pretty_formula"] for d in data))

    def test_query_chunk_size(self):
        criteria = {"nelements": 2, "elements": "O"}
        props = ['pretty_formula']
        data1 = self.rester.query(
            criteria=criteria, properties=props, chunk_size=0)
        data2 = self.rester.query(
            criteria=criteria, properties=props, chunk_size=500)
        self.assertEqual({d['pretty_formula'] for d in data1},
                         {d['pretty_formula'] for d in data2})
        self.assertIn("Al2O3", {d['pretty_formula'] for d in data1})

    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", "Cr"])
        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
        one_surf = self.rester.get_surface_data('mp-129', miller_index=[-2, -3, 1])
        self.assertAlmostEqual(one_surf['surface_energy'], 2.99156963, places=2)
        self.assertArrayAlmostEqual(one_surf['miller_index'], [3, 2, 1])
        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_gb_data(self):
        mo_gbs = self.rester.get_gb_data(chemsys='Mo')
        self.assertEqual(len(mo_gbs), 10)
        mo_gbs_s5 = self.rester.get_gb_data(pretty_formula='Mo', sigma=5)
        self.assertEqual(len(mo_gbs_s5), 3)
        mo_s3_112 = self.rester.get_gb_data(material_id='mp-129', sigma=3,
                                            gb_plane=[1, -1, -2],
                                            include_work_of_separation=True)
        self.assertEqual(len(mo_s3_112), 1)
        gb_f = mo_s3_112[0]['final_structure']
        self.assertArrayAlmostEqual(gb_f.rotation_axis, [1, 1, 0])
        self.assertAlmostEqual(gb_f.rotation_angle, 109.47122, places=4)
        self.assertAlmostEqual(mo_s3_112[0]['gb_energy'], 0.47965, places=2)
        self.assertAlmostEqual(mo_s3_112[0]['work_of_separation'], 6.318144, places=2)
        self.assertIn("Mo24", gb_f.formula)
        hcp_s7 = self.rester.get_gb_data(material_id='mp-87', gb_plane=[0, 0, 0, 1],
                                         include_work_of_separation=True)
        self.assertAlmostEqual(hcp_s7[0]['gb_energy'], 1.12, places=2)
        self.assertAlmostEqual(hcp_s7[0]['work_of_separation'], 2.46, places=2)


    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_atomic", 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"])

    def test_include_user_agent(self):
        headers = self.rester.session.headers
        self.assertIn("user-agent", headers, msg="Include user-agent header by default")
        m = re.match(
            r"pymatgen/(\d+)\.(\d+)\.(\d+) \(Python/(\d+)\.(\d)+\.(\d+) ([^\/]*)/([^\)]*)\)",
            headers['user-agent'])
        self.assertIsNotNone(m, msg="Unexpected user-agent value {}".format(headers['user-agent']))
        self.assertEqual(m.groups()[:3], tuple(pmg_version.split(".")))
        self.assertEqual(
            m.groups()[3:6],
            tuple(str(n) for n in (sys.version_info.major, sys.version_info.minor, sys.version_info.micro))
        )
        self.rester = MPRester(include_user_agent=False)
        self.assertNotIn("user-agent", self.rester.session.headers, msg="user-agent header unwanted")
Example #3
0
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"])
Example #4
0
class MPResterTest(PymatgenTest):
    _multiprocess_shared_ = True

    def setUp(self):
        self.rester = MPRester()
        warnings.simplefilter("ignore")

    def tearDown(self):
        warnings.simplefilter("default")
        self.rester.session.close()

    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_xas_data(self):
        # Test getting XAS data
        data = self.rester.get_xas_data("mp-19017", "Li")
        self.assertEqual("mp-19017,Li", data["mid_and_el"])
        self.assertAlmostEqual(data["spectrum"]["x"][0], 55.178, places=2)
        self.assertAlmostEqual(data["spectrum"]["y"][0], 0.0164634, places=2)

    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",
        }
        mpid = "mp-1143"
        vals = requests.get(
            f"http://legacy.materialsproject.org/materials/{mpid}/json/")
        expected_vals = vals.json()

        for prop in props:
            if prop not in [
                    "hubbards",
                    "unit_cell_formula",
                    "elements",
                    "icsd_ids",
                    "task_ids",
            ]:
                val = self.rester.get_data(mpid, prop=prop)[0][prop]
                if prop in ["energy", "energy_per_atom"]:
                    prop = "final_" + prop
                self.assertAlmostEqual(expected_vals[prop], val, 2,
                                       f"Failed with property {prop}")
            elif prop in ["elements", "icsd_ids", "task_ids"]:
                upstream_vals = set(
                    self.rester.get_data(mpid, prop=prop)[0][prop])
                self.assertLessEqual(set(expected_vals[prop]), upstream_vals)
            else:
                self.assertEqual(
                    expected_vals[prop],
                    self.rester.get_data(mpid, prop=prop)[0][prop],
                )

        props = ["structure", "initial_structure", "final_structure", "entry"]
        for prop in props:
            obj = self.rester.get_data(mpid, prop=prop)[0][prop]
            if prop.endswith("structure"):
                self.assertIsInstance(obj, Structure)
            elif prop == "entry":
                obj = self.rester.get_data(mpid, 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 = self.TEST_FILES_DIR / "Fe3O4.cif"
        data = m.find_structure(str(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"]
        syms2 = "Li-Fe-O"
        entries = self.rester.get_entries_in_chemsys(syms)
        entries2 = self.rester.get_entries_in_chemsys(syms2)
        elements = {Element(sym) for sym in syms}
        for e in entries:
            self.assertIsInstance(e, ComputedEntry)
            self.assertTrue(set(e.composition.elements).issubset(elements))

        e1 = {i.entry_id for i in entries}
        e2 = {i.entry_id for i in entries2}
        self.assertTrue(e1 == e2)

        stable_entries = self.rester.get_entries_in_chemsys(
            syms, additional_criteria={"e_above_hull": {
                "$lte": 0.001
            }})
        self.assertTrue(len(stable_entries) < len(entries))

    def test_get_structure_by_material_id(self):
        s1 = self.rester.get_structure_by_material_id("mp-1")
        self.assertEqual(s1.formula, "Cs1")

        # requesting via task-id instead of mp-id
        self.assertWarns(Warning, self.rester.get_structure_by_material_id,
                         "mp-698856")

        # requesting unknown mp-id
        self.assertRaises(MPRestError,
                          self.rester.get_structure_by_material_id,
                          "mp-does-not-exist")

    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,
                                 chunk_size=0)
        self.assertTrue(len(data) > 6)
        data = self.rester.query(criteria="*2O",
                                 properties=props,
                                 chunk_size=0)
        self.assertGreaterEqual(len(data), 52)
        self.assertIn("Li2O", (d["pretty_formula"] for d in data))

    def test_query_chunk_size(self):
        criteria = {"nelements": 2, "elements": "O"}
        props = ["pretty_formula"]
        data1 = self.rester.query(criteria=criteria,
                                  properties=props,
                                  chunk_size=0)
        data2 = self.rester.query(criteria=criteria,
                                  properties=props,
                                  chunk_size=500)
        self.assertEqual({d["pretty_formula"]
                          for d in data1},
                         {d["pretty_formula"]
                          for d in data2})
        self.assertIn("Al2O3", {d["pretty_formula"] for d in data1})

    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):
        # test input chemsys as a list of elements
        pbx_entries = self.rester.get_pourbaix_entries(["Fe", "Cr"])
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))

        # test input chemsys as a string
        pbx_entries = self.rester.get_pourbaix_entries("Fe-Cr")
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))

        # fe_two_plus = [e for e in pbx_entries if e.entry_id == "ion-0"][0]
        # self.assertAlmostEqual(fe_two_plus.energy, -1.12369, places=3)
        #
        # feo2 = [e for e in pbx_entries if e.entry_id == "mp-25332"][0]
        # self.assertAlmostEqual(feo2.energy, 3.56356, places=3)
        #
        # # Test S, which has Na in reference solids
        # pbx_entries = self.rester.get_pourbaix_entries(["S"])
        # so4_two_minus = pbx_entries[9]
        # self.assertAlmostEqual(so4_two_minus.energy, 0.301511, places=3)

        # Ensure entries are Pourbaix compatible
        PourbaixDiagram(pbx_entries)

    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=f"mod_{entry.entry_id}",
                    ))
        rest_ehulls = self.rester.get_stability(modified_entries)
        all_entries = entries + modified_entries
        compat = MaterialsProject2020Compatibility()
        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
        one_surf = self.rester.get_surface_data("mp-129",
                                                miller_index=[-2, -3, 1])
        self.assertAlmostEqual(one_surf["surface_energy"],
                               2.99156963,
                               places=2)
        self.assertArrayAlmostEqual(one_surf["miller_index"], [3, 2, 1])
        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_gb_data(self):
        mo_gbs = self.rester.get_gb_data(chemsys="Mo")
        self.assertEqual(len(mo_gbs), 10)
        mo_gbs_s5 = self.rester.get_gb_data(pretty_formula="Mo", sigma=5)
        self.assertEqual(len(mo_gbs_s5), 3)
        mo_s3_112 = self.rester.get_gb_data(
            material_id="mp-129",
            sigma=3,
            gb_plane=[1, -1, -2],
            include_work_of_separation=True,
        )
        self.assertEqual(len(mo_s3_112), 1)
        gb_f = mo_s3_112[0]["final_structure"]
        self.assertArrayAlmostEqual(gb_f.rotation_axis, [1, 1, 0])
        self.assertAlmostEqual(gb_f.rotation_angle, 109.47122, places=4)
        self.assertAlmostEqual(mo_s3_112[0]["gb_energy"], 0.47965, places=2)
        self.assertAlmostEqual(mo_s3_112[0]["work_of_separation"],
                               6.318144,
                               places=2)
        self.assertIn("Mo24", gb_f.formula)
        hcp_s7 = self.rester.get_gb_data(material_id="mp-87",
                                         gb_plane=[0, 0, 0, 1],
                                         include_work_of_separation=True)
        self.assertAlmostEqual(hcp_s7[0]["gb_energy"], 1.12, places=2)
        self.assertAlmostEqual(hcp_s7[0]["work_of_separation"], 2.47, places=2)

    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_atomic", 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_download_info(self):
        material_ids = ["mvc-2970"]
        task_types = [TaskType.GGA_OPT, TaskType.GGAU_UNIFORM]
        file_patterns = ["vasprun*", "OUTCAR*"]
        meta, urls = self.rester.get_download_info(material_ids,
                                                   task_types=task_types,
                                                   file_patterns=file_patterns)
        self.assertDictEqual(
            dict(meta),
            {
                "mvc-2970": [{
                    "task_id": "mp-1738602",
                    "task_type": "GGA+U NSCF Uniform"
                }],
            },
        )
        self.assertEqual(
            urls[0],
            "https://nomad-lab.eu/prod/rae/api/raw/query?file_pattern=vasprun*&file_pattern=OUTCAR*&external_id=mp"
            "-1738602",
        )

    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, f"Failed in {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 test_include_user_agent(self):
        headers = self.rester.session.headers
        self.assertIn("user-agent",
                      headers,
                      msg="Include user-agent header by default")
        m = re.match(
            r"pymatgen/(\d+)\.(\d+)\.(\d+)\.?(\d+)? \(Python/(\d+)\.(\d)+\.(\d+) ([^\/]*)/([^\)]*)\)",
            headers["user-agent"],
        )
        self.assertIsNotNone(
            m, msg=f"Unexpected user-agent value {headers['user-agent']}")
        self.rester = MPRester(include_user_agent=False)
        self.assertNotIn("user-agent",
                         self.rester.session.headers,
                         msg="user-agent header unwanted")

    def test_database_version(self):

        with MPRester(notify_db_version=True) as mpr:
            db_version = mpr.get_database_version()

        self.assertIsInstance(db_version, str)
        yaml = YAML()
        with open(MP_LOG_FILE) as f:
            d = yaml.load(f)

        self.assertEqual(d["MAPI_DB_VERSION"]["LAST_ACCESSED"], db_version)
        self.assertIsInstance(d["MAPI_DB_VERSION"]["LOG"][db_version], int)

    def test_pourbaix_heavy(self):

        entries = self.rester.get_pourbaix_entries(["Li", "Mg", "Sn", "Pd"])
        _ = PourbaixDiagram(entries, nproc=4, filter_solids=False)
        entries = self.rester.get_pourbaix_entries(
            ["Ba", "Ca", "V", "Cu", "F"])
        _ = PourbaixDiagram(entries, nproc=4, filter_solids=False)
        entries = self.rester.get_pourbaix_entries(
            ["Ba", "Ca", "V", "Cu", "F", "Fe"])
        _ = PourbaixDiagram(entries, nproc=4, filter_solids=False)
        entries = self.rester.get_pourbaix_entries(
            ["Na", "Ca", "Nd", "Y", "Ho", "F"])
        _ = PourbaixDiagram(entries, nproc=4, filter_solids=False)

    def test_pourbaix_mpr_pipeline(self):

        data = self.rester.get_pourbaix_entries(["Zn"])
        pbx = PourbaixDiagram(data, filter_solids=True, conc_dict={"Zn": 1e-8})
        pbx.find_stable_entry(10, 0)

        data = self.rester.get_pourbaix_entries(["Ag", "Te"])
        pbx = PourbaixDiagram(data,
                              filter_solids=True,
                              conc_dict={
                                  "Ag": 1e-8,
                                  "Te": 1e-8
                              })
        self.assertEqual(len(pbx.stable_entries), 29)
        test_entry = pbx.find_stable_entry(8, 2)
        self.assertEqual(sorted(test_entry.entry_id), ["ion-10", "mp-499"])

        # Test against ion sets with multiple equivalent ions (Bi-V regression)
        entries = self.rester.get_pourbaix_entries(["Bi", "V"])
        pbx = PourbaixDiagram(entries,
                              filter_solids=True,
                              conc_dict={
                                  "Bi": 1e-8,
                                  "V": 1e-8
                              })
        self.assertTrue(
            all([
                "Bi" in entry.composition and "V" in entry.composition
                for entry in pbx.all_entries
            ]))
Example #5
0
class MPResterTest(PymatgenTest):
    _multiprocess_shared_ = True

    def setUp(self):
        self.rester = MPRester()
        warnings.simplefilter("ignore")

    def tearDown(self):
        warnings.simplefilter("default")
        self.rester.session.close()

    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_xas_data(self):
        # Test getting XAS data
        data = self.rester.get_xas_data("mp-19017", "Li")
        self.assertEqual("mp-19017,Li", data["mid_and_el"])
        self.assertAlmostEqual(data["spectrum"]["x"][0], 55.178, places=2)
        self.assertAlmostEqual(data["spectrum"]["y"][0], 0.0164634, places=2)

    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",
        ]

        expected_vals = [
            -191.7661349,
            -6.848790532142857,
            -2.5571951564625857,
            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.4708958823634912,
            [
                159107,
                154117,
                160776,
                99860,
                181272,
                166815,
                260571,
                92198,
                165000,
                155580,
                38209,
                161479,
                153699,
                260569,
                260570,
                200155,
                260572,
                181341,
                181342,
                72545,
                56291,
                97764,
                162282,
                155635,
            ],
            0,
        ]

        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, 2,
                                       "Failed with property %s" % prop)
            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")

        # 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 = self.TEST_FILES_DIR / "Fe3O4.cif"
        data = m.find_structure(str(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"]
        syms2 = "Li-Fe-O"
        entries = self.rester.get_entries_in_chemsys(syms)
        entries2 = self.rester.get_entries_in_chemsys(syms2)
        elements = set([Element(sym) for sym in syms])
        for e in entries:
            self.assertIsInstance(e, ComputedEntry)
            self.assertTrue(set(e.composition.elements).issubset(elements))

        e1 = set([i.entry_id for i in entries])
        e2 = set([i.entry_id for i in entries2])
        self.assertTrue(e1 == e2)

    def test_get_structure_by_material_id(self):
        s1 = self.rester.get_structure_by_material_id("mp-1")
        self.assertEqual(s1.formula, "Cs1")

        # requesting via task-id instead of mp-id
        self.assertWarns(Warning, self.rester.get_structure_by_material_id,
                         "mp-698856")

        # requesting unknown mp-id
        self.assertRaises(MPRestError,
                          self.rester.get_structure_by_material_id,
                          "mp-does-not-exist")

    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,
                                 chunk_size=0)
        self.assertTrue(len(data) > 6)
        data = self.rester.query(criteria="*2O",
                                 properties=props,
                                 chunk_size=0)
        self.assertGreaterEqual(len(data), 52)
        self.assertIn("Li2O", (d["pretty_formula"] for d in data))

    def test_query_chunk_size(self):
        criteria = {"nelements": 2, "elements": "O"}
        props = ["pretty_formula"]
        data1 = self.rester.query(criteria=criteria,
                                  properties=props,
                                  chunk_size=0)
        data2 = self.rester.query(criteria=criteria,
                                  properties=props,
                                  chunk_size=500)
        self.assertEqual({d["pretty_formula"]
                          for d in data1},
                         {d["pretty_formula"]
                          for d in data2})
        self.assertIn("Al2O3", {d["pretty_formula"] for d in data1})

    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):
        # test input chemsys as a list of elements
        pbx_entries = self.rester.get_pourbaix_entries(["Fe", "Cr"])
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))

        # test input chemsys as a string
        pbx_entries = self.rester.get_pourbaix_entries("Fe-Cr")
        for pbx_entry in pbx_entries:
            self.assertTrue(isinstance(pbx_entry, PourbaixEntry))

        fe_two_plus = [e for e in pbx_entries if e.entry_id == "ion-0"][0]
        self.assertAlmostEqual(fe_two_plus.energy,
                               -1.6228450214319294,
                               places=2)

        feo2 = [e for e in pbx_entries if e.entry_id == "mp-25332"][0]
        self.assertAlmostEqual(feo2.energy, 2.5523680849999995, places=2)

        # Test S, which has Na in reference solids
        pbx_entries = self.rester.get_pourbaix_entries(["S"])
        so4_two_minus = pbx_entries[9]
        self.assertAlmostEqual(so4_two_minus.energy,
                               0.0644980568750011,
                               places=2)

        # Ensure entries are pourbaix compatible
        PourbaixDiagram(pbx_entries)

    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
        one_surf = self.rester.get_surface_data("mp-129",
                                                miller_index=[-2, -3, 1])
        self.assertAlmostEqual(one_surf["surface_energy"],
                               2.99156963,
                               places=2)
        self.assertArrayAlmostEqual(one_surf["miller_index"], [3, 2, 1])
        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_gb_data(self):
        mo_gbs = self.rester.get_gb_data(chemsys="Mo")
        self.assertEqual(len(mo_gbs), 10)
        mo_gbs_s5 = self.rester.get_gb_data(pretty_formula="Mo", sigma=5)
        self.assertEqual(len(mo_gbs_s5), 3)
        mo_s3_112 = self.rester.get_gb_data(
            material_id="mp-129",
            sigma=3,
            gb_plane=[1, -1, -2],
            include_work_of_separation=True,
        )
        self.assertEqual(len(mo_s3_112), 1)
        gb_f = mo_s3_112[0]["final_structure"]
        self.assertArrayAlmostEqual(gb_f.rotation_axis, [1, 1, 0])
        self.assertAlmostEqual(gb_f.rotation_angle, 109.47122, places=4)
        self.assertAlmostEqual(mo_s3_112[0]["gb_energy"], 0.47965, places=2)
        self.assertAlmostEqual(mo_s3_112[0]["work_of_separation"],
                               6.318144,
                               places=2)
        self.assertIn("Mo24", gb_f.formula)
        hcp_s7 = self.rester.get_gb_data(material_id="mp-87",
                                         gb_plane=[0, 0, 0, 1],
                                         include_work_of_separation=True)
        self.assertAlmostEqual(hcp_s7[0]["gb_energy"], 1.12, places=2)
        self.assertAlmostEqual(hcp_s7[0]["work_of_separation"], 2.47, places=2)

    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_atomic", 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_download_info(self):
        material_ids = ["mp-32800", "mp-23494"]
        task_types = [TaskType.GGA_OPT, TaskType.GGA_UNIFORM]
        file_patterns = ["vasprun*", "OUTCAR*"]
        meta, urls = self.rester.get_download_info(material_ids,
                                                   task_types=task_types,
                                                   file_patterns=file_patterns)
        self.assertDictEqual(
            dict(meta),
            {
                "mp-23494": [{
                    "task_id": "mp-1752825",
                    "task_type": "GGA NSCF Uniform"
                }],
                "mp-32800": [{
                    "task_id": "mp-739635",
                    "task_type": "GGA NSCF Uniform"
                }],
            },
        )
        prefix = "http://labdev-nomad.esc.rzg.mpg.de/fairdi/nomad/mp/api/raw/query?"
        # previous test
        # ids = 'mp-23494,mp-688563,mp-32800,mp-746913'
        ids = "mp-1752825,mp-739635"
        self.assertEqual(
            urls[0],
            f"{prefix}file_pattern=vasprun*&file_pattern=OUTCAR*&external_id={ids}",
        )

    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 test_include_user_agent(self):
        headers = self.rester.session.headers
        self.assertIn("user-agent",
                      headers,
                      msg="Include user-agent header by default")
        m = re.match(
            r"pymatgen/(\d+)\.(\d+)\.(\d+)\.?(\d+)? \(Python/(\d+)\.(\d)+\.(\d+) ([^\/]*)/([^\)]*)\)",
            headers["user-agent"],
        )
        self.assertIsNotNone(m,
                             msg="Unexpected user-agent value {}".format(
                                 headers["user-agent"]))
        self.rester = MPRester(include_user_agent=False)
        self.assertNotIn("user-agent",
                         self.rester.session.headers,
                         msg="user-agent header unwanted")

    def test_database_version(self):

        with MPRester(notify_db_version=True) as mpr:
            db_version = mpr.get_database_version()

        self.assertIsInstance(db_version, str)

        with open(SETTINGS_FILE, "rt") as f:
            d = yaml.safe_load(f)

        self.assertEqual(d["MAPI_DB_VERSION"]["LAST_ACCESSED"], db_version)
        self.assertIsInstance(d["MAPI_DB_VERSION"]["LOG"][db_version], int)
Example #6
0
from pymatgen.ext.matproj import MPRester
import pandas as pd

a = MPRester("6vuOTNU35SWJmEsk")
n = 10000  #First n mp-IDs to check for elastic properties

df = pd.DataFrame(columns=[
    'mpID', 'Chemical Formula', 'no. of elements', 'Total no. of atoms',
    'Space Group', 'Space Group Number', 'Shear_Modulus', 'Bulk_Modulus',
    'density', 'band-gap', 'stability', 'icsd_ID'
])

for i in range(n):
    data = a.get_data("mp-" + str(i))
    if not data:
        print("Property list for mp-ID " + str(i) + " is empty.")
    elif data[0]['elasticity'] == None:
        print("Elastic properties for mp-ID " + str(i) + " is not calculated.")
    elif data[0]['elasticity']['G_VRH'] > 2:
        data = data[0]
        df = df.append(
            {
                'mpID': str(i),
                'Chemical Formula': data['full_formula'],
                'no. of elements': data['nelements'],
                'Total no. of atoms': data['nsites'],
                'Space Group': data['spacegroup']['symbol'],
                'Space Group Number': data['spacegroup']['number'],
                'Shear_Modulus': data['elasticity']['G_VRH'],
                'Bulk_Modulus': data['elasticity']['K_VRH'],
                'density': data['density'],
    def _get_data_from_materials_project(self, composition):
        mprester = MPRester(self.mapi_key)
        structure_data_list = mprester.get_data(chemsys_formula_id=composition)

        # Sort structures by stability (i.e. E above hull), and only return most stable compound data
        if len(structure_data_list) > 0:
            structure_data_list = sorted(
                structure_data_list,
                key=lambda e_above: e_above['e_above_hull'])
            structure_data_most_stable = structure_data_list[0]
        else:
            structure_data_most_stable = {}

        # Trim down the full Materials Project data dict to include only quantities relevant to make features
        structure_data_dict_condensed = {}
        property_list = [
            "G_Voigt_Reuss_Hill", "G_Reuss", "K_Voigt_Reuss_Hill", "K_Reuss",
            "K_Voigt", "G_Voigt", "G_VRH", "homogeneous_poisson",
            "poisson_ratio", "universal_anisotropy", "K_VRH",
            "elastic_anisotropy", "band_gap", "e_above_hull",
            "formation_energy_per_atom", "nelements", "energy_per_atom",
            "volume", "density", "total_magnetization", "number"
        ]
        elastic_property_list = [
            "G_Voigt_Reuss_Hill", "G_Reuss", "K_Voigt_Reuss_Hill", "K_Reuss",
            "K_Voigt", "G_Voigt", "G_VRH", "homogeneous_poisson",
            "poisson_ratio", "universal_anisotropy", "K_VRH",
            "elastic_anisotropy"
        ]
        if len(structure_data_list) > 0:
            for property in property_list:
                if property in elastic_property_list:
                    try:
                        structure_data_dict_condensed[
                            property] = structure_data_most_stable[
                                "elasticity"][property]
                    except TypeError:
                        structure_data_dict_condensed[property] = ''
                elif property == "number":
                    try:
                        structure_data_dict_condensed[
                            "Spacegroup_" +
                            property] = structure_data_most_stable[
                                "spacegroup"][property]
                    except TypeError:
                        structure_data_dict_condensed[property] = ''
                else:
                    try:
                        structure_data_dict_condensed[
                            property] = structure_data_most_stable[property]
                    except TypeError:
                        structure_data_dict_condensed[property] = ''
        else:
            for property in property_list:
                if property == "number":
                    structure_data_dict_condensed["Spacegroup_" +
                                                  property] = ''
                else:
                    structure_data_dict_condensed[property] = ''

        return structure_data_dict_condensed
Example #8
0
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"])
Example #9
0
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"])
## create the Materials megabase if it doesn't exist
if (not os.path.exists(megabase)):
    os.makedirs(megabase)

counter = 0
for i in f:
    print(i.rstrip())
    mpid = i.rstrip()
    c = True
    while c:
        try:
            filename = mpid + '.txt'
            if (os.path.isfile(os.path.join(database, filename))):
                break

            data = mpr.get_data(mpid)
            print(data)
            if (len(data) == 0
                ):  #there was one record that did not have any data in it...
                break
            data = data[0]
            structure = mpr.get_structures(mpid)[0].as_dict()
            jsondat1 = json.dumps(data)
            jsondat2 = json.dumps(structure)
            g = open(os.path.join(database, filename), 'w')
            g.write(jsondat1)
            g.write('\n')
            g.write(jsondat2)

            c = False
        except Exception as e:
Example #11
0
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"])
Example #12
0
class MatProjCalc:
	def __init__(self,oxide_dict={}):
		#dict to store MX bond energies after calculation. Avoid repeated lookups in MP
		self.calc_MX_bond_energy = {} 
		#dict to store formation enthalpies after looking up
		self.fH_dict = {
				('Ce','gas','exp',''):(417.1,'Formation enthalpy for Ce in gas phase includes exp data from phases: gas') #correction to MP entry: fH for Ce gas is negative in MP
					}
		self.mp = MPRester(os.environ['MATPROJ_API_KEY'])
		print("Created MatProjCalc instance")
		
	@property
	def common_anions(self):
		"""List of common anions"""
		return ['N','P','O','S','F','Cl','Br','I']
		
	@property
	def dissocation_energy(self):
		"""
		Bond dissociation energies for gases at 298K in kJ/mol
		Source: https://labs.chem.ucsb.edu/zakarian/armen/11---bonddissociationenergy.pdf
		"""
		return dict(N=945.33,P=490,O=498.34,S=429,F=156.9,Cl=242.58,Br=193.87,I=152.549,H=436.002)
		
	@property
	def mn_combos(self):
		"""
		Possible m-n pairs (m,n up to 4)
		"""
		return [(1,1),(1,2),(1,3),(1,4),(2,1),(2,3),(3,1),(3,2),(3,4),(4,1)]
		
	def possible_ionic_formulas(self,metal,anion,metal_ox_lim=None,anion_ox_state=None):
		"""
		Get possible binary ionic compound formulas for metal-anion pair
		
		Parameters:
		-----------
		metal: metal element symbol
		anion: anion element symbol
		metal_ox_lim: tuple of metal oxidation state limits (min, max)
		anion_ox_state: anion oxidation state. If None, will attempt to find the common oxidation state for the anion 
		"""
		#get common oxidation state for anion
		if anion_ox_state is None:
			anion_ox_state = [ox for ox in mg.Element(anion).common_oxidation_states if ox < 0]
			if len(anion_ox_state) > 1:
				raise Exception(f"Multiple common oxidation states for {anion}. Please specify anion_ox_state")
			else:
				anion_ox_state = anion_ox_state[0]
				
		if metal_ox_lim is None:
			metal_ox_lim = [0,np.inf]
		
		return [f'{metal}{m}{anion}{n}' for m,n in self.mn_combos if m/n <= -anion_ox_state and metal_ox_lim[0] <= -anion_ox_state*n/m <= metal_ox_lim[1]]
		
	def get_fH(self,formula, phase='solid', data_type='exp',silent=True,exclude_phases=[]):
		"""
		Get average experimental formation enthalpy for formula and phase
		
		Parameters:
		-----------
		formula: chemical formula string
		phase: phase string. Can be 'solid', 'liquid', 'gas', or a specific solid phase (e.g. 'monoclinic'). If 'solid', returns average across all solid phases
		"""
		#first check for corrected/saved data in fH_dict
		try:
			fH,msg = self.fH_dict[(formula,phase,data_type,','.join(exclude_phases))]
			if silent==False:
				#print('already calculated')
				print(msg)
		#if no entry exists, look up in MP
		except KeyError:
			results = self.mp.get_data(formula,data_type=data_type)
			if data_type=='exp':
				#results = self.mp.get_exp_thermo_data(formula)
				if phase=='solid':
					phase_results = [r for r in results if r.type=='fH' and r.phaseinfo not in ['liquid','gas']+exclude_phases]
				else:
					phase_results = [r for r in results if r.type=='fH' and r.phaseinfo==phase]
				phases = np.unique([r.phaseinfo for r in phase_results])
				fH = [r.value for r in phase_results]
				
			elif data_type=='vasp':
				if phase in ('liquid','gas'):
					raise ValueError('VASP data only valid for solid phases')
				elif phase=='solid':
					#get entry with lowest energy above hull
					srt_results = sorted(results,key=lambda x: x['e_above_hull'])
					phase_results = srt_results[0:1]
				else:
					phase_results = [r for r in results if r['spacegroup']['crystal_system']==phase]
				phases = np.unique([r['spacegroup']['crystal_system'] for r in phase_results])
				n_atoms = mg.Composition(formula).num_atoms
				#DFT formation energies given in eV per atom - need to convert to kJ/mol
				fH = [r['formation_energy_per_atom']*n_atoms*96.485 for r in phase_results]
				
			if len(fH)==0:
				raise LookupError('No {} data for {} in {} phase'.format(data_type,formula,phase))
			maxdiff = np.max(fH) - np.min(fH)
			if maxdiff > 15:
				warnings.warn('Max discrepancy of {} in formation enthalpies for {} exceeds limit'.format(maxdiff,formula))
			fH = np.mean(fH)
			
			msg = 'Formation enthalpy for {} in {} phase includes {} data from phases: {}'.format(formula,phase,data_type,', '.join(phases))
			if silent==False:
				print(msg)
			
			#store value and info message for future lookup
			self.fH_dict[(formula,phase,data_type,','.join(exclude_phases))] = (fH,msg)
			
		return fH

	def ionic_formula_from_ox_state(self,metal,anion,metal_ox_state,anion_ox_state=None,return_mn=False):
		"""
		Get binary ionic compound formula with reduced integer units based on oxidation state
		
		Parameters:
		-----------
		metal: metal element symbol
		anion: anion element symbol
		metal_ox_state: metal oxidation state
		anion_ox_state: anion oxidation state. If None, will attempt to find the common oxidation state for the anion
		return_mn: if True, return formula units for metal (m) and anion (n)
		
		Returns: chemical formula string MmXn, and m, n if return_mn=True
		"""
		#get common oxidation state for anion
		if anion_ox_state is None:
			anion_ox_state = [ox for ox in mg.Element(anion).common_oxidation_states if ox < 0]
			if len(anion_ox_state) > 1:
				raise Exception(f"Multiple common oxidation states for {anion}. Please specify anion_ox_state")
			else:
				anion_ox_state = anion_ox_state[0]
				
		#formula MmXn
		deno = gcd(metal_ox_state,-anion_ox_state)
		m = -anion_ox_state/deno
		n = metal_ox_state/deno
		formula = '{}{}{}{}'.format(metal,m,anion,n)
		if return_mn==False:
			return formula
		else:
			return formula, m, n
			
	def ox_states_from_binary_formula(self,formula,anion=None,anion_ox_state=None):
		"""
		Determine oxidation states from binary formula.
		Could also use mg.Composition.oxi_state_guesses(), but the logic used is more complex.

		Args:
			formula: chemical formula
			anion: Element symbol of anion. If None, search for common anion
			anion_ox_state: oxidation state of anion. If None, assume common oxidation state
		"""
		comp = mg.Composition(formula)
		if len(comp.elements) != 2:
			raise ValueError('Formula must be binary')
		# determine anion
		if anion is None:
			anion = np.intersect1d([e.name for e in comp.elements],self.common_anions)
			if len(anion) > 1:
				raise ValueError('Found multiple possible anions in formula. Please specify anion')
			elif len(anion)==0:
				raise ValueError('No common anions found in formula. Please specify anion')
			else:
				anion = anion[0]
		metal = np.setdiff1d(comp.elements,mg.Element(anion))[0].name
			
		#get common oxidation state for anion
		if anion_ox_state is None:
			anion_ox_state = [ox for ox in mg.Element(anion).common_oxidation_states if ox < 0]
			if len(anion_ox_state) > 1:
				raise Exception(f"Multiple common oxidation states for {anion}. Please specify anion_ox_state")
			else:
				anion_ox_state = anion_ox_state[0]
				
		metal_ox_state = -comp.get(anion)*anion_ox_state/comp.get(metal)
		
		return {metal:metal_ox_state,anion:anion_ox_state}

	def MX_bond_energy(self,formula,data_type='exp',ordered_formula=False,silent=True,exclude_phases=[]):
		"""
		Get metal-anion bond energy per mole of metal for binary ionic compound
		
		Parameters:
		-----------
		formula: chemical formula string
		ordered_formula: if true, assume that first element in formula is metal, and second is anion (i.e. MmXn)
		exclude_phases: phases to exclude from aggregate over all solid phases
		"""
		
		comp = mg.Composition(formula)
		formula = comp.reduced_formula
		try:
			#look up compound if already calculated
			abe,msg = self.calc_MX_bond_energy[(formula,data_type,','.join(exclude_phases))]
			if silent==False:
				#print('already calculated')
				print(msg)
		except KeyError:
			if len(comp.elements) != 2:
				raise Exception("Formula is not a binary compound")
				
			if ordered_formula is False:
				anions = [el.name for el in comp.elements if el.name in self.common_anions]
				if len(anions) == 0:
					raise Exception('No common anions found in formula. Use ordered formula to indicate metal and anion')
				elif len(anions) > 1:
					raise Exception('Multiple anions found in formula.  Use ordered formula to indicate metal and anion')
				else:
					anion = anions[0]
				metal = [el.name for el in comp.elements if el.name!=anion][0]
			elif ordered_formula is True:
				metal = comp.elements[0].name
				anion = comp.elements[1].name
				
			m = comp.get_el_amt_dict()[metal]
			n = comp.get_el_amt_dict()[anion]
				
			fH = self.get_fH(formula,data_type=data_type,silent=silent,exclude_phases=exclude_phases) #oxide formation enthalpy
			H_sub = self.get_fH(metal, phase='gas',silent=silent,exclude_phases=[]) #metal sublimation enthalpy - must be exp data (no vasp data for gas)
			#look up info messages from get_fH to store in dict
			msg = self.fH_dict[formula,'solid',data_type,','.join(exclude_phases)][1] + '\n'
			msg += self.fH_dict[metal,'gas','exp',''][1]
			DX2 = self.dissocation_energy[anion] #anion dissociation energy
			abe = (fH - m*H_sub - (n/2)*DX2)/m #M-O bond energy per mole of M
			self.calc_MX_bond_energy[(formula,data_type,','.join(exclude_phases))] = (abe,msg)
		return abe
		
	def citations(self):
		"""Cite Materials Project, Materials API, and pymatgen"""
		return [
				"@article{Jain2013,"
					"author = {Jain, Anubhav and Ong, Shyue Ping and Hautier, Geoffroy and Chen, Wei and Richards, William Davidson and Dacek, Stephen and Cholia, Shreyas and Gunter, Dan and Skinner, David and Ceder, Gerbrand and Persson, Kristin a.},"
					"doi = {10.1063/1.4812323},"
					"issn = {2166532X},"
					"journal = {APL Materials},"
					"number = {1},"
					"pages = {011002},"
					"title = {{The Materials Project: A materials genome approach to accelerating materials innovation}},"
					"url = {http://link.aip.org/link/AMPADS/v1/i1/p011002/s1\&Agg=doi},"
					"volume = {1},"
					"year = {2013}"
				"}",
				"@article{Ong_2015,"
					"doi = {10.1016/j.commatsci.2014.10.037},"
					"url = {http://dx.doi.org/10.1016/j.commatsci.2014.10.037},"
					"year = 2015,"
					"month = {feb},"
					"publisher = {Elsevier {BV}},"
					"volume = {97},"
					"pages = {209--215},"
					"author = {Shyue Ping Ong and Shreyas Cholia and Anubhav Jain and Miriam Brafman and Dan Gunter and Gerbrand Ceder and Kristin A. Persson},"
					"title = {The Materials Application Programming Interface ({API}): A simple, flexible and efficient {API} for materials data based on {REpresentational} State Transfer ({REST}) principles},"
					"journal = {Computational Materials Science}"
				"}",
				"@article{Ong2012b,"
					"author = {Ong, Shyue Ping and Richards, William Davidson and Jain, Anubhav and Hautier, Geoffroy and Kocher, Michael and Cholia, Shreyas and Gunter, Dan and Chevrier, Vincent L. and Persson, Kristin A. and Ceder, Gerbrand},"
					"doi = {10.1016/j.commatsci.2012.10.028},"
					"file = {:Users/shyue/Mendeley Desktop/Ong et al/Computational Materials Science/2013 - Ong et al. - Python Materials Genomics (pymatgen) A robust, open-source python library for materials analysis.pdf:pdf;:Users/shyue/Mendeley Desktop/Ong et al/Computational Materials Science/2013 - Ong et al. - Python Materials Genomics (pymatgen) A robust, open-source python library for materials analysis(2).pdf:pdf},"
					"issn = {09270256},"
					"journal = {Computational Materials Science},"
					"month = feb,"
					"pages = {314--319},"
					"title = {{Python Materials Genomics (pymatgen): A robust, open-source python library for materials analysis}},"
					"url = {http://linkinghub.elsevier.com/retrieve/pii/S0927025612006295},"
					"volume = {68},"
					"year = {2013}"
				"}"
				]
Example #13
0
class mp_query(object):

    def __init__(self, api_key):
        self.mpr = MPRester(api_key)

    def find_access_strings(self, search):

        data = self.mpr.get_data(search)
        material_ids = [datum['material_id'] for datum in data]
    
        return material_ids
    
    def mp_structure(self, material_id, standardize=True):

        struct = self.mpr.get_structure_by_material_id(material_id)

        if standardize:
            struct = SpacegroupAnalyzer(struct).get_conventional_standard_structure()
    
        return struct
    
    def make_structures(self, search):
        
        material_ids = self.find_access_strings(search)
    
        structures = []
        for ID in material_ids:
            struct = self.mp_structure(ID)
            structures.append(struct)
    
        return structures

    def search_summary(self, search, print_energies=True, barplot=False, write_files=False, format='cif'):
        
        data  = self.mpr.get_data(search)
        energies = []

        for datum in data:
            f  = datum['pretty_formula']
            sn = str(datum['spacegroup']['number'])
            ss = datum['spacegroup']['symbol']
            i  = datum['material_id']
            te = float(datum['energy'])
            ae = float(datum['energy_per_atom'])

            struct = self.mp_structure(i, standardize=False)
            ase_atoms = AseAtomsAdaptor.get_atoms(struct)
            composition = ase_atoms.get_chemical_formula()

            if write_files:
                write(f + '_' + sn + '.' + format, ase_atoms, format=format)

            energies.append((f, sn, ss, te, ae, composition))

        energies.sort(key = lambda x: x[4])
        
        if print_energies:
            print('formula spacegroup_number spacegroup_symbol total_energy energy_per_atom composition')
            for l in energies:
                print('{:7} {:<17} {:<17} {:<12.5f} {:<15f} {:<11}'.format(*l))

        if barplot:
            
            energies = np.asarray(energies)
            epa = np.array(map(float, energies[:,4]))
            epa -= min(epa)
            xticks = [i + '_' + j for i,j in energies[:,0:2]]
            ind = np.arange(len(energies))

            fig = plt.figure()
            plt.ylabel('Relative energy per atom / eV')
            plt.xlabel('Material')
            plt.xticks(ind, xticks, rotation=90)
            fig.set_size_inches(6.5,3)
            plt.savefig(search + '.tiff', dpi=300, bbox_inches='tight')