From 605757fde1bf954ffbce73851de5b0e93b96c6e5 Mon Sep 17 00:00:00 2001 From: Janosh Riebesell Date: Thu, 9 Nov 2023 10:39:40 -0800 Subject: [PATCH] Module-scoped imports (#3464) * move imports to module scope * fix doc str trailing blank lines * fix circular import "from pymatgen.io.cif import CifWriter" in pymatgen.core.structure.py * fix circular import: cannot import name 'EnumerateStructureTransformation' from partially initialized module 'pymatgen.transformations.advanced_transformations' --- pymatgen/analysis/diffraction/neutron.py | 1 - pymatgen/analysis/ewald.py | 9 +++---- .../analysis/ferroelectricity/polarization.py | 18 +++++-------- pymatgen/analysis/local_env.py | 12 +++------ pymatgen/analysis/pourbaix_diagram.py | 9 ++----- pymatgen/analysis/quasirrho.py | 1 - pymatgen/analysis/solar/slme.py | 1 - pymatgen/core/lattice.py | 3 +-- pymatgen/core/structure.py | 13 +++------- pymatgen/core/units.py | 4 +-- pymatgen/electronic_structure/boltztrap.py | 3 +-- pymatgen/electronic_structure/dos.py | 17 ++++++------- pymatgen/electronic_structure/plotter.py | 5 ++-- pymatgen/entries/__init__.py | 1 - pymatgen/entries/compatibility.py | 17 ++++++------- pymatgen/ext/matproj_legacy.py | 3 +-- pymatgen/io/abinit/inputs.py | 25 +++++++++---------- pymatgen/io/adf.py | 14 +++-------- pymatgen/io/cp2k/outputs.py | 1 - pymatgen/io/gaussian.py | 4 +-- pymatgen/io/lammps/data.py | 6 ++--- pymatgen/io/lammps/inputs.py | 2 -- pymatgen/io/lobster/lobsterenv.py | 2 -- pymatgen/io/lobster/outputs.py | 3 +-- pymatgen/io/vasp/optics.py | 2 -- pymatgen/io/vasp/sets.py | 4 +-- pymatgen/io/xcrysden.py | 9 +------ pymatgen/phonon/dos.py | 13 +++++----- pymatgen/phonon/gruneisen.py | 3 +-- pymatgen/phonon/plotter.py | 3 +-- pymatgen/symmetry/groups.py | 10 +------- .../advanced_transformations.py | 3 +-- pymatgen/util/string.py | 9 +++---- tests/analysis/test_molecule_matcher.py | 5 +--- tests/core/test_structure.py | 2 +- tests/io/test_adf.py | 1 - .../test_advanced_transformations.py | 3 +-- .../test_standard_transformations.py | 8 +----- 38 files changed, 78 insertions(+), 171 deletions(-) diff --git a/pymatgen/analysis/diffraction/neutron.py b/pymatgen/analysis/diffraction/neutron.py index 8debe5b6017..e6aa0454b90 100644 --- a/pymatgen/analysis/diffraction/neutron.py +++ b/pymatgen/analysis/diffraction/neutron.py @@ -44,7 +44,6 @@ class NDCalculator(AbstractDiffractionPatternCalculator): Reference: Marc De Graef and Michael E. McHenry, Structure of Materials 2nd ed, Chapter13, Cambridge University Press 2003. - """ def __init__(self, wavelength=1.54184, symprec: float = 0, debye_waller_factors=None): diff --git a/pymatgen/analysis/ewald.py b/pymatgen/analysis/ewald.py index 40cd97565ad..16058874cb9 100644 --- a/pymatgen/analysis/ewald.py +++ b/pymatgen/analysis/ewald.py @@ -496,12 +496,9 @@ class EwaldMinimizer: ALGO_FAST = 0 ALGO_COMPLETE = 1 ALGO_BEST_FIRST = 2 - - """ - ALGO_TIME_LIMIT: Slowly increases the speed (with the cost of decreasing - accuracy) as the minimizer runs. Attempts to limit the run time to - approximately 30 minutes. - """ + # ALGO_TIME_LIMIT: Slowly increases the speed (with the cost of decreasing + # accuracy) as the minimizer runs. Attempts to limit the run time to + # approximately 30 minutes. ALGO_TIME_LIMIT = 3 def __init__(self, matrix, m_list, num_to_return=1, algo=ALGO_FAST): diff --git a/pymatgen/analysis/ferroelectricity/polarization.py b/pymatgen/analysis/ferroelectricity/polarization.py index c5692f471ec..1784fe00551 100644 --- a/pymatgen/analysis/ferroelectricity/polarization.py +++ b/pymatgen/analysis/ferroelectricity/polarization.py @@ -47,6 +47,7 @@ from __future__ import annotations import numpy as np +from scipy.interpolate import UnivariateSpline from pymatgen.core.lattice import Lattice from pymatgen.core.structure import Structure @@ -131,19 +132,16 @@ def get_nearest_site(self, coords, site, r=None): class Polarization: """ - Class for recovering the same branch polarization for a set of - polarization calculations along the nonpolar - polar distortion - path of a ferroelectric. + Class for recovering the same branch polarization for a set of polarization + calculations along the nonpolar - polar distortion path of a ferroelectric. p_elecs, p_ions, and structures lists should be given in order of nonpolar to polar! For example, the structures returned from: nonpolar.interpolate(polar,interpolate_lattices=True) if nonpolar is the nonpolar Structure and polar is the polar structure. - It is assumed that the electronic and ionic dipole moment values - are given in electron Angstroms along the three lattice directions - (a,b,c). - + It is assumed that the electronic and ionic dipole moment values are given in + electron Angstroms along the three lattice directions (a,b,c). """ def __init__( @@ -371,10 +369,8 @@ def get_polarization_change_norm(self, convert_to_muC_per_cm2=True, all_in_polar def same_branch_splines(self, convert_to_muC_per_cm2=True, all_in_polar=True): """ Fit splines to same branch polarization. This is used to assess any jumps - in the same branch polarizaiton. + in the same branch polarization. """ - from scipy.interpolate import UnivariateSpline - tot = self.get_same_branch_polarization_data( convert_to_muC_per_cm2=convert_to_muC_per_cm2, all_in_polar=all_in_polar ) @@ -430,8 +426,6 @@ def __init__(self, energies): def spline(self): """Fit spline to energy trend data.""" - from scipy.interpolate import UnivariateSpline - return UnivariateSpline(range(len(self.energies)), self.energies, k=4) def smoothness(self): diff --git a/pymatgen/analysis/local_env.py b/pymatgen/analysis/local_env.py index e2a799db6c3..b13a348ee27 100644 --- a/pymatgen/analysis/local_env.py +++ b/pymatgen/analysis/local_env.py @@ -4310,9 +4310,8 @@ def get_bonded_structure(self, structure: Structure, decorate: bool = False) -> Returns: StructureGraph: Bonded structure """ - # not a top-level import because critic2 is an optional - # dependency, only want to raise an import error if - # Critic2NN() is used + # not a top-level import because critic2 is an optional dependency, only want + # to raise an import error if Critic2NN() is used from pymatgen.command_line.critic2_caller import Critic2Caller if structure == self.__last_structure: @@ -4337,13 +4336,11 @@ def get_nn_info(self, structure: Structure, n: int): Args: structure (Structure): input structure. - n (int): index of site for which to determine near-neighbor - sites. + n (int): index of site for which to determine near-neighbor sites. Returns: siw (list of tuples (Site, array, float)): tuples, each one - of which represents a coordinated site, its image location, - and its weight. + of which represents a coordinated site, its image location, and its weight. """ sg = self.get_bonded_structure(structure) @@ -4411,7 +4408,6 @@ def metal_edge_extender( Returns: mol_graph: pymatgen.analysis.graphs.MoleculeGraph object with additional metal bonds (if any found) added - """ if metals is None: metals = [] diff --git a/pymatgen/analysis/pourbaix_diagram.py b/pymatgen/analysis/pourbaix_diagram.py index cd1b875c3cd..db5e5016083 100644 --- a/pymatgen/analysis/pourbaix_diagram.py +++ b/pymatgen/analysis/pourbaix_diagram.py @@ -12,17 +12,12 @@ from copy import deepcopy from functools import cmp_to_key, partial from multiprocessing import Pool +from typing import TYPE_CHECKING, Any, no_type_check import numpy as np from monty.json import MontyDecoder, MSONable from scipy.spatial import ConvexHull, HalfspaceIntersection - -try: - from scipy.special import comb -except ImportError: - from scipy.misc import comb - -from typing import TYPE_CHECKING, Any, no_type_check +from scipy.special import comb from pymatgen.analysis.phase_diagram import PDEntry, PhaseDiagram from pymatgen.analysis.reaction_calculator import Reaction, ReactionError diff --git a/pymatgen/analysis/quasirrho.py b/pymatgen/analysis/quasirrho.py index acff159eed6..49cd0b1d7dc 100644 --- a/pymatgen/analysis/quasirrho.py +++ b/pymatgen/analysis/quasirrho.py @@ -92,7 +92,6 @@ class QuasiRRHO: free_energy_ho (float): Free energy calculated without the Quasi-RRHO method, i.e. with a harmonic oscillator approximation for the vibrational entropy [Ha] - """ def __init__( diff --git a/pymatgen/analysis/solar/slme.py b/pymatgen/analysis/solar/slme.py index 25618bd4906..e33a17f61ac 100644 --- a/pymatgen/analysis/solar/slme.py +++ b/pymatgen/analysis/solar/slme.py @@ -155,7 +155,6 @@ def slme( Returns: The calculated maximum efficiency. - """ # Defining constants for tidy equations c = constants.c # speed of light, m/s diff --git a/pymatgen/core/lattice.py b/pymatgen/core/lattice.py index f6123ecaade..2892c72ef0f 100644 --- a/pymatgen/core/lattice.py +++ b/pymatgen/core/lattice.py @@ -15,6 +15,7 @@ from monty.json import MSONable from numpy import dot, pi, transpose from numpy.linalg import inv +from scipy.spatial import Voronoi from pymatgen.util.coord import pbc_shortest_vectors from pymatgen.util.due import Doi, due @@ -1222,8 +1223,6 @@ def get_wigner_seitz_cell(self) -> list[list[np.ndarray]]: for ii, jj, kk in itertools.product([-1, 0, 1], [-1, 0, 1], [-1, 0, 1]): list_k_points.append(ii * vec1 + jj * vec2 + kk * vec3) - from scipy.spatial import Voronoi - tess = Voronoi(list_k_points) out = [] for r in tess.ridge_dict: diff --git a/pymatgen/core/structure.py b/pymatgen/core/structure.py index 2951d17383e..4f6dd1938ca 100644 --- a/pymatgen/core/structure.py +++ b/pymatgen/core/structure.py @@ -31,7 +31,9 @@ from numpy import cross, eye from numpy.linalg import norm from ruamel.yaml import YAML -from scipy.linalg import expm +from scipy.cluster.hierarchy import fcluster, linkage +from scipy.linalg import expm, polar +from scipy.spatial.distance import squareform from tabulate import tabulate from pymatgen.core.bonds import CovalentBond, get_bond_length @@ -2218,8 +2220,6 @@ def interpolate( if interpolate_lattices: # interpolate lattice matrices using polar decomposition - from scipy.linalg import polar - # u is a unitary rotation, p is stretch u, p = polar(np.dot(end_structure.lattice.matrix.T, np.linalg.inv(self.lattice.matrix.T))) lvec = p - np.identity(3) @@ -4235,9 +4235,6 @@ def merge_sites(self, tol: float = 0.01, mode: Literal["sum", "delete", "average "average" means that the site is deleted but the properties are averaged Only first letter is considered. """ - from scipy.cluster.hierarchy import fcluster, linkage - from scipy.spatial.distance import squareform - dist_mat = self.distance_matrix np.fill_diagonal(dist_mat, 0) clusters = fcluster(linkage(squareform((dist_mat + dist_mat.T) / 2)), tol, "distance") @@ -4632,10 +4629,6 @@ def rotate_sites( axis (3x1 array): Rotation axis vector. anchor (3x1 array): Point of rotation. """ - from numpy import cross, eye - from numpy.linalg import norm - from scipy.linalg import expm - if indices is None: indices = range(len(self)) diff --git a/pymatgen/core/units.py b/pymatgen/core/units.py index f399a40ce25..94dc97fab8f 100644 --- a/pymatgen/core/units.py +++ b/pymatgen/core/units.py @@ -735,12 +735,10 @@ def unitized(unit): Args: unit: Specific unit (eV, Ha, m, ang, etc.). - Example usage:: - + Example: @unitized(unit="kg") def get_mass(): return 123.45 - """ def wrap(func): diff --git a/pymatgen/electronic_structure/boltztrap.py b/pymatgen/electronic_structure/boltztrap.py index 4bfe0e65d89..4b1780cbe27 100644 --- a/pymatgen/electronic_structure/boltztrap.py +++ b/pymatgen/electronic_structure/boltztrap.py @@ -32,6 +32,7 @@ from monty.json import MSONable, jsanitize from monty.os import cd from scipy import constants +from scipy.optimize import fsolve from scipy.spatial import distance from pymatgen.core.lattice import Lattice @@ -2264,8 +2265,6 @@ def eta_from_seebeck(seeb, Lambda): Returns: float: eta where the two seebeck coefficients are equal (reduced chemical potential). """ - from scipy.optimize import fsolve - out = fsolve(lambda x: (seebeck_spb(x, Lambda) - abs(seeb)) ** 2, 1.0, full_output=True) return out[0][0] diff --git a/pymatgen/electronic_structure/dos.py b/pymatgen/electronic_structure/dos.py index d628dd1467d..176f0ab9c36 100644 --- a/pymatgen/electronic_structure/dos.py +++ b/pymatgen/electronic_structure/dos.py @@ -10,6 +10,7 @@ import numpy as np from monty.json import MSONable from scipy.constants import value as _cd +from scipy.ndimage import gaussian_filter1d from scipy.signal import hilbert from pymatgen.core import Structure, get_el_sp @@ -220,13 +221,11 @@ def get_smeared_densities(self, sigma: float): Returns: Dict of Gaussian-smeared densities. """ - from scipy.ndimage import gaussian_filter1d - smeared_dens = {} diff = [self.energies[i + 1] - self.energies[i] for i in range(len(self.energies) - 1)] - avgdiff = sum(diff) / len(diff) + avg_diff = sum(diff) / len(diff) for spin, dens in self.densities.items(): - smeared_dens[spin] = gaussian_filter1d(dens, sigma / avgdiff) + smeared_dens[spin] = gaussian_filter1d(dens, sigma / avg_diff) return smeared_dens def __add__(self, other): @@ -343,14 +342,14 @@ def get_gap(self, tol: float = 0.001, abs_tol: bool = False, spin: Spin | None = def __str__(self): """Returns a string which can be easily plotted (using gnuplot).""" if Spin.down in self.densities: - stringarray = [f"#{'Energy':30s} {'DensityUp':30s} {'DensityDown':30s}"] + str_arr = [f"#{'Energy':30s} {'DensityUp':30s} {'DensityDown':30s}"] for i, energy in enumerate(self.energies): - stringarray.append(f"{energy:.5f} {self.densities[Spin.up][i]:.5f} {self.densities[Spin.down][i]:.5f}") + str_arr.append(f"{energy:.5f} {self.densities[Spin.up][i]:.5f} {self.densities[Spin.down][i]:.5f}") else: - stringarray = [f"#{'Energy':30s} {'DensityUp':30s}"] + str_arr = [f"#{'Energy':30s} {'DensityUp':30s}"] for i, energy in enumerate(self.energies): - stringarray.append(f"{energy:.5f} {self.densities[Spin.up][i]:.5f}") - return "\n".join(stringarray) + str_arr.append(f"{energy:.5f} {self.densities[Spin.up][i]:.5f}") + return "\n".join(str_arr) @classmethod def from_dict(cls, d) -> Dos: diff --git a/pymatgen/electronic_structure/plotter.py b/pymatgen/electronic_structure/plotter.py index 680c8f8a5e7..cb4f029dbcd 100644 --- a/pymatgen/electronic_structure/plotter.py +++ b/pymatgen/electronic_structure/plotter.py @@ -4217,7 +4217,7 @@ def plot_points(points, lattice=None, coords_are_cartesian=False, fold=False, ax @add_fig_kwargs -def plot_brillouin_zone_from_kpath(kpath, ax: plt.Axes = None, **kwargs): +def plot_brillouin_zone_from_kpath(kpath, ax: plt.Axes = None, **kwargs) -> plt.Axes: """Gives the plot (as a matplotlib object) of the symmetry line path in the Brillouin Zone. @@ -4227,8 +4227,7 @@ def plot_brillouin_zone_from_kpath(kpath, ax: plt.Axes = None, **kwargs): **kwargs: provided by add_fig_kwargs decorator Returns: - matplotlib figure - + plt.Axes: matplotlib Axes """ lines = [[kpath.kpath["kpoints"][k] for k in p] for p in kpath.kpath["path"]] return plot_brillouin_zone( diff --git a/pymatgen/entries/__init__.py b/pymatgen/entries/__init__.py index b82aa272677..d8e4a30812e 100644 --- a/pymatgen/entries/__init__.py +++ b/pymatgen/entries/__init__.py @@ -33,7 +33,6 @@ class Entry(MSONable, metaclass=ABCMeta): a specific chemical composition. This base class is not intended to be instantiated directly. Note that classes which inherit from Entry must define a .energy property. - """ def __init__(self, composition: Composition | str | dict[str, float], energy: float) -> None: diff --git a/pymatgen/entries/compatibility.py b/pymatgen/entries/compatibility.py index 6e0f320e433..83c7e91a530 100644 --- a/pymatgen/entries/compatibility.py +++ b/pymatgen/entries/compatibility.py @@ -206,7 +206,7 @@ def get_correction(self, entry) -> ufloat: # set error to 0 because old MPCompatibility doesn't have errors # only correct GGA or GGA+U entries - if entry.parameters.get("run_type") not in ["GGA", "GGA+U"]: + if entry.parameters.get("run_type") not in ("GGA", "GGA+U"): return ufloat(0.0, 0.0) rform = entry.composition.reduced_formula @@ -253,7 +253,7 @@ def get_correction(self, entry) -> ufloat: correction = ufloat(0.0, 0.0) # only correct GGA or GGA+U entries - if entry.parameters.get("run_type") not in ["GGA", "GGA+U"]: + if entry.parameters.get("run_type") not in ("GGA", "GGA+U"): return ufloat(0.0, 0.0) # Check for sulfide corrections @@ -347,14 +347,12 @@ def get_correction(self, entry) -> ufloat: Returns: Correction, Uncertainty. """ - from pymatgen.analysis.pourbaix_diagram import MU_H2O - comp = entry.composition rform = comp.reduced_formula cpd_energies = self.cpd_energies # only correct GGA or GGA+U entries - if entry.parameters.get("run_type") not in ["GGA", "GGA+U"]: + if entry.parameters.get("run_type") not in ("GGA", "GGA+U"): return ufloat(0.0, 0.0) correction = ufloat(0.0, 0.0) @@ -467,13 +465,12 @@ def get_correction(self, entry) -> ufloat: Returns: Correction, Uncertainty. """ - if entry.parameters.get("run_type") not in ["GGA", "GGA+U"]: + if entry.parameters.get("run_type") not in ("GGA", "GGA+U"): raise CompatibilityError( f"Entry {entry.entry_id} has invalid run type {entry.parameters.get('run_type')}. Discarding." ) - calc_u = entry.parameters.get("hubbards") - calc_u = defaultdict(int) if calc_u is None else calc_u + calc_u = entry.parameters.get("hubbards") or defaultdict(int) comp = entry.composition elements = sorted((el for el in comp.elements if comp[el] > 0), key=lambda el: el.X) @@ -481,7 +478,7 @@ def get_correction(self, entry) -> ufloat: correction = ufloat(0.0, 0.0) # only correct GGA or GGA+U entries - if entry.parameters.get("run_type") not in ["GGA", "GGA+U"]: + if entry.parameters.get("run_type") not in ("GGA", "GGA+U"): return ufloat(0.0, 0.0) u_corr = self.u_corrections.get(most_electroneg, {}) @@ -934,7 +931,7 @@ def get_adjustments(self, entry: AnyComputedEntry) -> list[EnergyAdjustment]: Raises: CompatibilityError if the entry is not compatible """ - if entry.parameters.get("run_type") not in ["GGA", "GGA+U"]: + if entry.parameters.get("run_type") not in ("GGA", "GGA+U"): raise CompatibilityError( f"Entry {entry.entry_id} has invalid run type {entry.parameters.get('run_type')}. " f"Must be GGA or GGA+U. Discarding." diff --git a/pymatgen/ext/matproj_legacy.py b/pymatgen/ext/matproj_legacy.py index e7b9cdfa095..c8d6bce8fa9 100644 --- a/pymatgen/ext/matproj_legacy.py +++ b/pymatgen/ext/matproj_legacy.py @@ -26,6 +26,7 @@ from pymatgen.core import SETTINGS, Composition, Element, Structure from pymatgen.core import __version__ as PMG_VERSION from pymatgen.core.surface import get_symmetrically_equivalent_miller_indices +from pymatgen.entries.compatibility import MaterialsProject2020Compatibility from pymatgen.entries.computed_entries import ComputedEntry, ComputedStructureEntry from pymatgen.entries.exp_entries import ExpEntry from pymatgen.symmetry.analyzer import SpacegroupAnalyzer @@ -557,8 +558,6 @@ def get_entries( ) entries.append(e) if compatible_only: - from pymatgen.entries.compatibility import MaterialsProject2020Compatibility - # suppress the warning about missing oxidation states with warnings.catch_warnings(): warnings.filterwarnings("ignore", message="Failed to guess oxidation states.*") diff --git a/pymatgen/io/abinit/inputs.py b/pymatgen/io/abinit/inputs.py index f0306095f38..385fb0010f0 100644 --- a/pymatgen/io/abinit/inputs.py +++ b/pymatgen/io/abinit/inputs.py @@ -12,7 +12,7 @@ import logging import os from collections import namedtuple -from collections.abc import Mapping, MutableMapping +from collections.abc import Mapping, MutableMapping, Sequence from enum import Enum import numpy as np @@ -23,6 +23,7 @@ from pymatgen.io.abinit import abiobjects as aobj from pymatgen.io.abinit.pseudos import Pseudo, PseudoTable from pymatgen.io.abinit.variable import InputVariable +from pymatgen.symmetry.bandstructure import HighSymmKpath logger = logging.getLogger(__file__) @@ -30,7 +31,7 @@ # List of Abinit variables used to specify the structure. # This variables should not be passed to set_vars since # they will be generated with structure.to_abivars() -GEOVARS = { +GEOVARS = ( "acell", "rprim", "rprimd", @@ -42,10 +43,10 @@ "typat", "ntypat", "natom", -} +) # Variables defining tolerances (used in pop_tolerances) -_TOLVARS = { +_TOLVARS = ( "toldfe", "tolvrs", "tolwfr", @@ -54,19 +55,19 @@ "tolimg", "tolmxf", "tolrde", -} +) -# Variables defining tolerances for the SCF cycle that are mutally exclusive -_TOLVARS_SCF = { +# Variables defining tolerances for the SCF cycle that are mutually exclusive +_TOLVARS_SCF = ( "toldfe", "tolvrs", "tolwfr", "tolrff", "toldff", -} +) # Variables determining if data files should be read in input -_IRDVARS = { +_IRDVARS = ( "irdbseig", "irdbsreso", "irdhaydock", @@ -82,7 +83,7 @@ "irdwfkfine", "irdwfq", "ird1wf", -} +) # Tolerances for the different levels of accuracy. @@ -664,7 +665,7 @@ def pop_vars(self, keys): """ return self.remove_vars(keys, strict=False) - def remove_vars(self, keys, strict=True): + def remove_vars(self, keys: Sequence[str], strict: bool = True) -> dict[str, InputVariable]: """ Remove the variables listed in keys. Return dictionary with the variables that have been removed. @@ -925,8 +926,6 @@ def set_kpath(self, ndivsm, kptbounds=None, iscf=-2): If None, we use the default high-symmetry k-path defined in the pymatgen database. """ if kptbounds is None: - from pymatgen.symmetry.bandstructure import HighSymmKpath - hsym_kpath = HighSymmKpath(self.structure) name2frac_coords = hsym_kpath.kpath["kpoints"] diff --git a/pymatgen/io/adf.py b/pymatgen/io/adf.py index e0938ce4505..96700d03905 100644 --- a/pymatgen/io/adf.py +++ b/pymatgen/io/adf.py @@ -24,17 +24,12 @@ def is_numeric(s) -> bool: """ Return True is the string ``s`` is a numeric string. - Parameters - ---------- - s : str - A string. + Args: + s (str): A string Returns: - ------- - res : bool - If True, ``s`` is a numeric string and can be converted to an int or a - float. Otherwise False will be returned. - + bool: If True, ``s`` is a numeric string and can be converted to an int or a + float. Otherwise False will be returned. """ try: float(s) @@ -680,7 +675,6 @@ class AdfOutput: The normal modes of the molecule. freq_type : str Either 'Analytical' or 'Numerical'. - """ def __init__(self, filename): diff --git a/pymatgen/io/cp2k/outputs.py b/pymatgen/io/cp2k/outputs.py index 954bb511d35..9e45ea7d044 100644 --- a/pymatgen/io/cp2k/outputs.py +++ b/pymatgen/io/cp2k/outputs.py @@ -1721,7 +1721,6 @@ def parse_pdos(dos_file=None, spin_channel=None, total=False): (2) energy levels of this dos file (3) fermi energy (in eV). DOS object is not created here - """ spin = Spin(spin_channel) if spin_channel else Spin.down if "BETA" in os.path.split(dos_file)[-1] else Spin.up diff --git a/pymatgen/io/gaussian.py b/pymatgen/io/gaussian.py index 7014673c2c3..adf528b83bc 100644 --- a/pymatgen/io/gaussian.py +++ b/pymatgen/io/gaussian.py @@ -8,6 +8,7 @@ import numpy as np import scipy.constants as cst from monty.io import zopen +from scipy.stats import norm from pymatgen.core import Composition, Element, Molecule from pymatgen.core.operations import SymmOp @@ -577,7 +578,6 @@ class GaussianOutput: .. method:: save_scan_plot() Save a matplotlib plot of the potential energy surface to a file - """ def __init__(self, filename): @@ -1242,8 +1242,6 @@ def get_spectre_plot(self, sigma=0.05, step=0.01): the sum of gaussian functions (xas). A matplotlib plot. """ - from scipy.stats import norm - ax = pretty_plot(12, 8) transitions = self.read_excitation_energies() diff --git a/pymatgen/io/lammps/data.py b/pymatgen/io/lammps/data.py index aa9703cc769..d3a1da465b9 100644 --- a/pymatgen/io/lammps/data.py +++ b/pymatgen/io/lammps/data.py @@ -898,10 +898,8 @@ def set_charge_atom_type(self, charges: dict[str | int, float]) -> None: class Topology(MSONable): """ - Class carrying most data in Atoms, Velocities and molecular - topology sections for ONE SINGLE Molecule or Structure - object, or a plain list of Sites. - + Class carrying most data in Atoms, Velocities and molecular topology sections for + ONE SINGLE Molecule or Structure object, or a plain list of Sites. """ def __init__( diff --git a/pymatgen/io/lammps/inputs.py b/pymatgen/io/lammps/inputs.py index 0966f0a3fe7..c2240113a03 100644 --- a/pymatgen/io/lammps/inputs.py +++ b/pymatgen/io/lammps/inputs.py @@ -1071,8 +1071,6 @@ def write_lammps_inputs( timestep 0.005 run 100 - - """ variables = {} if settings is None else settings template = Template(script_template) diff --git a/pymatgen/io/lobster/lobsterenv.py b/pymatgen/io/lobster/lobsterenv.py index 4c3181d78a1..881391c1e27 100644 --- a/pymatgen/io/lobster/lobsterenv.py +++ b/pymatgen/io/lobster/lobsterenv.py @@ -1384,8 +1384,6 @@ class ICOHPNeighborsInfo(NamedTuple): atoms (list[list[str]]): list of list describing the species present in the identified interactions (names from ICOHPLIST), e.g., ["Ag3", "O5"] central_isites (list[int]): list of the central isite for each identified interaction. - - """ total_icohp: float diff --git a/pymatgen/io/lobster/outputs.py b/pymatgen/io/lobster/outputs.py index 3a45552c6bf..9fcfc7a37a7 100644 --- a/pymatgen/io/lobster/outputs.py +++ b/pymatgen/io/lobster/outputs.py @@ -1664,9 +1664,8 @@ def get_orb_from_str(orbs): Returns: list of tw Orbital objects - """ - # TODO: also useful for plotting of dos + # TODO: also useful for plotting of DOS orb_labs = [ "s", "p_y", diff --git a/pymatgen/io/vasp/optics.py b/pymatgen/io/vasp/optics.py index cc2bbe69479..bb83c236c49 100644 --- a/pymatgen/io/vasp/optics.py +++ b/pymatgen/io/vasp/optics.py @@ -308,7 +308,6 @@ def get_delta(x0: float, sigma: float, nx: int, dx: float, ismear: int = 3): Return: np.array: Array of size `nx` with delta function on the desired outputgrid. - """ xgrid = np.linspace(0, nx * dx, nx, endpoint=False) xgrid -= x0 @@ -370,7 +369,6 @@ def epsilon_imag( Return: np.array: Array of size `nedos` with the imaginary part of the dielectric function. - """ norm_kweights = np.array(kweights) / np.sum(kweights) egrid = np.linspace(0, nedos * deltae, nedos, endpoint=False) diff --git a/pymatgen/io/vasp/sets.py b/pymatgen/io/vasp/sets.py index 1ef776b2192..9d3a92ad7e1 100644 --- a/pymatgen/io/vasp/sets.py +++ b/pymatgen/io/vasp/sets.py @@ -48,6 +48,7 @@ from pymatgen.analysis.structure_matcher import StructureMatcher from pymatgen.core import Element, PeriodicSite, SiteCollection, Species, Structure +from pymatgen.io.lobster import Lobsterin from pymatgen.io.vasp.inputs import Incar, Kpoints, Poscar, Potcar, VaspInput from pymatgen.io.vasp.outputs import Outcar, Vasprun from pymatgen.symmetry.analyzer import SpacegroupAnalyzer @@ -2891,8 +2892,6 @@ def __init__( @property def incar(self) -> Incar: - from pymatgen.io.lobster import Lobsterin - # predefined basis! Check if the basis is okay! (charge spilling and bandoverlaps!) if self.user_supplied_basis is None and self.address_basis_file is None: basis = Lobsterin.get_basis(structure=self.structure, potcar_symbols=self.potcar_symbols) @@ -3161,7 +3160,6 @@ class MPAbsorptionSet(MPRelaxSet): For all steps other than the first one (static), the recommendation is to use from_prev_calculation on the preceding run in the series. It is important to ensure Gamma centred kpoints for the RPA step. - """ # CONFIG = _load_yaml_config("MPAbsorptionSet") diff --git a/pymatgen/io/xcrysden.py b/pymatgen/io/xcrysden.py index f1c8a60ffe3..1a75ecccf22 100644 --- a/pymatgen/io/xcrysden.py +++ b/pymatgen/io/xcrysden.py @@ -2,14 +2,9 @@ from __future__ import annotations -from typing import TYPE_CHECKING - import numpy as np -from pymatgen.core import Element - -if TYPE_CHECKING: - from pymatgen.core import Structure +from pymatgen.core import Element, Structure __author__ = "Matteo Giantomassi" __copyright__ = "Copyright 2013, The Materials Project" @@ -116,8 +111,6 @@ def from_str(cls, input_string, cls_=None): raise ValueError("Invalid XSF data") if cls_ is None: - from pymatgen.core.structure import Structure - cls_ = Structure s = cls_(lattice, species, coords, coords_are_cartesian=True) diff --git a/pymatgen/phonon/dos.py b/pymatgen/phonon/dos.py index 2dea2f4b289..a38df186036 100644 --- a/pymatgen/phonon/dos.py +++ b/pymatgen/phonon/dos.py @@ -8,6 +8,7 @@ import scipy.constants as const from monty.functools import lazy_property from monty.json import MSONable +from scipy.ndimage.filters import gaussian_filter1d from pymatgen.core.structure import Structure from pymatgen.util.coord import get_linear_interpolated_value @@ -55,12 +56,10 @@ def get_smeared_densities(self, sigma: float) -> np.ndarray: Returns: Gaussian-smeared densities. """ - from scipy.ndimage.filters import gaussian_filter1d - diff = [self.frequencies[i + 1] - self.frequencies[i] for i in range(len(self.frequencies) - 1)] - avgdiff = sum(diff) / len(diff) + avg_diff = sum(diff) / len(diff) - return gaussian_filter1d(self.densities, sigma / avgdiff) + return gaussian_filter1d(self.densities, sigma / avg_diff) def __add__(self, other: PhononDos) -> PhononDos: """Adds two DOS together. Checks that frequency scales are the same. @@ -98,10 +97,10 @@ def get_interpolated_value(self, frequency) -> float: def __str__(self) -> str: """Returns a string which can be easily plotted (using gnuplot).""" - stringarray = [f"#{'Frequency':30s} {'Density':30s}"] + str_arr = [f"#{'Frequency':30s} {'Density':30s}"] for i, frequency in enumerate(self.frequencies): - stringarray.append(f"{frequency:.5f} {self.densities[i]:.5f}") - return "\n".join(stringarray) + str_arr.append(f"{frequency:.5f} {self.densities[i]:.5f}") + return "\n".join(str_arr) @classmethod def from_dict(cls, d: dict[str, Sequence]) -> PhononDos: diff --git a/pymatgen/phonon/gruneisen.py b/pymatgen/phonon/gruneisen.py index c726e81bc4f..69bc09fb269 100644 --- a/pymatgen/phonon/gruneisen.py +++ b/pymatgen/phonon/gruneisen.py @@ -8,6 +8,7 @@ import scipy.constants as const from monty.dev import requires from monty.json import MSONable +from scipy.interpolate import UnivariateSpline from pymatgen.core import Structure from pymatgen.core.lattice import Lattice @@ -194,8 +195,6 @@ def phdos(self) -> PhononDos: @property def debye_temp_limit(self) -> float: """Debye temperature in K. Adapted from apipy.""" - from scipy.interpolate import UnivariateSpline - f_mesh = self.tdos.frequency_points * const.tera dos = self.tdos.dos diff --git a/pymatgen/phonon/plotter.py b/pymatgen/phonon/plotter.py index ca86818d7a9..9daa2d617b8 100644 --- a/pymatgen/phonon/plotter.py +++ b/pymatgen/phonon/plotter.py @@ -41,8 +41,7 @@ def freq_units(units: Literal["thz", "ev", "mev", "ha", "cm-1", "cm^-1"]) -> Fre units: str, accepted values: thz, ev, mev, ha, cm-1, cm^-1. Returns: - Returns conversion factor from THz to the required units and the label in the form of a namedtuple - + Conversion factor from THz to the required units and the label in the form of a namedtuple """ dct = { "thz": FreqUnits(1, "THz"), diff --git a/pymatgen/symmetry/groups.py b/pymatgen/symmetry/groups.py index a3855792a78..2cc2de961c4 100644 --- a/pymatgen/symmetry/groups.py +++ b/pymatgen/symmetry/groups.py @@ -18,6 +18,7 @@ from monty.design_patterns import cached_class from monty.serialization import loadfn +from pymatgen.core.operations import SymmOp from pymatgen.util.string import Stringify if TYPE_CHECKING: @@ -25,7 +26,6 @@ # don't import at runtime to avoid circular import from pymatgen.core.lattice import Lattice - from pymatgen.core.operations import SymmOp # noqa: TCH004 SYMM_DATA = loadfn(os.path.join(os.path.dirname(__file__), "symm_data.json")) @@ -115,8 +115,6 @@ def __init__(self, int_symbol: str) -> None: Args: int_symbol (str): International or Hermann-Mauguin Symbol. """ - from pymatgen.core.operations import SymmOp - self.symbol = int_symbol self.generators = [ SYMM_DATA["generator_matrices"][enc] for enc in SYMM_DATA["point_group_encoding"][int_symbol] @@ -207,8 +205,6 @@ def __init__(self, int_symbol: str) -> None: classmethod. Alternative origin choices can be indicated by a translation vector, e.g., 'Fm-3m(a-1/4,b-1/4,c-1/4)'. """ - from pymatgen.core.operations import SymmOp - int_symbol = re.sub(r" ", "", int_symbol) if int_symbol in SpaceGroup.abbrev_sg_mapping: int_symbol = SpaceGroup.abbrev_sg_mapping[int_symbol] @@ -319,8 +315,6 @@ def symmetry_ops(self) -> set[SymmOp]: """Full set of symmetry operations as matrices. Lazily initialized as generation sometimes takes a bit of time. """ - from pymatgen.core.operations import SymmOp - if self._symmetry_ops is None: self._symmetry_ops = {SymmOp(m) for m in self._generate_full_symmetry_ops()} return self._symmetry_ops @@ -357,8 +351,6 @@ def get_orbit_and_generators(self, p: ArrayLike, tol: float = 1e-5) -> tuple[lis Returns: tuple[list[np.ndarray], list[SymmOp]]: Orbit and generators for point. """ - from pymatgen.core.operations import SymmOp - orbit: list[np.ndarray] = [np.array(p, dtype=float)] identity = SymmOp.from_rotation_and_translation(np.eye(3), np.zeros(3)) generators: list[np.ndarray] = [identity] diff --git a/pymatgen/transformations/advanced_transformations.py b/pymatgen/transformations/advanced_transformations.py index b460766e910..ee9dfceee3c 100644 --- a/pymatgen/transformations/advanced_transformations.py +++ b/pymatgen/transformations/advanced_transformations.py @@ -12,6 +12,7 @@ from typing import TYPE_CHECKING, Callable import numpy as np +from joblib import Parallel, delayed from monty.dev import requires from monty.fractions import lcm from monty.json import MSONable @@ -461,8 +462,6 @@ def _get_stats(struct): return {"num_sites": len(struct), "structure": struct} - from joblib import Parallel, delayed - all_structures = Parallel(n_jobs=self.n_jobs)(delayed(_get_stats)(struct) for struct in structures) def sort_func(s): diff --git a/pymatgen/util/string.py b/pymatgen/util/string.py index 152c97d6572..3d4f1a2579a 100644 --- a/pymatgen/util/string.py +++ b/pymatgen/util/string.py @@ -333,12 +333,9 @@ def disordered_formula(disordered_struct, symbols=("x", "y", "z"), fmt="plain"): Returns (str): a disordered formula string """ - # this is in string utils and not in - # Composition because we need to have access - # to site occupancies to calculate this, so - # have to pass the full structure as an argument - # (alternatively this could be made a method on - # Structure) + # this is in string utils and not in Composition because we need to have access to + # site occupancies to calculate this, so have to pass the full structure as an + # argument (alternatively this could be made a method on Structure) from pymatgen.core import Composition, get_el_sp if disordered_struct.is_ordered: diff --git a/tests/analysis/test_molecule_matcher.py b/tests/analysis/test_molecule_matcher.py index 1d5edf21806..d71afae26ec 100644 --- a/tests/analysis/test_molecule_matcher.py +++ b/tests/analysis/test_molecule_matcher.py @@ -18,6 +18,7 @@ ) from pymatgen.core.operations import SymmOp from pymatgen.core.structure import Lattice, Molecule, Structure +from pymatgen.io.xyz import XYZ from pymatgen.util.testing import TEST_FILES_DIR try: @@ -72,8 +73,6 @@ def permute(mol, seed): def generate_Si_cluster(): - from pymatgen.io.xyz import XYZ - coords = [[0, 0, 0], [0.75, 0.5, 0.75]] lattice = Lattice.from_parameters(a=3.84, b=3.84, c=3.84, alpha=120, beta=90, gamma=60) @@ -108,8 +107,6 @@ def generate_Si_cluster(): def generate_Si2O_cluster(): - from pymatgen.io.xyz import XYZ - coords = [ [0.625, 0.625, 0.625], [0.625, 0.625, 0.125], diff --git a/tests/core/test_structure.py b/tests/core/test_structure.py index 1222e652b8d..4e166c9db60 100644 --- a/tests/core/test_structure.py +++ b/tests/core/test_structure.py @@ -3,6 +3,7 @@ import json import os import random +from fractions import Fraction from pathlib import Path from shutil import which from unittest import skipIf @@ -1246,7 +1247,6 @@ def test_from_spacegroup(self): ["Cs"], [[0, 0, 0], [0.5, 0.5, 0.5]], ) - from fractions import Fraction struct = Structure.from_spacegroup(139, np.eye(3), ["H"], [[Fraction(1, 2), Fraction(1, 4), Fraction(0)]]) assert len(struct) == 8 diff --git a/tests/io/test_adf.py b/tests/io/test_adf.py index 878e9b0ddfe..4bd2ed4e5c7 100644 --- a/tests/io/test_adf.py +++ b/tests/io/test_adf.py @@ -82,7 +82,6 @@ def readfile(file_object): ------- content : str The content of the file. - """ if hasattr(file_object, "read"): return file_object.read() diff --git a/tests/transformations/test_advanced_transformations.py b/tests/transformations/test_advanced_transformations.py index 626011f40d0..6d5ba14566c 100644 --- a/tests/transformations/test_advanced_transformations.py +++ b/tests/transformations/test_advanced_transformations.py @@ -10,7 +10,7 @@ from numpy.testing import assert_allclose, assert_array_equal from pytest import approx -from pymatgen.analysis.energy_models import IsingModel +from pymatgen.analysis.energy_models import IsingModel, SymmetryModel from pymatgen.analysis.gb.grain import GrainBoundaryGenerator from pymatgen.core import Lattice, Molecule, Species, Structure from pymatgen.core.surface import SlabGenerator @@ -351,7 +351,6 @@ def test_as_from_dict(self): _ = json.dumps(d) trans = MagOrderingTransformation.from_dict(d) assert trans.mag_species_spin == {"Fe": 5} - from pymatgen.analysis.energy_models import SymmetryModel assert isinstance(trans.energy_model, SymmetryModel) diff --git a/tests/transformations/test_standard_transformations.py b/tests/transformations/test_standard_transformations.py index 5febecd4679..4136cfc32a0 100644 --- a/tests/transformations/test_standard_transformations.py +++ b/tests/transformations/test_standard_transformations.py @@ -348,13 +348,7 @@ def test_symmetrized_structure(self): def test_too_small_cell(self): trafo = OrderDisorderedStructureTransformation() coords = [[0.5, 0.5, 0.5]] - lattice = Lattice( - [ - [3.8401979337, 0.00, 0.00], - [1.9200989668, 3.3257101909, 0.00], - [0.00, -2.2171384943, 3.1355090603], - ] - ) + lattice = Lattice([[3.8401979337, 0, 0], [1.9200989668, 3.3257101909, 0], [0, -2.2171384943, 3.1355090603]]) struct = Structure(lattice, [{"X4+": 0.33, "O2-": 0.33, "P5+": 0.33}], coords) with pytest.raises(ValueError, match="Occupancy fractions not consistent with size of unit cell"): trafo.apply_transformation(struct)