From 1cd9841c1abbdd78f47633e1e8cecf835effaf1c Mon Sep 17 00:00:00 2001 From: Qihang Zhang Date: Sun, 20 Apr 2025 23:00:31 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(utils=5Fpack):=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=97=B6=E9=97=B4=E5=BA=8F=E5=88=97=E5=AF=B9=E6=AF=94?= =?UTF-8?q?=E7=BB=98=E5=9B=BE=E8=84=9A=E6=9C=AC=E5=92=8C=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E9=9B=86=E7=BB=98=E5=9B=BE=E8=84=9A=E6=9C=AC=20-=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=20draw=5Fline=5Fcompare.py=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=8E=9F=E5=A7=8B=E4=B8=8E=E6=89=B0=E5=8A=A8=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E5=BA=8F=E5=88=97=E5=AF=B9=E6=AF=94=E5=8F=8A=E5=B1=80=E9=83=A8?= =?UTF-8?q?=E6=94=BE=E5=A4=A7=20-=20=E6=94=AF=E6=8C=81=E7=A9=BA=E6=A0=BC?= =?UTF-8?q?=E5=92=8C=E9=80=97=E5=8F=B7=E5=88=86=E9=9A=94=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8A=A0=E8=BD=BD=EF=BC=8C=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E8=A1=8C=E5=8F=82=E6=95=B0=E7=81=B5=E6=B4=BB=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=20-=20=E6=96=B0=E5=A2=9E=20draw=5Fall=5Fdataset.py=20=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E7=BB=98=E5=88=B6Excel=E4=B8=ADCPadv=E4=B8=8ECPsoadv?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=AF=B9=E6=AF=94=E6=8A=98=E7=BA=BF=E5=9B=BE?= =?UTF-8?q?=20-=20=E8=AE=BE=E7=BD=AE=E5=85=A8=E5=B1=80=E5=AD=97=E4=BD=93?= =?UTF-8?q?=E4=B8=BA=20Times=20New=20Roman=EF=BC=8C=E4=BF=9D=E8=AF=81?= =?UTF-8?q?=E5=9B=BE=E8=A1=A8=E7=BE=8E=E8=A7=82=E4=B8=80=E8=87=B4=20-=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=20line=5Fcompare=5Fcommand.txt=20=E6=8F=90?= =?UTF-8?q?=E4=BE=9B=E7=BB=98=E5=9B=BE=E8=84=9A=E6=9C=AC=E7=A4=BA=E4=BE=8B?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=20-=20=E5=88=A0=E9=99=A4=E6=97=A0=E7=94=A8?= =?UTF-8?q?=E7=9A=84=20print=5Fresults=5Fpath.py=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E6=B8=85=E7=90=86=E9=A1=B9=E7=9B=AE=E5=86=97=E4=BD=99?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- print_results_path.py | 0 utils_pack/draw_all_dataset.py | 58 +++++++ utils_pack/draw_line_compare.py | 153 ++++++++++++++++++ .../filter_figures_folder.py | 0 utils_pack/line_compare_command.txt | 3 + 5 files changed, 214 insertions(+) delete mode 100644 print_results_path.py create mode 100644 utils_pack/draw_all_dataset.py create mode 100644 utils_pack/draw_line_compare.py rename filter_figures_folder.py => utils_pack/filter_figures_folder.py (100%) create mode 100644 utils_pack/line_compare_command.txt diff --git a/print_results_path.py b/print_results_path.py deleted file mode 100644 index e69de29..0000000 diff --git a/utils_pack/draw_all_dataset.py b/utils_pack/draw_all_dataset.py new file mode 100644 index 0000000..fe81325 --- /dev/null +++ b/utils_pack/draw_all_dataset.py @@ -0,0 +1,58 @@ +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np +import matplotlib as mpl + +# 设置全局字体为 Times New Roman +plt.rcParams['font.family'] = 'Times New Roman' +plt.rcParams['mathtext.fontset'] = 'stix' # 数学文本也使用与 Times New Roman 兼容的字体 + +# 读取Excel文件 +file_path = "实验结果.xlsx" # 请替换为你的文件路径 +sheet_name = "Sheet1" +df = pd.read_excel(file_path, sheet_name=sheet_name) + +# 提取所需数据 +# 注意: Excel范围F2:F42对应pandas的索引1:41 +# 同样L2:L43对应索引1:42,A2:A43对应索引1:42 +dataset_names = df.iloc[1:42, 0].values # A2:A43 数据集名称 +cp_adv = df.iloc[1:41, 5].values # F2:F42 CPadv数据 +cp_soadv = df.iloc[1:42, 12].values # L2:L43 CPsoadv数据 + +# 计算均值 +cp_adv_mean = np.mean(cp_adv) +cp_soadv_mean = np.mean(cp_soadv) + +# 创建图表 - 减小图片尺寸 +plt.figure(figsize=(10, 5)) # 从 (12, 6) 减小到 (10, 5) + +# 绘制CPadv折线 +plt.plot(dataset_names[:len(cp_adv)], cp_adv, 'b-', marker='o', label='CPadv') +# 绘制CPadv均值线 +plt.axhline(y=cp_adv_mean, color='b', linestyle='--', alpha=0.7, label='Mean of CPadv') + +# 绘制CPsoadv折线 +plt.plot(dataset_names[:len(cp_soadv)], cp_soadv, 'r-', marker='s', label='CPsoadv') +# 绘制CPsoadv均值线 +plt.axhline(y=cp_soadv_mean, color='r', linestyle='--', alpha=0.7, label='Mean of CPsoadv') + +# 设置图表标题和标签 +plt.ylabel('Queries', fontsize=12) +plt.grid(True, linestyle='--', alpha=0.7) +plt.legend() + +# 调整x轴标签 +plt.xticks(rotation=45, ha='right') +plt.tight_layout() + +# 保存为PDF矢量图 +plt.savefig('CCPP_comparison.pdf', bbox_inches='tight') + +# 同时也保存一份PNG格式(如果需要) +plt.savefig('CCPP_comparison.png', dpi=300, bbox_inches='tight') + +plt.show() + +# 打印均值结果 +print(f"CPadv 均值: {cp_adv_mean:.2f}") +print(f"CPsoadv 均值: {cp_soadv_mean:.2f}") \ No newline at end of file diff --git a/utils_pack/draw_line_compare.py b/utils_pack/draw_line_compare.py new file mode 100644 index 0000000..19f4299 --- /dev/null +++ b/utils_pack/draw_line_compare.py @@ -0,0 +1,153 @@ +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np +import argparse +from matplotlib.patches import Rectangle +import matplotlib.transforms as transforms + +# 设置全局字体为Times New Roman +plt.rcParams['font.family'] = 'Times New Roman' +plt.rcParams['mathtext.fontset'] = 'cm' # 确保数学公式也使用合适的字体 + +def load_data(file_path): + """加载数据,支持空格分隔和逗号分隔""" + try: + # 尝试以空格分隔符读取 + df = pd.read_csv(file_path, header=None, sep=r'\s+') + print(f"已使用空格分隔符读取文件: {file_path}") + return df + except Exception as e: + print(f"以空格分隔符读取失败,尝试以逗号分隔符读取: {e}") + try: + # 尝试以逗号分隔符读取 + df = pd.read_csv(file_path, header=None) + print(f"已使用逗号分隔符读取文件: {file_path}") + return df + except Exception as e: + print(f"读取文件失败: {e}") + raise + +def plot_time_series(original_file, perturbed_file, sequence_id, beta, zoom_start=None, zoom_end=None, sub_offset=0.1): + """绘制指定序号的原始和扰动时间序列对比图,并添加局部放大图 + + 参数: + original_file -- 原始时间序列文件路径 + perturbed_file -- 扰动时间序列文件路径 + sequence_id -- 要绘制的序列ID + beta -- beta参数值 + zoom_start -- 放大区域的起始索引(如果为None则不添加放大图) + zoom_end -- 放大区域的结束索引(如果为None则不添加放大图) + """ + # 加载数据 + original_data = load_data(original_file) + perturbed_data = load_data(perturbed_file) + + # 确保序号是整数 + sequence_id = int(sequence_id) + + # 在两个文件中查找指定序号的行 + original_row = original_data[original_data[0] == sequence_id] + perturbed_row = perturbed_data[perturbed_data[0] == sequence_id] + + print(f"数据中的唯一序号: {original_data[0].unique()}") + + if original_row.empty or perturbed_row.empty: + print(f"序号 {sequence_id} 在一个或两个文件中不存在!") + return + + # 提取时间序列数据(从第3列开始) + original_series = original_row.iloc[0, 2:].values + perturbed_series = perturbed_row.iloc[0, 2:].values + + # 创建x轴数据点 + x = np.arange(len(original_series)) + + # 设置图形大小和布局 + fig = plt.figure(figsize=(8, 5)) + + # 创建主图 + ax_main = plt.subplot(111) + ax_main.plot(x, original_series, label='origin', color='blue', linewidth=2) + ax_main.plot(x, perturbed_series, label='perturbed', color='red', linewidth=2) + ax_main.legend(prop={'family': 'Times New Roman', 'size': 16}) + ax_main.set_xlabel(r'$\beta=$' + f'{beta}', fontsize=24) + ax_main.grid(True, linestyle='--', alpha=0.7) + + # 增大主图坐标轴刻度字体 + ax_main.tick_params(axis='both', labelsize=20) + + # 如果提供了放大区域,添加子图和矩形框 + if zoom_start is not None and zoom_end is not None: + # 确保缩放范围有效 + zoom_start = max(0, min(zoom_start, len(original_series)-1)) + zoom_end = max(zoom_start+1, min(zoom_end, len(original_series))) + + # 计算放大区域的y轴范围 + min_y = min(min(original_series[zoom_start:zoom_end]), min(perturbed_series[zoom_start:zoom_end])) + max_y = max(max(original_series[zoom_start:zoom_end]), max(perturbed_series[zoom_start:zoom_end])) + y_margin = (max_y - min_y) * 0.1 # 10% 的边距 + + # 添加矩形框表示放大区域 + rect = Rectangle((zoom_start, min_y - y_margin), + zoom_end - zoom_start, + (max_y - min_y) + 2 * y_margin, + fill=False, edgecolor='gray', linestyle='--', linewidth=1.5) + ax_main.add_patch(rect) + + # 创建放大子图 - 调整位置到上方,缩小尺寸 + # 对主图对象进行调整 + box = ax_main.get_position() + ax_main.set_position([box.x0, box.y0, box.width, box.height * 0.9]) + + # 放大图放在上方,位置和大小调整 + left = sub_offset # 右侧位置 + bottom = 0.65 # 上方位置 + width = 0.35 # 缩小宽度 + height = 0.30 # 缩小高度 + + # 创建子图 + ax_zoom = fig.add_axes([left, bottom, width, height]) + ax_zoom.plot(x[zoom_start:zoom_end], original_series[zoom_start:zoom_end], color='blue', linewidth=2) + ax_zoom.plot(x[zoom_start:zoom_end], perturbed_series[zoom_start:zoom_end], color='red', linewidth=2) + ax_zoom.grid(True, linestyle='--', alpha=0.7) + + # 隐藏子图的坐标轴刻度数字 + ax_zoom.set_xticklabels([]) + ax_zoom.set_yticklabels([]) + + # 调整子图显示范围,添加一点边距 + ax_zoom.set_xlim(zoom_start, zoom_end) + ax_zoom.set_ylim(min_y - y_margin, max_y + y_margin) + + plt.tight_layout() + + # 保存图片 + output_filename = f'time_series_comparison_{beta}_{sequence_id}.pdf' + plt.savefig(output_filename) + print(f"图像已保存为 {output_filename}") + + # 显示图像 + plt.show() + +# python draw_line_compare.py --original /Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/factor/ECG200/0_02/ori_time_series0.txt --perturbed /Users/catb/Library/CloudStorage/CloudMounter-B40-4/home/BJTU/project/CPadv/CCPP实验结果/factor/ECG200/0_02/attack_time_series0.txt --id 2 --beta 0.02 --zoom-start 60 --zoom-end 80 +if __name__ == "__main__": + parser = argparse.ArgumentParser(description='绘制时间序列对比图') + parser.add_argument('--original', type=str, required=True, help='原始时间序列文件路径') + parser.add_argument('--perturbed', type=str, required=True, help='攻击/扰动时间序列文件路径') + parser.add_argument('--id', type=int, required=True, help='要绘制的时间序列序号') + parser.add_argument('--beta', type=float, default=0.01, help='beta参数值') + parser.add_argument('--zoom-start', type=int, help='放大区域的起始索引') + parser.add_argument('--zoom-end', type=int, help='放大区域的结束索引') + parser.add_argument('--sub_offset', type=float, help='放大子图向右偏移量') + + args = parser.parse_args() + + plot_time_series( + args.original, + args.perturbed, + args.id, + args.beta, + args.zoom_start, + args.zoom_end, + args.sub_offset + ) \ No newline at end of file diff --git a/filter_figures_folder.py b/utils_pack/filter_figures_folder.py similarity index 100% rename from filter_figures_folder.py rename to utils_pack/filter_figures_folder.py diff --git a/utils_pack/line_compare_command.txt b/utils_pack/line_compare_command.txt new file mode 100644 index 0000000..51941e2 --- /dev/null +++ b/utils_pack/line_compare_command.txt @@ -0,0 +1,3 @@ +python draw_line_compare.py --original ..\CCPP实验结果\factor\Lightning7\0_01\ori_time_series0.txt --perturbed ..\CCPP实验结果\factor\Lightning7\0_01\attack_time_series0.txt --id 1 --beta 0.01 --zoom-start 200 --zoom-end 225 --sub_offset 0.35 +python draw_line_compare.py --original ..\CCPP实验结果\factor\Lightning7\0_02\ori_time_series0.txt --perturbed ..\CCPP实验结果\factor\Lightning7\0_02\attack_time_series0.txt --id 1 --beta 0.02 --zoom-start 200 --zoom-end 225 --sub_offset 0.35 +python draw_line_compare.py --original ..\CCPP实验结果\factor\Lightning7\0_04\ori_time_series0.txt --perturbed ..\CCPP实验结果\factor\Lightning7\0_04\attack_time_series0.txt --id 1 --beta 0.04 --zoom-start 200 --zoom-end 225 --sub_offset 0.35