From 9e400f2c91a5d84aa67eaef060e0c70512a70567 Mon Sep 17 00:00:00 2001 From: Janosh Riebesell Date: Mon, 29 May 2023 12:31:06 -0700 Subject: [PATCH] Tweak variable names (#3019) * use modern f"{float:+}" for explicit + signs * fix tests * fix use of formula_double_format * fix reduced_form = "".join(reduced_form + polyanion) # type: ignore E TypeError: sequence item 3: expected str instance, int found * fix for ads in ads_strs: > label += f"{ads:+}" E ValueError: Sign not allowed in string format specifier --- .../coordination_geometries.py | 14 ++---- .../coordination_geometry_finder.py | 12 ++--- pymatgen/analysis/graphs.py | 18 +++---- pymatgen/analysis/phase_diagram.py | 2 +- pymatgen/analysis/surface_analysis.py | 42 ++++++++-------- .../command_line/tests/test_mcsqs_caller.py | 12 ++--- pymatgen/core/composition.py | 15 +++--- pymatgen/core/ion.py | 6 +-- pymatgen/core/operations.py | 8 ++- pymatgen/core/periodic_table.py | 23 +++------ pymatgen/core/structure.py | 24 ++++----- pymatgen/core/tests/test_composition.py | 2 +- pymatgen/core/tests/test_ion.py | 2 +- pymatgen/core/tests/test_operations.py | 34 ++++++------- pymatgen/core/tests/test_structure.py | 8 +-- pymatgen/electronic_structure/plotter.py | 12 +++-- pymatgen/io/lmto.py | 15 ++---- pymatgen/io/lobster/lobsterenv.py | 16 +++--- pymatgen/symmetry/analyzer.py | 6 +-- pymatgen/symmetry/structure.py | 50 ++++++++----------- .../tests/test_advanced_transformations.py | 18 +++---- pymatgen/util/string.py | 15 ++---- pymatgen/util/tests/test_string.py | 6 +-- 23 files changed, 163 insertions(+), 197 deletions(-) diff --git a/pymatgen/analysis/chemenv/coordination_environments/coordination_geometries.py b/pymatgen/analysis/chemenv/coordination_environments/coordination_geometries.py index 587c289084a..519382c5a52 100644 --- a/pymatgen/analysis/chemenv/coordination_environments/coordination_geometries.py +++ b/pymatgen/analysis/chemenv/coordination_environments/coordination_geometries.py @@ -337,7 +337,7 @@ def from_dict(cls, dd): Returns: a SeparationPlane algorithm. """ eop = ( - [np.array(eoperm) for eoperm in dd["explicit_optimized_permutations"]] + [np.array(eo_perm) for eo_perm in dd["explicit_optimized_permutations"]] if ("explicit_optimized_permutations" in dd and dd["explicit_optimized_permutations"] is not None) else None ) @@ -356,9 +356,9 @@ def from_dict(cls, dd): def __str__(self): out = "Separation plane algorithm with the following reference separation :\n" - out += f"[{'-'.join(str(pp) for pp in [self.point_groups[0]])}] | " - out += f"[{'-'.join(str(pp) for pp in [self.plane_points])}] | " - out += f"[{'-'.join(str(pp) for pp in [self.point_groups[1]])}]" + out += f"[{'-'.join(map(str, [self.point_groups[0]]))}] | " + out += f"[{'-'.join(map(str, [self.plane_points]))}] | " + out += f"[{'-'.join(map(str, [self.point_groups[1]]))}]" return out @@ -451,11 +451,7 @@ def double_cap_hints(self, hints_info): new_site_voronoi_indices2.remove(second_cap_voronoi_index) new_site_voronoi_indices3.remove(first_cap_voronoi_index) new_site_voronoi_indices3.remove(second_cap_voronoi_index) - return [ - new_site_voronoi_indices1, - new_site_voronoi_indices2, - new_site_voronoi_indices3, - ] + return new_site_voronoi_indices1, new_site_voronoi_indices2, new_site_voronoi_indices3 def triple_cap_hints(self, hints_info): """ diff --git a/pymatgen/analysis/chemenv/coordination_environments/coordination_geometry_finder.py b/pymatgen/analysis/chemenv/coordination_environments/coordination_geometry_finder.py index 2c5539489ef..c2f8039d3cc 100644 --- a/pymatgen/analysis/chemenv/coordination_environments/coordination_geometry_finder.py +++ b/pymatgen/analysis/chemenv/coordination_environments/coordination_geometry_finder.py @@ -1031,16 +1031,16 @@ def setup_test_perfect_environment( RR = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] else: RR = random_rotation - newcoords = [] + new_coords = [] for cc in coords: newcc = np.dot(RR, cc).T - newcoords.append(newcc.ravel()) - coords = newcoords - newcoords = [] + new_coords.append(newcc.ravel()) + coords = new_coords + new_coords = [] for cc in neighb_coords: newcc = np.dot(RR, cc.T) - newcoords.append(newcc.ravel()) - neighb_coords = newcoords + new_coords.append(newcc.ravel()) + neighb_coords = new_coords # Translating the test environment if random_translation == "RANDOM": diff --git a/pymatgen/analysis/graphs.py b/pymatgen/analysis/graphs.py index 9ad1ce4c3a5..32fb04cdf94 100644 --- a/pymatgen/analysis/graphs.py +++ b/pymatgen/analysis/graphs.py @@ -2688,24 +2688,20 @@ def as_dict(self): with using `to_dict_of_dicts` from NetworkX to store graph information. """ - d = { - "@module": type(self).__module__, - "@class": type(self).__name__, - "molecule": self.molecule.as_dict(), - "graphs": json_graph.adjacency_data(self.graph), - } - - return d + dct = {"@module": type(self).__module__, "@class": type(self).__name__} + dct["molecule"] = self.molecule.as_dict() + dct["graphs"] = json_graph.adjacency_data(self.graph) + return dct @classmethod - def from_dict(cls, d): + def from_dict(cls, dct): """ As in :class:`pymatgen.core.Molecule` except restoring graphs using `from_dict_of_dicts` from NetworkX to restore graph information. """ - m = Molecule.from_dict(d["molecule"]) - return cls(m, d["graphs"]) + m = Molecule.from_dict(dct["molecule"]) + return cls(m, dct["graphs"]) @classmethod def _edges_to_string(cls, g): diff --git a/pymatgen/analysis/phase_diagram.py b/pymatgen/analysis/phase_diagram.py index 6c825d81164..272b2ab5fd0 100644 --- a/pymatgen/analysis/phase_diagram.py +++ b/pymatgen/analysis/phase_diagram.py @@ -2989,7 +2989,7 @@ def get_marker_props(coords, entries, stable=True): e_above_hull = round(self._pd.get_e_above_hull(entry), 3) if e_above_hull > self.show_unstable: continue - label += f" (+{e_above_hull} eV/atom)" + label += f" ({e_above_hull:+} eV/atom)" energies.append(e_above_hull) else: uncertainty = 0 diff --git a/pymatgen/analysis/surface_analysis.py b/pymatgen/analysis/surface_analysis.py index 1a5a4968e64..a6465445f74 100644 --- a/pymatgen/analysis/surface_analysis.py +++ b/pymatgen/analysis/surface_analysis.py @@ -162,7 +162,7 @@ def as_dict(self): def gibbs_binding_energy(self, eads=False): """ - Returns the adsorption energy or Gibb's binding energy + Returns the adsorption energy or Gibbs binding energy of an adsorbate on a surface Args: eads (bool): Whether to calculate the adsorption energy @@ -170,10 +170,10 @@ def gibbs_binding_energy(self, eads=False): adsorption energy normalized by number of adsorbates. """ n = self.get_unit_primitive_area - Nads = self.Nads_in_slab + n_ads = self.Nads_in_slab - BE = (self.energy - n * self.clean_entry.energy) / Nads - sum(ads.energy_per_atom for ads in self.adsorbates) - return BE * Nads if eads else BE + BE = (self.energy - n * self.clean_entry.energy) / n_ads - sum(ads.energy_per_atom for ads in self.adsorbates) + return BE * n_ads if eads else BE def surface_energy(self, ucell_entry, ref_entries=None): """ @@ -211,7 +211,7 @@ def surface_energy(self, ucell_entry, ref_entries=None): ref_entries_dict.update(self.ads_entries_dict) # Calculate Gibbs free energy of the bulk per unit formula - gbulk = ucell_entry.energy / ucell_comp.get_integer_formula_and_factor()[1] + gibbs_bulk = ucell_entry.energy / ucell_comp.get_integer_formula_and_factor()[1] # First we get the contribution to the bulk energy # from each element with an existing ref_entry. @@ -228,8 +228,8 @@ def surface_energy(self, ucell_entry, ref_entries=None): for ref_el in ucell_comp.as_dict(): if str(ref_el) not in ref_entries_dict: break - refEperA = (gbulk - gbulk_eqn) / ucell_reduced_comp.as_dict()[ref_el] - bulk_energy += self.composition.as_dict()[ref_el] * refEperA + ref_e_per_a = (gibbs_bulk - gbulk_eqn) / ucell_reduced_comp.as_dict()[ref_el] + bulk_energy += self.composition.as_dict()[ref_el] * ref_e_per_a se = gamma.subs( { Symbol("E_surf"): self.energy, @@ -258,9 +258,9 @@ def get_monolayer(self): adsorbate. """ unit_a = self.get_unit_primitive_area - Nsurfs = self.Nsurfs_ads_in_slab - Nads = self.Nads_in_slab - return Nads / (unit_a * Nsurfs) + n_surfs = self.Nsurfs_ads_in_slab + n_ads = self.Nads_in_slab + return n_ads / (unit_a * n_surfs) @property def Nads_in_slab(self): @@ -278,31 +278,31 @@ def Nsurfs_ads_in_slab(self): weights = [s.species.weight for s in struct] center_of_mass = np.average(struct.frac_coords, weights=weights, axis=0) - Nsurfs = 0 + n_surfs = 0 # Are there adsorbates on top surface? if any( site.species_string in self.ads_entries_dict for site in struct if site.frac_coords[2] > center_of_mass[2] ): - Nsurfs += 1 + n_surfs += 1 # Are there adsorbates on bottom surface? if any( site.species_string in self.ads_entries_dict for site in struct if site.frac_coords[2] < center_of_mass[2] ): - Nsurfs += 1 + n_surfs += 1 - return Nsurfs + return n_surfs @classmethod - def from_dict(cls, d): + def from_dict(cls, dct): """ Returns a SlabEntry by reading in an dictionary """ - structure = SlabEntry.from_dict(d["structure"]) - energy = SlabEntry.from_dict(d["energy"]) - miller_index = d["miller_index"] - label = d["label"] - adsorbates = d["adsorbates"] - clean_entry = d["clean_entry"] + structure = SlabEntry.from_dict(dct["structure"]) + energy = SlabEntry.from_dict(dct["energy"]) + miller_index = dct["miller_index"] + label = dct["label"] + adsorbates = dct["adsorbates"] + clean_entry = dct["clean_entry"] return cls( structure, diff --git a/pymatgen/command_line/tests/test_mcsqs_caller.py b/pymatgen/command_line/tests/test_mcsqs_caller.py index b29952005c1..cdfa75ae464 100644 --- a/pymatgen/command_line/tests/test_mcsqs_caller.py +++ b/pymatgen/command_line/tests/test_mcsqs_caller.py @@ -22,8 +22,8 @@ @unittest.skipIf(not (which("mcsqs") and which("str2cif")), "mcsqs executable not present") class McsqsCallerTest(PymatgenTest): def setUp(self): - self.pztstructs = loadfn(os.path.join(test_dir, "pztstructs.json")) - self.pztstructs2 = loadfn(os.path.join(test_dir, "pztstructs2.json")) + self.pzt_structs = loadfn(os.path.join(test_dir, "pztstructs.json")) + self.pzt_structs2 = loadfn(os.path.join(test_dir, "pztstructs2.json")) self.struct = self.get_structure("Pb2TiZrO6") self.perfect_match_zzn_rs = loadfn(os.path.join(test_dir, "perfect_match_zzn_rs.json")) @@ -32,7 +32,7 @@ def test_mcsqs_caller_supercell(self): struct.replace_species({"Ti": {"Ti": 0.5, "Zr": 0.5}, "Zr": {"Ti": 0.5, "Zr": 0.5}}) sqs = run_mcsqs(struct, {2: 6, 3: 4}, scaling=[2, 1, 1], search_time=0.01, instances=1) - matches = [sqs.bestsqs.matches(s) for s in self.pztstructs] + matches = [sqs.bestsqs.matches(s) for s in self.pzt_structs] assert True in matches assert isinstance(sqs.bestsqs, Structure) @@ -51,7 +51,7 @@ def test_mcsqs_caller_total_atoms(self): struct.replace_species({"Ti": {"Ti": 0.5, "Zr": 0.5}, "Zr": {"Ti": 0.5, "Zr": 0.5}}) sqs = run_mcsqs(struct, {2: 6, 3: 4}, scaling=2, search_time=0.01, instances=1) - matches = [sqs.bestsqs.matches(s) for s in self.pztstructs2] + matches = [sqs.bestsqs.matches(s) for s in self.pzt_structs2] assert True in matches def test_mcsqs_caller_total_atoms_auto_instances(self): @@ -59,7 +59,7 @@ def test_mcsqs_caller_total_atoms_auto_instances(self): struct.replace_species({"Ti": {"Ti": 0.5, "Zr": 0.5}, "Zr": {"Ti": 0.5, "Zr": 0.5}}) sqs = run_mcsqs(struct, {2: 6, 3: 4}, scaling=2, search_time=0.01, instances=None) - matches = [sqs.bestsqs.matches(s) for s in self.pztstructs2] + matches = [sqs.bestsqs.matches(s) for s in self.pzt_structs2] assert True in matches def test_mcsqs_caller_parallel(self): @@ -69,7 +69,7 @@ def test_mcsqs_caller_parallel(self): struct.replace_species({"Ti": {"Ti": 0.5, "Zr": 0.5}, "Zr": {"Ti": 0.5, "Zr": 0.5}}) sqs = run_mcsqs(struct, {2: 6, 3: 4}, scaling=2, search_time=0.01, instances=4) - matches = [sqs.bestsqs.matches(s) for s in self.pztstructs2] + matches = [sqs.bestsqs.matches(s) for s in self.pzt_structs2] assert True in matches def test_mcsqs_perfect_match_error(self): diff --git a/pymatgen/core/composition.py b/pymatgen/core/composition.py index 8acc318392f..a41393ab652 100644 --- a/pymatgen/core/composition.py +++ b/pymatgen/core/composition.py @@ -293,7 +293,7 @@ def formula(self) -> str: """ sym_amt = self.get_el_amt_dict() syms = sorted(sym_amt, key=lambda sym: get_el_sp(sym).X) - formula = [s + formula_double_format(sym_amt[s], False) for s in syms] + formula = [f"{s}{formula_double_format(sym_amt[s], False)}" for s in syms] return " ".join(formula) @property @@ -317,7 +317,7 @@ def iupac_formula(self) -> str: """ sym_amt = self.get_el_amt_dict() syms = sorted(sym_amt, key=lambda s: get_el_sp(s).iupac_ordering) - formula = [s + formula_double_format(sym_amt[s], False) for s in syms] + formula = [f"{s}{formula_double_format(sym_amt[s], False)}" for s in syms] return " ".join(formula) @property @@ -1231,13 +1231,12 @@ def reduce_formula(sym_amt, iupac_ordering: bool = False) -> tuple[str, float]: syms = sorted(syms, key=lambda x: [get_el_sp(x).iupac_ordering, x]) reduced_form = [] - for s in syms: - normamt = sym_amt[s] * 1.0 / factor - reduced_form.append(s) - reduced_form.append(formula_double_format(normamt)) + for sym in syms: + norm_amt = sym_amt[sym] * 1.0 / factor + reduced_form.append(sym) + reduced_form.append(str(formula_double_format(norm_amt))) - reduced_form = "".join(reduced_form + polyanion) # type: ignore - return reduced_form, factor # type: ignore + return "".join([*reduced_form, *polyanion]), factor class ChemicalPotential(dict, MSONable): diff --git a/pymatgen/core/ion.py b/pymatgen/core/ion.py index f72e6b3e5c1..d16f99a5613 100644 --- a/pymatgen/core/ion.py +++ b/pymatgen/core/ion.py @@ -327,8 +327,6 @@ def to_pretty_string(self) -> str: :return: Pretty string with proper superscripts. """ str_ = super().reduced_formula - if self.charge > 0: - str_ += "^+" + formula_double_format(self.charge, False) - elif self._charge < 0: - str_ += "^" + formula_double_format(self.charge, False) + if val := formula_double_format(self.charge, False): + str_ += f"^{val:+}" return str_ diff --git a/pymatgen/core/operations.py b/pymatgen/core/operations.py index 5a85ccbd723..6477aa4ba3d 100644 --- a/pymatgen/core/operations.py +++ b/pymatgen/core/operations.py @@ -45,10 +45,14 @@ def __init__(self, affine_transformation_matrix: ArrayLike, tol: float = 0.01) - affine_transformation_matrix (4x4 array): Representing an affine transformation. tol (float): Tolerance for determining if matrices are equal. + + Raises: + ValueError: if matrix is not 4x4. """ affine_transformation_matrix = np.array(affine_transformation_matrix) - if affine_transformation_matrix.shape != (4, 4): - raise ValueError("Affine Matrix must be a 4x4 numpy array!") + shape = affine_transformation_matrix.shape + if shape != (4, 4): + raise ValueError(f"Affine Matrix must be a 4x4 numpy array, got {shape=}") self.affine_matrix = affine_transformation_matrix self.tol = tol diff --git a/pymatgen/core/periodic_table.py b/pymatgen/core/periodic_table.py index 62569f00017..c3abc404b54 100644 --- a/pymatgen/core/periodic_table.py +++ b/pymatgen/core/periodic_table.py @@ -1222,12 +1222,9 @@ def __repr__(self): def __str__(self): output = self.symbol if self.oxi_state is not None: - if self.oxi_state >= 0: - output += formula_double_format(self.oxi_state) + "+" - else: - output += formula_double_format(-self.oxi_state) + "-" - for p, v in self._properties.items(): - output += f",{p}={v}" + output += f"{formula_double_format(abs(self.oxi_state))}{'+' if self.oxi_state >= 0 else '-'}" + for prop, val in self._properties.items(): + output += f",{prop}={val}" return output def to_pretty_string(self) -> str: @@ -1236,10 +1233,7 @@ def to_pretty_string(self) -> str: """ output = self.symbol if self.oxi_state is not None: - if self.oxi_state >= 0: - output += formula_double_format(self.oxi_state) + "+" - else: - output += formula_double_format(-self.oxi_state) + "-" + output += f"{formula_double_format(abs(self.oxi_state))}{'+' if self.oxi_state >= 0 else '-'}" return output def get_nmr_quadrupole_moment(self, isotope: str | None = None) -> float: @@ -1547,12 +1541,9 @@ def __repr__(self): def __str__(self): output = self.symbol if self.oxi_state is not None: - if self.oxi_state >= 0: - output += formula_double_format(self.oxi_state) + "+" - else: - output += formula_double_format(-self.oxi_state) + "-" - for p, v in self._properties.items(): - output += f",{p}={v}" + output += f"{formula_double_format(abs(self.oxi_state))}{'+' if self.oxi_state >= 0 else '-'}" + for prop, val in self._properties.items(): + output += f",{prop}={val}" return output diff --git a/pymatgen/core/structure.py b/pymatgen/core/structure.py index 174afd711c9..67315cb12a6 100644 --- a/pymatgen/core/structure.py +++ b/pymatgen/core/structure.py @@ -2269,12 +2269,9 @@ def factors(n): def __repr__(self): outs = ["Structure Summary", repr(self.lattice)] if self._charge: - if self._charge >= 0: - outs.append(f"Overall Charge: +{self._charge}") - else: - outs.append(f"Overall Charge: -{self._charge}") - for s in self: - outs.append(repr(s)) + outs.append(f"Overall Charge: {self._charge:+}") + for site in self: + outs.append(repr(site)) return "\n".join(outs) def __str__(self): @@ -2283,24 +2280,21 @@ def __str__(self): f"Reduced Formula: {self.composition.reduced_formula}", ] - def to_s(x): - return f"{x:0.6f}" + def to_str(x): + return f"{x:>10.6f}" - outs.append("abc : " + " ".join(to_s(i).rjust(10) for i in self.lattice.abc)) - outs.append("angles: " + " ".join(to_s(i).rjust(10) for i in self.lattice.angles)) + outs.append("abc : " + " ".join(to_str(i) for i in self.lattice.abc)) + outs.append("angles: " + " ".join(to_str(i) for i in self.lattice.angles)) outs.append("pbc : " + " ".join(str(p).rjust(10) for p in self.lattice.pbc)) if self._charge: - if self._charge >= 0: - outs.append(f"Overall Charge: +{self._charge}") - else: - outs.append(f"Overall Charge: -{self._charge}") + outs.append(f"Overall Charge: {self._charge:+}") outs.append(f"Sites ({len(self)})") data = [] props = self.site_properties keys = sorted(props) for i, site in enumerate(self): row = [str(i), site.species_string] - row.extend([to_s(j) for j in site.frac_coords]) + row.extend([to_str(j) for j in site.frac_coords]) for k in keys: row.append(props[k][i]) data.append(row) diff --git a/pymatgen/core/tests/test_composition.py b/pymatgen/core/tests/test_composition.py index 7eef010fb8f..9540626d388 100644 --- a/pymatgen/core/tests/test_composition.py +++ b/pymatgen/core/tests/test_composition.py @@ -384,7 +384,7 @@ def test_equals(self): other_z = random.randint(1, 92) comp2 = Composition({fixed_el: 1, Element.from_Z(other_z): 0}) assert comp1 == comp2, f"Composition equality test failed. {comp1.formula} should be equal to {comp2.formula}" - assert hash(comp1) == hash(comp2), "Hashcode equality test failed!" + assert hash(comp1) == hash(comp2), "Hash equality test failed!" c1, c2 = self.comp[:2] assert c1 == c1 diff --git a/pymatgen/core/tests/test_ion.py b/pymatgen/core/tests/test_ion.py index 6875f0c0382..1d9896590e8 100644 --- a/pymatgen/core/tests/test_ion.py +++ b/pymatgen/core/tests/test_ion.py @@ -165,7 +165,7 @@ def test_equals(self): other_z = random.randint(1, 92) comp2 = Ion(Composition({fixed_el: 1, Element.from_Z(other_z): 0}), 1) assert comp1 == comp2, f"Composition equality test failed. {comp1.formula} should be equal to {comp2.formula}" - assert hash(comp1) == hash(comp2), "Hashcode equality test failed!" + assert hash(comp1) == hash(comp2), "Hash equality test failed!" def test_equality(self): assert self.comp[0] == (self.comp[0]) diff --git a/pymatgen/core/tests/test_operations.py b/pymatgen/core/tests/test_operations.py index b10cc10906e..a137d7270a9 100644 --- a/pymatgen/core/tests/test_operations.py +++ b/pymatgen/core/tests/test_operations.py @@ -19,35 +19,35 @@ def test_properties(self): def test_operate(self): point = np.array([1, 2, 3]) - newcoord = self.op.operate(point) - self.assert_all_close(newcoord, [-0.1339746, 2.23205081, 4.0], 2) + new_coord = self.op.operate(point) + self.assert_all_close(new_coord, [-0.1339746, 2.23205081, 4.0], 2) def test_operate_multi(self): point = np.array([1, 2, 3]) - newcoords = self.op.operate_multi([point, point]) - self.assert_all_close(newcoords, [[-0.1339746, 2.23205081, 4.0]] * 2, 2) - newcoords = self.op.operate_multi([[point, point]] * 2) - self.assert_all_close(newcoords, [[[-0.1339746, 2.23205081, 4.0]] * 2] * 2, 2) + new_coords = self.op.operate_multi([point, point]) + self.assert_all_close(new_coords, [[-0.1339746, 2.23205081, 4.0]] * 2, 2) + new_coords = self.op.operate_multi([[point, point]] * 2) + self.assert_all_close(new_coords, [[[-0.1339746, 2.23205081, 4.0]] * 2] * 2, 2) def test_inverse(self): point = np.random.rand(3) - newcoord = self.op.operate(point) - self.assert_all_close(self.op.inverse.operate(newcoord), point, 2) + new_coord = self.op.operate(point) + self.assert_all_close(self.op.inverse.operate(new_coord), point, 2) def test_reflection(self): normal = np.random.rand(3) origin = np.random.rand(3) refl = SymmOp.reflection(normal, origin) point = np.random.rand(3) - newcoord = refl.operate(point) + new_coord = refl.operate(point) # Distance to the plane should be negatives of each other. - assert round(abs(np.dot(newcoord - origin, normal) - -np.dot(point - origin, normal)), 7) == 0 + assert round(abs(np.dot(new_coord - origin, normal) - -np.dot(point - origin, normal)), 7) == 0 def test_apply_rotation_only(self): point = np.random.rand(3) - newcoord = self.op.operate(point) + new_coord = self.op.operate(point) rotate_only = self.op.apply_rotation_only(point) - self.assert_all_close(rotate_only + self.op.translation_vector, newcoord, 2) + self.assert_all_close(rotate_only + self.op.translation_vector, new_coord, 2) def test_transform_tensor(self): # Rank 2 @@ -150,9 +150,9 @@ def test_transform_tensor(self): def test_are_symmetrically_related(self): point = np.random.rand(3) - newcoord = self.op.operate(point) - assert self.op.are_symmetrically_related(point, newcoord) - assert self.op.are_symmetrically_related(newcoord, point) + new_coord = self.op.operate(point) + assert self.op.are_symmetrically_related(point, new_coord) + assert self.op.are_symmetrically_related(new_coord, point) def test_are_symmetrically_related_vectors(self): tol = 0.001 @@ -176,8 +176,8 @@ def test_to_from_dict(self): d = self.op.as_dict() op = SymmOp.from_dict(d) point = np.random.rand(3) - newcoord = self.op.operate(point) - assert op.are_symmetrically_related(point, newcoord) + new_coord = self.op.operate(point) + assert op.are_symmetrically_related(point, new_coord) def test_inversion(self): origin = np.random.rand(3) diff --git a/pymatgen/core/tests/test_structure.py b/pymatgen/core/tests/test_structure.py index 6ac3be01512..a23a94b402e 100644 --- a/pymatgen/core/tests/test_structure.py +++ b/pymatgen/core/tests/test_structure.py @@ -1347,8 +1347,8 @@ def test_relax_with_observer(self): assert len(getattr(trajectory, key)) == {"atoms": 2}.get(key, 1) def test_from_prototype(self): - for pt in ["bcc", "fcc", "hcp", "diamond"]: - struct = Structure.from_prototype(pt, ["C"], a=3, c=4) + for prototype in ["bcc", "fcc", "hcp", "diamond"]: + struct = Structure.from_prototype(prototype, ["C"], a=3, c=4) assert isinstance(struct, Structure) with pytest.raises(ValueError): @@ -1372,8 +1372,8 @@ def test_from_prototype(self): 6 Cl 0.5 0.5 0 7 Cl 0 0 0""" assert str(struct) == expected_struct_str - for pt in ("cscl", "fluorite", "antifluorite", "zincblende"): - struct = Structure.from_prototype(pt, ["Cs", "Cl"], a=5) + for prototype in ("cscl", "fluorite", "antifluorite", "zincblende"): + struct = Structure.from_prototype(prototype, ["Cs", "Cl"], a=5) assert struct.lattice.is_orthogonal diff --git a/pymatgen/electronic_structure/plotter.py b/pymatgen/electronic_structure/plotter.py index 0700ae55f8f..fc1606d223d 100644 --- a/pymatgen/electronic_structure/plotter.py +++ b/pymatgen/electronic_structure/plotter.py @@ -3275,7 +3275,7 @@ def plot_power_factor_temp(self, doping="all", output="average", relaxation_time plt.tight_layout() return plt - def plot_zt_temp(self, doping="all", output="average", relaxation_time=1e-14): + def plot_zt_temp(self, doping="all", output: Literal["average", "eigs"] = "average", relaxation_time=1e-14): """ Plot the figure of merit zT in function of temperature for different doping levels. @@ -3286,13 +3286,15 @@ def plot_zt_temp(self, doping="all", output="average", relaxation_time=1e-14): with 'eigs' you get all the three directions. relaxation_time: specify a constant relaxation time value + Raises: + ValueError: if output is not 'average' or 'eigs' + Returns: a matplotlib object """ - if output == "average": - zt = self._bz.get_zt(relaxation_time=relaxation_time, output="average") - elif output == "eigs": - zt = self._bz.get_zt(relaxation_time=relaxation_time, output="eigs") + if output not in ("average", "eigs"): + raise ValueError(f"{output=} must be 'average' or 'eigs'") + zt = self._bz.get_zt(relaxation_time=relaxation_time, output=output) plt = pretty_plot(22, 14) tlist = sorted(zt["n"]) diff --git a/pymatgen/io/lmto.py b/pymatgen/io/lmto.py index b107985b2ce..d0cdc6a31bb 100644 --- a/pymatgen/io/lmto.py +++ b/pymatgen/io/lmto.py @@ -378,19 +378,14 @@ def __init__(self, filename="COPL", to_eV=False): # This takes care of duplicate labels if label in cohp_data: - i = 1 - lab = f"{label}-{i}" + idx = 1 + lab = f"{label}-{idx}" while lab in cohp_data: - i += 1 - lab = f"{label}-{i}" + idx += 1 + lab = f"{label}-{idx}" label = lab - cohp_data[label] = { - "COHP": cohp, - "ICOHP": icohp, - "length": length, - "sites": sites, - } + cohp_data[label] = {"COHP": cohp, "ICOHP": icohp, "length": length, "sites": sites} self.cohp_data = cohp_data @staticmethod diff --git a/pymatgen/io/lobster/lobsterenv.py b/pymatgen/io/lobster/lobsterenv.py index 82331c5496e..9a48898fdd0 100644 --- a/pymatgen/io/lobster/lobsterenv.py +++ b/pymatgen/io/lobster/lobsterenv.py @@ -857,16 +857,20 @@ def _find_environments(self, additional_condition, lowerlimit, upperlimit, only_ index_here = neigh_new[2] index_here_list.append(index_here) cell_here = neigh_new[3] - newcoords = [ + new_coords = [ site_here.frac_coords[0] + float(cell_here[0]), site_here.frac_coords[1] + float(cell_here[1]), site_here.frac_coords[2] + float(cell_here[2]), ] - coords.append(site_here.lattice.get_cartesian_coords(newcoords)) - - # new_site = PeriodicSite(species=site_here.species_string, - # coords=site_here.lattice.get_cartesian_coords(newcoords), - # lattice=site_here.lattice, to_unit_cell=False, coords_are_cartesian=True) + coords.append(site_here.lattice.get_cartesian_coords(new_coords)) + + # new_site = PeriodicSite( + # species=site_here.species_string, + # coords=site_here.lattice.get_cartesian_coords(new_coords), + # lattice=site_here.lattice, + # to_unit_cell=False, + # coords_are_cartesian=True, + # ) neighbors_by_distance.append(neigh_new[0]) list_distances.append(neigh_new[1]) _list_neighsite = [] diff --git a/pymatgen/symmetry/analyzer.py b/pymatgen/symmetry/analyzer.py index 50e1c985845..99ff049aaae 100644 --- a/pymatgen/symmetry/analyzer.py +++ b/pymatgen/symmetry/analyzer.py @@ -67,7 +67,7 @@ def __init__(self, structure: Structure, symprec: float | None = 0.01, angle_tol self._symprec = symprec self._angle_tol = angle_tolerance self._structure = structure - self._siteprops = structure.site_properties + self._site_props = structure.site_properties unique_species: list[Element | Species] = [] zs = [] magmoms = [] @@ -336,7 +336,7 @@ def get_refined_structure(self, keep_site_properties=False): species = [self._unique_species[i - 1] for i in numbers] if keep_site_properties: site_properties = {} - for k, v in self._siteprops.items(): + for k, v in self._site_props.items(): site_properties[k] = [v[i - 1] for i in numbers] else: site_properties = None @@ -365,7 +365,7 @@ def find_primitive(self, keep_site_properties=False): species = [self._unique_species[i - 1] for i in numbers] if keep_site_properties: site_properties = {} - for k, v in self._siteprops.items(): + for k, v in self._site_props.items(): site_properties[k] = [v[i - 1] for i in numbers] else: site_properties = None diff --git a/pymatgen/symmetry/structure.py b/pymatgen/symmetry/structure.py index 0e328999902..cf09f91c13c 100644 --- a/pymatgen/symmetry/structure.py +++ b/pymatgen/symmetry/structure.py @@ -42,7 +42,7 @@ def __init__( wyckoff_letters (list[str]): Wyckoff letters """ self.spacegroup = spacegroup - u, inv = np.unique(equivalent_positions, return_inverse=True) + uniq, inverse = np.unique(equivalent_positions, return_inverse=True) self.site_labels = equivalent_positions super().__init__( @@ -52,17 +52,17 @@ def __init__( site_properties=structure.site_properties, ) - equivalent_indices = [[] for _ in range(len(u))] # type: ignore - equivalent_sites = [[] for _ in range(len(u))] # type: ignore - wyckoff_symbols = [[] for _ in range(len(u))] # type: ignore - for i, inv_ in enumerate(inv): - equivalent_indices[inv_].append(i) - equivalent_sites[inv_].append(self.sites[i]) - wyckoff_symbols[inv_].append(wyckoff_letters[i]) - self.equivalent_indices: list[int] = equivalent_indices # type: ignore - self.equivalent_sites: list[PeriodicSite] = equivalent_sites # type: ignore + equivalent_indices: list[list[int]] = [[] for _ in range(len(uniq))] + equivalent_sites: list[list[PeriodicSite]] = [[] for _ in range(len(uniq))] + wyckoff_symbols: list[list[str]] = [[] for _ in range(len(uniq))] + for idx, inv_ in enumerate(inverse): + equivalent_indices[inv_].append(idx) + equivalent_sites[inv_].append(self.sites[idx]) + wyckoff_symbols[inv_].append(wyckoff_letters[idx]) + self.equivalent_indices = equivalent_indices + self.equivalent_sites = equivalent_sites self.wyckoff_letters = wyckoff_letters - self.wyckoff_symbols = [f"{len(w)}{w[0]}" for w in wyckoff_symbols] + self.wyckoff_symbols = [f"{len(symb)}{symb[0]}" for symb in wyckoff_symbols] def copy(self): """ @@ -106,15 +106,12 @@ def __str__(self) -> str: ] def to_str(x): - return f"{x:0.6f}" + return f"{x:>10.6f}" - outs.append("abc : " + " ".join(to_str(i).rjust(10) for i in self.lattice.abc)) - outs.append("angles: " + " ".join(to_str(i).rjust(10) for i in self.lattice.angles)) + outs.append(f"abc : {' '.join(to_str(val) for val in self.lattice.abc)}") + outs.append(f"angles: {' '.join(to_str(val) for val in self.lattice.angles)}") if self._charge: - if self._charge >= 0: - outs.append(f"Overall Charge: +{self._charge}") - else: - outs.append(f"Overall Charge: -{self._charge}") + outs.append(f"Overall Charge: {self._charge:+}") outs.append(f"Sites ({len(self)})") data = [] props = self.site_properties @@ -127,12 +124,7 @@ def to_str(x): for k in keys: row.append(props[k][idx]) data.append(row) - outs.append( - tabulate( - data, - headers=["#", "SP", "a", "b", "c", "Wyckoff", *keys], - ) - ) + outs.append(tabulate(data, headers=["#", "SP", "a", "b", "c", "Wyckoff", *keys])) return "\n".join(outs) def as_dict(self): @@ -148,14 +140,14 @@ def as_dict(self): } @classmethod - def from_dict(cls, d): + def from_dict(cls, dct): """ :param d: Dict representation :return: SymmetrizedStructure """ return cls( - Structure.from_dict(d["structure"]), - spacegroup=d["spacegroup"], - equivalent_positions=d["equivalent_positions"], - wyckoff_letters=d["wyckoff_letters"], + Structure.from_dict(dct["structure"]), + spacegroup=dct["spacegroup"], + equivalent_positions=dct["equivalent_positions"], + wyckoff_letters=dct["wyckoff_letters"], ) diff --git a/pymatgen/transformations/tests/test_advanced_transformations.py b/pymatgen/transformations/tests/test_advanced_transformations.py index 96215cfcae6..4e854b94923 100644 --- a/pymatgen/transformations/tests/test_advanced_transformations.py +++ b/pymatgen/transformations/tests/test_advanced_transformations.py @@ -661,23 +661,23 @@ def test_apply_transformation(self): @unittest.skipIf(not mcsqs_cmd, "mcsqs not present.") class SQSTransformationTest(PymatgenTest): def test_apply_transformation(self): - pztstructs = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "mcsqs/pztstructs.json")) + pzt_structs = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "mcsqs/pztstructs.json")) trans = SQSTransformation(scaling=[2, 1, 1], search_time=0.01, instances=1, wd=0) # nonsensical example just for testing purposes struct = self.get_structure("Pb2TiZrO6").copy() struct.replace_species({"Ti": {"Ti": 0.5, "Zr": 0.5}, "Zr": {"Ti": 0.5, "Zr": 0.5}}) - struc_out = trans.apply_transformation(struct) - matches = [struc_out.matches(s) for s in pztstructs] + struct_out = trans.apply_transformation(struct) + matches = [struct_out.matches(s) for s in pzt_structs] assert True in matches def test_return_ranked_list(self): # list of structures - pztstructs2 = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "mcsqs/pztstructs2.json")) + pzt_structs2 = loadfn(os.path.join(PymatgenTest.TEST_FILES_DIR, "mcsqs/pztstructs2.json")) trans = SQSTransformation(scaling=2, search_time=0.01, instances=8, wd=0) struct = self.get_structure("Pb2TiZrO6").copy() struct.replace_species({"Ti": {"Ti": 0.5, "Zr": 0.5}, "Zr": {"Ti": 0.5, "Zr": 0.5}}) ranked_list_out = trans.apply_transformation(struct, return_ranked_list=True) - matches = [ranked_list_out[0]["structure"].matches(s) for s in pztstructs2] + matches = [ranked_list_out[0]["structure"].matches(s) for s in pzt_structs2] assert True in matches def test_spin(self): @@ -687,10 +687,10 @@ def test_spin(self): struct = self.get_structure("Pb2TiZrO6").copy() struct.replace_species({"Ti": {"Ti,spin=5": 0.5, "Ti,spin=-5": 0.5}}) - struc_out = trans.apply_transformation(struct) - struc_out_specie_strings = [site.species_string for site in struc_out] - assert "Ti,spin=-5" in struc_out_specie_strings - assert "Ti,spin=5" in struc_out_specie_strings + struct_out = trans.apply_transformation(struct) + struct_out_specie_strings = [site.species_string for site in struct_out] + assert "Ti,spin=-5" in struct_out_specie_strings + assert "Ti,spin=5" in struct_out_specie_strings class CubicSupercellTransformationTest(PymatgenTest): diff --git a/pymatgen/util/string.py b/pymatgen/util/string.py index c6b258ceef8..b9acc814ec6 100644 --- a/pymatgen/util/string.py +++ b/pymatgen/util/string.py @@ -135,8 +135,8 @@ def formula_double_format(afloat, ignore_ones=True, tol: float = 1e-8): if ignore_ones and afloat == 1: return "" if abs(afloat - int(afloat)) < tol: - return str(int(afloat)) - return str(round(afloat, 8)) + return int(afloat) + return round(afloat, 8) def charge_string(charge, brackets=True, explicit_one=True): @@ -150,12 +150,7 @@ def charge_string(charge, brackets=True, explicit_one=True): explicit_one: whether to include the number one for monovalent ions, e.g. +1 rather than +. Default: True """ - if charge > 0: - chg_str = f"+{formula_double_format(charge, False)}" - elif charge < 0: - chg_str = f"-{formula_double_format(abs(charge), False)}" - else: - chg_str = "(aq)" + chg_str = "(aq)" if charge == 0 else f"{formula_double_format(charge, False):+}" if chg_str in ["+1", "-1"] and not explicit_one: chg_str = chg_str.replace("1", "") @@ -409,7 +404,7 @@ def disordered_formula(disordered_struct, symbols=("x", "y", "z"), fmt="plain"): factor = factor_comp.get_reduced_formula_and_factor()[1] total_disordered_occu /= factor - remainder = formula_double_format(total_disordered_occu, ignore_ones=False) + "-" + "-".join(symbols) + remainder = f"{formula_double_format(total_disordered_occu, ignore_ones=False)}-{'-'.join(symbols)}" for sp, occu in comp: species = str(sp) @@ -441,6 +436,6 @@ def disordered_formula(disordered_struct, symbols=("x", "y", "z"), fmt="plain"): if fmt != "plain": disordered_formula.append(sub_end) disordered_formula.append(" ") - disordered_formula += [f"{k}={formula_double_format(v)} " for k, v in variable_map.items()] + disordered_formula += [f"{key}={formula_double_format(val)} " for key, val in variable_map.items()] return "".join(map(str, disordered_formula))[0:-1] diff --git a/pymatgen/util/tests/test_string.py b/pymatgen/util/tests/test_string.py index cd5e16176e6..72b2a8e6323 100644 --- a/pymatgen/util/tests/test_string.py +++ b/pymatgen/util/tests/test_string.py @@ -72,9 +72,9 @@ def test_unicodeify(self): def test_formula_double_format(self): assert formula_double_format(1.00) == "" - assert formula_double_format(2.00) == "2" - assert formula_double_format(2.10) == "2.1" - assert formula_double_format(2.10000000002) == "2.1" + assert formula_double_format(2.00) == 2 + assert formula_double_format(2.10) == 2.1 + assert formula_double_format(2.10000000002) == 2.1 def test_charge_string(self): assert charge_string(1) == "[+1]"