Shin Algo#

This example shows how to use the improved Shin algorithm and some examples on how the results compare to the original matlab implementation.

import pandas as pd
from matplotlib import pyplot as plt
from mobgap.data import LabExampleDataset
from mobgap.initial_contacts import IcdShinImproved

Loading data#

Note

More infos about data loading can be found in the data loading example.

We load example data from the lab dataset together with the INDIP reference system. We will use the INDIP output for initial contacts (“ic”) as ground truth.

from mobgap.utils.conversions import to_body_frame

example_data = LabExampleDataset(
    reference_system="INDIP", reference_para_level="wb"
)

single_test = example_data.get_subset(
    cohort="HA", participant_id="001", test="Test11", trial="Trial1"
)
imu_data = to_body_frame(single_test.data_ss)
reference_wbs = single_test.reference_parameters_.wb_list

sampling_rate_hz = single_test.sampling_rate_hz
ref_ics = single_test.reference_parameters_.ic_list

reference_wbs
start end n_strides duration_s length_m avg_walking_speed_mps avg_cadence_spm avg_stride_length_m termination_reason
wb_id
0 632 988 5 3.55 3.428989 0.975373 104.069084 1.124391 Pause
1 2864 3325 4 4.60 1.452572 0.411857 81.296475 0.581029 Pause
2 3853 5085 16 12.31 7.044042 0.617801 89.246331 0.838960 Pause
3 7641 8621 12 9.79 4.396574 0.510108 94.370318 0.645176 Pause
4 9451 9932 6 4.80 3.545277 0.755728 88.778698 1.021695 Pause
5 11989 12517 6 5.27 3.514735 0.880632 95.832693 1.021576 Pause


Applying the algorithm#

Below we apply the shin algorithm to a lab trial. We will use the GsIterator to iterate over the gait sequences and apply the algorithm to each wb.

ic
wb_id step_id
0 0 634
1 695
2 758
3 814
4 873
5 926
1 0 2926
1 2991
2 3061
3 3113
4 3182
5 3257
6 3321
2 0 3909
1 3978
2 4073
3 4139
4 4209
5 4281
6 4340
7 4419
8 4488
9 4555
10 4634
11 4692
12 4754
13 4821
14 4861
15 4963
16 5042
3 0 7732
1 7782
2 7842
3 7903
4 7983
5 8090
6 8164
7 8232
8 8276
9 8337
10 8398
11 8463
12 8537
13 8612
4 0 9462
1 9529
2 9593
3 9658
4 9724
5 9792
6 9860
5 0 12042
1 12100
2 12156
3 12211
4 12272
5 12353
6 12457


Matlab Outputs#

To check if the algorithm was implemented correctly, we compare the results to the matlab implementation.

import json

from mobgap import PACKAGE_ROOT


def load_matlab_output(datapoint):
    p = datapoint.group_label
    with (
        PACKAGE_ROOT.parent
        / f"example_data/original_results/icd_shin_improved/lab/{p.cohort}/{p.participant_id}/SD_Output.json"
    ).open() as f:
        original_results = json.load(f)["SD_Output"][p.time_measure][p.test][
            p.trial
        ]["SU"]["LowerBack"]["SD"]

    if not isinstance(original_results, list):
        original_results = [original_results]

    ics = {}
    for i, gs in enumerate(original_results, start=1):
        ics[i] = pd.DataFrame({"ic": gs["IC"]}).rename_axis(index="step_id")

    return (
        pd.concat(ics, names=["wb_id", ics[1].index.name])
        * datapoint.sampling_rate_hz
    ).astype("int64")


detected_ics_matlab = load_matlab_output(single_test)
detected_ics_matlab
ic
wb_id step_id
1 0 639
1 701
2 765
3 821
4 878
5 933
2 0 2933
1 2997
2 3067
3 3120
4 3186
5 3262
3 0 3914
1 3983
2 4079
3 4146
4 4214
5 4286
6 4346
7 4424
8 4494
9 4560
10 4638
11 4698
12 4760
13 4826
14 4866
15 4968
16 5046
4 0 7738
1 7788
2 7848
3 7910
4 7990
5 8096
6 8170
7 8238
8 8282
9 8342
10 8404
11 8468
12 8542
13 8618
5 0 9466
1 9533
2 9597
3 9664
4 9730
5 9797
6 9866
6 0 12048
1 12106
2 12162
3 12218
4 12278
5 12360
6 12464


Plotting the results#

With that we can compare the python, matlab and ground truth results. We zoom in into one of the gait sequences to better see the output.

We can make a couple of main observations:

  1. The python version finds the same ICs as the matlab version, but wil a small shift to the left (around 5-10 samples/50-100 ms). This is likely due to some differences in the downsampling process.

  2. Compared to the ground truth reference, both versions detect the IC too early most of the time.

  3. Both algorithms can not detect the first IC of the gait sequence. However, this is expected, as per definition, this first IC marks the start of the WB in the reference system. Hence, there are no samples before that point the algorithm can use to detect the IC.

imu_data.reset_index(drop=True).plot(y="acc_is")

plt.plot(
    ref_ics["ic"], imu_data["acc_is"].iloc[ref_ics["ic"]], "o", label="ref"
)
plt.plot(
    detected_ics["ic"],
    imu_data["acc_is"].iloc[detected_ics["ic"]],
    "x",
    label="shin_algo_py",
)
plt.plot(
    detected_ics_matlab["ic"],
    imu_data["acc_is"].iloc[detected_ics_matlab["ic"]],
    "+",
    label="shin_algo_matlab",
)
plt.xlim(reference_wbs.iloc[2]["start"] - 50, reference_wbs.iloc[2]["end"] + 50)
plt.legend()
plt.show()
02 shin algo

Evaluation of the algorithm against a reference#

To quantify how the Python output compares to the reference labels, we are providing a range of evaluation functions. See the example on ICD evaluation for more details.

Total running time of the script: (0 minutes 1.227 seconds)

Estimated memory usage: 9 MB

Gallery generated by Sphinx-Gallery