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)
def stable_mat_one_elem(pH, V, mat): """ Returns pymatgen pourbaix entry object corresponding to most stable species Args: pH: pH of system V: Potential with reference to the Standard Hydrogen Electrode (SHE) """ # | - - stable_mat_one_elem from pourdiag_single import pourdiag_single as pd_sgle from pymatgen.analysis.pourbaix.maker import PourbaixDiagram # Access entry Gibbs(pH, V) from pymatgen.analysis.pourbaix.analyzer import PourbaixAnalyzer pH = 0 V = 1 mat = 'Pt' all_entries = pd_sgle(mat) pourbaix = PourbaixDiagram(all_entries) PA = PourbaixAnalyzer(pourbaix) templist = [] for i in all_entries: templist.append(PA.g(i, pH, V)) minE = min(templist) for i in all_entries: if PA.g(i, pH, V) == minE: StableSpec = i return StableSpec # Returns the entries object of the stable species
def is_solid_phase(mat1, mat2, mat1_co=0.5): """Returns TRUE is there exists a all solid phase in the binary Pourbaix Diagram this means that the phase doesn't have any aqueous species. """ mat2_co = 1 - mat1_co pd_b = pd_entries(mat1, mat2) pd = PourbaixDiagram(pd_b, {mat1: mat1_co, mat2: mat2_co}) pl = PourbaixPlotter(pd) ppd = pl.pourbaix_plot_data([[-2, 16], [-3, 3]]) pd_lst = [] cnt = 0 for stable_entry in ppd[0]: pd_lst.append([]) pd_lst[cnt].append(ppd[0][stable_entry]) pd_lst[cnt].append(stable_entry.entrylist) cnt = cnt + 1 solidphase = False for i in pd_lst: if len(i[1]) == 1: if i[1][0].phase_type == 'Solid': solidphase = True if len(i[1]) == 2: if i[1][0].phase_type and i[1][1].phase_type == 'Solid': solidphase = True return solidphase
def setUp(self): module_dir = os.path.dirname(os.path.abspath(__file__)) (elements, entries) = PourbaixEntryIO.from_csv( os.path.join(module_dir, "test_entries.csv")) self.num_simplices = { "Zn(s)": 7, "ZnO2(s)": 7, "Zn[2+]": 4, "ZnO2[2-]": 4, "ZnHO2[-]": 4 } self.e_above_hull_test = {"ZnHO[+]": 0.0693, "ZnO(aq)": 0.0624} self.decomp_test = { "ZnHO[+]": { "ZnO(s)": 0.5, "Zn[2+]": 0.5 }, "ZnO(aq)": { "ZnO(s)": 1.0 } } self.pd = PourbaixDiagram(entries) self.analyzer = PourbaixAnalyzer(self.pd) self.multi_data = loadfn(os.path.join(test_dir, 'multicomp_pbx.json')) warnings.simplefilter("ignore")
def test_v_fe(self): v_fe_entries = self.multi_data['v_fe'] pd = PourbaixDiagram(v_fe_entries, comp_dict={"Fe": 0.5, "V": 0.5}) analyzer_vfe = PourbaixAnalyzer(pd) entries = sorted(pd._all_entries, key=lambda x: x.energy) self.assertAlmostEqual(entries[1].weights[1], 0.6666666666) self.assertAlmostEqual(entries[1].energy, -110.77582628499995) self.assertAlmostEqual(entries[100].energy, -20.685496454465955)
def setUp(self): module_dir = os.path.dirname(os.path.abspath(__file__)) (elements, entries) = PourbaixEntryIO.from_csv( os.path.join(module_dir, "test_entries.csv")) self._entries = entries self._pd = PourbaixDiagram(entries) self.list_of_stable_entries = [ "ZnO(s)", "Zn[2+]", "ZnO2(s)", "ZnHO2[-]", "ZnO2[2-]", "Zn(s)" ]
def test_get_entry_stability(self): stab = self.analyzer.get_entry_stability(self.pd.all_entries[0], pH=0, V=1) self.assertAlmostEqual(stab, 3.88159999) # binary pd_binary = PourbaixDiagram(self.multi_data['binary'], comp_dict = {"Ag": 0.5, "Te": 0.5}) analyzer_binary = PourbaixAnalyzer(pd_binary) ghull = analyzer_binary.get_entry_stability(self.multi_data['binary'][16], 0, -5)
def test_binary(self): # Test get_all_decomp_and_e_above_hull pd_binary = PourbaixDiagram(self.multi_data['binary'], comp_dict = {"Ag": 0.5, "Te": 0.5}) analyzer_binary = PourbaixAnalyzer(pd_binary) te_entry = pd_binary._unprocessed_entries[4] de, hull_e, entries = analyzer_binary.get_all_decomp_and_e_above_hull(te_entry) self.assertEqual(len(de), 10) self.assertEqual(len(hull_e), 10) self.assertAlmostEqual(hull_e[0], 5.4419792326439893)
def test_ternary(self): # Ternary te_entry = self.multi_data['ternary'][20] pd_ternary = PourbaixDiagram(self.multi_data['ternary'], comp_dict = {"Ag": 0.33333, "Te": 0.33333, "N": 0.33333}) analyzer_ternary = PourbaixAnalyzer(pd_ternary) de, hull_e, entries = analyzer_ternary.get_all_decomp_and_e_above_hull(te_entry) self.assertEqual(len(de), 116) self.assertEqual(len(hull_e), 116) self.assertAlmostEqual(hull_e[0], 29.2520325229)
def test_ternary(self): # Ternary te_entry = self.multi_data['ternary'][20] pd_ternary = PourbaixDiagram(self.multi_data['ternary'], comp_dict = {"Ag": 0.33333, "Te": 0.33333, "N": 0.33333}) analyzer_ternary = PourbaixAnalyzer(pd_ternary) de, hull_e, entries = analyzer_ternary.get_all_decomp_and_e_above_hull(te_entry) self.assertEqual(len(de), 116) self.assertEqual(len(hull_e), 116) tuples = zip(de, hull_e, entries) test_tuple = [t for t in tuples if t[2].name=='N2(s) + TeO4[2-] + Ag[2+]'][0] self.assertAlmostEqual(test_tuple[1], 50.337069095866745)
def test_plot_entry_stability(self): entry = self.pd.all_entries[0] plt = self.plotter.plot_entry_stability(entry, limits=[[-2, 14], [-3, 3]]) # binary system pd_binary = PourbaixDiagram(self.multi_data['binary'], comp_dict={ "Ag": 0.5, "Te": 0.5 }) binary_plotter = PourbaixPlotter(pd_binary) test_entry = pd_binary._unprocessed_entries[0] binary_plotter.plot_entry_stability(test_entry)
def test_binary(self): # Test get_all_decomp_and_e_above_hull pd_binary = PourbaixDiagram(self.multi_data['binary'], comp_dict = {"Ag": 0.5, "Te": 0.5}) analyzer_binary = PourbaixAnalyzer(pd_binary) te_entry = [e for e in pd_binary._unprocessed_entries if e.composition.formula == "Te3"][0] de, hull_e, entries = analyzer_binary.get_all_decomp_and_e_above_hull(te_entry) self.assertEqual(len(de), 10) self.assertEqual(len(hull_e), 10) # Find a specific multientry to test tuples = zip(de, hull_e, entries) test_tuple = [t for t in tuples if t[2].name=='Te(s) + Ag[2+]'][0] self.assertAlmostEqual(test_tuple[1], 5.1396968548627315)
def print_name(element1,element2,mat_co_1,entry): """ Print entry name if single, else print multientry """ str_name = "" entries= pd_entries(element1,element2) pourbaix = PourbaixDiagram(entries, {element1: mat_co_1, element2: 1- mat_co_1}) pd = pourbaix if isinstance(entry, MultiEntry): if len(entry.entrylist) > 2: return str(pd.qhull_entries.index(entry)) for e in entry.entrylist: str_name += (e.name) + " + " str_name = str_name[:-3] return str_name else: return entry.name
def phase_coord(entries, atom_comp, prim_elem=False): """ Produces a list of line segments corresponding to each phase area in a PD along with the PD entries corresponding to each area. The produced list is of the following form: list = [[[coordinate data], [pourbaix entry]], [], [] .... ] Args: entries: List of entries in a PD atom_comp: Composition of atom if system is binary, given as a fraction between 0 and 1. Corresponds to the element with lowest atomic number if prim_elem is left to its default prim_elem: Primary element to which the atom_comp is assigned """ # | - - phase_coord from pymatgen.analysis.pourbaix.maker import PourbaixDiagram from pymatgen.analysis.pourbaix.plotter import PourbaixPlotter from entry_methods import base_atom base_atoms = base_atom(entries) mat0 = base_atoms[0] if len(base_atoms) == 2: mat1 = base_atoms[1] else: mat1 = mat0 # If the primary element is declared then set the given composition to it if not prim_elem == False: for atom in base_atoms: if atom == prim_elem: mat0 = atom else: mat1 = atom pd = PourbaixDiagram(entries, {mat0: atom_comp, mat1: 1 - atom_comp}) pl = PourbaixPlotter(pd) ppd = pl.pourbaix_plot_data([[-2, 16], [-3, 3]]) #ppd == Pourbaix_Plot Data pd_lst = [] cnt = 0 for stable_entry in ppd[0]: pd_lst.append([]) pd_lst[cnt].append(ppd[0][stable_entry]) pd_lst[cnt].append(stable_entry.entrylist) cnt = cnt + 1 return pd_lst
def pourbaix_plot_data(element1,element2,mat_co_1,limits=None): """ Get stable/unstable species required to plot Pourbaix diagram. Args: limits: 2D list containing limits of the Pourbaix diagram of the form [[xlo, xhi], [ylo, yhi]] Returns: stable_entries, unstable_entries stable_entries: dict of lines. The keys are Pourbaix Entries, and lines are in the form of a list unstable_entries: list of unstable entries """ entries= pd_entries(element1,element2) pourbaix = PourbaixDiagram(entries, {element1: mat_co_1, element2: 1- mat_co_1}) pd = pourbaix analyzer = PourbaixAnalyzer(pd) # self._analyzer = analyzer if limits: analyzer.chempot_limits = limits chempot_ranges = analyzer.get_chempot_range_map(limits) # self.chempot_ranges = chempot_ranges stable_entries_list = collections.defaultdict(list) for entry in chempot_ranges: for line in chempot_ranges[entry]: x = [line.coords[0][0], line.coords[1][0]] y = [line.coords[0][1], line.coords[1][1]] coords = [x, y] stable_entries_list[entry].append(coords) unstable_entries_list = [entry for entry in pd.all_entries if entry not in pd.stable_entries] stable_entries_aq = [] stable_entries_solid = [] for entry in entries: entry_kj_per_mol = entry.energy * 96.4853 if entry.phase_type == "Ion": stable_entries_aq.append([entry.name,entry_kj_per_mol]) else: stable_entries_solid.append([entry.name,entry_kj_per_mol]) return stable_entries_list, unstable_entries_list, stable_entries_aq, stable_entries_solid
def oxidation_dissolution_product_0(i, j, scale): """ Creates Pourbaix Diagrams for single or binary systems """ #| - - oxidation_dissolution_product_0 # from pourdiag import pd_entries from pymatgen.analysis.pourbaix.maker import PourbaixDiagram from pymatgen.analysis.pourbaix.plotter import PourbaixPlotter from pd_screen_tools import phase_coord, phase_filter from stability_crit import most_stable_phase, oxidation_dissolution_product elem0 = i.symbol; elem1 = j.symbol mat_co_0 = 0.50 # Composition of 1st entry in elem_sys entr = pd_entries(elem0,elem1) pourbaix = PourbaixDiagram(entr,{elem0: mat_co_0,elem1: 1-mat_co_0}) plotter = PourbaixPlotter(pourbaix) coord = phase_coord(entr,mat_co_0) filt1 = phase_filter(coord,'metallic') filt2 = phase_filter(coord,'metallic_metallic') filt = filt1 + filt2 msp = most_stable_phase(filt,scale='RHE') tmp = oxidation_dissolution_product(coord,msp) if 'Ion' in tmp: entry_lst = 'dis' else: entry_lst = 'oxi' """ entry_lst = '' i_cnt = 0 for i in tmp: entry_lst = str(entry_lst)+'\n'+str(i) if i_cnt==0: entry_lst = entry_lst[1:] i_cnt=i_cnt+1 """ return entry_lst
def phase_coord(entries, atom_comp, prim_elem=None): """Produces a list of line segments corresponding to each phase area in a PD along with the PD entries corresponding to each area. The produced list is of the following form: list = [[[coordinate data], [pourbaix entry]], [], [] .... ] Parameters: ----------- entries: list entries in a PD atom_comp: float Composition of atom if system is binary, given as a fraction between 0 and 1. Corresponds to the element with lowest atomic number if prim_elem is left to its default prim_elem: str Primary element to which the atom_comp is assigned """ base_atoms = base_atom(entries) mat0 = base_atoms[0] if len(base_atoms) == 2: mat1 = base_atoms[1] else: mat1 = mat0 if prim_elem: for atom in base_atoms: if atom == prim_elem: mat0 = atom else: mat1 = atom pd = PourbaixDiagram(entries, {mat0: atom_comp, mat1: 1 - atom_comp}) pl = PourbaixPlotter(pd) ppd = pl.pourbaix_plot_data([[-2, 16], [-3, 3]]) pd_lst = [] for i, stable_entry in enumerate(ppd[0]): pd_lst += [[]] pd_lst[i] += [ppd[0][stable_entry]] if isinstance(stable_entry, PourbaixEntry): pd_lst[i] += [stable_entry] else: pd_lst[i] += [stable_entry.entrylist] return pd_lst
def is_solid_phase(mat1, mat2, mat1_co=0.5): """ Returns TRUE is there exists a all solid phase in the binary Pourbaix Diagram This means that the phase doesn't have any aqueous species Args: mat1: mat2: mat1_co: """ # | - - is_solid_phase from pourdiag import pourdiag # Returns Pourbaix entries for binary system from pymatgen.analysis.pourbaix.maker import PourbaixDiagram from pymatgen.analysis.pourbaix.plotter import PourbaixPlotter mat2_co = 1 - mat1_co pd_b = pourdiag(mat1, mat2) return pd_b pd = PourbaixDiagram(pd_b, {mat1: mat1_co, mat2: mat2_co}) pl = PourbaixPlotter(pd) ppd = pl.pourbaix_plot_data([[-2, 16], [-3, 3]]) #ppd == Pourbaix_Plot Data pd_lst = [] cnt = 0 for stable_entry in ppd[0]: pd_lst.append([]) pd_lst[cnt].append(ppd[0][stable_entry]) pd_lst[cnt].append(stable_entry.entrylist) cnt = cnt + 1 solidphase = False for i in pd_lst: if len(i[1]) == 1: if i[1][0].phase_type == 'Solid': solidphase = True if len(i[1]) == 2: if i[1][0].phase_type and i[1][1].phase_type == 'Solid': solidphase = True return solidphase
def setUp(self): module_dir = os.path.dirname(os.path.abspath(__file__)) (elements, entries) = PourbaixEntryIO.from_csv( os.path.join(module_dir, "test_entries.csv")) self.num_simplices = { "Zn(s)": 7, "ZnO2(s)": 7, "Zn[2+]": 4, "ZnO2[2-]": 4, "ZnHO2[-]": 4 } self.e_above_hull_test = {"ZnHO[+]": 0.0693, "ZnO(aq)": 0.0624} self.decomp_test = { "ZnHO[+]": { "ZnO(s)": 0.5, "Zn[2+]": 0.5 }, "ZnO(aq)": { "ZnO(s)": 1.0 } } self.pd = PourbaixDiagram(entries) self.plotter = PourbaixPlotter(self.pd)
def plot_pourbaix_diagram(metastability=0.0, ion_concentration=1e-6, fmt='pdf'): """ Creates a Pourbaix diagram for the material in the cwd. Args: metastability (float): desired metastable tolerance energy (meV/atom). <~50 is generally a sensible range to use. ion_concentration (float): in mol/kg. Sensible values are generally between 1e-8 and 1. fmt (str): matplotlib format style. Check the matplotlib docs for options. """ # Create a ComputedEntry object for the 2D material. composition = Structure.from_file('POSCAR').composition energy = Vasprun('vasprun.xml').final_energy cmpd = ComputedEntry(composition, energy) # Define the chemsys that describes the 2D compound. chemsys = ['O', 'H'] + [elt.symbol for elt in composition.elements if elt.symbol not in ['O', 'H']] # Pick out the ions pertaining to the 2D compound. ion_dict = dict() for elt in chemsys: if elt not in ['O', 'H'] and ION_FORMATION_ENERGIES[elt]: ion_dict.update(ION_FORMATION_ENERGIES[elt]) elements = [Element(elt) for elt in chemsys if elt not in ['O', 'H']] # Add "correction" for metastability cmpd.correction -= float(cmpd.composition.num_atoms)\ * float(metastability) / 1000.0 # Calculate formation energy of the compound from its end # members form_energy = cmpd.energy for elt in composition.as_dict(): form_energy -= CHEMICAL_POTENTIALS[elt] * cmpd.composition[elt] # Convert the compound entry to a pourbaix entry. # Default concentration for solid entries = 1 pbx_cmpd = PourbaixEntry(cmpd) pbx_cmpd.g0_replace(form_energy) pbx_cmpd.reduced_entry() # Add corrected ionic entries to the pourbaix diagram # dft corrections for experimental ionic energies: # Persson et.al PHYSICAL REVIEW B 85, 235438 (2012) pbx_ion_entries = list() # Get PourbaixEntry corresponding to each ion. # Default concentration for ionic entries = 1e-6 # ion_energy = ion_exp_energy + ion_correction * factor # where factor = fraction of element el in the ionic entry # compared to the reference entry for elt in elements: for key in ion_dict: comp = Ion.from_formula(key) if comp.composition[elt] != 0: factor = comp.composition[elt] energy = ion_dict[key] pbx_entry_ion = PourbaixEntry(IonEntry(comp, energy)) pbx_entry_ion.correction = ( ION_CORRECTIONS[elt.symbol] * factor ) pbx_entry_ion.conc = ion_concentration pbx_entry_ion.name = key pbx_ion_entries.append(pbx_entry_ion) # Generate and plot Pourbaix diagram # Each bulk solid/ion has a free energy g of the form: # g = g0_ref + 0.0591 * log10(conc) - nO * mu_H2O + # (nH - 2nO) * pH + phi * (-nH + 2nO + q) all_entries = [pbx_cmpd] + pbx_ion_entries total = sum([composition[el] for el in elements]) comp_dict = {el.symbol: composition[el]/total for el in elements} pourbaix_diagram = PourbaixDiagram(all_entries, comp_dict=comp_dict) plotter = PourbaixPlotter(pourbaix_diagram) # Plotting details... font = "serif" fig = plt.figure(figsize=(14, 9)) ax1 = fig.gca() ax1.set_xlim([0, 14]) ax1.set_xticklabels([int(t) for t in ax1.get_xticks()], fontname=font, fontsize=18) ax1.set_ylim(-2, 2) ax1.set_yticklabels(ax1.get_yticks(), fontname=font, fontsize=18) ax1.set_xlabel("pH", fontname=font, fontsize=18) ax1.set_ylabel("Potential vs. SHE (V)", fontname=font, fontsize=18) # Outline water's stability range. ax1.plot([0, 14], [0, -0.829], color="gray", linestyle="--", alpha=0.7, linewidth=2) ax1.plot([0, 14], [1.229, 0.401], color="gray", linestyle="--", alpha=0.7, linewidth=2) stable_entries = plotter.pourbaix_plot_data( limits=[[0, 14], [-2, 2]])[0] # Add coloring. colors = sb.color_palette("Set2", len(stable_entries)) i = 0 for entry in stable_entries: col = colors[i] i += 1 vertices = plotter.domain_vertices(entry) center_x = sum([v[0] for v in vertices])/len(vertices) center_y = sum([v[1] for v in vertices])/len(vertices) patch = Polygon(vertices, closed=True, fill=True, facecolor=col, linewidth=2, edgecolor="w") ax1.text(center_x, center_y, plotter.print_name(entry), verticalalignment="center", horizontalalignment="center", fontname=font, fontsize=18) ax1.add_patch(patch) plt.savefig("pourbaix.{}".format(fmt)) plt.close()
def setUp(self): module_dir = os.path.dirname(os.path.abspath(__file__)) (elements, entries) = PourbaixEntryIO.from_csv( os.path.join(module_dir, "test_entries.csv")) self._entries = entries self._pd = PourbaixDiagram(entries)
def plot_pourbaix_diagram(metastability=0.0, ion_concentration=1e-6, fmt='pdf'): """ Creates a Pourbaix diagram for the material in the cwd. Args: metastability (float): desired metastable tolerance energy (meV/atom). <~50 is generally a sensible range to use. ion_concentration (float): in mol/kg. Sensible values are generally between 1e-8 and 1. fmt (str): matplotlib format style. Check the matplotlib docs for options. """ # Create a ComputedEntry object for the 2D material. composition = Structure.from_file('POSCAR').composition energy = Vasprun('vasprun.xml').final_energy cmpd = ComputedEntry(composition, energy) # Define the chemsys that describes the 2D compound. chemsys = ['O', 'H'] + [ elt.symbol for elt in composition.elements if elt.symbol not in ['O', 'H'] ] # Pick out the ions pertaining to the 2D compound. ion_dict = dict() for elt in chemsys: if elt not in ['O', 'H'] and ION_FORMATION_ENERGIES[elt]: ion_dict.update(ION_FORMATION_ENERGIES[elt]) elements = [Element(elt) for elt in chemsys if elt not in ['O', 'H']] # Add "correction" for metastability cmpd.correction -= float(cmpd.composition.num_atoms)\ * float(metastability) / 1000.0 # Calculate formation energy of the compound from its end # members form_energy = cmpd.energy for elt in composition.as_dict(): form_energy -= CHEMICAL_POTENTIALS[elt] * cmpd.composition[elt] # Convert the compound entry to a pourbaix entry. # Default concentration for solid entries = 1 pbx_cmpd = PourbaixEntry(cmpd) pbx_cmpd.g0_replace(form_energy) pbx_cmpd.reduced_entry() # Add corrected ionic entries to the pourbaix diagram # dft corrections for experimental ionic energies: # Persson et.al PHYSICAL REVIEW B 85, 235438 (2012) pbx_ion_entries = list() # Get PourbaixEntry corresponding to each ion. # Default concentration for ionic entries = 1e-6 # ion_energy = ion_exp_energy + ion_correction * factor # where factor = fraction of element el in the ionic entry # compared to the reference entry for elt in elements: for key in ion_dict: comp = Ion.from_formula(key) if comp.composition[elt] != 0: factor = comp.composition[elt] energy = ion_dict[key] pbx_entry_ion = PourbaixEntry(IonEntry(comp, energy)) pbx_entry_ion.correction = (ION_CORRECTIONS[elt.symbol] * factor) pbx_entry_ion.conc = ion_concentration pbx_entry_ion.name = key pbx_ion_entries.append(pbx_entry_ion) # Generate and plot Pourbaix diagram # Each bulk solid/ion has a free energy g of the form: # g = g0_ref + 0.0591 * log10(conc) - nO * mu_H2O + # (nH - 2nO) * pH + phi * (-nH + 2nO + q) all_entries = [pbx_cmpd] + pbx_ion_entries pourbaix = PourbaixDiagram(all_entries) # Analysis features # panalyzer = PourbaixAnalyzer(pourbaix) # instability = panalyzer.get_e_above_hull(pbx_cmpd) plotter = PourbaixPlotter(pourbaix) plot = plotter.get_pourbaix_plot(limits=[[0, 14], [-2, 2]], label_domains=True) fig = plot.gcf() ax1 = fig.gca() # Add coloring to highlight the stability region for the 2D # material, if one exists. stable_entries = plotter.pourbaix_plot_data(limits=[[0, 14], [-2, 2]])[0] for entry in stable_entries: if entry == pbx_cmpd: col = plt.cm.Blues(0) else: col = plt.cm.rainbow( float(ION_COLORS[entry.composition.reduced_formula])) vertices = plotter.domain_vertices(entry) patch = Polygon(vertices, closed=True, fill=True, color=col) ax1.add_patch(patch) fig.set_size_inches((11.5, 9)) plot.tight_layout(pad=1.09) # Save plot if metastability: plot.suptitle('Metastable Tolerance =' ' {} meV/atom'.format(metastability), fontsize=20) plot.savefig('{}_{}.{}'.format(composition.reduced_formula, ion_concentration, fmt), transparent=True) else: plot.savefig('{}_{}.{}'.format(composition.reduced_formula, ion_concentration, fmt), transparent=True) plot.close()