Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inverse predictions #74

Merged
merged 2 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
*.ipynb filter=nbstripout
*.zpln filter=nbstripout
*.ipynb diff=ipynb
* text=auto
4 changes: 2 additions & 2 deletions docs/notebooks/gait/gait_analysis.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"source": [
"import os\n",
"from paradigma.preprocessing_config import IMUPreprocessingConfig\n",
"from paradigma.gait.gait_analysis import extract_gait_features_io, detect_gait_io, extract_arm_activity_features_io, detect_other_arm_activities_io, quantify_arm_swing_io\n",
"from paradigma.gait.gait_analysis import extract_gait_features_io, detect_gait_io, extract_arm_activity_features_io, filter_gait_io, quantify_arm_swing_io\n",
"from paradigma.gait.gait_analysis_config import GaitFeatureExtractionConfig, GaitDetectionConfig, ArmActivityFeatureExtractionConfig, FilteringGaitConfig, ArmSwingQuantificationConfig\n",
"from paradigma.imu_preprocessing import preprocess_imu_data_io"
]
Expand Down Expand Up @@ -126,7 +126,7 @@
"outputs": [],
"source": [
"config = FilteringGaitConfig()\n",
"detect_other_arm_activities_io(path_to_extracted_features, path_to_predictions, path_to_classifier, config)"
"filter_gait_io(path_to_extracted_features, path_to_predictions, path_to_classifier, config)"
]
},
{
Expand Down
4 changes: 2 additions & 2 deletions src/paradigma/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ class DataColumns():
GRAV_ACCELEROMETER_Z : str = "grav_accelerometer_z"
PRED_GAIT_PROBA: str = "pred_gait_proba"
PRED_GAIT : str = "pred_gait"
PRED_OTHER_ARM_ACTIVITY_PROBA: str = "pred_other_arm_activity_proba"
PRED_OTHER_ARM_ACTIVITY : str = "pred_other_arm_activity"
PRED_NO_OTHER_ARM_ACTIVITY_PROBA: str = "pred_no_other_arm_activity_proba"
PRED_NO_OTHER_ARM_ACTIVITY : str = "pred_no_other_arm_activity"
ANGLE : str = "angle"
ANGLE_SMOOTH : str = "angle_smooth"
VELOCITY : str = "velocity"
Expand Down
16 changes: 8 additions & 8 deletions src/paradigma/gait/gait_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ def extract_arm_activity_features_io(input_path: Union[str, Path], output_path:
write_df_data(metadata_time, metadata_samples, output_path, 'arm_activity_meta.json', df_windowed)


def detect_other_arm_activities(df: pd.DataFrame, config: FilteringGaitConfig, clf: Union[LogisticRegression, RandomForestClassifier]) -> pd.DataFrame:
def filter_gait(df: pd.DataFrame, config: FilteringGaitConfig, clf: Union[LogisticRegression, RandomForestClassifier]) -> pd.DataFrame:

# Prepare the data
clf.feature_names_in_ = ['std_norm_acc'] + [f'{x}_power_below_gait' for x in config.l_accelerometer_cols] + \
Expand All @@ -302,25 +302,25 @@ def detect_other_arm_activities(df: pd.DataFrame, config: FilteringGaitConfig, c
X = df.loc[:, clf.feature_names_in_]

# Make prediction
df[DataColumns.PRED_OTHER_ARM_ACTIVITY_PROBA] = clf.predict_proba(X)[:, 1]
df[DataColumns.PRED_NO_OTHER_ARM_ACTIVITY_PROBA] = clf.predict_proba(X)[:, 1]

return df

def detect_other_arm_activities_io(input_path: Union[str, Path], output_path: Union[str, Path], path_to_classifier_input: Union[str, Path], config: FilteringGaitConfig) -> None:
def filter_gait_io(input_path: Union[str, Path], output_path: Union[str, Path], path_to_classifier_input: Union[str, Path], config: FilteringGaitConfig) -> None:
# Load the data
metadata_time, metadata_samples = read_metadata(input_path, config.meta_filename, config.time_filename, config.values_filename)
df = tsdf.load_dataframe_from_binaries([metadata_time, metadata_samples], tsdf.constants.ConcatenationType.columns)

# Load the classifier
clf = pd.read_pickle(os.path.join(path_to_classifier_input, 'classifiers', config.classifier_file_name))

df = detect_other_arm_activities(df, config, clf)
df = filter_gait(df, config, clf)

# Prepare the metadata
metadata_samples.file_name = 'arm_activity_values.bin'
metadata_time.file_name = 'arm_activity_time.bin'

metadata_samples.channels = [DataColumns.PRED_OTHER_ARM_ACTIVITY_PROBA]
metadata_samples.channels = [DataColumns.PRED_NO_OTHER_ARM_ACTIVITY_PROBA]
metadata_samples.units = ['probability']

metadata_time.channels = [DataColumns.TIME]
Expand All @@ -332,11 +332,11 @@ def detect_other_arm_activities_io(input_path: Union[str, Path], output_path: Un
def quantify_arm_swing(df: pd.DataFrame, config: ArmSwingQuantificationConfig) -> pd.DataFrame:

# temporarily for testing: manually determine predictions
df[DataColumns.PRED_OTHER_ARM_ACTIVITY_PROBA] = np.concatenate([np.repeat([1], df.shape[0]//3), np.repeat([0], df.shape[0]//3), np.repeat([1], df.shape[0] - 2*df.shape[0]//3)], axis=0)
df[DataColumns.PRED_NO_OTHER_ARM_ACTIVITY_PROBA] = np.concatenate([np.repeat([1], df.shape[0]//3), np.repeat([0], df.shape[0]//3), np.repeat([1], df.shape[0] - 2*df.shape[0]//3)], axis=0)

# keep only predicted arm swing
# TODO: Aggregate overlapping windows for probabilities
df_filtered = df.loc[df[DataColumns.PRED_OTHER_ARM_ACTIVITY_PROBA]>=0.5].copy().reset_index(drop=True)
df_filtered = df.loc[df[DataColumns.PRED_NO_OTHER_ARM_ACTIVITY_PROBA]>=0.5].copy().reset_index(drop=True)

del df

Expand Down Expand Up @@ -398,7 +398,7 @@ def quantify_arm_swing_io(path_to_feature_input: Union[str, Path], path_to_predi
df_features = df_features[l_feature_cols]

# Concatenate features and predictions
df = pd.concat([df_features, df_predictions[DataColumns.PRED_OTHER_ARM_ACTIVITY_PROBA]], axis=1)
df = pd.concat([df_features, df_predictions[DataColumns.PRED_NO_OTHER_ARM_ACTIVITY_PROBA]], axis=1)

df_aggregates = quantify_arm_swing(df, config)

Expand Down
4 changes: 2 additions & 2 deletions src/paradigma/gait/gait_analysis_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ def __init__(self) -> None:

self.angle_colname = DataColumns.ANGLE
self.velocity_colname = DataColumns.VELOCITY
self.pred_other_arm_activity_proba_colname = DataColumns.PRED_OTHER_ARM_ACTIVITY_PROBA
self.pred_other_arm_activity_colname = DataColumns.PRED_OTHER_ARM_ACTIVITY
self.pred_other_arm_activity_proba_colname = DataColumns.PRED_NO_OTHER_ARM_ACTIVITY_PROBA
self.pred_other_arm_activity_colname = DataColumns.PRED_NO_OTHER_ARM_ACTIVITY

self.window_length_s = 3
self.window_step_size = 0.75
Expand Down
2 changes: 1 addition & 1 deletion tests/data/4.predictions/gait/arm_activity_meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
{
"file_name": "arm_activity_values.bin",
"channels": [
"pred_other_arm_activity_proba"
"pred_no_other_arm_activity_proba"
],
"units": [
"probability"
Expand Down
4 changes: 2 additions & 2 deletions tests/test_gait_analysis.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from pathlib import Path

from paradigma.gait.gait_analysis import detect_other_arm_activities_io, detect_gait_io, extract_arm_activity_features_io, extract_gait_features_io, quantify_arm_swing_io
from paradigma.gait.gait_analysis import filter_gait_io, detect_gait_io, extract_arm_activity_features_io, extract_gait_features_io, quantify_arm_swing_io
from paradigma.gait.gait_analysis_config import FilteringGaitConfig, ArmActivityFeatureExtractionConfig, ArmSwingQuantificationConfig, GaitDetectionConfig, GaitFeatureExtractionConfig
from paradigma.imu_preprocessing import preprocess_imu_data_io
from paradigma.preprocessing_config import IMUPreprocessingConfig
Expand Down Expand Up @@ -109,7 +109,7 @@ def test_5_arm_swing_detection_output(shared_datadir: Path):
tested_output_path = reference_output_path / "test-output"

config = FilteringGaitConfig()
detect_other_arm_activities_io(input_path, tested_output_path, path_to_classifier_input, config)
filter_gait_io(input_path, tested_output_path, path_to_classifier_input, config)
compare_data(reference_output_path, tested_output_path, arm_activity_binaries_pairs)


Expand Down