.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/wba/_01_assembling_wbs.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_wba__01_assembling_wbs.py: Assembling WBs ============== An important part of the Mobilise-D pipeline is that we output WBs based on a fixed set of definitions. These definitions are build based on a consensus process within the Mobilise-D consortium [1]_ and additional normative data from the literature to define realistic ranges for stride and WB level parameters. To support the process of creating WBs based on these and further custom rules, we provide a framework of dynamic rule objects that can be adjusted and combined and then used to create WBs from a list of strides. This works in 3 steps: 1. First, we filter the list of strides based on the stride-level rules. 2. Second, we iterate through the remaining list of strides and add them to a WB, until we reach a "Termination Criterion". 3. The WBs found in this way are then finally filtered based on WB-level rules. .. [1] Kluge F, Del Din S, Cereatti A, Gaßner H, Hansen C, Helbostad JL, et al. (2021) Consensus based framework for digital mobility monitoring. PLoS ONE 16(8): e0256541. https://doi.org/10.1371/journal.pone.0256541 .. GENERATED FROM PYTHON SOURCE LINES 22-24 .. code-block:: default # TODO: Update the example with real stride values and rules .. GENERATED FROM PYTHON SOURCE LINES 25-33 Step 1: Stride Selection ------------------------ Stride selection is a relatively simple process. Each stride is defined by its start and end time and a set of parameters. Stride-level rules are basically just threshold rules for these parameters or the duration of the stride. Let's start by creating a list of strides with dummy values. We specifically create list of "left" and "right" strides and combine them at the end. .. GENERATED FROM PYTHON SOURCE LINES 33-82 .. code-block:: default from itertools import count import matplotlib.pyplot as plt import numpy as np import pandas as pd id_counter = count(1) def window(start, end, **parameter): parameter = parameter or {} parameter = {**parameter, "duration": end - start} return dict(s_id=next(id_counter), start=start, end=end, **parameter) def naive_stride_list(start, stop, duration, foot=None, **paras): """A window list full of identical strides.""" x = np.arange(start, stop + duration, duration, dtype="int64") start_end = zip(x[:-1], x[1:]) return pd.DataFrame.from_records( [ window(start=s, end=e, foot=foot, duration=duration, **paras) for s, e in start_end ] ).set_index("s_id") stride_list = [ naive_stride_list(0, 5000, 100, foot="left"), naive_stride_list(50, 5050, 100, foot="right"), naive_stride_list(5000, 6020, 60, foot="left"), naive_stride_list(5050, 6070, 60, foot="right"), naive_stride_list(6020, 8000, 90, foot="left"), naive_stride_list(6070, 8050, 90, foot="right"), ] stride_list = pd.concat(stride_list).sort_values("start") # We reset the stride ids to have them in ascending order. stride_list = stride_list.reset_index(drop=True).rename_axis(index="s_id") stride_list.index += 1 # We add some additional parameters, we can use to filter later on. large_sl_ids = [10, 11, 12, 13, 14, 18, 19, 20, 21, 56, 90, 91, 121, 122, 176] stride_list["stride_length"] = 1 stride_list.loc[stride_list.index[large_sl_ids], "stride_length"] = 2 stride_list .. raw:: html
start end foot duration stride_length
s_id
1 0 100 left 100 1
2 50 150 right 100 1
3 100 200 left 100 1
4 150 250 right 100 1
5 200 300 left 100 1
... ... ... ... ... ...
174 7780 7870 right 90 1
175 7820 7910 left 90 1
176 7870 7960 right 90 1
177 7910 8000 left 90 2
178 7960 8050 right 90 1

178 rows × 5 columns



.. GENERATED FROM PYTHON SOURCE LINES 83-92 We can filter the stride list above based on a set of rules. We start with some simple rules to demonstrate the process. All rules must be subclasses of :class:`~mobgap.wba.BaseIntervalCriteria`. At the moment we have implemented :class:`~mobgap.wba.IntervalParameterCriteria` and :class:`~mobgap.wba.IntervalDurationCriteria`. But you could implement custom subclasses, if you see a need for it. Here we just implement a simple rule that filters strides based on their stride length for now. With the thresholds, all strides, we marked as "large" above should be filtered out. .. GENERATED FROM PYTHON SOURCE LINES 92-103 .. code-block:: default from mobgap.wba import IntervalParameterCriteria rules = [ ( "sl_thres", IntervalParameterCriteria( "stride_length", lower_threshold=0.5, upper_threshold=1.5 ), ) ] .. GENERATED FROM PYTHON SOURCE LINES 104-105 We can now use these rules to filter the stride list. .. GENERATED FROM PYTHON SOURCE LINES 105-113 .. code-block:: default from mobgap.wba import StrideSelection stride_selection = StrideSelection(rules) stride_selection.filter(stride_list, sampling_rate_hz=1) filtered_stride_list = stride_selection.filtered_stride_list_ filtered_stride_list .. raw:: html
start end foot duration stride_length
s_id
1 0 100 left 100 1
2 50 150 right 100 1
3 100 200 left 100 1
4 150 250 right 100 1
5 200 300 left 100 1
... ... ... ... ... ...
173 7730 7820 left 90 1
174 7780 7870 right 90 1
175 7820 7910 left 90 1
176 7870 7960 right 90 1
178 7960 8050 right 90 1

163 rows × 5 columns



.. GENERATED FROM PYTHON SOURCE LINES 114-116 .. code-block:: default filtered_stride_list["stride_length"].unique() .. rst-class:: sphx-glr-script-out .. code-block:: none array([1]) .. GENERATED FROM PYTHON SOURCE LINES 117-126 As we can see all the strides above the threshold were filtered out. Let's make this a little more complicated and add a second rule that filters strides based on their duration. This could either be done by a second rule targeting the parameter `duration` or by using the :class:`~mobgap.wba.IntervalDurationCriteria`, which recalculates the duration of the stride based on the `start` and `end` columns. We use the latter here. The thresholds we use here should filter out all the strides from above with a duration of 60 .. GENERATED FROM PYTHON SOURCE LINES 126-141 .. code-block:: default from mobgap.wba import IntervalDurationCriteria rules.append( ( "dur_thres", IntervalDurationCriteria(min_duration_s=80, max_duration_s=120), ) ) stride_selection = StrideSelection(rules) stride_selection.filter(stride_list, sampling_rate_hz=1) filtered_stride_list = stride_selection.filtered_stride_list_ filtered_stride_list .. raw:: html
start end foot duration stride_length
s_id
1 0 100 left 100 1
2 50 150 right 100 1
3 100 200 left 100 1
4 150 250 right 100 1
5 200 300 left 100 1
... ... ... ... ... ...
173 7730 7820 left 90 1
174 7780 7870 right 90 1
175 7820 7910 left 90 1
176 7870 7960 right 90 1
178 7960 8050 right 90 1

131 rows × 5 columns



.. GENERATED FROM PYTHON SOURCE LINES 142-144 .. code-block:: default filtered_stride_list["duration"].unique() .. rst-class:: sphx-glr-script-out .. code-block:: none array([100, 90]) .. GENERATED FROM PYTHON SOURCE LINES 145-146 We can also explicitly inspect which strides are filtered out. .. GENERATED FROM PYTHON SOURCE LINES 146-148 .. code-block:: default stride_selection.excluded_stride_list_ .. raw:: html
start end foot duration stride_length
s_id
11 500 600 left 100 2
12 550 650 right 100 2
13 600 700 left 100 2
14 650 750 right 100 2
15 700 800 left 100 2
19 900 1000 left 100 2
20 950 1050 right 100 2
21 1000 1100 left 100 2
22 1050 1150 right 100 2
57 2800 2900 left 100 2
91 4500 4600 left 100 2
92 4550 4650 right 100 2
101 5000 5060 left 60 1
102 5050 5110 right 60 1
103 5060 5120 left 60 1
104 5110 5170 right 60 1
105 5120 5180 left 60 1
106 5170 5230 right 60 1
107 5180 5240 left 60 1
108 5230 5290 right 60 1
109 5240 5300 left 60 1
110 5290 5350 right 60 1
111 5300 5360 left 60 1
112 5350 5410 right 60 1
113 5360 5420 left 60 1
114 5410 5470 right 60 1
115 5420 5480 left 60 1
116 5470 5530 right 60 1
117 5480 5540 left 60 1
118 5530 5590 right 60 1
119 5540 5600 left 60 1
120 5590 5650 right 60 1
121 5600 5660 left 60 1
122 5650 5710 right 60 2
123 5660 5720 left 60 2
124 5710 5770 right 60 1
125 5720 5780 left 60 1
126 5770 5830 right 60 1
127 5780 5840 left 60 1
128 5830 5890 right 60 1
129 5840 5900 left 60 1
130 5890 5950 right 60 1
131 5900 5960 left 60 1
132 5950 6010 right 60 1
133 5960 6020 left 60 1
134 6010 6070 right 60 1
177 7910 8000 left 90 2


.. GENERATED FROM PYTHON SOURCE LINES 149-151 And even see which rule filtered them out. Note, that only the first rule that filtered the stride is shown. .. GENERATED FROM PYTHON SOURCE LINES 151-155 .. code-block:: default stride_selection.excluded_stride_list_.merge( stride_selection.exclusion_reasons_, left_index=True, right_index=True ) .. raw:: html
start end foot duration stride_length rule_name rule_obj
s_id
11 500 600 left 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
12 550 650 right 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
13 600 700 left 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
14 650 750 right 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
15 700 800 left 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
19 900 1000 left 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
20 950 1050 right 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
21 1000 1100 left 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
22 1050 1150 right 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
57 2800 2900 left 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
91 4500 4600 left 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
92 4550 4650 right 100 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
101 5000 5060 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
102 5050 5110 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
103 5060 5120 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
104 5110 5170 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
105 5120 5180 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
106 5170 5230 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
107 5180 5240 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
108 5230 5290 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
109 5240 5300 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
110 5290 5350 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
111 5300 5360 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
112 5350 5410 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
113 5360 5420 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
114 5410 5470 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
115 5420 5480 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
116 5470 5530 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
117 5480 5540 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
118 5530 5590 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
119 5540 5600 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
120 5590 5650 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
121 5600 5660 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
122 5650 5710 right 60 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
123 5660 5720 left 60 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...
124 5710 5770 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
125 5720 5780 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
126 5770 5830 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
127 5780 5840 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
128 5830 5890 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
129 5840 5900 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
130 5890 5950 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
131 5900 5960 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
132 5950 6010 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
133 5960 6020 left 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
134 6010 6070 right 60 1 dur_thres IntervalDurationCriteria(inclusive=(False, Tru...
177 7910 8000 left 90 2 sl_thres IntervalParameterCriteria(inclusive=(False, Tr...


.. GENERATED FROM PYTHON SOURCE LINES 156-175 Step 2,3: WB Assembly --------------------- Now that we have a list of strides that we consider valid, we want to group them into WBs. For this we define a set of rules that define when a WB should be terminated and if a preliminary WB fulfills the criteria to be a valid WB. These rules are subclasses of :class:`~mobgap.wba.BaseWbCriteria` and each rule can act as both a termination criterion and an inclusion criterion. Have a look at the documentation of the specific rules for more details. For more details on how the rules are applied, have a look at the documentation of the :class:`~mobgap.wba.WbAssembly`. For this example, we use two rules: 1. :class:`~mobgap.wba.MaxBreakCriteria`: This rule terminates a WB if the time between two strides is larger than a given threshold. It acts as a termination criterion. 2. :class:`~mobgap.wba.NStridesCriteria`: This rule excludes preliminary WBs that have less than a given number of strides. It acts as an inclusion criterion. .. GENERATED FROM PYTHON SOURCE LINES 175-193 .. code-block:: default from mobgap.wba import MaxBreakCriteria, NStridesCriteria, WbAssembly rules = [ ( "max_break", MaxBreakCriteria( max_break_s=10, remove_last_ic="per_foot", consider_end_as_break=True, ), ), ("min_strides", NStridesCriteria(min_strides=5)), ] wb_assembly = WbAssembly(rules) # Note, that we use the filtered stride list from above. wb_assembly.assemble(filtered_stride_list, sampling_rate_hz=1) .. rst-class:: sphx-glr-script-out .. code-block:: none WbAssembly(rules=[('max_break', MaxBreakCriteria(consider_end_as_break=True, max_break_s=10, remove_last_ic='per_foot')), ('min_strides', NStridesCriteria(min_strides=5, min_strides_left=None, min_strides_right=None))]) .. GENERATED FROM PYTHON SOURCE LINES 194-202 The wb_assembly object now contains a grouping of each stride to a WB. Depending on how we want to further process the data, we can either use the `wbs_` attribute, which is a dictionary mapping a WB id to a list of strides, or the `annotated_stride_list_` attribute, which is a copy of the stride list containing an additional column `wb_id` that contains the id of the WB the stride belongs to. Note, that both outputs only contain the strides that belong to a final WB. Strides belonging to a WB that was ultimately filtered out, or never belonged to a WB in the first place are not included. They can be accessed via the `excluded_stride_list_` and `excluded_wbs` attributes. .. GENERATED FROM PYTHON SOURCE LINES 202-204 .. code-block:: default wb_assembly.annotated_stride_list_ .. raw:: html
start end foot duration stride_length
wb_id s_id
0 1 0 100 left 100 1
2 50 150 right 100 1
3 100 200 left 100 1
4 150 250 right 100 1
5 200 300 left 100 1
... ... ... ... ... ... ...
3 172 7690 7780 right 90 1
173 7730 7820 left 90 1
174 7780 7870 right 90 1
175 7820 7910 left 90 1
176 7870 7960 right 90 1

121 rows × 5 columns



.. GENERATED FROM PYTHON SOURCE LINES 205-207 .. code-block:: default print(f"The method identified {len(wb_assembly.wbs_)} WBs.") .. rst-class:: sphx-glr-script-out .. code-block:: none The method identified 4 WBs. .. GENERATED FROM PYTHON SOURCE LINES 208-209 We can also get an idea of how the final results looks, by plotting the wba outputs. .. GENERATED FROM PYTHON SOURCE LINES 209-213 .. code-block:: default from mobgap.wba.plot import plot_wba_results plot_wba_results(wb_assembly, stride_selection=stride_selection) plt.show() .. image-sg:: /auto_examples/wba/images/sphx_glr__01_assembling_wbs_001.png :alt: 01 assembling wbs :srcset: /auto_examples/wba/images/sphx_glr__01_assembling_wbs_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 2.612 seconds) **Estimated memory usage:** 9 MB .. _sphx_glr_download_auto_examples_wba__01_assembling_wbs.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: _01_assembling_wbs.py <_01_assembling_wbs.py>` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: _01_assembling_wbs.ipynb <_01_assembling_wbs.ipynb>` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_