Source code for pyretis.core.path_load
"""Load infinite-swapping paths from disk into :class:`.Path` objects.
These loaders were historically part of the inf-flavour ``Path`` module
(``pyretis.core._path_inf``). After the A3.1b Path collapse there is a
single :class:`pyretis.core.path.Path`, so the loaders live here, free of
the now-deleted ``_path_inf`` module. They build native ``Path`` objects
whose phasepoints are file-backed snapshot :class:`.System` objects (the
external-engine representation), exactly as the infinite-swapping
scheduler expects.
"""
from __future__ import annotations
import logging
import os
from typing import Any, Dict, List
from pyretis.core.path import Path
from pyretis.core._system_inf import System
from pyretis.inout._formatter_inf import (
EnergyPathFile,
OrderPathFile,
PathExtFile,
)
logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())
[docs]def load_path(pdir: str) -> Path:
"""Load a path from the given directory."""
trajtxt = os.path.join(pdir, "traj.txt")
ordertxt = os.path.join(pdir, "order.txt")
if not os.path.isfile(trajtxt):
raise FileNotFoundError(trajtxt)
if not os.path.isfile(ordertxt):
raise FileNotFoundError(ordertxt)
# load trajtxt
with PathExtFile(trajtxt, "r") as trajfile:
# Just get the first trajectory:
traj = next(trajfile.load())
# Update trajectory to use full path names:
for i, snapshot in enumerate(traj["data"]):
config = os.path.join(pdir, "accepted", snapshot[1])
traj["data"][i][1] = config
reverse = int(snapshot[3]) == -1
idx = int(snapshot[2])
traj["data"][i][2] = idx
traj["data"][i][3] = reverse
for config in set(frame[1] for frame in traj["data"]):
if not os.path.isfile(config):
raise FileNotFoundError(config)
# load ordertxt
with OrderPathFile(ordertxt, "r") as orderfile:
orderdata = next(orderfile.load())["data"][:, 1:]
path = Path()
for snapshot, order in zip(traj["data"], orderdata):
frame = System()
frame.order = order
frame.config = (snapshot[1], snapshot[2])
frame.vel_rev = snapshot[3]
path.phasepoints.append(frame)
_load_energies_for_path(path, pdir)
# TODO: CHECK PATH SOMEWHERE .acc, sta = _check_path(path, path_ensemble)
return path
[docs]def _load_energies_for_path(path: Path, dirname: str) -> None:
"""Load energy data for a path.
Args:
path: The path we are to set up/fill.
dirname: The path to the directory with the input files.
"""
energy_file_name = os.path.join(dirname, "energy.txt")
try:
with EnergyPathFile(energy_file_name, "r") as energyfile:
energy = next(energyfile.load())
path.update_energies(
energy["data"]["ekin"],
energy["data"]["vpot"],
energy["data"].get("etot", []),
energy["data"].get("temp", []),
)
except FileNotFoundError:
pass
[docs]def load_paths_from_disk(config: Dict[str, Any]) -> List[Path]:
"""Load paths from disk."""
load_dir = config["simulation"]["load_dir"]
paths = []
for pnumber in config["current"]["active"]:
new_path = load_path(os.path.join(load_dir, str(pnumber)))
status = "re" if "restarted_from" in config["current"] else "ld"
# TODO: important for shooting move if 'ld' is set. need a smart way
# to remember if status is 'sh' or 'wf' etc. maybe in the toml file.
new_path.generated = (status, float("nan"), 0, 0)
new_path.maxlen = config["simulation"]["tis_set"]["maxlength"]
paths.append(new_path)
# assign pnumber
paths[-1].path_number = pnumber
return paths