优化下面的代码,不显示眼图分析,具体显示其他分析,给我优化后完整的代码:classdef TDMPerformanceAnalyzer < TDMSystem
properties
analysisFigure % 独立分析窗口
performanceMetrics % 扩展的性能指标
constellationAxes % 星座图坐标轴
spectrumAxes % 频谱分析坐标轴
eyeDiagramAxes % 眼图坐标轴
correlationAxes % 相关分析坐标轴
metricTable % 性能指标表格
systemMetricsLabel % 系统级指标标签
end
methods function obj = TDMPerformanceAnalyzer(params) % 调用父类构造函数 obj = obj@TDMSystem(params); % 初始化扩展性能指标 obj.performanceMetrics = struct(... 'evm', [], ... % 误差矢量幅度 'throughput', [], ... % 系统吞吐量 'latency', [], ... % 系统延迟 'spectralEfficiency', [], ... % 频谱效率 'totalThroughput', [], ... % 系统总吞吐量 'overallSpectralEfficiency', [] ... % 总体频谱效率 ); end function obj = runPerformanceAnalysis(obj) % 运行基础仿真流程 obj = runSimulation(obj); % 计算扩展性能指标 obj = obj.calculateExtendedMetrics(); % 创建独立分析窗口 obj.createAnalysisWindow(); % 绘制综合性能分析 obj.plotComprehensiveAnalysis(); end function obj = calculateExtendedMetrics(obj) % 计算扩展性能指标 numSignals = obj.params.numSignals; obj.performanceMetrics.evm = zeros(1, numSignals); obj.performanceMetrics.throughput = zeros(1, numSignals); obj.performanceMetrics.latency = zeros(1, numSignals); obj.performanceMetrics.spectralEfficiency = zeros(1, numSignals); totalSymbols = 0; totalBits = 0; bandwidth = obj.params.fs; % 系统带宽 for i = 1:numSignals % 检查信号存在性 if size(obj.originalSignals, 1) < i || ... size(obj.syncedSignals, 1) < i || ... isempty(obj.originalSignals) || ... isempty(obj.syncedSignals) obj.performanceMetrics.evm(i) = NaN; obj.performanceMetrics.latency(i) = NaN; continue; end % 获取信号并确保行向量 orig = obj.originalSignals(i, :); decoded = obj.syncedSignals(i, :); orig = orig(:).'; % 强制转为行向量 decoded = decoded(:).'; % 强制转为行向量 % 确保信号长度匹配 minLen = min(length(orig), length(decoded)); if minLen < 10 obj.performanceMetrics.evm(i) = NaN; obj.performanceMetrics.latency(i) = NaN; continue; end % 截取相同长度部分 orig = orig(1:minLen); decoded = decoded(1:minLen); % 计算误差矢量幅度(EVM) evm = sqrt(mean(abs(orig - decoded).^2)) / ... sqrt(mean(abs(orig).^2)); obj.performanceMetrics.evm(i) = evm * 100; % 百分比 % 计算吞吐量 (bps) modType = obj.modulationParams.signalModulations{i}; bitsPerSymbol = obj.getBitsPerSymbol(modType); symbolRate = obj.params.fs / bitsPerSymbol; obj.performanceMetrics.throughput(i) = symbolRate * bitsPerSymbol; % 估计延迟 (ms) - 基于同步过程 [corr, lags] = xcorr(orig, decoded); if ~isempty(corr) [~, idx] = max(abs(corr)); delay = lags(idx) / obj.params.fs * 1000; % 转换为毫秒 obj.performanceMetrics.latency(i) = delay; else obj.performanceMetrics.latency(i) = NaN; end % 计算频谱效率 (bps/Hz) obj.performanceMetrics.spectralEfficiency(i) = ... obj.performanceMetrics.throughput(i) / bandwidth; % 统计总符号和比特数 if length(obj.modulatedSignals) >= i totalSymbols = totalSymbols + length(obj.modulatedSignals{i}); end if length(obj.encodedSignals) >= i totalBits = totalBits + length(obj.encodedSignals{i}); end end % 系统级指标 if totalBits > 0 && obj.params.duration > 0 obj.performanceMetrics.totalThroughput = totalBits / obj.params.duration; else obj.performanceMetrics.totalThroughput = 0; end obj.performanceMetrics.overallSpectralEfficiency = ... obj.performanceMetrics.totalThroughput / bandwidth; end function createAnalysisWindow(obj) % 创建独立分析窗口 (使用uifigure解决兼容性问题) obj.analysisFigure = uifigure('Name', 'TDM系统性能综合分析', ... 'Position', [100, 100, 1200, 850], ... 'Color', [0.95, 0.95, 0.95]); % 创建网格布局 (4行3列) gridLayout = uigridlayout(obj.analysisFigure, [4, 3]); gridLayout.RowHeight = {'1x', '1x', '0.5x', 40}; % 第4行固定高度 gridLayout.ColumnWidth = {'1x', '1x', '1x'}; gridLayout.Padding = [10, 10, 10, 10]; gridLayout.RowSpacing = 5; gridLayout.ColumnSpacing = 10; gridLayout.BackgroundColor = [0.95, 0.95, 0.95]; % === 星座图坐标轴 === obj.constellationAxes = uiaxes(gridLayout); obj.constellationAxes.Layout.Row = 1; obj.constellationAxes.Layout.Column = 1; title(obj.constellationAxes, '星座图分析'); xlabel(obj.constellationAxes, '同相分量 (I)'); ylabel(obj.constellationAxes, '正交分量 (Q)'); grid(obj.constellationAxes, 'on'); axis(obj.constellationAxes, 'equal'); % === 频谱分析坐标轴 === obj.spectrumAxes = uiaxes(gridLayout); obj.spectrumAxes.Layout.Row = 1; obj.spectrumAxes.Layout.Column = 2; title(obj.spectrumAxes, '频谱分析'); xlabel(obj.spectrumAxes, '频率 (kHz)'); ylabel(obj.spectrumAxes, '功率谱密度 (dB/Hz)'); grid(obj.spectrumAxes, 'on'); % === 眼图坐标轴 === obj.eyeDiagramAxes = uiaxes(gridLayout); obj.eyeDiagramAxes.Layout.Row = 1; obj.eyeDiagramAxes.Layout.Column = 3; title(obj.eyeDiagramAxes, '眼图分析'); xlabel(obj.eyeDiagramAxes, '时间 (符号周期)'); ylabel(obj.eyeDiagramAxes, '幅度'); grid(obj.eyeDiagramAxes, 'on'); % === 相关分析坐标轴 === obj.correlationAxes = uiaxes(gridLayout); obj.correlationAxes.Layout.Row = 2; obj.correlationAxes.Layout.Column = [1, 3]; title(obj.correlationAxes, '信号相关性分析'); xlabel(obj.correlationAxes, '滞后 (样本)'); ylabel(obj.correlationAxes, '相关系数'); grid(obj.correlationAxes, 'on'); % === 性能指标表格 === obj.metricTable = uitable(gridLayout); obj.metricTable.Layout.Row = 3; obj.metricTable.Layout.Column = [1, 3]; obj.metricTable.ColumnName = {'信号', 'BER', 'SNR (dB)', 'MSE', 'EVM (%)', ... '吞吐量 (bps)', '延迟 (ms)', '频谱效率 (bps/Hz)'}; obj.metricTable.RowName = {}; obj.metricTable.FontName = 'Consolas'; obj.metricTable.ColumnWidth = {60, 80, 80, 80, 80, 100, 80, 120}; % === 系统级指标标签 === obj.systemMetricsLabel = uilabel(gridLayout); obj.systemMetricsLabel.Layout.Row = 4; obj.systemMetricsLabel.Layout.Column = [1, 3]; obj.systemMetricsLabel.Text = '系统总吞吐量: 计算中...'; obj.systemMetricsLabel.HorizontalAlignment = 'center'; obj.systemMetricsLabel.BackgroundColor = [0.9, 0.9, 0.9]; obj.systemMetricsLabel.FontSize = 12; obj.systemMetricsLabel.FontWeight = 'bold'; end function plotComprehensiveAnalysis(obj) % 绘制星座图 plotConstellation(obj); % 绘制频谱分析 plotSpectrumAnalysis(obj); % 绘制眼图 plotEyeDiagram(obj); % 绘制信号相关性 plotSignalCorrelation(obj); % 更新性能指标表格 updateMetricTable(obj); % 更新系统级指标标签 if ~isempty(obj.performanceMetrics.totalThroughput) && ... ~isempty(obj.performanceMetrics.overallSpectralEfficiency) obj.systemMetricsLabel.Text = sprintf(... '系统总吞吐量: %.2f Mbps | 总频谱效率: %.2f bps/Hz', ... obj.performanceMetrics.totalThroughput/1e6, ... obj.performanceMetrics.overallSpectralEfficiency); else obj.systemMetricsLabel.Text = '系统指标计算失败'; end end function plotConstellation(obj) % 绘制第一个信号的星座图 signalIdx = 1; if length(obj.demuxSignals) >= signalIdx signal = obj.demuxSignals{signalIdx}; signal = signal(:); % 确保列向量 if length(signal) < 10 text(obj.constellationAxes, 0.5, 0.5, '样本不足', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); return; end % 提取实部和虚部 I = real(signal); Q = imag(signal); % 确保维度匹配 if length(I) ~= length(Q) minLen = min(length(I), length(Q)); I = I(1:minLen); Q = Q(1:minLen); end % 绘制星座图 scatter(obj.constellationAxes, I, Q, 15, ... 'filled', 'MarkerFaceAlpha', 0.6, 'MarkerEdgeColor', 'none'); title(obj.constellationAxes, sprintf('信号%d星座图 (%s调制)', ... signalIdx, obj.modulationParams.signalModulations{signalIdx})); % 添加EVM信息 if ~isnan(obj.performanceMetrics.evm(signalIdx)) text(obj.constellationAxes, ... 0.05, 0.95, ... % 归一化位置 sprintf('EVM: %.2f%%', obj.performanceMetrics.evm(signalIdx)), ... 'Units', 'normalized', ... 'BackgroundColor', [1, 1, 0.8], ... 'Margin', 3, ... 'FontSize', 10, ... 'VerticalAlignment', 'top'); end else text(obj.constellationAxes, 0.5, 0.5, '无可用信号数据', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); end end function plotSpectrumAnalysis(obj) % 分析TDM信号的频谱 fs = obj.params.fs; if isempty(obj.tdmSignal) text(obj.spectrumAxes, 0.5, 0.5, '无TDM信号', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); return; end signal = obj.tdmSignal(:); % 强制列向量 if length(signal) < 1024 text(obj.spectrumAxes, 0.5, 0.5, '信号长度不足', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); return; end % 计算功率谱密度 [psd, freq] = pwelch(signal, hamming(1024), 512, 1024, fs); % 关键修复1: 确保频率和PSD长度匹配 minLen = min(length(freq), length(psd)); freq = freq(1:minLen); psd = psd(1:minLen); % 关键修复2: 验证向量方向一致性 freq = freq(:); % 强制列向量 psd = psd(:); % 强制列向量 % 绘制频谱 plot(obj.spectrumAxes, freq/1e3, 10*log10(psd), ... 'LineWidth', 1.5, 'Color', [0, 0.4470, 0.7410,0.3]); xlim(obj.spectrumAxes, [0, fs/2/1e3]); % 添加带宽信息 try bandwidth = obw(signal, fs)/1e3; % 占用带宽(kHz) text(obj.spectrumAxes, ... 0.05, 0.95, ... % 归一化位置 sprintf('占用带宽: %.2f kHz', bandwidth), ... 'Units', 'normalized', ... 'BackgroundColor', [1, 1, 0.8], ... 'Margin', 3, ... 'FontSize', 10, ... 'VerticalAlignment', 'top'); catch % 带宽计算失败时跳过 end end function plotEyeDiagram(obj) % 绘制第一个信号的眼图 signalIdx = 1; if length(obj.demuxSignals) >= signalIdx signal = obj.demuxSignals{signalIdx}; signal = real(signal(:)); % 强制列向量并取实部 % 设置眼图参数 samplesPerSymbol = 20; % 每符号采样数 numSymbols = 500; % 显示符号数 % 创建眼图 plotEye(obj.eyeDiagramAxes, signal, samplesPerSymbol, numSymbols); title(obj.eyeDiagramAxes, sprintf('信号%d眼图', signalIdx)); else text(obj.eyeDiagramAxes, 0.5, 0.5, '无解复用信号数据', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); end end function plotSignalCorrelation(obj) % 分析原始信号与解码信号的相关性 signalIdx = 1; if size(obj.originalSignals, 1) >= signalIdx && ... size(obj.syncedSignals, 1) >= signalIdx orig = obj.originalSignals(signalIdx, :); decoded = obj.syncedSignals(signalIdx, :); % 强制行向量并截取相同长度 orig = orig(:).'; decoded = decoded(:).'; minLen = min(length(orig), length(decoded)); if minLen < 10 text(obj.correlationAxes, 0.5, 0.5, '信号长度不足', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); return; end orig = orig(1:minLen); decoded = decoded(1:minLen); % 计算互相关 try [corr, lags] = xcorr(orig, decoded, 'normalized'); % 关键修复1: 检查空结果 if isempty(corr) || isempty(lags) text(obj.correlationAxes, 0.5, 0.5, '互相关计算失败', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); return; end % 关键修复2: 确保维度匹配 if length(lags) ~= length(corr) minLen = min(length(lags), length(corr)); lags = lags(1:minLen); corr = corr(1:minLen); end % 关键修复3: 统一向量方向 lags = lags(:); corr = corr(:); % 绘制相关结果 stem(obj.correlationAxes, lags, corr, ... 'filled', 'MarkerSize', 4, 'MarkerFaceColor', [0.3010, 0.7450, 0.9330]); title(obj.correlationAxes, '原始信号与解码信号互相关'); % 标记峰值位置 if ~isempty(corr) [maxCorr, maxIdx] = max(abs(corr)); maxLag = lags(maxIdx); hold(obj.correlationAxes, 'on'); plot(obj.correlationAxes, maxLag, maxCorr, 'ro', 'MarkerSize', 8, 'LineWidth', 1.5); text(obj.correlationAxes, maxLag, maxCorr, ... sprintf(' 延迟: %d 样本 (%.2f ms)', maxLag, maxLag/obj.params.fs*1000), ... 'VerticalAlignment', 'bottom', ... 'FontSize', 10, ... 'BackgroundColor', [1, 1, 0.8]); hold(obj.correlationAxes, 'off'); end catch e % 捕获并显示相关计算错误 warning('相关计算错误: %s (信号长度: %d)', E.message, length(orig)); text(obj.correlationAxes, 0.5, 0.5, '相关计算失败', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); end else text(obj.correlationAxes, 0.5, 0.5, '无信号相关性数据', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); end end function updateMetricTable(obj) % 准备表格数据 numSignals = obj.params.numSignals; tableData = cell(numSignals, 8); for i = 1:numSignals tableData{i, 1} = sprintf('信号 %d', i); % 处理BER数据 if i <= length(obj.performance.ber) && ~isempty(obj.performance.ber) tableData{i, 2} = sprintf('%.2e', obj.performance.ber(i)); else tableData{i, 2} = 'N/A'; end % 处理SNR数据 if i <= length(obj.performance.snr) && ~isempty(obj.performance.snr) tableData{i, 3} = sprintf('%.1f', obj.performance.snr(i)); else tableData{i, 3} = 'N/A'; end % 处理其他指标 tableData{i, 4} = sprintf('%.2e', obj.performance.mse(i)); tableData{i, 5} = formatNumber(obj.performanceMetrics.evm(i), '%.2f%%'); tableData{i, 6} = formatNumber(obj.performanceMetrics.throughput(i), 'bps'); tableData{i, 7} = formatNumber(obj.performanceMetrics.latency(i), '%.2f ms'); tableData{i, 8} = formatNumber(obj.performanceMetrics.spectralEfficiency(i), '%.4f bps/Hz'); end % 设置表格数据 obj.metricTable.Data = tableData; end end methods (Access = private) function plotEye(~, ax, signal, samplesPerSymbol, numSymbols) % 绘制眼图辅助函数 if isempty(signal) || length(signal) < samplesPerSymbol text(ax, 0.5, 0.5, '数据不足', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); return; end % 确保样本数可被整除 numCompleteSymbols = floor(length(signal) / samplesPerSymbol); if numCompleteSymbols < 1 text(ax, 0.5, 0.5, '样本不足', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); return; end % 限制符号数量,防止内存溢出 maxSymbols = min(numCompleteSymbols, numSymbols); numSamples = maxSymbols * samplesPerSymbol; signal = signal(1:numSamples); % 重塑为矩阵 (每行代表一个符号周期) try % 截断信号到整数倍长度 newLength = floor(length(signal) / samplesPerSymbol) * samplesPerSymbol; signal = signal(1:newLength); if newLength < samplesPerSymbol error('信号长度不足,无法形成完整的符号周期'); end eyeMatrix = reshape(signal, samplesPerSymbol, []); % 验证矩阵维度 if size(eyeMatrix, 1) ~= samplesPerSymbol || isempty(eyeMatrix) error('眼图矩阵重塑失败'); end % 创建时间向量 t = (0:(samplesPerSymbol-1)) / samplesPerSymbol; t = t(:); % 强制列向量 % 关键修复: 验证时间向量与矩阵行数匹配 if length(t) ~= size(eyeMatrix, 1) error('时间向量长度(%d)与矩阵行数(%d)不匹配', length(t), size(eyeMatrix, 1)); end % 绘制眼图轨迹 (最多100条) numTraces = min(100, size(eyeMatrix, 2)); if numTraces > 0 % 确保时间向量与数据匹配 X = repmat(t, 1, numTraces); Y = eyeMatrix(:, 1:numTraces); % 关键修复: 验证维度一致性 if ~isequal(size(X), size(Y)) error('X(%dx%d)和Y(%dx%d)维度不匹配', size(X,1), size(X,2), size(Y,1), size(Y,2)); end plot(ax, X, Y, ... 'Color', [0, 0.4470, 0.7410, 0.3]); % 计算并绘制平均值 hold(ax, 'on'); meanTrace = mean(eyeMatrix, 2); plot(ax, t, meanTrace, 'r', 'LineWidth', 2); hold(ax, 'off'); end % 设置坐标轴属性 xlim(ax, [0, 1]); grid(ax, 'on'); box(ax, 'on'); catch e % 捕获并显示错误 warning('眼图绘制错误: %s', E.message); text(ax, 0.5, 0.5, '眼图绘制失败', ... 'HorizontalAlignment', 'center', 'Units', 'normalized'); end end end
end
% 增强型辅助函数:格式化数字和单位
function str = formatNumber(num, formatSpec)
if nargin < 2
formatSpec = ‘%.2f’;
end
if isempty(num) || isnan(num) str = 'N/A'; return; end % 处理带单位的格式化 if contains(formatSpec, 'bps') if num >= 1e9 str = sprintf([formatSpec ' Gbps'], num/1e9); elseif num >= 1e6 str = sprintf([formatSpec ' Mbps'], num/1e6); elseif num >= 1e3 str = sprintf([formatSpec ' Kbps'], num/1e3); else str = sprintf([formatSpec ' bps'], num); end else % 直接应用格式规范 str = sprintf(formatSpec, num); end
end
最新发布