From dae39113ee7c707b0fc8e1c79542a22701b03166 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 16:50:54 +0800 Subject: [PATCH 01/20] add dsa dataset and task --- docs/api/tasks/pyhealth.tasks.ActivityClassification.rst | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 docs/api/tasks/pyhealth.tasks.ActivityClassification.rst diff --git a/docs/api/tasks/pyhealth.tasks.ActivityClassification.rst b/docs/api/tasks/pyhealth.tasks.ActivityClassification.rst new file mode 100644 index 000000000..83ded0401 --- /dev/null +++ b/docs/api/tasks/pyhealth.tasks.ActivityClassification.rst @@ -0,0 +1,7 @@ +pyhealth.tasks.ActivityClassification +=================================== + +.. autoclass:: pyhealth.tasks.ActivityClassification + :members: + :undoc-members: + :show-inheritance: From 4a0c15bb048439aa213cf72c4404c5c9e827353a Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 17:01:09 +0800 Subject: [PATCH 02/20] add remaining changes --- docs/api/datasets.rst | 1 + .../datasets/pyhealth.datasets.DSADataset.rst | 10 ++ docs/api/tasks.rst | 1 + pyhealth/datasets/__init__.py | 1 + pyhealth/datasets/configs/dsa.yaml | 56 +++++++ pyhealth/datasets/dsa.py | 156 ++++++++++++++++++ pyhealth/tasks/__init__.py | 1 + pyhealth/tasks/activity_classification.py | 107 ++++++++++++ test-resources/dsa/dsa-pyhealth.csv | 21 +++ tests/core/test_dsa.py | 122 ++++++++++++++ 10 files changed, 476 insertions(+) create mode 100644 docs/api/datasets/pyhealth.datasets.DSADataset.rst create mode 100644 pyhealth/datasets/configs/dsa.yaml create mode 100644 pyhealth/datasets/dsa.py create mode 100644 pyhealth/tasks/activity_classification.py create mode 100644 test-resources/dsa/dsa-pyhealth.csv create mode 100755 tests/core/test_dsa.py diff --git a/docs/api/datasets.rst b/docs/api/datasets.rst index b02439d26..83858db13 100644 --- a/docs/api/datasets.rst +++ b/docs/api/datasets.rst @@ -243,5 +243,6 @@ Available Datasets datasets/pyhealth.datasets.ClinVarDataset datasets/pyhealth.datasets.COSMICDataset datasets/pyhealth.datasets.TCGAPRADDataset + datasets/pyhealth.datasets.DSADataset datasets/pyhealth.datasets.splitter datasets/pyhealth.datasets.utils diff --git a/docs/api/datasets/pyhealth.datasets.DSADataset.rst b/docs/api/datasets/pyhealth.datasets.DSADataset.rst new file mode 100644 index 000000000..84e909b07 --- /dev/null +++ b/docs/api/datasets/pyhealth.datasets.DSADataset.rst @@ -0,0 +1,10 @@ +pyhealth.datasets.DSADataset +=============================== + +The Daily and Sports Activities (DSA) dataset contains motion sensor data of +daily and sports activities. For more information see `Daily and Sports Activities `_. This dataset was contributed as part of the Prostate-VarBench benchmarking work (`arXiv:2511.09576 `_). + +.. autoclass:: pyhealth.datasets.DSADataset + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/api/tasks.rst b/docs/api/tasks.rst index d85d04bc3..6b4629f2a 100644 --- a/docs/api/tasks.rst +++ b/docs/api/tasks.rst @@ -231,3 +231,4 @@ Available Tasks Mutation Pathogenicity (COSMIC) Cancer Survival Prediction (TCGA) Cancer Mutation Burden (TCGA) + Activity Classification (DSA) diff --git a/pyhealth/datasets/__init__.py b/pyhealth/datasets/__init__.py index 3edbe06f7..6da686198 100644 --- a/pyhealth/datasets/__init__.py +++ b/pyhealth/datasets/__init__.py @@ -53,6 +53,7 @@ def __init__(self, *args, **kwargs): from .cosmic import COSMICDataset from .covid19_cxr import COVID19CXRDataset from .dreamt import DREAMTDataset +from .dsa import DSADataset from .ehrshot import EHRShotDataset from .eicu import eICUDataset from .isruc import ISRUCDataset diff --git a/pyhealth/datasets/configs/dsa.yaml b/pyhealth/datasets/configs/dsa.yaml new file mode 100644 index 000000000..bfe659538 --- /dev/null +++ b/pyhealth/datasets/configs/dsa.yaml @@ -0,0 +1,56 @@ +version: "1.0" +tables: + activities: + file_path: "dsa-pyhealth.csv" + patient_id: "patient" + timestamp: null + attributes: + - "activity" + - "patient" + - "segment" + - "sample_id" + - "T_xacc" + - "RA_xacc" + - "LA_xacc" + - "RL_xacc" + - "LL_xacc" + - "T_xgyro" + - "RA_xgyro" + - "LA_xgyro" + - "RL_xgyro" + - "LL_xgyro" + - "T_xmag" + - "RA_xmag" + - "LA_xmag" + - "RL_xmag" + - "LL_xmag" + - "T_yacc" + - "RA_yacc" + - "LA_yacc" + - "RL_yacc" + - "LL_yacc" + - "T_ygyro" + - "RA_ygyro" + - "LA_ygyro" + - "RL_ygyro" + - "LL_ygyro" + - "T_ymag" + - "RA_ymag" + - "LA_ymag" + - "RL_ymag" + - "LL_ymag" + - "T_zacc" + - "RA_zacc" + - "LA_zacc" + - "RL_zacc" + - "LL_zacc" + - "T_zgyro" + - "RA_zgyro" + - "LA_zgyro" + - "RL_zgyro" + - "LL_zgyro" + - "T_zmag" + - "RA_zmag" + - "LA_zmag" + - "RL_zmag" + - "LL_zmag" diff --git a/pyhealth/datasets/dsa.py b/pyhealth/datasets/dsa.py new file mode 100644 index 000000000..944e5327b --- /dev/null +++ b/pyhealth/datasets/dsa.py @@ -0,0 +1,156 @@ +"""Daily and Sports Activities dataset for PyHealth. + +This module provides the DSADataset class for loading and processing +DSA (Daily and Sports Activities) data for machine learning tasks. +""" + +import logging +import os +from pathlib import Path +from typing import List, Optional + +import pandas as pd + +from .base_dataset import BaseDataset + +logger = logging.getLogger(__name__) + + +class DSADataset(BaseDataset): + """Daily and Sports Activities dataset for motion sensor data analysis. + + Daily and Sports Activities (DSA) dataset contains motion sensor data of 19 + daily and sports activities each performed by 8 subjects for 5 minutes in + their own style. The 5-min period is divided into 5-sec segments so that 60 + segments are obtained for each activity and each subject. + + Five sensor units are placed on the torso, arms, and legs to capture + time-series data. Sensors are configured to capture data at 25 Hz frequency. + + In each text file, there are 45 columns (5 units * 9 sensors) and 125 rows + (5 seconds * 25 Hz). Each row represents sensor dimensions captured at a p + articular sampling instant from all sensors for one activity, one patient. + + The raw dataset structure looks like this: + - data + - a01: activity 01 + - p1: patient 1 + - s01.txt: segment 01 + - s02.txt: segment 02 + - ... ... + - s60.txt: segment 60 + - p2: patient 2 + - ... ... + - p8 + - a02: activity 02 + - ... ... + - a19 + + This dataset class loads raw data files and reformats into a single CSV file + with columns activity, patient, segment, sample_id, and 45 sensor columns. + + Dataset is available at: + https://archive.ics.uci.edu/dataset/256/daily+and+sports+activities + + Note: + This dataset is licensed under a Creative Commons Attribution 4.0 + International (CC BY 4.0) license. + + Args: + root: Root directory of the raw data containing the DSA dataset files. + dataset_name: Optional name of the dataset. Defaults to "dsa". + config_path: Optional path to the configuration file. If not provided, + uses the default config in the configs directory. + + Attributes: + root: Root directory of the raw data. + dataset_name: Name of the dataset. + config_path: Path to the configuration file. + + Examples: + >>> from pyhealth.datasets import DSADataset + >>> dataset = DSADataset(root="/path/to/dsa") + >>> dataset.stats() + >>> samples = dataset.set_task() + >>> print(samples[0]) + """ + + def __init__( + self, + root: str, + dataset_name: Optional[str] = None, + config_path: Optional[str] = None, + **kwargs, + ) -> None: + if config_path is None: + logger.info("No config path provided, using default config") + config_path = Path(__file__).parent / "configs" / "dsa.yaml" + + # Prepare standardized CSV if not exists + pyhealth_csv = os.path.join(root, "dsa-pyhealth.csv") + if not os.path.exists(pyhealth_csv): + logger.info("Preparing DSA data...") + self.prepare_data(root) + + super().__init__( + root=root, + tables=["activities"], + dataset_name=dataset_name or "dsa", + config_path=config_path, + **kwargs, + ) + + @staticmethod + def prepare_data(root: str) -> None: + """Prepare data for DSA dataset. + + Converts raw DSA text files to standardized CSV format. + + Args: + root: Root directory containing the DSA files. + """ + + data = [] + + columns = [ + f"{x}_{z}{y}" + for z in ["x", "y", "z"] + for y in ["acc", "gyro", "mag"] + for x in ["T", "RA", "LA", "RL", "LL"] + ] + + logger.info(f"Loading raw sensors data ...") + + for a in range(1, 20): + for p in range(1, 9): + for s in range(1, 61): + df = pd.read_csv( + root / f"a{a:02d}" / f"p{p}" / f"s{s:02d}.txt", + header=None, + ) + df.columns = columns + df = df.assign( + activity=a, + patient=p, + segment=s, + ) + df["sample_id"] = range(1, 126) + data.append(df) + + df_out = pd.concat(data) + + # Save to standardized CSV + output_path = os.path.join(root, "dsa-pyhealth.csv") + df_out.to_csv(output_path, index=False) + logger.info(f"Saved {len(df_out)} sensors to {output_path}") + + @property + def default_task(self): + """Returns the default task for this dataset. + + Returns: + ActivityClassification: The default classification task. + """ + from pyhealth.tasks import ActivityClassification + + return ActivityClassification() diff --git a/pyhealth/tasks/__init__.py b/pyhealth/tasks/__init__.py index 2f4294a19..62a1f53db 100644 --- a/pyhealth/tasks/__init__.py +++ b/pyhealth/tasks/__init__.py @@ -68,3 +68,4 @@ VariantClassificationClinVar, ) from .patient_linkage_mimic3 import PatientLinkageMIMIC3Task +from .activity_classification import ActivityClassification \ No newline at end of file diff --git a/pyhealth/tasks/activity_classification.py b/pyhealth/tasks/activity_classification.py new file mode 100644 index 000000000..5236f9565 --- /dev/null +++ b/pyhealth/tasks/activity_classification.py @@ -0,0 +1,107 @@ +"""Activity classification for PyHealth. + +This module provides a task for classifying daily and sports activity using +motion sensor data from Daily and Sports Activities (DSA) dataset. +""" + +from typing import Any, Dict, List, Optional + +from .base_task import BaseTask + + +class ActivityClassification(BaseTask): + """Task for classifying activity using motion sensor data. + + This task classifies which activity a patient is performing over a time + period from multi-sensor time-series data. + + Attributes: + task_name (str): The name of the task. + input_schema (Dict[str, str]): The input schema specifying required inputs. + output_schema (Dict[str, str]): The output schema specifying outputs. + + Note: + Each time-series is sampled over 5 seconds with 25 Hz frequency. + + Examples: + >>> from pyhealth.datasets import DSADataset + >>> from pyhealth.tasks import ActivityClassification + >>> dataset = DSADataset(root="/path/to/dsa") + >>> task = ActivityClassification() + >>> samples = dataset.set_task(task) + """ + + task_name: str = "ActivityClassification" + input_schema: Dict[str, str] = { + "features": "sequence", + } + output_schema: Dict[str, str] = { + "label": "text", + } + + def _extract_features(self, activity: Any) -> List[float]: + """Extract features from an activity event. + + Args: + activity: An activity event object. + + Returns: + List of feature values. + """ + features: List[float] = [] + + columns = [ + f"{x}_{z}{y}" + for z in ["x", "y", "z"] + for y in ["acc", "gyro", "mag"] + for x in ["T", "RA", "LA", "RL", "LL"] + ] + for c in columns: + x = getattr(activity, c, None) + features.append(x) + + return features + + def _extract_label(self, activity: Any) -> Optional[int]: + """Extract label for an activity event. + + Args: + activity: An activity event object. + + Returns: + 1 - 19 to represent activity, None if value is invalid or unknown. + """ + if activity is None: + return None + + label = getattr(activity, "activity", None) + + return label + + def __call__(self, patient: Any) -> List[Dict[str, Any]]: + """Process daily and sports activities data for activity classification. + + Args: + patient: A patient object containing activities data. + + Returns: + List[Dict[str, Any]]: A list containing dictionaries with + patient features and activity label. + + Note: + Returns empty list for patients with: + - No activities + """ + activities = patient.get_events(event_type="activities") + + if len(activities) == 0: + return [] + + return [ + { + "patient_id": patient.patient_id, + "features": self._extract_features(activity), + "label": self._extract_label(activity), + } + for activity in activities + ] diff --git a/test-resources/dsa/dsa-pyhealth.csv b/test-resources/dsa/dsa-pyhealth.csv new file mode 100644 index 000000000..1a57f5713 --- /dev/null +++ b/test-resources/dsa/dsa-pyhealth.csv @@ -0,0 +1,21 @@ +T_xacc,RA_xacc,LA_xacc,RL_xacc,LL_xacc,T_xgyro,RA_xgyro,LA_xgyro,RL_xgyro,LL_xgyro,T_xmag,RA_xmag,LA_xmag,RL_xmag,LL_xmag,T_yacc,RA_yacc,LA_yacc,RL_yacc,LL_yacc,T_ygyro,RA_ygyro,LA_ygyro,RL_ygyro,LL_ygyro,T_ymag,RA_ymag,LA_ymag,RL_ymag,LL_ymag,T_zacc,RA_zacc,LA_zacc,RL_zacc,LL_zacc,T_zgyro,RA_zgyro,LA_zgyro,RL_zgyro,LL_zgyro,T_zmag,RA_zmag,LA_zmag,RL_zmag,LL_zmag,activity,patient,segment,sample_id +8.3131,-0.89161,3.4829,-0.31429,0.039033,0.27511,-0.91084,0.41779,-0.071697,-0.84114,5.4726,7.9802,-0.33354,-0.29744,0.18019,-0.42968,-0.2345,-0.83518,-1.2729,-6.3533,5.826,-2.6156,1.1285,0.7457,-0.14533,0.90085,-0.30413,-0.42687,0.55892,1.2345,0.058055,-0.15068,1.0072,0.43424,-0.67505,0.20034,-9.6503,-10.189,-1.2675,-0.20789,-0.34648,0.27405,0.60667,0.48892,-0.34716,16,1,60,52 +11.84,0.059295,1.5869,0.71073,0.58851,0.13427,-0.93463,0.16111,0.38241,14.73,1.1219,1.185,1.1097,1.2687,-2.3585,-0.93797,0.27877,0.15077,14.253,-2.6582,1.6044,-0.24274,0.66728,1.8438,-0.93667,-0.088245,0.31095,-12.49,5.7882,2.1154,-1.4661,-0.57424,-0.051077,0.79858,0.45994,0.35114,-10.941,-0.74024,-0.40234,0.63481,0.060647,-0.15809,0.826,-0.35061,-0.38515,18,3,32,59 +10.172,2.4585,3.5307,-0.54464,-0.33529,-0.18707,-0.89917,-0.15392,0.1631,10.246,3.3153,0.13724,-0.49348,0.23491,-0.59136,-0.94365,0.061012,0.047113,11.182,0.10717,3.9649,2.1207,-0.08562,0.86037,-0.90022,-0.18463,0.017512,-12.59,-3.0806,2.6163,0.41921,0.14977,1.1836,0.6682,0.58396,-0.2919,-11.683,0.55632,-0.36202,0.36462,0.076038,1.0466,0.84949,-0.32773,0.17506,9,1,35,29 +9.416,-2.1977,4.693,0.95558,0.21684,-0.41964,-0.85492,0.53011,-0.015934,-0.56958,4.3747,9.0146,0.56839,0.41764,-0.078376,-0.50716,-0.13101,-0.88553,0.57454,-3.4865,9.3634,0.22778,-0.10896,-0.23502,-0.38079,0.6922,-0.58164,-8.4059,6.4897,0.44679,-0.1779,-0.005699,-2.4593,0.47813,-0.53446,0.30772,-8.591,-9.9117,-0.53818,0.30804,-0.16206,-2.2108,0.53678,0.55181,-0.43545,16,1,9,58 +8.0865,-0.2408,3.6028,0.15649,-0.32136,-0.048024,-0.62068,0.1848,-0.6332,8.4594,1.5216,0.67405,0.44756,0.90507,-1.7612,-0.35136,0.022328,-0.95171,8.6742,-2.6619,2.9889,-0.29812,-0.47963,-2.1346,-0.5662,0.76524,0.40703,-6.3341,4.0496,-0.22198,1.6531,-0.24082,0.005633,0.35098,-0.72703,0.35797,-9.9342,-3.2876,-1.3094,0.2463,0.3072,1.0892,1.0749,0.34908,-0.1557,10,6,42,17 +9.4769,-0.35637,1.3081,-0.023822,-0.47482,0.010213,-0.7806,-0.03383,-0.58585,3.2565,2.2587,8.761,0.12159,-0.39719,0.21735,0.23885,-0.24844,-0.88524,2.5931,-2.3315,8.544,0.11183,-0.28157,-0.29491,0.18529,0.018937,-0.92893,-0.26951,9.346,-1.1284,-0.28026,-0.10108,0.566,-0.42312,-0.8644,-0.059146,0.43549,-8.0116,-4.8812,-0.19694,0.57888,-0.42021,-0.49822,0.69599,0.46264,17,3,14,13 +10.413,-3.5139,5.7962,0.17605,0.1922,-0.073935,-0.74572,0.30642,-0.63589,3.7203,9.048,0.76887,0.2363,-0.55176,-0.32467,-0.41422,-0.56141,-0.48936,3.5781,-6.4982,7.7381,-0.069666,0.50068,-0.56215,0.015839,0.71056,-0.93329,-12.53,2.1052,-1.1003,0.643,-0.10938,-1.1014,0.84059,-0.36595,0.15484,-11.763,-5.6095,-3.8126,-1.3106,0.28608,0.98938,0.79251,0.67014,-0.042973,10,7,34,56 +9.1361,1.4385,4.4644,0.54445,0.40864,-0.3545,-0.91836,0.26298,-0.13111,2.3694,7.9979,4.8811,0.34208,0.21765,-0.30616,-0.76618,-0.4944,-0.52338,1.5973,-4.5506,8.5491,0.074027,-0.10415,-0.047873,-0.67156,0.66497,-0.56205,-9.5713,10.865,-0.64796,-0.42244,0.03298,-0.32233,0.6901,-0.15918,0.20492,-2.2445,-0.73998,-3.0723,0.73919,0.40397,-1.094,0.53545,0.69486,-0.081579,16,4,50,117 +10.004,2.5936,1.2038,-1.1109,-0.070371,-0.14837,-0.93787,-0.39985,0.064385,19.398,-1.9689,6.2024,3.1224,-0.34522,2.102,-0.79838,-0.54207,-0.13436,12.055,-1.4415,5.0604,0.76672,2.3059,2.2045,-0.88471,-0.32169,-0.36848,-9.3479,-0.15021,-0.8001,-0.14906,-0.16136,-0.98636,0.96718,-0.058197,-0.4121,-9.8898,-1.66,-2.311,0.70039,-0.007266,-0.28159,0.9171,-0.054443,0.38715,19,2,52,119 +9.5202,-0.097624,3.6071,-0.23136,0.030941,-0.32654,-0.89424,-0.04648,0.21146,9.9124,3.1205,2.7562,0.074591,-0.46495,0.22428,-0.83521,0.3164,0.21406,11.779,-1.8761,3.8031,-2.2067,0.054235,-0.46023,-0.88232,-0.076329,0.29956,-10.858,1.9206,-1.292,0.65118,-0.21272,-0.51304,0.63471,0.68898,-0.002028,-8.2238,-2.984,-3.5087,0.33753,0.99681,-0.027226,0.90993,-0.17071,0.00541,9,3,36,111 +7.1875,-1.4288,6.7869,0.016676,0.38276,0.007781,-0.34376,-0.00507,-0.90885,-2.2656,9.4839,2.4405,0.72472,0.045511,-1.1975,0.66073,-0.49822,-0.49374,-0.95824,-3.936,7.7712,-0.25698,-0.10244,0.72657,0.47468,0.067533,-0.83869,-2.2133,11.659,4.208,0.045985,0.59248,-0.30771,-0.23641,-0.78206,-0.51153,-4.2791,-9.8212,-0.55694,-0.37198,-0.0903,0.78076,-0.039183,0.97034,0.037953,17,8,8,84 +8.9235,0.43648,2.7027,-0.74201,-0.90844,-0.26481,-0.65358,-0.074521,-0.69317,8.8169,4.1858,6.0226,-1.6219,0.049449,-0.35822,0.12168,-0.37139,-0.78798,7.3198,-6.4745,5.5421,2.1826,0.41977,0.38122,-0.17416,0.48463,-0.66198,-8.9732,0.36566,0.027289,-0.30103,-0.20919,1.3483,0.81889,-0.33328,-0.39401,-7.7025,-2.3132,0.053663,0.53881,0.26991,1.0475,0.7397,0.56584,0.36006,13,1,30,78 +9.3581,0.92832,2.168,-0.053244,0.07298,-0.1165,-0.55718,-0.22505,0.19349,2.6188,0.78267,9.1984,0.066114,0.098715,-0.049549,-0.26382,-0.17587,-0.24441,1.8387,-0.74629,9.3833,0.067962,-0.010683,-0.052397,-0.64217,-0.14746,-0.49378,-3.7491,10.749,-1.3344,-0.83626,-0.12522,0.56644,0.43407,-0.51989,-0.097536,4.6338,-4.5922,0.46994,-0.23997,-0.011066,0.5567,0.1015,0.55677,0.24796,15,5,33,16 +7.6427,-1.6273,4.5589,-0.2402,-0.52003,-0.036924,-0.6604,-0.044255,0.00782,-0.14544,5.6893,7.9471,-0.18368,-0.094774,0.031512,-0.19736,-0.40985,-0.29236,-0.19959,-2.4768,9.0227,0.06562,-0.054854,-0.093852,-0.49338,-0.044472,-0.61961,6.4375,1.6976,0.74124,0.88016,-0.26015,-0.84731,0.1132,-0.65734,-0.14501,-2.0735,-12.592,-1.4314,-0.022301,0.29235,-0.84524,0.41643,0.37373,0.18079,15,6,26,40 +29.051,-3.98,-1.0241,-0.68134,0.8976,-0.19221,-0.94708,0.13103,-0.47876,4.3187,10.425,-0.44361,-0.35158,-0.041183,0.1427,-0.65283,-0.74088,-0.20948,6.2111,-7.5305,6.1445,-0.64165,-1.2791,-0.51271,-0.40626,0.5801,-0.96043,-24.381,-3.7933,-4.5389,-0.67705,0.083068,-2.3597,0.72578,-0.57876,0.041516,-20.012,7.7482,1.4062,0.75187,0.26712,-4.1026,0.88902,0.54831,0.18057,12,7,36,109 +5.2214,0.63878,4.4785,0.31555,-0.22662,-0.17395,-0.92408,0.021993,-0.081787,7.7444,2.9478,3.5724,0.079947,-0.90602,0.093311,-0.88031,0.18227,0.15357,8.6533,-1.9719,2.2627,0.56983,1.1164,2.3987,-0.90138,-0.064,-0.12198,-9.1805,-0.45633,-1.6623,1.2449,0.41394,-1.7511,0.74713,0.5394,0.10978,-8.8001,4.051,1.2805,1.7726,1.3693,-2.1018,0.83104,-0.38573,-0.059277,9,5,47,112 +-3.344,0.092144,9.3024,0.000882,0.015133,-0.011051,0.16791,-0.44661,-0.79888,-6.9891,0.89119,6.8429,0.00646,-0.004929,-0.002394,0.90553,-0.17152,-0.22212,-7.4414,1.3746,6.3046,-0.000863,-0.000727,-0.010735,0.31986,-0.087818,-0.86203,0.11418,7.7206,-5.9672,-0.006168,0.010131,-0.018441,-0.002306,-0.95486,0.11589,-0.075708,-6.3911,-7.364,-0.008523,-0.002583,0.005349,0.18579,0.18989,0.9558,3,3,17,58 +8.0246,-1.0831,2.7374,-0.025617,0.13309,0.32138,-0.63721,0.14383,-0.60481,-0.11918,7.9492,5.0985,0.088464,-0.38971,0.76724,0.034311,-0.18275,-0.62023,-0.13409,-6.5663,7.0712,0.2924,-0.38506,-0.36853,0.42253,0.83806,-0.64737,-12.131,1.1594,-1.7115,-0.71023,1.1461,2.7074,0.63972,-0.47338,0.5241,-7.4004,-1.8209,-3.8708,-0.83243,0.041936,1.8923,0.84989,0.68954,-0.19125,11,6,17,58 +9.1667,-1.575,3.1247,-0.007485,0.031151,0.004787,-0.55078,-0.33451,-0.51785,-1.0507,8.4647,4.8334,0.001327,-0.007116,-0.005842,0.4023,-0.64517,0.09924,1.1523,-6.2318,7.56,-0.001717,0.002918,-0.012575,0.29757,0.011825,-0.93756,-3.3308,9.1646,-0.91419,-0.002092,0.003455,-0.003042,-0.32326,-0.672,-0.4186,-3.5826,-9.154,-0.2246,-0.001867,0.001725,-0.008039,-0.021634,0.44214,0.56964,1,4,49,64 +7.9205,2.3204,3.8242,0.55641,0.027897,0.12651,-0.8821,-0.12107,0.21219,7.4176,2.3879,2.3572,0.9271,0.064412,0.45067,-0.92643,-0.093245,0.019932,7.2369,-3.6015,3.0001,-0.20576,-0.35735,-0.46375,-0.90387,-0.10805,0.021407,-8.3388,1.7509,-1.324,-0.54207,0.63262,0.78172,0.85166,0.34005,-0.02379,-9.7675,-0.22432,-1.6329,-1.1755,0.05182,1.0439,0.67785,-0.59859,0.1009,9,1,54,90 diff --git a/tests/core/test_dsa.py b/tests/core/test_dsa.py new file mode 100755 index 000000000..bea1dbe2c --- /dev/null +++ b/tests/core/test_dsa.py @@ -0,0 +1,122 @@ +""" +Unit tests for the DSADataset and ActivityClassification classes. + +Author: + Ran You +""" +# CR rayou: delete this +import torch +if not hasattr(torch, 'uint16'): + torch.uint16 = torch.int16 # This tricks litdata into thinking uint16 exists + + +import unittest +from pathlib import Path + +from pyhealth.datasets import DSADataset +from pyhealth.tasks import ActivityClassification + + +class TestDSADataset(unittest.TestCase): + """Test cases for DSADataset.""" + + @classmethod + def setUpClass(cls): + """Set up test resources path.""" + cls.test_resources = Path(__file__).parent.parent.parent / "test-resources" / "dsa" + + def test_dataset_initialization(self): + """Test that the dataset initializes correctly.""" + dataset = DSADataset(root=str(self.test_resources)) + self.assertIsNotNone(dataset) + self.assertEqual(dataset.dataset_name, "dsa") + + def test_stats(self): + """Test that stats() runs without error.""" + dataset = DSADataset(root=str(self.test_resources)) + dataset.stats() + + def test_num_patients(self): + """Test the number of unique patient IDs.""" + dataset = DSADataset(root=str(self.test_resources)) + # Should have 8 unique patient IDs (1-8) + self.assertEqual(len(dataset.unique_patient_ids), 8) + + def test_get_patient(self): + """Test retrieving a patient.""" + dataset = DSADataset(root=str(self.test_resources)) + patient = dataset.get_patient("5") + self.assertIsNotNone(patient) + self.assertEqual(patient.patient_id, "5") + + def test_get_events(self): + """Test getting motion sensor data from a patient.""" + dataset = DSADataset(root=str(self.test_resources)) + patient = dataset.get_patient("3") + events = patient.get_events(event_type="activities") + # patient 5 has 2 samples in test data + self.assertEqual(len(events), 4) + + def test_event_attributes(self): + """Test that event attributes are correctly loaded.""" + dataset = DSADataset(root=str(self.test_resources)) + patient = dataset.get_patient("5") + events = patient.get_events(event_type="activities") + event = events[0] + + # Check that attributes exist + self.assertIn("activity", event) + self.assertIn("segment", event) + self.assertIn("sample_id", event) + self.assertIn("LL_ygyro", event) + + def test_default_task(self): + """Test that the default task is ActivityClassification.""" + dataset = DSADataset(root=str(self.test_resources)) + self.assertIsInstance(dataset.default_task, ActivityClassification) + + def test_set_task(self): + """Test setting and running the activity classification task.""" + dataset = DSADataset(root=str(self.test_resources)) + task = ActivityClassification() + samples = dataset.set_task(task) + + # Should have samples for activities. + self.assertGreater(len(samples), 0) + + def test_task_output_format(self): + """Test that task output has the correct format.""" + dataset = DSADataset(root=str(self.test_resources)) + task = ActivityClassification() + samples = dataset.set_task(task) + + if len(samples) > 0: + sample = samples[0] + self.assertIn("patient_id", sample) + self.assertIn("features", sample) + self.assertIn("label", sample) + + +class TestActivityClassification(unittest.TestCase): + """Test cases for ActivityClassification task.""" + + def test_task_attributes(self): + """Test task class attributes.""" + task = ActivityClassification() + self.assertEqual(task.task_name, "ActivityClassification") + self.assertIn("features", task.input_schema) + self.assertIn("label", task.output_schema) + + def test_input_schema(self): + """Test input schema definition.""" + task = ActivityClassification() + self.assertEqual(task.input_schema["features"], "sequence") + + def test_output_schema(self): + """Test output schema definition.""" + task = ActivityClassification() + self.assertEqual(task.output_schema["label"], "text") + + +if __name__ == "__main__": + unittest.main() From c32e182fe288f541b26d3eb005abe30260f2fb2b Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 18:01:54 +0800 Subject: [PATCH 03/20] support downloading dataset --- pyhealth/datasets/dsa.py | 67 +++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/pyhealth/datasets/dsa.py b/pyhealth/datasets/dsa.py index 944e5327b..1d85033b8 100644 --- a/pyhealth/datasets/dsa.py +++ b/pyhealth/datasets/dsa.py @@ -32,19 +32,20 @@ class DSADataset(BaseDataset): articular sampling instant from all sensors for one activity, one patient. The raw dataset structure looks like this: - - data - - a01: activity 01 - - p1: patient 1 - - s01.txt: segment 01 - - s02.txt: segment 02 + - + - data + - a01: activity 01 + - p1: patient 1 + - s01.txt: segment 01 + - s02.txt: segment 02 + - ... ... + - s60.txt: segment 60 + - p2: patient 2 - ... ... - - s60.txt: segment 60 - - p2: patient 2 + - p8 + - a02: activity 02 - ... ... - - p8 - - a02: activity 02 - - ... ... - - a19 + - a19 This dataset class loads raw data files and reformats into a single CSV file with columns activity, patient, segment, sample_id, and 45 sensor columns. @@ -80,15 +81,29 @@ def __init__( root: str, dataset_name: Optional[str] = None, config_path: Optional[str] = None, + download : bool = False, **kwargs, ) -> None: if config_path is None: logger.info("No config path provided, using default config") config_path = Path(__file__).parent / "configs" / "dsa.yaml" + if download: + self.download_dataset(root=root) + # Prepare standardized CSV if not exists pyhealth_csv = os.path.join(root, "dsa-pyhealth.csv") if not os.path.exists(pyhealth_csv): + if len(os.listdir(root)) != 19: + logger.info( + f""" + The contexts in {root} are unexpected. You root directory is likely wrong. + You can download the dataset manually from https://archive.ics.uci.edu/dataset/256/daily+and+sports+activities + or directly set download=True. + """ + ) + raise + logger.info("Preparing DSA data...") self.prepare_data(root) @@ -100,6 +115,34 @@ def __init__( **kwargs, ) + @staticmethod + def download_dataset(root : str = None) -> None: + """Download DSA dataset and extract files. + + Args: + root: directory to extract downloaded files, default to ./daily-and-sports-activities + """ + import urllib.request + import zipfile + import os + + url = "https://archive.ics.uci.edu/static/public/256/daily+and+sports+activities.zip" + zip_path = "./daily+and+sports+activities.zip" + if root is None: + root = "./daily-and-sports-activities" + + logger.info(f"Downloading {url}...") + urllib.request.urlretrieve(url, zip_path) + + logger.info("Extracting files...") + with zipfile.ZipFile(zip_path, 'r') as zip_ref: + zip_ref.extractall(root) + + os.remove(zip_path) + + logger.info(f"Done! Files extracted to: {root}") + return + @staticmethod def prepare_data(root: str) -> None: """Prepare data for DSA dataset. @@ -125,7 +168,7 @@ def prepare_data(root: str) -> None: for p in range(1, 9): for s in range(1, 61): df = pd.read_csv( - root / f"a{a:02d}" / f"p{p}" / f"s{s:02d}.txt", + root / "data" / f"a{a:02d}" / f"p{p}" / f"s{s:02d}.txt", header=None, ) df.columns = columns From 226f5e8f3500cd63e6343171e0d0eb672eb675ab Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 18:03:38 +0800 Subject: [PATCH 04/20] fix path type --- pyhealth/datasets/dsa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyhealth/datasets/dsa.py b/pyhealth/datasets/dsa.py index 1d85033b8..1cd43b63d 100644 --- a/pyhealth/datasets/dsa.py +++ b/pyhealth/datasets/dsa.py @@ -168,7 +168,7 @@ def prepare_data(root: str) -> None: for p in range(1, 9): for s in range(1, 61): df = pd.read_csv( - root / "data" / f"a{a:02d}" / f"p{p}" / f"s{s:02d}.txt", + Path(root) / "data" / f"a{a:02d}" / f"p{p}" / f"s{s:02d}.txt", header=None, ) df.columns = columns From 6dd43b1b3c9c0933c3663220de893d70db57b537 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 18:12:15 +0800 Subject: [PATCH 05/20] bug fix for directory contents check --- pyhealth/datasets/dsa.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyhealth/datasets/dsa.py b/pyhealth/datasets/dsa.py index 1cd43b63d..b01008309 100644 --- a/pyhealth/datasets/dsa.py +++ b/pyhealth/datasets/dsa.py @@ -94,12 +94,12 @@ def __init__( # Prepare standardized CSV if not exists pyhealth_csv = os.path.join(root, "dsa-pyhealth.csv") if not os.path.exists(pyhealth_csv): - if len(os.listdir(root)) != 19: + if not os.path.exists(Path(root) / "data"): logger.info( f""" - The contexts in {root} are unexpected. You root directory is likely wrong. + There's no data directory in {root}. You root directory is likely wrong. You can download the dataset manually from https://archive.ics.uci.edu/dataset/256/daily+and+sports+activities - or directly set download=True. + then extract the downloaded zip file to , or directly set download=True. """ ) raise From 740fb467863c66e515db13bd2b0a1176d3f56fe1 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 20:21:20 +0800 Subject: [PATCH 06/20] reformat data into time-series --- pyhealth/datasets/configs/dsa.yaml | 47 +------------ pyhealth/datasets/dsa.py | 27 ++++--- pyhealth/tasks/activity_classification.py | 86 +++++++++-------------- test-resources/dsa/dsa-pyhealth.csv | 42 +++++------ tests/core/test_dsa.py | 25 +++++-- 5 files changed, 86 insertions(+), 141 deletions(-) diff --git a/pyhealth/datasets/configs/dsa.yaml b/pyhealth/datasets/configs/dsa.yaml index bfe659538..e264aa6af 100644 --- a/pyhealth/datasets/configs/dsa.yaml +++ b/pyhealth/datasets/configs/dsa.yaml @@ -8,49 +8,4 @@ tables: - "activity" - "patient" - "segment" - - "sample_id" - - "T_xacc" - - "RA_xacc" - - "LA_xacc" - - "RL_xacc" - - "LL_xacc" - - "T_xgyro" - - "RA_xgyro" - - "LA_xgyro" - - "RL_xgyro" - - "LL_xgyro" - - "T_xmag" - - "RA_xmag" - - "LA_xmag" - - "RL_xmag" - - "LL_xmag" - - "T_yacc" - - "RA_yacc" - - "LA_yacc" - - "RL_yacc" - - "LL_yacc" - - "T_ygyro" - - "RA_ygyro" - - "LA_ygyro" - - "RL_ygyro" - - "LL_ygyro" - - "T_ymag" - - "RA_ymag" - - "LA_ymag" - - "RL_ymag" - - "LL_ymag" - - "T_zacc" - - "RA_zacc" - - "LA_zacc" - - "RL_zacc" - - "LL_zacc" - - "T_zgyro" - - "RA_zgyro" - - "LA_zgyro" - - "RL_zgyro" - - "LL_zgyro" - - "T_zmag" - - "RA_zmag" - - "LA_zmag" - - "RL_zmag" - - "LL_zmag" + - "sensor" diff --git a/pyhealth/datasets/dsa.py b/pyhealth/datasets/dsa.py index b01008309..73f7ba430 100644 --- a/pyhealth/datasets/dsa.py +++ b/pyhealth/datasets/dsa.py @@ -48,7 +48,8 @@ class DSADataset(BaseDataset): - a19 This dataset class loads raw data files and reformats into a single CSV file - with columns activity, patient, segment, sample_id, and 45 sensor columns. + with columns activity, patient, segment, sensor, and 0-124 columns that + represent time series. Dataset is available at: https://archive.ics.uci.edu/dataset/256/daily+and+sports+activities @@ -164,21 +165,19 @@ def prepare_data(root: str) -> None: logger.info(f"Loading raw sensors data ...") - for a in range(1, 20): - for p in range(1, 9): - for s in range(1, 61): - df = pd.read_csv( - Path(root) / "data" / f"a{a:02d}" / f"p{p}" / f"s{s:02d}.txt", - header=None, - ) + for a in list(range(1, 20)): + for p in list(range(1, 9)): + for s in list(range(1, 61)): + df = pd.read_csv(root / "data" / f"a{a:02d}" / f"p{p}" / f"s{s:02d}.txt", header=None) df.columns = columns - df = df.assign( - activity=a, - patient=p, - segment=s, + + data.append( + df.T.reset_index().rename(columns={"index": "sensor"}).assign( + activity=a, + patient=p, + segment=s, + ) ) - df["sample_id"] = range(1, 126) - data.append(df) df_out = pd.concat(data) diff --git a/pyhealth/tasks/activity_classification.py b/pyhealth/tasks/activity_classification.py index 5236f9565..53a79a27b 100644 --- a/pyhealth/tasks/activity_classification.py +++ b/pyhealth/tasks/activity_classification.py @@ -3,11 +3,12 @@ This module provides a task for classifying daily and sports activity using motion sensor data from Daily and Sports Activities (DSA) dataset. """ - +import logging from typing import Any, Dict, List, Optional - +import pandas as pd from .base_task import BaseTask +logger = logging.getLogger(__name__) class ActivityClassification(BaseTask): """Task for classifying activity using motion sensor data. @@ -33,51 +34,16 @@ class ActivityClassification(BaseTask): task_name: str = "ActivityClassification" input_schema: Dict[str, str] = { - "features": "sequence", + "T": "sequence", + "RA": "sequence", + "LA": "sequence", + "RL": "sequence", + "LL": "sequence", } output_schema: Dict[str, str] = { "label": "text", } - def _extract_features(self, activity: Any) -> List[float]: - """Extract features from an activity event. - - Args: - activity: An activity event object. - - Returns: - List of feature values. - """ - features: List[float] = [] - - columns = [ - f"{x}_{z}{y}" - for z in ["x", "y", "z"] - for y in ["acc", "gyro", "mag"] - for x in ["T", "RA", "LA", "RL", "LL"] - ] - for c in columns: - x = getattr(activity, c, None) - features.append(x) - - return features - - def _extract_label(self, activity: Any) -> Optional[int]: - """Extract label for an activity event. - - Args: - activity: An activity event object. - - Returns: - 1 - 19 to represent activity, None if value is invalid or unknown. - """ - if activity is None: - return None - - label = getattr(activity, "activity", None) - - return label - def __call__(self, patient: Any) -> List[Dict[str, Any]]: """Process daily and sports activities data for activity classification. @@ -92,16 +58,30 @@ def __call__(self, patient: Any) -> List[Dict[str, Any]]: Returns empty list for patients with: - No activities """ - activities = patient.get_events(event_type="activities") + events = patient.get_events(event_type="activities") - if len(activities) == 0: + if len(events) == 0: return [] - - return [ - { - "patient_id": patient.patient_id, - "features": self._extract_features(activity), - "label": self._extract_label(activity), - } - for activity in activities - ] + + df = pd.DataFrame([e.attr_dict for e in events]) + + def extract_time_series(df, sensor): + return df[df["sensor"].str.startswith(sensor + "_")].reset_index(drop=True).sort_values("sensor").T + + records = [] + for a in df["activity"].unique(): + for s in df["segment"].unique(): + + df_one = df.query(f'activity == "{a}"').query(f'segment == "{s}"') + + if len(df_one) == 0: + continue + + record = { + sensor: extract_time_series(df_one, sensor) for sensor in ["T", "LA", "RA", "LL", "RL"] + } + record["patient_id"] = patient.patient_id + record["label"] = a + records.append(record) + + return records diff --git a/test-resources/dsa/dsa-pyhealth.csv b/test-resources/dsa/dsa-pyhealth.csv index 1a57f5713..2e7b3fe32 100644 --- a/test-resources/dsa/dsa-pyhealth.csv +++ b/test-resources/dsa/dsa-pyhealth.csv @@ -1,21 +1,21 @@ -T_xacc,RA_xacc,LA_xacc,RL_xacc,LL_xacc,T_xgyro,RA_xgyro,LA_xgyro,RL_xgyro,LL_xgyro,T_xmag,RA_xmag,LA_xmag,RL_xmag,LL_xmag,T_yacc,RA_yacc,LA_yacc,RL_yacc,LL_yacc,T_ygyro,RA_ygyro,LA_ygyro,RL_ygyro,LL_ygyro,T_ymag,RA_ymag,LA_ymag,RL_ymag,LL_ymag,T_zacc,RA_zacc,LA_zacc,RL_zacc,LL_zacc,T_zgyro,RA_zgyro,LA_zgyro,RL_zgyro,LL_zgyro,T_zmag,RA_zmag,LA_zmag,RL_zmag,LL_zmag,activity,patient,segment,sample_id -8.3131,-0.89161,3.4829,-0.31429,0.039033,0.27511,-0.91084,0.41779,-0.071697,-0.84114,5.4726,7.9802,-0.33354,-0.29744,0.18019,-0.42968,-0.2345,-0.83518,-1.2729,-6.3533,5.826,-2.6156,1.1285,0.7457,-0.14533,0.90085,-0.30413,-0.42687,0.55892,1.2345,0.058055,-0.15068,1.0072,0.43424,-0.67505,0.20034,-9.6503,-10.189,-1.2675,-0.20789,-0.34648,0.27405,0.60667,0.48892,-0.34716,16,1,60,52 -11.84,0.059295,1.5869,0.71073,0.58851,0.13427,-0.93463,0.16111,0.38241,14.73,1.1219,1.185,1.1097,1.2687,-2.3585,-0.93797,0.27877,0.15077,14.253,-2.6582,1.6044,-0.24274,0.66728,1.8438,-0.93667,-0.088245,0.31095,-12.49,5.7882,2.1154,-1.4661,-0.57424,-0.051077,0.79858,0.45994,0.35114,-10.941,-0.74024,-0.40234,0.63481,0.060647,-0.15809,0.826,-0.35061,-0.38515,18,3,32,59 -10.172,2.4585,3.5307,-0.54464,-0.33529,-0.18707,-0.89917,-0.15392,0.1631,10.246,3.3153,0.13724,-0.49348,0.23491,-0.59136,-0.94365,0.061012,0.047113,11.182,0.10717,3.9649,2.1207,-0.08562,0.86037,-0.90022,-0.18463,0.017512,-12.59,-3.0806,2.6163,0.41921,0.14977,1.1836,0.6682,0.58396,-0.2919,-11.683,0.55632,-0.36202,0.36462,0.076038,1.0466,0.84949,-0.32773,0.17506,9,1,35,29 -9.416,-2.1977,4.693,0.95558,0.21684,-0.41964,-0.85492,0.53011,-0.015934,-0.56958,4.3747,9.0146,0.56839,0.41764,-0.078376,-0.50716,-0.13101,-0.88553,0.57454,-3.4865,9.3634,0.22778,-0.10896,-0.23502,-0.38079,0.6922,-0.58164,-8.4059,6.4897,0.44679,-0.1779,-0.005699,-2.4593,0.47813,-0.53446,0.30772,-8.591,-9.9117,-0.53818,0.30804,-0.16206,-2.2108,0.53678,0.55181,-0.43545,16,1,9,58 -8.0865,-0.2408,3.6028,0.15649,-0.32136,-0.048024,-0.62068,0.1848,-0.6332,8.4594,1.5216,0.67405,0.44756,0.90507,-1.7612,-0.35136,0.022328,-0.95171,8.6742,-2.6619,2.9889,-0.29812,-0.47963,-2.1346,-0.5662,0.76524,0.40703,-6.3341,4.0496,-0.22198,1.6531,-0.24082,0.005633,0.35098,-0.72703,0.35797,-9.9342,-3.2876,-1.3094,0.2463,0.3072,1.0892,1.0749,0.34908,-0.1557,10,6,42,17 -9.4769,-0.35637,1.3081,-0.023822,-0.47482,0.010213,-0.7806,-0.03383,-0.58585,3.2565,2.2587,8.761,0.12159,-0.39719,0.21735,0.23885,-0.24844,-0.88524,2.5931,-2.3315,8.544,0.11183,-0.28157,-0.29491,0.18529,0.018937,-0.92893,-0.26951,9.346,-1.1284,-0.28026,-0.10108,0.566,-0.42312,-0.8644,-0.059146,0.43549,-8.0116,-4.8812,-0.19694,0.57888,-0.42021,-0.49822,0.69599,0.46264,17,3,14,13 -10.413,-3.5139,5.7962,0.17605,0.1922,-0.073935,-0.74572,0.30642,-0.63589,3.7203,9.048,0.76887,0.2363,-0.55176,-0.32467,-0.41422,-0.56141,-0.48936,3.5781,-6.4982,7.7381,-0.069666,0.50068,-0.56215,0.015839,0.71056,-0.93329,-12.53,2.1052,-1.1003,0.643,-0.10938,-1.1014,0.84059,-0.36595,0.15484,-11.763,-5.6095,-3.8126,-1.3106,0.28608,0.98938,0.79251,0.67014,-0.042973,10,7,34,56 -9.1361,1.4385,4.4644,0.54445,0.40864,-0.3545,-0.91836,0.26298,-0.13111,2.3694,7.9979,4.8811,0.34208,0.21765,-0.30616,-0.76618,-0.4944,-0.52338,1.5973,-4.5506,8.5491,0.074027,-0.10415,-0.047873,-0.67156,0.66497,-0.56205,-9.5713,10.865,-0.64796,-0.42244,0.03298,-0.32233,0.6901,-0.15918,0.20492,-2.2445,-0.73998,-3.0723,0.73919,0.40397,-1.094,0.53545,0.69486,-0.081579,16,4,50,117 -10.004,2.5936,1.2038,-1.1109,-0.070371,-0.14837,-0.93787,-0.39985,0.064385,19.398,-1.9689,6.2024,3.1224,-0.34522,2.102,-0.79838,-0.54207,-0.13436,12.055,-1.4415,5.0604,0.76672,2.3059,2.2045,-0.88471,-0.32169,-0.36848,-9.3479,-0.15021,-0.8001,-0.14906,-0.16136,-0.98636,0.96718,-0.058197,-0.4121,-9.8898,-1.66,-2.311,0.70039,-0.007266,-0.28159,0.9171,-0.054443,0.38715,19,2,52,119 -9.5202,-0.097624,3.6071,-0.23136,0.030941,-0.32654,-0.89424,-0.04648,0.21146,9.9124,3.1205,2.7562,0.074591,-0.46495,0.22428,-0.83521,0.3164,0.21406,11.779,-1.8761,3.8031,-2.2067,0.054235,-0.46023,-0.88232,-0.076329,0.29956,-10.858,1.9206,-1.292,0.65118,-0.21272,-0.51304,0.63471,0.68898,-0.002028,-8.2238,-2.984,-3.5087,0.33753,0.99681,-0.027226,0.90993,-0.17071,0.00541,9,3,36,111 -7.1875,-1.4288,6.7869,0.016676,0.38276,0.007781,-0.34376,-0.00507,-0.90885,-2.2656,9.4839,2.4405,0.72472,0.045511,-1.1975,0.66073,-0.49822,-0.49374,-0.95824,-3.936,7.7712,-0.25698,-0.10244,0.72657,0.47468,0.067533,-0.83869,-2.2133,11.659,4.208,0.045985,0.59248,-0.30771,-0.23641,-0.78206,-0.51153,-4.2791,-9.8212,-0.55694,-0.37198,-0.0903,0.78076,-0.039183,0.97034,0.037953,17,8,8,84 -8.9235,0.43648,2.7027,-0.74201,-0.90844,-0.26481,-0.65358,-0.074521,-0.69317,8.8169,4.1858,6.0226,-1.6219,0.049449,-0.35822,0.12168,-0.37139,-0.78798,7.3198,-6.4745,5.5421,2.1826,0.41977,0.38122,-0.17416,0.48463,-0.66198,-8.9732,0.36566,0.027289,-0.30103,-0.20919,1.3483,0.81889,-0.33328,-0.39401,-7.7025,-2.3132,0.053663,0.53881,0.26991,1.0475,0.7397,0.56584,0.36006,13,1,30,78 -9.3581,0.92832,2.168,-0.053244,0.07298,-0.1165,-0.55718,-0.22505,0.19349,2.6188,0.78267,9.1984,0.066114,0.098715,-0.049549,-0.26382,-0.17587,-0.24441,1.8387,-0.74629,9.3833,0.067962,-0.010683,-0.052397,-0.64217,-0.14746,-0.49378,-3.7491,10.749,-1.3344,-0.83626,-0.12522,0.56644,0.43407,-0.51989,-0.097536,4.6338,-4.5922,0.46994,-0.23997,-0.011066,0.5567,0.1015,0.55677,0.24796,15,5,33,16 -7.6427,-1.6273,4.5589,-0.2402,-0.52003,-0.036924,-0.6604,-0.044255,0.00782,-0.14544,5.6893,7.9471,-0.18368,-0.094774,0.031512,-0.19736,-0.40985,-0.29236,-0.19959,-2.4768,9.0227,0.06562,-0.054854,-0.093852,-0.49338,-0.044472,-0.61961,6.4375,1.6976,0.74124,0.88016,-0.26015,-0.84731,0.1132,-0.65734,-0.14501,-2.0735,-12.592,-1.4314,-0.022301,0.29235,-0.84524,0.41643,0.37373,0.18079,15,6,26,40 -29.051,-3.98,-1.0241,-0.68134,0.8976,-0.19221,-0.94708,0.13103,-0.47876,4.3187,10.425,-0.44361,-0.35158,-0.041183,0.1427,-0.65283,-0.74088,-0.20948,6.2111,-7.5305,6.1445,-0.64165,-1.2791,-0.51271,-0.40626,0.5801,-0.96043,-24.381,-3.7933,-4.5389,-0.67705,0.083068,-2.3597,0.72578,-0.57876,0.041516,-20.012,7.7482,1.4062,0.75187,0.26712,-4.1026,0.88902,0.54831,0.18057,12,7,36,109 -5.2214,0.63878,4.4785,0.31555,-0.22662,-0.17395,-0.92408,0.021993,-0.081787,7.7444,2.9478,3.5724,0.079947,-0.90602,0.093311,-0.88031,0.18227,0.15357,8.6533,-1.9719,2.2627,0.56983,1.1164,2.3987,-0.90138,-0.064,-0.12198,-9.1805,-0.45633,-1.6623,1.2449,0.41394,-1.7511,0.74713,0.5394,0.10978,-8.8001,4.051,1.2805,1.7726,1.3693,-2.1018,0.83104,-0.38573,-0.059277,9,5,47,112 --3.344,0.092144,9.3024,0.000882,0.015133,-0.011051,0.16791,-0.44661,-0.79888,-6.9891,0.89119,6.8429,0.00646,-0.004929,-0.002394,0.90553,-0.17152,-0.22212,-7.4414,1.3746,6.3046,-0.000863,-0.000727,-0.010735,0.31986,-0.087818,-0.86203,0.11418,7.7206,-5.9672,-0.006168,0.010131,-0.018441,-0.002306,-0.95486,0.11589,-0.075708,-6.3911,-7.364,-0.008523,-0.002583,0.005349,0.18579,0.18989,0.9558,3,3,17,58 -8.0246,-1.0831,2.7374,-0.025617,0.13309,0.32138,-0.63721,0.14383,-0.60481,-0.11918,7.9492,5.0985,0.088464,-0.38971,0.76724,0.034311,-0.18275,-0.62023,-0.13409,-6.5663,7.0712,0.2924,-0.38506,-0.36853,0.42253,0.83806,-0.64737,-12.131,1.1594,-1.7115,-0.71023,1.1461,2.7074,0.63972,-0.47338,0.5241,-7.4004,-1.8209,-3.8708,-0.83243,0.041936,1.8923,0.84989,0.68954,-0.19125,11,6,17,58 -9.1667,-1.575,3.1247,-0.007485,0.031151,0.004787,-0.55078,-0.33451,-0.51785,-1.0507,8.4647,4.8334,0.001327,-0.007116,-0.005842,0.4023,-0.64517,0.09924,1.1523,-6.2318,7.56,-0.001717,0.002918,-0.012575,0.29757,0.011825,-0.93756,-3.3308,9.1646,-0.91419,-0.002092,0.003455,-0.003042,-0.32326,-0.672,-0.4186,-3.5826,-9.154,-0.2246,-0.001867,0.001725,-0.008039,-0.021634,0.44214,0.56964,1,4,49,64 -7.9205,2.3204,3.8242,0.55641,0.027897,0.12651,-0.8821,-0.12107,0.21219,7.4176,2.3879,2.3572,0.9271,0.064412,0.45067,-0.92643,-0.093245,0.019932,7.2369,-3.6015,3.0001,-0.20576,-0.35735,-0.46375,-0.90387,-0.10805,0.021407,-8.3388,1.7509,-1.324,-0.54207,0.63262,0.78172,0.85166,0.34005,-0.02379,-9.7675,-0.22432,-1.6329,-1.1755,0.05182,1.0439,0.67785,-0.59859,0.1009,9,1,54,90 +sensor,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,activity,patient,segment +LL_yacc,-0.078456,-0.33406,-0.56166,-0.61154,-0.47572,-0.49548,-0.47364,-0.5938,-0.44523,-0.21173,-0.17766,-0.5601,-0.97679,-0.87833,-0.634,-0.86217,-1.3394,-1.799,-2.4054,-2.7506,-2.8182,-2.6564,-2.6037,-2.3597,-2.2109,-1.8638,-1.7018,-1.6301,-1.3909,-1.2519,-1.076,-0.63153,-0.35454,-0.48332,0.1011,0.75036,1.3341,1.7557,2.211,2.0685,2.2413,2.6918,2.2989,1.743,1.4128,1.1837,0.92611,0.8006,0.77474,0.63276,0.5993,0.68246,0.52242,0.63401,0.81958,0.71967,0.68243,0.52111,0.39795,0.28212,0.4346,0.53291,0.51424,0.043438,0.16393,0.3332,0.37012,-0.2447,0.53354,-1.5823,-1.3022,-1.4766,-1.5341,-1.9246,-0.85574,-1.1274,-1.4165,-1.216,-1.4871,-0.93795,-3.6112,1.3855,-2.181,-1.9718,-1.5532,-1.4982,-1.0876,-1.7095,-2.2004,-2.9462,-2.4321,-0.24488,-1.1011,-1.1245,-0.36749,-0.62969,-1.1742,-1.424,-1.6563,-1.9775,0.59562,0.68884,0.50297,0.61936,0.8236,0.70791,0.68089,0.51834,0.41255,0.28888,0.43938,0.54549,0.52831,0.039244,0.16455,0.32609,0.36362,-0.26697,0.54095,-1.5902,-1.2951,-1.4879,-1.5265,-1.9076,-0.86388,5,8,1 +LL_yacc,-7.1121,-7.1049,-7.0879,-7.0805,-7.0391,-7.0952,-7.0686,-7.1196,-7.105,-7.0976,-7.1193,-7.0708,-7.1095,-7.1047,-7.027,-7.0513,-7.0732,-7.0804,-7.0998,-7.0172,-7.0465,-7.1679,-7.0805,-7.0366,-7.0683,-7.1148,-7.0857,-7.0563,-7.0805,-7.0491,-7.071,-7.0903,-7.1049,-7.0757,-7.0195,-7.0416,-7.0565,-7.1149,-7.11,-6.9906,-7.0513,-7.1145,-7.0419,-7.0589,-7.0879,-7.0953,-7.0418,-7.0515,-7.088,-7.0417,-7.0757,-7.0757,-7.0418,-7.0856,-7.066,-7.032,-7.0295,-7.0561,-7.061,-7.0415,-7.061,-7.1363,-7.073,-6.9736,-7.1539,-7.0561,-6.9831,-7.0806,-7.1969,-6.9976,-6.9585,-7.0781,-7.1002,-7.0777,-6.9976,-7.1708,-7.081,-7.0295,-7.0524,-7.1178,-7.0836,-7.061,-7.0854,-7.0458,-7.0724,-7.0817,-7.1038,-7.0774,-7.0232,-7.0322,-7.0481,-7.1123,-7.1133,-6.9885,-7.0608,-7.1354,-7.0392,-7.0484,-7.1071,-7.0915,-7.0313,-7.0484,-7.0902,-7.045,-7.0846,-7.0663,-7.0312,-7.0922,-7.0487,-7.0416,-7.0334,-7.0798,-7.0567,-7.0284,-7.071,-7.1454,-7.0832,-6.9967,-7.1499,-7.0518,-6.9687,-7.0707,-7.2189,-7.0045,-6.9573,8,8,1 +RL_ymag,-4.1866,-3.4676,-1.129,-2.7259,0.064433,0.43543,2.05,1.0613,-2.2628,-2.4528,-0.65198,-0.85922,-1.1272,-1.0884,5.0912,7.6014,4.5893,-2.187,-4.8983,-3.8311,-3.7709,-3.7715,-2.6944,-7.3639,-7.479,-7.0876,-3.7868,22.489,15.372,-12.197,8.055,-12.323,-5.5942,-1.3761,-2.898,-1.6669,-0.60695,2.3974,3.0038,-1.9557,-2.2339,-0.11049,-1.2767,-1.0487,-1.3693,2.1601,6.4541,6.3575,-0.12304,-5.0629,-5.7536,-2.9201,-3.6907,-3.0871,-4.7066,-6.7371,-5.9892,-3.5007,8.525,32.83,-7.3105,1.1673,1.2121,-7.0754,-4.1858,-1.3314,-2.5226,-2.7758,-0.55628,3.3774,1.192,-3.0907,-1.387,-0.024656,-0.60788,-0.61766,1.1728,5.9116,8.2043,-0.13,-5.6751,-5.332,-3.2111,-3.5294,-4.0723,-5.031,-7.9919,-7.4829,-3.6733,20.252,19.041,-11.799,10.003,-7.0715,-6.82,-1.8533,-1.7373,-2.8306,-0.59691,-0.65312,4.5975,-0.45595,-2.4282,-1.8479,-0.19199,-0.46822,-0.037453,6.5331,9.0025,2.4171,-5.2432,-5.4247,-3.9297,-3.7519,-5.3124,-4.2193,-7.6001,-9.3195,-4.1245,15.289,21.904,-11.201,5.5697,-3.8976,-7.6989,9,5,1 +LL_zacc,-0.12384,-0.15544,-0.20615,-0.26044,-0.30428,-0.34718,-0.39004,-0.428,-0.44873,-0.45804,-0.46129,-0.45528,-0.44222,-0.42557,-0.43151,-0.42913,-0.40199,-0.37235,-0.34638,-0.32901,-0.31054,-0.28675,-0.27099,-0.25345,-0.23489,-0.2171,-0.1954,-0.17326,-0.1529,-0.12917,-0.10974,-0.084811,-0.067923,-0.063372,-0.06723,-0.099072,-0.14681,-0.19862,-0.23442,-0.26986,-0.31821,-0.36817,-0.41951,-0.4555,-0.48396,-0.50444,-0.51467,-0.51884,-0.51926,-0.51564,-0.50691,-0.49138,-0.45897,-0.45354,-0.44541,-0.41305,-0.37252,-0.3402,-0.31777,-0.29531,-0.27174,-0.24518,-0.2288,-0.20922,-0.17993,-0.15237,-0.13091,-0.10767,-0.081104,-0.06028,-0.066124,-0.10331,-0.16708,-0.23108,-0.28129,-0.33789,-0.39959,-0.46136,-0.51381,-0.55557,-0.57445,-0.58289,-0.57927,-0.56946,-0.5569,-0.54158,-0.53796,-0.50446,-0.47033,-0.4449,-0.41635,-0.38911,-0.36024,-0.34105,-0.32255,-0.29871,-0.28554,-0.26666,-0.25527,-0.25749,-0.29497,-0.37602,-0.46801,-0.53931,-0.59708,-0.64952,-0.68969,-0.70597,-0.69718,-0.67751,-0.64877,-0.61056,-0.55943,-0.53481,-0.5263,-0.50121,-0.48722,-0.48524,-0.47631,-0.46079,-0.4412,-0.41957,-0.39658,-0.38164,-0.37506,19,2,1 +T_xmag,1.9057,1.8813,1.8911,1.9129,1.8862,1.8839,1.8717,1.8911,1.8838,1.8863,1.9008,1.8863,1.8814,1.9056,1.8814,1.8814,1.8887,1.8863,1.8911,1.8862,1.891,1.8814,1.8936,1.9007,1.8718,1.8862,1.9153,1.8451,1.9057,1.8863,1.8861,1.9009,1.8741,1.925,1.8813,1.7939,1.9323,1.8911,1.9057,1.8668,1.8911,1.896,1.8668,1.9008,1.9009,1.891,1.9202,1.8475,1.9152,1.9398,1.8998,1.8715,1.8613,1.8928,1.894,1.8796,1.8926,1.9058,1.8469,1.91,1.8916,1.8703,1.897,1.8589,1.9365,1.8633,1.7746,1.9418,1.8909,1.8847,1.8793,1.8947,1.9066,1.8678,1.913,1.9018,1.8863,1.8928,1.8927,1.8902,1.8918,1.8743,1.8942,1.8758,1.8764,1.9094,1.8485,1.9042,1.8887,1.8796,1.905,1.8781,1.9312,1.8845,1.7861,1.9351,1.8931,1.8973,1.8505,1.879,1.8951,1.8746,1.9028,1.8959,1.8877,1.932,1.8442,1.9182,1.9364,1.8993,1.8848,1.8633,1.9011,1.8861,1.8784,1.9152,1.919,1.8346,1.9048,1.873,1.8527,1.8977,1.8575,1.9447,1.8473,3,8,1 +RL_zmag,0.72361,0.71264,0.72427,0.73525,0.70836,0.68749,0.66654,0.62116,0.56071,0.52211,0.48363,0.43996,0.40588,0.37114,0.33447,0.29906,0.26254,0.22866,0.20267,0.22304,0.29823,0.4034,0.50456,0.62393,0.68323,0.71003,0.72942,0.73487,0.73792,0.73178,0.73019,0.74373,0.7514,0.70547,0.68468,0.65652,0.6144,0.58265,0.54746,0.50702,0.4652,0.42094,0.3779,0.33425,0.29176,0.25537,0.22394,0.21554,0.26796,0.36901,0.46615,0.56416,0.63978,0.69656,0.72261,0.72893,0.7312,0.73913,0.71979,0.71909,0.73491,0.71167,0.68849,0.67068,0.62898,0.58714,0.55105,0.50915,0.46946,0.43075,0.39498,0.36147,0.32177,0.28157,0.24683,0.22388,0.22965,0.30264,0.40863,0.50924,0.60219,0.66252,0.70101,0.72467,0.73131,0.73558,0.72654,0.7125,0.71789,0.72204,0.70452,0.68687,0.64322,0.5897,0.56087,0.53376,0.49512,0.45568,0.4118,0.36798,0.3285,0.27949,0.23274,0.20052,0.21124,0.27158,0.38063,0.48401,0.6143,0.68064,0.70745,0.72076,0.72075,0.71886,0.72298,0.72881,0.73867,0.74501,0.70566,0.68868,0.65783,0.60866,0.57071,0.53161,0.48604,10,6,1 +RL_zmag,-0.082618,-0.095608,-0.10766,-0.11824,-0.1304,-0.14558,-0.16126,-0.17291,-0.17769,-0.17879,-0.17267,-0.17136,-0.17396,-0.17716,-0.18119,-0.18016,-0.17159,-0.15717,-0.1382,-0.12187,-0.11456,-0.11442,-0.1238,-0.12696,-0.1225,-0.12026,-0.12691,-0.13502,-0.14425,-0.16413,-0.18511,-0.19838,-0.20812,-0.21533,-0.22637,-0.23511,-0.24609,-0.25734,-0.26359,-0.26968,-0.27657,-0.2844,-0.29218,-0.29721,-0.30251,-0.30685,-0.31304,-0.31588,-0.31814,-0.31589,-0.31006,-0.30249,-0.2883,-0.271,-0.25014,-0.22744,-0.20503,-0.18682,-0.17828,-0.17443,-0.17487,-0.17841,-0.18678,-0.19406,-0.2167,-0.24003,-0.2591,-0.26865,-0.26645,-0.26915,-0.27212,-0.27268,-0.27443,-0.27814,-0.27984,-0.28347,-0.28724,-0.29139,-0.29512,-0.30187,-0.30621,-0.30841,-0.30649,-0.29938,-0.29089,-0.27903,-0.26061,-0.23543,-0.20311,-0.16748,-0.12998,-0.10113,-0.072605,-0.039947,-0.00509,0.035558,0.080901,0.12642,0.17051,0.20514,0.22668,0.23619,0.23527,0.22963,0.22284,0.21239,0.19874,0.1838,0.16984,0.15897,0.14801,0.13837,0.13309,0.13454,0.13626,0.13822,0.13754,0.13675,0.13587,0.13549,0.13562,0.13747,0.13901,0.13953,0.14259,8,5,1 +RL_xmag,-0.40295,-0.61681,-0.70294,-0.89072,-0.92199,-1.1709,-1.3203,-1.1321,-0.86014,-0.56995,-0.23194,0.020402,0.022609,-0.025966,-0.046097,-0.10848,-0.27584,-0.38752,-0.35305,-0.27702,-0.1826,-0.13882,-0.1001,0.068238,0.22092,0.27582,0.25823,0.44874,0.78913,1.1527,1.2713,1.0468,0.58401,0.2894,0.205,0.1691,0.057298,-0.12012,-0.2118,-0.27468,-0.37559,-0.42541,-0.3036,-0.50172,-0.78565,-0.93614,-0.9837,-0.68928,-0.28245,-0.14966,-0.15484,-0.20784,-0.3001,-0.41229,-0.4838,-0.48956,-0.45562,-0.40963,-0.31865,-0.1227,0.27328,0.37508,0.35592,0.45303,0.64039,1.1468,1.4204,1.2606,0.87799,0.60465,0.46439,0.39112,0.31094,0.17132,0.006264,-0.18371,-0.37838,-0.37483,-0.64265,-0.99787,-1.1277,-1.136,-0.92561,-0.5326,-0.099088,-0.27224,-0.14787,-0.18884,-0.22705,-0.25209,-0.24816,-0.21373,-0.15335,-0.12066,-0.014842,0.11394,0.16666,0.19298,0.27047,0.54753,0.87225,1.0047,1.0735,0.87468,0.55987,0.31229,0.21352,0.11345,0.009139,-0.13993,-0.2701,-0.37499,-0.52675,-0.4337,-0.51994,-0.81689,-0.90345,-0.77897,-0.48315,-0.11001,-0.039387,0.002179,-0.013371,-0.14084,-0.25192,9,4,1 +LL_ygyro,-0.44869,-0.44751,-0.44718,-0.44775,-0.44746,-0.44881,-0.4485,-0.4481,-0.44889,-0.44915,-0.44686,-0.446,-0.44617,-0.44634,-0.44669,-0.44831,-0.44641,-0.44596,-0.44556,-0.44605,-0.44665,-0.44649,-0.44625,-0.44564,-0.44726,-0.44542,-0.44671,-0.4458,-0.44681,-0.44756,-0.4481,-0.44908,-0.44789,-0.44769,-0.44646,-0.44726,-0.44771,-0.44821,-0.44852,-0.44849,-0.44751,-0.44875,-0.44786,-0.44687,-0.44736,-0.44711,-0.44685,-0.44593,-0.44578,-0.44628,-0.44478,-0.4452,-0.44457,-0.44447,-0.4448,-0.44576,-0.44699,-0.44649,-0.44639,-0.44614,-0.44665,-0.44501,-0.44556,-0.44661,-0.44605,-0.44487,-0.44586,-0.4456,-0.4456,-0.44555,-0.44712,-0.44742,-0.4465,-0.44751,-0.44636,-0.44691,-0.44705,-0.44704,-0.44666,-0.44696,-0.44738,-0.44743,-0.44715,-0.44753,-0.44723,-0.44589,-0.44766,-0.44642,-0.44702,-0.44709,-0.44723,-0.44631,-0.44716,-0.44674,-0.44578,-0.44714,-0.44748,-0.44666,-0.44795,-0.44741,-0.44682,-0.44793,-0.44717,-0.44647,-0.44671,-0.44718,-0.44639,-0.44689,-0.44673,-0.44575,-0.44702,-0.44706,-0.4469,-0.4477,-0.44663,-0.44713,-0.44586,-0.44614,-0.44545,-0.44685,-0.44637,-0.44686,-0.44642,-0.44769,-0.44665,4,2,1 +RL_yacc,8.1265,9.1109,11.206,12.434,11.939,10.568,8.7569,8.5012,8.6641,9.3956,10.485,9.8637,8.3433,8.0607,8.2255,8.3081,8.0592,7.7085,7.6015,7.604,7.7303,8.1521,9.3658,11.454,10.063,8.7525,8.6345,8.3936,8.55,8.6822,7.9942,7.1458,7.3828,7.9021,8.204,8.1306,8.4327,8.8398,8.9982,8.9716,9.9541,11.066,11.12,10.683,9.4444,7.4022,8.1581,10.253,9.834,8.6651,7.642,7.4221,7.5581,7.8379,7.6207,7.455,7.6451,8.4491,9.1894,10.817,10.569,8.9719,8.8132,9.3285,9.3769,8.8275,7.5559,6.8008,6.823,7.1323,7.5052,7.8,8.2964,8.4982,8.92,10.165,11.572,12.04,10.257,9.1406,8.1981,8.1427,9.5374,9.5669,8.5245,9.0358,9.1075,8.7706,8.6536,8.327,7.7859,7.7225,8.1,8.6676,9.6668,11.47,10.313,8.8878,8.6164,8.5934,8.9374,8.3062,7.0928,6.4593,6.7665,7.6095,8.1502,8.6862,8.9659,8.7392,9.0224,9.6951,10.466,11.775,9.9043,9.0525,8.7924,8.6908,10.194,10.452,9.3579,8.7469,8.3815,8.2082,8.2007,9,4,1 +LA_zmag,0.45426,0.43546,0.43232,0.41855,0.42558,0.42125,0.43712,0.45578,0.47678,0.48487,0.48749,0.48614,0.47059,0.45039,0.44308,0.4312,0.42678,0.42507,0.44481,0.46625,0.49181,0.4919,0.4829,0.47623,0.46334,0.44524,0.43299,0.43632,0.43498,0.43738,0.45435,0.47725,0.49862,0.49962,0.49675,0.49306,0.47382,0.45432,0.45085,0.4329,0.42723,0.43424,0.4515,0.47594,0.50156,0.50923,0.50412,0.49574,0.48087,0.47002,0.45523,0.45274,0.4454,0.45894,0.47372,0.49261,0.51094,0.51566,0.50875,0.50467,0.48601,0.46474,0.47051,0.45619,0.45455,0.46162,0.47546,0.49153,0.50971,0.51694,0.52225,0.51958,0.50265,0.48414,0.46777,0.45588,0.46026,0.45656,0.46559,0.48691,0.50719,0.51511,0.51507,0.5171,0.50755,0.48225,0.47666,0.45708,0.45138,0.44931,0.4598,0.47984,0.50036,0.51518,0.51156,0.50589,0.50222,0.49428,0.48122,0.46735,0.45948,0.4581,0.45821,0.48262,0.50156,0.51541,0.51802,0.51781,0.50963,0.49112,0.46829,0.46037,0.43867,0.44621,0.44354,0.4548,0.4765,0.49993,0.5107,0.50725,0.50496,0.49755,0.48157,0.47111,0.45416,18,1,1 +RA_yacc,-0.55907,-0.55684,-0.55788,-0.56833,-0.5599,-0.55966,-0.55804,-0.55911,-0.55778,-0.56112,-0.5618,-0.55955,-0.55882,-0.55968,-0.56159,-0.56081,-0.55917,-0.5592,-0.55942,-0.56041,-0.55989,-0.55966,-0.55942,-0.56006,-0.56109,-0.56003,-0.55943,-0.55993,-0.54836,-0.55969,-0.55821,-0.56001,-0.56026,-0.5592,-0.55719,-0.55675,-0.55925,-0.55945,-0.55927,-0.55857,-0.55672,-0.55959,-0.55876,-0.55892,-0.55883,-0.55819,-0.56024,-0.55816,-0.56026,-0.55984,-0.55946,-0.56091,-0.55843,-0.57114,-0.56294,-0.56374,-0.55983,-0.56003,-0.55934,-0.56306,-0.56399,-0.5616,-0.56057,-0.56158,-0.56309,-0.56298,-0.56263,-0.56001,-0.56159,-0.56173,-0.56335,-0.56062,-0.56273,-0.56217,-0.56084,-0.56242,-0.56116,-0.56274,-0.55033,-0.56063,-0.5612,-0.56121,-0.56252,-0.56202,-0.56086,-0.56056,-0.56164,-0.56165,-0.56245,-0.55996,-0.55993,-0.56156,-0.56183,-0.56288,-0.56292,-0.56345,-0.5645,-0.56441,-0.5627,-0.56375,-0.56414,-0.56483,-0.56452,-0.57428,-0.56661,-0.56697,-0.56487,-0.56526,-0.56443,-0.56634,-0.56559,-0.56535,-0.56621,-0.56586,-0.5664,-0.56535,-0.56477,-0.56553,-0.56593,-0.56758,-0.56639,-0.56606,-0.56578,-0.56659,-0.56579,1,1,1 +T_yacc,-0.33699,-0.33723,-0.33727,-0.33686,-0.3374,-0.33684,-0.33657,-0.33691,-0.33726,-0.33702,-0.33694,-0.33673,-0.33738,-0.33611,-0.33644,-0.3374,-0.33696,-0.337,-0.337,-0.33643,-0.3372,-0.33634,-0.33693,-0.33609,-0.33787,-0.33639,-0.33698,-0.33634,-0.33617,-0.33547,-0.33696,-0.33779,-0.33664,-0.33715,-0.33624,-0.3371,-0.33632,-0.33631,-0.33577,-0.33728,-0.33738,-0.33737,-0.33665,-0.33711,-0.33782,-0.33805,-0.33735,-0.33666,-0.33769,-0.33806,-0.33857,-0.33764,-0.33693,-0.33751,-0.33701,-0.3372,-0.3374,-0.3368,-0.33642,-0.33747,-0.33819,-0.33767,-0.33737,-0.33698,-0.33826,-0.33674,-0.33606,-0.33654,-0.33527,-0.33676,-0.33709,-0.33553,-0.33659,-0.33697,-0.33619,-0.33593,-0.33657,-0.33644,-0.3371,-0.33688,-0.33694,-0.33737,-0.33657,-0.33712,-0.33656,-0.33695,-0.3371,-0.3356,-0.33763,-0.33739,-0.33769,-0.338,-0.33748,-0.33716,-0.33695,-0.33715,-0.33643,-0.33732,-0.33656,-0.33685,-0.33814,-0.33764,-0.33717,-0.33638,-0.3372,-0.33689,-0.33895,-0.33759,-0.33682,-0.33704,-0.33708,-0.3376,-0.33672,-0.33693,-0.33665,-0.33643,-0.33697,-0.33675,-0.3368,-0.3373,-0.33566,-0.33717,-0.33602,-0.33726,-0.33633,3,1,1 +LA_zmag,0.49065,0.52042,0.5518,0.56914,0.58181,0.59043,0.59569,0.60151,0.61094,0.61576,0.618,0.61737,0.61784,0.62049,0.62311,0.62609,0.62457,0.62373,0.61995,0.61126,0.59237,0.55217,0.50494,0.46486,0.42316,0.39005,0.36575,0.34613,0.32939,0.31581,0.3006,0.28935,0.28904,0.29269,0.30483,0.31908,0.3432,0.37092,0.39575,0.42805,0.46332,0.50277,0.53054,0.54031,0.54906,0.56203,0.56944,0.58352,0.59967,0.60704,0.61248,0.61231,0.61447,0.62198,0.62356,0.62688,0.6264,0.62541,0.62297,0.61096,0.59219,0.55798,0.51939,0.48353,0.44308,0.40335,0.36978,0.34453,0.32258,0.30677,0.29306,0.28553,0.27917,0.27723,0.2863,0.29894,0.31939,0.34305,0.36793,0.39727,0.42961,0.47821,0.51438,0.52337,0.52749,0.54239,0.55101,0.56293,0.58179,0.59332,0.60312,0.60726,0.61134,0.62132,0.62288,0.62112,0.61557,0.61009,0.60612,0.59401,0.57763,0.55189,0.52358,0.49957,0.4675,0.42683,0.3901,0.35995,0.33655,0.31294,0.29403,0.28469,0.27793,0.27497,0.27874,0.2837,0.29202,0.29935,0.31442,0.34458,0.38193,0.42877,0.47013,0.50793,0.54089,14,2,1 +RA_xgyro,-0.68619,-0.6868,-0.68492,-0.68523,-0.68543,-0.68596,-0.68598,-0.68598,-0.68655,-0.68506,-0.68584,-0.68502,-0.68522,-0.68466,-0.68474,-0.68512,-0.68455,-0.68501,-0.68786,-0.68598,-0.68594,-0.68567,-0.68558,-0.68467,-0.68504,-0.68432,-0.68293,-0.68444,-0.68482,-0.68478,-0.68379,-0.684,-0.68375,-0.68299,-0.68332,-0.68393,-0.68346,-0.68546,-0.68471,-0.68497,-0.6838,-0.68426,-0.68322,-0.68288,-0.68376,-0.68292,-0.6824,-0.68304,-0.68336,-0.68421,-0.68392,-0.68328,-0.68345,-0.68458,-0.68461,-0.68484,-0.68345,-0.68545,-0.68485,-0.6838,-0.6821,-0.68246,-0.68326,-0.68225,-0.68291,-0.6818,-0.68321,-0.68177,-0.68185,-0.68241,-0.68229,-0.68238,-0.68261,-0.68342,-0.68183,-0.68163,-0.68272,-0.68388,-0.68342,-0.68445,-0.6836,-0.68367,-0.68398,-0.6854,-0.68477,-0.68738,-0.68823,-0.68816,-0.69053,-0.69025,-0.69227,-0.69314,-0.69585,-0.69473,-0.69708,-0.69939,-0.70101,-0.70418,-0.70668,-0.70851,-0.71096,-0.71202,-0.71636,-0.72113,-0.72411,-0.72596,-0.72919,-0.73286,-0.73759,-0.74116,-0.74692,-0.75013,-0.75533,-0.76077,-0.76506,-0.77102,-0.77438,-0.77989,-0.7867,-0.79247,-0.79802,-0.80251,-0.80874,-0.81347,-0.81969,7,7,1 +LA_yacc,-0.78977,-0.78944,-0.78909,-0.78944,-0.78835,-0.78862,-0.78923,-0.78906,-0.78841,-0.78784,-0.78908,-0.78815,-0.78778,-0.78878,-0.78912,-0.78912,-0.78805,-0.7878,-0.78828,-0.78733,-0.78934,-0.78778,-0.78832,-0.78806,-0.78739,-0.78721,-0.78762,-0.78799,-0.78696,-0.78682,-0.78739,-0.78628,-0.78648,-0.78627,-0.78755,-0.78649,-0.78733,-0.78716,-0.78693,-0.78666,-0.78725,-0.78698,-0.78649,-0.78711,-0.78775,-0.78836,-0.78889,-0.78843,-0.78981,-0.78897,-0.78958,-0.78977,-0.78979,-0.79121,-0.79065,-0.79118,-0.79043,-0.79157,-0.79076,-0.78991,-0.79056,-0.79062,-0.78996,-0.79022,-0.78968,-0.79035,-0.79111,-0.79004,-0.78935,-0.78953,-0.78994,-0.78993,-0.79053,-0.79178,-0.79006,-0.79107,-0.7907,-0.79084,-0.79071,-0.79024,-0.79018,-0.79015,-0.79144,-0.79092,-0.79158,-0.79165,-0.79156,-0.79129,-0.79238,-0.79044,-0.79082,-0.79087,-0.79206,-0.79083,-0.7908,-0.79039,-0.78983,-0.78909,-0.79078,-0.78971,-0.78993,-0.78997,-0.79039,-0.79136,-0.79259,-0.79214,-0.79353,-0.79374,-0.79454,-0.79429,-0.79482,-0.79492,-0.79449,-0.79623,-0.7945,-0.79603,-0.79642,-0.795,-0.7939,-0.79373,-0.79547,-0.79501,-0.79476,-0.79456,-0.79348,4,2,1 +RA_zacc,0.023233,0.003854,0.019717,0.005615,0.017946,0.011798,0.002965,0.004732,-0.011997,0.012661,0.016187,0.010894,0.009125,0.000342,0.019682,0.032012,0.019707,0.009153,0.026757,0.007395,-0.000522,0.012648,0.010902,0.010044,0.010909,-0.002281,0.006501,0.016181,0.00739,0.006414,-0.006814,0.018718,0.009035,0.016971,0.003769,0.003787,0.02663,0.005502,0.019621,-0.005028,0.001991,0.024868,0.020464,-0.001524,0.010788,0.01608,0.010785,0.017828,0.003764,0.006398,0.003769,0.021347,0.005522,0.01432,0.024893,0.009032,0.003766,-0.001512,0.009042,0.017834,0.021372,-0.007669,0.007266,0.013438,0.009058,0.002015,0.016082,0.019619,-0.008582,0.007293,-0.003273,0.007281,0.016076,-0.001536,-0.00153,0.007277,-0.003279,0.005513,0.017825,0.005517,0.016096,0.009027,0.017845,0.020484,0.002001,0.007285,0.01607,0.017752,-0.008664,0.00541,0.013332,0.009818,0.001873,0.009814,0.007168,0.020381,0.009813,0.023885,0.003651,0.011573,0.023012,0.023882,0.00891,0.015975,0.021242,0.00275,0.016856,0.003653,0.020366,0.01071,0.007171,0.005418,0.02037,0.003642,0.007164,0.014233,-0.001618,0.033577,0.012465,0.002779,0.015961,0.01246,-0.002518,0.005398,0.007164,1,4,1 +T_zmag,0.39211,0.13513,0.04723,-0.17345,0.006449,-0.21635,-0.39754,-0.45393,-0.35084,-0.64262,-0.16831,0.1461,-0.67212,-0.5547,-0.59418,-0.64993,-0.87709,-0.71255,-0.58686,-0.60913,-0.39491,-0.54261,0.067551,0.37387,0.37666,-1.323,0.98504,1.0346,0.56992,0.27197,0.22973,0.21056,0.15761,0.36056,0.45005,0.21567,-0.017751,-0.082486,0.02835,0.093815,0.031356,-0.055494,-0.062826,-0.047365,-0.036943,-0.088704,-0.14018,-0.16127,-0.14617,-0.12973,-0.14058,-0.17478,-0.14706,-0.1251,-0.069755,0.004582,-0.054159,-0.11099,-0.06573,-0.012752,-0.016663,-0.013144,0.023837,-0.009225,0.016041,-0.000795,0.023679,0.007388,0.041848,0.011658,-0.021792,0.005067,-0.004071,0.03349,0.046949,0.014694,0.024478,0.03159,-0.004473,0.007986,-0.003874,-0.004873,0.018275,-0.006575,-0.006082,-0.017931,-0.000298,0.10388,0.029146,0.023507,0.02867,0.063026,0.10313,0.10027,0.073331,0.038485,0.018692,0.006337,-0.006694,-0.020073,-0.017859,-0.038086,-0.035029,-0.03127,-0.01731,0.005152,-0.054304,-0.049314,0.022171,0.034904,0.034,0.00437,-0.0068,0.024938,0.049484,0.017127,0.007896,0.010541,0.020188,0.066343,-0.011303,0.046953,-0.021976,-0.037287,0.013498,8,3,1 +RL_zmag,0.15432,0.1804,0.19911,0.22632,0.25956,0.26658,0.25555,0.25024,0.23626,0.20541,0.18692,0.16313,0.13553,0.10816,0.084072,0.061035,0.041324,0.017779,-0.004934,-0.00472,0.014563,0.048108,0.086554,0.12014,0.14035,0.14107,0.12824,0.11451,0.09001,0.052011,0.025704,0.001471,-0.007906,0.005688,0.026877,0.024716,0.006411,0.002226,-0.031559,-0.07119,-0.10146,-0.12892,-0.15337,-0.1791,-0.20091,-0.21598,-0.22701,-0.23681,-0.24663,-0.25162,-0.24801,-0.24004,-0.21322,-0.17622,-0.12639,-0.087445,-0.04003,-0.003726,0.011847,0.014963,-0.001314,-0.008493,0.003577,-0.003483,-0.018048,-0.028704,-0.02617,-0.031543,-0.041468,-0.050599,-0.059972,-0.067014,-0.067665,-0.066384,-0.06771,-0.067211,-0.064329,-0.058603,-0.057955,-0.058211,-0.055985,-0.054029,-0.061071,-0.067559,-0.070117,-0.066638,-0.053826,-0.024655,0.009013,0.011736,0.007855,0.009178,0.016711,0.030134,0.048623,0.066812,0.080052,0.07915,0.073858,0.073593,0.080235,0.080487,0.076461,0.07648,0.088959,0.10775,0.12163,0.13123,0.14316,0.15232,0.164,0.17384,0.18909,0.20694,0.22398,0.24075,0.26083,0.27677,0.29123,0.29981,0.29864,0.29309,0.28809,0.28678,0.28467,8,1,1 +RA_zmag,-0.29142,-0.22589,-0.098233,0.001665,-0.008271,-0.060571,-0.041036,0.008032,-0.011372,-0.14034,-0.24382,-0.34825,-0.1895,-0.17105,-0.18664,-0.20378,-0.30248,-0.36628,-0.39014,-0.29552,-0.23619,-0.20216,-0.20676,-0.277,-0.23939,-0.24569,-0.28919,-0.34612,-0.34168,-0.40346,-0.40112,-0.49268,-0.56365,-0.56004,-0.62527,-0.60725,-0.64142,-0.6018,-0.51895,-0.50083,-0.49802,-0.41662,-0.34279,-0.29344,-0.25372,-0.18596,-0.10532,-0.099506,-0.042933,-0.029523,-0.063349,0.013007,0.03973,0.036713,0.10827,0.10608,0.071849,0.003413,-0.006851,-0.068055,-0.050258,-0.047072,0.042929,0.036541,0.065023,0.10484,0.15004,0.18082,0.22072,0.23502,0.29329,0.37014,0.43155,0.52306,0.61369,0.65778,0.72594,0.78234,0.85714,0.86414,0.87889,0.93548,0.87067,0.89976,0.89453,0.8653,0.78081,0.68536,0.60578,0.49863,-0.15197,-0.58776,-0.2204,0.22027,0.23976,-0.16923,-0.29533,-0.012785,0.14581,0.050513,-0.015391,-0.000341,-0.007636,-0.022636,-0.29339,-0.26559,-0.19295,-0.073325,-0.066727,-0.12098,-0.29672,-0.16574,-0.14684,-0.12302,-0.081307,-0.052761,-0.082324,-0.10529,-0.050877,-0.15134,-0.51749,-0.67015,-0.86985,-0.78326,-0.82961,17,7,1 diff --git a/tests/core/test_dsa.py b/tests/core/test_dsa.py index bea1dbe2c..288122354 100755 --- a/tests/core/test_dsa.py +++ b/tests/core/test_dsa.py @@ -52,10 +52,10 @@ def test_get_patient(self): def test_get_events(self): """Test getting motion sensor data from a patient.""" dataset = DSADataset(root=str(self.test_resources)) - patient = dataset.get_patient("3") + patient = dataset.get_patient("4") events = patient.get_events(event_type="activities") # patient 5 has 2 samples in test data - self.assertEqual(len(events), 4) + self.assertEqual(len(events), 3) def test_event_attributes(self): """Test that event attributes are correctly loaded.""" @@ -67,8 +67,7 @@ def test_event_attributes(self): # Check that attributes exist self.assertIn("activity", event) self.assertIn("segment", event) - self.assertIn("sample_id", event) - self.assertIn("LL_ygyro", event) + self.assertIn("sensor", event) def test_default_task(self): """Test that the default task is ActivityClassification.""" @@ -93,7 +92,11 @@ def test_task_output_format(self): if len(samples) > 0: sample = samples[0] self.assertIn("patient_id", sample) - self.assertIn("features", sample) + self.assertIn("T", sample) + self.assertIn("LA", sample) + self.assertIn("RA", sample) + self.assertIn("LL", sample) + self.assertIn("RL", sample) self.assertIn("label", sample) @@ -104,13 +107,21 @@ def test_task_attributes(self): """Test task class attributes.""" task = ActivityClassification() self.assertEqual(task.task_name, "ActivityClassification") - self.assertIn("features", task.input_schema) + self.assertIn("T", task.input_schema) + self.assertIn("LA", task.input_schema) + self.assertIn("RA", task.input_schema) + self.assertIn("LL", task.input_schema) + self.assertIn("RL", task.input_schema) self.assertIn("label", task.output_schema) def test_input_schema(self): """Test input schema definition.""" task = ActivityClassification() - self.assertEqual(task.input_schema["features"], "sequence") + self.assertEqual(task.input_schema["T"], "sequence") + self.assertEqual(task.input_schema["RA"], "sequence") + self.assertEqual(task.input_schema["LA"], "sequence") + self.assertEqual(task.input_schema["RL"], "sequence") + self.assertEqual(task.input_schema["LL"], "sequence") def test_output_schema(self): """Test output schema definition.""" From 95b70ff54948ecc37ce5c2d830c49b15ac43f3a3 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 20:48:37 +0800 Subject: [PATCH 07/20] bug fix path --- pyhealth/datasets/dsa.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyhealth/datasets/dsa.py b/pyhealth/datasets/dsa.py index 73f7ba430..57b414afc 100644 --- a/pyhealth/datasets/dsa.py +++ b/pyhealth/datasets/dsa.py @@ -168,7 +168,7 @@ def prepare_data(root: str) -> None: for a in list(range(1, 20)): for p in list(range(1, 9)): for s in list(range(1, 61)): - df = pd.read_csv(root / "data" / f"a{a:02d}" / f"p{p}" / f"s{s:02d}.txt", header=None) + df = pd.read_csv(Path(root) / "data" / f"a{a:02d}" / f"p{p}" / f"s{s:02d}.txt", header=None) df.columns = columns data.append( From 5c045a07b16f0070cfac1fa00a152f32cd48e11f Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 20:59:26 +0800 Subject: [PATCH 08/20] convert to numpy --- pyhealth/tasks/activity_classification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyhealth/tasks/activity_classification.py b/pyhealth/tasks/activity_classification.py index 53a79a27b..9095165e7 100644 --- a/pyhealth/tasks/activity_classification.py +++ b/pyhealth/tasks/activity_classification.py @@ -66,7 +66,7 @@ def __call__(self, patient: Any) -> List[Dict[str, Any]]: df = pd.DataFrame([e.attr_dict for e in events]) def extract_time_series(df, sensor): - return df[df["sensor"].str.startswith(sensor + "_")].reset_index(drop=True).sort_values("sensor").T + return df[df["sensor"].str.startswith(sensor + "_")].reset_index(drop=True).sort_values("sensor").T.to_numpy() records = [] for a in df["activity"].unique(): From 64b93564914badebcb85d7bcc6b2b428263550b8 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 21:00:33 +0800 Subject: [PATCH 09/20] add ablation study --- examples/activity_classification_using_dsa.py | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 examples/activity_classification_using_dsa.py diff --git a/examples/activity_classification_using_dsa.py b/examples/activity_classification_using_dsa.py new file mode 100644 index 000000000..0fc271e7c --- /dev/null +++ b/examples/activity_classification_using_dsa.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +"""activity_classification_using_dsa.ipynb + +# Activity Classification Using DSA Dataset + +# Install PyHealth + +You might need to restart kernel after running this section. +""" + +! rm -rf PyHealth + +!git clone https://github.com/ranyou/PyHealth.git +!cd PyHealth && pip install -e . + +"""# Load Dataset""" + +from pyhealth.datasets import DSADataset + +dataset = DSADataset(download=True, root="./daily-and-sports-activities") +dataset.stats() + +"""# Define Task""" + +samples = dataset.set_task() + +from pyhealth.datasets import get_dataloader, split_by_sample + +train_dataset, val_dataset, test_dataset = split_by_sample(samples, [0.7, 0.1, 0.2]) + +train_loader = get_dataloader(train_dataset, batch_size=16, shuffle=True) +val_loader = get_dataloader(val_dataset, batch_size=16, shuffle=False) +test_loader = get_dataloader(test_dataset, batch_size=16, shuffle=False) + +"""# Define Model""" + +from pyhealth.models import RNN + +model = RNN(samples) + +"""# Train Model""" + +from pyhealth.trainer import Trainer + +trainer = Trainer(model=model, metrics=["accuracy"]) +trainer.train(train_dataloader=train_loader, val_dataloader=val_loader, epochs=1) + +"""# Evaluate Model""" + +trainer.evaluate(test_loader) + From 3d433c1e9fbe9f3b43f625c92ed4be3a0f850703 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 21:05:46 +0800 Subject: [PATCH 10/20] include time columns --- pyhealth/datasets/configs/dsa.yaml | 125 ++++++++++++++++++++++ pyhealth/tasks/activity_classification.py | 3 +- 2 files changed, 127 insertions(+), 1 deletion(-) diff --git a/pyhealth/datasets/configs/dsa.yaml b/pyhealth/datasets/configs/dsa.yaml index e264aa6af..54bc5d4cc 100644 --- a/pyhealth/datasets/configs/dsa.yaml +++ b/pyhealth/datasets/configs/dsa.yaml @@ -9,3 +9,128 @@ tables: - "patient" - "segment" - "sensor" + - "0" + - "1" + - "2" + - "3" + - "4" + - "5" + - "6" + - "7" + - "8" + - "9" + - "10" + - "11" + - "12" + - "13" + - "14" + - "15" + - "16" + - "17" + - "18" + - "19" + - "20" + - "21" + - "22" + - "23" + - "24" + - "25" + - "26" + - "27" + - "28" + - "29" + - "30" + - "31" + - "32" + - "33" + - "34" + - "35" + - "36" + - "37" + - "38" + - "39" + - "40" + - "41" + - "42" + - "43" + - "44" + - "45" + - "46" + - "47" + - "48" + - "49" + - "50" + - "51" + - "52" + - "53" + - "54" + - "55" + - "56" + - "57" + - "58" + - "59" + - "60" + - "61" + - "62" + - "63" + - "64" + - "65" + - "66" + - "67" + - "68" + - "69" + - "70" + - "71" + - "72" + - "73" + - "74" + - "75" + - "76" + - "77" + - "78" + - "79" + - "80" + - "81" + - "82" + - "83" + - "84" + - "85" + - "86" + - "87" + - "88" + - "89" + - "90" + - "91" + - "92" + - "93" + - "94" + - "95" + - "96" + - "97" + - "98" + - "99" + - "100" + - "101" + - "102" + - "103" + - "104" + - "105" + - "106" + - "107" + - "108" + - "109" + - "110" + - "111" + - "112" + - "113" + - "114" + - "115" + - "116" + - "117" + - "118" + - "119" + - "120" + - "121" + - "122" + - "123" + - "124" \ No newline at end of file diff --git a/pyhealth/tasks/activity_classification.py b/pyhealth/tasks/activity_classification.py index 9095165e7..587b94c76 100644 --- a/pyhealth/tasks/activity_classification.py +++ b/pyhealth/tasks/activity_classification.py @@ -66,7 +66,8 @@ def __call__(self, patient: Any) -> List[Dict[str, Any]]: df = pd.DataFrame([e.attr_dict for e in events]) def extract_time_series(df, sensor): - return df[df["sensor"].str.startswith(sensor + "_")].reset_index(drop=True).sort_values("sensor").T.to_numpy() + columns = [f"{d}" for d in range(125)] + return df[df["sensor"].str.startswith(sensor + "_")][columns].reset_index(drop=True).sort_values("sensor").T.to_numpy() records = [] for a in df["activity"].unique(): From 9ac55f706811114a05510ec5f3a717b0f87e3e97 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 21:08:56 +0800 Subject: [PATCH 11/20] include sensor in columns --- pyhealth/tasks/activity_classification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyhealth/tasks/activity_classification.py b/pyhealth/tasks/activity_classification.py index 587b94c76..5486c66ed 100644 --- a/pyhealth/tasks/activity_classification.py +++ b/pyhealth/tasks/activity_classification.py @@ -66,7 +66,7 @@ def __call__(self, patient: Any) -> List[Dict[str, Any]]: df = pd.DataFrame([e.attr_dict for e in events]) def extract_time_series(df, sensor): - columns = [f"{d}" for d in range(125)] + columns = [f"{d}" for d in range(125)] + ["sensor"] return df[df["sensor"].str.startswith(sensor + "_")][columns].reset_index(drop=True).sort_values("sensor").T.to_numpy() records = [] From 1d839b44d7a303a488202a3c2647a149e78733de Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 21:10:59 +0800 Subject: [PATCH 12/20] convert numpy array to list --- pyhealth/tasks/activity_classification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyhealth/tasks/activity_classification.py b/pyhealth/tasks/activity_classification.py index 5486c66ed..fb9dcd682 100644 --- a/pyhealth/tasks/activity_classification.py +++ b/pyhealth/tasks/activity_classification.py @@ -67,7 +67,7 @@ def __call__(self, patient: Any) -> List[Dict[str, Any]]: def extract_time_series(df, sensor): columns = [f"{d}" for d in range(125)] + ["sensor"] - return df[df["sensor"].str.startswith(sensor + "_")][columns].reset_index(drop=True).sort_values("sensor").T.to_numpy() + return df[df["sensor"].str.startswith(sensor + "_")][columns].reset_index(drop=True).sort_values("sensor").T.to_numpy().tolist() records = [] for a in df["activity"].unique(): From 90ffb2d4745ec3ee299b4cea1e1c892f45426f01 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 21:16:48 +0800 Subject: [PATCH 13/20] convert features to float --- pyhealth/tasks/activity_classification.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyhealth/tasks/activity_classification.py b/pyhealth/tasks/activity_classification.py index fb9dcd682..7c669b1e0 100644 --- a/pyhealth/tasks/activity_classification.py +++ b/pyhealth/tasks/activity_classification.py @@ -66,9 +66,9 @@ def __call__(self, patient: Any) -> List[Dict[str, Any]]: df = pd.DataFrame([e.attr_dict for e in events]) def extract_time_series(df, sensor): - columns = [f"{d}" for d in range(125)] + ["sensor"] - return df[df["sensor"].str.startswith(sensor + "_")][columns].reset_index(drop=True).sort_values("sensor").T.to_numpy().tolist() - + columns = [f"{d}" for d in range(125)] + return df[df["sensor"].str.startswith(sensor + "_")].sort_values("sensor")[columns].astype(float).reset_index(drop=True).T.to_numpy().tolist() + records = [] for a in df["activity"].unique(): for s in df["segment"].unique(): From 14a6f5a8c5c1acaeb396ab1932a8a9e45336c27c Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 21:19:34 +0800 Subject: [PATCH 14/20] conver inner lists to tuples --- pyhealth/tasks/activity_classification.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyhealth/tasks/activity_classification.py b/pyhealth/tasks/activity_classification.py index 7c669b1e0..889b6169d 100644 --- a/pyhealth/tasks/activity_classification.py +++ b/pyhealth/tasks/activity_classification.py @@ -67,8 +67,9 @@ def __call__(self, patient: Any) -> List[Dict[str, Any]]: def extract_time_series(df, sensor): columns = [f"{d}" for d in range(125)] - return df[df["sensor"].str.startswith(sensor + "_")].sort_values("sensor")[columns].astype(float).reset_index(drop=True).T.to_numpy().tolist() - + tss = df[df["sensor"].str.startswith(sensor + "_")].sort_values("sensor")[columns].astype(float).reset_index(drop=True).T.to_numpy().tolist() + return [tuple(ts) for ts in tss] + records = [] for a in df["activity"].unique(): for s in df["segment"].unique(): From 1f3573e6bf1399411514b73fcb9fdf8b00b931db Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 21:26:45 +0800 Subject: [PATCH 15/20] fix time series type --- pyhealth/tasks/activity_classification.py | 10 +++++----- tests/core/test_dsa.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pyhealth/tasks/activity_classification.py b/pyhealth/tasks/activity_classification.py index 889b6169d..5a63da102 100644 --- a/pyhealth/tasks/activity_classification.py +++ b/pyhealth/tasks/activity_classification.py @@ -34,11 +34,11 @@ class ActivityClassification(BaseTask): task_name: str = "ActivityClassification" input_schema: Dict[str, str] = { - "T": "sequence", - "RA": "sequence", - "LA": "sequence", - "RL": "sequence", - "LL": "sequence", + "T": "timeseries", + "RA": "timeseries", + "LA": "timeseries", + "RL": "timeseries", + "LL": "timeseries", } output_schema: Dict[str, str] = { "label": "text", diff --git a/tests/core/test_dsa.py b/tests/core/test_dsa.py index 288122354..52a0b7941 100755 --- a/tests/core/test_dsa.py +++ b/tests/core/test_dsa.py @@ -117,11 +117,11 @@ def test_task_attributes(self): def test_input_schema(self): """Test input schema definition.""" task = ActivityClassification() - self.assertEqual(task.input_schema["T"], "sequence") - self.assertEqual(task.input_schema["RA"], "sequence") - self.assertEqual(task.input_schema["LA"], "sequence") - self.assertEqual(task.input_schema["RL"], "sequence") - self.assertEqual(task.input_schema["LL"], "sequence") + self.assertEqual(task.input_schema["T"], "timeseries") + self.assertEqual(task.input_schema["RA"], "timeseries") + self.assertEqual(task.input_schema["LA"], "timeseries") + self.assertEqual(task.input_schema["RL"], "timeseries") + self.assertEqual(task.input_schema["LL"], "timeseries") def test_output_schema(self): """Test output schema definition.""" From d1efdf8e9d96f8f5eca4a3b1ca262389feea9339 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 22:10:33 +0800 Subject: [PATCH 16/20] fix schema --- pyhealth/tasks/activity_classification.py | 33 ++++++++++++++--------- tests/core/test_dsa.py | 31 +++++++++------------ 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/pyhealth/tasks/activity_classification.py b/pyhealth/tasks/activity_classification.py index 5a63da102..45b11e315 100644 --- a/pyhealth/tasks/activity_classification.py +++ b/pyhealth/tasks/activity_classification.py @@ -3,11 +3,11 @@ This module provides a task for classifying daily and sports activity using motion sensor data from Daily and Sports Activities (DSA) dataset. """ -import logging + from typing import Any, Dict, List, Optional import pandas as pd from .base_task import BaseTask - +import logging logger = logging.getLogger(__name__) class ActivityClassification(BaseTask): @@ -34,14 +34,13 @@ class ActivityClassification(BaseTask): task_name: str = "ActivityClassification" input_schema: Dict[str, str] = { - "T": "timeseries", - "RA": "timeseries", - "LA": "timeseries", - "RL": "timeseries", - "LL": "timeseries", + f"{x}_{y}{z}": "sequence" + for x in ["T", "LA", "RA", "LL", "RL"] + for y in ["x", "y", "z"] + for z in ["acc", "gyro", "mag"] } output_schema: Dict[str, str] = { - "label": "text", + "label": "multiclass", } def __call__(self, patient: Any) -> List[Dict[str, Any]]: @@ -67,9 +66,12 @@ def __call__(self, patient: Any) -> List[Dict[str, Any]]: def extract_time_series(df, sensor): columns = [f"{d}" for d in range(125)] - tss = df[df["sensor"].str.startswith(sensor + "_")].sort_values("sensor")[columns].astype(float).reset_index(drop=True).T.to_numpy().tolist() - return [tuple(ts) for ts in tss] - + ts = df[df["sensor"] == sensor][columns].astype(float).to_numpy().tolist() + # return times, values + if len(ts) > 0: + return ts[0] + return [] + records = [] for a in df["activity"].unique(): for s in df["segment"].unique(): @@ -79,8 +81,15 @@ def extract_time_series(df, sensor): if len(df_one) == 0: continue + features = [ + f"{x}_{y}{z}" + for y in ["x", "y", "z"] + for z in ["acc", "gyro", "mag"] + for x in ["T", "RA", "LA", "RL", "LL"] + ] + record = { - sensor: extract_time_series(df_one, sensor) for sensor in ["T", "LA", "RA", "LL", "RL"] + feature: extract_time_series(df_one, feature) for feature in features } record["patient_id"] = patient.patient_id record["label"] = a diff --git a/tests/core/test_dsa.py b/tests/core/test_dsa.py index 52a0b7941..9fff32003 100755 --- a/tests/core/test_dsa.py +++ b/tests/core/test_dsa.py @@ -9,14 +9,12 @@ if not hasattr(torch, 'uint16'): torch.uint16 = torch.int16 # This tricks litdata into thinking uint16 exists - import unittest from pathlib import Path from pyhealth.datasets import DSADataset from pyhealth.tasks import ActivityClassification - class TestDSADataset(unittest.TestCase): """Test cases for DSADataset.""" @@ -92,11 +90,9 @@ def test_task_output_format(self): if len(samples) > 0: sample = samples[0] self.assertIn("patient_id", sample) - self.assertIn("T", sample) - self.assertIn("LA", sample) - self.assertIn("RA", sample) - self.assertIn("LL", sample) - self.assertIn("RL", sample) + self.assertIn("T_xacc", sample) + self.assertIn("LA_ygyro", sample) + self.assertIn("LL_zmag", sample) self.assertIn("label", sample) @@ -107,26 +103,25 @@ def test_task_attributes(self): """Test task class attributes.""" task = ActivityClassification() self.assertEqual(task.task_name, "ActivityClassification") - self.assertIn("T", task.input_schema) - self.assertIn("LA", task.input_schema) - self.assertIn("RA", task.input_schema) - self.assertIn("LL", task.input_schema) - self.assertIn("RL", task.input_schema) + self.assertIn("T_xacc", task.input_schema) + self.assertIn("LA_ygyro", task.input_schema) + self.assertIn("LL_zmag", task.input_schema) self.assertIn("label", task.output_schema) def test_input_schema(self): """Test input schema definition.""" task = ActivityClassification() - self.assertEqual(task.input_schema["T"], "timeseries") - self.assertEqual(task.input_schema["RA"], "timeseries") - self.assertEqual(task.input_schema["LA"], "timeseries") - self.assertEqual(task.input_schema["RL"], "timeseries") - self.assertEqual(task.input_schema["LL"], "timeseries") + + for x in ["T", "LA", "RA", "LL", "RL"]: + for y in ["x", "y", "z"]: + for z in ["acc", "gyro", "mag"]: + feature = f"{x}_{y}{z}" + self.assertEqual(task.input_schema[feature], "sequence") def test_output_schema(self): """Test output schema definition.""" task = ActivityClassification() - self.assertEqual(task.output_schema["label"], "text") + self.assertEqual(task.output_schema["label"], "multiclass") if __name__ == "__main__": From 75e1307ab9020b5a157a236450f3c1da6648b420 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 22:40:41 +0800 Subject: [PATCH 17/20] update notebook --- examples/activity_classification_using_dsa.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/activity_classification_using_dsa.py b/examples/activity_classification_using_dsa.py index 0fc271e7c..8d13efbb8 100644 --- a/examples/activity_classification_using_dsa.py +++ b/examples/activity_classification_using_dsa.py @@ -8,8 +8,6 @@ You might need to restart kernel after running this section. """ -! rm -rf PyHealth - !git clone https://github.com/ranyou/PyHealth.git !cd PyHealth && pip install -e . From 654dfcb647b4f2b48051c2feadb4315611927fc4 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 22:41:01 +0800 Subject: [PATCH 18/20] delete pytorch hack --- tests/core/test_dsa.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/core/test_dsa.py b/tests/core/test_dsa.py index 9fff32003..c0c854bc7 100755 --- a/tests/core/test_dsa.py +++ b/tests/core/test_dsa.py @@ -4,10 +4,6 @@ Author: Ran You """ -# CR rayou: delete this -import torch -if not hasattr(torch, 'uint16'): - torch.uint16 = torch.int16 # This tricks litdata into thinking uint16 exists import unittest from pathlib import Path From 495adeafe34fced9166916feda749b541cf02b04 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sat, 4 Apr 2026 22:49:44 +0800 Subject: [PATCH 19/20] rename notebook --- ...classification_using_dsa.py => dsa_activity_classification.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename examples/{activity_classification_using_dsa.py => dsa_activity_classification.py} (100%) diff --git a/examples/activity_classification_using_dsa.py b/examples/dsa_activity_classification.py similarity index 100% rename from examples/activity_classification_using_dsa.py rename to examples/dsa_activity_classification.py From 0a4b3c98c794207e8fc029a7534a4dce49619688 Mon Sep 17 00:00:00 2001 From: ranyou Date: Sun, 5 Apr 2026 14:10:44 +0800 Subject: [PATCH 20/20] update example notebook --- examples/dsa_activity_classification.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/dsa_activity_classification.py b/examples/dsa_activity_classification.py index 8d13efbb8..afbabe060 100644 --- a/examples/dsa_activity_classification.py +++ b/examples/dsa_activity_classification.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""activity_classification_using_dsa.ipynb +"""dsa_activity_classification.ipynb # Activity Classification Using DSA Dataset