From cadcae4f3bda1706c197f97cf48f77724961e137 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 14 Aug 2024 23:41:34 +0800 Subject: [PATCH] Docstring tweaks for `io.vasp.inputs` and format tweaks for some other parts (#3996) * docstring tweaks * fix typo * reduce indentation level * fix vasp case to VASP * use walrus operator * revert overlapping functional changes from #3994 * my bad, I get confused hopping between two PRs * remove debug code from vasp.help * fix `use-named-expression` with sourcery * clean up Vasprun.as_dict * simplify dict generation * re-raise and update -> |= * simplify logic conditions * remove unused logger * remove a lot of unused logger, wondering if they exist for a reason? * remove some unused module_dir, they must have gone stranded * CAPS LOCK ENGAGED: Go up! module level variables! --- src/pymatgen/alchemy/filters.py | 3 +- src/pymatgen/analysis/bond_dissociation.py | 3 - src/pymatgen/analysis/bond_valence.py | 6 +- .../chemenv_strategies.py | 3 - .../coordination_geometries.py | 8 +- src/pymatgen/analysis/cost.py | 4 +- src/pymatgen/analysis/diffraction/tem.py | 4 +- src/pymatgen/analysis/fragmenter.py | 3 - src/pymatgen/analysis/graphs.py | 15 +- src/pymatgen/analysis/hhi.py | 6 +- src/pymatgen/analysis/local_env.py | 12 +- src/pymatgen/analysis/pourbaix_diagram.py | 3 +- src/pymatgen/analysis/prototypes.py | 4 +- src/pymatgen/analysis/reaction_calculator.py | 4 - src/pymatgen/analysis/structure_matcher.py | 10 +- src/pymatgen/analysis/transition_state.py | 3 +- src/pymatgen/apps/borg/hive.py | 3 +- src/pymatgen/apps/borg/queen.py | 3 +- src/pymatgen/command_line/critic2_caller.py | 11 +- src/pymatgen/command_line/gulp_caller.py | 4 +- src/pymatgen/core/composition.py | 4 +- src/pymatgen/core/periodic_table.py | 12 +- src/pymatgen/core/surface.py | 4 +- src/pymatgen/io/abinit/inputs.py | 3 +- src/pymatgen/io/abinit/pseudos.py | 3 +- src/pymatgen/io/aims/sets/base.py | 3 - src/pymatgen/io/cp2k/outputs.py | 8 +- src/pymatgen/io/feff/outputs.py | 9 +- src/pymatgen/io/lammps/generators.py | 8 +- src/pymatgen/io/lammps/inputs.py | 6 +- src/pymatgen/io/lammps/sets.py | 5 +- src/pymatgen/io/optimade.py | 3 +- src/pymatgen/io/qchem/inputs.py | 3 - src/pymatgen/io/qchem/outputs.py | 3 - src/pymatgen/io/qchem/sets.py | 3 - src/pymatgen/io/vasp/help.py | 12 +- src/pymatgen/io/vasp/inputs.py | 208 +++++++++--------- src/pymatgen/io/vasp/outputs.py | 57 ++--- src/pymatgen/io/vasp/sets.py | 53 +++-- src/pymatgen/io/xtb/inputs.py | 3 - src/pymatgen/io/xtb/outputs.py | 3 - src/pymatgen/phonon/plotter.py | 3 +- .../standard_transformations.py | 3 - src/pymatgen/vis/structure_vtk.py | 4 +- tests/analysis/test_pourbaix_diagram.py | 3 - tests/entries/test_compatibility.py | 9 +- tests/files/io/vasp/inputs/POTCAR_spec | 4 +- tests/io/aims/conftest.py | 6 +- tests/io/aims/test_sets/test_bs_generator.py | 18 +- tests/io/aims/test_sets/test_gw_generator.py | 10 +- tests/io/aims/test_sets/test_md_generator.py | 10 +- .../io/aims/test_sets/test_relax_generator.py | 14 +- .../aims/test_sets/test_static_generator.py | 10 +- ...est_static_restart_from_relax_generator.py | 36 +-- tests/io/lobster/test_inputs.py | 2 - tests/io/lobster/test_lobsterenv.py | 2 - tests/io/qchem/test_inputs.py | 6 - tests/io/qchem/test_utils.py | 3 - tests/io/test_lmto.py | 6 +- tests/io/test_shengbte.py | 4 - 60 files changed, 280 insertions(+), 398 deletions(-) diff --git a/src/pymatgen/alchemy/filters.py b/src/pymatgen/alchemy/filters.py index 923ca1e8056..f8bd3c777a4 100644 --- a/src/pymatgen/alchemy/filters.py +++ b/src/pymatgen/alchemy/filters.py @@ -132,8 +132,7 @@ def test(self, structure: Structure): all_species = set(self.specie_and_min_dist) for site in structure: species = set(site.species) - sp_to_test = species.intersection(all_species) - if sp_to_test: + if sp_to_test := species.intersection(all_species): max_r = max(self.specie_and_min_dist[sp] for sp in sp_to_test) neighbors = structure.get_neighbors(site, max_r) for sp in sp_to_test: diff --git a/src/pymatgen/analysis/bond_dissociation.py b/src/pymatgen/analysis/bond_dissociation.py index 73b9f2d4fe2..17cc9c1d560 100644 --- a/src/pymatgen/analysis/bond_dissociation.py +++ b/src/pymatgen/analysis/bond_dissociation.py @@ -2,7 +2,6 @@ from __future__ import annotations -import logging import warnings from typing import cast @@ -23,8 +22,6 @@ __status__ = "Alpha" __date__ = "7/26/18" -logger = logging.getLogger(__name__) - class BondDissociationEnergies(MSONable): """ diff --git a/src/pymatgen/analysis/bond_valence.py b/src/pymatgen/analysis/bond_valence.py index a4ed8389120..9294f9ce2bc 100644 --- a/src/pymatgen/analysis/bond_valence.py +++ b/src/pymatgen/analysis/bond_valence.py @@ -22,15 +22,15 @@ # JACS, 1991, 113(9), 3226-3229. doi:10.1021/ja00009a002. ELECTRONEG = [Element(sym) for sym in "H B C Si N P As Sb O S Se Te F Cl Br I".split()] -module_dir = os.path.dirname(os.path.abspath(__file__)) +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) # Read in BV parameters. BV_PARAMS = {} -for key, val in loadfn(f"{module_dir}/bvparam_1991.yaml").items(): +for key, val in loadfn(f"{MODULE_DIR}/bvparam_1991.yaml").items(): BV_PARAMS[Element(key)] = val # Read in YAML containing data-mined ICSD BV data. -all_data = loadfn(f"{module_dir}/icsd_bv.yaml") +all_data = loadfn(f"{MODULE_DIR}/icsd_bv.yaml") ICSD_BV_DATA = {Species.from_str(sp): data for sp, data in all_data["bvsum"].items()} PRIOR_PROB = {Species.from_str(sp): data for sp, data in all_data["occurrence"].items()} diff --git a/src/pymatgen/analysis/chemenv/coordination_environments/chemenv_strategies.py b/src/pymatgen/analysis/chemenv/coordination_environments/chemenv_strategies.py index 3f814ac3ade..75f770a5175 100644 --- a/src/pymatgen/analysis/chemenv/coordination_environments/chemenv_strategies.py +++ b/src/pymatgen/analysis/chemenv/coordination_environments/chemenv_strategies.py @@ -8,7 +8,6 @@ from __future__ import annotations import abc -import os from typing import TYPE_CHECKING import numpy as np @@ -43,8 +42,6 @@ __email__ = "david.waroquiers@gmail.com" __date__ = "Feb 20, 2016" -module_dir = os.path.dirname(os.path.abspath(__file__)) - MPSYMBOL_TO_CN = AllCoordinationGeometries().get_symbol_cn_mapping() ALLCG = AllCoordinationGeometries() diff --git a/src/pymatgen/analysis/chemenv/coordination_environments/coordination_geometries.py b/src/pymatgen/analysis/chemenv/coordination_environments/coordination_geometries.py index 3e9df3df9cf..6cc6348ca89 100644 --- a/src/pymatgen/analysis/chemenv/coordination_environments/coordination_geometries.py +++ b/src/pymatgen/analysis/chemenv/coordination_environments/coordination_geometries.py @@ -32,7 +32,7 @@ __email__ = "david.waroquiers@gmail.com" __date__ = "Feb 20, 2016" -module_dir = os.path.dirname(os.path.abspath(__file__)) +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) UNKNOWN_ENVIRONMENT_SYMBOL = "UNKNOWN" UNCLEAR_ENVIRONMENT_SYMBOL = "UNCLEAR" @@ -850,17 +850,17 @@ def __init__(self, permutations_safe_override=False, only_symbols=None): dict.__init__(self) self.cg_list: list[CoordinationGeometry] = [] if only_symbols is None: - with open(f"{module_dir}/coordination_geometries_files/allcg.txt") as file: + with open(f"{MODULE_DIR}/coordination_geometries_files/allcg.txt") as file: data = file.readlines() for line in data: - cg_file = f"{module_dir}/{line.strip()}" + cg_file = f"{MODULE_DIR}/{line.strip()}" with open(cg_file) as file: dd = json.load(file) self.cg_list.append(CoordinationGeometry.from_dict(dd)) else: for symbol in only_symbols: fsymbol = symbol.replace(":", "#") - cg_file = f"{module_dir}/coordination_geometries_files/{fsymbol}.json" + cg_file = f"{MODULE_DIR}/coordination_geometries_files/{fsymbol}.json" with open(cg_file) as file: dd = json.load(file) self.cg_list.append(CoordinationGeometry.from_dict(dd)) diff --git a/src/pymatgen/analysis/cost.py b/src/pymatgen/analysis/cost.py index e5b34ed623c..564dfbf8db2 100644 --- a/src/pymatgen/analysis/cost.py +++ b/src/pymatgen/analysis/cost.py @@ -32,7 +32,7 @@ __email__ = "ajain@lbl.gov" __date__ = "Aug 27, 2013" -module_dir = os.path.dirname(os.path.abspath(__file__)) +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) class CostEntry(PDEntry): @@ -112,7 +112,7 @@ class CostDBElements(CostDBCSV): """Singleton that provides the cost data for elements.""" def __init__(self): - CostDBCSV.__init__(self, f"{module_dir}/costdb_elements.csv") + CostDBCSV.__init__(self, f"{MODULE_DIR}/costdb_elements.csv") class CostAnalyzer: diff --git a/src/pymatgen/analysis/diffraction/tem.py b/src/pymatgen/analysis/diffraction/tem.py index d20699f7699..83ea51db320 100644 --- a/src/pymatgen/analysis/diffraction/tem.py +++ b/src/pymatgen/analysis/diffraction/tem.py @@ -30,8 +30,8 @@ __date__ = "03/31/2020" -module_dir = os.path.dirname(__file__) -with open(f"{module_dir}/atomic_scattering_params.json", encoding="utf-8") as file: +MODULE_DIR = os.path.dirname(__file__) +with open(f"{MODULE_DIR}/atomic_scattering_params.json", encoding="utf-8") as file: ATOMIC_SCATTERING_PARAMS = json.load(file) diff --git a/src/pymatgen/analysis/fragmenter.py b/src/pymatgen/analysis/fragmenter.py index 7458a46dfeb..aff87787972 100644 --- a/src/pymatgen/analysis/fragmenter.py +++ b/src/pymatgen/analysis/fragmenter.py @@ -3,7 +3,6 @@ from __future__ import annotations import copy -import logging from typing import TYPE_CHECKING from monty.json import MSONable @@ -23,8 +22,6 @@ __status__ = "Beta" __date__ = "8/21/19" -logger = logging.getLogger(__name__) - class Fragmenter(MSONable): """Molecule fragmenter class.""" diff --git a/src/pymatgen/analysis/graphs.py b/src/pymatgen/analysis/graphs.py index a23ce49ef36..851e1f30942 100644 --- a/src/pymatgen/analysis/graphs.py +++ b/src/pymatgen/analysis/graphs.py @@ -429,8 +429,7 @@ def add_edge( # there should only ever be at most one edge # between a given (site, jimage) pair and another # (site, jimage) pair - existing_edge_data = self.graph.get_edge_data(from_index, to_index) - if existing_edge_data: + if existing_edge_data := self.graph.get_edge_data(from_index, to_index): for d in existing_edge_data.values(): if d["to_jimage"] == to_jimage: if warn_duplicates: @@ -1287,12 +1286,10 @@ def __rmul__(self, other): def _edges_to_str(cls, g) -> str: header = "from to to_image " header_line = "---- ---- ------------" - edge_weight_name = g.graph["edge_weight_name"] - if edge_weight_name: + if g.graph["edge_weight_name"]: print_weights = True edge_label = g.graph["edge_weight_name"] - edge_weight_units = g.graph["edge_weight_units"] - if edge_weight_units: + if edge_weight_units := g.graph["edge_weight_units"]: edge_label += f" ({edge_weight_units})" header += f" {edge_label}" header_line += f" {'-' * max([18, len(edge_label)])}" @@ -2673,12 +2670,10 @@ def from_dict(cls, dct: dict) -> Self: def _edges_to_str(cls, g): header = "from to to_image " header_line = "---- ---- ------------" - edge_weight_name = g.graph["edge_weight_name"] - if edge_weight_name: + if g.graph["edge_weight_name"]: print_weights = ["weight"] edge_label = g.graph["edge_weight_name"] - edge_weight_units = g.graph["edge_weight_units"] - if edge_weight_units: + if edge_weight_units := g.graph["edge_weight_units"]: edge_label += f" ({edge_weight_units})" header += f" {edge_label}" header_line += f" {'-' * max([18, len(edge_label)])}" diff --git a/src/pymatgen/analysis/hhi.py b/src/pymatgen/analysis/hhi.py index 85708e78366..f1ae3a1dc72 100644 --- a/src/pymatgen/analysis/hhi.py +++ b/src/pymatgen/analysis/hhi.py @@ -25,8 +25,8 @@ __date__ = "Oct 27, 2014" -module_dir = os.path.dirname(os.path.abspath(__file__)) -csv_path = f"{module_dir}/hhi_data.csv" +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) +HHI_CSV_PATH = f"{MODULE_DIR}/hhi_data.csv" @singleton @@ -37,7 +37,7 @@ def __init__(self): """Init for HHIModel.""" self.symbol_hhip_hhir = {} # symbol->(HHI_production, HHI reserve) - with open(csv_path) as file: + with open(HHI_CSV_PATH) as file: for line in file: if line[0] != "#": symbol, hhi_production, hhi_reserve = line.split(",") diff --git a/src/pymatgen/analysis/local_env.py b/src/pymatgen/analysis/local_env.py index 61a0e338707..31f628c8381 100644 --- a/src/pymatgen/analysis/local_env.py +++ b/src/pymatgen/analysis/local_env.py @@ -50,16 +50,16 @@ __status__ = "Production" __date__ = "August 17, 2017" -module_dir = os.path.dirname(os.path.abspath(__file__)) +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) yaml = YAML() -with open(f"{module_dir}/op_params.yaml") as file: +with open(f"{MODULE_DIR}/op_params.yaml") as file: default_op_params = yaml.load(file) -with open(f"{module_dir}/cn_opt_params.yaml") as file: +with open(f"{MODULE_DIR}/cn_opt_params.yaml") as file: cn_opt_params = yaml.load(file) -with open(f"{module_dir}/ionic_radii.json") as file: +with open(f"{MODULE_DIR}/ionic_radii.json") as file: _ion_radii = json.load(file) @@ -1211,7 +1211,7 @@ def __init__( self.min_bond_distance = min_bond_distance # Load elemental radii table - bonds_file = f"{module_dir}/bonds_jmol_ob.yaml" + bonds_file = f"{MODULE_DIR}/bonds_jmol_ob.yaml" with open(bonds_file) as file: yaml = YAML() self.el_radius = yaml.load(file) @@ -4226,7 +4226,7 @@ def from_preset(cls, preset) -> Self: A CutOffDictNN using the preset cut-off dictionary. """ if preset == "vesta_2019": - cut_offs = loadfn(f"{module_dir}/vesta_cutoffs.yaml") + cut_offs = loadfn(f"{MODULE_DIR}/vesta_cutoffs.yaml") return cls(cut_off_dict=cut_offs) raise ValueError(f"Unknown {preset=}") diff --git a/src/pymatgen/analysis/pourbaix_diagram.py b/src/pymatgen/analysis/pourbaix_diagram.py index 135f2abbabf..fcd9e2f90a8 100644 --- a/src/pymatgen/analysis/pourbaix_diagram.py +++ b/src/pymatgen/analysis/pourbaix_diagram.py @@ -604,8 +604,7 @@ def _preprocess_pourbaix_entries(self, entries, nproc=None): else: # Serial processing of multi-entry generation for combo in all_combos: - multi_entry = self.process_multientry(combo, prod_comp=tot_comp) - if multi_entry: + if multi_entry := self.process_multientry(combo, prod_comp=tot_comp): multi_entries.append(multi_entry) return multi_entries diff --git a/src/pymatgen/analysis/prototypes.py b/src/pymatgen/analysis/prototypes.py index a9cdf29c70c..b47d8445cb4 100644 --- a/src/pymatgen/analysis/prototypes.py +++ b/src/pymatgen/analysis/prototypes.py @@ -24,8 +24,8 @@ if TYPE_CHECKING: from pymatgen.core import Structure -module_dir = os.path.dirname(os.path.abspath(__file__)) -AFLOW_PROTOTYPE_LIBRARY = loadfn(f"{module_dir}/aflow_prototypes.json") +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) +AFLOW_PROTOTYPE_LIBRARY = loadfn(f"{MODULE_DIR}/aflow_prototypes.json") @due.dcite( diff --git a/src/pymatgen/analysis/reaction_calculator.py b/src/pymatgen/analysis/reaction_calculator.py index 26f5766dd36..9c7933c2690 100644 --- a/src/pymatgen/analysis/reaction_calculator.py +++ b/src/pymatgen/analysis/reaction_calculator.py @@ -2,7 +2,6 @@ from __future__ import annotations -import logging import re from itertools import chain, combinations from typing import TYPE_CHECKING, no_type_check, overload @@ -32,9 +31,6 @@ __date__ = "Jul 11 2012" -logger = logging.getLogger(__name__) - - class BalancedReaction(MSONable): """Represent a complete chemical reaction.""" diff --git a/src/pymatgen/analysis/structure_matcher.py b/src/pymatgen/analysis/structure_matcher.py index cf6e890c9e7..2166d603b5c 100644 --- a/src/pymatgen/analysis/structure_matcher.py +++ b/src/pymatgen/analysis/structure_matcher.py @@ -968,8 +968,7 @@ def get_rms_anonymous(self, struct1, struct2): struct1, struct2 = self._process_species([struct1, struct2]) struct1, struct2, fu, s1_supercell = self._preprocess(struct1, struct2) - matches = self._anonymous_match(struct1, struct2, fu, s1_supercell, use_rms=True, break_on_match=False) - if matches: + if matches := self._anonymous_match(struct1, struct2, fu, s1_supercell, use_rms=True, break_on_match=False): best = min(matches, key=lambda x: x[1][0]) return best[1][0], best[0] @@ -993,9 +992,7 @@ def get_best_electronegativity_anonymous_mapping(self, struct1: Structure, struc struct1, struct2 = self._process_species([struct1, struct2]) struct1, struct2, fu, s1_supercell = self._preprocess(struct1, struct2) - matches = self._anonymous_match(struct1, struct2, fu, s1_supercell, use_rms=True, break_on_match=True) - - if matches: + if matches := self._anonymous_match(struct1, struct2, fu, s1_supercell, use_rms=True, break_on_match=True): min_X_diff = np.inf best = None for match in matches: @@ -1027,8 +1024,7 @@ def get_all_anonymous_mappings(self, struct1, struct2, niggli=True, include_dist struct1, struct2 = self._process_species([struct1, struct2]) struct1, struct2, fu, s1_supercell = self._preprocess(struct1, struct2, niggli) - matches = self._anonymous_match(struct1, struct2, fu, s1_supercell, break_on_match=not include_dist) - if matches: + if matches := self._anonymous_match(struct1, struct2, fu, s1_supercell, break_on_match=not include_dist): if include_dist: return [(m[0], m[1][0]) for m in matches] diff --git a/src/pymatgen/analysis/transition_state.py b/src/pymatgen/analysis/transition_state.py index 5dbbe1fbb54..4f76801aa79 100644 --- a/src/pymatgen/analysis/transition_state.py +++ b/src/pymatgen/analysis/transition_state.py @@ -248,8 +248,7 @@ def from_dir(cls, root_dir, relaxation_dirs=None, **kwargs) -> Self: if terminal: for ds in terminal_dirs: od = ds[0] if idx == 0 else ds[1] - outcar = glob(f"{od}/OUTCAR*") - if outcar: + if outcar := glob(f"{od}/OUTCAR*"): outcar = sorted(outcar) outcars.append(Outcar(outcar[-1])) break diff --git a/src/pymatgen/apps/borg/hive.py b/src/pymatgen/apps/borg/hive.py index a90380d0dee..81e65495dd5 100644 --- a/src/pymatgen/apps/borg/hive.py +++ b/src/pymatgen/apps/borg/hive.py @@ -418,8 +418,7 @@ def from_dict(cls, dct: dict) -> Self: def _get_transformation_history(path): """Check for a transformations.json* file and returns the history.""" - trans_json = glob(f"{path}/transformations.json*") - if trans_json: + if trans_json := glob(f"{path}/transformations.json*"): try: with zopen(trans_json[0]) as file: return json.load(file)["history"] diff --git a/src/pymatgen/apps/borg/queen.py b/src/pymatgen/apps/borg/queen.py index 27e8f92c130..86ed6c57485 100644 --- a/src/pymatgen/apps/borg/queen.py +++ b/src/pymatgen/apps/borg/queen.py @@ -110,8 +110,7 @@ def load_data(self, filename): def order_assimilation(args): """Internal helper method for BorgQueen to process assimilation.""" path, drone, data, status = args - new_data = drone.assimilate(path) - if new_data: + if new_data := drone.assimilate(path): data.append(json.dumps(new_data, cls=MontyEncoder)) status["count"] += 1 count = status["count"] diff --git a/src/pymatgen/command_line/critic2_caller.py b/src/pymatgen/command_line/critic2_caller.py index 4f6261afe3e..3c359fedda8 100644 --- a/src/pymatgen/command_line/critic2_caller.py +++ b/src/pymatgen/command_line/critic2_caller.py @@ -277,17 +277,16 @@ def from_path(cls, path, suffix="", zpsp=None) -> Self: chgcar = Chgcar.from_file(chgcar_path) chgcar_ref = None - if not zpsp: - potcar_path = get_filepath( + if not zpsp and ( + potcar_path := get_filepath( "POTCAR", "Could not find POTCAR, will not be able to calculate charge transfer.", path, suffix, ) - - if potcar_path: - potcar = Potcar.from_file(potcar_path) - zpsp = {p.element: p.zval for p in potcar} + ): + potcar = Potcar.from_file(potcar_path) + zpsp = {p.element: p.zval for p in potcar} if not zpsp: # try and get reference "all-electron-like" charge density if zpsp not present diff --git a/src/pymatgen/command_line/gulp_caller.py b/src/pymatgen/command_line/gulp_caller.py index b13912f2433..58ea510fb38 100644 --- a/src/pymatgen/command_line/gulp_caller.py +++ b/src/pymatgen/command_line/gulp_caller.py @@ -23,7 +23,7 @@ __status__ = "Production" __date__ = "Jun 22, 2013M" -module_dir = os.path.dirname(os.path.abspath(__file__)) +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) _anions = set(map(Element, ["O", "S", "F", "Cl", "Br", "N", "P"])) _cations = set( @@ -868,7 +868,7 @@ class TersoffPotential: def __init__(self): """Init TersoffPotential.""" - with open(f"{module_dir}/OxideTersoffPotentials") as file: + with open(f"{MODULE_DIR}/OxideTersoffPotentials") as file: data = {} for row in file: metaloxi = row.split()[0] diff --git a/src/pymatgen/core/composition.py b/src/pymatgen/core/composition.py index 168591cbff4..9d28a18be56 100644 --- a/src/pymatgen/core/composition.py +++ b/src/pymatgen/core/composition.py @@ -31,7 +31,7 @@ from pymatgen.util.typing import SpeciesLike -module_dir = os.path.dirname(os.path.abspath(__file__)) +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) @total_ordering @@ -959,7 +959,7 @@ def _get_oxi_state_guesses( # Load prior probabilities of oxidation states, used to rank solutions if not type(self).oxi_prob: - all_data = loadfn(f"{module_dir}/../analysis/icsd_bv.yaml") + all_data = loadfn(f"{MODULE_DIR}/../analysis/icsd_bv.yaml") type(self).oxi_prob = {Species.from_str(sp): data for sp, data in all_data["occurrence"].items()} oxi_states_override = oxi_states_override or {} # Assert Composition only has integer amounts diff --git a/src/pymatgen/core/periodic_table.py b/src/pymatgen/core/periodic_table.py index d8a2d9cadd9..d4e3cbd7fcb 100644 --- a/src/pymatgen/core/periodic_table.py +++ b/src/pymatgen/core/periodic_table.py @@ -380,10 +380,8 @@ def average_cationic_radius(self) -> FloatWithUnit: taken over all positive oxidation states of the element for which data is present. """ - if "Ionic radii" in self._data: - radii = [v for k, v in self._data["Ionic radii"].items() if int(k) > 0] - if radii: - return FloatWithUnit(sum(radii) / len(radii), "ang") + if "Ionic radii" in self._data and (radii := [v for k, v in self._data["Ionic radii"].items() if int(k) > 0]): + return FloatWithUnit(sum(radii) / len(radii), "ang") return FloatWithUnit(0.0, "ang") @property @@ -392,10 +390,8 @@ def average_anionic_radius(self) -> FloatWithUnit: taken over all negative oxidation states of the element for which data is present. """ - if "Ionic radii" in self._data: - radii = [v for k, v in self._data["Ionic radii"].items() if int(k) < 0] - if radii: - return FloatWithUnit(sum(radii) / len(radii), "ang") + if "Ionic radii" in self._data and (radii := [v for k, v in self._data["Ionic radii"].items() if int(k) < 0]): + return FloatWithUnit(sum(radii) / len(radii), "ang") return FloatWithUnit(0.0, "ang") @property diff --git a/src/pymatgen/core/surface.py b/src/pymatgen/core/surface.py index 8eed9340450..3e0d5086b7b 100644 --- a/src/pymatgen/core/surface.py +++ b/src/pymatgen/core/surface.py @@ -1680,8 +1680,8 @@ def generate_all_slabs( # Load the reconstructions_archive JSON file -module_dir = os.path.dirname(os.path.abspath(__file__)) -with open(f"{module_dir}/reconstructions_archive.json", encoding="utf-8") as data_file: +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) +with open(f"{MODULE_DIR}/reconstructions_archive.json", encoding="utf-8") as data_file: RECONSTRUCTIONS_ARCHIVE = json.load(data_file) diff --git a/src/pymatgen/io/abinit/inputs.py b/src/pymatgen/io/abinit/inputs.py index 180fabff915..0c0854af881 100644 --- a/src/pymatgen/io/abinit/inputs.py +++ b/src/pymatgen/io/abinit/inputs.py @@ -1059,8 +1059,7 @@ def __init__(self, structure: Structure | Sequence[Structure], pseudos, pseudo_d pseudo_dir = os.path.abspath(pseudo_dir) pseudo_paths = [os.path.join(pseudo_dir, p) for p in pseudos] - missing = [p for p in pseudo_paths if not os.path.isfile(p)] - if missing: + if missing := [p for p in pseudo_paths if not os.path.isfile(p)]: raise self.Error(f"Cannot find the following pseudopotential files:\n{missing}") pseudos = PseudoTable(pseudo_paths) diff --git a/src/pymatgen/io/abinit/pseudos.py b/src/pymatgen/io/abinit/pseudos.py index 345f6dc652c..e2a5ec6815a 100644 --- a/src/pymatgen/io/abinit/pseudos.py +++ b/src/pymatgen/io/abinit/pseudos.py @@ -1540,8 +1540,7 @@ def from_dir(cls, top, exts=None, exclude_dirs="_*") -> Self | None: for filepath in [os.path.join(top, fn) for fn in os.listdir(top)]: if os.path.isfile(filepath): try: - pseudo = Pseudo.from_file(filepath) - if pseudo: + if pseudo := Pseudo.from_file(filepath): pseudos.append(pseudo) else: logger.info(f"Skipping file {filepath}") diff --git a/src/pymatgen/io/aims/sets/base.py b/src/pymatgen/io/aims/sets/base.py index 5f266a21a0c..8f5893d1912 100644 --- a/src/pymatgen/io/aims/sets/base.py +++ b/src/pymatgen/io/aims/sets/base.py @@ -4,7 +4,6 @@ import copy import json -import logging from dataclasses import dataclass, field from typing import TYPE_CHECKING, Any from warnings import warn @@ -31,8 +30,6 @@ DEFAULT_AIMS_PROPERTIES = ("energy", "free_energy", "forces", "stress", "stresses", "dipole", "magmom") -logger = logging.getLogger(__name__) - class AimsInputSet(InputSet): """A class to represent a set of Aims inputs.""" diff --git a/src/pymatgen/io/cp2k/outputs.py b/src/pymatgen/io/cp2k/outputs.py index ec539e97329..0258f19a0a0 100644 --- a/src/pymatgen/io/cp2k/outputs.py +++ b/src/pymatgen/io/cp2k/outputs.py @@ -5,7 +5,6 @@ from __future__ import annotations -import logging import os import re import warnings @@ -32,8 +31,6 @@ __version__ = "2.0" __status__ = "Production" -logger = logging.getLogger(__name__) - class Cp2kOutput: """Parse output file from CP2K. The CP2K output file is very flexible in the way that @@ -932,13 +929,12 @@ def parse_mulliken(self): pattern = r"\s+(\d)\s+(\w+)\s+(\d+)\s+(-?\d+\.\d+)\s+(-?\d+\.\d+)" footer = r".+Total charge" - d = self.read_table_pattern( + if self.read_table_pattern( header_pattern=header, row_pattern=pattern, footer_pattern=footer, last_one_only=False, - ) - if d: + ): print("Found data, but not yet implemented!") def parse_hirshfeld(self): diff --git a/src/pymatgen/io/feff/outputs.py b/src/pymatgen/io/feff/outputs.py index 9d5d00137d9..17b1d7be841 100644 --- a/src/pymatgen/io/feff/outputs.py +++ b/src/pymatgen/io/feff/outputs.py @@ -122,12 +122,11 @@ def from_file(cls, feff_inp_file: str = "feff.inp", ldos_file: str = "ldos") -> all_pdos.append(defaultdict(dict)) for k, v in vorb.items(): density = [ldos[pot_index][j][forb[k] + 1] for j in range(d_length)] - updos = density - downdos = None - if downdos: - all_pdos[-1][v] = {Spin.up: updos, Spin.down: downdos} + up_dos = density + if down_dos := None: + all_pdos[-1][v] = {Spin.up: up_dos, Spin.down: down_dos} else: - all_pdos[-1][v] = {Spin.up: updos} + all_pdos[-1][v] = {Spin.up: up_dos} pdos = all_pdos vorb2 = {0: Orbital.s, 1: Orbital.py, 2: Orbital.dxy, 3: Orbital.f0} diff --git a/src/pymatgen/io/lammps/generators.py b/src/pymatgen/io/lammps/generators.py index afc2f39b5dc..171d393448f 100644 --- a/src/pymatgen/io/lammps/generators.py +++ b/src/pymatgen/io/lammps/generators.py @@ -9,7 +9,6 @@ from __future__ import annotations -import logging import os from dataclasses import dataclass, field from string import Template @@ -26,9 +25,8 @@ __copyright__ = "Copyright 2021, The Materials Project" __version__ = "0.2" -logger = logging.getLogger(__name__) -module_dir = os.path.dirname(os.path.abspath(__file__)) -template_dir = f"{module_dir}/templates" +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) +TEMPLATE_DIR = f"{MODULE_DIR}/templates" @dataclass @@ -128,7 +126,7 @@ def __init__( If False, stage names are not printed and all commands appear in a single block. """ if template is None: - template = f"{template_dir}/minimization.template" + template = f"{TEMPLATE_DIR}/minimization.template" settings = { "units": units, "atom_style": atom_style, diff --git a/src/pymatgen/io/lammps/inputs.py b/src/pymatgen/io/lammps/inputs.py index 0a5742898d2..18c3cdd52ab 100644 --- a/src/pymatgen/io/lammps/inputs.py +++ b/src/pymatgen/io/lammps/inputs.py @@ -39,8 +39,8 @@ __email__ = "z4deng@eng.ucsd.edu, info@matgenix.com" __date__ = "Nov 2022" -module_dir = os.path.dirname(os.path.abspath(__file__)) -template_dir = f"{module_dir}/templates" +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) +TEMPLATE_DIR = f"{MODULE_DIR}/templates" class LammpsInputFile(InputFile): @@ -907,7 +907,7 @@ def md( other_settings (dict): other settings to be filled into placeholders. """ - template_path = os.path.join(template_dir, "md.template") + template_path = os.path.join(TEMPLATE_DIR, "md.template") with open(template_path, encoding="utf-8") as file: script_template = file.read() settings = other_settings.copy() if other_settings else {} diff --git a/src/pymatgen/io/lammps/sets.py b/src/pymatgen/io/lammps/sets.py index 85d11f81410..4aab10d3a2b 100644 --- a/src/pymatgen/io/lammps/sets.py +++ b/src/pymatgen/io/lammps/sets.py @@ -9,7 +9,6 @@ from __future__ import annotations -import logging import os from typing import TYPE_CHECKING @@ -26,9 +25,7 @@ __copyright__ = "Copyright 2021, The Materials Project" __version__ = "0.2" -logger = logging.getLogger(__name__) -module_dir = os.path.dirname(os.path.abspath(__file__)) -template_dir = f"{module_dir}/templates" +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) class LammpsInputSet(InputSet): diff --git a/src/pymatgen/io/optimade.py b/src/pymatgen/io/optimade.py index cbc1237a5d3..af620b07220 100644 --- a/src/pymatgen/io/optimade.py +++ b/src/pymatgen/io/optimade.py @@ -175,8 +175,7 @@ def get_structure(resource: dict) -> Structure: properties: dict[str, Any] = {"optimade_id": _id} # Take any prefixed attributes and save them as properties - custom_properties = {k: v for k, v in attributes.items() if k.startswith("_")} - if custom_properties: + if custom_properties := {k: v for k, v in attributes.items() if k.startswith("_")}: properties["optimade_attributes"] = custom_properties return Structure( diff --git a/src/pymatgen/io/qchem/inputs.py b/src/pymatgen/io/qchem/inputs.py index 38ef5909971..12bd21cb6dc 100644 --- a/src/pymatgen/io/qchem/inputs.py +++ b/src/pymatgen/io/qchem/inputs.py @@ -2,7 +2,6 @@ from __future__ import annotations -import logging import re from typing import TYPE_CHECKING @@ -26,8 +25,6 @@ __email__ = "samblau1@gmail.com" __credits__ = "Xiaohui Qu" -logger = logging.getLogger(__name__) - class QCInput(InputFile): """ diff --git a/src/pymatgen/io/qchem/outputs.py b/src/pymatgen/io/qchem/outputs.py index c2cccd2ddc9..c3244adfb7b 100644 --- a/src/pymatgen/io/qchem/outputs.py +++ b/src/pymatgen/io/qchem/outputs.py @@ -3,7 +3,6 @@ from __future__ import annotations import copy -import logging import math import os import re @@ -45,8 +44,6 @@ __email__ = "samblau1@gmail.com" __credits__ = "Gabe Gomes" -logger = logging.getLogger(__name__) - class QCOutput(MSONable): """Parse QChem output files.""" diff --git a/src/pymatgen/io/qchem/sets.py b/src/pymatgen/io/qchem/sets.py index d85cfbad903..56fa235f1a3 100644 --- a/src/pymatgen/io/qchem/sets.py +++ b/src/pymatgen/io/qchem/sets.py @@ -2,7 +2,6 @@ from __future__ import annotations -import logging import os import warnings from typing import TYPE_CHECKING @@ -24,8 +23,6 @@ __maintainer__ = "Samuel Blau" __email__ = "samblau1@gmail.com" -logger = logging.getLogger(__name__) - # Note that in addition to the solvent-specific parameters, this dict contains # dielectric constants for use with each solvent. The dielectric constants # are used by the isodensity SS(V)PE electrostatic calculation part of CMIRS diff --git a/src/pymatgen/io/vasp/help.py b/src/pymatgen/io/vasp/help.py index 7a0a508950f..0bc29497bda 100644 --- a/src/pymatgen/io/vasp/help.py +++ b/src/pymatgen/io/vasp/help.py @@ -62,11 +62,9 @@ def get_help(cls, tag: str, fmt: str = "text") -> str: main_doc = soup.find(id="mw-content-text") if fmt == "text": output = main_doc.text - output = re.sub("\n{2,}", "\n\n", output) - else: - output = str(main_doc) + return re.sub("\n{2,}", "\n\n", output) - return output + return str(main_doc) @classmethod def get_incar_tags(cls) -> list[str]: @@ -83,9 +81,3 @@ def get_incar_tags(cls) -> list[str]: for child in children: tags.append(child.text.strip()) return tags - - -if __name__ == "__main__": - doc = VaspDoc() - doc.print_help("ISYM") - print(doc.get_incar_tags()) diff --git a/src/pymatgen/io/vasp/inputs.py b/src/pymatgen/io/vasp/inputs.py index 8c12dad8279..58fd67cabc1 100644 --- a/src/pymatgen/io/vasp/inputs.py +++ b/src/pymatgen/io/vasp/inputs.py @@ -9,7 +9,6 @@ import hashlib import itertools import json -import logging import math import os import re @@ -39,7 +38,7 @@ from pymatgen.util.typing import Kpoint, Tuple3Floats, Tuple3Ints, Vector3D if TYPE_CHECKING: - from collections.abc import Iterator, Sequence + from collections.abc import Sequence from typing import Any, ClassVar, Literal from numpy.typing import ArrayLike @@ -52,12 +51,11 @@ __author__ = "Shyue Ping Ong, Geoffroy Hautier, Rickard Armiento, Vincent L Chevrier, Stephen Dacek" __copyright__ = "Copyright 2011, The Materials Project" -logger = logging.getLogger(__name__) -module_dir = os.path.dirname(os.path.abspath(__file__)) +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) class Poscar(MSONable): - """Object for representing the data in a POSCAR or CONTCAR file. + """Represent the data in a POSCAR or CONTCAR file. Attributes: structure: Associated Structure. @@ -112,38 +110,38 @@ def __init__( sort_structure (bool, optional): Whether to sort the structure. Useful if species are not grouped properly together. Defaults to False. """ - if structure.is_ordered: - site_properties = {} - - if selective_dynamics is not None: - selective_dynamics = np.array(selective_dynamics) - if not selective_dynamics.all(): - site_properties["selective_dynamics"] = selective_dynamics - - if velocities: - velocities = np.array(velocities) - if velocities.any(): - site_properties["velocities"] = velocities - - if predictor_corrector: - predictor_corrector = np.array(predictor_corrector) - if predictor_corrector.any(): - site_properties["predictor_corrector"] = predictor_corrector - - structure = Structure.from_sites(structure) - self.structure = structure.copy(site_properties=site_properties) - if sort_structure: - self.structure = self.structure.get_sorted_structure() - self.true_names = true_names - self.comment = structure.formula if comment is None else comment - if predictor_corrector_preamble: - self.structure.properties["predictor_corrector_preamble"] = predictor_corrector_preamble - - if lattice_velocities and np.any(lattice_velocities): - self.structure.properties["lattice_velocities"] = np.asarray(lattice_velocities) - else: + if not structure.is_ordered: raise ValueError("Disordered structure with partial occupancies cannot be converted into POSCAR!") + site_properties: dict[str, Any] = {} + + if selective_dynamics is not None: + selective_dynamics = np.array(selective_dynamics) + if not selective_dynamics.all(): + site_properties["selective_dynamics"] = selective_dynamics + + if velocities: + velocities = np.array(velocities) + if velocities.any(): + site_properties["velocities"] = velocities + + if predictor_corrector: + predictor_corrector = np.array(predictor_corrector) + if predictor_corrector.any(): + site_properties["predictor_corrector"] = predictor_corrector + + structure = Structure.from_sites(structure) + self.structure = structure.copy(site_properties=site_properties) + if sort_structure: + self.structure = self.structure.get_sorted_structure() + self.true_names = true_names + self.comment = structure.formula if comment is None else comment + if predictor_corrector_preamble: + self.structure.properties["predictor_corrector_preamble"] = predictor_corrector_preamble + + if lattice_velocities and np.any(lattice_velocities): + self.structure.properties["lattice_velocities"] = np.asarray(lattice_velocities) + self.temperature = -1.0 def __setattr__(self, name: str, value: Any) -> None: @@ -168,49 +166,44 @@ def velocities(self) -> ArrayLike | None: """Velocities in Poscar.""" return self.structure.site_properties.get("velocities") + @velocities.setter + def velocities(self, velocities: ArrayLike | None) -> None: + self.structure.add_site_property("velocities", velocities) + @property def selective_dynamics(self) -> ArrayLike | None: """Selective dynamics in Poscar.""" return self.structure.site_properties.get("selective_dynamics") + @selective_dynamics.setter + def selective_dynamics(self, selective_dynamics: ArrayLike | None) -> None: + self.structure.add_site_property("selective_dynamics", selective_dynamics) + @property def predictor_corrector(self) -> ArrayLike | None: """Predictor corrector in Poscar.""" return self.structure.site_properties.get("predictor_corrector") + @predictor_corrector.setter + def predictor_corrector(self, predictor_corrector: ArrayLike | None) -> None: + self.structure.add_site_property("predictor_corrector", predictor_corrector) + @property def predictor_corrector_preamble(self) -> str | None: """Predictor corrector preamble in Poscar.""" return self.structure.properties.get("predictor_corrector_preamble") + @predictor_corrector_preamble.setter + def predictor_corrector_preamble(self, predictor_corrector_preamble: str | None) -> None: + self.structure.properties["predictor_corrector"] = predictor_corrector_preamble + @property def lattice_velocities(self) -> ArrayLike | None: """Lattice velocities in Poscar (including the current lattice vectors).""" return self.structure.properties.get("lattice_velocities") - @velocities.setter # type: ignore[no-redef, attr-defined] - def velocities(self, velocities: ArrayLike | None) -> None: - """Setter for Poscar.velocities.""" - self.structure.add_site_property("velocities", velocities) - - @selective_dynamics.setter # type: ignore[no-redef, attr-defined] - def selective_dynamics(self, selective_dynamics: ArrayLike | None) -> None: - """Setter for Poscar.selective_dynamics.""" - self.structure.add_site_property("selective_dynamics", selective_dynamics) - - @predictor_corrector.setter # type: ignore[no-redef, attr-defined] - def predictor_corrector(self, predictor_corrector: ArrayLike | None) -> None: - """Setter for Poscar.predictor_corrector.""" - self.structure.add_site_property("predictor_corrector", predictor_corrector) - - @predictor_corrector_preamble.setter # type: ignore[no-redef, attr-defined] - def predictor_corrector_preamble(self, predictor_corrector_preamble: str | None) -> None: - """Setter for Poscar.predictor_corrector.""" - self.structure.properties["predictor_corrector"] = predictor_corrector_preamble - - @lattice_velocities.setter # type: ignore[no-redef, attr-defined] + @lattice_velocities.setter def lattice_velocities(self, lattice_velocities: ArrayLike | None) -> None: - """Setter for Poscar.lattice_velocities.""" self.structure.properties["lattice_velocities"] = np.asarray(lattice_velocities) @property @@ -222,7 +215,7 @@ def site_symbols(self) -> list[str]: @property def natoms(self) -> list[int]: """Sequence of number of sites of each type associated with the Poscar. - Similar to 7th line in vasp 5+ POSCAR or the 6th line in vasp 4 POSCAR. + Similar to 7th line in VASP 5+ POSCAR or the 6th line in VASP 4 POSCAR. """ syms: list[str] = [site.specie.symbol for site in self.structure] return [len(tuple(a[1])) for a in itertools.groupby(syms)] @@ -272,15 +265,17 @@ def from_file( dirname: str = os.path.dirname(os.path.abspath(filename)) names: list[str] | None = None - if check_for_potcar and SETTINGS.get("PMG_POTCAR_CHECKS") is not False: - potcars = glob(f"{dirname}/*POTCAR*") - if potcars: - try: - potcar = Potcar.from_file(min(potcars)) - names = [sym.split("_")[0] for sym in potcar.symbols] - [get_el_sp(n) for n in names] # ensure valid names - except Exception: - names = None + if ( + check_for_potcar + and SETTINGS.get("PMG_POTCAR_CHECKS") is not False + and (potcars := glob(f"{dirname}/*POTCAR*")) + ): + try: + potcar = Potcar.from_file(min(potcars)) + names = [sym.split("_")[0] for sym in potcar.symbols] + map(get_el_sp, names) # ensure valid names + except Exception: + names = None with zopen(filename, mode="rt") as file: return cls.from_str(file.read(), names, read_velocities=read_velocities) @@ -339,7 +334,7 @@ def from_str( scale: float = float(lines[1]) lattice: np.ndarray = np.array([[float(i) for i in line.split()] for line in lines[2:5]]) if scale < 0: - # In vasp, a negative scale factor is treated as a volume. We need + # In VASP, a negative scale factor is treated as a volume. We need # to translate this to a proper lattice vector scaling. vol: float = abs(np.linalg.det(lattice)) lattice *= (-scale / vol) ** (1 / 3) @@ -357,7 +352,7 @@ def from_str( vasp5_symbols = True symbols: list[str] = [symbol.split("/")[0] for symbol in lines[5].split()] - # Atoms and number of atoms in POSCAR written with vasp appear on + # Atoms and number of atoms in POSCAR written with VASP appear on # multiple lines when atoms of the same type are not grouped together # and more than 20 groups are then defined ... # Example : @@ -533,13 +528,13 @@ def get_str( significant_figures: int = 16, ) -> str: """Return a string to be written as a POSCAR file. By default, site - symbols are written, which is compatible for vasp >= 5. + symbols are written, which is compatible for VASP >= 5. Args: direct (bool): Whether coordinates are output in direct or Cartesian. Defaults to True. vasp4_compatible (bool): Set to True to omit site symbols on 6th - line to maintain backward vasp 4.x compatibility. Defaults + line to maintain backward VASP 4.x compatibility. Defaults to False. significant_figures (int): Number of significant digits to output all quantities. Defaults to 16. Note that positions are @@ -705,7 +700,7 @@ class BadPoscarWarning(UserWarning): class Incar(dict, MSONable): """ - INCAR object for reading and writing INCAR files. + Read and write INCAR files. Essentially a dictionary with some helper functions. """ @@ -1017,7 +1012,7 @@ def check_params(self) -> None: will ignore the tag and set it as default without letting you know. """ # Load INCAR tag/value check reference file - with open(os.path.join(module_dir, "incar_parameters.json"), encoding="utf-8") as json_file: + with open(os.path.join(MODULE_DIR, "incar_parameters.json"), encoding="utf-8") as json_file: incar_params = json.loads(json_file.read()) for tag, val in self.items(): @@ -1076,7 +1071,7 @@ def from_str(cls, mode: str) -> Self: class Kpoints(MSONable): """KPOINTS reader/writer.""" - supported_modes = KpointsSupportedModes + supported_modes: ClassVar[type[KpointsSupportedModes]] = KpointsSupportedModes def __init__( self, @@ -1101,6 +1096,9 @@ def __init__( constructors (automatic, gamma_automatic, monkhorst_automatic) and it is recommended that you use those. + The default behavior of the constructor is for a Gamma-centered, + 1x1x1 KPOINTS with no shift. + Args: comment (str): String comment for Kpoints. Defaults to "Default gamma". num_kpts: Following VASP method of defining the KPOINTS file, this @@ -1127,9 +1125,6 @@ def __init__( of the tetrahedrons for the tetrahedron method. Format is a list of tuples, [ (sym_weight, [tet_vertices]), ...] - - The default behavior of the constructor is for a Gamma centered, - 1x1x1 KPOINTS with no shift. """ if num_kpts > 0 and not labels and not kpts_weights: raise ValueError("For explicit or line-mode kpoints, either the labels or kpts_weights must be specified.") @@ -1171,7 +1166,7 @@ def __repr__(self) -> str: else: lines[-1] += f" {int(self.kpts_weights[idx])}" - # Print tetrahedron parameters if the number of tetrahedrons > 0 + # Tetrahedron parameters if the number of tetrahedrons > 0 if style not in "lagm" and self.tet_number > 0: lines.extend(("Tetrahedron", f"{self.tet_number} {self.tet_weight:f}")) if self.tet_connections is not None: @@ -1179,7 +1174,7 @@ def __repr__(self) -> str: a, b, c, d = vertices lines.append(f"{sym_weight} {a} {b} {c} {d}") - # Print shifts for automatic kpoints types if not zero. + # Shifts for automatic kpoints types if not zero if self.num_kpts <= 0 and tuple(self.kpts_shift) != (0, 0, 0): lines.append(" ".join(map(str, self.kpts_shift))) return "\n".join(lines) + "\n" @@ -1209,11 +1204,11 @@ def style(self) -> KpointsSupportedModes: return self._style @style.setter - def style(self, style) -> None: + def style(self, style: str | KpointsSupportedModes) -> None: """Set the style for the Kpoints. One of Kpoints_supported_modes enum. Args: - style: Style + style (str | KpointsSupportedModes): Style """ if isinstance(style, str): style = type(self).supported_modes.from_str(style) @@ -1239,7 +1234,7 @@ def style(self, style) -> None: def automatic(cls, subdivisions: int) -> Self: """ Constructor for a fully automatic Kpoint grid, with - gamma centered Monkhorst-Pack grids and the number of subdivisions + Gamma-centered grids and the number of subdivisions along each reciprocal lattice vector determined by the scheme in the VASP manual. @@ -1248,7 +1243,7 @@ def automatic(cls, subdivisions: int) -> Self: each reciprocal lattice vector. Returns: - Kpoints object + Kpoints """ return cls( "Fully automatic kpoint scheme", @@ -1262,7 +1257,7 @@ def automatic(cls, subdivisions: int) -> Self: @classmethod def gamma_automatic(cls, kpts: Kpoint = (1, 1, 1), shift: Vector3D = (0, 0, 0)) -> Self: """ - Constructor for an automatic Gamma centered Kpoint grid. + Construct an automatic Gamma-centered Kpoint grid. Args: kpts: Subdivisions N_1, N_2 and N_3 along reciprocal lattice @@ -1270,15 +1265,14 @@ def gamma_automatic(cls, kpts: Kpoint = (1, 1, 1), shift: Vector3D = (0, 0, 0)) shift: Shift to be applied to the kpoints. Defaults to (0, 0, 0). Returns: - Kpoints object + Kpoints """ return cls("Automatic kpoint scheme", 0, cls.supported_modes.Gamma, kpts=[kpts], kpts_shift=shift) @classmethod def monkhorst_automatic(cls, kpts: Kpoint = (2, 2, 2), shift: Vector3D = (0, 0, 0)) -> Self: """ - Convenient static constructor for an automatic Monkhorst pack Kpoint - grid. + Construct an automatic Monkhorst-Pack Kpoint grid. Args: kpts: Subdivisions N_1, N_2, N_3 along reciprocal lattice @@ -1286,13 +1280,13 @@ def monkhorst_automatic(cls, kpts: Kpoint = (2, 2, 2), shift: Vector3D = (0, 0, shift: Shift to be applied to the kpoints. Defaults to (0, 0, 0). Returns: - Kpoints object + Kpoints """ return cls("Automatic kpoint scheme", 0, cls.supported_modes.Monkhorst, kpts=[kpts], kpts_shift=shift) @classmethod def automatic_density(cls, structure: Structure, kppa: float, force_gamma: bool = False) -> Self: - """Get an automatic Kpoint object based on a structure and a kpoint + """Get an automatic Kpoints object based on a structure and a kpoint density. Uses Gamma centered meshes for hexagonal cells and face-centered cells, Monkhorst-Pack grids otherwise. @@ -1337,7 +1331,7 @@ def automatic_density(cls, structure: Structure, kppa: float, force_gamma: bool @classmethod def automatic_gamma_density(cls, structure: Structure, kppa: float) -> Self: - """Get an automatic Kpoint object based on a structure and a kpoint + """Get an automatic Kpoints object based on a structure and a kpoint density. Uses Gamma centered meshes always. For GW. Algorithm: @@ -1376,7 +1370,7 @@ def automatic_gamma_density(cls, structure: Structure, kppa: float) -> Self: @classmethod def automatic_density_by_vol(cls, structure: Structure, kppvol: int, force_gamma: bool = False) -> Self: - """Get an automatic Kpoint object based on a structure and a kpoint + """Get an automatic Kpoints object based on a structure and a kpoint density per inverse Angstrom^3 of reciprocal cell. Algorithm: @@ -1398,11 +1392,11 @@ def automatic_density_by_vol(cls, structure: Structure, kppvol: int, force_gamma def automatic_density_by_lengths( cls, structure: Structure, length_densities: Sequence[float], force_gamma: bool = False ) -> Self: - """Get an automatic Kpoint object based on a structure and a k-point + """Get an automatic Kpoints object based on a structure and a k-point density normalized by lattice constants. Algorithm: - For a given dimension, the # of k-points is chosen as + For a given dimension, the number of k-points is chosen as length_density = # of kpoints * lattice constant, e.g. [50.0, 50.0, 1.0] would have k-points of 50/a x 50/b x 1/c. @@ -1520,7 +1514,7 @@ def from_str(cls, string: str) -> Self: coord_pattern = re.compile(r"^\s*([\d+.\-Ee]+)\s+([\d+.\-Ee]+)\s+([\d+.\-Ee]+)") - # Automatic gamma and Monk KPOINTS, with optional shift + # Automatic Gamma-centered or Monkhorst-Pack KPOINTS, with optional shift if style in {"g", "m"}: _kpt: list[float] = [float(i) for i in lines[3].split()] if len(_kpt) != 3: @@ -1727,10 +1721,10 @@ class OrbitalDescription(NamedTuple): # Hashes computed from the full POTCAR file contents by pymatgen (not 1st-party VASP hashes) -PYMATGEN_POTCAR_HASHES = loadfn(f"{module_dir}/vasp_potcar_pymatgen_hashes.json") +PYMATGEN_POTCAR_HASHES = loadfn(f"{MODULE_DIR}/vasp_potcar_pymatgen_hashes.json") # Written to some newer POTCARs by VASP -VASP_POTCAR_HASHES = loadfn(f"{module_dir}/vasp_potcar_file_hashes.json") -POTCAR_STATS_PATH: str = os.path.join(module_dir, "potcar-summary-stats.json.bz2") +VASP_POTCAR_HASHES = loadfn(f"{MODULE_DIR}/vasp_potcar_file_hashes.json") +POTCAR_STATS_PATH: str = os.path.join(MODULE_DIR, "potcar-summary-stats.json.bz2") class PotcarSingle: @@ -1930,8 +1924,8 @@ def __getattr__(self, attr: str) -> Any: """ try: return self.keywords[attr.upper()] - except Exception: - raise AttributeError(attr) + except Exception as exc: + raise AttributeError(attr) from exc def __str__(self) -> str: return f"{self.data}\n" @@ -2407,7 +2401,7 @@ def identify_potcar_hash_based( the PotcarSingle """ # Dict to translate the sets in the .json file to the keys used in VaspInputSet - mapping_dict = { + mapping_dict: dict[str, dict[str, str]] = { "potUSPP_GGA": { "pymatgen_key": "PW91_US", "vasp_description": "Ultrasoft pseudo potentials" @@ -2515,7 +2509,7 @@ def _gen_potcar_summary_stats( append: bool = False, vasp_psp_dir: str | None = None, summary_stats_filename: str | None = POTCAR_STATS_PATH, -): +) -> dict: """ Regenerate the reference data in potcar-summary-stats.json.bz2 used to validate POTCARs by comparing header values and several statistics of copyrighted POTCAR data without @@ -2577,7 +2571,7 @@ def _gen_potcar_summary_stats( class Potcar(list, MSONable): """Read and write POTCAR files for calculations. Consists of a list of PotcarSingle.""" - FUNCTIONAL_CHOICES = tuple(PotcarSingle.functional_dir) + FUNCTIONAL_CHOICES: ClassVar[tuple] = tuple(PotcarSingle.functional_dir) def __init__( self, @@ -2610,12 +2604,6 @@ def __init__( def __str__(self) -> str: return "\n".join(str(potcar).strip("\n") for potcar in self) + "\n" - def __iter__(self) -> Iterator[PotcarSingle]: - """Boilerplate code. Only here to supply type hint so - `for psingle in Potcar()` is correctly inferred as PotcarSingle. - """ - return super().__iter__() - @property def symbols(self) -> list[str]: """The atomic symbols of all the atoms in the POTCAR file.""" @@ -2720,7 +2708,7 @@ class UnknownPotcarWarning(UserWarning): class VaspInput(dict, MSONable): - """Contain a set of vasp input objects corresponding to a run.""" + """Contain a set of VASP input objects corresponding to a run.""" def __init__( self, @@ -2752,7 +2740,7 @@ def __init__( self._potcar_filename = "POTCAR" + (".spec" if potcar_spec else "") self |= {"INCAR": incar, "KPOINTS": kpoints, "POSCAR": poscar, self._potcar_filename: potcar} if optional_files is not None: - self.update(optional_files) + self |= optional_files def __str__(self) -> str: output: list = [] diff --git a/src/pymatgen/io/vasp/outputs.py b/src/pymatgen/io/vasp/outputs.py index 40634973a1f..457d238cb99 100644 --- a/src/pymatgen/io/vasp/outputs.py +++ b/src/pymatgen/io/vasp/outputs.py @@ -3,7 +3,6 @@ from __future__ import annotations import itertools -import logging import math import os import re @@ -55,8 +54,6 @@ from pymatgen.util.typing import PathLike -logger = logging.getLogger(__name__) - def _parse_parameters(val_type: str, val: str) -> bool | str | float | int: """ @@ -1241,25 +1238,21 @@ def update_charge_from_potcar(self, path: PathLike | bool) -> None: def as_dict(self) -> dict: """JSON-serializable dict representation.""" - dct = { + comp = self.final_structure.composition + unique_symbols = sorted(set(self.atomic_symbols)) + dct: dict[str, Any] = { "vasp_version": self.vasp_version, "has_vasp_completed": self.converged, "nsites": len(self.final_structure), + "unit_cell_formula": comp.as_dict(), + "reduced_cell_formula": Composition(comp.reduced_formula).as_dict(), + "pretty_formula": comp.reduced_formula, + "is_hubbard": self.is_hubbard, + "hubbards": self.hubbards, + "elements": unique_symbols, + "nelements": len(unique_symbols), + "run_type": self.run_type, } - comp = self.final_structure.composition - dct["unit_cell_formula"] = comp.as_dict() - dct["reduced_cell_formula"] = Composition(comp.reduced_formula).as_dict() - dct["pretty_formula"] = comp.reduced_formula - symbols = [s.split()[1] for s in self.potcar_symbols] - symbols = [re.split(r"_", s)[0] for s in symbols] - dct["is_hubbard"] = self.is_hubbard - dct["hubbards"] = self.hubbards - - unique_symbols = sorted(set(self.atomic_symbols)) - dct["elements"] = unique_symbols - dct["nelements"] = len(unique_symbols) - - dct["run_type"] = self.run_type vin: dict[str, Any] = { "incar": dict(self.incar.items()), @@ -1493,7 +1486,6 @@ def _parse_optical_transition(elem: XML_Element) -> tuple[NDArray, NDArray]: def _parse_chemical_shielding(self, elem: XML_Element) -> list[dict[str, Any]]: """Parse NMR chemical shielding.""" - calculation = [] istep: dict[str, Any] = {} # not all calculations have a structure _struct = elem.find("structure") @@ -1503,7 +1495,9 @@ def _parse_chemical_shielding(self, elem: XML_Element) -> list[dict[str, Any]]: istep[va.attrib["name"]] = _parse_vasp_array(va) istep["structure"] = struct istep["electronic_steps"] = [] - calculation.append(istep) + calculation = [ + istep, + ] for scstep in elem.findall("scstep"): try: e_steps_dict = {i.attrib["name"]: _vasprun_float(i.text) for i in scstep.find("energy").findall("i")} # type: ignore[union-attr, arg-type] @@ -1763,25 +1757,22 @@ def __init__( def as_dict(self) -> dict: """JSON-serializable dict representation.""" + comp = self.final_structure.composition + unique_symbols = sorted(set(self.atomic_symbols)) dct = { "vasp_version": self.vasp_version, "has_vasp_completed": True, "nsites": len(self.final_structure), + "unit_cell_formula": comp.as_dict(), + "reduced_cell_formula": Composition(comp.reduced_formula).as_dict(), + "pretty_formula": comp.reduced_formula, + "is_hubbard": self.is_hubbard, + "hubbards": self.hubbards, + "elements": unique_symbols, + "nelements": len(unique_symbols), + "run_type": self.run_type, } - comp = self.final_structure.composition - dct["unit_cell_formula"] = comp.as_dict() - dct["reduced_cell_formula"] = Composition(comp.reduced_formula).as_dict() - dct["pretty_formula"] = comp.reduced_formula - dct["is_hubbard"] = self.is_hubbard - dct["hubbards"] = self.hubbards - - unique_symbols = sorted(set(self.atomic_symbols)) - dct["elements"] = unique_symbols - dct["nelements"] = len(unique_symbols) - - dct["run_type"] = self.run_type - vin: dict[str, Any] = { "incar": dict(self.incar), "crystal": self.final_structure.as_dict(), diff --git a/src/pymatgen/io/vasp/sets.py b/src/pymatgen/io/vasp/sets.py index 08ce0dedb18..b394fbf46aa 100644 --- a/src/pymatgen/io/vasp/sets.py +++ b/src/pymatgen/io/vasp/sets.py @@ -828,21 +828,21 @@ def kpoints(self) -> Kpoints | None: density = kconfig["reciprocal_density"] base_kpoints = Kpoints.automatic_density_by_vol(self.structure, density, self.force_gamma) - if explicit and base_kpoints is not None: - sga = SpacegroupAnalyzer(self.structure, symprec=self.sym_prec) - mesh = sga.get_ir_reciprocal_mesh(base_kpoints.kpts[0]) - base_kpoints = Kpoints( - comment="Uniform grid", - style=Kpoints.supported_modes.Reciprocal, - num_kpts=len(mesh), - kpts=tuple(i[0] for i in mesh), - kpts_weights=[i[1] for i in mesh], - ) - else: + if not explicit or base_kpoints is None: # If not explicit that means no other options have been specified # so we can return the k-points as is return base_kpoints + sga = SpacegroupAnalyzer(self.structure, symprec=self.sym_prec) + mesh = sga.get_ir_reciprocal_mesh(base_kpoints.kpts[0]) + base_kpoints = Kpoints( + comment="Uniform grid", + style=Kpoints.supported_modes.Reciprocal, + num_kpts=len(mesh), + kpts=tuple(i[0] for i in mesh), + kpts_weights=[i[1] for i in mesh], + ) + zero_weighted_kpoints = None if kconfig.get("zero_weighted_line_density"): # zero_weighted k-points along line mode path @@ -885,9 +885,9 @@ def kpoints(self) -> Kpoints | None: kpts_weights=[0] * len(points), ) - if base_kpoints and not (added_kpoints or zero_weighted_kpoints): + if base_kpoints and not added_kpoints and not zero_weighted_kpoints: return base_kpoints - if added_kpoints and not (base_kpoints or zero_weighted_kpoints): + if added_kpoints and not base_kpoints and not zero_weighted_kpoints: return added_kpoints # Sanity check @@ -937,11 +937,10 @@ def potcar_symbols(self) -> list[str]: potcar_symbols = [] settings = self._config_dict["POTCAR"] - if isinstance(settings[elements[-1]], dict): - for el in elements: + for el in elements: + if isinstance(settings[elements[-1]], dict): potcar_symbols.append(settings[el]["symbol"] if el in settings else el) - else: - for el in elements: + else: potcar_symbols.append(settings.get(el, el)) return potcar_symbols @@ -1003,10 +1002,8 @@ def override_from_prev_calc(self, prev_calc_dir: PathLike = ".") -> Self: ) files_to_transfer = {} - if getattr(self, "copy_chgcar", False): - chgcars = sorted(glob(str(Path(prev_calc_dir) / "CHGCAR*"))) - if chgcars: - files_to_transfer["CHGCAR"] = str(chgcars[-1]) + if getattr(self, "copy_chgcar", False) and (chgcars := sorted(glob(str(Path(prev_calc_dir) / "CHGCAR*")))): + files_to_transfer["CHGCAR"] = str(chgcars[-1]) if getattr(self, "copy_wavecar", False): for fname in ("WAVECAR", "WAVEDER", "WFULL"): @@ -1865,14 +1862,14 @@ def structure(self, structure: Structure | None) -> None: if self.magmom: structure = structure.copy(site_properties={"magmom": self.magmom}) - # MAGMOM has to be 3D for SOC calculation. - if hasattr(structure[0], "magmom"): - if not isinstance(structure[0].magmom, list): - # Project MAGMOM to z-axis - structure = structure.copy(site_properties={"magmom": [[0, 0, site.magmom] for site in structure]}) - else: + # MAGMOM has to be 3D for SOC calculation + if not hasattr(structure[0], "magmom"): raise ValueError("Neither the previous structure has magmom property nor magmom provided") + if not isinstance(structure[0].magmom, list): + # Project MAGMOM to z-axis + structure = structure.copy(site_properties={"magmom": [[0, 0, site.magmom] for site in structure]}) + assert VaspInputSet.structure is not None VaspInputSet.structure.fset(self, structure) @@ -2379,7 +2376,7 @@ def write_input( if write_path_cif: sites = { PeriodicSite(site.species, site.frac_coords, self.structures[0].lattice) - for site in chain(*(struct for struct in self.structures)) + for site in chain(*iter(self.structures)) } neb_path = Structure.from_sites(sorted(sites)) neb_path.to(filename=f"{output_dir}/path.cif") diff --git a/src/pymatgen/io/xtb/inputs.py b/src/pymatgen/io/xtb/inputs.py index b5bcca3b4b6..cadd644c1f2 100644 --- a/src/pymatgen/io/xtb/inputs.py +++ b/src/pymatgen/io/xtb/inputs.py @@ -2,7 +2,6 @@ from __future__ import annotations -import logging import os from typing import TYPE_CHECKING @@ -18,8 +17,6 @@ __email__ = "aepstein@lbl.gov" __credits__ = "Sam Blau, Evan Spotte-Smith" -logger = logging.getLogger(__name__) - class CRESTInput(MSONable): """ diff --git a/src/pymatgen/io/xtb/outputs.py b/src/pymatgen/io/xtb/outputs.py index 4751c251a8f..9aef57b9712 100644 --- a/src/pymatgen/io/xtb/outputs.py +++ b/src/pymatgen/io/xtb/outputs.py @@ -2,7 +2,6 @@ from __future__ import annotations -import logging import os import re @@ -18,8 +17,6 @@ __email__ = "aepstein@lbl.gov" __credits__ = "Sam Blau, Evan Spotte-Smith" -logger = logging.getLogger(__name__) - class CRESTOutput(MSONable): """Parse CREST output files.""" diff --git a/src/pymatgen/phonon/plotter.py b/src/pymatgen/phonon/plotter.py index 64f58499212..7d1c2261b67 100644 --- a/src/pymatgen/phonon/plotter.py +++ b/src/pymatgen/phonon/plotter.py @@ -313,8 +313,7 @@ def _make_ticks(self, ax: Axes) -> Axes: ticks = self.get_ticks() # zip to sanitize, only plot the uniq values - ticks_labels = list(zip(*zip(ticks["distance"], ticks["label"]))) - if ticks_labels: + if ticks_labels := list(zip(*zip(ticks["distance"], ticks["label"]))): ax.set_xticks(ticks_labels[0]) ax.set_xticklabels(ticks_labels[1]) diff --git a/src/pymatgen/transformations/standard_transformations.py b/src/pymatgen/transformations/standard_transformations.py index e27406ec574..285180fb43d 100644 --- a/src/pymatgen/transformations/standard_transformations.py +++ b/src/pymatgen/transformations/standard_transformations.py @@ -6,7 +6,6 @@ from __future__ import annotations -import logging from fractions import Fraction from typing import TYPE_CHECKING @@ -30,8 +29,6 @@ from pymatgen.core.sites import PeriodicSite from pymatgen.util.typing import SpeciesLike -logger = logging.getLogger(__name__) - class RotationTransformation(AbstractTransformation): """The RotationTransformation applies a rotation to a structure.""" diff --git a/src/pymatgen/vis/structure_vtk.py b/src/pymatgen/vis/structure_vtk.py index 2bc4293e2e1..0ad4fcffffa 100644 --- a/src/pymatgen/vis/structure_vtk.py +++ b/src/pymatgen/vis/structure_vtk.py @@ -28,8 +28,8 @@ from collections.abc import Sequence from typing import ClassVar -module_dir = os.path.dirname(os.path.abspath(__file__)) -EL_COLORS = loadfn(f"{module_dir}/ElementColorSchemes.yaml") +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) +EL_COLORS = loadfn(f"{MODULE_DIR}/ElementColorSchemes.yaml") class StructureVis: diff --git a/tests/analysis/test_pourbaix_diagram.py b/tests/analysis/test_pourbaix_diagram.py index 3119877f33b..ede30ae164e 100644 --- a/tests/analysis/test_pourbaix_diagram.py +++ b/tests/analysis/test_pourbaix_diagram.py @@ -1,6 +1,5 @@ from __future__ import annotations -import logging import multiprocessing from unittest import TestCase @@ -17,8 +16,6 @@ TEST_DIR = f"{TEST_FILES_DIR}/analysis/pourbaix_diagram" -logger = logging.getLogger(__name__) - class TestPourbaixEntry(PymatgenTest): """Test all functions using a fictitious entry""" diff --git a/tests/entries/test_compatibility.py b/tests/entries/test_compatibility.py index 03578f2f135..01696beccf2 100644 --- a/tests/entries/test_compatibility.py +++ b/tests/entries/test_compatibility.py @@ -39,6 +39,9 @@ from pymatgen.util.typing import CompositionLike +MODULE_DIR = os.path.dirname(os.path.abspath(pymatgen.entries.__file__)) + + class TestCorrectionSpecificity(TestCase): """Make sure corrections are only applied to GGA or GGA+U entries.""" @@ -1909,8 +1912,7 @@ def test_parallel_process_entries(self): class TestAqueousCorrection(TestCase): def setUp(self): - module_dir = os.path.dirname(os.path.abspath(pymatgen.entries.__file__)) - fp = f"{module_dir}/MITCompatibility.yaml" + fp = f"{MODULE_DIR}/MITCompatibility.yaml" self.corr = AqueousCorrection(fp) def test_compound_energy(self): @@ -1939,8 +1941,7 @@ class TestMITAqueousCompatibility(TestCase): def setUp(self): self.compat = MITCompatibility(check_potcar_hash=True) self.aqcompat = MITAqueousCompatibility(check_potcar_hash=True) - module_dir = os.path.dirname(os.path.abspath(pymatgen.entries.__file__)) - fp = f"{module_dir}/MITCompatibility.yaml" + fp = f"{MODULE_DIR}/MITCompatibility.yaml" self.aqcorr = AqueousCorrection(fp) def test_aqueous_compat(self): diff --git a/tests/files/io/vasp/inputs/POTCAR_spec b/tests/files/io/vasp/inputs/POTCAR_spec index 475f075b304..3f52d540d3f 100644 --- a/tests/files/io/vasp/inputs/POTCAR_spec +++ b/tests/files/io/vasp/inputs/POTCAR_spec @@ -1,3 +1,3 @@ -Dummy POTCAR.spec file +Dummy POTCAR.spec file -This file sould be ignored by Vasprun.get_potcars() \ No newline at end of file +This file should be ignored by Vasprun.get_potcars() \ No newline at end of file diff --git a/tests/io/aims/conftest.py b/tests/io/aims/conftest.py index 5060ba4b259..96244ba975c 100644 --- a/tests/io/aims/conftest.py +++ b/tests/io/aims/conftest.py @@ -6,14 +6,14 @@ from pymatgen.core import SETTINGS -module_dir = os.path.dirname(__file__) +MODULE_DIR = os.path.dirname(__file__) @pytest.fixture(autouse=True) def _set_aims_species_dir_env_var(monkeypatch: pytest.MonkeyPatch) -> None: - monkeypatch.setenv("AIMS_SPECIES_DIR", f"{module_dir}/species_directory") + monkeypatch.setenv("AIMS_SPECIES_DIR", f"{MODULE_DIR}/species_directory") @pytest.fixture(autouse=True) def _set_aims_species_dir_settings(monkeypatch: pytest.MonkeyPatch): - monkeypatch.setitem(SETTINGS, "AIMS_SPECIES_DIR", f"{module_dir}/species_directory") + monkeypatch.setitem(SETTINGS, "AIMS_SPECIES_DIR", f"{MODULE_DIR}/species_directory") diff --git a/tests/io/aims/test_sets/test_bs_generator.py b/tests/io/aims/test_sets/test_bs_generator.py index 2dfe1e36b53..2eb625dae2d 100644 --- a/tests/io/aims/test_sets/test_bs_generator.py +++ b/tests/io/aims/test_sets/test_bs_generator.py @@ -7,32 +7,32 @@ from pymatgen.io.aims.sets.bs import BandStructureSetGenerator from pymatgen.util.testing.aims import Si, comp_system -module_dir = Path(__file__).resolve().parents[1] -species_dir = module_dir / "species_directory" -ref_path = (module_dir / "aims_input_generator_ref").resolve() +MODULE_DIR = Path(__file__).resolve().parents[1] +SPECIES_DIR = MODULE_DIR / "species_directory" +REF_PATH = (MODULE_DIR / "aims_input_generator_ref").resolve() def test_si_bs(tmp_path): parameters = { - "species_dir": str(species_dir / "light"), + "species_dir": str(SPECIES_DIR / "light"), "k_grid": [8, 8, 8], } - comp_system(Si, parameters, "static-si-bs", tmp_path, ref_path, BandStructureSetGenerator) + comp_system(Si, parameters, "static-si-bs", tmp_path, REF_PATH, BandStructureSetGenerator) def test_si_bs_output(tmp_path): parameters = { - "species_dir": str(species_dir / "light"), + "species_dir": str(SPECIES_DIR / "light"), "k_grid": [8, 8, 8], "output": ["json_log"], } - comp_system(Si, parameters, "static-si-bs-output", tmp_path, ref_path, BandStructureSetGenerator) + comp_system(Si, parameters, "static-si-bs-output", tmp_path, REF_PATH, BandStructureSetGenerator) def test_si_bs_density(tmp_path): parameters = { - "species_dir": str(species_dir / "light"), + "species_dir": str(SPECIES_DIR / "light"), "k_grid": [8, 8, 8], "k_point_density": 40, } - comp_system(Si, parameters, "static-si-bs-density", tmp_path, ref_path, BandStructureSetGenerator) + comp_system(Si, parameters, "static-si-bs-density", tmp_path, REF_PATH, BandStructureSetGenerator) diff --git a/tests/io/aims/test_sets/test_gw_generator.py b/tests/io/aims/test_sets/test_gw_generator.py index a1f5fef8cac..a021df04b72 100644 --- a/tests/io/aims/test_sets/test_gw_generator.py +++ b/tests/io/aims/test_sets/test_gw_generator.py @@ -7,15 +7,15 @@ from pymatgen.io.aims.sets.bs import GWSetGenerator from pymatgen.util.testing.aims import Si, comp_system -module_dir = Path(__file__).resolve().parents[1] -species_dir = module_dir / "species_directory" -ref_path = (module_dir / "aims_input_generator_ref").resolve() +MODULE_DIR = Path(__file__).resolve().parents[1] +SPECIES_DIR = MODULE_DIR / "species_directory" +REF_PATH = (MODULE_DIR / "aims_input_generator_ref").resolve() def test_si_gw(tmp_path): parameters = { - "species_dir": str(species_dir / "light"), + "species_dir": str(SPECIES_DIR / "light"), "k_grid": [2, 2, 2], "k_point_density": 10, } - comp_system(Si, parameters, "static-si-gw", tmp_path, ref_path, GWSetGenerator) + comp_system(Si, parameters, "static-si-gw", tmp_path, REF_PATH, GWSetGenerator) diff --git a/tests/io/aims/test_sets/test_md_generator.py b/tests/io/aims/test_sets/test_md_generator.py index f8b9f71cbef..3e413238915 100644 --- a/tests/io/aims/test_sets/test_md_generator.py +++ b/tests/io/aims/test_sets/test_md_generator.py @@ -9,15 +9,15 @@ from pymatgen.io.aims.sets.core import MDSetGenerator from pymatgen.util.testing.aims import Si, compare_files -module_dir = Path(__file__).resolve().parents[1] -species_dir = module_dir / "species_directory" -ref_path = (module_dir / "aims_input_generator_ref").resolve() +MODULE_DIR = Path(__file__).resolve().parents[1] +SPECIES_DIR = MODULE_DIR / "species_directory" +REF_PATH = (MODULE_DIR / "aims_input_generator_ref").resolve() def test_si_md(tmp_path): # default behaviour parameters = { - "species_dir": str(species_dir / "light"), + "species_dir": str(SPECIES_DIR / "light"), "k_grid": [2, 2, 2], } test_name = "md-si" @@ -46,4 +46,4 @@ def test_si_md(tmp_path): input_set = generator.get_input_set(Si) input_set.write_input(tmp_path / test_name) - return compare_files(test_name, tmp_path, ref_path) + return compare_files(test_name, tmp_path, REF_PATH) diff --git a/tests/io/aims/test_sets/test_relax_generator.py b/tests/io/aims/test_sets/test_relax_generator.py index 1f2798c1514..450eeaaa369 100644 --- a/tests/io/aims/test_sets/test_relax_generator.py +++ b/tests/io/aims/test_sets/test_relax_generator.py @@ -5,9 +5,9 @@ from pymatgen.io.aims.sets.core import RelaxSetGenerator from pymatgen.util.testing.aims import O2, Si, comp_system -module_dir = Path(__file__).resolve().parents[1] -species_dir = module_dir / "species_directory" -ref_path = (module_dir / "aims_input_generator_ref").resolve() +MODULE_DIR = Path(__file__).resolve().parents[1] +SPECIES_DIR = MODULE_DIR / "species_directory" +REF_PATH = (MODULE_DIR / "aims_input_generator_ref").resolve() def test_relax_si(tmp_path): @@ -15,14 +15,14 @@ def test_relax_si(tmp_path): "species_dir": "light", "k_grid": [2, 2, 2], } - comp_system(Si, params, "relax-si/", tmp_path, ref_path, RelaxSetGenerator) + comp_system(Si, params, "relax-si/", tmp_path, REF_PATH, RelaxSetGenerator) def test_relax_si_no_kgrid(tmp_path): params = {"species_dir": "light"} - comp_system(Si, params, "relax-no-kgrid-si", tmp_path, ref_path, RelaxSetGenerator) + comp_system(Si, params, "relax-no-kgrid-si", tmp_path, REF_PATH, RelaxSetGenerator) def test_relax_o2(tmp_path): - params = {"species_dir": str(species_dir / "light")} - comp_system(O2, params, "relax-o2", tmp_path, ref_path, RelaxSetGenerator) + params = {"species_dir": str(SPECIES_DIR / "light")} + comp_system(O2, params, "relax-o2", tmp_path, REF_PATH, RelaxSetGenerator) diff --git a/tests/io/aims/test_sets/test_static_generator.py b/tests/io/aims/test_sets/test_static_generator.py index a38c002897d..b4549bc77c4 100644 --- a/tests/io/aims/test_sets/test_static_generator.py +++ b/tests/io/aims/test_sets/test_static_generator.py @@ -5,8 +5,8 @@ from pymatgen.io.aims.sets.core import StaticSetGenerator from pymatgen.util.testing.aims import O2, Si, comp_system -module_dir = Path(__file__).resolve().parents[1] -ref_path = (module_dir / "aims_input_generator_ref").resolve() +MODULE_DIR = Path(__file__).resolve().parents[1] +REF_PATH = (MODULE_DIR / "aims_input_generator_ref").resolve() def test_static_si(tmp_path): @@ -14,7 +14,7 @@ def test_static_si(tmp_path): "species_dir": "light", "k_grid": [2, 2, 2], } - comp_system(Si, parameters, "static-si", tmp_path, ref_path, StaticSetGenerator) + comp_system(Si, parameters, "static-si", tmp_path, REF_PATH, StaticSetGenerator) def test_static_si_no_kgrid(tmp_path): @@ -23,9 +23,9 @@ def test_static_si_no_kgrid(tmp_path): for site in Si_supercell: # round site.coords to ignore floating point errors site.coords = [round(x, 15) for x in site.coords] - comp_system(Si_supercell, parameters, "static-no-kgrid-si", tmp_path, ref_path, StaticSetGenerator) + comp_system(Si_supercell, parameters, "static-no-kgrid-si", tmp_path, REF_PATH, StaticSetGenerator) def test_static_o2(tmp_path): parameters = {"species_dir": "light"} - comp_system(O2, parameters, "static-o2", tmp_path, ref_path, StaticSetGenerator) + comp_system(O2, parameters, "static-o2", tmp_path, REF_PATH, StaticSetGenerator) diff --git a/tests/io/aims/test_sets/test_static_restart_from_relax_generator.py b/tests/io/aims/test_sets/test_static_restart_from_relax_generator.py index 07d1e0ca295..46374f786c9 100644 --- a/tests/io/aims/test_sets/test_static_restart_from_relax_generator.py +++ b/tests/io/aims/test_sets/test_static_restart_from_relax_generator.py @@ -7,76 +7,76 @@ from pymatgen.io.aims.sets.core import StaticSetGenerator from pymatgen.util.testing.aims import O2, Si, comp_system -module_dir = Path(__file__).resolve().parents[1] -species_dir = module_dir / "species_directory" -ref_path = (module_dir / "aims_input_generator_ref").resolve() +MODULE_DIR = Path(__file__).resolve().parents[1] +SPECIES_DIR = MODULE_DIR / "species_directory" +REF_PATH = (MODULE_DIR / "aims_input_generator_ref").resolve() def test_static_from_relax_si(tmp_path): - user_params = {"species_dir": str(species_dir / "light")} + user_params = {"species_dir": str(SPECIES_DIR / "light")} comp_system( Si, user_params, "static-from-prev-si", tmp_path, - ref_path, + REF_PATH, StaticSetGenerator, properties=["energy", "forces", "stress"], - prev_dir=f"{ref_path}/relax-si/", + prev_dir=f"{REF_PATH}/relax-si/", ) def test_static_from_relax_si_no_kgrid(tmp_path): - user_params = {"species_dir": str(species_dir / "light")} + user_params = {"species_dir": str(SPECIES_DIR / "light")} comp_system( Si, user_params, "static-from-prev-no-kgrid-si", tmp_path, - ref_path, + REF_PATH, StaticSetGenerator, properties=["energy", "forces", "stress"], - prev_dir=f"{ref_path}/relax-no-kgrid-si/", + prev_dir=f"{REF_PATH}/relax-no-kgrid-si/", ) def test_static_from_relax_default_species_dir(tmp_path): - user_params = {"species_dir": str(species_dir / "light")} + user_params = {"species_dir": str(SPECIES_DIR / "light")} comp_system( Si, user_params, "static-from-prev-si", tmp_path, - ref_path, + REF_PATH, StaticSetGenerator, properties=["energy", "forces", "stress"], - prev_dir=f"{ref_path}/relax-si/", + prev_dir=f"{REF_PATH}/relax-si/", ) def test_static_from_relax_o2(tmp_path): - user_params = {"species_dir": str(species_dir / "light")} + user_params = {"species_dir": str(SPECIES_DIR / "light")} comp_system( O2, user_params, "static-from-prev-o2", tmp_path, - ref_path, + REF_PATH, StaticSetGenerator, properties=["energy", "forces", "stress"], - prev_dir=f"{ref_path}/relax-o2/", + prev_dir=f"{REF_PATH}/relax-o2/", ) def test_static_from_relax_default_species_dir_o2(tmp_path): - user_params = {"species_dir": str(species_dir / "light")} + user_params = {"species_dir": str(SPECIES_DIR / "light")} comp_system( O2, user_params, "static-from-prev-o2", tmp_path, - ref_path, + REF_PATH, StaticSetGenerator, properties=["energy", "forces", "stress"], - prev_dir=f"{ref_path}/relax-o2/", + prev_dir=f"{REF_PATH}/relax-o2/", ) diff --git a/tests/io/lobster/test_inputs.py b/tests/io/lobster/test_inputs.py index 6675eaf70c8..c5c2a989882 100644 --- a/tests/io/lobster/test_inputs.py +++ b/tests/io/lobster/test_inputs.py @@ -41,8 +41,6 @@ __email__ = "janine.george@uclouvain.be, esters@uoregon.edu" __date__ = "Dec 10, 2017" -module_dir = os.path.dirname(os.path.abspath(__file__)) - class TestCohpcar(PymatgenTest): def setUp(self): diff --git a/tests/io/lobster/test_lobsterenv.py b/tests/io/lobster/test_lobsterenv.py index 6ee94d82902..63b5809d051 100644 --- a/tests/io/lobster/test_lobsterenv.py +++ b/tests/io/lobster/test_lobsterenv.py @@ -1,6 +1,5 @@ from __future__ import annotations -import os from unittest import TestCase import numpy as np @@ -23,7 +22,6 @@ __date__ = "Jan 14, 2021" TEST_DIR = f"{TEST_FILES_DIR}/electronic_structure/cohp/environments" -module_dir = os.path.dirname(os.path.abspath(__file__)) class TestLobsterNeighbors(TestCase): diff --git a/tests/io/qchem/test_inputs.py b/tests/io/qchem/test_inputs.py index 6a49daba428..0dbfa23b1ea 100644 --- a/tests/io/qchem/test_inputs.py +++ b/tests/io/qchem/test_inputs.py @@ -1,6 +1,5 @@ from __future__ import annotations -import logging import os import pytest @@ -20,13 +19,8 @@ __email__ = "samblau1@gmail.com" __credits__ = "Xiaohui Qu" -logger = logging.getLogger(__name__) - class TestQCInput(PymatgenTest): - # ef setUpClass(cls): - # add things that show up over and over again - def test_molecule_template(self): species = ["C", "O"] coords = [ diff --git a/tests/io/qchem/test_utils.py b/tests/io/qchem/test_utils.py index 394ab8c142b..0c4681c4f21 100644 --- a/tests/io/qchem/test_utils.py +++ b/tests/io/qchem/test_utils.py @@ -1,6 +1,5 @@ from __future__ import annotations -import logging import struct import pytest @@ -12,8 +11,6 @@ __author__ = "Ryan Kingsbury, Samuel Blau" __copyright__ = "Copyright 2018-2022, The Materials Project" -logger = logging.getLogger(__name__) - TEST_DIR = f"{TEST_FILES_DIR}/io/qchem/new_qchem_files" diff --git a/tests/io/test_lmto.py b/tests/io/test_lmto.py index 393a0b06bae..1ddc8c2abcf 100644 --- a/tests/io/test_lmto.py +++ b/tests/io/test_lmto.py @@ -20,7 +20,7 @@ TEST_DIR = f"{TEST_FILES_DIR}/electronic_structure/cohp" -module_dir = os.path.dirname(os.path.abspath(__file__)) +MODULE_DIR = os.path.dirname(os.path.abspath(__file__)) class TestCtrl(PymatgenTest): @@ -30,7 +30,7 @@ def setUp(self): self.ref_fe = LMTOCtrl.from_file() def tearDown(self): - os.chdir(module_dir) + os.chdir(MODULE_DIR) def test_dict(self): assert self.ref_bise == LMTOCtrl.from_dict(self.ref_bise.as_dict()) @@ -55,7 +55,7 @@ def setUp(self): self.copl_fe = LMTOCopl() def tearDown(self): - os.chdir(module_dir) + os.chdir(MODULE_DIR) def test_attributes(self): assert not self.copl_bise.is_spin_polarized diff --git a/tests/io/test_shengbte.py b/tests/io/test_shengbte.py index 67779c458a1..06fbb813d11 100644 --- a/tests/io/test_shengbte.py +++ b/tests/io/test_shengbte.py @@ -1,7 +1,5 @@ from __future__ import annotations -import os - import pytest from numpy.testing import assert_array_equal @@ -11,8 +9,6 @@ f90nml = pytest.importorskip("f90nml") TEST_DIR = f"{TEST_FILES_DIR}/io/shengbte" -module_dir = os.path.dirname(os.path.abspath(__file__)) - class TestShengBTE(PymatgenTest): def setUp(self):