From f258838a86f5d2b77e5fc7d511ce8b33e51a7633 Mon Sep 17 00:00:00 2001 From: marques Date: Mon, 10 Nov 2025 14:37:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=91=BC=E5=90=B8=E4=BD=93=E5=8A=A8=E6=A3=80?= =?UTF-8?q?=E6=B5=8B=E5=9F=BA=E6=9C=AC=E7=A8=B3=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HYS_process.py | 11 +++++---- dataset_config/HYS_config.yaml | 6 +++++ signal_method/rule_base_event.py | 41 ++++++++++++++++++++++---------- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/HYS_process.py b/HYS_process.py index 0c3627c..1eecdf5 100644 --- a/HYS_process.py +++ b/HYS_process.py @@ -28,7 +28,7 @@ import numpy as np import signal_method import os from matplotlib import pyplot as plt -os.environ['DISPLAY'] = "localhost:14.0" +os.environ['DISPLAY'] = "localhost:10.0" def process_one_signal(samp_id): signal_path = list((org_signal_root_path / f"{samp_id}").glob("OrgBCG_Sync_*.txt")) @@ -144,14 +144,15 @@ def process_one_signal(samp_id): print("resp_movement_mask revise is skipped") - # 分析Resp的幅值突变区间 - if resp_movement_mask is not None: + resp_amp_change_conf = conf.get("resp_amp_change", None) + if resp_amp_change_conf is not None and resp_movement_mask is not None: resp_amp_change_mask, resp_amp_change_list = signal_method.position_based_sleep_recognition_v3( signal_data=resp_data, movement_mask=resp_movement_mask, movement_list=resp_movement_position_list, - sampling_rate=resp_fs) + sampling_rate=resp_fs, + **resp_amp_change_conf) print(f"amp_change_mask_shape: {resp_amp_change_mask.shape}, num_amp_change: {np.sum(resp_amp_change_mask == 1)}, count_amp_change_positions: {len(resp_amp_change_list)}") else: resp_amp_change_mask = None @@ -237,4 +238,4 @@ if __name__ == '__main__': all_samp_disable_df = utils.read_disable_excel(disable_df_path) - process_one_signal(select_ids[7]) + process_one_signal(select_ids[0]) diff --git a/dataset_config/HYS_config.yaml b/dataset_config/HYS_config.yaml index 97d650e..101c1b0 100644 --- a/dataset_config/HYS_config.yaml +++ b/dataset_config/HYS_config.yaml @@ -48,6 +48,12 @@ resp_movement_revise: merge_gap_sec: 10 min_duration_sec: 1 +resp_amp_change: + mav_calc_window_sec: 5 + threshold_amplitude: 0.1 + threshold_energy: 0.4 + + bcg: downsample_fs: 100 diff --git a/signal_method/rule_base_event.py b/signal_method/rule_base_event.py index 161f378..4a408ab 100644 --- a/signal_method/rule_base_event.py +++ b/signal_method/rule_base_event.py @@ -194,10 +194,15 @@ def movement_revise(signal_data, sampling_rate, movement_mask, movement_list, up # 往左右两边取compare_size个点的mav,取平均值 for start, end in movement_list: - left_values = collect_values(arr=mav, index=start - 1, step=-1, limit=compare_size, mask=movement_mask) - right_values = collect_values(arr=mav, index=end + 5, step=1, limit=compare_size, mask=movement_mask) + left_points = start - 5 + right_points = end + 5 + + left_values = collect_values(arr=mav, index=left_points, step=-1, limit=compare_size, mask=movement_mask) + right_values = collect_values(arr=mav, index=right_points, step=1, limit=compare_size, mask=movement_mask) + left_value_metrics = np.median(left_values) if len(left_values) > 0 else 0 right_value_metrics = np.median(right_values) if len(right_values) > 0 else 0 + if left_value_metrics == 0: value_metrics = right_value_metrics elif right_value_metrics == 0: @@ -207,7 +212,7 @@ def movement_revise(signal_data, sampling_rate, movement_mask, movement_list, up # 逐秒遍历mav,判断是否需要修正 # print(f"Revising movement from index {start} to {end}, left_mean: {left_value_mean:.2f}, right_mean: {right_value_mean:.2f}, mean: {value_mean:.2f}") - for i in range(start, end + 5): + for i in range(left_points, right_points): if i < 0 or i >= len(mav): continue # print(f"Index {i}, mav: {mav[i]:.2f}, left_mean: {left_value_mean:.2f}, right_mean: {right_value_mean:.2f}, mean: {value_mean:.2f}") @@ -514,9 +519,13 @@ def position_based_sleep_recognition_v2(signal_data, movement_mask, sampling_rat return position_changes, position_change_times -def position_based_sleep_recognition_v3(signal_data, movement_mask, movement_list, sampling_rate=100): +def position_based_sleep_recognition_v3(signal_data, movement_mask, movement_list, sampling_rate, mav_calc_window_sec, + threshold_amplitude, threshold_energy): """ + :param threshold_energy: + :param threshold_amplitude: + :param mav_calc_window_sec: :param movement_list: :param signal_data: :param movement_mask: mask的采样率为1Hz @@ -524,11 +533,6 @@ def position_based_sleep_recognition_v3(signal_data, movement_mask, movement_lis :param window_size_sec: :return: """ - mav_calc_window_sec = 1 # 计算mav的窗口大小,单位秒 - # 判断是否存在显著变化 (可根据实际情况调整阈值) - threshold_amplitude = 0.1 # 幅值变化阈值 - threshold_energy = 0.1 # 能量变化阈值 - # 获取有效片段起止位置 valid_list = utils.event_mask_2_list(movement_mask, event_true=False) @@ -549,16 +553,26 @@ def position_based_sleep_recognition_v3(signal_data, movement_mask, movement_lis return [], [] def clac_mav(data_segment): - mav = np.nanmean( + # 确定data_segment长度为mav_calc_window_sec的整数倍 + if len(data_segment) % (mav_calc_window_sec * sampling_rate) != 0: + data_segment = data_segment[:-(len(data_segment) % (mav_calc_window_sec * sampling_rate))] + + mav = np.nanstd( np.nanmax(data_segment.reshape(-1, mav_calc_window_sec * sampling_rate), - axis=0)) - np.nanmean( + axis=0) - np.nanmin(data_segment.reshape(-1, mav_calc_window_sec * sampling_rate), axis=0)) return mav def clac_energy(data_segment): - energy = np.nansum(np.abs(data_segment ** 2)) + energy = np.nansum(np.abs(data_segment ** 2)) // (len(data_segment) // sampling_rate) return energy + def calc_mav_by_quantiles(data_segment): + # 先计算所有的mav值 + mav_values = np.nanmax(data_segment.reshape(-1, mav_calc_window_sec * sampling_rate), axis=0) - np.nanmin( + data_segment.reshape(-1, mav_calc_window_sec * sampling_rate)) + # 计算分位数 + position_changes = np.zeros(len(signal_data) // sampling_rate, dtype=int) position_change_list = [] @@ -583,7 +597,8 @@ def position_based_sleep_recognition_v3(signal_data, movement_mask, movement_lis # 避免过短的片段 if movement_end - movement_start <= sampling_rate: # 小于1秒的片段不考虑 - print(f"Skipping movement segment {i + 1} due to insufficient length. movement start: {movement_start}, movement end: {movement_end}") + print( + f"Skipping movement segment {i + 1} due to insufficient length. movement start: {movement_start}, movement end: {movement_end}") continue # 计算前后片段的幅值和能量