Source code for stable_datasets.timeseries.daily_and_sports_activities

"""Subject-disjoint windows from UCI's Daily and Sports Activities dataset."""

import re
import zipfile

import numpy as np

from stable_datasets.schema import (
    ClassLabel,
    DatasetInfo,
    DatasetSource,
    DownloadInfo,
    Features,
    Sequence,
    Value,
    Version,
)
from stable_datasets.utils import BaseDatasetBuilder


[docs] class DailyAndSportsActivities(BaseDatasetBuilder): """Load 5-second, 45-channel windows without mixing subjects across splits. The source provides no official train/test partition. This builder defines a reproducible cross-subject split: subjects 1-6 train, subjects 7-8 test. ``series`` is time-major (125, 45). Original 1-based subject and segment identifiers are retained; activity labels are zero-based. """ VERSION = Version("1.0.1") SOURCE = DatasetSource( homepage="https://archive.ics.uci.edu/dataset/256/daily+and+sports+activities", assets={ split: DownloadInfo( url="https://archive.ics.uci.edu/static/public/256/daily+and+sports+activities.zip", filename="daily_and_sports_activities.zip", ) for split in ("train", "test") }, citation="""@misc{daily_and_sports_activities_256, author = {Barshan, Billur and Altun, Kerem}, title = {Daily and Sports Activities}, year = {2010}, publisher = {UCI Machine Learning Repository}, doi = {10.24432/C5C59F}, url = {https://doi.org/10.24432/C5C59F} }""", license="CC BY 4.0", ) SAMPLE_RATE = 25 SEQUENCE_LENGTH = 125 CLASS_NAMES = ( "sitting", "standing", "lying_on_back", "lying_on_right_side", "ascending_stairs", "descending_stairs", "standing_in_elevator", "moving_in_elevator", "walking_in_parking_lot", "walking_on_flat_treadmill", "walking_on_inclined_treadmill", "running_on_treadmill", "stepper", "cross_trainer", "cycling_horizontal", "cycling_vertical", "rowing", "jumping", "basketball", ) CHANNEL_NAMES = tuple( f"{unit}_{sensor}_{axis}" for unit in ("torso", "right_arm", "left_arm", "right_leg", "left_leg") for sensor in ("acc", "gyro", "mag") for axis in ("x", "y", "z") ) SPLIT_SUBJECTS = {"train": frozenset(range(1, 7)), "test": frozenset((7, 8))} def _info(self): return DatasetInfo( description=( "19 activities performed by 8 subjects using five body-worn IMUs at 25 Hz. " "Each example is an unnormalized, time-major (125, 45) window. " "Builder-defined split: subjects 1-6 train and 7-8 test; no official split exists." ), features=Features( { "series": Sequence(Sequence(Value("float32"))), "label": ClassLabel(names=list(self.CLASS_NAMES)), "subject_id": Value("int32"), "segment_id": Value("int32"), } ), supervised_keys=("series", "label"), homepage=self.SOURCE.homepage, citation=self.SOURCE.citation, license=self.SOURCE.license, ) def _generate_examples(self, data_path, split): if split not in self.SPLIT_SUBJECTS: raise ValueError(f"Unknown split {split!r}; expected 'train' or 'test'.") subjects = self.SPLIT_SUBJECTS[split] pattern = re.compile(r"(?:^|/)a(\d{2})/p(\d+)/s(\d{2})\.txt$") with zipfile.ZipFile(data_path) as archive: members = [] seen = set() for name in archive.namelist(): match = pattern.search(name) if match is None: continue activity, subject, segment = map(int, match.groups()) if not (1 <= activity <= 19 and 1 <= subject <= 8 and 1 <= segment <= 60): raise ValueError(f"Invalid activity/subject/segment identifier in {name!r}.") key = (activity, subject, segment) if key in seen: raise ValueError(f"Duplicate activity/subject/segment window: {key}.") seen.add(key) if subject in subjects: members.append((key, name)) if not members: raise ValueError(f"No Daily and Sports Activities windows found for {split!r}.") for (activity, subject, segment), name in sorted(members): with archive.open(name) as stream: series = np.loadtxt(stream, delimiter=",", dtype=np.float32, ndmin=2) if series.shape != (self.SEQUENCE_LENGTH, len(self.CHANNEL_NAMES)): raise ValueError(f"Expected (125, 45) in {name!r}, got {series.shape}.") if not np.isfinite(series).all(): raise ValueError(f"Non-finite sensor values in {name!r}.") yield ( f"a{activity:02d}/p{subject}/s{segment:02d}", { "series": series, "label": activity - 1, "subject_id": subject, "segment_id": segment, }, )