figrecipe 0.6.0__py3-none-any.whl → 0.9.0__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 (269) hide show
  1. figrecipe/__init__.py +161 -1030
  2. figrecipe/__main__.py +12 -0
  3. figrecipe/_api/__init__.py +48 -0
  4. figrecipe/_api/_extract.py +108 -0
  5. figrecipe/_api/_notebook.py +61 -0
  6. figrecipe/_api/_panel.py +113 -0
  7. figrecipe/_api/_save.py +287 -0
  8. figrecipe/_api/_seaborn_proxy.py +34 -0
  9. figrecipe/_api/_style_manager.py +153 -0
  10. figrecipe/_api/_subplots.py +333 -0
  11. figrecipe/_api/_validate.py +82 -0
  12. figrecipe/_cli/__init__.py +7 -0
  13. figrecipe/_cli/_compose.py +87 -0
  14. figrecipe/_cli/_convert.py +117 -0
  15. figrecipe/_cli/_crop.py +82 -0
  16. figrecipe/_cli/_edit.py +70 -0
  17. figrecipe/_cli/_extract.py +128 -0
  18. figrecipe/_cli/_fonts.py +47 -0
  19. figrecipe/_cli/_info.py +67 -0
  20. figrecipe/_cli/_main.py +58 -0
  21. figrecipe/_cli/_reproduce.py +79 -0
  22. figrecipe/_cli/_style.py +77 -0
  23. figrecipe/_cli/_validate.py +66 -0
  24. figrecipe/_cli/_version.py +50 -0
  25. figrecipe/_composition/__init__.py +32 -0
  26. figrecipe/_composition/_alignment.py +452 -0
  27. figrecipe/_composition/_compose.py +179 -0
  28. figrecipe/_composition/_import_axes.py +127 -0
  29. figrecipe/_composition/_visibility.py +125 -0
  30. figrecipe/_dev/__init__.py +4 -93
  31. figrecipe/_dev/_plotters.py +76 -0
  32. figrecipe/_dev/_run_demos.py +56 -0
  33. figrecipe/_dev/browser/__init__.py +69 -0
  34. figrecipe/_dev/browser/_audio.py +240 -0
  35. figrecipe/_dev/browser/_caption.py +356 -0
  36. figrecipe/_dev/browser/_click_effect.py +146 -0
  37. figrecipe/_dev/browser/_cursor.py +196 -0
  38. figrecipe/_dev/browser/_highlight.py +105 -0
  39. figrecipe/_dev/browser/_narration.py +237 -0
  40. figrecipe/_dev/browser/_recorder.py +446 -0
  41. figrecipe/_dev/browser/_utils.py +178 -0
  42. figrecipe/_dev/browser/_video_trim/__init__.py +152 -0
  43. figrecipe/_dev/browser/_video_trim/_detection.py +223 -0
  44. figrecipe/_dev/browser/_video_trim/_markers.py +140 -0
  45. figrecipe/_dev/demo_plotters/__init__.py +35 -166
  46. figrecipe/_dev/demo_plotters/_categories.py +81 -0
  47. figrecipe/_dev/demo_plotters/_figure_creators.py +119 -0
  48. figrecipe/_dev/demo_plotters/_helpers.py +31 -0
  49. figrecipe/_dev/demo_plotters/_registry.py +50 -0
  50. figrecipe/_dev/demo_plotters/bar_categorical/__init__.py +4 -0
  51. figrecipe/_dev/demo_plotters/contour_surface/__init__.py +4 -0
  52. figrecipe/_dev/demo_plotters/distribution/__init__.py +4 -0
  53. figrecipe/_dev/demo_plotters/image_matrix/__init__.py +4 -0
  54. figrecipe/_dev/demo_plotters/line_curve/__init__.py +4 -0
  55. figrecipe/_dev/demo_plotters/{plot_plot.py → line_curve/plot_plot.py} +3 -2
  56. figrecipe/_dev/demo_plotters/scatter_points/__init__.py +4 -0
  57. figrecipe/_dev/demo_plotters/special/__init__.py +4 -0
  58. figrecipe/_dev/demo_plotters/{plot_pie.py → special/plot_pie.py} +5 -1
  59. figrecipe/_dev/demo_plotters/spectral_signal/__init__.py +4 -0
  60. figrecipe/_dev/demo_plotters/vector_flow/__init__.py +4 -0
  61. figrecipe/_editor/__init__.py +61 -13
  62. figrecipe/_editor/_bbox/__init__.py +43 -0
  63. figrecipe/_editor/_bbox/_collections.py +177 -0
  64. figrecipe/_editor/_bbox/_elements.py +159 -0
  65. figrecipe/_editor/_bbox/_extract.py +402 -0
  66. figrecipe/_editor/_bbox/_extract_axes.py +370 -0
  67. figrecipe/_editor/_bbox/_extract_text.py +466 -0
  68. figrecipe/_editor/_bbox/_lines.py +173 -0
  69. figrecipe/_editor/_bbox/_transforms.py +146 -0
  70. figrecipe/_editor/_call_overrides.py +183 -0
  71. figrecipe/_editor/_datatable_plot_handlers.py +249 -0
  72. figrecipe/_editor/_figure_layout.py +211 -0
  73. figrecipe/_editor/_flask_app.py +200 -1030
  74. figrecipe/_editor/_helpers.py +251 -0
  75. figrecipe/_editor/_hitmap/__init__.py +76 -0
  76. figrecipe/_editor/_hitmap/_artists/__init__.py +21 -0
  77. figrecipe/_editor/_hitmap/_artists/_collections.py +345 -0
  78. figrecipe/_editor/_hitmap/_artists/_images.py +68 -0
  79. figrecipe/_editor/_hitmap/_artists/_lines.py +107 -0
  80. figrecipe/_editor/_hitmap/_artists/_patches.py +163 -0
  81. figrecipe/_editor/_hitmap/_artists/_text.py +190 -0
  82. figrecipe/_editor/_hitmap/_colors.py +181 -0
  83. figrecipe/_editor/_hitmap/_detect.py +194 -0
  84. figrecipe/_editor/_hitmap/_restore.py +154 -0
  85. figrecipe/_editor/_hitmap_main.py +182 -0
  86. figrecipe/_editor/_overrides.py +4 -1
  87. figrecipe/_editor/_plot_types_registry.py +190 -0
  88. figrecipe/_editor/_preferences.py +135 -0
  89. figrecipe/_editor/_render_overrides.py +507 -0
  90. figrecipe/_editor/_renderer.py +81 -186
  91. figrecipe/_editor/_routes_annotation.py +114 -0
  92. figrecipe/_editor/_routes_axis.py +482 -0
  93. figrecipe/_editor/_routes_captions.py +130 -0
  94. figrecipe/_editor/_routes_composition.py +270 -0
  95. figrecipe/_editor/_routes_core.py +126 -0
  96. figrecipe/_editor/_routes_datatable.py +364 -0
  97. figrecipe/_editor/_routes_element.py +335 -0
  98. figrecipe/_editor/_routes_files.py +443 -0
  99. figrecipe/_editor/_routes_image.py +200 -0
  100. figrecipe/_editor/_routes_snapshot.py +94 -0
  101. figrecipe/_editor/_routes_style.py +243 -0
  102. figrecipe/_editor/_templates/__init__.py +116 -1
  103. figrecipe/_editor/_templates/_html.py +154 -64
  104. figrecipe/_editor/_templates/_html_components/__init__.py +13 -0
  105. figrecipe/_editor/_templates/_html_components/_composition_toolbar.py +79 -0
  106. figrecipe/_editor/_templates/_html_components/_file_browser.py +41 -0
  107. figrecipe/_editor/_templates/_html_datatable.py +92 -0
  108. figrecipe/_editor/_templates/_scripts/__init__.py +178 -0
  109. figrecipe/_editor/_templates/_scripts/_accordion.py +328 -0
  110. figrecipe/_editor/_templates/_scripts/_annotation_drag.py +504 -0
  111. figrecipe/_editor/_templates/_scripts/_api.py +228 -0
  112. figrecipe/_editor/_templates/_scripts/_canvas_context_menu.py +182 -0
  113. figrecipe/_editor/_templates/_scripts/_captions.py +231 -0
  114. figrecipe/_editor/_templates/_scripts/_colors.py +485 -0
  115. figrecipe/_editor/_templates/_scripts/_composition.py +283 -0
  116. figrecipe/_editor/_templates/_scripts/_core.py +493 -0
  117. figrecipe/_editor/_templates/_scripts/_datatable/__init__.py +59 -0
  118. figrecipe/_editor/_templates/_scripts/_datatable/_cell_edit.py +97 -0
  119. figrecipe/_editor/_templates/_scripts/_datatable/_clipboard.py +164 -0
  120. figrecipe/_editor/_templates/_scripts/_datatable/_context_menu.py +221 -0
  121. figrecipe/_editor/_templates/_scripts/_datatable/_core.py +150 -0
  122. figrecipe/_editor/_templates/_scripts/_datatable/_editable.py +511 -0
  123. figrecipe/_editor/_templates/_scripts/_datatable/_import.py +161 -0
  124. figrecipe/_editor/_templates/_scripts/_datatable/_plot.py +261 -0
  125. figrecipe/_editor/_templates/_scripts/_datatable/_selection.py +438 -0
  126. figrecipe/_editor/_templates/_scripts/_datatable/_table.py +256 -0
  127. figrecipe/_editor/_templates/_scripts/_datatable/_tabs.py +354 -0
  128. figrecipe/_editor/_templates/_scripts/_debug_snapshot.py +186 -0
  129. figrecipe/_editor/_templates/_scripts/_element_editor.py +325 -0
  130. figrecipe/_editor/_templates/_scripts/_files.py +429 -0
  131. figrecipe/_editor/_templates/_scripts/_files_context_menu.py +240 -0
  132. figrecipe/_editor/_templates/_scripts/_hitmap.py +512 -0
  133. figrecipe/_editor/_templates/_scripts/_image_drop.py +428 -0
  134. figrecipe/_editor/_templates/_scripts/_inspector.py +315 -0
  135. figrecipe/_editor/_templates/_scripts/_labels.py +464 -0
  136. figrecipe/_editor/_templates/_scripts/_legend_drag.py +270 -0
  137. figrecipe/_editor/_templates/_scripts/_modals.py +226 -0
  138. figrecipe/_editor/_templates/_scripts/_multi_select.py +198 -0
  139. figrecipe/_editor/_templates/_scripts/_overlays.py +292 -0
  140. figrecipe/_editor/_templates/_scripts/_panel_drag.py +505 -0
  141. figrecipe/_editor/_templates/_scripts/_panel_drag_snapshot.py +33 -0
  142. figrecipe/_editor/_templates/_scripts/_panel_position.py +463 -0
  143. figrecipe/_editor/_templates/_scripts/_panel_resize.py +230 -0
  144. figrecipe/_editor/_templates/_scripts/_panel_snap.py +307 -0
  145. figrecipe/_editor/_templates/_scripts/_region_select.py +255 -0
  146. figrecipe/_editor/_templates/_scripts/_selection.py +244 -0
  147. figrecipe/_editor/_templates/_scripts/_sync.py +242 -0
  148. figrecipe/_editor/_templates/_scripts/_tabs.py +89 -0
  149. figrecipe/_editor/_templates/_scripts/_undo_redo.py +348 -0
  150. figrecipe/_editor/_templates/_scripts/_view_mode.py +107 -0
  151. figrecipe/_editor/_templates/_scripts/_zoom.py +212 -0
  152. figrecipe/_editor/_templates/_styles/__init__.py +78 -0
  153. figrecipe/_editor/_templates/_styles/_base.py +111 -0
  154. figrecipe/_editor/_templates/_styles/_buttons.py +327 -0
  155. figrecipe/_editor/_templates/_styles/_color_input.py +123 -0
  156. figrecipe/_editor/_templates/_styles/_composition.py +87 -0
  157. figrecipe/_editor/_templates/_styles/_controls.py +430 -0
  158. figrecipe/_editor/_templates/_styles/_datatable/__init__.py +40 -0
  159. figrecipe/_editor/_templates/_styles/_datatable/_editable.py +203 -0
  160. figrecipe/_editor/_templates/_styles/_datatable/_panel.py +268 -0
  161. figrecipe/_editor/_templates/_styles/_datatable/_table.py +479 -0
  162. figrecipe/_editor/_templates/_styles/_datatable/_toolbar.py +384 -0
  163. figrecipe/_editor/_templates/_styles/_datatable/_vars.py +123 -0
  164. figrecipe/_editor/_templates/_styles/_dynamic_props.py +144 -0
  165. figrecipe/_editor/_templates/_styles/_file_browser.py +466 -0
  166. figrecipe/_editor/_templates/_styles/_forms.py +224 -0
  167. figrecipe/_editor/_templates/_styles/_hitmap.py +191 -0
  168. figrecipe/_editor/_templates/_styles/_inspector.py +90 -0
  169. figrecipe/_editor/_templates/_styles/_labels.py +118 -0
  170. figrecipe/_editor/_templates/_styles/_modals.py +127 -0
  171. figrecipe/_editor/_templates/_styles/_overlays.py +130 -0
  172. figrecipe/_editor/_templates/_styles/_preview.py +430 -0
  173. figrecipe/_editor/_templates/_styles/_selection.py +73 -0
  174. figrecipe/_editor/_templates/_styles/_spinner.py +117 -0
  175. figrecipe/_editor/static/audio/click.mp3 +0 -0
  176. figrecipe/_editor/static/click.mp3 +0 -0
  177. figrecipe/_editor/static/icons/favicon.ico +0 -0
  178. figrecipe/_integrations/__init__.py +17 -0
  179. figrecipe/_integrations/_scitex_stats.py +298 -0
  180. figrecipe/_params/_DECORATION_METHODS.py +8 -0
  181. figrecipe/_recorder.py +63 -109
  182. figrecipe/_recorder_utils.py +124 -0
  183. figrecipe/_reproducer/__init__.py +18 -0
  184. figrecipe/_reproducer/_core.py +509 -0
  185. figrecipe/_reproducer/_custom_plots.py +279 -0
  186. figrecipe/_reproducer/_seaborn.py +100 -0
  187. figrecipe/_reproducer/_violin.py +186 -0
  188. figrecipe/_signatures/_kwargs.py +273 -0
  189. figrecipe/_signatures/_loader.py +21 -423
  190. figrecipe/_signatures/_parsing.py +147 -0
  191. figrecipe/_utils/__init__.py +3 -0
  192. figrecipe/_utils/_bundle.py +205 -0
  193. figrecipe/_wrappers/_axes.py +252 -895
  194. figrecipe/_wrappers/_axes_helpers.py +136 -0
  195. figrecipe/_wrappers/_axes_plots.py +418 -0
  196. figrecipe/_wrappers/_axes_seaborn.py +157 -0
  197. figrecipe/_wrappers/_caption_generator.py +218 -0
  198. figrecipe/_wrappers/_figure.py +188 -1
  199. figrecipe/_wrappers/_panel_labels.py +127 -0
  200. figrecipe/_wrappers/_plot_helpers.py +143 -0
  201. figrecipe/_wrappers/_stat_annotation.py +274 -0
  202. figrecipe/_wrappers/_violin_helpers.py +180 -0
  203. figrecipe/styles/__init__.py +8 -6
  204. figrecipe/styles/_dotdict.py +72 -0
  205. figrecipe/styles/_finalize.py +134 -0
  206. figrecipe/styles/_fonts.py +77 -0
  207. figrecipe/styles/_kwargs_converter.py +178 -0
  208. figrecipe/styles/_plot_styles.py +209 -0
  209. figrecipe/styles/_style_applier.py +42 -480
  210. figrecipe/styles/_style_loader.py +16 -192
  211. figrecipe/styles/_themes.py +151 -0
  212. figrecipe/styles/presets/MATPLOTLIB.yaml +2 -1
  213. figrecipe/styles/presets/SCITEX.yaml +40 -28
  214. figrecipe-0.9.0.dist-info/METADATA +427 -0
  215. figrecipe-0.9.0.dist-info/RECORD +277 -0
  216. figrecipe-0.9.0.dist-info/entry_points.txt +2 -0
  217. figrecipe/_editor/_bbox.py +0 -978
  218. figrecipe/_editor/_hitmap.py +0 -937
  219. figrecipe/_editor/_templates/_scripts.py +0 -2778
  220. figrecipe/_editor/_templates/_styles.py +0 -1326
  221. figrecipe/_reproducer.py +0 -975
  222. figrecipe-0.6.0.dist-info/METADATA +0 -394
  223. figrecipe-0.6.0.dist-info/RECORD +0 -90
  224. /figrecipe/_dev/demo_plotters/{plot_bar.py → bar_categorical/plot_bar.py} +0 -0
  225. /figrecipe/_dev/demo_plotters/{plot_barh.py → bar_categorical/plot_barh.py} +0 -0
  226. /figrecipe/_dev/demo_plotters/{plot_contour.py → contour_surface/plot_contour.py} +0 -0
  227. /figrecipe/_dev/demo_plotters/{plot_contourf.py → contour_surface/plot_contourf.py} +0 -0
  228. /figrecipe/_dev/demo_plotters/{plot_tricontour.py → contour_surface/plot_tricontour.py} +0 -0
  229. /figrecipe/_dev/demo_plotters/{plot_tricontourf.py → contour_surface/plot_tricontourf.py} +0 -0
  230. /figrecipe/_dev/demo_plotters/{plot_tripcolor.py → contour_surface/plot_tripcolor.py} +0 -0
  231. /figrecipe/_dev/demo_plotters/{plot_triplot.py → contour_surface/plot_triplot.py} +0 -0
  232. /figrecipe/_dev/demo_plotters/{plot_boxplot.py → distribution/plot_boxplot.py} +0 -0
  233. /figrecipe/_dev/demo_plotters/{plot_ecdf.py → distribution/plot_ecdf.py} +0 -0
  234. /figrecipe/_dev/demo_plotters/{plot_hist.py → distribution/plot_hist.py} +0 -0
  235. /figrecipe/_dev/demo_plotters/{plot_hist2d.py → distribution/plot_hist2d.py} +0 -0
  236. /figrecipe/_dev/demo_plotters/{plot_violinplot.py → distribution/plot_violinplot.py} +0 -0
  237. /figrecipe/_dev/demo_plotters/{plot_hexbin.py → image_matrix/plot_hexbin.py} +0 -0
  238. /figrecipe/_dev/demo_plotters/{plot_imshow.py → image_matrix/plot_imshow.py} +0 -0
  239. /figrecipe/_dev/demo_plotters/{plot_matshow.py → image_matrix/plot_matshow.py} +0 -0
  240. /figrecipe/_dev/demo_plotters/{plot_pcolor.py → image_matrix/plot_pcolor.py} +0 -0
  241. /figrecipe/_dev/demo_plotters/{plot_pcolormesh.py → image_matrix/plot_pcolormesh.py} +0 -0
  242. /figrecipe/_dev/demo_plotters/{plot_spy.py → image_matrix/plot_spy.py} +0 -0
  243. /figrecipe/_dev/demo_plotters/{plot_errorbar.py → line_curve/plot_errorbar.py} +0 -0
  244. /figrecipe/_dev/demo_plotters/{plot_fill.py → line_curve/plot_fill.py} +0 -0
  245. /figrecipe/_dev/demo_plotters/{plot_fill_between.py → line_curve/plot_fill_between.py} +0 -0
  246. /figrecipe/_dev/demo_plotters/{plot_fill_betweenx.py → line_curve/plot_fill_betweenx.py} +0 -0
  247. /figrecipe/_dev/demo_plotters/{plot_stackplot.py → line_curve/plot_stackplot.py} +0 -0
  248. /figrecipe/_dev/demo_plotters/{plot_stairs.py → line_curve/plot_stairs.py} +0 -0
  249. /figrecipe/_dev/demo_plotters/{plot_step.py → line_curve/plot_step.py} +0 -0
  250. /figrecipe/_dev/demo_plotters/{plot_scatter.py → scatter_points/plot_scatter.py} +0 -0
  251. /figrecipe/_dev/demo_plotters/{plot_eventplot.py → special/plot_eventplot.py} +0 -0
  252. /figrecipe/_dev/demo_plotters/{plot_loglog.py → special/plot_loglog.py} +0 -0
  253. /figrecipe/_dev/demo_plotters/{plot_semilogx.py → special/plot_semilogx.py} +0 -0
  254. /figrecipe/_dev/demo_plotters/{plot_semilogy.py → special/plot_semilogy.py} +0 -0
  255. /figrecipe/_dev/demo_plotters/{plot_stem.py → special/plot_stem.py} +0 -0
  256. /figrecipe/_dev/demo_plotters/{plot_acorr.py → spectral_signal/plot_acorr.py} +0 -0
  257. /figrecipe/_dev/demo_plotters/{plot_angle_spectrum.py → spectral_signal/plot_angle_spectrum.py} +0 -0
  258. /figrecipe/_dev/demo_plotters/{plot_cohere.py → spectral_signal/plot_cohere.py} +0 -0
  259. /figrecipe/_dev/demo_plotters/{plot_csd.py → spectral_signal/plot_csd.py} +0 -0
  260. /figrecipe/_dev/demo_plotters/{plot_magnitude_spectrum.py → spectral_signal/plot_magnitude_spectrum.py} +0 -0
  261. /figrecipe/_dev/demo_plotters/{plot_phase_spectrum.py → spectral_signal/plot_phase_spectrum.py} +0 -0
  262. /figrecipe/_dev/demo_plotters/{plot_psd.py → spectral_signal/plot_psd.py} +0 -0
  263. /figrecipe/_dev/demo_plotters/{plot_specgram.py → spectral_signal/plot_specgram.py} +0 -0
  264. /figrecipe/_dev/demo_plotters/{plot_xcorr.py → spectral_signal/plot_xcorr.py} +0 -0
  265. /figrecipe/_dev/demo_plotters/{plot_barbs.py → vector_flow/plot_barbs.py} +0 -0
  266. /figrecipe/_dev/demo_plotters/{plot_quiver.py → vector_flow/plot_quiver.py} +0 -0
  267. /figrecipe/_dev/demo_plotters/{plot_streamplot.py → vector_flow/plot_streamplot.py} +0 -0
  268. {figrecipe-0.6.0.dist-info → figrecipe-0.9.0.dist-info}/WHEEL +0 -0
  269. {figrecipe-0.6.0.dist-info → figrecipe-0.9.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,427 @@
1
+ Metadata-Version: 2.4
2
+ Name: figrecipe
3
+ Version: 0.9.0
4
+ Summary: Reproducible matplotlib wrapper with mm-precision layouts
5
+ Project-URL: Homepage, https://github.com/ywatanabe1989/figrecipe
6
+ Project-URL: Documentation, https://github.com/ywatanabe1989/figrecipe#readme
7
+ Project-URL: Repository, https://github.com/ywatanabe1989/figrecipe.git
8
+ Project-URL: Issues, https://github.com/ywatanabe1989/figrecipe/issues
9
+ Author-email: Yusuke Watanabe <ywatanabe@scitex.ai>
10
+ License-Expression: AGPL-3.0
11
+ License-File: LICENSE
12
+ Keywords: matplotlib,millimeter,plotting,publication,recipe,reproducibility,scientific,visualization,yaml
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: GNU Affero General Public License v3
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Scientific/Engineering :: Visualization
23
+ Requires-Python: >=3.9
24
+ Requires-Dist: click>=8.0.0
25
+ Requires-Dist: matplotlib>=3.5.0
26
+ Requires-Dist: numpy>=1.20.0
27
+ Requires-Dist: ruamel-yaml>=0.17.0
28
+ Requires-Dist: scipy>=1.7.0
29
+ Provides-Extra: all
30
+ Requires-Dist: flask>=2.0.0; extra == 'all'
31
+ Requires-Dist: pandas>=1.3.0; extra == 'all'
32
+ Requires-Dist: pillow>=9.0.0; extra == 'all'
33
+ Requires-Dist: playwright>=1.40.0; extra == 'all'
34
+ Requires-Dist: pytesseract>=0.3.0; extra == 'all'
35
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'all'
36
+ Requires-Dist: pytest>=7.0.0; extra == 'all'
37
+ Requires-Dist: pywebview>=4.0.0; extra == 'all'
38
+ Requires-Dist: seaborn>=0.12.0; extra == 'all'
39
+ Provides-Extra: demo
40
+ Requires-Dist: playwright>=1.40.0; extra == 'demo'
41
+ Requires-Dist: pytesseract>=0.3.0; extra == 'demo'
42
+ Provides-Extra: desktop
43
+ Requires-Dist: flask>=2.0.0; extra == 'desktop'
44
+ Requires-Dist: pillow>=9.0.0; extra == 'desktop'
45
+ Requires-Dist: pyqt6-webengine>=6.0.0; extra == 'desktop'
46
+ Requires-Dist: pyqt6>=6.0.0; extra == 'desktop'
47
+ Requires-Dist: pywebview>=4.0.0; extra == 'desktop'
48
+ Requires-Dist: qtpy>=2.0.0; extra == 'desktop'
49
+ Provides-Extra: dev
50
+ Requires-Dist: pre-commit>=3.5.0; extra == 'dev'
51
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
52
+ Requires-Dist: pytest-xdist>=3.0.0; extra == 'dev'
53
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
54
+ Provides-Extra: editor
55
+ Requires-Dist: flask>=2.0.0; extra == 'editor'
56
+ Requires-Dist: pillow>=9.0.0; extra == 'editor'
57
+ Provides-Extra: imaging
58
+ Requires-Dist: pillow>=9.0.0; extra == 'imaging'
59
+ Provides-Extra: seaborn
60
+ Requires-Dist: pandas>=1.3.0; extra == 'seaborn'
61
+ Requires-Dist: seaborn>=0.12.0; extra == 'seaborn'
62
+ Description-Content-Type: text/markdown
63
+
64
+ <!-- ---
65
+ !-- Timestamp: 2025-12-27 02:15:07
66
+ !-- Author: ywatanabe
67
+ !-- File: /home/ywatanabe/proj/figrecipe/README.md
68
+ !-- --- -->
69
+
70
+ <p align="center">
71
+ <a href="https://scitex.ai" target="_blank">
72
+ <img src="docs/figrecipe_logo.png" alt="figrecipe logo" width="200"/>
73
+ </a>
74
+ </p>
75
+
76
+ # FigRecipe — **Reproducible matplotlib figures with mm-precision layouts.**
77
+
78
+ FigRecipe separates **what** is plotted (data) from **how** it is styled, storing both in a structured format. This enables reproducible figures with GUI editing while preserving scientific integrity, and allows AI integration in a scientifically rigorous manner. Ultimately, FigRecipe will bundle: (1) reproducible, style-editable figures, and (2) metadata such as statistical values—creating atomic, portable, and traceable scientific figure objects essential for automated research in the AI era.
79
+
80
+ FigRecipe is part of [**SciTeX™ (pending) – Research OS for reproducible science**](https://scitex.ai)
81
+
82
+ [![PyPI version](https://badge.fury.io/py/figrecipe.svg)](https://badge.fury.io/py/figrecipe)
83
+ [![Tests](https://github.com/ywatanabe1989/figrecipe/actions/workflows/test.yml/badge.svg)](https://github.com/ywatanabe1989/figrecipe/actions/workflows/test.yml)
84
+ [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-blue.svg)](https://www.gnu.org/licenses/agpl-3.0)
85
+
86
+
87
+ ---
88
+
89
+ ## Key Features
90
+
91
+ - ✅ Drop-in replacement for `matplotlib.pyplot`—minimal migration and learning cost
92
+ - ✅ All intermediate files use familiar formats (PNG/SVG/PDF/YAML/JSON)
93
+ - ✅ Import/Export to integrate with your existing workflow
94
+ - ✅ Millimeter-based layout (journal-ready)—difficult to achieve manually with matplotlib
95
+ - ✅ Publication-quality style presets
96
+ - ✅ Dark theme support (data colors preserved), with light theme export for journal compliance
97
+ - ✅ Research-focused features: automatic cropping, axis alignment, panel labels, and caption embedding
98
+ - ✅ Interactive GUI editor for manual adjustments
99
+
100
+ ---
101
+
102
+ ## Examples
103
+
104
+ 📓 **[View Demo Notebook on nbviewer](https://nbviewer.org/github/ywatanabe1989/figrecipe/blob/main/examples/figrecipe_demo.ipynb)** (recommended)
105
+
106
+ <details>
107
+ <summary><b>Demo Videos</b> — GUI Editor in action</summary>
108
+
109
+ | Dark Mode | Change Color | Drag Panel |
110
+ |:---:|:---:|:---:|
111
+ | ![Dark Mode](examples/demo_movie/outputs/01_enable_dark_mode.gif) | ![Change Color](examples/demo_movie/outputs/02_change_element_color.gif) | ![Drag Panel](examples/demo_movie/outputs/03_drag_panel_position.gif) |
112
+
113
+ | Move Legend | Undo/Redo | Toggle Theme |
114
+ |:---:|:---:|:---:|
115
+ | ![Move Legend](examples/demo_movie/outputs/04_move_legend.gif) | ![Undo Redo](examples/demo_movie/outputs/05_undo_and_redo.gif) | ![Toggle Theme](examples/demo_movie/outputs/06_toggle_theme.gif) |
116
+
117
+ | Hover Feedback | Edit Labels | Zoom Controls |
118
+ |:---:|:---:|:---:|
119
+ | ![Hover](examples/demo_movie/outputs/07_hover_feedback.gif) | ![Edit Labels](examples/demo_movie/outputs/08_edit_labels.gif) | ![Zoom](examples/demo_movie/outputs/09_zoom_controls.gif) |
120
+
121
+ </details>
122
+
123
+ <details>
124
+ <summary><b>Supported Plot Types</b> — 46 matplotlib plot types in 9 categories</summary>
125
+
126
+ <p align="center">
127
+ <img src="docs/images/plot_types/all_plot_types.png" alt="All Plot Types" width="100%"/>
128
+ </p>
129
+
130
+ | Line & Curve | Scatter | Distribution |
131
+ |:---:|:---:|:---:|
132
+ | ![Line](docs/images/plot_types/category_line_curve.png) | ![Scatter](docs/images/plot_types/category_scatter_points.png) | ![Distribution](docs/images/plot_types/category_distribution.png) |
133
+
134
+ | Bar & Categorical | Contour & Surface | 2D/Image/Matrix |
135
+ |:---:|:---:|:---:|
136
+ | ![Bar](docs/images/plot_types/category_bar_categorical.png) | ![Contour](docs/images/plot_types/category_contour_surface.png) | ![Image](docs/images/plot_types/category_2d_image_matrix.png) |
137
+
138
+ | Vector & Flow | Spectral & Signal | Special |
139
+ |:---:|:---:|:---:|
140
+ | ![Vector](docs/images/plot_types/category_vector_flow.png) | ![Spectral](docs/images/plot_types/category_spectral_signal.png) | ![Special](docs/images/plot_types/category_special.png) |
141
+
142
+ Generate all plots: `python examples/demo_plot_all.py`
143
+ </details>
144
+
145
+ ## Installation
146
+
147
+ ```bash
148
+ pip install figrecipe
149
+
150
+ # Optional extras
151
+ pip install figrecipe[seaborn] # seaborn + pandas support
152
+ pip install figrecipe[imaging] # image cropping (Pillow)
153
+ pip install figrecipe[all] # all extras
154
+
155
+ # Optional: for PDF export from notebooks (SVG → PDF)
156
+ sudo apt install inkscape # Linux
157
+ brew install inkscape # macOS
158
+ ```
159
+
160
+ **Requirements:** Python >= 3.9
161
+
162
+ ## Basic Usage
163
+
164
+ ### Recording & Saving
165
+
166
+ ``` python
167
+ import figrecipe as fr
168
+ # import figrecipe.pyplot as plt
169
+ import numpy as np
170
+
171
+ x = np.linspace(0, 10, 100)
172
+ y = np.sin(x)
173
+
174
+ fig, ax = fr.subplots() # or plt.subplots()
175
+ ax.plot(x, y, color='red', linewidth=2, id='sine_wave')
176
+ ax.set_xlabel('Time (s)')
177
+ ax.set_ylabel('Amplitude')
178
+
179
+ # Save image + recipe
180
+ img_path, yaml_path, result = fr.save(fig, 'figure.png')
181
+ # → creates: figure.png + figure.yaml
182
+ ```
183
+
184
+ <details>
185
+ <summary><b>Supported I/O Formats</b> — Save and load are fully symmetric</summary>
186
+
187
+ **Save** creates both image and recipe. **Load** finds recipe from any format:
188
+
189
+ ```python
190
+ # Save examples
191
+ fr.save(fig, 'figure.png') # → figure.png + figure.yaml
192
+ fr.save(fig, 'figure.yaml') # → figure.yaml + figure.png
193
+ fr.save(fig, 'figure_bundle/') # → directory with recipe.yaml + figure.png
194
+ fr.save(fig, 'figure.zip') # → ZIP containing recipe.yaml + figure.png
195
+
196
+ # Load examples (symmetric with save)
197
+ fig, ax = fr.load('figure.png') # ← finds figure.yaml
198
+ fig, ax = fr.load('figure.yaml') # ← direct
199
+ fig, ax = fr.load('figure_bundle/') # ← finds recipe.yaml inside
200
+ fig, ax = fr.load('figure.zip') # ← extracts recipe.yaml
201
+
202
+ # Edit also supports all formats
203
+ fr.edit('figure.png') # Opens editor, finds figure.yaml
204
+
205
+ # Note: fr.reproduce() is an alias for fr.load()
206
+ ```
207
+
208
+ | Format | Save | Load | Notes |
209
+ |--------|:----:|:----:|-------|
210
+ | `.png` / `.jpg` / `.jpeg` | ✓ | ✓ | Creates/finds `.yaml` alongside |
211
+ | `.pdf` / `.svg` | ✓ | ✓ | Creates/finds `.yaml` alongside |
212
+ | `.tif` / `.tiff` | ✓ | ✓ | Creates/finds `.yaml` alongside |
213
+ | `.yaml` / `.yml` | ✓ | ✓ | Creates/finds image alongside |
214
+ | Directory (`path/`) | ✓ | ✓ | Bundle with `recipe.yaml` + image |
215
+ | `.zip` | ✓ | ✓ | ZIP bundle with `recipe.yaml` + image |
216
+
217
+ **Alternative save method:**
218
+ ```python
219
+ fig.savefig('figure.png') # Same as fr.save()
220
+ fig.savefig('figure.png', save_recipe=False) # Image only, no recipe
221
+ ```
222
+
223
+ </details>
224
+
225
+ ### Reproducing a Figure
226
+
227
+ ``` python
228
+ import figrecipe as fr
229
+
230
+ fig, ax = fr.reproduce('figure.yaml') # Or .png, .pdf, directory/, .zip
231
+ ```
232
+
233
+ ### Extracting Plotted Data
234
+
235
+ ``` python
236
+ import figrecipe as fr
237
+
238
+ data = fr.extract_data('figure.yaml')
239
+ # {'sine_wave': {'x': array([...]), 'y': array([...])}}
240
+ ```
241
+
242
+ ### Style Presets
243
+
244
+ ``` python
245
+ fr.list_presets()
246
+ # ['MATPLOTLIB', 'SCITEX']
247
+
248
+ # Publication-quality preset (applied globally)
249
+ fr.load_style('SCITEX')
250
+ fig, ax = fr.subplots()
251
+
252
+ # Dark theme (UI-only, data colors preserved)
253
+ fr.load_style('SCITEX_DARK')
254
+ # or: fr.load_style('SCITEX', dark=True)
255
+
256
+ # Custom style
257
+ fr.load_style('/path/to/my_style.yaml')
258
+ ```
259
+
260
+ See [src/figrecipe/styles/presets/](src/figrecipe/styles/presets/) for full examples.
261
+
262
+ ### Millimeter-Based Layout (Publication-Ready)
263
+
264
+ ``` python
265
+ fig, ax = fr.subplots(
266
+ axes_width_mm=60,
267
+ axes_height_mm=40,
268
+ margin_left_mm=15,
269
+ margin_bottom_mm=12,
270
+ )
271
+ ```
272
+ This guarantees consistent sizing across editors, exports, and journals.
273
+
274
+ ### Figure Legends (Scientific Captions)
275
+
276
+ Store publication-ready figure legends as metadata (not rendered on the figure):
277
+
278
+ ``` python
279
+ fig, axes = fr.subplots(1, 2)
280
+
281
+ # Figure legend (main description)
282
+ fig.set_caption(
283
+ "Comparison of treatment effects on neural activity. "
284
+ "Data represent mean ± SEM."
285
+ )
286
+
287
+ # Panel legends (A, B, C, ...)
288
+ axes[0].set_caption("Representative traces from control condition")
289
+ axes[1].set_caption("Quantification across subjects (n=12)")
290
+
291
+ # Access captions
292
+ print(fig.caption) # Figure legend
293
+ print(axes[0].caption) # Panel A legend
294
+
295
+ # Auto-generate with statistics
296
+ fig.set_stats({"comparisons": [{"name": "A vs B", "p_value": 0.003}]})
297
+ full_legend = fig.generate_caption(style="publication")
298
+ # → "Comparison of... (A) Representative traces... (B) Quantification... A vs B (p=0.003)."
299
+ ```
300
+
301
+ Captions are saved in the recipe YAML and displayed in the GUI editor's caption pane below the canvas—ready for copy-paste into manuscripts.
302
+
303
+ ### Interactive GUI Editor
304
+
305
+ ``` python
306
+ import figrecipe as fr
307
+ import numpy as np
308
+
309
+ fig, ax = fr.subplots()
310
+ ax.plot(np.sin(np.linspace(0, 10, 100)))
311
+
312
+ # Launch browser-based editor
313
+ overrides = fr.edit(fig, port=5050)
314
+
315
+ # Returns style overrides when editor is closed (Ctrl+C)
316
+ # Apply overrides to future figures or save to custom YAML
317
+ ```
318
+
319
+ <p align="center">
320
+ <img src="docs/images/gui_editor_demo.png" alt="FigRecipe GUI Editor" width="100%"/>
321
+ </p>
322
+
323
+ The editor provides:
324
+ - **Live preview** with real-time style updates
325
+ - **Theme switching** between SCITEX/MATPLOTLIB presets
326
+ - **Element selection** with hover highlighting
327
+ - **Property panels** for Figure, Axis, Legend, and Labels
328
+ - **Download** in PNG, SVG, PDF formats
329
+ - **Export** updated recipe YAML
330
+
331
+ | Axis Properties | Download Options | Dark Mode |
332
+ |:---:|:---:|:---:|
333
+ | ![Axis Panel](docs/images/editor_axis_panel.png) | ![Download](docs/images/editor_download_options.png) | ![Dark Mode](docs/images/editor_dark_mode.png) |
334
+
335
+ <details>
336
+ <summary><b>Style Format (YAML)</b> — Full preset example</summary>
337
+
338
+ ``` yaml
339
+ # FIGRECIPE Style Preset (SCITEX)
340
+ axes:
341
+ width_mm: 40
342
+ height_mm: 28
343
+ thickness_mm: 0.2
344
+
345
+ margins:
346
+ left_mm: 1
347
+ right_mm: 1
348
+ bottom_mm: 1
349
+ top_mm: 1
350
+
351
+ fonts:
352
+ family: "Arial"
353
+ axis_label_pt: 7
354
+ tick_label_pt: 7
355
+ title_pt: 8
356
+
357
+ lines:
358
+ trace_mm: 0.2
359
+ errorbar_mm: 0.2
360
+
361
+ ticks:
362
+ length_mm: 0.8
363
+ thickness_mm: 0.2
364
+ direction: "out"
365
+
366
+ output:
367
+ dpi: 300
368
+ transparent: true
369
+ format: "pdf"
370
+
371
+ theme:
372
+ mode: "light"
373
+ dark:
374
+ text: "#d4d4d4"
375
+ spine: "#d4d4d4"
376
+ light:
377
+ text: "black"
378
+ spine: "black"
379
+
380
+ colors:
381
+ palette:
382
+ - [0, 128, 192] # blue
383
+ - [255, 70, 50] # red
384
+ - [20, 180, 20] # green
385
+ # EOF
386
+ ```
387
+
388
+ See [src/figrecipe/styles/presets/](src/figrecipe/styles/presets/) for complete examples.
389
+ </details>
390
+
391
+
392
+ ### API Overview
393
+
394
+ | Import | Description |
395
+ |----------------------------------|---------------------------------------------------|
396
+ | `import figrecipe.pyplot as plt` | Drop-in replacement of `matplotlib.pyplot as plt` |
397
+ | `import figrecipe as fr` | Import figrecipe package |
398
+
399
+ | Function | |
400
+ |----------------------------------|---------------------------------------------------|
401
+ | `fr.subplots()` | Create a recording-enabled figure |
402
+ | `fr.save(fig, 'fig.png')` | Save image + recipe |
403
+ | `fr.reproduce('fig.yaml')` | Reproduce figure from recipe |
404
+ | `fr.extract_data('fig.yaml')` | Extract plotted data |
405
+ | `fr.info('fig.yaml')` | Inspect recipe metadata |
406
+ | `fr.edit(fig)` | Launch interactive GUI editor |
407
+ | `fr.load_style()` | Load style preset (global) |
408
+ | `fr.list_presets()` | List available presets |
409
+ | `fr.crop('fig.png')` | Crop to content with mm margin |
410
+ | `fig.set_caption(text)` | Set figure legend (metadata) |
411
+ | `ax.set_caption(text)` | Set panel legend (metadata) |
412
+
413
+
414
+ ## License
415
+
416
+ AGPL-3.0 See [LICENSE](LICENSE)
417
+
418
+ ## Contact
419
+ Yusuke Watanabe (ywatanabe@scitex.ai)
420
+
421
+ <p align="center">
422
+ <a href="https://scitex.ai" target="_blank">
423
+ <img src="docs/scitex-icon-navy-inverted.png" alt="SciTeX" width="80"/>
424
+ </a>
425
+ </p>
426
+
427
+ <!-- EOF -->