Skip to content

Commit

Permalink
Merge pull request #74 from biomarkersParkinson/inverse_predictions
Browse files Browse the repository at this point in the history
Inverse predictions
  • Loading branch information
nienketimmermans authored Nov 5, 2024
2 parents af4a9cb + 9fee8bf commit dde3a75
Show file tree
Hide file tree
Showing 7 changed files with 18 additions and 17 deletions.
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

0 comments on commit dde3a75

Please sign in to comment.