Skip to content

qlroms.utils.paths

Path registry: one place to name directories, including ones OUTSIDE data_dir().

The defaults below all live under data_dir() ($QLROM_DATA or ~/.cache/qlrom). Machine-specific locations (cluster mounts, external drives, other repos) go in paths_local.py next to this file -- plain module-level constants that extend or override the defaults:

# qlroms/utils/paths_local.py  (gitignored, never committed or distributed)
from pathlib import Path
PINBALL_MESHES = Path("/somewhere/pinball/meshes")

Usage:

from qlroms.utils import paths
paths.PINBALL_MESHES          # local override if defined, default otherwise
paths.defined()               # everything registered, name -> Path

paths_local.py is gitignored and releases are built by CI from the git tag, so personal paths never reach GitHub or PyPI.

data_dir()

Cache root for self-generated trajectories/models: $QLROM_DATA or ~/.cache/qlrom.

Source code in qlroms/utils/paths.py
28
29
30
def data_dir() -> Path:
    """Cache root for self-generated trajectories/models: $QLROM_DATA or ~/.cache/qlrom."""
    return Path(os.environ.get("QLROM_DATA", str(Path.home() / ".cache" / "qlrom")))

models_dir(family)

Where trained models are saved: /models// when qlroms runs from an editable checkout (pyproject.toml at the repo root), else data_dir()/models/. $QLROM_MODELS overrides the root.

Source code in qlroms/utils/paths.py
49
50
51
52
53
54
55
56
57
58
59
def models_dir(family: str) -> Path:
    """Where trained models are saved: <repo>/models/<family>/ when qlroms runs
    from an editable checkout (pyproject.toml at the repo root), else
    data_dir()/models/<family>. $QLROM_MODELS overrides the root."""
    root = os.environ.get("QLROM_MODELS")
    if root is None:
        repo = Path(__file__).resolve().parents[2]
        root = repo / "models" if (repo / "pyproject.toml").exists() else data_dir() / "models"
    d = Path(root) / family
    d.mkdir(parents=True, exist_ok=True)
    return d

defined()

All registered paths (defaults + local overrides), name -> Path.

Source code in qlroms/utils/paths.py
62
63
64
65
def defined() -> dict[str, Path]:
    """All registered paths (defaults + local overrides), name -> Path."""
    return {name: Path(value) for name, value in globals().items()
            if not name.startswith("_") and isinstance(value, (str, Path))}

mmap_npz(path, mirror_root)

Dict of memory-mapped arrays for path, unpacked once under mirror_root/<stem>/ (one .npy per key); later calls only stat the source. The stamp carries the source's size and mtime, so rebuilding the npz refreshes the mirror by itself.

Source code in qlroms/utils/paths.py
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
def mmap_npz(path, mirror_root):
    """Dict of memory-mapped arrays for ``path``, unpacked once under
    ``mirror_root/<stem>/`` (one .npy per key); later calls only stat the source.
    The stamp carries the source's size and mtime, so rebuilding the npz
    refreshes the mirror by itself."""
    path = Path(path)
    mirror = Path(mirror_root) / path.stem
    stamp = mirror / "stamp"
    key = f"{path.stat().st_size} {int(path.stat().st_mtime)}"
    if not (stamp.exists() and stamp.read_text() == key):
        print(f"caching {path.name} as mmap-able .npy files -> {mirror}/ (one-off) ...")
        mirror.mkdir(parents=True, exist_ok=True)
        with np.load(path, allow_pickle=False) as z:
            for k in z.files:
                np.save(mirror / f"{k}.npy", z[k])
        stamp.write_text(key)
    return {f.stem: np.load(f, mmap_mode="r") for f in mirror.glob("*.npy")}