一种表征心电图信号多重分形的方法——质量指数谱曲率。

今天拿到了一个小鼠的心电图,准备做一些实验。阅读文献时找到一个方法:质量指数谱,通过曲率来衡量其非线性。曲率越大,表示信号的非线性越强,多重分形结构越明显。

并且文章对小鼠进行注毒,发现健康小鼠的非线性最大[1]。此外该方法也可用于人类ECG[2]。

具体方法很简单,通过熵表述不确定性,曲率量化非线性复杂度,具体可参考对应文献,二者的算法一致。

Matlab 复制代码
clear; close all; clc;

%% 1. 加载数据
data_path = 'D:\xiaoshu\cleandata.mat';
load(data_path);

% 自动识别信号变量(double 列向量)
vars = whos('-file', data_path);
signal = [];
for i = 1:length(vars)
    if strcmp(vars(i).class, 'double') && vars(i).size(2) == 1
        signal = eval(vars(i).name);
        fprintf('已加载信号:%s,长度 %d 点\n', vars(i).name, length(signal));
        break;
    end
end
if isempty(signal)
    error('未找到合适的信号变量(需为 double 列向量)');
end

% 去直流
signal = signal - mean(signal);

%% 2. 参数设置(请根据实际数据修改采样率!)
fs = 2000;                   % 采样率 Hz(论文中为 5000 Hz,请按你的数据调整)
gamma_max = 50;              % 最大尺度因子(论文取 50)
q_list = -10:0.2:10;         % q 值行向量
L_min = 4;                   % 最小段落长度(点数)
L_num = 12;                  % 段落长度数目(对数等分)

%% 3. 执行多尺度分析
fprintf('\n开始多尺度分析(修正版)...\n');
results = msmf_analysis_corrected(signal, fs, gamma_max, q_list, L_min, L_num);

%% 4. 显示结果
fprintf('\n=== 多尺度曲率结果 ===\n');
fprintf('gamma\t频率(Hz)\tK\n');
for i = 1:length(results.gamma)
    fprintf('%d\t%.1f\t\t%.4f\n', results.gamma(i), results.frequency(i), results.K(i));
end

[~, max_idx] = max(abs(results.K));
fprintf('\n|K| 最大值出现在 gamma = %d,对应频率 %.1f Hz\n', results.gamma(max_idx), results.frequency(max_idx));

%% 5. 绘图
figure('Position', [100 100 900 400]);
subplot(1,2,1);
plot(results.gamma, results.K, 'bo-', 'LineWidth', 1.5);
xlabel('Scale factor \gamma');
ylabel('K_{\pi(q)}');
title('曲率 vs 尺度因子');
grid on;

subplot(1,2,2);
semilogx(results.frequency, results.K, 'ro-', 'LineWidth', 1.5);
xlabel('频率 (Hz)');
ylabel('K_{\pi(q)}');
title('曲率 vs 频率');
set(gca, 'XDir', 'reverse');
grid on;

%% 6. 保存结果
save_path = fullfile(fileparts(data_path), 'MSMF_results_corrected.mat');
save(save_path, 'results');
fprintf('\n结果已保存至:%s\n', save_path);

%% ================= 函数定义 =================

function results = msmf_analysis_corrected(signal, fs, gamma_max, q_list, L_min, L_num)
% 多尺度分析主函数
    gamma_vec = (1:gamma_max)';
    K_vec = zeros(gamma_max, 1);
    freq_vec = fs ./ (2 * gamma_vec);   % 信号频率 = fs/(2*gamma)
    
    for g = 1:gamma_max
        fprintf('Processing gamma = %d ...\n', g);
        y = coarse_grain_fast(signal, g);
        K = multifractal_spectrum_corrected(y, q_list, L_min, L_num);
        K_vec(g) = K;
    end
    
    results.gamma = gamma_vec;
    results.K = K_vec;
    results.frequency = freq_vec;
end

function y = coarse_grain_fast(x, gamma)
% 向量化粗粒化:每 gamma 个连续点取平均
    N = length(x);
    n_new = floor(N / gamma);
    if n_new == 0
        y = [];
        return;
    end
    % 截取可整除部分,reshape 后按列求平均
    x_trim = x(1 : gamma * n_new);
    y = mean(reshape(x_trim, gamma, n_new), 1)';
end

function K = multifractal_spectrum_corrected(y, q_list, L_min, L_num)
% 对单个粗粒化信号计算曲率 K(修正测度定义与曲率计算)
    Ny = length(y);
    if Ny < L_min * 4
        K = NaN;
        return;
    end
    
    % 生成段落长度数组(对数等分)
    L_max = floor(Ny / 4);
    L_vals = unique(round(logspace(log10(L_min), log10(L_max), L_num)));
    L_vals(L_vals > Ny/2) = [];
    if length(L_vals) < 3
        K = NaN;
        return;
    end
    
    % 计算配分函数
    [logL, logZ] = partition_function_corrected(y, L_vals, q_list);
    
    % 剔除无效行
    valid_rows = all(~isnan(logZ), 2);
    if sum(valid_rows) < 3
        K = NaN;
        return;
    end
    logL = logL(valid_rows);
    logZ = logZ(valid_rows, :);
    
    % 计算 τ(q)
    tau = compute_tau(logL, logZ);
    if any(isnan(tau))
        K = NaN;
        return;
    end
    
    % 强制 q=1 处 τ=0(与论文图1(a)拐角对应)
    [~, idx_q1] = min(abs(q_list - 1));
    tau(idx_q1) = 0;
    
    % 计算曲率
    K = compute_curvature_corrected(q_list, tau);
end

function [logL, logZ] = partition_function_corrected(y, L_list, q_list)
% 计算配分函数 Z(q) 及其对数(修正测度为段内均值,不加绝对值)
    nL = length(L_list);
    nq = length(q_list);
    logL = log(L_list(:));
    logZ = zeros(nL, nq);
    
    for iL = 1:nL
        L = L_list(iL);
        measures = compute_measures_corrected(y, L);
        total = sum(measures);
        if total == 0
            logZ(iL, :) = NaN;
            continue;
        end
        P = measures / total;
        
        for iq = 1:nq
            q = q_list(iq);
            if q == 1
                % 香农熵的指数形式,避免 log(0)
                nonzero = P > 0;
                Z = exp(sum(P(nonzero) .* log(P(nonzero))));
            else
                Z = sum(P .^ q);
            end
            logZ(iL, iq) = log(Z);
        end
    end
end

function measures = compute_measures_corrected(y, L)
% 将信号 y 划分为长度为 L 的段落,计算每段的均值(不加绝对值,与论文一致)
    Ny = length(y);
    nseg = floor(Ny / L);
    if nseg == 0
        measures = [];
        return;
    end
    % 向量化计算每段均值
    y_trim = y(1 : L * nseg);
    y_reshaped = reshape(y_trim, L, nseg);
    measures = mean(y_reshaped, 1)';
    
    % 由于 ECG 信号有正负,均值可能为负。为确保概率非负,将整体平移至最小值非负
    min_m = min(measures);
    if min_m < 0
        measures = measures - min_m + eps;
    end
end

function tau = compute_tau(logL, logZ)
% 线性拟合得到质量指数 τ(q)
    nq = size(logZ, 2);
    tau = zeros(1, nq);
    for iq = 1:nq
        valid = ~isnan(logZ(:, iq));
        if sum(valid) < 2
            tau(iq) = NaN;
            continue;
        end
        p = polyfit(logL(valid), logZ(valid, iq), 1);
        tau(iq) = p(1);
    end
end

function K = compute_curvature_corrected(q_list, tau)
% 计算曲率 K = tan(phi)
    idx_left = q_list < 1;
    idx_right = q_list > 1;
    if sum(idx_left) < 2 || sum(idx_right) < 2
        K = NaN;
        return;
    end
    p_left = polyfit(q_list(idx_left), tau(idx_left), 1);
    p_right = polyfit(q_list(idx_right), tau(idx_right), 1);
    k1 = p_left(1);
    k2 = p_right(1);
    K = abs((k2 - k1) / (1 + k1 * k2));   
end

我数据来源是正常小鼠,和文章比较,整体趋势还是接近的:

参考文献:

1\]X. Yang, T. Sun, S. Ma and Y. Zhou, "Multiscale Detection in ECG Multifractal Structure," *2010 4th International Conference on Bioinformatics and Biomedical Engineering*, Chengdu, China, 2010, pp. 1-4, doi: 10.1109/ICBBE.2010.5515828. \[2\]杨小冬,宁新宝,何爱军,等.基于多尺度的人体ECG信号质量指数谱分析\[J\].物理学报,2008,(03):1514-1521. \*\*\*\*\*\*\*\*\*\*\*\*\*END\*\*\*\*\*\*\*\*\*\*\*\*\*

相关推荐
T.i.s7 天前
番外(开源心电图数据库处理)--mit-bih-normal-sinus-rhythm-database的使用教程
matlab·信号处理·心电图
lucy153027510791 年前
电致变色和电泳技术在低功耗显示器中大放异彩
计算机外设·心电图·超声波·音箱·胎心仪·立体声收录机
lucy153027510791 年前
内置ALC的前置放大器D2538A/D3308
心电图·超声波·音箱·胎心仪·立体声收录机·小型电话机
微学AI1 年前
人工智能在医疗领域的应用:AI模型在冠心病预测中的应用实例,以及决策建议
人工智能·医疗·心电图·冠心病
与诸君共勉3 年前
avalonia、WPF使用ScottPlot动态显示ECG心电图
c#·wpf·avalonia·ecg·心电图