Exemplo n.º 1
0
 def setUp(self):
     entrylist = list()
     weights = list()
     comp = Composition("Mn2O3")
     entry = PDEntry(comp, 49)
     entrylist.append(PourbaixEntry(entry))
     weights.append(1.0)
     comp = Ion.from_formula("MnO4[-]")
     entry = IonEntry(comp, 25)
     entrylist.append(PourbaixEntry(entry))
     weights.append(0.25)
     comp = Composition("Fe2O3")
     entry = PDEntry(comp, 50)
     entrylist.append(PourbaixEntry(entry))
     weights.append(0.5)
     comp = Ion.from_formula("Fe[2+]")
     entry = IonEntry(comp, 15)
     entrylist.append(PourbaixEntry(entry))
     weights.append(2.5)
     comp = Ion.from_formula("Fe[3+]")
     entry = IonEntry(comp, 20)
     entrylist.append(PourbaixEntry(entry))
     weights.append(1.5)
     self.weights = weights
     self.entrylist = entrylist
     self.multientry = MultiEntry(entrylist, weights)
Exemplo n.º 2
0
    def __init__(self, entry_list, weights=None):
        """
        Initializes a MultiEntry.

        Args:
            entry_list: List of component PourbaixEntries
            weights: Weights associated with each entry. Default is None
        """
        if weights is None:
            self.weights = [1.0] * len(entry_list)
        else:
            self.weights = weights
        self.entrylist = entry_list
        self.correction = 0.0
        self.uncorrected_energy = 0.0
        self.npH = 0.0
        self.nPhi = 0.0
        self.nH2O = 0.0
        self.nM = 0.0
        self.name = ""
        self.entry_id = list()
        self.total_composition = Composition()
        for w, e in zip(self.weights, entry_list):
            self.uncorrected_energy += w * \
                e.uncorrected_energy
            self.correction += w * e.correction
            self.npH += w * e.npH
            self.nPhi += w * e.nPhi
            self.nH2O += w * e.nH2O
            self.nM += w * e.nM
            self.name += e.name + " + "
            self.entry_id.append(e.entry_id)
            self.total_composition += w * e.composition
        self.name = self.name[:-3]
Exemplo n.º 3
0
    def test_read_write_csv(self):
        Zn_solids = ["Zn", "ZnO", "ZnO2"]
        sol_g = [0.0, -3.338, -1.315]
        Zn_ions = ["Zn[2+]", "ZnOH[+]", "HZnO2[-]", "ZnO2[2-]", "ZnO"]
        liq_g = [-1.527, -3.415, -4.812, -4.036, -2.921]
        liq_conc = [1e-6, 1e-6, 1e-6, 1e-6, 1e-6]
        solid_entry = list()
        for sol in Zn_solids:
            comp = Composition(sol)
            delg = sol_g[Zn_solids.index(sol)]
            solid_entry.append(PourbaixEntry(PDEntry(comp, delg)))
        ion_entry = list()
        for ion in Zn_ions:
            comp_ion = Ion.from_formula(ion)
            delg = liq_g[Zn_ions.index(ion)]
            conc = liq_conc[Zn_ions.index(ion)]
            PoE = PourbaixEntry(IonEntry(comp_ion, delg))
            PoE.conc = conc
            ion_entry.append(PoE)
        entries = solid_entry + ion_entry
        PourbaixEntryIO.to_csv("pourbaix_test_entries.csv", entries)

        (elements,
         entries) = PourbaixEntryIO.from_csv("pourbaix_test_entries.csv")
        self.assertEqual(
            elements, [Element('Zn'),
                       Element('H'), Element('O')], "Wrong elements!")
        self.assertEqual(len(entries), 8, "Wrong number of entries!")
        os.remove("pourbaix_test_entries.csv")
Exemplo n.º 4
0
    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"])
Exemplo n.º 5
0
    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.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],
                         3.999999999]

        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)
Exemplo n.º 6
0
    def _get_int_removals_helper(self, spec_amts_oxi, redox_el, redox_els,
                                 numa):
        """
        This is a helper method for get_removals_int_oxid!

        Args:
            spec_amts_oxi - a dict of species to their amounts in the structure
            redox_el - the element to oxidize or reduce
            redox_els - the full list of elements that might be oxidized or reduced
            numa - a running set of numbers of A ion at integer oxidation steps
        Returns:
            a set of numbers A; steps for for oxidizing oxid_el first, then the other oxid_els in this list
        """

        # If a given redox_el has multiple oxidation states present in the structure, we want
        # to oxidize the lowest state or reduce the highest state
        if self.working_ion_charge < 0:
            oxid_old = max(spec.oxi_state for spec in spec_amts_oxi
                           if spec.symbol == redox_el.symbol)
            oxid_new = math.ceil(oxid_old - 1)
            lowest_oxid = defaultdict(lambda: 2, {"Cu": 1})
            # if this is not a valid solution, break out of here and don't add anything to the list
            if oxid_new < min(
                    os for os in Element(redox_el.symbol).oxidation_states
                    if os >= lowest_oxid[redox_el.symbol]):
                return numa
        else:
            oxid_old = min(spec.oxi_state for spec in spec_amts_oxi
                           if spec.symbol == redox_el.symbol)
            oxid_new = math.floor(oxid_old + 1)
            # if this is not a valid solution, break out of here and don't add anything to the list
            if oxid_new > redox_el.max_oxidation_state:
                return numa
        # update the spec_amts_oxi map to reflect that the redox took place
        spec_old = Species(redox_el.symbol, oxid_old)
        spec_new = Species(redox_el.symbol, oxid_new)
        specamt = spec_amts_oxi[spec_old]
        spec_amts_oxi = {
            sp: amt
            for sp, amt in spec_amts_oxi.items() if sp != spec_old
        }
        spec_amts_oxi[spec_new] = specamt
        spec_amts_oxi = Composition(spec_amts_oxi)

        # determine the amount of ion A in the structure needed for charge balance and add it to the list
        oxi_noA = sum(spec.oxi_state * spec_amts_oxi[spec]
                      for spec in spec_amts_oxi
                      if spec.symbol not in self.working_ion.symbol)
        a = max(0, -oxi_noA / self.working_ion_charge)
        numa = numa.union({a})

        # recursively try the other oxidation states
        if a == 0:
            return numa
        for red in redox_els:
            numa = numa.union(
                self._get_int_removals_helper(spec_amts_oxi.copy(), red,
                                              redox_els, numa))
        return numa
Exemplo n.º 7
0
 def setUp(self):
     comp = Composition("Mn2O3")
     self.solentry = PDEntry(comp, 49)
     ion = Ion.from_formula("MnO4-")
     self.ionentry = IonEntry(ion, 25)
     self.PxIon = PourbaixEntry(self.ionentry)
     self.PxSol = PourbaixEntry(self.solentry)
     self.PxIon.conc = 1e-4
Exemplo n.º 8
0
def ion_or_solid_comp_object(formula):
    """
    Returns either an ion object or composition object given
    a formula.

    Args:
        formula: String formula. Eg. of ion: NaOH(aq), Na[+];
            Eg. of solid: Fe2O3(s), Fe(s), Na2O

    Returns:
        Composition/Ion object
    """
    m = re.search(r"\[([^\[\]]+)\]|\(aq\)", formula)
    if m:
        comp_obj = Ion.from_formula(formula)
    elif re.search(r"\(s\)", formula):
        comp_obj = Composition(formula[:-3])
    else:
        comp_obj = Composition(formula)
    return comp_obj
Exemplo n.º 9
0
    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")
Exemplo n.º 10
0
    def _get_int_removals_helper(self, spec_amts_oxi, oxid_el, oxid_els, numa):
        """
        This is a helper method for get_removals_int_oxid!

        Args:
            spec_amts_oxi - a dict of species to their amounts in the structure
            oxid_el - the element to oxidize
            oxid_els - the full list of elements that might be oxidized
            numa - a running set of numbers of A cation at integer oxidation steps
        Returns:
            a set of numbers A; steps for for oxidizing oxid_el first, then the other oxid_els in this list
        """

        # If Mn is the oxid_el, we have a mixture of Mn2+, Mn3+, determine the minimum oxidation state for Mn
        #this is the state we want to oxidize!
        oxid_old = min([
            spec.oxi_state for spec in spec_amts_oxi
            if spec.symbol == oxid_el.symbol
        ])
        oxid_new = math.floor(oxid_old + 1)
        #if this is not a valid solution, break out of here and don't add anything to the list
        if oxid_new > oxid_el.max_oxidation_state:
            return numa

        #update the spec_amts_oxi map to reflect that the oxidation took place
        spec_old = Specie(oxid_el.symbol, oxid_old)
        spec_new = Specie(oxid_el.symbol, oxid_new)
        specamt = spec_amts_oxi[spec_old]
        spec_amts_oxi = {
            sp: amt
            for sp, amt in spec_amts_oxi.items() if sp != spec_old
        }
        spec_amts_oxi[spec_new] = specamt
        spec_amts_oxi = Composition(spec_amts_oxi)

        #determine the amount of cation A in the structure needed for charge balance and add it to the list
        oxi_noA = sum([
            spec.oxi_state * spec_amts_oxi[spec] for spec in spec_amts_oxi
            if spec.symbol not in self.cation.symbol
        ])
        a = max(0, -oxi_noA / self.cation_charge)
        numa = numa.union({a})

        #recursively try the other oxidation states
        if a == 0:
            return numa
        else:
            for oxid_el in oxid_els:
                numa = numa.union(
                    self._get_int_removals_helper(spec_amts_oxi.copy(),
                                                  oxid_el, oxid_els, numa))
            return numa
    def get_only_sites(self):
        """
        Get a copy of the structure with only the sites

        Args:

        Returns:
          Structure: Structure with all possible migrating ion sites

        """
        migrating_ion_sites = list(
            filter(
                lambda site: site.species == Composition(
                    {self.migrating_specie: 1}), self.structure.sites))
        return Structure.from_sites(migrating_ion_sites)
Exemplo n.º 12
0
    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_id", "total_magnetization"]
        expected_vals = [-191.33812137, -6.833504334642858, -2.5532843405078913,
                         28, {u'P': 4, u'Fe': 4, u'O': 16, u'Li': 4},
                         "LiFePO4", True, [u'Li', u'O', u'P', u'Fe'], 4, 0.0,
                         {u'Fe': 5.3, u'Li': 0.0, u'O': 0.0, u'P': 0.0}, True,
                         [540081, 19017], 3.4662026991351147, 56291, 16.0001687]

        for (i, prop) in enumerate(props):
            if prop not in ['hubbards', 'unit_cell_formula', 'elements']:
                val = self.rester.get_data(540081, prop=prop)[0][prop]
                self.assertAlmostEqual(expected_vals[i], val)
            elif prop == "elements":
                self.assertEqual(set(expected_vals[i]),
                                 set(self.rester.get_data(540081,
                                                          prop=prop)[0][prop]))
            else:
                self.assertEqual(expected_vals[i],
                                 self.rester.get_data(540081,
                                                      prop=prop)[0][prop])

        props = ['structure', 'initial_structure', 'final_structure', 'entry']
        for prop in props:
            obj = self.rester.get_data(540081, prop=prop)[0][prop]
            if prop.endswith("structure"):
                self.assertIsInstance(obj, Structure)
            elif prop == "entry":
                obj = self.rester.get_data(540081, 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")
Exemplo n.º 13
0
    def from_csv(filename):
        """
        Imports PourbaixEntries from a csv.

        Args:
            filename - Filename to import from.

        Returns:
            List of Entries
        """
        import csv
        reader = csv.reader(open(filename, "rb"),
                            delimiter=",",
                            quotechar="\"",
                            quoting=csv.QUOTE_MINIMAL)
        entries = list()
        header_read = False
        for row in reader:
            if not header_read:
                elements = row[1:(len(row) - 4)]
                header_read = True
            else:
                name = row[0]
                energy = float(row[-4])
                conc = float(row[-1])
                comp = dict()
                for ind in range(1, len(row) - 4):
                    if float(row[ind]) > 0:
                        comp[Element(elements[ind - 1])] = float(row[ind])
                phase_type = row[-3]
                if phase_type == "Ion":
                    PoE = PourbaixEntry(
                        IonEntry(Ion.from_formula(name), energy))
                    PoE.set_conc(conc)
                    PoE.set_name(name)
                    entries.append(PoE)
                else:
                    entries.append(
                        PourbaixEntry(PDEntry(Composition(comp), energy)))
        elements = [Element(el) for el in elements]
        return elements, entries
Exemplo n.º 14
0
    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")
Exemplo n.º 15
0
    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)
Exemplo n.º 16
0
def curate_cifstring(cifstring):
    """
    :return
    integrity_class
        3 can run all calculations
        2 can only run geometric analyses
        1 do not run any calculations (exception)
    outputs
        files written by this function
    structural_schemas
        structural_schemas['configuration']: the major config
        structural_schemas['molgraphs']: a list of unique molgraphs from the major config, rsorted by # of atoms
        structural_schemas['molsmiles']: a list of unique molecular smiles from the major config, rsorted by # of atoms
    identifier
        hashconfig(major_config)
    """
    integrity_class = 3
    outputs = []
    structural_schemas = OrderedDict()
    dp = DisParser(cifstring)
    try:
        print('--- begin DisParser.to_configs ---')
        dis_pstructure, dis_unwrap_str, dis_mols, config_infos = dp.to_configs(
            write_files=True, vanilla=True
        )  # if True writes conf_x.cif, configs is a list of pmg Structure
    except:
        emsg = 'ERROR: dp.to_configs failed!'
        print(emsg)
        raise CuratorError(emsg)
    if len(config_infos) not in [1, 2]:
        emsg = 'ERROR: vanilla to_configs found too many configs'
        print(emsg)
        raise CuratorError(emsg)
    disorder_class = dp.classification
    print('disorder class: {}'.format(disorder_class))
    print('--- end DisParser.to_configs ---\n')

    print('--- begin composition check ---')
    try:
        cif_comp = Composition(dp.cifdata['_chemical_formula_sum'])
        print('_chemical_formula_sum: {}'.format(cif_comp))
    except (KeyError, CompositionError) as e:
        cif_comp = None
        print(
            WEAK_WMSG.format(
                '_chemical_formula_sum does not exist or cannot be parsed'))
    try:
        comp_str = dp.cifdata['_chemical_formula_moiety']
        moiety_comps = [Composition(s) for s in comp_str.split(',')]
        moiety_comps = sorted(moiety_comps, key=lambda x: len(x), reverse=True)
        print('_chemical_formula_moiety:')
        for moiety_comp in moiety_comps:
            print('-- {}'.format(moiety_comp))
    except (KeyError, CompositionError) as e:
        print(
            WEAK_WMSG.format(
                '_chemical_formula_moiety does not exist or cannot be parsed'))
    major_config_structure, major_occu = config_infos[0]
    print('major config comps: {}'.format(major_config_structure.composition))
    print('major config occu: {}'.format(major_occu))
    if isinstance(cif_comp, Composition):
        if not major_config_structure.composition == cif_comp:
            print(
                WEAK_WMSG.format(
                    'major comps does not match _chemical_formula_sum'))
    try:
        minor_config_structure, minor_occu = config_infos[1]
        print('minor config comps: {}'.format(
            minor_config_structure.composition))
        print('minor config occu: {}'.format(minor_occu))
        major_minor_comps_match = minor_config_structure.composition == major_config_structure
        if major_minor_comps_match:
            print(WEAK_WMSG.format('minor and major comps do not match'))
    except IndexError:
        pass
    print('--- end composition check ---\n')

    print('--- begin major config check ---')
    try:
        major_config = Config.from_labeled_clean_pstructure(
            major_config_structure, major_occu)
    except:
        emsg = 'ERROR: cannot parse major config structure into a config!'
        print(emsg)
        raise CuratorError(emsg)
    structural_schemas['configuration'] = major_config.as_dict()
    major_config_cif = 'curated_major_config.cif'
    major_config.pstructure.to('cif', major_config_cif)
    outputs.append('{}/{}'.format(os.getcwd(), major_config_cif))
    if not major_config.molconformers_all_legit():
        emsg = 'ERROR: cannot convert all molconformers to rdkit mol'
        print(emsg)
        raise CuratorError(emsg)

    print('major config moiety comps:')
    mc: MolConformer
    max_nradicals = 0

    imc = 0
    for mc in major_config.molconformers:
        print('  -- imc {}: {}'.format(imc, mc.composition))
        try:
            rdmol, smiles, _, _ = mc.to_rdmol(charged_fragments=False)
            Chem.SanitizeMol(rdmol)
        except:
            print(
                WMSG.format(
                    'rdmol sanitize failed, integrity_class is set to 2'))
            if integrity_class > 2:
                integrity_class = 2
        nradicals = mc.is_missing_hydrogen()
        print('     missing hydrogen: {}'.format(nradicals))
        mc_xyzfils = 'curated_molconformer_{}_{}.xyz'.format(imc, nradicals)
        mc.to('xyz', mc_xyzfils)
        outputs.append(mc_xyzfils)
        if nradicals > max_nradicals:
            max_nradicals = nradicals
        imc += 1

    molsmiles = []
    for mc in sorted(major_config.molconformers,
                     key=lambda x: len(x),
                     reverse=True):
        # imol == imc, imol is not assigned based on len(mc), so use another for loop to do this
        molsmiles.append(mc.smiles)
    structural_schemas['molsmiles'] = list(set(molsmiles))

    if max_nradicals:
        print(
            WMSG.format(
                'major config missing hydrogen, integrity_class is set to 2'))
        if integrity_class > 2:
            integrity_class = 2

    unique_molgraphs = major_config.molgraph_set()
    structural_schemas['molgraphs'] = [
        umg.as_dict()
        for umg in sorted(list(unique_molgraphs), key=lambda x: len(x))
    ]
    if len(unique_molgraphs) > 1:
        emsg = 'ERROR: more than one unique molecule in the major config!'
        print(emsg)
        raise CuratorError(emsg)
    print('--- end major config check ---\n')

    print('integrity_class: {}'.format(integrity_class))
    return integrity_class, outputs, structural_schemas, major_config.hashconfig(
    )
Exemplo n.º 17
0
    def read(self):
        dis_pstructure, dis_unwrap_str, dis_mols, config_infos = self.dp.to_configs(write_files=False, vanilla=True)  # if True writes conf_x.cif, configs is a list of pmg Structure
        self.disorder_class = self.dp.classification
        self.results['disordered_pstructure'] = dis_unwrap_str
        self.results['disordered_pmgmols'] = dis_mols

        config_structures = []
        config_occupancies = []
        for item in config_infos:
            config_structures.append(item[0])
            config_occupancies.append(item[1])

        self.results['config_sturcutures'] = config_structures
        self.results['config_occupancies'] = config_occupancies


        configs = []
        missh = []
        for i in range(len(config_structures)):
            structure = config_structures[i]
            conf = Config.from_labeled_clean_pstructure(structure, occu=config_occupancies[i])
            config_missingh = False
            for conformer in conf.molconformers:
                if conformer.is_missing_hydrogen():
                    config_missingh = True
                    break
            if config_missingh:
                conf.pstructure.to('cif', '{}_mhconf_{}.cif'.format(self.identifier, i))
                warnings.warn('missing hydrogens in {}_mhconf_{}.cif'.format(self.identifier, i))
            configs.append(conf)
            missh.append(config_missingh)
        self.results['configurations'] = configs
        self.results['missingh'] = missh

        # these are checked against to configs[0]
        check_config = configs[0]
        try:
            self.results['n_unique_molecule'] = len(check_config.molgraph_set())
            self.results['n_molconformers'] = len(check_config.molconformers)
            self.results['all_molconformers_legit'] = check_config.molconformers_all_legit()
            self.results['disorder_location'] = self.where_is_disorder(check_config)
        except:
            warnings.warn('there are problems in readcif.results, some fileds will be missing!')
        
        try:
            comp = Composition(self.dp.cifdata['_chemical_formula_sum'])
            self.results['cif_sum_composition'] = comp
            if not all(self.results['cif_sum_composition'] == mc.composition for mc in check_config.molconformers):
                self.results['sum_composition_match'] = False
                print('cif_sum_composition: {}'.format(self.results['cif_sum_composition']))
                for mc in check_config.molconformers:
                    print('mc composition: {}'.format(mc.composition))
                warnings.warn('moiety sum composition does not match that specified in cif file!')
            else:
                self.results['sum_composition_match'] = True
        except (KeyError, CompositionError) as e:
            self.results['cif_sum_composition'] = None
            self.results['sum_composition_match'] = None

        try:
            comp_str = self.dp.cifdata['_chemical_formula_moiety']
            comps = [Composition(s) for s in comp_str.split(',')]
            comps = sorted(comps, key=lambda x:len(x), reverse=True)
            if len(comps) > 1:
                warnings.warn('more than 1 moiety from cif file! only the largest one is checked!')
            self.results['cif_moiety_composition'] = comps[0]
            if not all(self.results['cif_moiety_composition'] == mc.composition for mc in check_config.molconformers):
                self.results['moiety_composition_match'] = False
                print('cif_moiety_composition: {}'.format(self.results['cif_moiety_composition']))
                for mc in check_config.molconformers:
                    print('mc composition: {}'.format(mc.composition))
                warnings.warn('moiety composition does not match that specified in cif file!')
            else:
                self.results['moiety_composition_match'] = True
        except (KeyError, CompositionError) as e:
            self.results['cif_moiety_composition'] = None
            self.results['moiety_composition_match'] = None
Exemplo n.º 18
0
    def apply_transformation(self, structure, return_ranked_list=False):
        # Make a mutable structure first
        mods = Structure.from_sites(structure)
        for sp, spin in self.mag_species_spin.items():
            sp = get_el_sp(sp)
            oxi_state = getattr(sp, "oxi_state", 0)
            if spin:
                up = Specie(sp.symbol, oxi_state, {"spin": abs(spin)})
                down = Specie(sp.symbol, oxi_state, {"spin": -abs(spin)})
                mods.replace_species({
                    sp:
                    Composition({
                        up: self.order_parameter,
                        down: 1 - self.order_parameter
                    })
                })
            else:
                mods.replace_species(
                    {sp: Specie(sp.symbol, oxi_state, {"spin": spin})})

        if mods.is_ordered:
            return [mods] if return_ranked_list > 1 else mods

        enum_args = self.kwargs

        enum_args["min_cell_size"] = max(
            int(
                MagOrderingTransformation.determine_min_cell(
                    structure, self.mag_species_spin, self.order_parameter)),
            enum_args.get("min_cell_size", 1))

        max_cell = enum_args.get('max_cell_size')
        if max_cell:
            if enum_args["min_cell_size"] > max_cell:
                raise ValueError('Specified max cell size is smaller'
                                 ' than the minimum enumerable cell size')
        else:
            enum_args["max_cell_size"] = enum_args["min_cell_size"]

        t = EnumerateStructureTransformation(**enum_args)

        alls = t.apply_transformation(mods,
                                      return_ranked_list=return_ranked_list)

        try:
            num_to_return = int(return_ranked_list)
        except ValueError:
            num_to_return = 1

        if num_to_return == 1 or not return_ranked_list:
            return alls[0]["structure"] if num_to_return else alls

        m = StructureMatcher(comparator=SpinComparator())
        key = lambda x: SpacegroupAnalyzer(x, 0.1).get_space_group_number()
        out = []
        for _, g in groupby(sorted([d["structure"] for d in alls], key=key),
                            key):
            g = list(g)
            grouped = m.group_structures(g)
            out.extend([{
                "structure": g[0],
                "energy": self.energy_model.get_energy(g[0])
            } for g in grouped])

        self._all_structures = sorted(out, key=lambda d: d["energy"])

        return self._all_structures[0:num_to_return]
Exemplo n.º 19
0
Created on Wed Feb 28 15:40:02 2018

@author: jherfson
"""
from pymatgen.analysis.pourbaix.entry import PourbaixEntry, IonEntry  #, MultiEntry
from pymatgen.analysis.pourbaix.entry import PourbaixEntryIO
from pymatgen.analysis.phase_diagram import PDEntry
from pymatgen.core.ion import Ion
from pymatgen.core.structure import Composition

Zn_solids = ["Zn", "ZnO", "ZnO2"]
sol_g = [0.0, -3.338, -1.315]
Zn_ions = ["Zn[2+]", "ZnOH[+]", "HZnO2[-]", "ZnO2[2-]", "ZnO"]
liq_g = [-1.527, -3.415, -4.812, -4.036, -2.921]
liq_conc = [1e-6, 1e-6, 1e-6, 1e-6, 1e-6]
solid_entry = list()
for sol in Zn_solids:
    comp = Composition(sol)
    delg = sol_g[Zn_solids.index(sol)]
    solid_entry.append(PourbaixEntry(PDEntry(comp, delg)))
ion_entry = list()
for ion in Zn_ions:
    comp_ion = Ion.from_formula(ion)
    delg = liq_g[Zn_ions.index(ion)]
    conc = liq_conc[Zn_ions.index(ion)]
    PoE = PourbaixEntry(IonEntry(comp_ion, delg))
    PoE.conc = conc
    ion_entry.append(PoE)
entries = solid_entry + ion_entry
PourbaixEntryIO.to_csv("pourbaix_test_entries.csv", entries)