Skip to content

Commit

Permalink
make ResProvider child of MSONable
Browse files Browse the repository at this point in the history
  • Loading branch information
janosh committed Sep 7, 2022
1 parent d2c23cd commit bc239c3
Showing 1 changed file with 28 additions and 27 deletions.
55 changes: 28 additions & 27 deletions pymatgen/io/res.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Converting from and back to pymatgen objects is expected to be reversible, i.e. you
should get the same Structure or ComputedStructureEntry back. On the other hand, converting
from and back to a string/file is not garunteed to be reversible, i.e. a diff on the output
from and back to a string/file is not guaranteed to be reversible, i.e. a diff on the output
would not be empty. The difference should be limited to whitespace, float precision, and the
REM entries.
Expand All @@ -19,6 +19,7 @@

import dateutil.parser # type: ignore
from monty.io import zopen
from monty.json import MSONable

from pymatgen.core.lattice import Lattice
from pymatgen.core.periodic_table import Element
Expand Down Expand Up @@ -138,11 +139,11 @@ def __init__(self):
self.source: str = ""

def _parse_titl(self, line: str) -> AirssTITL | None:
"""Parses the TITL entry. Checks for airss values in the entry."""
"""Parses the TITL entry. Checks for AIRSS values in the entry."""
fields = line.split(maxsplit=6)
if len(fields) >= 6:
# this is probably an airss res file
seed, pressure, volume, energy, spin, absspin = fields[:6]
# this is probably an AIRSS res file
seed, pressure, volume, energy, spin, abs_spin = fields[:6]
spg, nap = "P1", "1"
if len(fields) == 7:
rest = fields[6]
Expand All @@ -153,10 +154,10 @@ def _parse_titl(self, line: str) -> AirssTITL | None:
nmin = rest.find("n -")
nap = rest[nmin + 4 :]
return AirssTITL(
seed, float(pressure), float(volume), float(energy), float(spin), float(absspin), spg, int(nap)
seed, float(pressure), float(volume), float(energy), float(spin), float(abs_spin), spg, int(nap)
)
else:
# there should at least be the first 6 fields if it's an airss res file
# there should at least be the first 6 fields if it's an AIRSS res file
# if it doesn't have them, then just stop looking
return None

Expand Down Expand Up @@ -239,7 +240,7 @@ def _parse_str(cls, source: str) -> Res:
return self._parse_txt()

@classmethod
def _parse_filename(cls, filename: str) -> Res:
def _parse_file(cls, filename: str) -> Res:
"""Parses the res file as a file."""
self = cls()
self.filename = filename
Expand Down Expand Up @@ -323,24 +324,24 @@ def write(self, filename: str) -> None:
return None


class ResProvider:
class ResProvider(MSONable):
"""
Provides access to elements of the res file in the form of familiar pymatgen objects.
"""

def __init__(self, res: Res):
def __init__(self, res: Res) -> None:
"""The :func:`from_str` and :func:`from_file` methods should be used instead of constructing this directly."""
self._res = res

@classmethod
def from_str(cls, string: str):
def from_str(cls, string: str) -> ResProvider:
"""Construct a Provider from a string."""
return cls(ResParser._parse_str(string))

@classmethod
def from_file(cls, filename: str):
def from_file(cls, filename: str) -> ResProvider:
"""Construct a Provider from a file."""
return cls(ResParser._parse_filename(filename))
return cls(ResParser._parse_file(filename))

@property
def rems(self) -> list[str]:
Expand All @@ -356,8 +357,8 @@ def lattice(self) -> Lattice:
@property
def sites(self) -> list[PeriodicSite]:
"""Construct a list of PeriodicSites from the res file."""
sfactag = self._res.SFAC
return [PeriodicSite(ion.specie, ion.pos, self.lattice) for ion in sfactag.ions]
sfac_tag = self._res.SFAC
return [PeriodicSite(ion.specie, ion.pos, self.lattice) for ion in sfac_tag.ions]

@property
def structure(self) -> Structure:
Expand All @@ -369,7 +370,7 @@ class AirssProvider(ResProvider):
"""
Provides access to the res file as does :class:`ResProvider`. This class additionally provides
access to fields in the TITL entry and various other fields found in the REM entries
that airss puts in the file. Values in the TITL entry that AIRSS could not get end up as 0.
that AIRSS puts in the file. Values in the TITL entry that AIRSS could not get end up as 0.
If the TITL entry is malformed, empty, or missing then attempting to construct this class
from a res file will raise a ResError.
Expand Down Expand Up @@ -399,14 +400,14 @@ def __init__(self, res: Res, parse_rems: Literal["gentle", "strict"] = "gentle")
self.parse_rems = parse_rems

@classmethod
def from_str(cls, string: str, parse_rems: Literal["gentle", "strict"] = "gentle"):
def from_str(cls, string: str, parse_rems: Literal["gentle", "strict"] = "gentle") -> AirssProvider:
"""Construct a Provider from a string."""
return cls(ResParser._parse_str(string), parse_rems)

@classmethod
def from_file(cls, filename: str, parse_rems: Literal["gentle", "strict"] = "gentle"):
def from_file(cls, filename: str, parse_rems: Literal["gentle", "strict"] = "gentle") -> AirssProvider:
"""Construct a Provider from a file."""
return cls(ResParser._parse_filename(filename), parse_rems)
return cls(ResParser._parse_file(filename), parse_rems)

@classmethod
def _parse_date(cls, string: str) -> datetime.date:
Expand All @@ -417,10 +418,10 @@ def _parse_date(cls, string: str) -> datetime.date:
date_string = match.group(0)
return dateutil.parser.parse(date_string) # type: ignore

def _raise_or_none(self, e: ParseError):
def _raise_or_none(self, err: ParseError) -> None:
if self.parse_rems != "strict":
return None
raise e
raise err

def get_run_start_info(self) -> tuple[datetime.date, str] | None:
"""
Expand All @@ -434,7 +435,7 @@ def get_run_start_info(self) -> tuple[datetime.date, str] | None:
date = self._parse_date(rem)
path = rem.split()[-1]
return date, path
return self._raise_or_none(ParseError("Could not find run started information."))
return self._raise_or_none(ParseError("Could not find run started information.")) # type: ignore

def get_castep_version(self) -> str | None:
"""
Expand All @@ -447,7 +448,7 @@ def get_castep_version(self) -> str | None:
if rem.strip().startswith("CASTEP"):
srem = rem.split()
return srem[1][:-1]
return self._raise_or_none(ParseError("Could not find castep version.")) # type: ignore
return self._raise_or_none(ParseError("Could not find CASTEP version.")) # type: ignore

def get_func_rel_disp(self) -> tuple[str, str, str] | None:
"""
Expand All @@ -464,7 +465,7 @@ def get_func_rel_disp(self) -> tuple[str, str, str] | None:

def get_cut_grid_gmax_fsbc(self) -> tuple[float, float, float, str] | None:
"""
Retirieves the cut-off energy, grid scale, Gmax, and finite basis set correction setting
Retrieves the cut-off energy, grid scale, Gmax, and finite basis set correction setting
from the REM entries.
Returns:
Expand All @@ -480,7 +481,7 @@ def get_mpgrid_offset_nkpts_spacing(
self,
) -> tuple[tuple[int, int, int], tuple[float, float, float], int, float] | None:
"""
Retrieves the MP grid, the grid offsets, number of kpoints, and maximim kpoint spacing.
Retrieves the MP grid, the grid offsets, number of kpoints, and maximum kpoint spacing.
Returns:
(MP grid), (offsets), No. kpts, max spacing)
Expand All @@ -505,7 +506,7 @@ def get_airss_version(self) -> tuple[str, datetime.date] | None:
date = self._parse_date(rem)
v = rem.split()[2]
return v, date
return self._raise_or_none(ParseError("Could not find line with airss version.")) # type: ignore
return self._raise_or_none(ParseError("Could not find line with AIRSS version.")) # type: ignore

def _get_compiler(self):
raise NotImplementedError()
Expand Down Expand Up @@ -554,12 +555,12 @@ def energy(self) -> float:

@property
def integrated_spin_density(self) -> float:
"""Corresponds to the last ``Integrated Spin Density`` in the castep file."""
"""Corresponds to the last ``Integrated Spin Density`` in the CASTEP file."""
return self._TITL.integrated_spin_density

@property
def integrated_absolute_spin_density(self) -> float:
"""Corresponds to the last ``Integrated |Spin Density|`` in the castep file."""
"""Corresponds to the last ``Integrated |Spin Density|`` in the CASTEP file."""
return self._TITL.integrated_absolute_spin_density

@property
Expand Down

0 comments on commit bc239c3

Please sign in to comment.