gaitmap.event_detection.HerzerEventDetection#
- class gaitmap.event_detection.HerzerEventDetection(min_vel_search_win_size_ms: float = 100, mid_swing_peak_prominence: tuple[float, float] | float = 20, mid_swing_n_considered_peaks: int = 3, ic_lowpass_filter: BaseFilter = cf(ButterworthFilter(cutoff_freq_hz=4, filter_type='lowpass', order=1)), memory: Memory | None = None, enforce_consistency: bool = True, detect_only: tuple[str, ...] | None = None)[source]#
Find gait events in the IMU raw signal based on signal characteristics.
HerzerEventDetection uses signal processing approaches to find temporal gait events by searching for characteristic features in the foot-mounted sensor signals. The method was first developed in the context of the Bachelor Thesis by Liv Herzer (2021) under the supervision of Nils Roth [3]. It combines techniques used in Rampp et al. (2014) [1] and Figueiredo et al. (2018) [2] with some original approaches. The particular goial was to create an Event Detection that worked well during level walking and stair ambulation. For more details refer to the
Notessection.- Parameters:
- min_vel_search_win_size_ms
The size of the sliding window for finding the minimum gyroscope energy in ms.
- mid_swing_peak_prominence
The expected min/(min, max) peak prominence of the mid swing peak in the
gyr_mlsignal. This value is passed directly tofind_peaks. The detected mid-swing peak is used to define the search region for the IC- mid_swing_n_considered_peaks
The number of peaks that should be considered in the initial search for the mid-swing. In particular for stair climbing, multiple prominent peaks might occure. The search algorithm consideres the n-most prominent and takes the one occuring first in the signal as the mid-swing. The detected mid-swing peak is used to define the search region for the IC
- ic_lowpass_filter
An instance of a Filter-transform (e.g.
ButterworthFilter) that will be applied to the acc_pa signal before calculating the derivative when detecting the IC. While not enforced, this should be a lowpass filter to ensure that the results are as expected.- memory
An optional
joblib.Memoryobject that can be provided to cache the detection of all events.- enforce_consistency
An optional bool that can be set to False if you wish to disable postprocessing (see Notes section for more information).
- detect_only
An optional tuple of strings that can be used to only detect a subset of events. By default, all events (“ic”, “tc”, “min_vel”) are detected. If
min_velis not detected, themin_vel_event_list_output will not be available. If “ic” is not detected, thepre_icwill also not be available in the output.
- Other Parameters:
- data
The data passed to the
detectmethod.- sampling_rate_hz
The sampling rate of the data
- stride_list
A list of strides provided by a stride segmentation method. The stride list is expected to have no gaps between subsequent strides. That means for subsequent strides the end sample of one stride should be the start sample of the next stride.
- Attributes:
- min_vel_event_list_A stride list or dictionary with such values
The result of the
detectmethod holding all temporal gait events and start / end of all strides. The stride borders for the stride_events are aligned with the min_vel samples. Hence, the start sample of each stride corresponds to the min_vel sample of that stride and the end sample corresponds to the min_vel sample of the subsequent stride. Strides for which no valid events could be found are removed. Additional strides might have been removed due to the conversion from segmented to min_vel strides.- segmented_event_list_A stride list or dictionary with such values
The result of the
detectmethod holding all temporal gait events and start / end of all strides. This version of the results has the same stride borders than the inputstride_listand has additional columns for all the detected events. Strides for which no valid events could be found are removed.
Notes
This methods implements the detection of three events:
- terminal contact (
tc), also called toe-off (TO): At
tcthe movement of the ankle joint changes from a plantar flexion to a dorsal extension in the sagittal plane.tcoccurs roughly at the poit of the most rapid plantar flexion of the foot in the saggital plane. This corresponds to a minimum in thegyr_mlsignal [2].- initial contact (
ic), also called heel strike (HS): At
icthe foot decelerates rapidly when the foot hits the ground. However, looking simply for the point of highest deacceleration is not always robust. Therefore, this algorithm looks for the fastest change in acceleration. Specifically we are looking for the maximum in the derivative of the low-pass filtered acc_pa signal in the region after the swing phase. This usualy corresponds to a point closely after the minimum in the normal acc_pa signal. The apprach of looking at the derivative was inspired by [2]. Note, that in the original bachelors thesis, the minimum of the derviative was searched. This is because the coordinate axis definition was different (corresponding to [1]). To make sure that the correct peak is detected, as search window from the first prominent maximum of gyr_ml ( swing phase) and 70% of the stride duration is defined. The search area is further narrowed down to be between the maximum of the low-pass filteredacc_pasignal and the steepest positive slope of thegyr_mlsignal. After that the low-pass filteredacc_pasignal derivative is searched for a maximum in this area.- minimal velocity (
min_vel_), originally called mid stance (MS) in the paper [1]: At
min_velthe foot has the lowest velocity. It is defined to be the middle of the window with the lowest energy in all axes of the gyr signal. The default window size is set to 100 ms with 50 % overlap. The window size can be adjusted via themin_vel_search_win_size_msparameter. This approach is identical to [1].
The
detectmethod provides a stride listmin_vel_event_listwith the gait events mentioned above and additionallystartandendof each stride, which are aligned to themin_velsamples. The start sample of each stride corresponds to the min_vel sample of that stride and the end sample corresponds to the min_vel sample of the subsequent stride. Furthermore, themin_vel_event_listlist provides thepre_icwhich is the ic event of the previous stride in the stride list. This function should NOT be used, since the detection of the min_vel gait events has not been validated for stair ambulation. Please refer to thesegmented_event_list_instead.The
HerzerEventDetectionincludes a consistency check that is enabled by default. The gait events within one stride provided by thestride_listmust occur in the expected order. Any stride where the gait events are detected in a different order or are not detected at all is dropped! For more infos on this seeenforce_stride_list_consistency. If you wish to disable this consistency check, setenforce_consistencyto False. In this case, the attributemin_vel_event_list_will not be set, but you can usesegmented_event_list_to get all detected events for the exact stride list that was used as input. Note, that this list might contain NaN for some events.Furthermore, during the conversion from the segmented stride list to the “min_vel” stride list, breaks in continuous gait sequences (with continuous subsequent strides according to the
stride_list) are detected and the first (segmented) stride of each sequence is dropped. This is required due to the shift of stride borders between thestride_listand themin_vel_event_list. Thus, the first segmented stride of a continuous sequence only provides a pre_ic and a min_vel sample for the first stride in themin_vel_event_list. Therefore, themin_vel_event_listlist has one stride less per gait sequence than thesegmented_stride_list.Further information regarding the coordinate system can be found here and regarding the different types of strides can be found here.
- Differences to original Implementation (Bachelorthesis by Liv Herzer [3]):
This implementation does not use an adaptive cut-off for the low-pass filter.
Instead of iteratively lowering the detection threshold to find the maximum of the swing phase, we simply use
find_peaksto search for the peak with the highest prominence that is still over some baseline threshold.The coordinate system that was considered in the BA was different to the gaitmap bodyframe. This means the acc_pa axis was upside down.
[1] (1,2,3,4)Rampp, A., Barth, J., Schülein, S., Gaßmann, K. G., Klucken, J., & Eskofier, B. M. (2014). Inertial sensor-based stride parameter calculation from gait sequences in geriatric patients. IEEE transactions on biomedical engineering, 62(4), 1089-1097.. https://doi.org/10.1109/TBME.2014.2368211
[2] (1,2,3)J. Figueiredo, P. Félix, L. Costa, J. C. Moreno and C. P. Santos, “Gait Event Detection in Controlled and Real-Life Situations: Repeated Measures From Healthy Subjects,” in IEEE Transactions on Neural Systems and Rehabilitation Engineering, vol. 26, no. 10, pp. 1945-1956, Oct. 2018, doi: 10.1109/TNSRE.2018.2868094.
Examples
Get gait events from single sensor signal
>>> event_detection = HerzerEventDetection() >>> event_detection.detect(data=data, stride_list=stride_list, sampling_rate_hz=204.8) >>> event_detection.segmented_event_list_ start end ic tc min_vel s_id 0 48304 48558 48382.0 48304.0 48479.0 1 48558 48788 48668.0 48558.0 48732.0 2 48788 48994 48872.0 48788.0 48932.0 3 48994 49201 49074.0 48994.0 49137.0 4 49201 49422 49287.0 49201.0 49353.0 ... ... ... ... ... ...
Methods
clone()Create a new instance of the class with all parameters copied over.
detect(data, stride_list, *, sampling_rate_hz)Find gait events in data within strides provided by stride_list.
from_json(json_str)Import an gaitmap object from its json representation.
get_params([deep])Get parameters for this algorithm.
set_params(**params)Set the parameters of this Algorithm.
to_json()Export the current object parameters as json.
- __init__(min_vel_search_win_size_ms: float = 100, mid_swing_peak_prominence: tuple[float, float] | float = 20, mid_swing_n_considered_peaks: int = 3, ic_lowpass_filter: BaseFilter = cf(ButterworthFilter(cutoff_freq_hz=4, filter_type='lowpass', order=1)), memory: Memory | None = None, enforce_consistency: bool = True, detect_only: tuple[str, ...] | None = None) None[source]#
- clone() Self[source]#
Create a new instance of the class with all parameters copied over.
This will create a new instance of the class itself and all nested objects
- detect(data: DataFrame | dict[Union[collections.abc.Hashable, str], pandas.core.frame.DataFrame], stride_list: DataFrame | dict[Union[collections.abc.Hashable, str], pandas.core.frame.DataFrame], *, sampling_rate_hz: float) Self[source]#
Find gait events in data within strides provided by stride_list.
- Parameters:
- data
The data set holding the imu raw data
- stride_list
A list of strides provided by a stride segmentation method
- sampling_rate_hz
The sampling rate of the data
- Returns:
- self
The class instance with all result attributes populated
- classmethod from_json(json_str: str) Self[source]#
Import an gaitmap object from its json representation.
For details have a look at the this example.
You can use the
to_jsonmethod of a class to export it as a compatible json string.- Parameters:
- json_str
json formatted string
- get_params(deep: bool = True) dict[str, Any][source]#
Get parameters for this algorithm.
- Parameters:
- deep
Only relevant if object contains nested algorithm objects. If this is the case and deep is True, the params of these nested objects are included in the output using a prefix like
nested_object_name__(Note the two “_” at the end)
- Returns:
- params
Parameter names mapped to their values.