worldmem-baseline-evals / DecMem /scripts /build_worldmem_csv.py
BonanDing's picture
Add isolated Minecraft and RE10K baseline evaluation suite
59630ba verified
Raw History Blame Contribute Delete
3.22 kB
#!/usr/bin/env python3
"""Build WorldMem train/test CSV index files from mp4/npz pairs.
Each row: video_path, action_path (paths relative to the project cwd when possible).
When --root is a symlink under the project (e.g. ./data), CSV rows use paths like
data/training/.... Avoid resolving symlinks so relative paths stay valid.
Example:
python scripts/build_worldmem_csv.py
"""
from __future__ import annotations
import argparse
import csv
import random
from pathlib import Path
def _path_for_csv(path: Path) -> str:
"""Path for CSV rows, relative to cwd when possible (preserves symlinks)."""
if not path.is_absolute():
return path.as_posix()
try:
return path.relative_to(Path.cwd()).as_posix()
except ValueError:
return path.as_posix()
def collect_pairs(split_dir: Path, root: Path) -> list[tuple[str, str]]:
"""Collect (video_path, action_path) for every mp4 with a matching npz."""
if not split_dir.is_dir():
raise FileNotFoundError(f"Split directory not found: {split_dir}")
pairs: list[tuple[str, str]] = []
missing_npz: list[str] = []
for mp4 in sorted(split_dir.rglob("*.mp4")):
npz = mp4.with_suffix(".npz")
if not npz.is_file():
missing_npz.append(mp4.relative_to(root).as_posix())
continue
pairs.append((
_path_for_csv(mp4),
_path_for_csv(npz),
))
if missing_npz:
print(f" warning: {len(missing_npz)} mp4 files without matching npz "
f"(first: {missing_npz[0]})")
return pairs
def write_csv(rows: list[tuple[str, str]], output_path: Path) -> None:
output_path.parent.mkdir(parents=True, exist_ok=True)
with output_path.open("w", newline="", encoding="utf-8") as f:
writer = csv.writer(f)
writer.writerow(["video_path", "action_path"])
writer.writerows(rows)
print(f" wrote {len(rows)} rows -> {output_path}")
def main() -> None:
parser = argparse.ArgumentParser(description="Build WorldMem train/test CSV metadata.")
parser.add_argument(
"--root",
type=str,
default='./data',
help=f"Dataset root directory",
)
parser.add_argument(
"--output_dir",
type=str,
default='./data',
help="Directory for train.csv / test.csv (default: same as --root)",
)
parser.add_argument(
"--seed",
type=int,
default=42,
help="Random seed for shuffling rows",
)
args = parser.parse_args()
root = Path(args.root)
output_dir = Path(args.output_dir) if args.output_dir else root
splits = {
"train.csv": root / "training",
"test.csv": root / "test",
}
print(f"Dataset root : {root} (-> {root.resolve()})")
print(f"Output dir : {output_dir}")
print(f"Shuffle seed : {args.seed}")
rng = random.Random(args.seed)
for csv_name, split_dir in splits.items():
print(f"\n[{csv_name}] scanning {split_dir.relative_to(root)}/")
pairs = collect_pairs(split_dir, root)
rng.shuffle(pairs)
write_csv(pairs, output_dir / csv_name)
print("\nDone.")
if __name__ == "__main__":
main()