roh8exe's picture
Upload folder using huggingface_hub
60b21d3 verified
Raw
History Blame Contribute Delete
7.27 kB
# SPDX-FileCopyrightText: 2025 Stanford University, ETH Zurich, and the project authors (see CONTRIBUTORS.md)
# SPDX-FileCopyrightText: 2025 This source file is part of the OpenTSLM open-source project.
#
# SPDX-License-Identifier: MIT
from typing import Tuple
import pandas as pd
from opentslm.time_series_datasets.pamap2.pamap2_loader import ensure_pamap2_data
from torch.utils.data import Dataset
ACTIVITIY_ID_DICT = {
0: "transient",
1: "lying",
2: "sitting",
3: "standing",
4: "walking",
5: "running",
6: "cycling",
7: "nordic walking",
9: "watching TV",
10: "computer work",
11: "car driving",
12: "ascending stairs",
13: "descending stairs",
16: "vacuum cleaning",
17: "ironing",
18: "folding laundry",
19: "house cleaning",
20: "playing soccer",
24: "rope jumping",
}
class PAMAP2Dataset(Dataset):
# source: https://github.com/andreasKyratzis/PAMAP2-Physical-Activity-Monitoring-Data-Analysis-and-ML/blob/master/pamap2.ipynb
def _data_cleaning(self, dataCollection):
dataCollection = dataCollection.drop(
[
"handOrientation1",
"handOrientation2",
"handOrientation3",
"handOrientation4",
"chestOrientation1",
"chestOrientation2",
"chestOrientation3",
"chestOrientation4",
"ankleOrientation1",
"ankleOrientation2",
"ankleOrientation3",
"ankleOrientation4",
],
axis=1,
) # removal of orientation columns as they are not needed
dataCollection = dataCollection.drop(
dataCollection[dataCollection.activityID == 0].index
) # removal of any row of activity 0 as it is transient activity which it is not used
dataCollection = dataCollection.apply(
pd.to_numeric, errors="coerce"
) # removal of non numeric data in cells
dataCollection = dataCollection.interpolate() # removal of any remaining NaN value cells by constructing new data points in known set of data points
return dataCollection
def _load_data(self, list_of_files):
# Load data
ensure_pamap2_data()
colNames = ["timestamp", "activityID", "heartrate"]
IMUhand = [
"handTemperature",
"handAcc16_1",
"handAcc16_2",
"handAcc16_3",
"handAcc6_1",
"handAcc6_2",
"handAcc6_3",
"handGyro1",
"handGyro2",
"handGyro3",
"handMagne1",
"handMagne2",
"handMagne3",
"handOrientation1",
"handOrientation2",
"handOrientation3",
"handOrientation4",
]
IMUchest = [
"chestTemperature",
"chestAcc16_1",
"chestAcc16_2",
"chestAcc16_3",
"chestAcc6_1",
"chestAcc6_2",
"chestAcc6_3",
"chestGyro1",
"chestGyro2",
"chestGyro3",
"chestMagne1",
"chestMagne2",
"chestMagne3",
"chestOrientation1",
"chestOrientation2",
"chestOrientation3",
"chestOrientation4",
]
IMUankle = [
"ankleTemperature",
"ankleAcc16_1",
"ankleAcc16_2",
"ankleAcc16_3",
"ankleAcc6_1",
"ankleAcc6_2",
"ankleAcc6_3",
"ankleGyro1",
"ankleGyro2",
"ankleGyro3",
"ankleMagne1",
"ankleMagne2",
"ankleMagne3",
"ankleOrientation1",
"ankleOrientation2",
"ankleOrientation3",
"ankleOrientation4",
]
columns = colNames + IMUhand + IMUchest + IMUankle # all columns in one list
dataCollection = pd.DataFrame()
for file in list_of_files:
procData = pd.read_table(file, header=None, sep=r"\s+")
procData.columns = columns
procData["subject_id"] = int(file[-5])
dataCollection = pd.concat([dataCollection, procData], ignore_index=True)
dataCollection.reset_index(drop=True, inplace=True)
dataCol = self._data_cleaning(dataCollection)
dataCol.reset_index(drop=True, inplace=True)
for i in range(0, 4):
dataCol.loc[i, "heartrate"] = 100
dataCol["activityID"] = dataCol["activityID"].map(ACTIVITIY_ID_DICT)
return dataCol
def __init__(self, list_of_files):
super().__init__()
self.df = self._load_data(list_of_files)
# create 3-second windows and store them as tensors + labels
self.time_series, self.labels = self._make_windows(
window_size="3s", min_pct=0.5
)
def _make_windows(self, window_size, min_pct=0.5):
"""
Returns:
windows: list of numpy arrays of shape (n_features, n_steps)
labels : list of activity labels (the mode of each window)
Drops any window whose modal activity < min_pct of that window's rows,
and only ever groups rows from the same subject.
"""
# 1) copy & timestamp → datetime → index
df = self.df.copy()
df["timestamp"] = pd.to_datetime(df["timestamp"], unit="s")
df = df.set_index("timestamp")
# 2) define which columns are features (everything except label & subject_id)
feature_cols = df.columns.drop(["activityID"])
windows = []
labels = []
# 3) first split by subject_id so no window can span subjects
for subject, df_sub in df.groupby("subject_id"):
# align your 2‑minute bins to this subject’s first timestamp
origin = df_sub.index[0]
for window_start, win in df_sub.resample(window_size, origin=origin):
if win.empty:
continue
# 4) find most common activity in this window
mode_ser = win["activityID"].mode()
if mode_ser.empty:
continue
mode = mode_ser.iloc[0]
# 5) check that it covers at least min_pct of the rows
if (win["activityID"] == mode).sum() < min_pct * len(win):
continue
# 6) store the **transposed** feature‑array + label
# now the shape is (n_features, n_steps)
ts_dict = {col: win[col].values for col in feature_cols}
windows.append(ts_dict)
labels.append(mode)
return windows, labels
def __len__(self):
# now based on windows, not raw rows
return len(self.time_series)
def __getitem__(self, idx):
# returns (n_steps × n_features array, activity string)
return {"time_series": self.time_series[idx], "label": self.labels[idx]}
if __name__ == "__main__":
dataset = PAMAP2Dataset()
for data_point in dataset:
window = data_point["time_series"]
label = data_point["label"]
print(f"{window}, {label}")