def step_id(df_f, df_t, forcepla=[2], R='RCAL', L='LCAL', show_msg=True): """Identification of step side based on .forces and .trc files. """ if show_msg: print('Step identification ... ', end='') if not isinstance(forcepla, list): forcepla = [forcepla] if not forcepla: forcepla = list(set([int(fp[-1]) for fp in df_f.columns.values])) forces = [ force + str(fp) for fp in forcepla for force in ['FX', 'FY', 'FZ', 'MZ'] ] time = df_f.index.values freq = np.round(np.mean(1 / np.diff(time)), 0) # resample trc data to the forces frequency R = np.interp(time, df_t.index.values, df_t[R].Y.values[:, 0]) L = np.interp(time, df_t.index.values, df_t[L].Y.values[:, 0]) # detect onsets in Fy data threshold = 50 n_above = int(0.1 * freq) n_below = int(0.01 * freq) threshold2 = 10 * threshold # N n_above2 = int(0.02 * freq) idx = detect_onset(df_f[forces[1]].values, threshold, n_above, n_below, threshold2, n_above2) # column names of the .mot dataframe cols = [ 'R_ground_force_vx', 'R_ground_force_vy', 'R_ground_force_vz', 'R_ground_force_px', 'R_ground_force_py', 'R_ground_force_pz', 'L_ground_force_vx', 'L_ground_force_vy', 'L_ground_force_vz', 'L_ground_force_px', 'L_ground_force_py', 'L_ground_force_pz', 'R_ground_torque_x', 'R_ground_torque_y', 'R_ground_torque_z', 'L_ground_torque_x', 'L_ground_torque_y', 'L_ground_torque_z' ] data = np.zeros((df_f.shape[0], len(cols))) # step side identification for ini, end in idx: if R[ini:int((ini + end) / 2)].sum() < L[ini:int((ini + end) / 2)].sum(): data[ini:end + 1, [0, 1, 2, 3, 4, 5, 14]] = df_f.values[ini:end + 1, :] else: data[ini:end + 1, [6, 7, 8, 9, 10, 11, 17]] = df_f.values[ini:end + 1, :] df = pd.DataFrame(data=data, columns=cols, index=time) df.index.name = 'time' if show_msg: print('done.') return df
def detect_onset_aux(dfData, **args_func_cortes): #Si se pasa como argumento corte_ini=1, coge el corte del final de cada ventana try: from detecta import detect_onset except: from detect_onset import detect_onset try: #si no se ha indicado el núm corte, coge el primero corte_ini = args_func_cortes['corte_ini'] args_func_cortes.pop('corte_ini', None) except: corte_ini = 0 cortes = detect_onset(dfData, **args_func_cortes) if corte_ini == 1: cortes = cortes[:, corte_ini] + 1 #si se elije el final de la ventana, se añade 1 para que empiece cuando ya ha superado el umbral cortes = cortes[:-1] #quita el último porque suele quedar cortado else: cortes = cortes[:, corte_ini] #se queda con el primer o segundo dato de cada par de datos. cortes = cortes[1:] #quita el primero porque suele quedar cortado return cortes
def filter_forces(df, h, forcepla=[2], fc_forces=20, fc_cop=6, threshold=50, show_msg=True): """Filter force data from the treadmill. """ if not isinstance(forcepla, list): forcepla = [forcepla] if not forcepla: forcepla = list(set([int(fp[-1]) for fp in df.columns.values])) forces = [ force + str(fp) for fp in forcepla for force in ['FX', 'FY', 'FZ', 'MZ'] ] cops = [cop + str(fp) for fp in forcepla for cop in ['X', 'Z']] df2 = df.copy() F = df2[forces[1]].values freq = h['SampleRate'] npad = int(freq / 4) npad2 = 2 # filter parameters for COP b_cd, a_cd, fc_cd = critic_damp(fcut=fc_cop, freq=freq, npass=2, fcorr=True, filt='critic') if show_msg: print('Filtering: COP Fc: {:.2f} Hz'.format(fc_cd), end=', ') n_above = int(0.1 * freq) n_below = int(0.01 * freq) threshold2 = 10 * threshold # N n_above2 = int(0.02 * freq) # detect onsets in Fy data idx1 = detect_onset(F, threshold, n_above, n_below, threshold2, n_above2) for cop in cops: COP = df2[cop].values # for each foot strike for ini, end in idx1: # reliable COP portion idx2 = detect_onset(F[ini:end + 1], 4 * threshold, n_above, n_below, None, 1, del_ini_end=False) if idx2.shape[0]: # fit polynomiun y = COP[ini + idx2[0, 0]:ini + idx2[0, 1] + 1] t = ini + idx2[0, 0] + np.linspace(0, y.shape[0] - 1, y.shape[0]) p = np.polyfit(t, y, 2) # values at the extremities for using to pad data z = np.polyval(p, [ini, end]) q = np.hstack((z[0] * np.ones(npad), COP[ini:end + 1], z[1] * np.ones(npad))) # filter data q2 = signal.filtfilt(b_cd, a_cd, q) COP[ini - npad2:end + 1 + npad2] = q2[npad - npad2:-npad + npad2] df2[cop] = COP b_cd, a_cd, fc_cd = critic_damp(fcut=fc_forces, freq=freq, npass=2, fcorr=True, filt='critic') if show_msg: print('Forces Fc: {:.2f} Hz'.format(fc_cd)) for force in forces: df2[force] = signal.filtfilt(b_cd, a_cd, df2[force]) return df2