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 399b8f1aa..43a3f8802 100644 --- a/docs/api/tasks.rst +++ b/docs/api/tasks.rst @@ -229,3 +229,4 @@ Available Tasks Mutation Pathogenicity (COSMIC) Cancer Survival Prediction (TCGA) Cancer Mutation Burden (TCGA) + Activity Classification (DSA) 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: diff --git a/examples/dsa_activity_classification.py b/examples/dsa_activity_classification.py new file mode 100644 index 000000000..afbabe060 --- /dev/null +++ b/examples/dsa_activity_classification.py @@ -0,0 +1,49 @@ +# -*- coding: utf-8 -*- +"""dsa_activity_classification.ipynb + +# Activity Classification Using DSA Dataset + +# Install PyHealth + +You might need to restart kernel after running this section. +""" + +!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) + diff --git a/pyhealth/datasets/__init__.py b/pyhealth/datasets/__init__.py index 54e77670c..01da8c066 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..54bc5d4cc --- /dev/null +++ b/pyhealth/datasets/configs/dsa.yaml @@ -0,0 +1,136 @@ +version: "1.0" +tables: + activities: + file_path: "dsa-pyhealth.csv" + patient_id: "patient" + timestamp: null + attributes: + - "activity" + - "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/datasets/dsa.py b/pyhealth/datasets/dsa.py new file mode 100644 index 000000000..57b414afc --- /dev/null +++ b/pyhealth/datasets/dsa.py @@ -0,0 +1,198 @@ +"""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, sensor, and 0-124 columns that + represent time series. + + 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, + 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 not os.path.exists(Path(root) / "data"): + logger.info( + f""" + 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 + then extract the downloaded zip file to , or directly set download=True. + """ + ) + raise + + 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 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. + + 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 list(range(1, 20)): + for p in list(range(1, 9)): + for s in list(range(1, 61)): + 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( + df.T.reset_index().rename(columns={"index": "sensor"}).assign( + activity=a, + patient=p, + segment=s, + ) + ) + + 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 797988377..71dcce08a 100644 --- a/pyhealth/tasks/__init__.py +++ b/pyhealth/tasks/__init__.py @@ -66,3 +66,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..45b11e315 --- /dev/null +++ b/pyhealth/tasks/activity_classification.py @@ -0,0 +1,98 @@ +"""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 +import pandas as pd +from .base_task import BaseTask +import logging +logger = logging.getLogger(__name__) + +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] = { + 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": "multiclass", + } + + 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 + """ + events = patient.get_events(event_type="activities") + + if len(events) == 0: + return [] + + df = pd.DataFrame([e.attr_dict for e in events]) + + def extract_time_series(df, sensor): + columns = [f"{d}" for d in range(125)] + 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(): + + df_one = df.query(f'activity == "{a}"').query(f'segment == "{s}"') + + 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 = { + feature: extract_time_series(df_one, feature) for feature in features + } + 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 new file mode 100644 index 000000000..2e7b3fe32 --- /dev/null +++ b/test-resources/dsa/dsa-pyhealth.csv @@ -0,0 +1,21 @@ +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 new file mode 100755 index 000000000..c0c854bc7 --- /dev/null +++ b/tests/core/test_dsa.py @@ -0,0 +1,124 @@ +""" +Unit tests for the DSADataset and ActivityClassification classes. + +Author: + Ran You +""" + +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("4") + events = patient.get_events(event_type="activities") + # patient 5 has 2 samples in test data + self.assertEqual(len(events), 3) + + 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("sensor", 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("T_xacc", sample) + self.assertIn("LA_ygyro", sample) + self.assertIn("LL_zmag", 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("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() + + 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"], "multiclass") + + +if __name__ == "__main__": + unittest.main()