paperplotter 0.1.2__tar.gz → 0.1.4__tar.gz

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 (107) hide show
  1. {paperplotter-0.1.2/paperplotter.egg-info → paperplotter-0.1.4}/PKG-INFO +21 -7
  2. {paperplotter-0.1.2 → paperplotter-0.1.4}/README.md +20 -6
  3. paperplotter-0.1.4/examples/Data_Analysis_Utils/utility_functions_example.png +0 -0
  4. paperplotter-0.1.4/examples/Domain_Specific_Plots/bifurcation_diagram_example.png +0 -0
  5. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Domain_Specific_Plots/bifurcation_diagram_example.py +10 -7
  6. paperplotter-0.1.4/examples/Domain_Specific_Plots/domain_specific_plots.png +0 -0
  7. paperplotter-0.1.4/examples/Domain_Specific_Plots/phasor_diagram_example.png +0 -0
  8. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Domain_Specific_Plots/phasor_diagram_example.py +7 -3
  9. paperplotter-0.1.4/examples/Features_Customization/advanced_customization_figure.png +0 -0
  10. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Features_Customization/cleanup_demonstration.py +4 -2
  11. paperplotter-0.1.4/examples/Features_Customization/cleanup_demonstration_figure.png +0 -0
  12. paperplotter-0.1.4/examples/Features_Customization/composite_figure.png +0 -0
  13. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Features_Customization/composite_figure_example.py +1 -1
  14. paperplotter-0.1.4/examples/Features_Customization/feature_expansion_figure.png +0 -0
  15. paperplotter-0.1.4/examples/Features_Customization/fig_annotation_example.png +0 -0
  16. paperplotter-0.1.4/examples/Features_Customization/fig_annotation_example.py +72 -0
  17. paperplotter-0.1.4/examples/Features_Customization/fig_text_example.png +0 -0
  18. paperplotter-0.1.4/examples/Features_Customization/fig_text_example.py +51 -0
  19. paperplotter-0.1.4/examples/Features_Customization/global_controls_figure.png +0 -0
  20. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Features_Customization/heatmap_colorbar_example.py +2 -2
  21. paperplotter-0.1.4/examples/Features_Customization/heatmap_default_figure.png +0 -0
  22. paperplotter-0.1.4/examples/Features_Customization/heatmap_shared_colorbar_figure.png +0 -0
  23. paperplotter-0.1.4/examples/Features_Customization/highlighting_example.png +0 -0
  24. paperplotter-0.1.4/examples/Features_Customization/highlighting_example.py +62 -0
  25. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Features_Customization/multi_plot_grid.py +5 -1
  26. paperplotter-0.1.4/examples/Features_Customization/multi_plot_grid_figure.png +0 -0
  27. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Layout/advanced_layout_example.py +1 -1
  28. paperplotter-0.1.4/examples/Layout/advanced_layout_figure.png +0 -0
  29. paperplotter-0.1.4/examples/Layout/block_span_figure.png +0 -0
  30. paperplotter-0.1.4/examples/Layout/declarative_nested_layout.png +0 -0
  31. paperplotter-0.1.4/examples/Layout/declarative_nested_layout_example.py +91 -0
  32. paperplotter-0.1.4/examples/Layout/row_span_figure.png +0 -0
  33. paperplotter-0.1.4/examples/Styles_Aesthetics/style_gallery_flat.png +0 -0
  34. paperplotter-0.1.4/examples/Styles_Aesthetics/style_gallery_nord.png +0 -0
  35. paperplotter-0.1.4/examples/Styles_Aesthetics/style_gallery_presentation.png +0 -0
  36. paperplotter-0.1.4/examples/Styles_Aesthetics/style_gallery_publication.png +0 -0
  37. paperplotter-0.1.4/examples/Styles_Aesthetics/style_gallery_solarized_light.png +0 -0
  38. paperplotter-0.1.4/paperplot/core.py +254 -0
  39. paperplotter-0.1.4/paperplot/mixins/__init__.py +1 -0
  40. paperplotter-0.1.4/paperplot/mixins/domain.py +331 -0
  41. paperplotter-0.1.4/paperplot/mixins/generic.py +95 -0
  42. paperplotter-0.1.4/paperplot/mixins/modifiers.py +504 -0
  43. {paperplotter-0.1.2 → paperplotter-0.1.4/paperplotter.egg-info}/PKG-INFO +21 -7
  44. paperplotter-0.1.4/paperplotter.egg-info/SOURCES.txt +83 -0
  45. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplotter.egg-info/top_level.txt +1 -0
  46. {paperplotter-0.1.2 → paperplotter-0.1.4}/pyproject.toml +1 -1
  47. paperplotter-0.1.2/examples/advanced_customization_figure.png +0 -0
  48. paperplotter-0.1.2/examples/advanced_layout_figure.png +0 -0
  49. paperplotter-0.1.2/examples/block_span_figure.png +0 -0
  50. paperplotter-0.1.2/examples/cleanup_demonstration_figure.png +0 -0
  51. paperplotter-0.1.2/examples/composite_figure.png +0 -0
  52. paperplotter-0.1.2/examples/domain_specific_plots.png +0 -0
  53. paperplotter-0.1.2/examples/feature_expansion_figure.png +0 -0
  54. paperplotter-0.1.2/examples/global_controls_figure.png +0 -0
  55. paperplotter-0.1.2/examples/heatmap_default_figure.png +0 -0
  56. paperplotter-0.1.2/examples/heatmap_shared_colorbar_figure.png +0 -0
  57. paperplotter-0.1.2/examples/multi_plot_grid_figure.png +0 -0
  58. paperplotter-0.1.2/examples/presentation_style_figure.png +0 -0
  59. paperplotter-0.1.2/examples/publication_style_figure.png +0 -0
  60. paperplotter-0.1.2/examples/row_span_figure.png +0 -0
  61. paperplotter-0.1.2/examples/style_gallery_flat.png +0 -0
  62. paperplotter-0.1.2/examples/style_gallery_nord.png +0 -0
  63. paperplotter-0.1.2/examples/style_gallery_presentation.png +0 -0
  64. paperplotter-0.1.2/examples/style_gallery_publication.png +0 -0
  65. paperplotter-0.1.2/examples/style_gallery_solarized_light.png +0 -0
  66. paperplotter-0.1.2/examples/utility_functions_example.png +0 -0
  67. paperplotter-0.1.2/paperplot/core.py +0 -1256
  68. paperplotter-0.1.2/paperplotter.egg-info/SOURCES.txt +0 -71
  69. {paperplotter-0.1.2 → paperplotter-0.1.4}/LICENSE +0 -0
  70. {paperplotter-0.1.2 → paperplotter-0.1.4}/MANIFEST.in +0 -0
  71. {paperplotter-0.1.2/examples → paperplotter-0.1.4/examples/Data_Analysis_Utils}/data_analysis_utils_example.png +0 -0
  72. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Data_Analysis_Utils/data_analysis_utils_example.py +0 -0
  73. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Data_Analysis_Utils/utility_functions_example.py +0 -0
  74. {paperplotter-0.1.2/examples → paperplotter-0.1.4/examples/Domain_Specific_Plots}/concentration_map_example.png +0 -0
  75. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Domain_Specific_Plots/concentration_map_example.py +0 -0
  76. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Domain_Specific_Plots/domain_specific_plots_example.py +0 -0
  77. {paperplotter-0.1.2/examples → paperplotter-0.1.4/examples/Domain_Specific_Plots}/learning_curve_example.png +0 -0
  78. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Domain_Specific_Plots/learning_curve_example.py +0 -0
  79. {paperplotter-0.1.2/examples → paperplotter-0.1.4/examples/Domain_Specific_Plots}/power_timeseries_example.png +0 -0
  80. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Domain_Specific_Plots/power_timeseries_example.py +0 -0
  81. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Features_Customization/advanced_customization.py +0 -0
  82. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Features_Customization/error_handling_test.py +0 -0
  83. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Features_Customization/feature_expansion_example.py +0 -0
  84. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Features_Customization/global_controls_example.py +0 -0
  85. {paperplotter-0.1.2/examples → paperplotter-0.1.4/examples/Features_Customization}/resources/placeholder_image.png +0 -0
  86. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Layout/aspect_ratio_example.py +0 -0
  87. {paperplotter-0.1.2/examples → paperplotter-0.1.4/examples/Layout}/aspect_ratio_mosaic.png +0 -0
  88. {paperplotter-0.1.2/examples → paperplotter-0.1.4/examples/Layout}/aspect_ratio_simple_grid.png +0 -0
  89. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Layout/block_span_example.py +0 -0
  90. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Layout/row_span_example.py +0 -0
  91. {paperplotter-0.1.2/examples → paperplotter-0.1.4/examples/Styles_Aesthetics}/aesthetic_and_processing_example.png +0 -0
  92. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Styles_Aesthetics/aesthetic_and_processing_example.py +0 -0
  93. {paperplotter-0.1.2/examples → paperplotter-0.1.4/examples/Styles_Aesthetics}/statistical_annotation_example.png +0 -0
  94. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Styles_Aesthetics/statistical_annotation_example.py +0 -0
  95. {paperplotter-0.1.2 → paperplotter-0.1.4}/examples/Styles_Aesthetics/style_gallery_example.py +0 -0
  96. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplot/__init__.py +0 -0
  97. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplot/exceptions.py +0 -0
  98. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplot/styles/flat.mplstyle +0 -0
  99. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplot/styles/nord.mplstyle +0 -0
  100. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplot/styles/presentation.mplstyle +0 -0
  101. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplot/styles/publication.mplstyle +0 -0
  102. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplot/styles/solarized_light.mplstyle +0 -0
  103. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplot/utils.py +0 -0
  104. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplotter.egg-info/dependency_links.txt +0 -0
  105. {paperplotter-0.1.2 → paperplotter-0.1.4}/paperplotter.egg-info/requires.txt +0 -0
  106. {paperplotter-0.1.2 → paperplotter-0.1.4}/setup.cfg +0 -0
  107. {paperplotter-0.1.2 → paperplotter-0.1.4}/tests/test_plotter.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: paperplotter
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: 一个为科研论文设计的声明式 Matplotlib 封装库,让复杂图表的创建变得简单直观。
5
5
  Author-email: VerNe <yuu_seeing@foxmail.com>
6
6
  License-Expression: MIT
@@ -35,8 +35,11 @@ Dynamic: license-file
35
35
 
36
36
  * **🎨 声明式链式调用**: 像写句子一样构建你的图表,例如 `plotter.add_line(...).set_title(...).set_xlabel(...)`。
37
37
  * **🏷️ 基于标签的控制**: 给每个子图一个独一无二的 `tag`,之后就可以随时通过 `tag` 对其进行任何修改,告别混乱的 `axes[i][j]` 索引。
38
- * **🧩 强大的布局系统**: 无论是简单的 `(行, 列)` 网格,还是使用 `subplot_mosaic` 实现的跨行跨列复杂布局,都能轻松定义。
38
+ * **🧩 强大的布局系统**: 无论是简单的 `(行, 列)` 网格,还是使用 `mosaic` 实现的跨行跨列复杂布局,都能轻松定义。
39
+ * **🧱 声明式嵌套布局**: 通过一个字典即可一次性定义包含子网格的复杂层级布局,并使用 `'容器.子图'` 这样的直观路径进行引用,完美实现“图中图”。
40
+ * **📐 灵活的尺寸控制**: 除了传统的 `figsize`,还可以通过 `subplot_aspect` 指定子图单元格的宽高比,让 `PaperPlot` 自动计算最合适的画布尺寸。
39
41
  * **✨ 内置科研主题**: 提供多种专业美观的内置样式,如 `publication`, `presentation` 等,一键切换图表风格。
42
+ * **🌐 全局图层级标注**: 提供了在整个画布(Figure)上添加文本、线条、方框和标签的 API,非常适合添加全局注释或高亮一组图表。
40
43
  * **🔬 丰富的领域专用图表**: 内置了科研中常用的图表类型,如光谱图、混淆矩阵、ROC 曲线、学习曲线、分岔图、相量图等。
41
44
  * **🔧 智能美化工具**: `cleanup()` 方法可以智能地共享坐标轴、对齐标签;`cleanup_heatmaps()` 可以为多个热图创建共享的颜色条。
42
45
 
@@ -66,10 +69,13 @@ df_scatter = pd.DataFrame({
66
69
  })
67
70
 
68
71
  # 2. 初始化 Plotter 并绘图
72
+ # 对于简单布局,可以直接使用元组 (rows, cols)
69
73
  plotter = pp.Plotter(layout=(1, 2), figsize=(10, 4))
70
74
 
71
- # 3. 添加图表并使用 tag 标记
75
+ # 3. 顺序添加图表,Plotter会自动填充网格
76
+ # 第一次调用 add_line 会画在左边
72
77
  plotter.add_line(data=df_line, x='time', y='signal', tag='time_series')
78
+ # 第二次调用 add_scatter 会画在右边
73
79
  plotter.add_scatter(data=df_scatter, x='x', y='y', tag='scatter_plot')
74
80
 
75
81
  # 4. 通过 tag 设置标题和标签
@@ -94,7 +100,8 @@ plotter.save("quick_start_figure.png")
94
100
 
95
101
  | 示例 | 描述 | 关键功能 |
96
102
  | :--- | :--- | :--- |
97
- | **高级布局**<br/> `Layout/advanced_layout_example.py` | 展示如何使用列表定义一个跨列的复杂布局。 | `layout=[['A', 'B', 'B'], ...]`<br/>`get_ax_by_name()` |
103
+ | **声明式嵌套布局**<br/> `Layout/declarative_nested_layout_example.py` | 使用字典来声明式地定义一个包含子网格的复杂、多层级布局,实现“图中图”的效果。 | `layout={...}`<br/> `tag='容器.子图'` |
104
+ | **高级布局**<br/> `Layout/advanced_layout_example.py` | 展示如何使用列表定义一个跨列的复杂布局。 | `layout=[['A', 'B', 'B'], ...]` |
98
105
  | **行跨越**<br/> `Layout/row_span_example.py` | 创建一个图表,其中某个子图跨越多行。 | `layout=[['A', 'B'], ['A', 'C']]` |
99
106
  | **块跨越**<br/> `Layout/block_span_example.py` | 创建一个图表,其中某个子图同时跨越多行和多列。 | `layout=[['A', 'A', 'B'], ['A', 'A', 'C']]` |
100
107
  | **固定子图宽高比**<br/> `Layout/aspect_ratio_example.py` | 在不指定 `figsize` 的情况下,通过 `subplot_aspect` 保证每个子图单元格的宽高比,Plotter 会自动计算画布大小。 | `subplot_aspect=(16, 9)` |
@@ -103,15 +110,22 @@ plotter.save("quick_start_figure.png")
103
110
 
104
111
  | 示例 | 描述 | 关键功能 |
105
112
  | :--- | :--- | :--- |
106
- | **多图网格**<br/> `Features_Customization/multi_plot_grid.py` | 在一个网格中混合绘制不同类型的图表(线图、柱状图、散点图、热图)。 | `add_line()`, `add_bar()`, `add_scatter()`, `add_heatmap()` |
113
+ | **多图网格**<br/> `Features_Customization/multi_plot_grid.py` | 在一个网格中通过链式调用混合绘制不同类型的图表。 | `plotter.add_...().add_...()` |
107
114
  | **高级定制**<br/> `Features_Customization/advanced_customization.py` | 演示如何使用 `get_ax()` "逃生舱口" 来获取原生的 Matplotlib `Axes` 对象,并添加任意 `Patch`(如椭圆)。 | `get_ax()`, `ax.add_patch()` |
108
115
  | **全局控制**<br/> `Features_Customization/global_controls_example.py` | 展示如何设置全局标题 (`suptitle`) 和创建全局图例。 | `set_suptitle()`, `add_global_legend()` |
109
116
  | **共享颜色条**<br/> `Features_Customization/heatmap_colorbar_example.py` | 为多个热图创建一个共享的、能反映全局数据范围的颜色条。 | `add_heatmap(cbar=False)`, `cleanup_heatmaps()` |
110
- | **智能清理**<br/> `Features_Customization/cleanup_demonstration.py` | 演示 `cleanup()` 函数如何动态地为指定行/列的子图共享 X/Y 轴,并自动隐藏多余的刻度标签。 | `cleanup(share_y_on_rows=...)`, `cleanup(share_x_on_cols=...)` |
117
+ | **智能清理**<br/> `Features_Customization/cleanup_demonstration.py` | 演示 `cleanup()` 函数如何动态地为指定行/列的子图共享 X/Y 轴,并自动隐藏多余的刻度标签。 | `cleanup(auto_share=True)` |
111
118
  | **组合图与内嵌图**<br/> `Features_Customization/composite_figure_example.py` | 创建一个 L 型的复杂图表,并在其中一个子图内部嵌入一张图片。 | `layout=[['A', 'A'], ['B', '.']]`, `add_inset_image()` |
112
119
  | **功能扩展**<br/> `Features_Customization/feature_expansion_example.py` | 演示双Y轴 (`add_twinx`)、回归图 (`add_regplot`)、参考线 (`add_hline`) 和文本标注 (`add_text`) 等高级功能。 | `add_twinx()`, `add_regplot()`, `add_hline()`, `add_text()` |
113
120
  | **错误处理**<br/> `Features_Customization/error_handling_test.py` | 展示 `PaperPlot` 的自定义异常,如 `DuplicateTagError`, `TagNotFoundError`, `PlottingSpaceError`。 | `try...except pp.PaperPlotError` |
114
121
 
122
+ ### 标注与高亮 (Annotation & Highlighting)
123
+
124
+ | 示例 | 描述 | 关键功能 |
125
+ | :--- | :--- | :--- |
126
+ | **图层级标注**<br/>`Features_Customization/fig_annotation_example.py`| 演示添加跨越多个子图的画布级注解,如方框、标签和线条。| `fig_add_box()`, `fig_add_label()`, `fig_add_line()`, `fig_add_text()`|
127
+ | **区域高亮**<br/>`Features_Customization/highlighting_example.py` | 展示如何在子图内部高亮特定的数据区域,并为整个图表添加边框。| `add_highlight_box()`, `fig_add_boundary_box()` |
128
+
115
129
  ### 风格与美化 (Styles & Aesthetics)
116
130
 
117
131
  | 示例 | 描述 | 关键功能 |
@@ -129,7 +143,7 @@ plotter.save("quick_start_figure.png")
129
143
  | **SERS 浓度图**<br/> `Domain_Specific_Plots/concentration_map_example.py` | 绘制 SERS Mapping 浓度图,本质上是带有专业美化的热图。 | `add_concentration_map()` |
130
144
  | **电力系统时间序列**<br/> `Domain_Specific_Plots/power_timeseries_example.py` | 绘制电力系统动态仿真结果,并自动标记故障、切除等事件。 | `add_power_timeseries()` |
131
145
  | **相量图**<br/> `Domain_Specific_Plots/phasor_diagram_example.py` | 在极坐标上绘制电气工程中的相量图。 | `add_phasor_diagram()` |
132
- | **分岔图**<br/> `Domain_Specific_Plots/bifurcation_diagram_example.py` | 绘制常用于非线性系统和稳定性分析的分岔图。 | `utils.plot_bifurcation_diagram()` |
146
+ | **分岔图**<br/> `Domain_Specific_Plots/bifurcation_diagram_example.py` | 绘制常用于非线性系统和稳定性分析的分岔图。 | `add_scatter(rasterized=True)` |
133
147
 
134
148
  ### 数据分析工具 (Data Analysis Utils)
135
149
 
@@ -11,8 +11,11 @@
11
11
 
12
12
  * **🎨 声明式链式调用**: 像写句子一样构建你的图表,例如 `plotter.add_line(...).set_title(...).set_xlabel(...)`。
13
13
  * **🏷️ 基于标签的控制**: 给每个子图一个独一无二的 `tag`,之后就可以随时通过 `tag` 对其进行任何修改,告别混乱的 `axes[i][j]` 索引。
14
- * **🧩 强大的布局系统**: 无论是简单的 `(行, 列)` 网格,还是使用 `subplot_mosaic` 实现的跨行跨列复杂布局,都能轻松定义。
14
+ * **🧩 强大的布局系统**: 无论是简单的 `(行, 列)` 网格,还是使用 `mosaic` 实现的跨行跨列复杂布局,都能轻松定义。
15
+ * **🧱 声明式嵌套布局**: 通过一个字典即可一次性定义包含子网格的复杂层级布局,并使用 `'容器.子图'` 这样的直观路径进行引用,完美实现“图中图”。
16
+ * **📐 灵活的尺寸控制**: 除了传统的 `figsize`,还可以通过 `subplot_aspect` 指定子图单元格的宽高比,让 `PaperPlot` 自动计算最合适的画布尺寸。
15
17
  * **✨ 内置科研主题**: 提供多种专业美观的内置样式,如 `publication`, `presentation` 等,一键切换图表风格。
18
+ * **🌐 全局图层级标注**: 提供了在整个画布(Figure)上添加文本、线条、方框和标签的 API,非常适合添加全局注释或高亮一组图表。
16
19
  * **🔬 丰富的领域专用图表**: 内置了科研中常用的图表类型,如光谱图、混淆矩阵、ROC 曲线、学习曲线、分岔图、相量图等。
17
20
  * **🔧 智能美化工具**: `cleanup()` 方法可以智能地共享坐标轴、对齐标签;`cleanup_heatmaps()` 可以为多个热图创建共享的颜色条。
18
21
 
@@ -42,10 +45,13 @@ df_scatter = pd.DataFrame({
42
45
  })
43
46
 
44
47
  # 2. 初始化 Plotter 并绘图
48
+ # 对于简单布局,可以直接使用元组 (rows, cols)
45
49
  plotter = pp.Plotter(layout=(1, 2), figsize=(10, 4))
46
50
 
47
- # 3. 添加图表并使用 tag 标记
51
+ # 3. 顺序添加图表,Plotter会自动填充网格
52
+ # 第一次调用 add_line 会画在左边
48
53
  plotter.add_line(data=df_line, x='time', y='signal', tag='time_series')
54
+ # 第二次调用 add_scatter 会画在右边
49
55
  plotter.add_scatter(data=df_scatter, x='x', y='y', tag='scatter_plot')
50
56
 
51
57
  # 4. 通过 tag 设置标题和标签
@@ -70,7 +76,8 @@ plotter.save("quick_start_figure.png")
70
76
 
71
77
  | 示例 | 描述 | 关键功能 |
72
78
  | :--- | :--- | :--- |
73
- | **高级布局**<br/> `Layout/advanced_layout_example.py` | 展示如何使用列表定义一个跨列的复杂布局。 | `layout=[['A', 'B', 'B'], ...]`<br/>`get_ax_by_name()` |
79
+ | **声明式嵌套布局**<br/> `Layout/declarative_nested_layout_example.py` | 使用字典来声明式地定义一个包含子网格的复杂、多层级布局,实现“图中图”的效果。 | `layout={...}`<br/> `tag='容器.子图'` |
80
+ | **高级布局**<br/> `Layout/advanced_layout_example.py` | 展示如何使用列表定义一个跨列的复杂布局。 | `layout=[['A', 'B', 'B'], ...]` |
74
81
  | **行跨越**<br/> `Layout/row_span_example.py` | 创建一个图表,其中某个子图跨越多行。 | `layout=[['A', 'B'], ['A', 'C']]` |
75
82
  | **块跨越**<br/> `Layout/block_span_example.py` | 创建一个图表,其中某个子图同时跨越多行和多列。 | `layout=[['A', 'A', 'B'], ['A', 'A', 'C']]` |
76
83
  | **固定子图宽高比**<br/> `Layout/aspect_ratio_example.py` | 在不指定 `figsize` 的情况下,通过 `subplot_aspect` 保证每个子图单元格的宽高比,Plotter 会自动计算画布大小。 | `subplot_aspect=(16, 9)` |
@@ -79,15 +86,22 @@ plotter.save("quick_start_figure.png")
79
86
 
80
87
  | 示例 | 描述 | 关键功能 |
81
88
  | :--- | :--- | :--- |
82
- | **多图网格**<br/> `Features_Customization/multi_plot_grid.py` | 在一个网格中混合绘制不同类型的图表(线图、柱状图、散点图、热图)。 | `add_line()`, `add_bar()`, `add_scatter()`, `add_heatmap()` |
89
+ | **多图网格**<br/> `Features_Customization/multi_plot_grid.py` | 在一个网格中通过链式调用混合绘制不同类型的图表。 | `plotter.add_...().add_...()` |
83
90
  | **高级定制**<br/> `Features_Customization/advanced_customization.py` | 演示如何使用 `get_ax()` "逃生舱口" 来获取原生的 Matplotlib `Axes` 对象,并添加任意 `Patch`(如椭圆)。 | `get_ax()`, `ax.add_patch()` |
84
91
  | **全局控制**<br/> `Features_Customization/global_controls_example.py` | 展示如何设置全局标题 (`suptitle`) 和创建全局图例。 | `set_suptitle()`, `add_global_legend()` |
85
92
  | **共享颜色条**<br/> `Features_Customization/heatmap_colorbar_example.py` | 为多个热图创建一个共享的、能反映全局数据范围的颜色条。 | `add_heatmap(cbar=False)`, `cleanup_heatmaps()` |
86
- | **智能清理**<br/> `Features_Customization/cleanup_demonstration.py` | 演示 `cleanup()` 函数如何动态地为指定行/列的子图共享 X/Y 轴,并自动隐藏多余的刻度标签。 | `cleanup(share_y_on_rows=...)`, `cleanup(share_x_on_cols=...)` |
93
+ | **智能清理**<br/> `Features_Customization/cleanup_demonstration.py` | 演示 `cleanup()` 函数如何动态地为指定行/列的子图共享 X/Y 轴,并自动隐藏多余的刻度标签。 | `cleanup(auto_share=True)` |
87
94
  | **组合图与内嵌图**<br/> `Features_Customization/composite_figure_example.py` | 创建一个 L 型的复杂图表,并在其中一个子图内部嵌入一张图片。 | `layout=[['A', 'A'], ['B', '.']]`, `add_inset_image()` |
88
95
  | **功能扩展**<br/> `Features_Customization/feature_expansion_example.py` | 演示双Y轴 (`add_twinx`)、回归图 (`add_regplot`)、参考线 (`add_hline`) 和文本标注 (`add_text`) 等高级功能。 | `add_twinx()`, `add_regplot()`, `add_hline()`, `add_text()` |
89
96
  | **错误处理**<br/> `Features_Customization/error_handling_test.py` | 展示 `PaperPlot` 的自定义异常,如 `DuplicateTagError`, `TagNotFoundError`, `PlottingSpaceError`。 | `try...except pp.PaperPlotError` |
90
97
 
98
+ ### 标注与高亮 (Annotation & Highlighting)
99
+
100
+ | 示例 | 描述 | 关键功能 |
101
+ | :--- | :--- | :--- |
102
+ | **图层级标注**<br/>`Features_Customization/fig_annotation_example.py`| 演示添加跨越多个子图的画布级注解,如方框、标签和线条。| `fig_add_box()`, `fig_add_label()`, `fig_add_line()`, `fig_add_text()`|
103
+ | **区域高亮**<br/>`Features_Customization/highlighting_example.py` | 展示如何在子图内部高亮特定的数据区域,并为整个图表添加边框。| `add_highlight_box()`, `fig_add_boundary_box()` |
104
+
91
105
  ### 风格与美化 (Styles & Aesthetics)
92
106
 
93
107
  | 示例 | 描述 | 关键功能 |
@@ -105,7 +119,7 @@ plotter.save("quick_start_figure.png")
105
119
  | **SERS 浓度图**<br/> `Domain_Specific_Plots/concentration_map_example.py` | 绘制 SERS Mapping 浓度图,本质上是带有专业美化的热图。 | `add_concentration_map()` |
106
120
  | **电力系统时间序列**<br/> `Domain_Specific_Plots/power_timeseries_example.py` | 绘制电力系统动态仿真结果,并自动标记故障、切除等事件。 | `add_power_timeseries()` |
107
121
  | **相量图**<br/> `Domain_Specific_Plots/phasor_diagram_example.py` | 在极坐标上绘制电气工程中的相量图。 | `add_phasor_diagram()` |
108
- | **分岔图**<br/> `Domain_Specific_Plots/bifurcation_diagram_example.py` | 绘制常用于非线性系统和稳定性分析的分岔图。 | `utils.plot_bifurcation_diagram()` |
122
+ | **分岔图**<br/> `Domain_Specific_Plots/bifurcation_diagram_example.py` | 绘制常用于非线性系统和稳定性分析的分岔图。 | `add_scatter(rasterized=True)` |
109
123
 
110
124
  ### 数据分析工具 (Data Analysis Utils)
111
125
 
@@ -38,18 +38,21 @@ df_bifurcation = pd.DataFrame({
38
38
  # --- 2. 创建绘图 ---
39
39
  try:
40
40
  plotter = pp.Plotter(layout=(1, 1), figsize=(8, 6))
41
- ax = plotter.get_ax(1) # 获取第一个ax
42
-
43
- # 使用新的 plot_bifurcation_diagram 函数
44
- pp.utils.plot_bifurcation_diagram(
45
- ax=ax,
41
+ # 使用 plotter.add_scatter 直接绘图,并指定 tag=1
42
+ # 这会自动处理坐标轴的获取和标签的注册
43
+ plotter.add_scatter(
46
44
  data=df_bifurcation,
47
45
  x='r',
48
- y='x'
46
+ y='x',
47
+ tag=1, # 显式指定 tag
48
+ s=0.001,
49
+ alpha=0.2,
50
+ marker='.',
51
+ rasterized=True # 对于有大量数据点的图,设为True可以提高渲染性能
49
52
  )
50
53
 
51
54
  # --- 3. 设置标题和标签 ---
52
- # 函数已设置默认值,这里可以覆盖
55
+ # 现在 tag=1 已经被正确注册,可以安全使用
53
56
  plotter.set_title(1, 'Bifurcation Diagram of the Logistic Map')
54
57
  plotter.set_xlabel(1, 'Parameter r')
55
58
  plotter.set_ylabel(1, 'State x')
@@ -17,19 +17,23 @@ labels = ['V_ref', 'I_load', 'V_bus']
17
17
  try:
18
18
  # 初始化Plotter,创建一个普通的笛卡尔轴
19
19
  # add_phasor_diagram 会自动将其转换为极坐标
20
- plotter = pp.Plotter(layout=(1, 1), figsize=(8, 8))
20
+ plotter = pp.Plotter(
21
+ layout=(1, 1),
22
+ figsize=(8, 8),
23
+ ax_configs={'ax00': {'projection': 'polar'}} # 明确指定ax00为极坐标轴
24
+ )
21
25
 
22
26
  # 添加相量图
23
27
  plotter.add_phasor_diagram(
24
28
  magnitudes=[1.0, 0.8, 1.2],
25
29
  angles=[0, 90, -45],
26
30
  labels=['V_ref', 'I_load', 'V_bus'],
27
- tag='phasor_ax',
31
+ tag='ax00', # 使用布局中定义的tag
28
32
  angle_unit='degrees'
29
33
  )
30
34
 
31
35
  # 获取极坐标轴并设置标题
32
- ax = plotter.get_ax('phasor_ax')
36
+ ax = plotter.get_ax('ax00')
33
37
  ax.set_title('Phasor Diagram Example', va='bottom')
34
38
 
35
39
  # --- 3. 清理和保存 ---
@@ -5,6 +5,8 @@ import pandas as pd
5
5
  import numpy as np
6
6
  import matplotlib.pyplot as plt
7
7
 
8
+ from paperplot import Plotter
9
+
8
10
  print(f"--- Running Example: {__file__} ---")
9
11
 
10
12
  # --- 1. 准备一组适合共享坐标轴的数据 ---
@@ -24,7 +26,7 @@ df4 = generate_data(offset=1)
24
26
  # 目的是为了后续演示 cleanup 函数如何动态地创建共享关系
25
27
  try:
26
28
  print("Creating a 2x2 plot with INDEPENDENT axes...")
27
- plotter = pp.Plotter(n_rows=2, n_cols=2, figsize=(10, 8), sharex=False, sharey=False)
29
+ plotter = Plotter(layout=(2, 2), figsize=(10, 8), style='flat')
28
30
 
29
31
  # --- 3. 填充图表 ---
30
32
  plotter.add_line(data=df1, x='time', y='signal', tag='cond1')
@@ -44,7 +46,7 @@ try:
44
46
  # 我们指令cleanup函数:
45
47
  # - 对第0行和第1行的Y轴进行共享和清理
46
48
  # - 对第0列和第1列的X轴进行共享和清理
47
- plotter.cleanup(share_y_on_rows=[0, 1], share_x_on_cols=[0, 1])
49
+ plotter.cleanup(auto_share=True)
48
50
 
49
51
  # --- 6. 保存图像 ---
50
52
  plotter.save("cleanup_demonstration_figure.png")
@@ -51,7 +51,7 @@ try:
51
51
  print("Adding an inset image to the 'SERS_Spectra' plot...")
52
52
  plotter.add_inset_image(
53
53
  host_tag='spectra_A',
54
- image_path='./resources/placeholder_image.png',
54
+ image_path='./examples/Features_Customization/resources/placeholder_image.png',
55
55
  rect=[0.7, 0.65, 0.28, 0.28] # [x, y, width, height] in relative coordinates
56
56
  )
57
57
 
@@ -0,0 +1,72 @@
1
+ # examples/Features_Customization/fig_annotation_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
+ try:
11
+ # 1. Create a Plotter instance with a 2x2 layout
12
+ plotter = pp.Plotter(layout=(2, 2), figsize=(12, 10), style='publication')
13
+
14
+ # 2. Add some plots to the subplots
15
+ df = pd.DataFrame({
16
+ 'x': np.linspace(0, 10, 50),
17
+ 'y1': np.sin(np.linspace(0, 10, 50)),
18
+ 'y2': np.cos(np.linspace(0, 10, 50)),
19
+ 'y3': np.random.rand(50) * 5
20
+ })
21
+
22
+ plotter.add_line(data=df, x='x', y='y1', tag='ax00', label='Sine')
23
+ plotter.set_title('ax00', 'Top-Left Plot')
24
+ plotter.set_legend('ax00')
25
+
26
+ plotter.add_scatter(data=df, x='x', y='y2', tag='ax01', label='Cosine', marker='o')
27
+ plotter.set_title('ax01', 'Top-Right Plot')
28
+ plotter.set_legend('ax01')
29
+
30
+ plotter.add_hist(data=df, x='y3', tag='ax10', bins=10, color='skyblue')
31
+ plotter.set_title('ax10', 'Bottom-Left Plot')
32
+
33
+ plotter.add_bar(data=pd.DataFrame({'cat': ['A', 'B', 'C'], 'val': [1, 3, 2]}), x='cat', y='val', tag='ax11')
34
+ plotter.set_title('ax11', 'Bottom-Right Plot')
35
+
36
+ # Apply cleanup for shared axes
37
+ plotter.cleanup(auto_share=True)
38
+
39
+ # 3. Use the new global figure-level annotation APIs
40
+
41
+ # fig_add_text
42
+ plotter.fig_add_text(0.5, 0.96, 'Comprehensive Figure Analysis', ha='center', va='top', fontsize=16, weight='bold', color='darkblue')
43
+ plotter.fig_add_text(0.02, 0.02, 'Generated by PaperPlot', ha='left', va='bottom', fontsize=8, style='italic')
44
+
45
+ # fig_add_line - draw a line across the figure
46
+ plotter.fig_add_line([0.1, 0.9], [0.5, 0.5], color='red', linestyle=':', linewidth=2)
47
+ plotter.fig_add_text(0.5, 0.51, 'Mid-Figure Separator', ha='center', va='bottom', color='red', fontsize=10)
48
+
49
+ # fig_add_box - box around top row plots
50
+ plotter.fig_add_box(tags=['ax00', 'ax01'], padding=0.01, edgecolor='green', linewidth=2, linestyle='-')
51
+ plotter.fig_add_label(tags=['ax00', 'ax01'], text='Top Row Insights', position='top_center', padding=0.02, fontsize=12, color='green')
52
+
53
+ # fig_add_box - box around bottom-left plot
54
+ plotter.fig_add_box(tags='ax10', padding=0.005, edgecolor='purple', linewidth=1, linestyle='-.')
55
+ plotter.fig_add_label(tags='ax10', text='Distribution', position='bottom_right', padding=0.01, fontsize=10, color='purple')
56
+
57
+ # fig_add_label - label for the entire figure (relative to all axes)
58
+ plotter.fig_add_label(tags=['ax00', 'ax01', 'ax10', 'ax11'], text='Overall Study Results', position='right_center', padding=0.05, rotation=-90, fontsize=14, color='gray')
59
+
60
+
61
+ # 4. Save the figure
62
+ plotter.save("fig_annotation_example.png")
63
+
64
+ except pp.PaperPlotError as e:
65
+ print(f"\nA PaperPlot error occurred:\n{e}")
66
+ except Exception as e:
67
+ print(f"An unexpected error occurred: {e}")
68
+ finally:
69
+ plt.close('all')
70
+
71
+ print(f"--- Finished Example: {__file__} ---")
72
+ print("A new file 'fig_annotation_example.png' was generated.")
@@ -0,0 +1,51 @@
1
+ # examples/Features_Customization/fig_text_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
+ try:
11
+ # 1. Create a Plotter instance with a 1x2 layout
12
+ plotter = pp.Plotter(layout=(1, 2), figsize=(10, 5), style='publication')
13
+
14
+ # 2. Add some plots to the subplots
15
+ df = pd.DataFrame({
16
+ 'x': np.linspace(0, 10, 100),
17
+ 'y1': np.sin(np.linspace(0, 10, 100)),
18
+ 'y2': np.cos(np.linspace(0, 10, 100))
19
+ })
20
+
21
+ plotter.add_line(data=df, x='x', y='y1', tag='ax00', label='Sine Wave')
22
+ plotter.set_title('ax00', 'Left Subplot')
23
+ plotter.set_xlabel('ax00', 'X-axis')
24
+ plotter.set_ylabel('ax00', 'Y-axis')
25
+ plotter.set_legend('ax00')
26
+
27
+ plotter.add_scatter(data=df, x='x', y='y2', tag='ax01', label='Cosine Points', marker='o', s=20)
28
+ plotter.set_title('ax01', 'Right Subplot')
29
+ plotter.set_xlabel('ax01', 'X-axis')
30
+ plotter.set_ylabel('ax01', 'Y-axis')
31
+ plotter.set_legend('ax01')
32
+
33
+ # 3. Add figure-level text using fig_text
34
+ plotter.fig_add_text(0.5, 0.96, 'Overall Figure Title (using fig_add_text)', ha='center', va='top', fontsize=14, weight='bold')
35
+ plotter.fig_add_text(0.02, 0.5, 'Left Side Annotation', rotation=90, va='center', ha='left', fontsize=10, color='gray')
36
+ plotter.fig_add_text(0.98, 0.5, 'Right Side Annotation', rotation=-90, va='center', ha='right', fontsize=10, color='gray')
37
+ plotter.fig_add_text(0.5, 0.02, 'Figure Footer - Source: Example Data', ha='center', va='bottom', fontsize=8, style='italic')
38
+
39
+ # 4. Apply cleanup and save the figure
40
+ plotter.cleanup(auto_share=True) # Auto-share for demonstration
41
+ plotter.save("fig_text_example.png")
42
+
43
+ except pp.PaperPlotError as e:
44
+ print(f"\nA PaperPlot error occurred:\n{e}")
45
+ except Exception as e:
46
+ print(f"An unexpected error occurred: {e}")
47
+ finally:
48
+ plt.close('all')
49
+
50
+ print(f"--- Finished Example: {__file__} ---")
51
+ print("A new file 'fig_text_example.png' was generated.")
@@ -18,7 +18,7 @@ df3 = generate_heatmap_data(-5, 5)
18
18
  # --- 2. 演示共享颜色条功能 ---
19
19
  try:
20
20
  print("Creating 3 heatmaps with a shared colorbar...")
21
- plotter = pp.Plotter(n_rows=1, n_cols=3, figsize=(12, 4))
21
+ plotter = pp.Plotter(layout=(1, 3), figsize=(12, 4))
22
22
 
23
23
  # --- 3. 添加热图,并明确指定 cbar=False ---
24
24
  # 这是关键一步:我们告诉plotter不要为每个热图单独创建颜色条
@@ -52,7 +52,7 @@ finally:
52
52
  # --- 7. 作为对比,创建一个带独立颜色条的热图 ---
53
53
  try:
54
54
  print("\nCreating a single heatmap with its own colorbar (default behavior)...")
55
- plotter_single = pp.Plotter(n_rows=1, n_cols=1)
55
+ plotter_single = pp.Plotter(layout=(1, 1))
56
56
  # 默认调用,不加 cbar 参数,会自动创建颜色条
57
57
  plotter_single.add_heatmap(data=df1, tag='single')
58
58
  plotter_single.set_title('single', 'Default Behavior with cbar=True')
@@ -0,0 +1,62 @@
1
+ # examples/Features_Customization/highlighting_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
+ try:
11
+ # 1. Create a Plotter instance
12
+ plotter = pp.Plotter(layout=(1, 1), figsize=(8, 6), style='publication')
13
+
14
+ # 2. Add a plot with some interesting features
15
+ x = np.linspace(0, 2 * np.pi, 200)
16
+ y = np.sin(x) * np.exp(-x / 4)
17
+ df = pd.DataFrame({'x': x, 'y': y})
18
+
19
+ plotter.add_line(data=df, x='x', y='y', tag='main_plot', label='Damped Sine Wave')
20
+ plotter.set_title('main_plot', 'Highlighting Data Regions and Figure Boundary')
21
+ plotter.set_xlabel('main_plot', 'Time')
22
+ plotter.set_ylabel('main_plot', 'Amplitude')
23
+ plotter.set_legend('main_plot')
24
+
25
+ # 3. Use add_highlight_box to highlight a specific data region
26
+ # Highlight the first peak of the wave
27
+ plotter.add_highlight_box(
28
+ tag='main_plot',
29
+ x_range=(0.5, 2.5),
30
+ y_range=(0.4, 0.8),
31
+ facecolor='orange',
32
+ alpha=0.3,
33
+ label='First Peak Region' # Note: label won't show by default, but can be used with legends
34
+ )
35
+ plotter.add_text('main_plot', 1.5, 0.6, 'First Peak', ha='center', va='center', fontsize=10)
36
+
37
+ # Highlight the region where the wave decays
38
+ plotter.add_highlight_box(
39
+ tag='main_plot',
40
+ x_range=(4, 6),
41
+ y_range=(-0.2, 0.2),
42
+ facecolor='lightblue',
43
+ alpha=0.4
44
+ )
45
+ plotter.add_text('main_plot', 5, 0, 'Decay Region', ha='center', va='center', fontsize=10)
46
+
47
+ # 4. Use fig_add_boundary_box to draw a border around the axes area
48
+
49
+ # plotter.fig_add_text(0.5, 0.98, 'Figure with Smart Boundary Box', ha='center', va='top', fontsize=12)
50
+ plotter.fig_add_boundary_box(padding=0.08, edgecolor='darkgray', linewidth=2)
51
+ # 5. Save the figure
52
+ plotter.save("highlighting_example.png")
53
+
54
+ except pp.PaperPlotError as e:
55
+ print(f"\nA PaperPlot error occurred:\n{e}")
56
+ except Exception as e:
57
+ print(f"An unexpected error occurred: {e}")
58
+ finally:
59
+ plt.close('all')
60
+
61
+ print(f"--- Finished Example: {__file__} ---")
62
+ print("A new file 'highlighting_example.png' was generated.")
@@ -5,6 +5,8 @@ import pandas as pd
5
5
  import numpy as np
6
6
  import matplotlib.pyplot as plt
7
7
 
8
+ from paperplot import Plotter
9
+
8
10
  print(f"--- Running Example: {__file__} ---")
9
11
 
10
12
  # --- 1. 准备多样化的数据 ---
@@ -36,7 +38,7 @@ df_heatmap = pd.DataFrame(heatmap_data, columns=[f'col_{i}' for i in range(10)])
36
38
  try:
37
39
  print("Creating a 2x2 plot with shared axes...")
38
40
  # sharex=True, sharey=True 是关键
39
- plotter = pp.Plotter(n_rows=2, n_cols=2, figsize=(10, 8), sharex=False, sharey=False)
41
+ plotter = Plotter(layout=(2, 2), figsize=(10, 8), style='flat')
40
42
 
41
43
  # --- 3. 在网格中填充不同的图表 ---
42
44
  print("Populating the grid with different plot types...")
@@ -74,6 +76,8 @@ try:
74
76
  plotter.tick_params('heatmap', axis='x', rotation=90)
75
77
 
76
78
  # --- 5. 应用默认美化并保存 ---
79
+ # print("Applying cleanup for shared axes and saving...")
80
+ # plotter.cleanup(auto_share=True)
77
81
  plotter.save("multi_plot_grid_figure.png")
78
82
 
79
83
  except pp.PaperPlotError as e:
@@ -54,7 +54,7 @@ try:
54
54
  # --- 6. 演示 hide_axes() 功能 ---
55
55
  # 为了让布局更紧凑,我们隐藏所有X轴
56
56
  print("Hiding all X-axes using hide_axes(x=True)...")
57
- plotter.hide_axes(x=True)
57
+ plotter.hide_axes(x=True, y=True)
58
58
 
59
59
  # --- 7. 保存图像 ---
60
60
  plotter.save("advanced_layout_figure.png")
@@ -0,0 +1,91 @@
1
+ # examples/Layout/declarative_nested_layout_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
+ df_line = pd.DataFrame({
13
+ 'x': np.linspace(0, 2 * np.pi, 100),
14
+ 'y': np.sin(np.linspace(0, 2 * np.pi, 100))
15
+ })
16
+ # 子网格的热图数据
17
+ heatmap_data_1 = pd.DataFrame(np.random.rand(8, 50))
18
+ heatmap_data_2 = pd.DataFrame(np.random.rand(8, 50))
19
+ heatmap_data_3 = pd.DataFrame(np.random.rand(8, 50))
20
+ # Y轴标签
21
+ y_labels = ['~NH₂', 'v(C-N-C)', 'v(C-C)ring']
22
+ all_heatmap_data = [heatmap_data_1, heatmap_data_2, heatmap_data_3]
23
+
24
+ try:
25
+ # --- 2. 使用字典声明式地定义整个嵌套布局 ---
26
+ # 这是新API的核心:一个字典描述了所有层级和结构
27
+ nested_layout = {
28
+ # 'main' 定义了顶层 1x2 布局
29
+ 'main': [
30
+ ['main_plot', 'heatmap_group']
31
+ ],
32
+ # 'subgrids' 定义了 'heatmap_group' 区域如何被再次划分
33
+ 'subgrids': {
34
+ 'heatmap_group': {
35
+ # 'layout' 定义了 3x1 的内部网格,并为每个单元命名
36
+ 'layout': [
37
+ ['nh2_map'],
38
+ ['cnc_map'],
39
+ ['ring_map']
40
+ ],
41
+ # 'hspace' 控制这个子网格内部的垂直间距,使其紧凑
42
+ 'hspace': 0.05
43
+ }
44
+ }
45
+ }
46
+
47
+ # --- 3. 初始化 Plotter ---
48
+ # 直接将定义好的字典传给 layout 参数
49
+ # layout_engine=None 确保我们可以手动控制间距
50
+ plotter = pp.Plotter(layout=nested_layout, figsize=(12, 6), layout_engine=None)
51
+ plotter.set_suptitle("Declarative Nested Layout Example", fontsize=16, weight='bold')
52
+
53
+ # --- 4. 填充主图区域 ---
54
+ # 直接使用顶层布局中定义的名字 'main_plot' 作为 tag
55
+ plotter.add_line(data=df_line, x='x', y='y', tag='main_plot')
56
+ plotter.set_title('main_plot', 'Standard Plot')
57
+ plotter.set_xlabel('main_plot', 'X-axis')
58
+ plotter.set_ylabel('main_plot', 'Y-axis')
59
+
60
+ # --- 5. 填充子网格区域 ---
61
+ # 使用 '容器名.子图名' 的层级结构来直接引用嵌套的子图
62
+ subgrid_names = ['nh2_map', 'cnc_map', 'ring_map']
63
+ for i, sub_name in enumerate(subgrid_names):
64
+ # 构造层级 tag, e.g., 'heatmap_group.nh2_map'
65
+ hierarchical_tag = f"heatmap_group.{sub_name}"
66
+
67
+ plotter.add_heatmap(data=all_heatmap_data[i], tag=hierarchical_tag)
68
+ plotter.set_ylabel(hierarchical_tag, y_labels[i], fontsize=14, weight='bold')
69
+
70
+ # --- 6. 对子网格进行精细化设置 ---
71
+ # a. 只在最顶部的子图上添加标题
72
+ plotter.set_title('heatmap_group.nh2_map', 'Nested Heatmap Group', fontsize=14)
73
+
74
+ # b. 隐藏不需要的 X 轴刻度标签,实现共享X轴的效果
75
+ # (这里我们假设您已经实现了更精细的 hide_axes 或 tick_params)
76
+ plotter.tick_params('heatmap_group.nh2_map', axis='x', labelbottom=False)
77
+ plotter.tick_params('heatmap_group.cnc_map', axis='x', labelbottom=False)
78
+
79
+ # c. 只在最底部的子图上添加 X 轴标签
80
+ plotter.set_xlabel('heatmap_group.ring_map', 'Time (min)', fontsize=14, weight='bold')
81
+
82
+ # --- 7. 保存图像 ---
83
+ plotter.save("declarative_nested_layout.png")
84
+
85
+ except (pp.PaperPlotError, ValueError, KeyError) as e:
86
+ print(f"\nAn error occurred:\n{e}")
87
+ finally:
88
+ plt.close('all')
89
+
90
+ print(f"\n--- Finished Example: {__file__} ---")
91
+ print("A new file 'declarative_nested_layout.png' was generated.")