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)
def get_e_above_hull(formula, energy): atoms = Atoms(formula) full_symbols = atoms.get_chemical_symbols() symbols, counts = np.unique(full_symbols, return_counts=True) # list(set(atoms.get_chemical_symbols())) with MPRester() as m: data = m.get_entries_in_chemsys(symbols, compatible_only=True, property_data=[ 'energy_per_atom', 'unit_cell_formula', 'pretty_formula' ]) PDentries = [] for d in data: d = d.as_dict() PDentries += [PDEntry(d['data']['unit_cell_formula'], d['energy'])] print(d['data']['pretty_formula'], d['energy']) PD = PhaseDiagram(PDentries) # Need to apply MP corrections to +U calculations # MP advanced correction + anion correction #print(energy * 2, energy * 2 + corr_energy * 2) PDE0 = PDEntry(formula, energy) e_hull = PD.get_e_above_hull(PDE0) return e_hull
def test_get_quasi_e_to_hull(self): for entry in self.pd.unstable_entries: # catch duplicated stable entries if entry.normalize( inplace=False) in self.pd.get_stable_entries_normed(): self.assertLessEqual( self.pd.get_quasi_e_to_hull(entry), 0, "Duplicated stable entries should have negative decomposition energy!" ) else: self.assertGreaterEqual( self.pd.get_quasi_e_to_hull(entry), 0, "Unstable entries should have positive decomposition energy!" ) for entry in self.pd.stable_entries: if entry.composition.is_element: self.assertEqual( self.pd.get_quasi_e_to_hull(entry), 0, "Stable elemental entries should have decomposition energy of zero!" ) else: self.assertLessEqual( self.pd.get_quasi_e_to_hull(entry), 0, "Stable entries should have negative decomposition energy!" ) novel_stable_entry = PDEntry("Li5FeO4", -999) self.assertLess( self.pd.get_quasi_e_to_hull(novel_stable_entry), 0, "Novel stable entries should have negative decomposition energy!") novel_unstable_entry = PDEntry("Li5FeO4", 999) self.assertGreater( self.pd.get_quasi_e_to_hull(novel_unstable_entry), 0, "Novel unstable entries should have positive decomposition energy!" ) duplicate_entry = PDEntry("Li2O", -14.31361175) scaled_dup_entry = PDEntry("Li4O2", -14.31361175 * 2) stable_entry = [e for e in self.pd.stable_entries if e.name == "Li2O"][0] self.assertEqual( self.pd.get_quasi_e_to_hull(duplicate_entry), self.pd.get_quasi_e_to_hull(stable_entry), "Novel duplicates of stable entries should have same decomposition energy!" ) self.assertEqual( self.pd.get_quasi_e_to_hull(scaled_dup_entry), self.pd.get_quasi_e_to_hull(stable_entry), "Novel scaled duplicates of stable entries should have same decomposition energy!" )
def _pd(structures, energies, ce): """ Generate a phase diagram with the structures and energies """ entries = [] for s, e in zip(structures, energies): entries.append(PDEntry(s.composition.element_composition, e)) max_e = max(entries, key=lambda e: e.energy_per_atom).energy_per_atom + 1000 for el in ce.structure.composition.keys(): entries.append(PDEntry(Composition({el: 1}).element_composition, max_e)) return PhaseDiagram(entries)
def get_convex_hull_area(self, composition_space): """ Prints out the area or volume of the convex hull defined by the organisms in the promotion set. """ # make a phase diagram of just the organisms in the promotion set # (on the lower convex hull) pdentries = [] for organism in self.promotion_set: pdentries.append( PDEntry(organism.composition, organism.total_energy)) compound_pd = CompoundPhaseDiagram(pdentries, composition_space.endpoints) # get the data for the convex hull qhull_data = compound_pd.qhull_data # for some reason, the last point is positive, so remove it hull_data = np.delete(qhull_data, -1, 0) # make a ConvexHull object from the hull data try: convex_hull = ConvexHull(hull_data) except: return None if len(composition_space.endpoints) == 2: return convex_hull.area else: return convex_hull.volume
class PDEntryTest(unittest.TestCase): def setUp(self): comp = Composition("LiFeO2") self.entry = PDEntry(comp, 53) self.gpentry = GrandPotPDEntry(self.entry, {Element("O"): 1.5}) def test_get_energy(self): self.assertEqual(self.entry.energy, 53, "Wrong energy!") self.assertEqual(self.gpentry.energy, 50, "Wrong energy!") def test_get_chemical_energy(self): self.assertEqual(self.gpentry.chemical_energy, 3, "Wrong energy!") def test_get_energy_per_atom(self): self.assertEqual(self.entry.energy_per_atom, 53.0 / 4, "Wrong energy per atom!") self.assertEqual(self.gpentry.energy_per_atom, 50.0 / 2, "Wrong energy per atom!") def test_get_name(self): self.assertEqual(self.entry.name, "LiFeO2", "Wrong name!") self.assertEqual(self.gpentry.name, "LiFeO2", "Wrong name!") def test_get_composition(self): comp = self.entry.composition expected_comp = Composition("LiFeO2") self.assertEqual(comp, expected_comp, "Wrong composition!") comp = self.gpentry.composition expected_comp = Composition("LiFe") self.assertEqual(comp, expected_comp, "Wrong composition!") def test_is_element(self): self.assertFalse(self.entry.is_element) self.assertFalse(self.gpentry.is_element) def test_to_from_dict(self): d = self.entry.as_dict() gpd = self.gpentry.as_dict() entry = PDEntry.from_dict(d) self.assertEqual(entry.name, "LiFeO2", "Wrong name!") self.assertEqual(entry.energy_per_atom, 53.0 / 4) gpentry = GrandPotPDEntry.from_dict(gpd) self.assertEqual(gpentry.name, "LiFeO2", "Wrong name!") self.assertEqual(gpentry.energy_per_atom, 50.0 / 2) d_anon = d.copy() del d_anon["name"] try: entry = PDEntry.from_dict(d_anon) except KeyError: self.fail("Should not need to supply name!") def test_str(self): self.assertIsNotNone(str(self.entry)) def test_read_csv(self): entries = EntrySet.from_csv(str(module_dir / "pdentries_test.csv")) self.assertEqual(entries.chemsys, {"Li", "Fe", "O"}, "Wrong elements!") self.assertEqual(len(entries), 490, "Wrong number of entries!")
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")
def from_csv(cls, filename: str): """ Imports PDEntries from a csv. Args: filename: Filename to import from. Returns: List of Elements, List of PDEntries """ with open(filename, "r", encoding="utf-8") as f: reader = csv.reader(f, delimiter=unicode2str(","), quotechar=unicode2str("\""), quoting=csv.QUOTE_MINIMAL) entries = list() header_read = False elements = None for row in reader: if not header_read: elements = row[1:(len(row) - 1)] header_read = True else: name = row[0] energy = float(row[-1]) comp = dict() for ind in range(1, len(row) - 1): if float(row[ind]) > 0: comp[Element(elements[ind - 1])] = float(row[ind]) entries.append(PDEntry(Composition(comp), energy, name)) return cls(entries)
def Create_Compositional_PhaseDiagram(self): phasediagram_entries = [] for compound in self.compounds_info.keys(): compound_composition = {} # Disregard elements not included in main compound if (compound in self.all_elements) and (compound not in self.elements_list): continue # Elements if compound in self.elements_list: compound_composition[compound] = self.compounds_info[compound][ "dft_" + compound] # Compounds else: for element in self.compounds_info[compound]["elements_list"]: compound_composition[element] = self.compounds_info[ compound]["dft_" + element] compound_total_energy = self.compounds_info[compound][ "total_energy"] phasediagram_entries.append( PDEntry(compound_composition, compound_total_energy)) self.phasediagram = PhaseDiagram(phasediagram_entries)
def get_decomp_product_ids(structures, competing_phases): # Create phase diagrams for each of the new structure chemical systems phase_diagrams = [] for competing in competing_phases: # Add competing phases entries = [ PDEntry(Composition(i['full_formula']), i['final_energy'], name=i['task_id']) for i in competing ] pd = PhaseDiagram(entries) phase_diagrams.append(pd) # Put new structures on phase diagram to get the set of decomp products all_decomp_prods = [] for new_struc, pd in zip(structures, phase_diagrams): comp = new_struc['structure'].composition.element_composition decomp_prods = pd.get_decomposition(comp=comp) all_decomp_prods.extend([i.name for i in decomp_prods]) # Reduce decomposition products to unique set all_decomp_prods = list(set(all_decomp_prods)) print('{} unique competing phases to calculate'.format( len(all_decomp_prods))) return (all_decomp_prods)
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
def setUp(self): comp = Composition("LiFeO2") entry = PDEntry(comp, 53) self.transformed_entry = TransformedPDEntry( { DummySpecies("Xa"): 1, DummySpecies("Xb"): 1 }, entry)
def test_to_from_dict(self): d = self.entry.as_dict() gpd = self.gpentry.as_dict() entry = PDEntry.from_dict(d) self.assertEqual(entry.name, "LiFeO2", "Wrong name!") self.assertEqual(entry.energy_per_atom, 53.0 / 4) gpentry = GrandPotPDEntry.from_dict(gpd) self.assertEqual(gpentry.name, "LiFeO2", "Wrong name!") self.assertEqual(gpentry.energy_per_atom, 50.0 / 2) d_anon = d.copy() del d_anon["name"] try: entry = PDEntry.from_dict(d_anon) except KeyError: self.fail("Should not need to supply name!")
def from_entries(cls, entries, working_ion_entry): """ Create a new InsertionElectrode. Args: entries: A list of ComputedStructureEntries (or subclasses) representing the different topotactic states of the battery, e.g. TiO2 and LiTiO2. working_ion_entry: A single ComputedEntry or PDEntry representing the element that carries charge across the battery, e.g. Li. """ _working_ion = working_ion_entry.composition.elements[0] _working_ion_entry = working_ion_entry # Prepare to make phase diagram: determine elements and set their energy # to be very high elements = set() for entry in entries: elements.update(entry.composition.elements) # Set an artificial energy for each element for convex hull generation element_energy = max([entry.energy_per_atom for entry in entries]) + 10 pdentries = [] pdentries.extend(entries) pdentries.extend( [PDEntry(Composition({el: 1}), element_energy) for el in elements]) # Make phase diagram to determine which entries are stable vs. unstable pd = PhaseDiagram(pdentries) def lifrac(e): return e.composition.get_atomic_fraction(_working_ion) # stable entries ordered by amount of Li asc _stable_entries = tuple( sorted([e for e in pd.stable_entries if e in entries], key=lifrac)) # unstable entries ordered by amount of Li asc _unstable_entries = tuple( sorted([e for e in pd.unstable_entries if e in entries], key=lifrac)) # create voltage pairs _vpairs = tuple([ InsertionVoltagePair.from_entries( _stable_entries[i], _stable_entries[i + 1], working_ion_entry, ) for i in range(len(_stable_entries) - 1) ]) return cls( voltage_pairs=_vpairs, working_ion_entry=_working_ion_entry, _stable_entries=_stable_entries, _unstable_entries=_unstable_entries, )
def test_str(self): self.assertEqual( str(self.entry), "PDEntry : Li1 Fe1 O2 (mp-757614) with energy = 53.0000") pde = self.entry.as_dict() del pde["name"] pde = PDEntry.from_dict(pde) self.assertEqual(str(pde), "PDEntry : Li1 Fe1 O2 with energy = 53.0000")
def is_in_composition_space_pd(self, organism, composition_space, constraints, pool): """ Returns a boolean indicating whether the organism is in the composition space. Whether composition space endpoints are allowed is determined by the value of constraints.allow_endpoints. Args: organism: the Organism to check composition_space: the CompositionSpace of the search constraints: the Constraints of the search pool: the Pool """ # cast the endpoints to PDEntries (just make up some energies) pdentries = [] for endpoint in composition_space.endpoints: pdentries.append(PDEntry(endpoint, -10)) pdentries.append(PDEntry(organism.composition, -10)) # make a CompoundPhaseDiagram and use it to check if the organism # is in the composition space from how many entries it returns composition_checker = CompoundPhaseDiagram(pdentries, composition_space.endpoints) if len( composition_checker.transform_entries( pdentries, composition_space.endpoints)[0]) == len( composition_space.endpoints): print('Organism {} lies outside the composition space '.format( organism.id)) return False # check the composition space endpoints if specified if not constraints.allow_endpoints and len(pool.to_list()) > 0: for endpoint in composition_space.endpoints: if endpoint.almost_equals( organism.composition.reduced_composition): print('Organism {} is at a composition space ' 'endpoint '.format(organism.id)) return False return True
def setUp(self): comp = Composition("LiFeO2") entry = PDEntry(comp, 53) terminal_compositions = ["Li2O", "FeO", "LiO8"] terminal_compositions = [Composition(c) for c in terminal_compositions] sp_mapping = OrderedDict() for i, comp in enumerate(terminal_compositions): sp_mapping[comp] = DummySpecies("X" + chr(102 + i)) self.transformed_entry = TransformedPDEntry(entry, sp_mapping)
def from_dict(cls, d): """ Invokes """ entry_type = d["entry_type"] if entry_type == "Ion": entry = IonEntry.from_dict(d["entry"]) else: entry = PDEntry.from_dict(d["entry"]) entry_id = d["entry_id"] concentration = d["concentration"] return PourbaixEntry(entry, entry_id, concentration)
def from_dict(cls, d): """ Returns a PourbaixEntry by reading in an Ion """ entry_type = d["entry type"] if entry_type == "Ion": entry = IonEntry.from_dict(d["entry"]) else: entry = PDEntry.from_dict(d["entry"]) correction = d["correction"] entry_id = d["entry_id"] return PourbaixEntry(entry, correction, entry_id)
def setUp(self): entries = list(EntrySet.from_csv(os.path.join(module_dir, "pdentries_test.csv"))) self.pd_ternary = PhaseDiagram(entries) self.plotter_ternary_mpl = PDPlotter(self.pd_ternary, backend="matplotlib") self.plotter_ternary_plotly = PDPlotter(self.pd_ternary, backend="plotly") entrieslio = [e for e in entries if "Fe" not in e.composition] self.pd_binary = PhaseDiagram(entrieslio) self.plotter_binary_mpl = PDPlotter(self.pd_binary, backend="matplotlib") self.plotter_binary_plotly = PDPlotter(self.pd_binary, backend="plotly") entries.append(PDEntry("C", 0)) self.pd_quaternary = PhaseDiagram(entries) self.plotter_quaternary_mpl = PDPlotter(self.pd_quaternary, backend="matplotlib") self.plotter_quaternary_plotly = PDPlotter(self.pd_quaternary, backend="plotly")
def compute_pd_values(self, organisms_list, composition_space): """ Constructs a convex hull from the provided organisms and sets the organisms' values to their distances from the convex hull. Returns the CompoundPhaseDiagram object computed from the organisms in organisms_list. Args: organisms_list: a list of Organisms whose values we need to compute composition_space: the CompositionSpace of the search """ # create a PDEntry object for each organism in the list of organisms pdentries = {} for organism in organisms_list: pdentries[organism.id] = PDEntry(organism.composition, organism.total_energy) # put the pdentries in a list pdentries_list = [] for organism_id in pdentries: pdentries_list.append(pdentries[organism_id]) # create a compound phase diagram object from the list of pdentries compound_pd = CompoundPhaseDiagram(pdentries_list, composition_space.endpoints) # transform the pdentries and put them in a dictionary, with the # organism id's as the keys transformed_pdentries = {} for org_id in pdentries: transformed_pdentries[org_id] = compound_pd.transform_entries( [pdentries[org_id]], composition_space.endpoints)[0][0] # put the values in a dictionary, with the organism id's as the keys values = {} for org_id in pdentries: values[org_id] = compound_pd.get_e_above_hull( transformed_pdentries[org_id]) # assign values to the organisms for organism in organisms_list: organism.value = values[organism.id] return compound_pd
def test_planar_inputs(self): e1 = PDEntry("H", 0) e2 = PDEntry("He", 0) e3 = PDEntry("Li", 0) e4 = PDEntry("Be", 0) e5 = PDEntry("B", 0) e6 = PDEntry("Rb", 0) pd = PhaseDiagram([e1, e2, e3, e4, e5, e6], map(Element, ["Rb", "He", "B", "Be", "Li", "H"])) self.assertEqual(len(pd.facets), 1)
def getPourbaixEntryfromMongo(elements): entries = [] unique_entries = {} elements_with_H_O = elements elements_with_H_O.append('H') elements_with_H_O.append('O') elements_with_H_O.sort() print(elements) allcombinations = getAllCombinations(elements_with_H_O) myclient = pymongo.MongoClient("mongodb://localhost:27017/") mydb = myclient["mp"] mycol = mydb["aml_all5"] for c in allcombinations: c.sort() p = '^' for i in c: p = p + i + '[0-9]+\s*' p = p + '$' mq = {"elements": c} md = mycol.find(mq) for x in md: print(x['pretty_formula']) fe = x['formation_energy_per_atom'] if fe is not None: try: fe = float(x['formation_energy_per_atom']) if unique_entries.get(x['pretty_formula']) is not None: if unique_entries[x['pretty_formula']] > x[ 'formation_energy_per_atom'] * x['natoms']: unique_entries[x['pretty_formula']] = x[ 'formation_energy_per_atom'] * x['natoms'] else: unique_entries[x['pretty_formula']] = x[ 'formation_energy_per_atom'] * x['natoms'] except ValueError: fe = 100.0 print(x['task_id'], x['pretty_formula'], fe) for u in unique_entries: print(u, unique_entries[u]) ent = PDEntry(Composition(u), unique_entries[u], attribute={'task_id': x['task_id']}) ent = PourbaixEntry(ent) #ent.phase_type='Solid' entries.append(ent) return entries
def Create_Compositional_PhaseDiagram(self): # Record all entries for the phase diagram phasediagram_entries = [] for compound in self.compounds_info.keys(): # Disregard elements not included in main compound if (compound in self.all_elements) and (compound not in self.elements_list): continue # Get the compound's composition compound_composition = {} if compound in self.elements_list: # Elemental material compound_composition[compound] = self.compounds_info[compound][ "dft_" + compound] else: # Compound material for element in self.compounds_info[compound]["elements_list"]: compound_composition[element] = self.compounds_info[ compound]["dft_" + element] # Get the compound's total energy compound_total_energy = self.compounds_info[compound][ "total_energy"] # Record to list of entries phasediagram_entries.append( PDEntry(compound_composition, compound_total_energy)) # Calculate compositional phase diagram (using pymatgen) # The output data structure is as follows: # lines --> List of arrays, each array is 2x2 for ternary (3x3 for quaternary, etc.), column vector represents point on phase diagram. # ex: array([ [0.3, 0.5], [1.0, 0.0] ]) is a line that goes from point [x=0.3, y=1.0] to point [x=0.5, y=0.0] # labels --> Dictionary with point-PDEntry pairs. self.pmg_phasediagram = PhaseDiagram(phasediagram_entries) self.pmg_phasediagram_plot_object = PDPlotter(self.pmg_phasediagram) (lines, labels, unstable) = self.pmg_phasediagram_plot_object.pd_plot_data # Record all lines and points of the compositional phase diagram self.lines = lines self.labels = labels
def get_phase_diagram_plot(self): """ Returns a phase diagram plot, as a matplotlib plot object. """ # set the font to Times, rendered with Latex plt.rc('font', **{'family': 'serif', 'serif': ['Times']}) plt.rc('text', usetex=True) # parse the composition space endpoints endpoints_line = self.lines[0].split() endpoints = [] for word in endpoints_line[::-1]: if word == 'endpoints:': break else: endpoints.append(Composition(word)) if len(endpoints) < 2: print('There must be at least 2 endpoint compositions to make a ' 'phase diagram.') quit() # parse the compositions and total energies of all the structures compositions = [] total_energies = [] for i in range(4, len(self.lines)): line = self.lines[i].split() compositions.append(Composition(line[1])) total_energies.append(float(line[2])) # make a list of PDEntries pdentries = [] for i in range(len(compositions)): pdentries.append(PDEntry(compositions[i], total_energies[i])) # make a CompoundPhaseDiagram compound_pd = CompoundPhaseDiagram(pdentries, endpoints) # make a PhaseDiagramPlotter pd_plotter = PDPlotter(compound_pd, show_unstable=50) return pd_plotter.get_plot(label_unstable=False)
def from_csv(filename): """ Imports PourbaixEntries from a csv. Args: filename: Filename to import from. Returns: List of Entries """ with open(filename, "rt") as f: reader = csv.reader(f, delimiter=unicode2str(","), quotechar=unicode2str("\""), 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 elif row: 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.conc = conc PoE.name = name entries.append(PoE) else: entries.append( PourbaixEntry(PDEntry(Composition(comp), energy))) elements = [Element(el) for el in elements] return elements, entries
def get_convex_hull_area(self, composition_space): """ Returns the area/volume of the current convex hull. Args: composition_space: the CompositionSpace of the search """ # check if the initial population contains organisms at all the # endpoints of the composition space if self.has_endpoints(composition_space) and \ self.has_non_endpoint(composition_space): # compute and print the area or volume of the convex hull pdentries = [] for organism in self.initial_population: pdentries.append( PDEntry(organism.composition, organism.total_energy)) compound_pd = CompoundPhaseDiagram(pdentries, composition_space.endpoints) # get the data for the convex hull qhull_data = compound_pd.qhull_data # for some reason, the last point is positive, so remove it hull_data = np.delete(qhull_data, -1, 0) # make a ConvexHull object from the hull data # Sometime this fails, saying that only two points were given to # construct the convex hull, even though the if statement above # checks that there are enough points. try: convex_hull = ConvexHull(hull_data) except: return None if len(composition_space.endpoints) == 2: return convex_hull.area else: return convex_hull.volume
def update_entries_store(rows): if rows is None: raise PreventUpdate entries = [] for row in rows: try: comp = Composition(row["Formula"]) energy = row["Formation Energy (eV/atom)"] if row["Material ID"] is None: attribute = "Custom Entry" else: attribute = row["Material ID"] entry = PDEntry(comp, float(energy) * comp.num_atoms, attribute=attribute) entries.append(entry) except: pass if not entries: raise PreventUpdate return self.to_data(entries)
def update_entries_store(rows): if rows is None: raise PreventUpdate entries = [] for row in rows: try: comp = Composition(row["Formula"]) energy = row["Formation Energy (eV/atom)"] if row["Material ID"] is None: attribute = "Custom Entry" else: attribute = row["Material ID"] # create new entry object containing mpid as attribute (to combine with custom entries) entry = PDEntry(comp, float(energy) * comp.num_atoms, attribute=attribute) entries.append(entry) except: continue if not entries: raise PreventUpdate return entries
def test_1d_pd(self): entry = PDEntry("H", 0) pd = PhaseDiagram([entry]) decomp, e = pd.get_decomp_and_e_above_hull(PDEntry("H", 1)) self.assertAlmostEqual(e, 1) self.assertAlmostEqual(decomp[entry], 1.0)