Skip to content

Commit 6b21752

Browse files
committed
solve another bug
1 parent 1a335d8 commit 6b21752

File tree

2 files changed

+49
-45
lines changed

2 files changed

+49
-45
lines changed

src/paradigma/feature_extraction.py

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -454,54 +454,58 @@ def extract_angle_extremes(
454454
The extracted angle extremes (peaks)
455455
"""
456456
# determine peaks
457-
df[f'{angle_colname}_maxima'] = df.apply(
458-
lambda row: find_peaks(row[angle_colname],
459-
distance=sampling_frequency * 0.6 / row[dominant_frequency_colname],
460-
prominence=2)[0], axis=1
461-
)
462-
df[f'{angle_colname}_minima'] = df.apply(
463-
lambda row: find_peaks([-x for x in row[angle_colname]],
464-
distance=sampling_frequency * 0.6 / row[dominant_frequency_colname],
465-
prominence=2)[0], axis=1
466-
)
457+
df[f'{angle_colname}_maxima'] = df.apply(lambda x: signal.find_peaks(x[angle_colname], distance=sampling_frequency * 0.6 / x[dominant_frequency_colname], prominence=0.5)[0], axis=1)
458+
df[f'{angle_colname}_minima'] = df.apply(lambda x: signal.find_peaks([-x for x in x[angle_colname]], distance=sampling_frequency * 0.6 / x[dominant_frequency_colname], prominence=0.5)[0], axis=1)
467459

468460
df[f'{angle_colname}_new_minima'] = df[f'{angle_colname}_minima'].copy()
469461
df[f'{angle_colname}_new_maxima'] = df[f'{angle_colname}_maxima'].copy()
470462

471-
def refine_extrema(minima, maxima, angle_values):
472-
"""Refine the minima and maxima by removing consecutive points that don't adhere to the rules."""
473-
i_pks = 0
474-
while i_pks < len(minima) - 1 and i_pks < len(maxima):
475-
# Min-min or max-max sequences handling
476-
if minima[i_pks+1] < maxima[i_pks]:
477-
if angle_values[minima[i_pks+1]] < angle_values[minima[i_pks]]:
478-
minima = np.delete(minima, i_pks)
479-
else:
480-
minima = np.delete(minima, i_pks+1)
481-
i_pks -= 1
482-
elif maxima[i_pks] < minima[i_pks]:
483-
if angle_values[maxima[i_pks]] < angle_values[maxima[i_pks-1]]:
484-
maxima = np.delete(maxima, i_pks)
485-
else:
486-
maxima = np.delete(maxima, i_pks-1)
487-
i_pks -= 1
488-
i_pks += 1
489-
return minima, maxima
490-
491-
# Apply refinement to each row
492-
for index, row in df.iterrows():
493-
minima, maxima = refine_extrema(row[f'{angle_colname}_new_minima'], row[f'{angle_colname}_new_maxima'], row[angle_colname])
494-
df.loc[index, f'{angle_colname}_new_minima'] = minima
495-
df.loc[index, f'{angle_colname}_new_maxima'] = maxima
496-
497-
# Ensure scalar values are converted to lists
498-
df[f'{angle_colname}_new_minima'] = df[f'{angle_colname}_new_minima'].apply(lambda x: [x] if isinstance(x, int) else x)
499-
df[f'{angle_colname}_new_maxima'] = df[f'{angle_colname}_new_maxima'].apply(lambda x: [x] if isinstance(x, int) else x)
500-
501-
# Combine and sort minima and maxima
502-
df[f'{angle_colname}_extrema_values'] = df.apply(
503-
lambda row: [row[angle_colname][i] for i in sorted(np.concatenate([row[f'{angle_colname}_new_minima'], row[f'{angle_colname}new_maxima']]))], axis=1
504-
)
463+
for index, _ in df.iterrows():
464+
i_pks = 0 # iterable to keep track of consecutive min-min and max-max versus min-max
465+
n_min = df.loc[index, f'{angle_colname}_new_minima'].size # number of minima in window
466+
n_max = df.loc[index, f'{angle_colname}_new_maxima'].size # number of maxima in window
467+
468+
if n_min > 0 and n_max > 0:
469+
if df.loc[index, f'{angle_colname}_new_maxima'][0] > df.loc[index, f'{angle_colname}_new_minima'][0]: # if first minimum occurs before first maximum, start with minimum
470+
while i_pks < df.loc[index, f'{angle_colname}_new_minima'].size - 1 and i_pks < df.loc[index, f'{angle_colname}_new_maxima'].size: # only continue if there's enough minima and maxima to perform operations
471+
if df.loc[index, f'{angle_colname}_new_minima'][i_pks+1] < df.loc[index, f'{angle_colname}_new_maxima'][i_pks]: # if angle of next minimum comes before the current maxima, we have two minima in a row
472+
if df.loc[index, angle_colname][df.loc[index, f'{angle_colname}_new_minima'][i_pks+1]] < df.loc[index, angle_colname][df.loc[index, f'{angle_colname}_new_minima'][i_pks]]: # if second minimum if smaller than first, keep second
473+
df.at[index, f'{angle_colname}_new_minima'] = np.delete(df.loc[index, f'{angle_colname}_new_minima'], i_pks)
474+
else: # otherwise keep the first
475+
df.at[index, f'{angle_colname}_new_minima'] = np.delete(df.loc[index, f'{angle_colname}_new_minima'], i_pks+1)
476+
i_pks -= 1
477+
if i_pks >= 0 and df.loc[index, f'{angle_colname}_new_minima'][i_pks] > df.loc[index, f'{angle_colname}_new_maxima'][i_pks]:
478+
if df.loc[index, angle_colname][df.loc[index, f'{angle_colname}_new_maxima'][i_pks]] < df.loc[index, angle_colname][df.loc[index, f'{angle_colname}_new_maxima'][i_pks-1]]:
479+
df.at[index, f'{angle_colname}_new_maxima'] = np.delete(df.loc[index, f'{angle_colname}_new_maxima'], i_pks)
480+
else:
481+
df.at[index, f'{angle_colname}_new_maxima'] = np.delete(df.loc[index, f'{angle_colname}_new_maxima'], i_pks-1)
482+
i_pks -= 1
483+
i_pks += 1
484+
485+
elif df.loc[index, f'{angle_colname}_new_maxima'][0] < df.loc[index, f'{angle_colname}_new_minima'][0]: # if the first maximum occurs before the first minimum, start with the maximum
486+
while i_pks < df.loc[index, f'{angle_colname}_new_minima'].size and i_pks < df.loc[index, f'{angle_colname}_new_maxima'].size-1:
487+
if df.loc[index, f'{angle_colname}_new_minima'][i_pks] > df.loc[index, f'{angle_colname}_new_maxima'][i_pks+1]:
488+
if df.loc[index, angle_colname][df.loc[index, f'{angle_colname}_new_maxima'][i_pks+1]] > df.loc[index, angle_colname][df.loc[index, f'{angle_colname}_new_maxima'][i_pks]]:
489+
df.at[index, f'{angle_colname}_new_maxima'] = np.delete(df.loc[index, f'{angle_colname}_new_maxima'], i_pks)
490+
else:
491+
df.at[index, f'{angle_colname}_new_maxima'] = np.delete(df.loc[index, f'{angle_colname}_new_maxima'], i_pks+1)
492+
i_pks -= 1
493+
if i_pks > 0 and df.loc[index, f'{angle_colname}_new_minima'][i_pks] < df.loc[index, f'{angle_colname}_new_maxima'][i_pks]:
494+
if df.loc[index, angle_colname][df.loc[index, f'{angle_colname}_new_minima'][i_pks]] < df.loc[index, angle_colname][df.loc[index, f'{angle_colname}_new_minima'][i_pks-1]]:
495+
df.at[index, f'{angle_colname}_new_minima'] = np.delete(df.loc[index, f'{angle_colname}_new_minima'], i_pks-1)
496+
497+
else:
498+
df.at[index, f'{angle_colname}_new_minima'] = np.delete(df.loc[index, f'{angle_colname}_new_minima'], i_pks)
499+
i_pks -= 1
500+
i_pks += 1
501+
502+
# for some peculiar reason, if a single item remains in the row for {angle_colname}_new_minima or
503+
# angle_new_maxima, it could be either a scalar or a vector.
504+
for col in [f'{angle_colname}_new_minima', f'{angle_colname}_new_maxima']:
505+
df.loc[df.apply(lambda x: type(x[col].tolist())==int, axis=1), col] = df.loc[df.apply(lambda x: type(x[col].tolist())==int, axis=1), col].apply(lambda x: [x])
506+
507+
# extract amplitude
508+
df[f'{angle_colname}_extrema_values'] = df.apply(lambda x: [x[angle_colname][i] for i in sorted(np.concatenate([x[f'{angle_colname}_new_minima'], x[f'{angle_colname}_new_maxima']]))], axis=1)
505509

506510
return df[f'{angle_colname}_extrema_values']
507511

src/paradigma/gait_analysis.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def extract_arm_swing_features(input_path: Union[str, Path], output_path: Union[
207207
)
208208

209209
# determine the extrema (minima and maxima) of the angle signal
210-
extract_angle_extremes(
210+
df_windowed['angle_extrema_values'] = extract_angle_extremes(
211211
df=df_windowed,
212212
angle_colname=config.angle_smooth_colname,
213213
dominant_frequency_colname='angle_dominant_frequency',

0 commit comments

Comments
 (0)