Source code for omniloader.data.npy

"""A dataset over a per-sample ``.npy`` folder layout.

:class:`NpyFolderDataset` reads the common feature-extraction layout where each
sample is a directory of ``.npy`` files, one per named value::

    root/
      <sample_key>/
        video.npy
        audio.npy
        valence.npy
        ...

Arrays are memory-mapped (``mmap_mode="r"``) so large features are not copied into
RAM until sliced. Every sample directory is expected to contain the same set of
files; the first sample defines the key set unless ``keys`` is given.
"""

from __future__ import annotations

from pathlib import Path
from typing import TYPE_CHECKING, Any

import numpy as np
import torch
from torch.utils.data import Dataset

if TYPE_CHECKING:
    from collections.abc import Sequence


[docs] class NpyFolderDataset(Dataset): """Read samples from a directory of per-sample ``.npy`` sub-folders. Args: root: Directory whose immediate sub-directories are samples. keys: Optional value names (``.npy`` stems) to load. When ``None``, the files present in the first sample directory define the key set. mmap: Memory-map the arrays instead of reading them fully. Defaults to ``True``. Raises: FileNotFoundError: If ``root`` has no sample sub-directories. """ def __init__( self, root: str | Path, keys: Sequence[str] | None = None, mmap: bool = True, ) -> None: self.root = Path(root) self.mmap = mmap self.sample_dirs = sorted(p for p in self.root.iterdir() if p.is_dir()) if not self.sample_dirs: raise FileNotFoundError(f"No sample sub-directories found under {self.root}") self.keys = ( list(keys) if keys is not None else sorted(p.stem for p in self.sample_dirs[0].glob("*.npy")) )
[docs] def __len__(self) -> int: """Number of sample directories.""" return len(self.sample_dirs)
[docs] def __getitem__(self, index: int) -> dict[str, Any]: """Load the sample at ``index`` as a dict of tensors plus its key. Args: index: Sample position. Returns: A dict mapping each key to a tensor, plus a ``key`` metadata string (the sample directory name). """ sample_dir = self.sample_dirs[index] sample: dict[str, Any] = {"key": sample_dir.name} for name in self.keys: path = sample_dir / f"{name}.npy" if not path.exists(): continue array = np.load(path, mmap_mode="r" if self.mmap else None) # Copy out of the (read-only) memmap so the tensor owns writable memory. sample[name] = torch.from_numpy(np.array(array)) return sample