Skip to content
Open
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
7 changes: 4 additions & 3 deletions dpdata/bond_order_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,12 @@ def __init__(
self.check_data()

def from_fmt_obj(self, fmtobj, file_name, **kwargs):
post_func_controls = self._get_post_func_controls(
fmtobj.from_bond_order_system, kwargs
)
mol = fmtobj.from_bond_order_system(file_name, **kwargs)
self.from_rdkit_mol(mol)
if hasattr(fmtobj.from_bond_order_system, "post_func"):
for post_f in fmtobj.from_bond_order_system.post_func: # type: ignore
self.post_funcs.get_plugin(post_f)(self)
self._apply_post_funcs(fmtobj.from_bond_order_system, post_func_controls)
return self

def to_fmt_obj(self, fmtobj, *args, **kwargs):
Expand Down
62 changes: 47 additions & 15 deletions dpdata/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ class System:

Restrictions:
- `d_example['orig']` is always [0, 0, 0]
- `d_example['cells'][ii]` is always lower triangular (lammps cell tensor convention)
- `d_example['cells'][ii]` is lower triangular (the LAMMPS cell tensor
convention) when `rot_lower_triangular` is enabled. Set
`rot_lower_triangular=False` while loading to preserve the source
cell orientation.

Attributes
----------
Expand Down Expand Up @@ -108,6 +111,7 @@ def __init__(
step: int = 1,
data: dict[str, Any] | None = None,
convergence_check: bool = True,
rot_lower_triangular: bool = True,
**kwargs,
):
"""Constructor.
Expand Down Expand Up @@ -180,6 +184,9 @@ def __init__(
The raw data of System class.
convergence_check : boolean
Whether to request a convergence check.
rot_lower_triangular : boolean
Whether to apply the registered ``rot_lower_triangular`` post
function after loading. The default is ``True``.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
**kwargs : dict
other parameters
"""
Expand All @@ -197,15 +204,19 @@ def __init__(
return
if file_name is None:
return
self.from_fmt(
file_name,
fmt,
type_map=type_map,
begin=begin,
step=step,
convergence_check=convergence_check,
load_kwargs = {
"type_map": type_map,
"begin": begin,
"step": step,
"convergence_check": convergence_check,
**kwargs,
)
}
# The default keeps the historical post-processing behavior. Only
# pass an explicit opt-out to format readers; this avoids adding a
# control-only keyword to third-party readers that do not accept it.
if not rot_lower_triangular:
load_kwargs["rot_lower_triangular"] = False
self.from_fmt(file_name, fmt, **load_kwargs)

if type_map is not None:
self.apply_type_map(type_map)
Expand Down Expand Up @@ -236,7 +247,29 @@ def from_fmt(self, file_name: Any, fmt: str = "auto", **kwargs: Any):
fmt = os.path.basename(file_name).split(".")[-1].lower()
return self.from_fmt_obj(load_format(fmt), file_name, **kwargs)

def _get_post_func_controls(
self, from_method: Any, kwargs: dict[str, Any]
) -> dict[str, Any]:
"""Remove registered post-function controls from format arguments."""
controls = {}
for post_f in getattr(from_method, "post_func", ()):
if post_f in kwargs:
controls[post_f] = kwargs.pop(post_f)
return controls

def _apply_post_funcs(self, from_method: Any, controls: dict[str, Any]):
"""Run registered post functions unless explicitly disabled.

A post function can be disabled by passing a false value under its
registered name. This keeps format-specific post-processing opt-out
while retaining the existing default behavior.
"""
for post_f in getattr(from_method, "post_func", ()):
if controls.get(post_f, True):
self.post_funcs.get_plugin(post_f)(self)

def from_fmt_obj(self, fmtobj: Format, file_name: Any, **kwargs: Any):
post_func_controls = self._get_post_func_controls(fmtobj.from_system, kwargs)
data = fmtobj.from_system(file_name, **kwargs)
if data:
if isinstance(data, (list, tuple)):
Expand All @@ -245,9 +278,7 @@ def from_fmt_obj(self, fmtobj: Format, file_name: Any, **kwargs: Any):
else:
self.data = {**self.data, **data}
self.check_data()
if hasattr(fmtobj.from_system, "post_func"):
for post_f in fmtobj.from_system.post_func: # type: ignore
self.post_funcs.get_plugin(post_f)(self)
self._apply_post_funcs(fmtobj.from_system, post_func_controls)
return self

def to(self, fmt: str, *args: Any, **kwargs: Any) -> System:
Expand Down Expand Up @@ -1257,6 +1288,9 @@ class LabeledSystem(System):
post_funcs = Plugin() + System.post_funcs

def from_fmt_obj(self, fmtobj, file_name, **kwargs):
post_func_controls = self._get_post_func_controls(
fmtobj.from_labeled_system, kwargs
)
data = fmtobj.from_labeled_system(file_name, **kwargs)
if data:
if isinstance(data, (list, tuple)):
Expand All @@ -1265,9 +1299,7 @@ def from_fmt_obj(self, fmtobj, file_name, **kwargs):
else:
self.data = {**self.data, **data}
self.check_data()
if hasattr(fmtobj.from_labeled_system, "post_func"):
for post_f in fmtobj.from_labeled_system.post_func: # type: ignore
self.post_funcs.get_plugin(post_f)(self)
self._apply_post_funcs(fmtobj.from_labeled_system, post_func_controls)
return self

def to_fmt_obj(self, fmtobj, *args, **kwargs):
Expand Down
15 changes: 15 additions & 0 deletions tests/test_vasp_poscar_to_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,21 @@ def test_move_flags(self):
self.assertTrue(np.array_equal(self.system["move"], expected))


class TestPOSCARPostFunctionControl(unittest.TestCase):
def test_disable_rot_lower_triangular(self):
system = dpdata.System(
os.path.join("poscars", "POSCAR.oh.c"),
fmt="vasp/poscar",
rot_lower_triangular=False,
)
expected_cell = np.array(
[[0.0, 1.785, 1.785], [1.6065, 0.0, 1.785], [1.9635, 1.8207, 0.0]]
)
expected_coords = np.array([[0.0, 0.0, 0.0], [0.8925, 0.8925, 0.8925]])
np.testing.assert_allclose(system["cells"][0], expected_cell)
np.testing.assert_allclose(system["coords"][0], expected_coords)


class TestPOSCARMoveFlags(unittest.TestCase):
def setUp(self):
self.tmp_file = "POSCAR.tmp.1"
Expand Down
Loading