Datasets and loading
A dataset presents a logical collection of physical samples through a common PyG interface. The reading strategy determines how much numerical data stays in memory; the returned sample fields and their physical meaning are shared by both strategies.
Reading ELFES HDF5
HDF5Dataset and InMemoryDataset use different HDF5 reading paths but return the same edge-free, single-sample torch_geometric.data.Data structure. The Data contains batchable sample tensors and compact basis references; complete basis sets and physical-data descriptions remain on the owning Dataset. Standard PyTorch DataLoaders invoke each Dataset's __getitems__() for one batch of indices: the on-disk Dataset reads all selected physical data directly into batch-contiguous storage without constructing physical Sample objects, while the in-memory Dataset separates views from its existing collated storage before ordinary PyG collation.
The input paths are ordered shards of one logical dataset. physical_data_selection=None reads all physical quantities, while an empty selection reads geometry and basis references without quantity values. The dataset exposes definitions for the selected quantities and complete basis sets. Field shapes and batch behavior are described in Samples and batches.
HDF5Dataset opens file handles within the process that reads them and provides close() for releasing them. InMemoryDataset.from_hdf5() loads the selected arrays into CPU tensor storage and does not retain HDF5 handles.
HDF5Dataset
HDF5Dataset(
paths: StrPath | Sequence[StrPath],
*,
physical_data_selection: Collection[str] | None = None,
)
Bases: Dataset[Data]
On-disk PyG view of one logical ELFES HDF5 dataset.
The input paths are ordered shards of the same logical dataset. Construction
reads their sample IDs and shared dataset definition, but numerical sample
data remains on disk. Integer and batched indexing read the requested
quantity-major arrays directly into continuous storage and return lightweight
edge-free Data views in the requested order without constructing physical
Sample objects.
The common returned Data structure is documented in
Samples and batches.
HDF5 handles are opened on first access within each process, so DataLoader
workers do not share live handles. Multi-worker DataLoaders should use the
forkserver multiprocessing context and persistent workers. Call close()
when the dataset is no longer needed.
Parameters:
-
paths(StrPath | Sequence[StrPath]) –One HDF5 path or an ordered sequence of shard paths.
-
physical_data_selection(Collection[str] | None, default:None) –Physical data to read, selected by globally unique name.
Noneselects all data; an empty collection selects none.
Attributes:
-
sample_ids–Sample IDs in logical dataset order.
-
basis_sets–Dataset-level basis sets keyed by role.
-
physical_data_descriptions–Definitions of physical data returned by the Dataset.
-
physical_data_names–Physical data returned by the Dataset.
-
atomic_basis_tables–Atomic bases indexed by the atomic-basis IDs stored in
Data.
close
close() -> None
Close HDF5 handles opened by the current process.
InMemoryDataset
InMemoryDataset(
collated_data: Data,
slice_dict: dict[str, Any],
*,
sample_ids: tuple[str, ...],
basis_sets: dict[str, BasisSet],
physical_data_descriptions: dict[str, PhysicalDataDescription],
physical_data_names: Collection[str],
)
Bases: Dataset[Data]
In-memory ELFES dataset backed by one collated PyG tensor store.
from_hdf5() bulk-reads the selected quantity-major arrays from all ordered
shards and converts them directly into a combined PyG Data plus nested
sample boundaries. It does not retain HDF5 handles or construct a physical
Sample for every row.
Integer indexing uses PyG separate() to return an edge-free sample whose
tensors view the combined storage. Atom indices remain sample-local until a
standard PyG DataLoader constructs a real batch; batched indexing applies the
same operation to the complete requested index sequence.
The common returned Data structure is documented in
Samples and batches.
Parameters:
-
collated_data(Data) –Combined PyG data for every sample.
-
slice_dict(dict[str, Any]) –Nested sample boundaries for fields in
collated_data. -
sample_ids(tuple[str, ...]) –Sample IDs in logical dataset order.
-
basis_sets(dict[str, BasisSet]) –Dataset-level basis sets keyed by role.
-
physical_data_descriptions(dict[str, PhysicalDataDescription]) –Definitions of physical data in
collated_data. -
physical_data_names(Collection[str]) –Physical data present in
collated_data.
Attributes:
-
sample_ids–Sample IDs in logical dataset order.
-
basis_sets–Dataset-level basis sets keyed by role.
-
physical_data_descriptions–Definitions of physical data returned by the Dataset.
-
physical_data_names–Physical data returned by the Dataset.
-
atomic_basis_tables–Atomic bases indexed by the atomic-basis IDs stored in
Data.
from_hdf5
classmethod
from_hdf5(
paths: StrPath | Sequence[StrPath],
*,
physical_data_selection: Collection[str] | None = None,
) -> Self
Read and convert complete HDF5 shards into memory.
Parameters:
-
paths(StrPath | Sequence[StrPath]) –One HDF5 path or an ordered sequence of shard paths.
-
physical_data_selection(Collection[str] | None, default:None) –Physical data to read, selected by globally unique name.
Noneselects all data; an empty collection selects none.
Converting physical samples
SampleToData provides the physical conversion for Sample objects that are already in memory. Because a physical Sample has no intrinsic dataset membership, this direct conversion does not add data.sample_id. Construct one converter from the basis sets shared by a logical dataset, then reuse it for every compatible sample:
from elfes.data import SampleToData
converter = SampleToData(basis_sets)
data = converter(sample)
SampleToData
dataclass
SampleToData(basis_sets: Mapping[str, BasisSet])
Convert one physical Sample into edge-free PyG data.
Geometry and electronic quantities become Torch tensors, while every atom receives its atomic-basis-table index and orbital count for each available basis role. Atom-pair indices remain local to the sample; a later PyG DataLoader performs the index increments required for a real batch.
Parameters:
-
basis_sets(Mapping[str, BasisSet]) –Dataset-level basis sets keyed by role. Every converted sample must use the same definitions.
Forming batches
create_data_loader() uses PyG collation. With with_connectivity=False, it returns edge-free batches. With with_connectivity=True, a cutoff is required and directed connectivity is built during CPU collation. Worker-based loading uses forkserver and persistent workers; the connectivity reference explains how to add edges after loading instead.
For an existing ELFES HDF5 file, a minimal edge-free loading path is:
from elfes.data import HDF5Dataset, create_data_loader
dataset = HDF5Dataset("samples.h5", physical_data_selection=["energy", "forces"])
loader = create_data_loader(dataset, batch_size=8, with_connectivity=False)
try:
for batch in loader:
positions = batch.pos
forces = batch.physical_data["forces"]
finally:
dataset.close()
Here energy and forces are names defined by the example dataset. Conversion retains ELFES physical units and conventions. Target normalization and other preparation steps are composed explicitly with the loader.
create_data_loader
create_data_loader(
dataset: Dataset[Data] | Sequence[Data],
*,
batch_size: int,
with_connectivity: bool,
cutoff: float | None = None,
cpu_threads: int | None = None,
shuffle: bool = False,
num_workers: int = 0,
pin_memory: bool = False,
prefetch_factor: int | None = None,
drop_last: bool = False,
) -> DataLoader[Batch]
Return a DataLoader that forms PyG batches with explicit connectivity.
Worker-based loading uses forkserver so on-disk datasets never inherit
open HDF5 handles, and keeps workers alive across iterations. When
with_connectivity is true, cutoff is required and connectivity is built
independently inside each worker using cpu_threads threads. Otherwise,
batches remain edge-free and cutoff and cpu_threads must not be set.