paperplotter 0.1.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. examples/Data_Analysis_Utils/data_analysis_utils_example.png +0 -0
  2. examples/Data_Analysis_Utils/data_analysis_utils_example.py +81 -0
  3. examples/Data_Analysis_Utils/utility_functions_example.png +0 -0
  4. examples/Data_Analysis_Utils/utility_functions_example.py +82 -0
  5. examples/Domain_Specific_Plots/bifurcation_diagram_example.png +0 -0
  6. examples/Domain_Specific_Plots/bifurcation_diagram_example.py +70 -0
  7. examples/Domain_Specific_Plots/concentration_map_example.png +0 -0
  8. examples/Domain_Specific_Plots/concentration_map_example.py +54 -0
  9. examples/Domain_Specific_Plots/domain_specific_plots.png +0 -0
  10. examples/Domain_Specific_Plots/domain_specific_plots_example.py +104 -0
  11. examples/Domain_Specific_Plots/learning_curve_example.png +0 -0
  12. examples/Domain_Specific_Plots/learning_curve_example.py +86 -0
  13. examples/Domain_Specific_Plots/phasor_diagram_example.png +0 -0
  14. examples/Domain_Specific_Plots/phasor_diagram_example.py +49 -0
  15. examples/Domain_Specific_Plots/power_timeseries_example.png +0 -0
  16. examples/Domain_Specific_Plots/power_timeseries_example.py +65 -0
  17. examples/Features_Customization/advanced_customization.py +70 -0
  18. examples/Features_Customization/advanced_customization_figure.png +0 -0
  19. examples/Features_Customization/cleanup_demonstration.py +62 -0
  20. examples/Features_Customization/cleanup_demonstration_figure.png +0 -0
  21. examples/Features_Customization/composite_figure.png +0 -0
  22. examples/Features_Customization/composite_figure_example.py +88 -0
  23. examples/Features_Customization/error_handling_test.py +75 -0
  24. examples/Features_Customization/feature_expansion_example.py +84 -0
  25. examples/Features_Customization/feature_expansion_figure.png +0 -0
  26. examples/Features_Customization/fig_annotation_example.png +0 -0
  27. examples/Features_Customization/fig_annotation_example.py +72 -0
  28. examples/Features_Customization/fig_text_example.png +0 -0
  29. examples/Features_Customization/fig_text_example.py +51 -0
  30. examples/Features_Customization/global_controls_example.py +66 -0
  31. examples/Features_Customization/global_controls_figure.png +0 -0
  32. examples/Features_Customization/heatmap_colorbar_example.py +68 -0
  33. examples/Features_Customization/heatmap_default_figure.png +0 -0
  34. examples/Features_Customization/heatmap_shared_colorbar_figure.png +0 -0
  35. examples/Features_Customization/highlighting_example.png +0 -0
  36. examples/Features_Customization/highlighting_example.py +62 -0
  37. examples/Features_Customization/multi_plot_grid.py +91 -0
  38. examples/Features_Customization/multi_plot_grid_figure.png +0 -0
  39. examples/Features_Customization/resources/placeholder_image.png +0 -0
  40. examples/Layout/advanced_layout_example.py +70 -0
  41. examples/Layout/advanced_layout_figure.png +0 -0
  42. examples/Layout/aspect_ratio_example.py +72 -0
  43. examples/Layout/aspect_ratio_mosaic.png +0 -0
  44. examples/Layout/aspect_ratio_simple_grid.png +0 -0
  45. examples/Layout/block_span_example.py +64 -0
  46. examples/Layout/block_span_figure.png +0 -0
  47. examples/Layout/declarative_nested_layout.png +0 -0
  48. examples/Layout/declarative_nested_layout_example.py +91 -0
  49. examples/Layout/row_span_example.py +68 -0
  50. examples/Layout/row_span_figure.png +0 -0
  51. examples/Styles_Aesthetics/aesthetic_and_processing_example.png +0 -0
  52. examples/Styles_Aesthetics/aesthetic_and_processing_example.py +85 -0
  53. examples/Styles_Aesthetics/statistical_annotation_example.png +0 -0
  54. examples/Styles_Aesthetics/statistical_annotation_example.py +65 -0
  55. examples/Styles_Aesthetics/style_gallery_example.py +64 -0
  56. examples/Styles_Aesthetics/style_gallery_flat.png +0 -0
  57. examples/Styles_Aesthetics/style_gallery_nord.png +0 -0
  58. examples/Styles_Aesthetics/style_gallery_presentation.png +0 -0
  59. examples/Styles_Aesthetics/style_gallery_publication.png +0 -0
  60. examples/Styles_Aesthetics/style_gallery_solarized_light.png +0 -0
  61. paperplot/__init__.py +30 -0
  62. paperplot/core.py +254 -0
  63. paperplot/exceptions.py +35 -0
  64. paperplot/mixins/__init__.py +1 -0
  65. paperplot/mixins/domain.py +331 -0
  66. paperplot/mixins/generic.py +95 -0
  67. paperplot/mixins/modifiers.py +504 -0
  68. paperplot/styles/flat.mplstyle +40 -0
  69. paperplot/styles/nord.mplstyle +44 -0
  70. paperplot/styles/presentation.mplstyle +41 -0
  71. paperplot/styles/publication.mplstyle +24 -0
  72. paperplot/styles/solarized_light.mplstyle +44 -0
  73. paperplot/utils.py +510 -0
  74. paperplotter-0.1.4.dist-info/METADATA +163 -0
  75. paperplotter-0.1.4.dist-info/RECORD +78 -0
  76. paperplotter-0.1.4.dist-info/WHEEL +5 -0
  77. paperplotter-0.1.4.dist-info/licenses/LICENSE +21 -0
  78. paperplotter-0.1.4.dist-info/top_level.txt +2 -0
@@ -0,0 +1,81 @@
1
+ # examples/data_analysis_utils_example.py
2
+
3
+ import paperplot as pp
4
+ import pandas as pd
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+ from scipy import stats
8
+
9
+ print(f"--- Running Example: {__file__} ---")
10
+
11
+ # --- 1. 准备数据 ---
12
+ # 分布拟合示例数据
13
+ np.random.seed(42)
14
+ normal_data = np.random.normal(loc=0, scale=1, size=1000)
15
+ df_dist = pd.DataFrame({'value': normal_data})
16
+
17
+ # 数据分箱示例数据
18
+ x_bin = np.linspace(0, 10, 200)
19
+ y_bin = 2 * x_bin + np.random.normal(loc=0, scale=2, size=200)
20
+ df_bin = pd.DataFrame({'x': x_bin, 'y': y_bin})
21
+
22
+
23
+ # --- 2. 创建绘图 ---
24
+ try:
25
+ plotter = pp.Plotter(layout=(1, 2), figsize=(12, 5))
26
+ plotter.set_suptitle("Data Analysis Utilities", fontsize=16, weight='bold')
27
+
28
+ # --- 3. 左图: 分布拟合 ---
29
+ ax_dist = plotter.get_ax_by_name('ax00')
30
+ plotter.tag_to_ax['dist'] = ax_dist # 手动关联tag
31
+
32
+ # 绘制直方图
33
+ ax_dist.hist(df_dist['value'], bins=30, density=True, alpha=0.6, color='skyblue', label='Data Histogram')
34
+
35
+ # 拟合并绘制正态分布
36
+ pp.utils.fit_and_plot_distribution(
37
+ ax=ax_dist,
38
+ data_series=df_dist['value'],
39
+ dist_name='norm',
40
+ color='red',
41
+ linestyle='--',
42
+ lw=2
43
+ )
44
+
45
+ plotter.set_title('dist', 'fit_and_plot_distribution() Example')
46
+ plotter.set_xlabel('dist', 'Value')
47
+ plotter.set_ylabel('dist', 'Density')
48
+ plotter.set_legend('dist')
49
+
50
+ # --- 4. 右图: 数据分箱 ---
51
+ ax_bin = plotter.get_ax_by_name('ax01')
52
+ plotter.tag_to_ax['bin'] = ax_bin
53
+
54
+ # 绘制原始散点图
55
+ ax_bin.scatter(df_bin['x'], df_bin['y'], alpha=0.3, label='Raw Data')
56
+
57
+ # 分箱数据
58
+ binned_df = pp.utils.bin_data(df_bin, x='x', y='y', bins=5)
59
+
60
+ # 绘制分箱后的结果(带误差棒的线图)
61
+ ax_bin.errorbar(binned_df['bin_center'], binned_df['y_agg'],
62
+ yerr=binned_df['y_error'], fmt='-o', color='green',
63
+ capsize=5, label='Binned Data (Mean ± Std)')
64
+
65
+ plotter.set_title('bin', 'bin_data() Example')
66
+ plotter.set_xlabel('bin', 'X Value')
67
+ plotter.set_ylabel('bin', 'Y Value')
68
+ plotter.set_legend('bin')
69
+
70
+
71
+ # --- 5. 清理和保存 ---
72
+ plotter.cleanup()
73
+ plotter.save("data_analysis_utils_example.png")
74
+
75
+ except Exception as e:
76
+ print(f"An unexpected error occurred: {e}")
77
+ finally:
78
+ plt.close('all')
79
+
80
+ print(f"\n--- Finished Example: {__file__} ---")
81
+ print("A new file 'data_analysis_utils_example.png' was generated.")
@@ -0,0 +1,82 @@
1
+ # examples/utility_functions_example.py
2
+
3
+ import paperplot as pp
4
+ import pandas as pd
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+
8
+ print(f"--- Running Example: {__file__} ---")
9
+
10
+ # --- 1. 准备数据 ---
11
+
12
+ # SERS 光谱数据
13
+ x_spec = np.linspace(400, 1800, 1000)
14
+ y_spec = (0.8 * np.exp(-((x_spec - 600)**2) / (2 * 30**2)) +
15
+ 0.6 * np.exp(-((x_spec - 1200)**2) / (2 * 50**2)) +
16
+ np.random.rand(1000) * 0.1)
17
+ spectra_df = pd.DataFrame({'wavenumber': x_spec, 'intensity': y_spec})
18
+ peaks_to_highlight = [600, 1200]
19
+
20
+
21
+ # 时间序列数据
22
+ time = np.linspace(0, 100, 200)
23
+ signal = np.sin(time / 10) * np.exp(time / 50) + np.random.randn(200) * 0.1
24
+ timeseries_df = pd.DataFrame({'time': time, 'signal': signal})
25
+ event_points = [25, 50, 80]
26
+ event_labels = ['Fault', 'Clear', 'Load Shed']
27
+
28
+
29
+ # --- 2. 创建一个 1x2 的布局 ---
30
+ try:
31
+ plotter = pp.Plotter(layout=(1, 2), figsize=(12, 5))
32
+ plotter.set_suptitle("Utility Functions Demonstration", fontsize=16, weight='bold')
33
+
34
+ # --- 3. 左侧子图: 高亮光谱峰 ---
35
+ plotter.add_line(data=spectra_df, x='wavenumber', y='intensity', tag='spectra')
36
+ plotter.set_title('spectra', 'highlight_peaks() Example')
37
+ plotter.set_xlabel('spectra', 'Wavenumber (cm⁻¹)')
38
+ plotter.set_ylabel('spectra', 'Intensity (a.u.)')
39
+
40
+ # 调用 utils 函数
41
+ ax_spectra = plotter.get_ax('spectra')
42
+ pp.utils.highlight_peaks(
43
+ ax=ax_spectra,
44
+ x=spectra_df['wavenumber'],
45
+ y=spectra_df['intensity'],
46
+ peaks_x=peaks_to_highlight,
47
+ label_positions={
48
+ 1200: (1250, 0.4) # 手动将1200峰的标签移动到右下方
49
+ },
50
+ ha='center' # 水平居中
51
+ )
52
+
53
+ # --- 4. 右侧子图: 标记时间序列事件 ---
54
+ plotter.add_line(data=timeseries_df, x='time', y='signal', tag='timeseries', color='navy')
55
+ plotter.set_title('timeseries', 'add_event_markers() Example')
56
+ plotter.set_xlabel('timeseries', 'Time (s)')
57
+ plotter.set_ylabel('timeseries', 'Signal Value')
58
+
59
+ # 调用 utils 函数
60
+ ax_timeseries = plotter.get_ax('timeseries')
61
+ pp.utils.add_event_markers(
62
+ ax=ax_timeseries,
63
+ event_dates=event_points,
64
+ labels=event_labels,
65
+ label_positions={
66
+ 25: (15, 2.5) # 手动移动 'Fault' 标签
67
+ }
68
+ )
69
+
70
+ # --- 5. 清理和保存 ---
71
+ plotter.cleanup(align_labels=True)
72
+ plotter.save("utility_functions_example.png")
73
+
74
+ except (pp.PaperPlotError, ValueError) as e:
75
+ print(f"\nAn error occurred:\n{e}")
76
+ except Exception as e:
77
+ print(f"An unexpected error occurred: {e}")
78
+ finally:
79
+ plt.close('all')
80
+
81
+ print(f"\n--- Finished Example: {__file__} ---")
82
+ print("A new file 'utility_functions_example.png' was generated.")
@@ -0,0 +1,70 @@
1
+ # examples/bifurcation_diagram_example.py
2
+
3
+ import paperplot as pp
4
+ import pandas as pd
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+
8
+ print(f"--- Running Example: {__file__} ---")
9
+
10
+ # --- 1. 准备数据 ---
11
+ # 模拟一个典型分岔图的数据(逻辑斯蒂映射)
12
+ def logistic_map(r, x):
13
+ return r * x * (1 - x)
14
+
15
+ n_steps = 1000
16
+ n_transient = 200 # 忽略前面的瞬态过程
17
+ r_values = np.linspace(2.5, 4.0, 2000)
18
+ x_values = []
19
+ bifurcation_param = []
20
+
21
+ for r in r_values:
22
+ x = 0.1 # 初始值
23
+ # 迭代瞬态过程
24
+ for _ in range(n_transient):
25
+ x = logistic_map(r, x)
26
+ # 记录稳定后的值
27
+ for _ in range(n_steps):
28
+ x = logistic_map(r, x)
29
+ x_values.append(x)
30
+ bifurcation_param.append(r)
31
+
32
+ df_bifurcation = pd.DataFrame({
33
+ 'r': bifurcation_param,
34
+ 'x': x_values
35
+ })
36
+
37
+
38
+ # --- 2. 创建绘图 ---
39
+ try:
40
+ plotter = pp.Plotter(layout=(1, 1), figsize=(8, 6))
41
+ # 使用 plotter.add_scatter 直接绘图,并指定 tag=1
42
+ # 这会自动处理坐标轴的获取和标签的注册
43
+ plotter.add_scatter(
44
+ data=df_bifurcation,
45
+ x='r',
46
+ y='x',
47
+ tag=1, # 显式指定 tag
48
+ s=0.001,
49
+ alpha=0.2,
50
+ marker='.',
51
+ rasterized=True # 对于有大量数据点的图,设为True可以提高渲染性能
52
+ )
53
+
54
+ # --- 3. 设置标题和标签 ---
55
+ # 现在 tag=1 已经被正确注册,可以安全使用
56
+ plotter.set_title(1, 'Bifurcation Diagram of the Logistic Map')
57
+ plotter.set_xlabel(1, 'Parameter r')
58
+ plotter.set_ylabel(1, 'State x')
59
+
60
+ # --- 4. 清理和保存 ---
61
+ plotter.cleanup()
62
+ plotter.save("bifurcation_diagram_example.png")
63
+
64
+ except Exception as e:
65
+ print(f"An unexpected error occurred: {e}")
66
+ finally:
67
+ plt.close('all')
68
+
69
+ print(f"\n--- Finished Example: {__file__} ---")
70
+ print("A new file 'bifurcation_diagram_example.png' was generated.")
@@ -0,0 +1,54 @@
1
+ # examples/concentration_map_example.py
2
+
3
+ import paperplot as pp
4
+ import pandas as pd
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+
8
+ print(f"--- Running Example: {__file__} ---")
9
+
10
+ # --- 1. 准备数据 ---
11
+ # 模拟一个SERS浓度图数据
12
+ np.random.seed(42)
13
+ grid_size = 20
14
+ x_coords = np.arange(grid_size)
15
+ y_coords = np.arange(grid_size)
16
+ X, Y = np.meshgrid(x_coords, y_coords)
17
+
18
+ # 创建一个中心有高浓度,边缘浓度逐渐降低的模拟数据
19
+ center_x, center_y = grid_size / 2, grid_size / 2
20
+ sigma = 5
21
+ concentration = np.exp(-((X - center_x)**2 + (Y - center_y)**2) / (2 * sigma**2))
22
+ concentration += np.random.rand(grid_size, grid_size) * 0.1 # 添加一些噪声
23
+
24
+ # 转换为DataFrame
25
+ df_concentration = pd.DataFrame(concentration, index=y_coords, columns=x_coords)
26
+
27
+ # --- 2. 创建绘图 ---
28
+ try:
29
+ plotter = pp.Plotter(layout=(1, 1), figsize=(7, 6))
30
+
31
+ # 使用新的 add_concentration_map 方法
32
+ plotter.add_concentration_map(
33
+ data=df_concentration,
34
+ tag='sers_map',
35
+ cbar_kws={'label': 'Concentration (a.u.)'} # 自定义颜色条标签
36
+ )
37
+
38
+ # --- 3. 设置标题和标签 ---
39
+ plotter.set_title('sers_map', 'SERS Concentration Map Example')
40
+ # X, Y 轴标签已由 add_concentration_map 默认设置,但可以覆盖
41
+ # plotter.set_xlabel('sers_map', 'Position X (µm)')
42
+ # plotter.set_ylabel('sers_map', 'Position Y (µm)')
43
+
44
+ # --- 4. 清理和保存 ---
45
+ plotter.cleanup()
46
+ plotter.save("concentration_map_example.png")
47
+
48
+ except Exception as e:
49
+ print(f"An unexpected error occurred: {e}")
50
+ finally:
51
+ plt.close('all')
52
+
53
+ print(f"\n--- Finished Example: {__file__} ---")
54
+ print("A new file 'concentration_map_example.png' was generated.")
@@ -0,0 +1,104 @@
1
+ # examples/domain_specific_plots_example.py
2
+
3
+ import paperplot as pp
4
+ import pandas as pd
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+ from sklearn.metrics import confusion_matrix, roc_curve, auc
8
+ from sklearn.preprocessing import label_binarize
9
+ from sklearn.decomposition import PCA
10
+
11
+ print(f"--- Running Example: {__file__} ---")
12
+
13
+ # --- 1. 准备数据 ---
14
+
15
+ # SERS 光谱数据
16
+ def generate_spectra_data(num_spectra=3):
17
+ x = np.linspace(400, 1800, 500)
18
+ df = pd.DataFrame({'wavenumber': x})
19
+ for i in range(num_spectra):
20
+ peak_pos = np.random.uniform(600, 1600)
21
+ peak_width = np.random.uniform(50, 150)
22
+ peak_intensity = np.random.uniform(0.5, 1)
23
+ noise = np.random.rand(500) * 0.05
24
+ y = peak_intensity * np.exp(-((x - peak_pos)**2) / (2 * peak_width**2)) + noise
25
+ df[f'Sample_{i+1}'] = y
26
+ return df
27
+
28
+ spectra_df = generate_spectra_data()
29
+
30
+ # 机器学习数据
31
+ y_true = np.array([0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2])
32
+ y_score = np.random.rand(12, 3) # 模拟分类器的得分输出
33
+ y_pred = np.argmax(y_score, axis=1)
34
+ class_names = ['Class A', 'Class B', 'Class C']
35
+
36
+ # 混淆矩阵
37
+ cm = confusion_matrix(y_true, y_pred)
38
+
39
+ # ROC 曲线数据
40
+ y_true_bin = label_binarize(y_true, classes=[0, 1, 2])
41
+ n_classes = y_true_bin.shape[1]
42
+ fpr, tpr, roc_auc = dict(), dict(), dict()
43
+ for i in range(n_classes):
44
+ fpr[class_names[i]], tpr[class_names[i]], _ = roc_curve(y_true_bin[:, i], y_score[:, i])
45
+ roc_auc[class_names[i]] = auc(fpr[class_names[i]], tpr[class_names[i]])
46
+
47
+ # PCA 数据
48
+ pca_data = np.random.rand(50, 10)
49
+ pca = PCA(n_components=2)
50
+ pca_result = pca.fit_transform(pca_data)
51
+ pca_df = pd.DataFrame(data=pca_result, columns=['PC1', 'PC2'])
52
+ pca_df['Category'] = np.random.choice(['Group X', 'Group Y'], 50)
53
+
54
+
55
+ # --- 2. 创建一个 2x2 的布局 ---
56
+ try:
57
+ plotter = pp.Plotter(layout=(2, 2), figsize=(12, 10))
58
+ plotter.set_suptitle("Domain-Specific Plotting Functions", fontsize=16, weight='bold')
59
+
60
+ # --- Top-Left: SERS 光谱 ---
61
+ y_cols = [col for col in spectra_df.columns if col.startswith('Sample')]
62
+ plotter.add_spectra(
63
+ data=spectra_df, x='wavenumber', y_cols=y_cols, tag='spectra', offset=0.5
64
+ )
65
+ plotter.set_title('spectra', 'SERS Spectra with Offset')
66
+ plotter.set_xlabel('spectra', 'Wavenumber (cm⁻¹)')
67
+ plotter.set_ylabel('spectra', 'Intensity (a.u.)')
68
+ plotter.set_legend('spectra')
69
+
70
+ # --- Top-Right: 混淆矩阵 ---
71
+ plotter.add_confusion_matrix(
72
+ matrix=cm, class_names=class_names, tag='cm', normalize=True
73
+ )
74
+ plotter.set_title('cm', 'Normalized Confusion Matrix')
75
+
76
+ # --- Bottom-Left: ROC 曲线 ---
77
+ plotter.add_roc_curve(
78
+ fpr=fpr, tpr=tpr, roc_auc=roc_auc, tag='roc'
79
+ )
80
+ # add_roc_curve 已经设置了大部分标题和标签,我们也可以覆盖它们
81
+ plotter.set_title('roc', 'Multi-Class ROC Curves')
82
+
83
+ # --- Bottom-Right: PCA 散点图 ---
84
+ plotter.add_pca_scatter(
85
+ data=pca_df, x_pc='PC1', y_pc='PC2', hue='Category', tag='pca'
86
+ )
87
+ plotter.set_title('pca', 'PCA Scatter Plot')
88
+ plotter.set_xlabel('pca', f'Principal Component 1 ({pca.explained_variance_ratio_[0]:.1%})')
89
+ plotter.set_ylabel('pca', f'Principal Component 2 ({pca.explained_variance_ratio_[1]:.1%})')
90
+
91
+
92
+ # --- 5. 清理和保存 ---
93
+ plotter.cleanup(align_labels=True)
94
+ plotter.save("domain_specific_plots.png")
95
+
96
+ except (pp.PaperPlotError, ValueError) as e:
97
+ print(f"\nAn error occurred:\n{e}")
98
+ except Exception as e:
99
+ print(f"An unexpected error occurred: {e}")
100
+ finally:
101
+ plt.close('all')
102
+
103
+ print(f"\n--- Finished Example: {__file__} ---")
104
+ print("An updated file 'domain_specific_plots.png' was generated with 4 plots.")
@@ -0,0 +1,86 @@
1
+ # examples/learning_curve_example.py
2
+
3
+ import paperplot as pp
4
+ import numpy as np
5
+ import matplotlib.pyplot as plt
6
+
7
+ print(f"--- Running Example: {__file__} ---")
8
+
9
+ # --- 1. 准备数据 ---
10
+ # 模拟 scikit-learn 中 learning_curve 函数的输出
11
+ np.random.seed(0)
12
+ train_sizes = np.linspace(.1, 1.0, 5)
13
+ n_folds = 5
14
+ n_ticks = len(train_sizes)
15
+
16
+ # 模拟一个欠拟合模型的得分
17
+ train_scores_underfit = np.random.rand(n_ticks, n_folds) * 0.1 + 0.6
18
+ test_scores_underfit = np.random.rand(n_ticks, n_folds) * 0.1 + 0.55
19
+
20
+ # 模拟一个理想模型的得分
21
+ train_scores_good = 0.95 - np.logspace(-1, -2, n_ticks)[:, np.newaxis] * (0.1 + np.random.rand(n_ticks, n_folds) * 0.1)
22
+ test_scores_good = 0.9 - np.logspace(-1, -2, n_ticks)[:, np.newaxis] * (0.1 + np.random.rand(n_ticks, n_folds) * 0.1)
23
+
24
+ # 模拟一个过拟合模型的得分
25
+ train_scores_overfit = np.ones((n_ticks, n_folds)) * 0.99 - np.random.rand(n_ticks, n_folds) * 0.01
26
+ test_scores_overfit = 0.7 - np.linspace(0, 0.2, n_ticks)[:, np.newaxis] + np.random.rand(n_ticks, n_folds) * 0.05
27
+
28
+
29
+ # --- 2. 创建绘图 ---
30
+ try:
31
+ plotter = pp.Plotter(layout=(1, 3), figsize=(18, 5))
32
+ plotter.set_suptitle("Learning Curve Examples", fontsize=16, weight='bold')
33
+
34
+ # --- 3. 绘制三个学习曲线 ---
35
+ # 理想模型
36
+ ax_good = plotter.get_ax_by_name('ax00')
37
+ pp.utils.plot_learning_curve(
38
+ ax=ax_good,
39
+ train_sizes=train_sizes * 1000, # 假设最多1000个样本
40
+ train_scores=train_scores_good,
41
+ test_scores=test_scores_good,
42
+ title='Good Fit',
43
+ color='blue'
44
+ )
45
+ plotter.tag_to_ax['good_fit'] = ax_good # 手动关联tag
46
+
47
+ # 欠拟合模型
48
+ ax_underfit = plotter.get_ax_by_name('ax01')
49
+ pp.utils.plot_learning_curve(
50
+ ax=ax_underfit,
51
+ train_sizes=train_sizes * 1000,
52
+ train_scores=train_scores_underfit,
53
+ test_scores=test_scores_underfit,
54
+ title='Underfitting',
55
+ color='orange'
56
+ )
57
+ plotter.tag_to_ax['underfit'] = ax_underfit
58
+
59
+ # 过拟合模型
60
+ ax_overfit = plotter.get_ax_by_name('ax02')
61
+ pp.utils.plot_learning_curve(
62
+ ax=ax_overfit,
63
+ train_sizes=train_sizes * 1000,
64
+ train_scores=train_scores_overfit,
65
+ test_scores=test_scores_overfit,
66
+ title='Overfitting',
67
+ color='red'
68
+ )
69
+ plotter.tag_to_ax['overfit'] = ax_overfit
70
+
71
+ # --- 4. 统一Y轴范围以便比较 ---
72
+ plotter.set_ylim('good_fit', 0.4, 1.05)
73
+ plotter.set_ylim('underfit', 0.4, 1.05)
74
+ plotter.set_ylim('overfit', 0.4, 1.05)
75
+
76
+ # --- 5. 清理和保存 ---
77
+ plotter.cleanup()
78
+ plotter.save("learning_curve_example.png")
79
+
80
+ except Exception as e:
81
+ print(f"An unexpected error occurred: {e}")
82
+ finally:
83
+ plt.close('all')
84
+
85
+ print(f"\n--- Finished Example: {__file__} ---")
86
+ print("A new file 'learning_curve_example.png' was generated.")
@@ -0,0 +1,49 @@
1
+ # examples/phasor_diagram_example.py
2
+
3
+ import paperplot as pp
4
+ import pandas as pd
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+
8
+ print(f"--- Running Example: {__file__} ---")
9
+
10
+ # --- 1. 准备数据 ---
11
+ # 示例相量数据
12
+ magnitudes = [1.0, 0.8, 1.2]
13
+ angels = [0, 90, -45] # 角度,单位为度
14
+ labels = ['V_ref', 'I_load', 'V_bus']
15
+
16
+ # --- 2. 创建绘图 ---
17
+ try:
18
+ # 初始化Plotter,创建一个普通的笛卡尔轴
19
+ # add_phasor_diagram 会自动将其转换为极坐标
20
+ plotter = pp.Plotter(
21
+ layout=(1, 1),
22
+ figsize=(8, 8),
23
+ ax_configs={'ax00': {'projection': 'polar'}} # 明确指定ax00为极坐标轴
24
+ )
25
+
26
+ # 添加相量图
27
+ plotter.add_phasor_diagram(
28
+ magnitudes=[1.0, 0.8, 1.2],
29
+ angles=[0, 90, -45],
30
+ labels=['V_ref', 'I_load', 'V_bus'],
31
+ tag='ax00', # 使用布局中定义的tag
32
+ angle_unit='degrees'
33
+ )
34
+
35
+ # 获取极坐标轴并设置标题
36
+ ax = plotter.get_ax('ax00')
37
+ ax.set_title('Phasor Diagram Example', va='bottom')
38
+
39
+ # --- 3. 清理和保存 ---
40
+ plotter.cleanup()
41
+ plotter.save("phasor_diagram_example.png")
42
+
43
+ except Exception as e:
44
+ print(f"An unexpected error occurred: {e}")
45
+ finally:
46
+ plt.close('all')
47
+
48
+ print(f"\n--- Finished Example: {__file__} ---")
49
+ print("A new file 'phasor_diagram_example.png' was generated.")
@@ -0,0 +1,65 @@
1
+ # examples/power_timeseries_example.py
2
+
3
+ import paperplot as pp
4
+ import pandas as pd
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+
8
+ print(f"--- Running Example: {__file__} ---")
9
+
10
+ # --- 1. 准备数据 ---
11
+ # 模拟一个电力系统动态过程
12
+ np.random.seed(0)
13
+ time = np.linspace(0, 5, 500)
14
+ # 基础信号
15
+ base_signal = 0.98 + 0.02 * np.sin(time * 5)
16
+ # 故障期间的电压跌落
17
+ fault_dip = -0.5 * (np.exp(-(time - 1.1)**2 / 0.01))
18
+ # 故障切除后的恢复振荡
19
+ recovery_oscillation = 0.05 * np.sin((time - 1.2) * 20) * np.exp(-(time - 1.2) / 1.5)
20
+
21
+ # 信号组合
22
+ voltage = base_signal + fault_dip + recovery_oscillation
23
+ frequency = 60 - 0.5 * (np.exp(-(time - 1.1)**2 / 0.02)) + 0.1 * np.sin((time - 1.2) * 15) * np.exp(-(time - 1.2))
24
+
25
+ df = pd.DataFrame({
26
+ 'time': time,
27
+ 'Voltage (p.u.)': voltage,
28
+ 'Frequency (Hz)': frequency
29
+ })
30
+
31
+ # 定义事件
32
+ events = {
33
+ 'Fault On': 1.0,
34
+ 'Fault Cleared': 1.2
35
+ }
36
+
37
+ # --- 2. 创建绘图 ---
38
+ try:
39
+ plotter = pp.Plotter(layout=(1, 1), figsize=(8, 5))
40
+
41
+ # 使用新的 add_power_timeseries 方法
42
+ plotter.add_power_timeseries(
43
+ data=df,
44
+ x='time',
45
+ y_cols=['Voltage (p.u.)', 'Frequency (Hz)'], # 这里我们把两个不同单位的信号画在一起了,仅为演示
46
+ tag='power_dynamics',
47
+ events=events
48
+ )
49
+
50
+ # --- 3. 设置标题和标签 ---
51
+ # add_power_timeseries 已经设置了默认标签,但我们可以覆盖它们
52
+ plotter.set_title('power_dynamics', 'Power System Dynamic Simulation')
53
+ plotter.set_ylabel('power_dynamics', 'Value') # 保持通用标签
54
+
55
+ # --- 4. 清理和保存 ---
56
+ plotter.cleanup()
57
+ plotter.save("power_timeseries_example.png")
58
+
59
+ except Exception as e:
60
+ print(f"An unexpected error occurred: {e}")
61
+ finally:
62
+ plt.close('all')
63
+
64
+ print(f"\n--- Finished Example: {__file__} ---")
65
+ print("A new file 'power_timeseries_example.png' was generated.")
@@ -0,0 +1,70 @@
1
+ # examples/advanced_customization.py
2
+
3
+ import paperplot as pp
4
+ import pandas as pd
5
+ import numpy as np
6
+ import matplotlib.pyplot as plt
7
+ from matplotlib.patches import Ellipse
8
+
9
+ print(f"--- Running Example: {__file__} ---")
10
+
11
+ # --- 1. 定义一个自定义美化模板 ---
12
+ def custom_template(fig, axes):
13
+ """
14
+ 一个自定义模板,它会给图表加上一个灰色背景,并用虚线绘制网格。
15
+ Args:
16
+ fig (plt.Figure): The main figure object.
17
+ axes (list[plt.Axes]): A list of axes to apply the template to.
18
+ """
19
+ print("\nApplying CUSTOM cleanup template...")
20
+ for ax in axes:
21
+ ax.set_facecolor('#f0f0f0') # 设置背景颜色
22
+ ax.grid(True, linestyle='--', color='white', linewidth=1.5)
23
+ ax.spines['top'].set_visible(False)
24
+ ax.spines['right'].set_visible(False)
25
+ ax.spines['left'].set_color('gray')
26
+ ax.spines['bottom'].set_color('gray')
27
+
28
+ # --- 2. 准备数据 ---
29
+ df = pd.DataFrame({
30
+ 'x': np.random.gumbel(size=100),
31
+ 'y': np.random.gumbel(size=100)
32
+ })
33
+
34
+ # --- 3. 初始化并绘图 ---
35
+ try:
36
+ plotter = pp.Plotter(figsize=(6, 6), layout=(1, 1))
37
+
38
+ # 注册我们的自定义模板
39
+ print("Registering custom cleanup template named 'gray_grid'...")
40
+ # plotter.register_cleanup_template('gray_grid', custom_template)
41
+
42
+ plotter.add_scatter(data=df, x='x', y='y', tag='gumbel_dist')
43
+
44
+ # --- 4. 使用 "逃生舱口" get_ax() 进行高级定制 ---
45
+ print("Using get_ax() for advanced customization...")
46
+ # 假设我们要添加一个matplotlib原生对象,比如一个椭圆
47
+ ax = plotter.get_ax('gumbel_dist')
48
+
49
+ # 创建一个椭圆 Patch
50
+ ellipse = Ellipse(xy=(0, 0), width=2, height=4, angle=30,
51
+ facecolor='none', edgecolor='red', linestyle='--', lw=2)
52
+ ax.add_patch(ellipse)
53
+
54
+ # 设置标题和标签
55
+ plotter.set_title('gumbel_dist', 'Gumbel Distribution with Ellipse')
56
+ plotter.set_xlabel('gumbel_dist', 'X value')
57
+ plotter.set_ylabel('gumbel_dist', 'Y value')
58
+
59
+ # --- 5. 使用自定义模板进行美化并保存 ---
60
+ plotter.cleanup()
61
+ plotter.save("advanced_customization_figure.png")
62
+
63
+ except pp.PaperPlotError as e:
64
+ print(f"\nA PaperPlot error occurred:\n{e}")
65
+ except Exception as e:
66
+ print(f"An unexpected error occurred: {e}")
67
+ finally:
68
+ plt.close('all')
69
+
70
+ print(f"--- Finished Example: {__file__} ---")