Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert some staticmethod to classmethod #3710

Merged
merged 3 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pymatgen/alchemy/transmuters.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,8 @@ def __init__(self, poscar_string, transformations=None, extend_collection=False)
trafo_struct = TransformedStructure.from_poscar_str(poscar_string, [])
super().__init__([trafo_struct], transformations, extend_collection=extend_collection)

@staticmethod
def from_filenames(poscar_filenames, transformations=None, extend_collection=False):
@classmethod
def from_filenames(cls, poscar_filenames, transformations=None, extend_collection=False) -> StandardTransmuter:
"""Convenient constructor to generates a POSCAR transmuter from a list of
POSCAR filenames.

Expand Down
28 changes: 13 additions & 15 deletions pymatgen/analysis/graphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ def with_empty_graph(

return cls(structure, graph_data=graph_data)

@staticmethod
def with_edges(structure: Structure, edges: dict) -> StructureGraph:
@classmethod
def with_edges(cls, structure: Structure, edges: dict) -> Self:
"""
Constructor for MoleculeGraph, using pre-existing or pre-defined edges
with optional edge parameters.
Expand All @@ -213,9 +213,7 @@ def with_edges(structure: Structure, edges: dict) -> StructureGraph:
Returns:
sg, a StructureGraph
"""
struct_graph = StructureGraph.with_empty_graph(
structure, name="bonds", edge_weight_name="weight", edge_weight_units=""
)
struct_graph = cls.with_empty_graph(structure, name="bonds", edge_weight_name="weight", edge_weight_units="")

for edge, props in edges.items():
try:
Expand Down Expand Up @@ -252,10 +250,10 @@ def with_edges(structure: Structure, edges: dict) -> StructureGraph:
struct_graph.set_node_attributes()
return struct_graph

@staticmethod
@classmethod
def with_local_env_strategy(
structure: Structure, strategy: NearNeighbors, weights: bool = False, edge_properties: bool = False
) -> StructureGraph:
cls, structure: Structure, strategy: NearNeighbors, weights: bool = False, edge_properties: bool = False
) -> Self:
"""
Constructor for StructureGraph, using a strategy
from pymatgen.analysis.local_env.
Expand All @@ -269,7 +267,7 @@ def with_local_env_strategy(
if not strategy.structures_allowed:
raise ValueError("Chosen strategy is not designed for use with structures! Please choose another strategy.")

struct_graph = StructureGraph.with_empty_graph(structure, name="bonds")
struct_graph = cls.with_empty_graph(structure, name="bonds")

for idx, neighbors in enumerate(strategy.get_all_nn_info(structure)):
for neighbor in neighbors:
Expand Down Expand Up @@ -1627,8 +1625,8 @@ def with_empty_graph(cls, molecule, name="bonds", edge_weight_name=None, edge_we

return cls(molecule, graph_data=graph_data)

@staticmethod
def with_edges(molecule: Molecule, edges: dict[tuple[int, int], None | dict]) -> MoleculeGraph:
@classmethod
def with_edges(cls, molecule: Molecule, edges: dict[tuple[int, int], None | dict]) -> Self:
"""
Constructor for MoleculeGraph, using pre-existing or pre-defined edges
with optional edge parameters.
DanielYang59 marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -1643,7 +1641,7 @@ def with_edges(molecule: Molecule, edges: dict[tuple[int, int], None | dict]) ->
Returns:
A MoleculeGraph
"""
mg = MoleculeGraph.with_empty_graph(molecule, name="bonds", edge_weight_name="weight", edge_weight_units="")
mg = cls.with_empty_graph(molecule, name="bonds", edge_weight_name="weight", edge_weight_units="")

for edge, props in edges.items():
try:
Expand Down Expand Up @@ -1671,8 +1669,8 @@ def with_edges(molecule: Molecule, edges: dict[tuple[int, int], None | dict]) ->
mg.set_node_attributes()
return mg

@staticmethod
def with_local_env_strategy(molecule, strategy) -> MoleculeGraph:
@classmethod
def with_local_env_strategy(cls, molecule, strategy) -> Self:
"""
Constructor for MoleculeGraph, using a strategy
from pymatgen.analysis.local_env.
Expand All @@ -1688,7 +1686,7 @@ def with_local_env_strategy(molecule, strategy) -> MoleculeGraph:
raise ValueError(f"{strategy=} is not designed for use with molecules! Choose another strategy.")
extend_structure = strategy.extend_structure_molecules

mg = MoleculeGraph.with_empty_graph(molecule, name="bonds", edge_weight_name="weight", edge_weight_units="")
mg = cls.with_empty_graph(molecule, name="bonds", edge_weight_name="weight", edge_weight_units="")

# NearNeighbor classes only (generally) work with structures
# molecules have to be boxed first
Expand Down
8 changes: 5 additions & 3 deletions pymatgen/core/operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from typing import Any

from numpy.typing import ArrayLike
from typing_extensions import Self

__author__ = "Shyue Ping Ong, Shyam Dwaraknath, Matthew Horton"

Expand Down Expand Up @@ -54,12 +55,13 @@ def __init__(self, affine_transformation_matrix: ArrayLike, tol: float = 0.01) -
self.affine_matrix = affine_transformation_matrix
self.tol = tol

@staticmethod
@classmethod
def from_rotation_and_translation(
cls,
rotation_matrix: ArrayLike = ((1, 0, 0), (0, 1, 0), (0, 0, 1)),
translation_vec: ArrayLike = (0, 0, 0),
tol: float = 0.1,
) -> SymmOp:
) -> Self:
"""Creates a symmetry operation from a rotation matrix and a translation
vector.

Expand All @@ -80,7 +82,7 @@ def from_rotation_and_translation(
affine_matrix = np.eye(4)
affine_matrix[0:3][:, 0:3] = rotation_matrix
affine_matrix[0:3][:, 3] = translation_vec
return SymmOp(affine_matrix, tol)
return cls(affine_matrix, tol)

def __eq__(self, other: object) -> bool:
if not isinstance(other, SymmOp):
Expand Down
4 changes: 2 additions & 2 deletions pymatgen/io/abinit/pseudos.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ def as_pseudo(cls, obj):
"""
return obj if isinstance(obj, cls) else cls.from_file(obj)

@staticmethod
def from_file(filename) -> Pseudo:
@classmethod
def from_file(cls, filename: str) -> Self:
"""
Build an instance of a concrete Pseudo subclass from filename.
Note: the parser knows the concrete class that should be instantiated
Expand Down
6 changes: 3 additions & 3 deletions pymatgen/io/babel.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,8 +333,8 @@ def from_file(

return cls(next(mols).OBMol)

@staticmethod
def from_molecule_graph(mol: MoleculeGraph) -> BabelMolAdaptor:
@classmethod
def from_molecule_graph(cls, mol: MoleculeGraph) -> Self:
"""
Read a molecule from a pymatgen MoleculeGraph object.

Expand All @@ -344,7 +344,7 @@ def from_molecule_graph(mol: MoleculeGraph) -> BabelMolAdaptor:
Returns:
BabelMolAdaptor object
"""
return BabelMolAdaptor(mol.molecule)
return cls(mol.molecule)

@needs_openbabel
@classmethod
Expand Down
8 changes: 4 additions & 4 deletions pymatgen/io/cp2k/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def __eq__(self, other: object) -> bool:
if self.name.upper() == other.name.upper():
v1 = [val.upper() if isinstance(val, str) else val for val in self.values]
v2 = [val.upper() if isinstance(val, str) else val for val in other.values] # noqa: PD011
if v1 == v2 and self.units == self.units:
if v1 == v2 and self.units == other.units:
return True
return False

Expand Down Expand Up @@ -2129,8 +2129,8 @@ def __init__(

# TODO kpoints objects are defined in the vasp module instead of a code agnostic module
# if this changes in the future as other codes are added, then this will need to change
@staticmethod
def from_kpoints(kpoints: VaspKpoints, kpoints_line_density=20):
@classmethod
def from_kpoints(cls, kpoints: VaspKpoints, kpoints_line_density: int = 20) -> Self:
"""
Initialize band structure section from a line-mode Kpoint object.

DanielYang59 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -2167,7 +2167,7 @@ def pairwise(iterable):
raise ValueError(
"Unsupported k-point style. Must be line-mode or explicit k-points (reciprocal/cartesian)."
)
return Band_Structure(kpoint_sets=kpoint_sets, filename="BAND.bs")
return cls(kpoint_sets=kpoint_sets, filename="BAND.bs")


@dataclass
Expand Down
8 changes: 4 additions & 4 deletions pymatgen/io/feff/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,10 +197,10 @@ def __init__(
raise ValueError("'struct' argument must be a Structure or Molecule!")
self.comment = comment or "None given"

@staticmethod
def from_cif_file(cif_file, source="", comment=""):
@classmethod
def from_cif_file(cls, cif_file: str, source: str = "", comment: str = "") -> Self:
"""
Static method to create Header object from cif_file.
Create Header object from cif_file.

Args:
cif_file: cif_file path and name
Expand All @@ -213,7 +213,7 @@ def from_cif_file(cif_file, source="", comment=""):
"""
parser = CifParser(cif_file)
structure = parser.parse_structures(primitive=True)[0]
return Header(structure, source, comment)
return cls(structure, source, comment)

@property
def structure_symmetry(self):
Expand Down
16 changes: 8 additions & 8 deletions pymatgen/io/pwmat/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
from pymatgen.symmetry.kpath import KPathSeek

if TYPE_CHECKING:
from typing_extensions import Self

from pymatgen.util.typing import PathLike

__author__ = "Hanyu Liu"
Expand Down Expand Up @@ -499,8 +501,8 @@ def __init__(
self.kpath.update({"path": path})
self.density = density

@staticmethod
def from_structure(structure: Structure, dim: int, density: float = 0.01) -> GenKpt:
@classmethod
def from_structure(cls, structure: Structure, dim: int, density: float = 0.01) -> Self:
"""Obtain a AtomConfig object from Structure object.

Args:
Expand Down Expand Up @@ -530,7 +532,7 @@ def from_structure(structure: Structure, dim: int, density: float = 0.01) -> Gen
kpts = kpath_set.kpath["kpoints"]
path = kpath_set.kpath["path"]
rec_lattice: np.ndarray = structure.lattice.reciprocal_lattice.matrix # with 2*pi
return GenKpt(rec_lattice, kpts, path, density * 2 * np.pi)
return cls(rec_lattice, kpts, path, density * 2 * np.pi)

def get_str(self):
"""Returns a string to be written as a gen.kpt file."""
Expand Down Expand Up @@ -601,8 +603,8 @@ def __init__(self, reciprocal_lattice: np.ndarray, kpts: dict[str, list], path:
self.kpath.update({"path": path})
self.density = density

@staticmethod
def from_structure(structure: Structure, dim: int, density: float = 0.01) -> HighSymmetryPoint:
@classmethod
def from_structure(cls, structure: Structure, dim: int, density: float = 0.01) -> Self:
"""Obtain HighSymmetry object from Structure object.

Args:
Expand All @@ -613,9 +615,7 @@ def from_structure(structure: Structure, dim: int, density: float = 0.01) -> Hig
"""
reciprocal_lattice: np.ndarray = structure.lattice.reciprocal_lattice.matrix
gen_kpt = GenKpt.from_structure(structure=structure, dim=dim, density=density)
return HighSymmetryPoint(
reciprocal_lattice, gen_kpt.kpath["kpoints"], gen_kpt.kpath["path"], density * 2 * np.pi
)
return cls(reciprocal_lattice, gen_kpt.kpath["kpoints"], gen_kpt.kpath["path"], density * 2 * np.pi)

def get_str(self) -> str:
"""Returns a string describing high symmetry points in HIGH_SYMMETRY_POINTS format."""
Expand Down
57 changes: 27 additions & 30 deletions pymatgen/io/vasp/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -1126,10 +1126,10 @@ def style(self, style) -> None:

self._style = style

@staticmethod
def automatic(subdivisions):
@classmethod
def automatic(cls, subdivisions) -> Self:
"""
Convenient static constructor for a fully automatic Kpoint grid, with
Constructor for a fully automatic Kpoint grid, with
gamma centered Monkhorst-Pack grids and the number of subdivisions
along each reciprocal lattice vector determined by the scheme in the
VASP manual.
DanielYang59 marked this conversation as resolved.
Show resolved Hide resolved
Expand All @@ -1141,15 +1141,12 @@ def automatic(subdivisions):
Returns:
Kpoints object
"""
return Kpoints(
"Fully automatic kpoint scheme", 0, style=Kpoints.supported_modes.Automatic, kpts=[[subdivisions]]
)
return cls("Fully automatic kpoint scheme", 0, style=Kpoints.supported_modes.Automatic, kpts=[[subdivisions]])

@staticmethod
def gamma_automatic(kpts: tuple[int, int, int] = (1, 1, 1), shift: Vector3D = (0, 0, 0)):
@classmethod
def gamma_automatic(cls, kpts: tuple[int, int, int] = (1, 1, 1), shift: Vector3D = (0, 0, 0)) -> Self:
"""
Convenient static constructor for an automatic Gamma centered Kpoint
grid.
Constructor for an automatic Gamma centered Kpoint grid.

Args:
kpts: Subdivisions N_1, N_2 and N_3 along reciprocal lattice
Expand All @@ -1159,10 +1156,10 @@ def gamma_automatic(kpts: tuple[int, int, int] = (1, 1, 1), shift: Vector3D = (0
Returns:
Kpoints object
"""
return Kpoints("Automatic kpoint scheme", 0, Kpoints.supported_modes.Gamma, kpts=[kpts], kpts_shift=shift)
return cls("Automatic kpoint scheme", 0, Kpoints.supported_modes.Gamma, kpts=[kpts], kpts_shift=shift)

@staticmethod
def monkhorst_automatic(kpts: tuple[int, int, int] = (2, 2, 2), shift: Vector3D = (0, 0, 0)):
@classmethod
def monkhorst_automatic(cls, kpts: tuple[int, int, int] = (2, 2, 2), shift: Vector3D = (0, 0, 0)) -> Self:
"""
Convenient static constructor for an automatic Monkhorst pack Kpoint
grid.
Expand All @@ -1175,10 +1172,10 @@ def monkhorst_automatic(kpts: tuple[int, int, int] = (2, 2, 2), shift: Vector3D
Returns:
Kpoints object
"""
return Kpoints("Automatic kpoint scheme", 0, Kpoints.supported_modes.Monkhorst, kpts=[kpts], kpts_shift=shift)
return cls("Automatic kpoint scheme", 0, Kpoints.supported_modes.Monkhorst, kpts=[kpts], kpts_shift=shift)

@staticmethod
def automatic_density(structure: Structure, kppa: float, force_gamma: bool = False):
@classmethod
def automatic_density(cls, structure: Structure, kppa: float, force_gamma: bool = False) -> Self:
"""
Returns an automatic Kpoint object based on a structure and a kpoint
density. Uses Gamma centered meshes for hexagonal cells and face-centered cells,
Expand Down Expand Up @@ -1215,10 +1212,10 @@ def automatic_density(structure: Structure, kppa: float, force_gamma: bool = Fal
else:
style = Kpoints.supported_modes.Monkhorst

return Kpoints(comment, 0, style, [num_div], (0, 0, 0))
return cls(comment, 0, style, [num_div], (0, 0, 0))

@staticmethod
def automatic_gamma_density(structure: Structure, kppa: float):
@classmethod
def automatic_gamma_density(cls, structure: Structure, kppa: float) -> Self:
"""
Returns an automatic Kpoint object based on a structure and a kpoint
density. Uses Gamma centered meshes always. For GW.
Expand Down Expand Up @@ -1249,10 +1246,10 @@ def automatic_gamma_density(structure: Structure, kppa: float):
comment = f"pymatgen with grid density = {kppa:.0f} / number of atoms"

n_kpts = 0
return Kpoints(comment, n_kpts, style, [n_div], (0, 0, 0))
return cls(comment, n_kpts, style, [n_div], (0, 0, 0))

@staticmethod
def automatic_density_by_vol(structure: Structure, kppvol: int, force_gamma: bool = False) -> Kpoints:
@classmethod
def automatic_density_by_vol(cls, structure: Structure, kppvol: int, force_gamma: bool = False) -> Self:
"""
Returns an automatic Kpoint object based on a structure and a kpoint
density per inverse Angstrom^3 of reciprocal cell.
Expand All @@ -1270,12 +1267,12 @@ def automatic_density_by_vol(structure: Structure, kppvol: int, force_gamma: boo
"""
vol = structure.lattice.reciprocal_lattice.volume
kppa = kppvol * vol * len(structure)
return Kpoints.automatic_density(structure, kppa, force_gamma=force_gamma)
return cls.automatic_density(structure, kppa, force_gamma=force_gamma)

@staticmethod
@classmethod
def automatic_density_by_lengths(
structure: Structure, length_densities: Sequence[float], force_gamma: bool = False
):
cls, structure: Structure, length_densities: Sequence[float], force_gamma: bool = False
) -> Self:
"""
Returns an automatic Kpoint object based on a structure and a k-point
density normalized by lattice constants.
Expand Down Expand Up @@ -1309,10 +1306,10 @@ def automatic_density_by_lengths(
else:
style = Kpoints.supported_modes.Monkhorst

return Kpoints(comment, 0, style, [num_div], (0, 0, 0))
return cls(comment, 0, style, [num_div], (0, 0, 0))

@staticmethod
def automatic_linemode(divisions, ibz):
@classmethod
def automatic_linemode(cls, divisions, ibz) -> Self:
"""
Convenient static constructor for a KPOINTS in mode line_mode.
gamma centered Monkhorst-Pack grids and the number of subdivisions
Expand Down Expand Up @@ -1340,7 +1337,7 @@ def automatic_linemode(divisions, ibz):
kpoints.append(ibz.kpath["kpoints"][path[-1]])
labels.append(path[-1])

return Kpoints(
return cls(
"Line_mode KPOINTS file",
style=Kpoints.supported_modes.Line_mode,
coord_type="Reciprocal",
Expand Down
Loading